tesseract  v4.0.0-17-g361f3264
Open Source OCR Engine
matrix.h
1 /* -*-C-*-
2  ******************************************************************************
3  * File: matrix.h
4  * Description: Generic 2-d array/matrix and banded triangular matrix class.
5  * Author: Ray Smith
6  * TODO(rays) Separate from ratings matrix, which it also contains:
7  *
8  * Description: Ratings matrix class (specialization of banded matrix).
9  * Segmentation search matrix of lists of BLOB_CHOICE.
10  * Author: Mark Seaman, OCR Technology
11  * Created: Wed May 16 13:22:06 1990
12  * Modified: Tue Mar 19 16:00:20 1991 (Mark Seaman) marks@hpgrlt
13  *
14  * (c) Copyright 1990, Hewlett-Packard Company.
15  ** Licensed under the Apache License, Version 2.0 (the "License");
16  ** you may not use this file except in compliance with the License.
17  ** You may obtain a copy of the License at
18  ** http://www.apache.org/licenses/LICENSE-2.0
19  ** Unless required by applicable law or agreed to in writing, software
20  ** distributed under the License is distributed on an "AS IS" BASIS,
21  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22  ** See the License for the specific language governing permissions and
23  ** limitations under the License.
24  *
25  *********************************************************************************/
26 
27 #ifndef TESSERACT_CCSTRUCT_MATRIX_H_
28 #define TESSERACT_CCSTRUCT_MATRIX_H_
29 
30 #include <algorithm> // for max, min
31 #include <cmath> // for sqrt, fabs, isfinite
32 #include <cstdint> // for int32_t
33 #include <cstdio> // for FILE
34 #include <cstring> // for memcpy
35 #include "errcode.h" // for ASSERT_HOST
36 #include "helpers.h" // for ReverseN, ClipToRange
37 #include "kdpair.h" // for KDPairInc
38 #include "points.h" // for ICOORD
39 #include "serialis.h" // for TFile
40 
41 class BLOB_CHOICE_LIST;
42 class UNICHARSET;
43 
44 #define NOT_CLASSIFIED static_cast<BLOB_CHOICE_LIST*>(nullptr)
45 
46 // A generic class to hold a 2-D matrix with entries of type T, but can also
47 // act as a base class for other implementations, such as a triangular or
48 // banded matrix.
49 template <class T>
50 class GENERIC_2D_ARRAY {
51  public:
52  // Initializes the array size, and empty element, but cannot allocate memory
53  // for the subclasses or initialize because calls to the num_elements
54  // member will be routed to the base class implementation. Subclasses can
55  // either pass the memory in, or allocate after by calling Resize().
56  GENERIC_2D_ARRAY(int dim1, int dim2, const T& empty, T* array)
57  : empty_(empty), dim1_(dim1), dim2_(dim2), array_(array) {
58  size_allocated_ = dim1 * dim2;
59  }
60  // Original constructor for a full rectangular matrix DOES allocate memory
61  // and initialize it to empty.
62  GENERIC_2D_ARRAY(int dim1, int dim2, const T& empty)
63  : empty_(empty), dim1_(dim1), dim2_(dim2) {
64  int new_size = dim1 * dim2;
65  array_ = new T[new_size];
66  size_allocated_ = new_size;
67  for (int i = 0; i < size_allocated_; ++i)
68  array_[i] = empty_;
69  }
70  // Default constructor for array allocation. Use Resize to set the size.
72  : array_(nullptr), empty_(static_cast<T>(0)), dim1_(0), dim2_(0),
73  size_allocated_(0) {
74  }
76  : array_(nullptr), empty_(static_cast<T>(0)), dim1_(0), dim2_(0),
77  size_allocated_(0) {
78  *this = src;
79  }
80  virtual ~GENERIC_2D_ARRAY() { delete[] array_; }
81 
82  void operator=(const GENERIC_2D_ARRAY<T>& src) {
83  ResizeNoInit(src.dim1(), src.dim2());
84  memcpy(array_, src.array_, num_elements() * sizeof(array_[0]));
85  }
86 
87  // Reallocates the array to the given size. Does not keep old data, but does
88  // not initialize the array either.
89  // The allocated memory is expanded on the end by pad, allowing deliberate
90  // access beyond the bounds of the array.
91  void ResizeNoInit(int size1, int size2, int pad = 0) {
92  int new_size = size1 * size2 + pad;
93  if (new_size > size_allocated_) {
94  delete [] array_;
95  array_ = new T[new_size];
96  size_allocated_ = new_size;
97  }
98  dim1_ = size1;
99  dim2_ = size2;
100  // Fill the padding data so it isn't uninitialized.
101  for (int i = size1 * size2; i < new_size; ++i) array_[i] = empty_;
102  }
103 
104  // Reallocate the array to the given size. Does not keep old data.
105  void Resize(int size1, int size2, const T& empty) {
106  empty_ = empty;
107  ResizeNoInit(size1, size2);
108  Clear();
109  }
110 
111  // Reallocate the array to the given size, keeping old data.
112  void ResizeWithCopy(int size1, int size2) {
113  if (size1 != dim1_ || size2 != dim2_) {
114  int new_size = size1 * size2;
115  T* new_array = new T[new_size];
116  for (int col = 0; col < size1; ++col) {
117  for (int row = 0; row < size2; ++row) {
118  int old_index = col * dim2() + row;
119  int new_index = col * size2 + row;
120  if (col < dim1_ && row < dim2_) {
121  new_array[new_index] = array_[old_index];
122  } else {
123  new_array[new_index] = empty_;
124  }
125  }
126  }
127  delete[] array_;
128  array_ = new_array;
129  dim1_ = size1;
130  dim2_ = size2;
131  size_allocated_ = new_size;
132  }
133  }
134 
135  // Sets all the elements of the array to the empty value.
136  void Clear() {
137  int total_size = num_elements();
138  for (int i = 0; i < total_size; ++i)
139  array_[i] = empty_;
140  }
141 
142  // Writes to the given file. Returns false in case of error.
143  // Only works with bitwise-serializeable types!
144  bool Serialize(FILE* fp) const {
145  if (!SerializeSize(fp)) return false;
146  if (!tesseract::Serialize(fp, &empty_)) return false;
147  int size = num_elements();
148  return tesseract::Serialize(fp, &array_[0], size);
149  }
150 
151  bool Serialize(tesseract::TFile* fp) const {
152  if (!SerializeSize(fp)) return false;
153  if (!fp->Serialize(&empty_)) return false;
154  int size = num_elements();
155  return fp->Serialize(&array_[0], size);
156  }
157 
158  // Reads from the given file. Returns false in case of error.
159  // Only works with bitwise-serializeable types!
160  // If swap is true, assumes a big/little-endian swap is needed.
161  bool DeSerialize(bool swap, FILE* fp) {
162  if (!DeSerializeSize(swap, fp)) return false;
163  if (!tesseract::DeSerialize(fp, &empty_)) return false;
164  if (swap) ReverseN(&empty_, sizeof(empty_));
165  int size = num_elements();
166  if (!tesseract::DeSerialize(fp, &array_[0], size)) return false;
167  if (swap) {
168  for (int i = 0; i < size; ++i)
169  ReverseN(&array_[i], sizeof(array_[i]));
170  }
171  return true;
172  }
173 
175  return DeSerializeSize(fp) &&
176  fp->DeSerialize(&empty_) &&
177  fp->DeSerialize(&array_[0], num_elements());
178  }
179 
180  // Writes to the given file. Returns false in case of error.
181  // Assumes a T::Serialize(FILE*) const function.
182  bool SerializeClasses(FILE* fp) const {
183  if (!SerializeSize(fp)) return false;
184  if (!empty_.Serialize(fp)) return false;
185  int size = num_elements();
186  for (int i = 0; i < size; ++i) {
187  if (!array_[i].Serialize(fp)) return false;
188  }
189  return true;
190  }
191 
192  // Reads from the given file. Returns false in case of error.
193  // Assumes a T::DeSerialize(bool swap, FILE*) function.
194  // If swap is true, assumes a big/little-endian swap is needed.
195  bool DeSerializeClasses(bool swap, FILE* fp) {
196  if (!DeSerializeSize(swap, fp)) return false;
197  if (!empty_.DeSerialize(swap, fp)) return false;
198  int size = num_elements();
199  for (int i = 0; i < size; ++i) {
200  if (!array_[i].DeSerialize(swap, fp)) return false;
201  }
202  return true;
203  }
204 
205  // Provide the dimensions of this rectangular matrix.
206  int dim1() const { return dim1_; }
207  int dim2() const { return dim2_; }
208  // Returns the number of elements in the array.
209  // Banded/triangular matrices may override.
210  virtual int num_elements() const { return dim1_ * dim2_; }
211 
212  // Expression to select a specific location in the matrix. The matrix is
213  // stored COLUMN-major, so the left-most index is the most significant.
214  // This allows [][] access to use indices in the same order as (,).
215  virtual int index(int column, int row) const {
216  return (column * dim2_ + row);
217  }
218 
219  // Put a list element into the matrix at a specific location.
220  void put(ICOORD pos, const T& thing) {
221  array_[this->index(pos.x(), pos.y())] = thing;
222  }
223  void put(int column, int row, const T& thing) {
224  array_[this->index(column, row)] = thing;
225  }
226 
227  // Get the item at a specified location from the matrix.
228  T get(ICOORD pos) const {
229  return array_[this->index(pos.x(), pos.y())];
230  }
231  T get(int column, int row) const {
232  return array_[this->index(column, row)];
233  }
234  // Return a reference to the element at the specified location.
235  const T& operator()(int column, int row) const {
236  return array_[this->index(column, row)];
237  }
238  T& operator()(int column, int row) {
239  return array_[this->index(column, row)];
240  }
241  // Allow access using array[column][row]. NOTE that the indices are
242  // in the same left-to-right order as the () indexing.
243  T* operator[](int column) {
244  return &array_[this->index(column, 0)];
245  }
246  const T* operator[](int column) const {
247  return &array_[this->index(column, 0)];
248  }
249 
250  // Adds addend to *this, element-by-element.
251  void operator+=(const GENERIC_2D_ARRAY<T>& addend) {
252  if (dim2_ == addend.dim2_) {
253  // Faster if equal size in the major dimension.
254  int size = std::min(num_elements(), addend.num_elements());
255  for (int i = 0; i < size; ++i) {
256  array_[i] += addend.array_[i];
257  }
258  } else {
259  for (int x = 0; x < dim1_; x++) {
260  for (int y = 0; y < dim2_; y++) {
261  (*this)(x, y) += addend(x, y);
262  }
263  }
264  }
265  }
266  // Subtracts minuend from *this, element-by-element.
267  void operator-=(const GENERIC_2D_ARRAY<T>& minuend) {
268  if (dim2_ == minuend.dim2_) {
269  // Faster if equal size in the major dimension.
270  int size = std::min(num_elements(), minuend.num_elements());
271  for (int i = 0; i < size; ++i) {
272  array_[i] -= minuend.array_[i];
273  }
274  } else {
275  for (int x = 0; x < dim1_; x++) {
276  for (int y = 0; y < dim2_; y++) {
277  (*this)(x, y) -= minuend(x, y);
278  }
279  }
280  }
281  }
282  // Adds addend to all elements.
283  void operator+=(const T& addend) {
284  int size = num_elements();
285  for (int i = 0; i < size; ++i) {
286  array_[i] += addend;
287  }
288  }
289  // Multiplies *this by factor, element-by-element.
290  void operator*=(const T& factor) {
291  int size = num_elements();
292  for (int i = 0; i < size; ++i) {
293  array_[i] *= factor;
294  }
295  }
296  // Clips *this to the given range.
297  void Clip(const T& rangemin, const T& rangemax) {
298  int size = num_elements();
299  for (int i = 0; i < size; ++i) {
300  array_[i] = ClipToRange(array_[i], rangemin, rangemax);
301  }
302  }
303  // Returns true if all elements of *this are within the given range.
304  // Only uses operator<
305  bool WithinBounds(const T& rangemin, const T& rangemax) const {
306  int size = num_elements();
307  for (int i = 0; i < size; ++i) {
308  const T& value = array_[i];
309  if (value < rangemin || rangemax < value)
310  return false;
311  }
312  return true;
313  }
314  // Normalize the whole array.
315  double Normalize() {
316  int size = num_elements();
317  if (size <= 0) return 0.0;
318  // Compute the mean.
319  double mean = 0.0;
320  for (int i = 0; i < size; ++i) {
321  mean += array_[i];
322  }
323  mean /= size;
324  // Subtract the mean and compute the standard deviation.
325  double sd = 0.0;
326  for (int i = 0; i < size; ++i) {
327  double normed = array_[i] - mean;
328  array_[i] = normed;
329  sd += normed * normed;
330  }
331  sd = sqrt(sd / size);
332  if (sd > 0.0) {
333  // Divide by the sd.
334  for (int i = 0; i < size; ++i) {
335  array_[i] /= sd;
336  }
337  }
338  return sd;
339  }
340 
341  // Returns the maximum value of the array.
342  T Max() const {
343  int size = num_elements();
344  if (size <= 0) return empty_;
345  // Compute the max.
346  T max_value = array_[0];
347  for (int i = 1; i < size; ++i) {
348  const T& value = array_[i];
349  if (value > max_value) max_value = value;
350  }
351  return max_value;
352  }
353 
354  // Returns the maximum absolute value of the array.
355  T MaxAbs() const {
356  int size = num_elements();
357  if (size <= 0) return empty_;
358  // Compute the max.
359  T max_abs = static_cast<T>(0);
360  for (int i = 0; i < size; ++i) {
361  T value = static_cast<T>(fabs(array_[i]));
362  if (value > max_abs) max_abs = value;
363  }
364  return max_abs;
365  }
366 
367  // Accumulates the element-wise sums of squares of src into *this.
368  void SumSquares(const GENERIC_2D_ARRAY<T>& src, const T& decay_factor) {
369  T update_factor = 1.0 - decay_factor;
370  int size = num_elements();
371  for (int i = 0; i < size; ++i) {
372  array_[i] = array_[i] * decay_factor +
373  update_factor * src.array_[i] * src.array_[i];
374  }
375  }
376 
377  // Scales each element using the adam algorithm, ie array_[i] by
378  // sqrt(sqsum[i] + epsilon)).
380  const GENERIC_2D_ARRAY<T>& sqsum, const T& epsilon) {
381  int size = num_elements();
382  for (int i = 0; i < size; ++i) {
383  array_[i] += sum.array_[i] / (sqrt(sqsum.array_[i]) + epsilon);
384  }
385  }
386 
387  void AssertFinite() const {
388  int size = num_elements();
389  for (int i = 0; i < size; ++i) {
390  ASSERT_HOST(isfinite(array_[i]));
391  }
392  }
393 
394  // REGARDLESS OF THE CURRENT DIMENSIONS, treats the data as a
395  // num_dims-dimensional array/tensor with dimensions given by dims, (ordered
396  // from most significant to least significant, the same as standard C arrays)
397  // and moves src_dim to dest_dim, with the initial dest_dim and any dimensions
398  // in between shifted towards the hole left by src_dim. Example:
399  // Current data content: array_=[0, 1, 2, ....119]
400  // perhaps *this may be of dim[40, 3], with values [[0, 1, 2][3, 4, 5]...
401  // but the current dimensions are irrelevant.
402  // num_dims = 4, dims=[5, 4, 3, 2]
403  // src_dim=3, dest_dim=1
404  // tensor=[[[[0, 1][2, 3][4, 5]]
405  // [[6, 7][8, 9][10, 11]]
406  // [[12, 13][14, 15][16, 17]]
407  // [[18, 19][20, 21][22, 23]]]
408  // [[[24, 25]...
409  // output dims =[5, 2, 4, 3]
410  // output tensor=[[[[0, 2, 4][6, 8, 10][12, 14, 16][18, 20, 22]]
411  // [[1, 3, 5][7, 9, 11][13, 15, 17][19, 21, 23]]]
412  // [[[24, 26, 28]...
413  // which is stored in the array_ as:
414  // [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 1, 3, 5, 7, 9, 11, 13...]
415  // NOTE: the 2 stored matrix dimensions are simply copied from *this. To
416  // change the dimensions after the transpose, use ResizeNoInit.
417  // Higher dimensions above 2 are strictly the responsibility of the caller.
418  void RotatingTranspose(const int* dims, int num_dims, int src_dim,
419  int dest_dim, GENERIC_2D_ARRAY<T>* result) const {
420  int max_d = std::max(src_dim, dest_dim);
421  int min_d = std::min(src_dim, dest_dim);
422  // In a tensor of shape [d0, d1... min_d, ... max_d, ... dn-2, dn-1], the
423  // ends outside of min_d and max_d are unaffected, with [max_d +1, dn-1]
424  // being contiguous blocks of data that will move together, and
425  // [d0, min_d -1] being replicas of the transpose operation.
426  // num_replicas represents the large dimensions unchanged by the operation.
427  // move_size represents the small dimensions unchanged by the operation.
428  // src_step represents the stride in the src between each adjacent group
429  // in the destination.
430  int num_replicas = 1, move_size = 1, src_step = 1;
431  for (int d = 0; d < min_d; ++d) num_replicas *= dims[d];
432  for (int d = max_d + 1; d < num_dims; ++d) move_size *= dims[d];
433  for (int d = src_dim + 1; d < num_dims; ++d) src_step *= dims[d];
434  if (src_dim > dest_dim) src_step *= dims[src_dim];
435  // wrap_size is the size of a single replica, being the amount that is
436  // handled num_replicas times.
437  int wrap_size = move_size;
438  for (int d = min_d; d <= max_d; ++d) wrap_size *= dims[d];
439  result->ResizeNoInit(dim1_, dim2_);
440  result->empty_ = empty_;
441  const T* src = array_;
442  T* dest = result->array_;
443  for (int replica = 0; replica < num_replicas; ++replica) {
444  for (int start = 0; start < src_step; start += move_size) {
445  for (int pos = start; pos < wrap_size; pos += src_step) {
446  memcpy(dest, src + pos, sizeof(*dest) * move_size);
447  dest += move_size;
448  }
449  }
450  src += wrap_size;
451  }
452  }
453 
454  // Delete objects pointed to by array_[i].
456  int size = num_elements();
457  for (int i = 0; i < size; ++i) {
458  T matrix_cell = array_[i];
459  if (matrix_cell != empty_)
460  delete matrix_cell;
461  }
462  }
463 
464  protected:
465  // Factored helper to serialize the size.
466  bool SerializeSize(FILE* fp) const {
467  uint32_t size = dim1_;
468  if (!tesseract::Serialize(fp, &size)) return false;
469  size = dim2_;
470  return tesseract::Serialize(fp, &size);
471  }
472  bool SerializeSize(tesseract::TFile* fp) const {
473  uint32_t size = dim1_;
474  if (!fp->Serialize(&size)) return false;
475  size = dim2_;
476  return fp->Serialize(&size);
477  }
478  // Factored helper to deserialize the size.
479  // If swap is true, assumes a big/little-endian swap is needed.
480  bool DeSerializeSize(bool swap, FILE* fp) {
481  uint32_t size1, size2;
482  if (!tesseract::DeSerialize(fp, &size1)) return false;
483  if (!tesseract::DeSerialize(fp, &size2)) return false;
484  if (swap) {
485  ReverseN(&size1, sizeof(size1));
486  ReverseN(&size2, sizeof(size2));
487  }
488  // Arbitrarily limit the number of elements to protect against bad data.
489  if (size1 > UINT16_MAX) return false;
490  if (size2 > UINT16_MAX) return false;
491  Resize(size1, size2, empty_);
492  return true;
493  }
495  int32_t size1, size2;
496  if (!fp->DeSerialize(&size1)) return false;
497  if (!fp->DeSerialize(&size2)) return false;
498  // Arbitrarily limit the number of elements to protect against bad data.
499  if (size1 > UINT16_MAX) return false;
500  if (size2 > UINT16_MAX) return false;
501  Resize(size1, size2, empty_);
502  return true;
503  }
504 
505  T* array_;
506  T empty_; // The unused cell.
507  int dim1_; // Size of the 1st dimension in indexing functions.
508  int dim2_; // Size of the 2nd dimension in indexing functions.
509  // The total size to which the array can be expanded before a realloc is
510  // needed. If Resize is used, memory is retained so it can be re-expanded
511  // without a further alloc, and this stores the allocated size.
513 };
514 
515 // A generic class to store a banded triangular matrix with entries of type T.
516 // In this array, the nominally square matrix is dim1_ x dim1_, and dim2_ is
517 // the number of bands, INCLUDING the diagonal. The storage is thus of size
518 // dim1_ * dim2_ and index(col, row) = col * dim2_ + row - col, and an
519 // assert will fail if row < col or row - col >= dim2.
520 template <class T>
521 class BandTriMatrix : public GENERIC_2D_ARRAY<T> {
522  public:
523  // Allocate a piece of memory to hold a 2d-array of the given dimension.
524  // Initialize all the elements of the array to empty instead of assuming
525  // that a default constructor can be used.
526  BandTriMatrix(int dim1, int dim2, const T& empty)
527  : GENERIC_2D_ARRAY<T>(dim1, dim2, empty) {
528  }
529  // The default destructor will do.
530 
531  // Provide the dimensions of this matrix.
532  // dimension is the size of the nominally square matrix.
533  int dimension() const { return this->dim1_; }
534  // bandwidth is the number of bands in the matrix, INCLUDING the diagonal.
535  int bandwidth() const { return this->dim2_; }
536 
537  // Expression to select a specific location in the matrix. The matrix is
538  // stored COLUMN-major, so the left-most index is the most significant.
539  // This allows [][] access to use indices in the same order as (,).
540  virtual int index(int column, int row) const {
541  ASSERT_HOST(row >= column);
542  ASSERT_HOST(row - column < this->dim2_);
543  return column * this->dim2_ + row - column;
544  }
545 
546  // Appends array2 corner-to-corner to *this, making an array of dimension
547  // equal to the sum of the individual dimensions.
548  // array2 is not destroyed, but is left empty, as all elements are moved
549  // to *this.
551  int new_dim1 = this->dim1_ + array2->dim1_;
552  int new_dim2 = std::max(this->dim2_, array2->dim2_);
553  T* new_array = new T[new_dim1 * new_dim2];
554  for (int col = 0; col < new_dim1; ++col) {
555  for (int j = 0; j < new_dim2; ++j) {
556  int new_index = col * new_dim2 + j;
557  if (col < this->dim1_ && j < this->dim2_) {
558  new_array[new_index] = this->get(col, col + j);
559  } else if (col >= this->dim1_ && j < array2->dim2_) {
560  new_array[new_index] = array2->get(col - this->dim1_,
561  col - this->dim1_ + j);
562  array2->put(col - this->dim1_, col - this->dim1_ + j, nullptr);
563  } else {
564  new_array[new_index] = this->empty_;
565  }
566  }
567  }
568  delete[] this->array_;
569  this->array_ = new_array;
570  this->dim1_ = new_dim1;
571  this->dim2_ = new_dim2;
572  }
573 };
574 
575 class MATRIX : public BandTriMatrix<BLOB_CHOICE_LIST *> {
576  public:
577  MATRIX(int dimension, int bandwidth)
578  : BandTriMatrix<BLOB_CHOICE_LIST *>(dimension, bandwidth, NOT_CLASSIFIED) {}
579 
580  virtual ~MATRIX();
581 
582  // Returns true if there are any real classification results.
583  bool Classified(int col, int row, int wildcard_id) const;
584 
585  // Expands the existing matrix in-place to make the band wider, without
586  // losing any existing data.
587  void IncreaseBandSize(int bandwidth);
588 
589  // Returns a bigger MATRIX with a new column and row in the matrix in order
590  // to split the blob at the given (ind,ind) diagonal location.
591  // Entries are relocated to the new MATRIX using the transformation defined
592  // by MATRIX_COORD::MapForSplit.
593  // Transfers the pointer data to the new MATRIX and deletes *this.
594  MATRIX* ConsumeAndMakeBigger(int ind);
595 
596  // Makes and returns a deep copy of *this, including all the BLOB_CHOICEs
597  // on the lists, but not any LanguageModelState that may be attached to the
598  // BLOB_CHOICEs.
599  MATRIX* DeepCopy() const;
600 
601  // Print a shortened version of the contents of the matrix.
602  void print(const UNICHARSET &unicharset) const;
603 };
604 
605 struct MATRIX_COORD {
606  static void Delete(void *arg) {
607  MATRIX_COORD *c = static_cast<MATRIX_COORD *>(arg);
608  delete c;
609  }
610  // Default constructor required by GenericHeap.
611  MATRIX_COORD() : col(0), row(0) {}
612  MATRIX_COORD(int c, int r): col(c), row(r) {}
614 
615  bool Valid(const MATRIX &m) const {
616  return 0 <= col && col < m.dimension() &&
617  col <= row && row < col + m.bandwidth() && row < m.dimension();
618  }
619 
620  // Remaps the col,row pair to split the blob at the given (ind,ind) diagonal
621  // location.
622  // Entries at (i,j) for i in [0,ind] and j in [ind,dim) move to (i,j+1),
623  // making a new row at ind.
624  // Entries at (i,j) for i in [ind+1,dim) and j in [i,dim) move to (i+i,j+1),
625  // making a new column at ind+1.
626  void MapForSplit(int ind) {
627  ASSERT_HOST(row >= col);
628  if (col > ind) ++col;
629  if (row >= ind) ++row;
630  ASSERT_HOST(row >= col);
631  }
632 
633  int col;
634  int row;
635 };
636 
637 // The MatrixCoordPair contains a MATRIX_COORD and its priority.
639 
640 #endif // TESSERACT_CCSTRUCT_MATRIX_H_
void operator-=(const GENERIC_2D_ARRAY< T > &minuend)
Definition: matrix.h:267
GENERIC_2D_ARRAY(int dim1, int dim2, const T &empty, T *array)
Definition: matrix.h:56
void put(int column, int row, const T &thing)
Definition: matrix.h:223
~MATRIX_COORD()
Definition: matrix.h:613
int size_allocated_
Definition: matrix.h:512
bool SerializeSize(tesseract::TFile *fp) const
Definition: matrix.h:472
double Normalize()
Definition: matrix.h:315
BandTriMatrix(int dim1, int dim2, const T &empty)
Definition: matrix.h:526
int dim1_
Definition: matrix.h:507
void SumSquares(const GENERIC_2D_ARRAY< T > &src, const T &decay_factor)
Definition: matrix.h:368
int16_t x() const
access function
Definition: points.h:53
bool DeSerializeClasses(bool swap, FILE *fp)
Definition: matrix.h:195
bool SerializeSize(FILE *fp) const
Definition: matrix.h:466
void put(ICOORD pos, const T &thing)
Definition: matrix.h:220
T MaxAbs() const
Definition: matrix.h:355
int col
Definition: matrix.h:633
Definition: kdpair.h:51
void ResizeWithCopy(int size1, int size2)
Definition: matrix.h:112
Definition: intsimdmatrix.h:25
Definition: unicharset.h:146
GENERIC_2D_ARRAY(int dim1, int dim2, const T &empty)
Definition: matrix.h:62
void AdamUpdate(const GENERIC_2D_ARRAY< T > &sum, const GENERIC_2D_ARRAY< T > &sqsum, const T &epsilon)
Definition: matrix.h:379
void operator*=(const T &factor)
Definition: matrix.h:290
void Clip(const T &rangemin, const T &rangemax)
Definition: matrix.h:297
T empty_
Definition: matrix.h:506
MATRIX_COORD()
Definition: matrix.h:611
Definition: matrix.h:575
void AssertFinite() const
Definition: matrix.h:387
Definition: serialis.h:77
int dim1() const
Definition: matrix.h:206
GENERIC_2D_ARRAY()
Definition: matrix.h:71
void RotatingTranspose(const int *dims, int num_dims, int src_dim, int dest_dim, GENERIC_2D_ARRAY< T > *result) const
Definition: matrix.h:418
bool DeSerializeSize(bool swap, FILE *fp)
Definition: matrix.h:480
T & operator()(int column, int row)
Definition: matrix.h:238
void operator=(const GENERIC_2D_ARRAY< T > &src)
Definition: matrix.h:82
int dim2() const
Definition: matrix.h:207
void MapForSplit(int ind)
Definition: matrix.h:626
void operator+=(const GENERIC_2D_ARRAY< T > &addend)
Definition: matrix.h:251
const T * operator[](int column) const
Definition: matrix.h:246
bool DeSerialize(char *data, size_t count=1)
Definition: serialis.cpp:103
bool Serialize(FILE *fp) const
Definition: matrix.h:144
bool Serialize(tesseract::TFile *fp) const
Definition: matrix.h:151
int bandwidth() const
Definition: matrix.h:535
bool DeSerialize(tesseract::TFile *fp)
Definition: matrix.h:174
bool Serialize(FILE *fp, const char *data, size_t n)
Definition: serialis.cpp:59
int16_t y() const
access_function
Definition: points.h:57
void ResizeNoInit(int size1, int size2, int pad=0)
Definition: matrix.h:91
bool Valid(const MATRIX &m) const
Definition: matrix.h:615
void operator+=(const T &addend)
Definition: matrix.h:283
T Max() const
Definition: matrix.h:342
virtual int num_elements() const
Definition: matrix.h:210
bool DeSerialize(bool swap, FILE *fp)
Definition: matrix.h:161
T get(ICOORD pos) const
Definition: matrix.h:228
integer coordinate
Definition: points.h:32
int row
Definition: matrix.h:634
MATRIX(int dimension, int bandwidth)
Definition: matrix.h:577
GENERIC_2D_ARRAY(const GENERIC_2D_ARRAY< T > &src)
Definition: matrix.h:75
virtual int index(int column, int row) const
Definition: matrix.h:215
bool SerializeClasses(FILE *fp) const
Definition: matrix.h:182
void Resize(int size1, int size2, const T &empty)
Definition: matrix.h:105
int dimension() const
Definition: matrix.h:533
virtual ~GENERIC_2D_ARRAY()
Definition: matrix.h:80
int dim2_
Definition: matrix.h:508
bool Serialize(const char *data, size_t count=1)
Definition: serialis.cpp:147
Definition: matrix.h:605
T * operator[](int column)
Definition: matrix.h:243
T * array_
Definition: matrix.h:505
bool DeSerializeSize(tesseract::TFile *fp)
Definition: matrix.h:494
bool WithinBounds(const T &rangemin, const T &rangemax) const
Definition: matrix.h:305
const T & operator()(int column, int row) const
Definition: matrix.h:235
void AttachOnCorner(BandTriMatrix< T > *array2)
Definition: matrix.h:550
Definition: matrix.h:521
MATRIX_COORD(int c, int r)
Definition: matrix.h:612
bool DeSerialize(FILE *fp, char *data, size_t n)
Definition: serialis.cpp:27
static void Delete(void *arg)
Definition: matrix.h:606
virtual int index(int column, int row) const
Definition: matrix.h:540
void Clear()
Definition: matrix.h:136
void delete_matrix_pointers()
Definition: matrix.h:455