/src/tesseract/src/lstm/stridemap.cpp
Line | Count | Source (jump to first uncovered line) |
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 | 5.20G | bool StrideMap::Index::IsValid() const { |
25 | | // Cheap check first. |
26 | 15.5G | for (int index : indices_) { |
27 | 15.5G | if (index < 0) { |
28 | 40.0M | return false; |
29 | 40.0M | } |
30 | 15.5G | } |
31 | 20.5G | for (int d = 0; d < FD_DIMSIZE; ++d) { |
32 | 15.4G | if (indices_[d] > MaxIndexOfDim(static_cast<FlexDimensions>(d))) { |
33 | 54.6M | return false; |
34 | 54.6M | } |
35 | 15.4G | } |
36 | 5.10G | return true; |
37 | 5.16G | } |
38 | | |
39 | | // Returns true if the index of the given dimension is the last. |
40 | 575M | bool StrideMap::Index::IsLast(FlexDimensions dimension) const { |
41 | 575M | return MaxIndexOfDim(dimension) == indices_[dimension]; |
42 | 575M | } |
43 | | |
44 | | // Given that the dimensions up to and including dim-1 are valid, returns the |
45 | | // maximum index for dimension dim. |
46 | 16.0G | int StrideMap::Index::MaxIndexOfDim(FlexDimensions dim) const { |
47 | 16.0G | int max_index = stride_map_->shape_[dim] - 1; |
48 | 16.0G | if (dim == FD_BATCH) { |
49 | 5.16G | return max_index; |
50 | 5.16G | } |
51 | 10.8G | assert(0 <= indices_[FD_BATCH]); |
52 | 10.8G | const size_t batch = indices_[FD_BATCH]; |
53 | 10.8G | if (dim == FD_HEIGHT) { |
54 | 5.18G | if (batch >= stride_map_->heights_.size() || stride_map_->heights_[batch] > max_index) { |
55 | 5.18G | return max_index; |
56 | 5.18G | } |
57 | 0 | return stride_map_->heights_[batch] - 1; |
58 | 5.18G | } |
59 | 5.68G | if (batch >= stride_map_->widths_.size() || stride_map_->widths_[batch] > max_index) { |
60 | 5.68G | return max_index; |
61 | 5.68G | } |
62 | 0 | return stride_map_->widths_[batch] - 1; |
63 | 5.68G | } |
64 | | |
65 | | // Adds the given offset to the given dimension. Returns true if the result |
66 | | // makes a valid index. |
67 | 5.20G | bool StrideMap::Index::AddOffset(int offset, FlexDimensions dimension) { |
68 | 5.20G | indices_[dimension] += offset; |
69 | 5.20G | SetTFromIndices(); |
70 | 5.20G | return IsValid(); |
71 | 5.20G | } |
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 | 462M | bool StrideMap::Index::Increment() { |
76 | 486M | for (int d = FD_DIMSIZE - 1; d >= 0; --d) { |
77 | 485M | if (!IsLast(static_cast<FlexDimensions>(d))) { |
78 | 460M | t_ += stride_map_->t_increments_[d]; |
79 | 460M | ++indices_[d]; |
80 | 460M | return true; |
81 | 460M | } |
82 | 24.4M | t_ -= stride_map_->t_increments_[d] * indices_[d]; |
83 | 24.4M | indices_[d] = 0; |
84 | | // Now carry to the next dimension. |
85 | 24.4M | } |
86 | 1.91M | return false; |
87 | 462M | } |
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 | 0 | bool StrideMap::Index::Decrement() { |
93 | 0 | for (int d = FD_DIMSIZE - 1; d >= 0; --d) { |
94 | 0 | if (indices_[d] > 0) { |
95 | 0 | --indices_[d]; |
96 | 0 | 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 | 0 | InitToLastOfBatch(indices_[FD_BATCH]); |
100 | 0 | } else { |
101 | 0 | t_ -= stride_map_->t_increments_[d]; |
102 | 0 | } |
103 | 0 | return true; |
104 | 0 | } |
105 | 0 | indices_[d] = MaxIndexOfDim(static_cast<FlexDimensions>(d)); |
106 | 0 | t_ += stride_map_->t_increments_[d] * indices_[d]; |
107 | | // Now borrow from the next dimension. |
108 | 0 | } |
109 | 0 | return false; |
110 | 0 | } |
111 | | |
112 | | // Initializes the indices to the last valid location in the given batch |
113 | | // index. |
114 | 0 | void StrideMap::Index::InitToLastOfBatch(int batch) { |
115 | 0 | indices_[FD_BATCH] = batch; |
116 | 0 | for (int d = FD_BATCH + 1; d < FD_DIMSIZE; ++d) { |
117 | 0 | indices_[d] = MaxIndexOfDim(static_cast<FlexDimensions>(d)); |
118 | 0 | } |
119 | 0 | SetTFromIndices(); |
120 | 0 | } |
121 | | |
122 | | // Computes and sets t_ from the current indices_. |
123 | 5.24G | void StrideMap::Index::SetTFromIndices() { |
124 | 5.24G | t_ = 0; |
125 | 20.9G | for (int d = 0; d < FD_DIMSIZE; ++d) { |
126 | 15.7G | t_ += stride_map_->t_increments_[d] * indices_[d]; |
127 | 15.7G | } |
128 | 5.24G | } |
129 | | |
130 | | // Sets up the stride for the given array of height, width pairs. |
131 | 274k | void StrideMap::SetStride(const std::vector<std::pair<int, int>> &h_w_pairs) { |
132 | 274k | int max_height = 0; |
133 | 274k | int max_width = 0; |
134 | 274k | for (const std::pair<int, int> &hw : h_w_pairs) { |
135 | 274k | int height = hw.first; |
136 | 274k | int width = hw.second; |
137 | 274k | heights_.push_back(height); |
138 | 274k | widths_.push_back(width); |
139 | 274k | if (height > max_height) { |
140 | 274k | max_height = height; |
141 | 274k | } |
142 | 274k | if (width > max_width) { |
143 | 274k | max_width = width; |
144 | 274k | } |
145 | 274k | } |
146 | 274k | shape_[FD_BATCH] = heights_.size(); |
147 | 274k | shape_[FD_HEIGHT] = max_height; |
148 | 274k | shape_[FD_WIDTH] = max_width; |
149 | 274k | ComputeTIncrements(); |
150 | 274k | } |
151 | | |
152 | | // Scales width and height dimensions by the given factors. |
153 | 274k | void StrideMap::ScaleXY(int x_factor, int y_factor) { |
154 | 274k | for (int &height : heights_) { |
155 | 274k | height /= y_factor; |
156 | 274k | } |
157 | 274k | for (int &width : widths_) { |
158 | 274k | width /= x_factor; |
159 | 274k | } |
160 | 274k | shape_[FD_HEIGHT] /= y_factor; |
161 | 274k | shape_[FD_WIDTH] /= x_factor; |
162 | 274k | ComputeTIncrements(); |
163 | 274k | } |
164 | | |
165 | | // Reduces width to 1, across the batch, whatever the input size. |
166 | 274k | void StrideMap::ReduceWidthTo1() { |
167 | 274k | widths_.assign(widths_.size(), 1); |
168 | 274k | shape_[FD_WIDTH] = 1; |
169 | 274k | ComputeTIncrements(); |
170 | 274k | } |
171 | | |
172 | | // Transposes the width and height dimensions. |
173 | 548k | void StrideMap::TransposeXY() { |
174 | 548k | std::swap(shape_[FD_HEIGHT], shape_[FD_WIDTH]); |
175 | 548k | std::swap(heights_, widths_); |
176 | 548k | ComputeTIncrements(); |
177 | 548k | } |
178 | | |
179 | | // Computes t_increments_ from shape_. |
180 | 1.37M | void StrideMap::ComputeTIncrements() { |
181 | 1.37M | t_increments_[FD_DIMSIZE - 1] = 1; |
182 | 4.11M | for (int d = FD_DIMSIZE - 2; d >= 0; --d) { |
183 | 2.74M | t_increments_[d] = t_increments_[d + 1] * shape_[d + 1]; |
184 | 2.74M | } |
185 | 1.37M | } |
186 | | |
187 | | } // namespace tesseract |