Coverage Report

Created: 2025-09-27 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tesseract/src/lstm/stridemap.cpp
Line
Count
Source
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.15G
bool StrideMap::Index::IsValid() const {
25
  // Cheap check first.
26
15.4G
  for (int index : indices_) {
27
15.4G
    if (index < 0) {
28
39.6M
      return false;
29
39.6M
    }
30
15.4G
  }
31
20.3G
  for (int d = 0; d < FD_DIMSIZE; ++d) {
32
15.3G
    if (indices_[d] > MaxIndexOfDim(static_cast<FlexDimensions>(d))) {
33
53.9M
      return false;
34
53.9M
    }
35
15.3G
  }
36
5.06G
  return true;
37
5.11G
}
38
39
// Returns true if the index of the given dimension is the last.
40
569M
bool StrideMap::Index::IsLast(FlexDimensions dimension) const {
41
569M
  return MaxIndexOfDim(dimension) == indices_[dimension];
42
569M
}
43
44
// Given that the dimensions up to and including dim-1 are valid, returns the
45
// maximum index for dimension dim.
46
15.8G
int StrideMap::Index::MaxIndexOfDim(FlexDimensions dim) const {
47
15.8G
  int max_index = stride_map_->shape_[dim] - 1;
48
15.8G
  if (dim == FD_BATCH) {
49
5.11G
    return max_index;
50
5.11G
  }
51
15.8G
  assert(0 <= indices_[FD_BATCH]);
52
10.7G
  const size_t batch = indices_[FD_BATCH];
53
10.7G
  if (dim == FD_HEIGHT) {
54
5.13G
    if (batch >= stride_map_->heights_.size() || stride_map_->heights_[batch] > max_index) {
55
5.13G
      return max_index;
56
5.13G
    }
57
0
    return stride_map_->heights_[batch] - 1;
58
5.13G
  }
59
5.63G
  if (batch >= stride_map_->widths_.size() || stride_map_->widths_[batch] > max_index) {
60
5.63G
    return max_index;
61
5.63G
  }
62
0
  return stride_map_->widths_[batch] - 1;
63
5.63G
}
64
65
// Adds the given offset to the given dimension. Returns true if the result
66
// makes a valid index.
67
5.15G
bool StrideMap::Index::AddOffset(int offset, FlexDimensions dimension) {
68
5.15G
  indices_[dimension] += offset;
69
5.15G
  SetTFromIndices();
70
5.15G
  return IsValid();
71
5.15G
}
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
458M
bool StrideMap::Index::Increment() {
76
482M
  for (int d = FD_DIMSIZE - 1; d >= 0; --d) {
77
480M
    if (!IsLast(static_cast<FlexDimensions>(d))) {
78
456M
      t_ += stride_map_->t_increments_[d];
79
456M
      ++indices_[d];
80
456M
      return true;
81
456M
    }
82
24.0M
    t_ -= stride_map_->t_increments_[d] * indices_[d];
83
24.0M
    indices_[d] = 0;
84
    // Now carry to the next dimension.
85
24.0M
  }
86
1.88M
  return false;
87
458M
}
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.19G
void StrideMap::Index::SetTFromIndices() {
124
5.19G
  t_ = 0;
125
20.7G
  for (int d = 0; d < FD_DIMSIZE; ++d) {
126
15.5G
    t_ += stride_map_->t_increments_[d] * indices_[d];
127
15.5G
  }
128
5.19G
}
129
130
// Sets up the stride for the given array of height, width pairs.
131
269k
void StrideMap::SetStride(const std::vector<std::pair<int, int>> &h_w_pairs) {
132
269k
  int max_height = 0;
133
269k
  int max_width = 0;
134
269k
  for (const std::pair<int, int> &hw : h_w_pairs) {
135
269k
    int height = hw.first;
136
269k
    int width = hw.second;
137
269k
    heights_.push_back(height);
138
269k
    widths_.push_back(width);
139
269k
    if (height > max_height) {
140
269k
      max_height = height;
141
269k
    }
142
269k
    if (width > max_width) {
143
269k
      max_width = width;
144
269k
    }
145
269k
  }
146
269k
  shape_[FD_BATCH] = heights_.size();
147
269k
  shape_[FD_HEIGHT] = max_height;
148
269k
  shape_[FD_WIDTH] = max_width;
149
269k
  ComputeTIncrements();
150
269k
}
151
152
// Scales width and height dimensions by the given factors.
153
269k
void StrideMap::ScaleXY(int x_factor, int y_factor) {
154
269k
  for (int &height : heights_) {
155
269k
    height /= y_factor;
156
269k
  }
157
269k
  for (int &width : widths_) {
158
269k
    width /= x_factor;
159
269k
  }
160
269k
  shape_[FD_HEIGHT] /= y_factor;
161
269k
  shape_[FD_WIDTH] /= x_factor;
162
269k
  ComputeTIncrements();
163
269k
}
164
165
// Reduces width to 1, across the batch, whatever the input size.
166
269k
void StrideMap::ReduceWidthTo1() {
167
269k
  widths_.assign(widths_.size(), 1);
168
269k
  shape_[FD_WIDTH] = 1;
169
269k
  ComputeTIncrements();
170
269k
}
171
172
// Transposes the width and height dimensions.
173
538k
void StrideMap::TransposeXY() {
174
538k
  std::swap(shape_[FD_HEIGHT], shape_[FD_WIDTH]);
175
538k
  std::swap(heights_, widths_);
176
538k
  ComputeTIncrements();
177
538k
}
178
179
// Computes t_increments_ from shape_.
180
1.34M
void StrideMap::ComputeTIncrements() {
181
1.34M
  t_increments_[FD_DIMSIZE - 1] = 1;
182
4.03M
  for (int d = FD_DIMSIZE - 2; d >= 0; --d) {
183
2.69M
    t_increments_[d] = t_increments_[d + 1] * shape_[d + 1];
184
2.69M
  }
185
1.34M
}
186
187
} // namespace tesseract