comparison mupdf-source/thirdparty/tesseract/src/lstm/stridemap.cpp @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 ///////////////////////////////////////////////////////////////////////
2 // File: stridemap.cpp
3 // Description: Indexing into a 4-d tensor held in a 2-d Array.
4 // Author: Ray Smith
5 //
6 // (C) Copyright 2016, Google Inc.
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 ///////////////////////////////////////////////////////////////////////
17
18 #include "stridemap.h"
19 #include <cassert> // for assert
20
21 namespace tesseract {
22
23 // Returns true if *this is a valid index.
24 bool StrideMap::Index::IsValid() const {
25 // Cheap check first.
26 for (int index : indices_) {
27 if (index < 0) {
28 return false;
29 }
30 }
31 for (int d = 0; d < FD_DIMSIZE; ++d) {
32 if (indices_[d] > MaxIndexOfDim(static_cast<FlexDimensions>(d))) {
33 return false;
34 }
35 }
36 return true;
37 }
38
39 // Returns true if the index of the given dimension is the last.
40 bool StrideMap::Index::IsLast(FlexDimensions dimension) const {
41 return MaxIndexOfDim(dimension) == indices_[dimension];
42 }
43
44 // Given that the dimensions up to and including dim-1 are valid, returns the
45 // maximum index for dimension dim.
46 int StrideMap::Index::MaxIndexOfDim(FlexDimensions dim) const {
47 int max_index = stride_map_->shape_[dim] - 1;
48 if (dim == FD_BATCH) {
49 return max_index;
50 }
51 assert(0 <= indices_[FD_BATCH]);
52 const size_t batch = indices_[FD_BATCH];
53 if (dim == FD_HEIGHT) {
54 if (batch >= stride_map_->heights_.size() || stride_map_->heights_[batch] > max_index) {
55 return max_index;
56 }
57 return stride_map_->heights_[batch] - 1;
58 }
59 if (batch >= stride_map_->widths_.size() || stride_map_->widths_[batch] > max_index) {
60 return max_index;
61 }
62 return stride_map_->widths_[batch] - 1;
63 }
64
65 // Adds the given offset to the given dimension. Returns true if the result
66 // makes a valid index.
67 bool StrideMap::Index::AddOffset(int offset, FlexDimensions dimension) {
68 indices_[dimension] += offset;
69 SetTFromIndices();
70 return IsValid();
71 }
72
73 // Increments the index in some encapsulated way that guarantees to remain
74 // valid until it returns false, meaning that the iteration is complete.
75 bool StrideMap::Index::Increment() {
76 for (int d = FD_DIMSIZE - 1; d >= 0; --d) {
77 if (!IsLast(static_cast<FlexDimensions>(d))) {
78 t_ += stride_map_->t_increments_[d];
79 ++indices_[d];
80 return true;
81 }
82 t_ -= stride_map_->t_increments_[d] * indices_[d];
83 indices_[d] = 0;
84 // Now carry to the next dimension.
85 }
86 return false;
87 }
88
89 // Decrements the index in some encapsulated way that guarantees to remain
90 // valid until it returns false, meaning that the iteration (that started
91 // with InitToLast()) is complete.
92 bool StrideMap::Index::Decrement() {
93 for (int d = FD_DIMSIZE - 1; d >= 0; --d) {
94 if (indices_[d] > 0) {
95 --indices_[d];
96 if (d == FD_BATCH) {
97 // The upper limits of the other dimensions may have changed as a result
98 // of a different batch index, so they have to be reset.
99 InitToLastOfBatch(indices_[FD_BATCH]);
100 } else {
101 t_ -= stride_map_->t_increments_[d];
102 }
103 return true;
104 }
105 indices_[d] = MaxIndexOfDim(static_cast<FlexDimensions>(d));
106 t_ += stride_map_->t_increments_[d] * indices_[d];
107 // Now borrow from the next dimension.
108 }
109 return false;
110 }
111
112 // Initializes the indices to the last valid location in the given batch
113 // index.
114 void StrideMap::Index::InitToLastOfBatch(int batch) {
115 indices_[FD_BATCH] = batch;
116 for (int d = FD_BATCH + 1; d < FD_DIMSIZE; ++d) {
117 indices_[d] = MaxIndexOfDim(static_cast<FlexDimensions>(d));
118 }
119 SetTFromIndices();
120 }
121
122 // Computes and sets t_ from the current indices_.
123 void StrideMap::Index::SetTFromIndices() {
124 t_ = 0;
125 for (int d = 0; d < FD_DIMSIZE; ++d) {
126 t_ += stride_map_->t_increments_[d] * indices_[d];
127 }
128 }
129
130 // Sets up the stride for the given array of height, width pairs.
131 void StrideMap::SetStride(const std::vector<std::pair<int, int>> &h_w_pairs) {
132 int max_height = 0;
133 int max_width = 0;
134 for (const std::pair<int, int> &hw : h_w_pairs) {
135 int height = hw.first;
136 int width = hw.second;
137 heights_.push_back(height);
138 widths_.push_back(width);
139 if (height > max_height) {
140 max_height = height;
141 }
142 if (width > max_width) {
143 max_width = width;
144 }
145 }
146 shape_[FD_BATCH] = heights_.size();
147 shape_[FD_HEIGHT] = max_height;
148 shape_[FD_WIDTH] = max_width;
149 ComputeTIncrements();
150 }
151
152 // Scales width and height dimensions by the given factors.
153 void StrideMap::ScaleXY(int x_factor, int y_factor) {
154 for (int &height : heights_) {
155 height /= y_factor;
156 }
157 for (int &width : widths_) {
158 width /= x_factor;
159 }
160 shape_[FD_HEIGHT] /= y_factor;
161 shape_[FD_WIDTH] /= x_factor;
162 ComputeTIncrements();
163 }
164
165 // Reduces width to 1, across the batch, whatever the input size.
166 void StrideMap::ReduceWidthTo1() {
167 widths_.assign(widths_.size(), 1);
168 shape_[FD_WIDTH] = 1;
169 ComputeTIncrements();
170 }
171
172 // Transposes the width and height dimensions.
173 void StrideMap::TransposeXY() {
174 std::swap(shape_[FD_HEIGHT], shape_[FD_WIDTH]);
175 std::swap(heights_, widths_);
176 ComputeTIncrements();
177 }
178
179 // Computes t_increments_ from shape_.
180 void StrideMap::ComputeTIncrements() {
181 t_increments_[FD_DIMSIZE - 1] = 1;
182 for (int d = FD_DIMSIZE - 2; d >= 0; --d) {
183 t_increments_[d] = t_increments_[d + 1] * shape_[d + 1];
184 }
185 }
186
187 } // namespace tesseract