/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  |