tesseract  3.05.02
matrix.h
Go to the documentation of this file.
1 /* -*-C-*-
2  ******************************************************************************
3  * File: matrix.h (Formerly 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  * Descrition: 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  * Language: C
14  * Package: N/A
15  * Status: Experimental (Do Not Distribute)
16  *
17  * (c) Copyright 1990, Hewlett-Packard Company.
18  ** Licensed under the Apache License, Version 2.0 (the "License");
19  ** you may not use this file except in compliance with the License.
20  ** You may obtain a copy of the License at
21  ** http://www.apache.org/licenses/LICENSE-2.0
22  ** Unless required by applicable law or agreed to in writing, software
23  ** distributed under the License is distributed on an "AS IS" BASIS,
24  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25  ** See the License for the specific language governing permissions and
26  ** limitations under the License.
27  *
28  *********************************************************************************/
29 #ifndef TESSERACT_CCSTRUCT_MATRIX_H__
30 #define TESSERACT_CCSTRUCT_MATRIX_H__
31 
32 #include <math.h>
33 #include "kdpair.h"
34 #include "points.h"
35 #include "serialis.h"
36 #include "unicharset.h"
37 
38 class BLOB_CHOICE;
39 class BLOB_CHOICE_LIST;
40 
41 #define NOT_CLASSIFIED reinterpret_cast<BLOB_CHOICE_LIST*>(0)
42 
43 // A generic class to hold a 2-D matrix with entries of type T, but can also
44 // act as a base class for other implementations, such as a triangular or
45 // banded matrix.
46 template <class T>
48  public:
49  // Initializes the array size, and empty element, but cannot allocate memory
50  // for the subclasses or initialize because calls to the num_elements
51  // member will be routed to the base class implementation. Subclasses can
52  // either pass the memory in, or allocate after by calling Resize().
53  GENERIC_2D_ARRAY(int dim1, int dim2, const T& empty, T* array)
54  : empty_(empty), dim1_(dim1), dim2_(dim2), array_(array) {
56  }
57  // Original constructor for a full rectangular matrix DOES allocate memory
58  // and initialize it to empty.
59  GENERIC_2D_ARRAY(int dim1, int dim2, const T& empty)
60  : empty_(empty), dim1_(dim1), dim2_(dim2) {
61  int new_size = dim1 * dim2;
62  array_ = new T[new_size];
63  size_allocated_ = new_size;
64  for (int i = 0; i < size_allocated_; ++i)
65  array_[i] = empty_;
66  }
67  // Default constructor for array allocation. Use Resize to set the size.
69  : array_(NULL), empty_(static_cast<T>(0)), dim1_(0), dim2_(0),
70  size_allocated_(0) {
71  }
73  : array_(NULL), empty_(static_cast<T>(0)), dim1_(0), dim2_(0),
74  size_allocated_(0) {
75  *this = src;
76  }
77  virtual ~GENERIC_2D_ARRAY() { delete[] array_; }
78 
79  void operator=(const GENERIC_2D_ARRAY<T>& src) {
80  ResizeNoInit(src.dim1(), src.dim2());
81  memcpy(array_, src.array_, num_elements() * sizeof(array_[0]));
82  }
83 
84  // Reallocate the array to the given size. Does not keep old data, but does
85  // not initialize the array either.
86  void ResizeNoInit(int size1, int size2) {
87  int new_size = size1 * size2;
88  if (new_size > size_allocated_) {
89  delete [] array_;
90  array_ = new T[new_size];
91  size_allocated_ = new_size;
92  }
93  dim1_ = size1;
94  dim2_ = size2;
95  }
96 
97  // Reallocate the array to the given size. Does not keep old data.
98  void Resize(int size1, int size2, const T& empty) {
99  empty_ = empty;
100  ResizeNoInit(size1, size2);
101  Clear();
102  }
103 
104  // Reallocate the array to the given size, keeping old data.
105  void ResizeWithCopy(int size1, int size2) {
106  if (size1 != dim1_ || size2 != dim2_) {
107  int new_size = size1 * size2;
108  T* new_array = new T[new_size];
109  for (int col = 0; col < size1; ++col) {
110  for (int row = 0; row < size2; ++row) {
111  int old_index = col * dim2() + row;
112  int new_index = col * size2 + row;
113  if (col < dim1_ && row < dim2_) {
114  new_array[new_index] = array_[old_index];
115  } else {
116  new_array[new_index] = empty_;
117  }
118  }
119  }
120  delete[] array_;
121  array_ = new_array;
122  dim1_ = size1;
123  dim2_ = size2;
124  size_allocated_ = new_size;
125  }
126  }
127 
128  // Sets all the elements of the array to the empty value.
129  void Clear() {
130  int total_size = num_elements();
131  for (int i = 0; i < total_size; ++i)
132  array_[i] = empty_;
133  }
134 
135  // Writes to the given file. Returns false in case of error.
136  // Only works with bitwise-serializeable types!
137  bool Serialize(FILE* fp) const {
138  if (!SerializeSize(fp)) return false;
139  if (fwrite(&empty_, sizeof(empty_), 1, fp) != 1) return false;
140  int size = num_elements();
141  if (fwrite(array_, sizeof(*array_), size, fp) != size) return false;
142  return true;
143  }
144  bool Serialize(tesseract::TFile* fp) const {
145  if (!SerializeSize(fp)) return false;
146  if (fp->FWrite(&empty_, sizeof(empty_), 1) != 1) return false;
147  int size = num_elements();
148  if (fp->FWrite(array_, sizeof(*array_), size) != size) return false;
149  return true;
150  }
151 
152  // Reads from the given file. Returns false in case of error.
153  // Only works with bitwise-serializeable types!
154  // If swap is true, assumes a big/little-endian swap is needed.
155  bool DeSerialize(bool swap, FILE* fp) {
156  if (!DeSerializeSize(swap, fp)) return false;
157  if (fread(&empty_, sizeof(empty_), 1, fp) != 1) return false;
158  if (swap) ReverseN(&empty_, sizeof(empty_));
159  int size = num_elements();
160  if (fread(array_, sizeof(*array_), size, fp) != size) return false;
161  if (swap) {
162  for (int i = 0; i < size; ++i)
163  ReverseN(&array_[i], sizeof(array_[i]));
164  }
165  return true;
166  }
167  bool DeSerialize(bool swap, tesseract::TFile* fp) {
168  if (!DeSerializeSize(swap, fp)) return false;
169  if (fp->FRead(&empty_, sizeof(empty_), 1) != 1) return false;
170  if (swap) ReverseN(&empty_, sizeof(empty_));
171  int size = num_elements();
172  if (fp->FRead(array_, sizeof(*array_), size) != size) return false;
173  if (swap) {
174  for (int i = 0; i < size; ++i)
175  ReverseN(&array_[i], sizeof(array_[i]));
176  }
177  return true;
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 = 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 = 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) {
369  int size = num_elements();
370  for (int i = 0; i < size; ++i) {
371  array_[i] += src.array_[i] * src.array_[i];
372  }
373  }
374 
375  // Scales each element using the ada-grad algorithm, ie array_[i] by
376  // sqrt(num_samples/max(1,sqsum[i])).
377  void AdaGradScaling(const GENERIC_2D_ARRAY<T>& sqsum, int num_samples) {
378  int size = num_elements();
379  for (int i = 0; i < size; ++i) {
380  array_[i] *= sqrt(num_samples / MAX(1.0, sqsum.array_[i]));
381  }
382  }
383 
384  void AssertFinite() const {
385  int size = num_elements();
386  for (int i = 0; i < size; ++i) {
387  ASSERT_HOST(isfinite(array_[i]));
388  }
389  }
390 
391  // REGARDLESS OF THE CURRENT DIMENSIONS, treats the data as a
392  // num_dims-dimensional array/tensor with dimensions given by dims, (ordered
393  // from most significant to least significant, the same as standard C arrays)
394  // and moves src_dim to dest_dim, with the initial dest_dim and any dimensions
395  // in between shifted towards the hole left by src_dim. Example:
396  // Current data content: array_=[0, 1, 2, ....119]
397  // perhaps *this may be of dim[40, 3], with values [[0, 1, 2][3, 4, 5]...
398  // but the current dimensions are irrelevant.
399  // num_dims = 4, dims=[5, 4, 3, 2]
400  // src_dim=3, dest_dim=1
401  // tensor=[[[[0, 1][2, 3][4, 5]]
402  // [[6, 7][8, 9][10, 11]]
403  // [[12, 13][14, 15][16, 17]]
404  // [[18, 19][20, 21][22, 23]]]
405  // [[[24, 25]...
406  // output dims =[5, 2, 4, 3]
407  // output tensor=[[[[0, 2, 4][6, 8, 10][12, 14, 16][18, 20, 22]]
408  // [[1, 3, 5][7, 9, 11][13, 15, 17][19, 21, 23]]]
409  // [[[24, 26, 28]...
410  // which is stored in the array_ as:
411  // [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 1, 3, 5, 7, 9, 11, 13...]
412  // NOTE: the 2 stored matrix dimensions are simply copied from *this. To
413  // change the dimensions after the transpose, use ResizeNoInit.
414  // Higher dimensions above 2 are strictly the responsibility of the caller.
415  void RotatingTranspose(const int* dims, int num_dims, int src_dim,
416  int dest_dim, GENERIC_2D_ARRAY<T>* result) const {
417  int max_d = MAX(src_dim, dest_dim);
418  int min_d = MIN(src_dim, dest_dim);
419  // In a tensor of shape [d0, d1... min_d, ... max_d, ... dn-2, dn-1], the
420  // ends outside of min_d and max_d are unaffected, with [max_d +1, dn-1]
421  // being contiguous blocks of data that will move together, and
422  // [d0, min_d -1] being replicas of the transpose operation.
423  // num_replicas represents the large dimensions unchanged by the operation.
424  // move_size represents the small dimensions unchanged by the operation.
425  // src_step represents the stride in the src between each adjacent group
426  // in the destination.
427  int num_replicas = 1, move_size = 1, src_step = 1;
428  for (int d = 0; d < min_d; ++d) num_replicas *= dims[d];
429  for (int d = max_d + 1; d < num_dims; ++d) move_size *= dims[d];
430  for (int d = src_dim + 1; d < num_dims; ++d) src_step *= dims[d];
431  if (src_dim > dest_dim) src_step *= dims[src_dim];
432  // wrap_size is the size of a single replica, being the amount that is
433  // handled num_replicas times.
434  int wrap_size = move_size;
435  for (int d = min_d; d <= max_d; ++d) wrap_size *= dims[d];
436  result->ResizeNoInit(dim1_, dim2_);
437  result->empty_ = empty_;
438  const T* src = array_;
439  T* dest = result->array_;
440  for (int replica = 0; replica < num_replicas; ++replica) {
441  for (int start = 0; start < src_step; start += move_size) {
442  for (int pos = start; pos < wrap_size; pos += src_step) {
443  memcpy(dest, src + pos, sizeof(*dest) * move_size);
444  dest += move_size;
445  }
446  }
447  src += wrap_size;
448  }
449  }
450 
451  // Delete objects pointed to by array_[i].
453  int size = num_elements();
454  for (int i = 0; i < size; ++i) {
455  T matrix_cell = array_[i];
456  if (matrix_cell != empty_)
457  delete matrix_cell;
458  }
459  }
460 
461  protected:
462  // Factored helper to serialize the size.
463  bool SerializeSize(FILE* fp) const {
464  inT32 size = dim1_;
465  if (fwrite(&size, sizeof(size), 1, fp) != 1) return false;
466  size = dim2_;
467  if (fwrite(&size, sizeof(size), 1, fp) != 1) return false;
468  return true;
469  }
470  bool SerializeSize(tesseract::TFile* fp) const {
471  inT32 size = dim1_;
472  if (fp->FWrite(&size, sizeof(size), 1) != 1) return false;
473  size = dim2_;
474  if (fp->FWrite(&size, sizeof(size), 1) != 1) return false;
475  return true;
476  }
477  // Factored helper to deserialize the size.
478  // If swap is true, assumes a big/little-endian swap is needed.
479  bool DeSerializeSize(bool swap, FILE* fp) {
480  inT32 size1, size2;
481  if (fread(&size1, sizeof(size1), 1, fp) != 1) return false;
482  if (fread(&size2, sizeof(size2), 1, fp) != 1) return false;
483  if (swap) {
484  ReverseN(&size1, sizeof(size1));
485  ReverseN(&size2, sizeof(size2));
486  }
487  Resize(size1, size2, empty_);
488  return true;
489  }
490  bool DeSerializeSize(bool swap, tesseract::TFile* fp) {
491  inT32 size1, size2;
492  if (fp->FRead(&size1, sizeof(size1), 1) != 1) return false;
493  if (fp->FRead(&size2, sizeof(size2), 1) != 1) return false;
494  if (swap) {
495  ReverseN(&size1, sizeof(size1));
496  ReverseN(&size2, sizeof(size2));
497  }
498  Resize(size1, size2, empty_);
499  return true;
500  }
501 
502  T* array_;
503  T empty_; // The unused cell.
504  int dim1_; // Size of the 1st dimension in indexing functions.
505  int dim2_; // Size of the 2nd dimension in indexing functions.
506  // The total size to which the array can be expanded before a realloc is
507  // needed. If Resize is used, memory is retained so it can be re-expanded
508  // without a further alloc, and this stores the allocated size.
510 };
511 
512 // A generic class to store a banded triangular matrix with entries of type T.
513 // In this array, the nominally square matrix is dim1_ x dim1_, and dim2_ is
514 // the number of bands, INCLUDING the diagonal. The storage is thus of size
515 // dim1_ * dim2_ and index(col, row) = col * dim2_ + row - col, and an
516 // assert will fail if row < col or row - col >= dim2.
517 template <class T>
518 class BandTriMatrix : public GENERIC_2D_ARRAY<T> {
519  public:
520  // Allocate a piece of memory to hold a 2d-array of the given dimension.
521  // Initialize all the elements of the array to empty instead of assuming
522  // that a default constructor can be used.
523  BandTriMatrix(int dim1, int dim2, const T& empty)
524  : GENERIC_2D_ARRAY<T>(dim1, dim2, empty) {
525  }
526  // The default destructor will do.
527 
528  // Provide the dimensions of this matrix.
529  // dimension is the size of the nominally square matrix.
530  int dimension() const { return this->dim1_; }
531  // bandwidth is the number of bands in the matrix, INCLUDING the diagonal.
532  int bandwidth() const { return this->dim2_; }
533 
534  // Expression to select a specific location in the matrix. The matrix is
535  // stored COLUMN-major, so the left-most index is the most significant.
536  // This allows [][] access to use indices in the same order as (,).
537  virtual int index(int column, int row) const {
538  ASSERT_HOST(row >= column);
539  ASSERT_HOST(row - column < this->dim2_);
540  return column * this->dim2_ + row - column;
541  }
542 
543  // Appends array2 corner-to-corner to *this, making an array of dimension
544  // equal to the sum of the individual dimensions.
545  // array2 is not destroyed, but is left empty, as all elements are moved
546  // to *this.
548  int new_dim1 = this->dim1_ + array2->dim1_;
549  int new_dim2 = MAX(this->dim2_, array2->dim2_);
550  T* new_array = new T[new_dim1 * new_dim2];
551  for (int col = 0; col < new_dim1; ++col) {
552  for (int j = 0; j < new_dim2; ++j) {
553  int new_index = col * new_dim2 + j;
554  if (col < this->dim1_ && j < this->dim2_) {
555  new_array[new_index] = this->get(col, col + j);
556  } else if (col >= this->dim1_ && j < array2->dim2_) {
557  new_array[new_index] = array2->get(col - this->dim1_,
558  col - this->dim1_ + j);
559  array2->put(col - this->dim1_, col - this->dim1_ + j, NULL);
560  } else {
561  new_array[new_index] = this->empty_;
562  }
563  }
564  }
565  delete[] this->array_;
566  this->array_ = new_array;
567  this->dim1_ = new_dim1;
568  this->dim2_ = new_dim2;
569  }
570 };
571 
572 class MATRIX : public BandTriMatrix<BLOB_CHOICE_LIST *> {
573  public:
575  : BandTriMatrix<BLOB_CHOICE_LIST *>(dimension, bandwidth, NOT_CLASSIFIED) {}
576 
577  // Returns true if there are any real classification results.
578  bool Classified(int col, int row, int wildcard_id) const;
579 
580  // Expands the existing matrix in-place to make the band wider, without
581  // losing any existing data.
582  void IncreaseBandSize(int bandwidth);
583 
584  // Returns a bigger MATRIX with a new column and row in the matrix in order
585  // to split the blob at the given (ind,ind) diagonal location.
586  // Entries are relocated to the new MATRIX using the transformation defined
587  // by MATRIX_COORD::MapForSplit.
588  // Transfers the pointer data to the new MATRIX and deletes *this.
589  MATRIX* ConsumeAndMakeBigger(int ind);
590 
591  // Makes and returns a deep copy of *this, including all the BLOB_CHOICEs
592  // on the lists, but not any LanguageModelState that may be attached to the
593  // BLOB_CHOICEs.
594  MATRIX* DeepCopy() const;
595 
596  // Print a shortened version of the contents of the matrix.
597  void print(const UNICHARSET &unicharset) const;
598 };
599 
600 struct MATRIX_COORD {
601  static void Delete(void *arg) {
602  MATRIX_COORD *c = static_cast<MATRIX_COORD *>(arg);
603  delete c;
604  }
605  // Default constructor required by GenericHeap.
606  MATRIX_COORD() : col(0), row(0) {}
607  MATRIX_COORD(int c, int r): col(c), row(r) {}
609 
610  bool Valid(const MATRIX &m) const {
611  return 0 <= col && col < m.dimension() &&
612  col <= row && row < col + m.bandwidth() && row < m.dimension();
613  }
614 
615  // Remaps the col,row pair to split the blob at the given (ind,ind) diagonal
616  // location.
617  // Entries at (i,j) for i in [0,ind] and j in [ind,dim) move to (i,j+1),
618  // making a new row at ind.
619  // Entries at (i,j) for i in [ind+1,dim) and j in [i,dim) move to (i+i,j+1),
620  // making a new column at ind+1.
621  void MapForSplit(int ind) {
622  ASSERT_HOST(row >= col);
623  if (col > ind) ++col;
624  if (row >= ind) ++row;
625  ASSERT_HOST(row >= col);
626  }
627 
628  int col;
629  int row;
630 };
631 
632 // The MatrixCoordPair contains a MATRIX_COORD and its priority.
634 
635 #endif // TESSERACT_CCSTRUCT_MATRIX_H__
T * operator[](int column)
Definition: matrix.h:243
void Clip(const T &rangemin, const T &rangemax)
Definition: matrix.h:297
bool SerializeSize(tesseract::TFile *fp) const
Definition: matrix.h:470
void Resize(int size1, int size2, const T &empty)
Definition: matrix.h:98
void IncreaseBandSize(int bandwidth)
Definition: matrix.cpp:49
T & operator()(int column, int row)
Definition: matrix.h:238
MATRIX_COORD(int c, int r)
Definition: matrix.h:607
#define NOT_CLASSIFIED
Definition: matrix.h:41
GENERIC_2D_ARRAY()
Definition: matrix.h:68
virtual int num_elements() const
Definition: matrix.h:210
integer coordinate
Definition: points.h:30
int dimension() const
Definition: matrix.h:530
bool DeSerializeClasses(bool swap, FILE *fp)
Definition: matrix.h:195
int FWrite(const void *buffer, int size, int count)
Definition: serialis.cpp:131
void ResizeNoInit(int size1, int size2)
Definition: matrix.h:86
void operator+=(const GENERIC_2D_ARRAY< T > &addend)
Definition: matrix.h:251
int dim2() const
Definition: matrix.h:207
GENERIC_2D_ARRAY(int dim1, int dim2, const T &empty, T *array)
Definition: matrix.h:53
void RotatingTranspose(const int *dims, int num_dims, int src_dim, int dest_dim, GENERIC_2D_ARRAY< T > *result) const
Definition: matrix.h:415
void Clear()
Definition: matrix.h:129
int dim1() const
Definition: matrix.h:206
static void Delete(void *arg)
Definition: matrix.h:601
T get(ICOORD pos) const
Definition: matrix.h:228
#define MIN(x, y)
Definition: ndminx.h:28
const T & operator()(int column, int row) const
Definition: matrix.h:235
void MapForSplit(int ind)
Definition: matrix.h:621
bool DeSerializeSize(bool swap, FILE *fp)
Definition: matrix.h:479
T ClipToRange(const T &x, const T &lower_bound, const T &upper_bound)
Definition: helpers.h:115
GENERIC_2D_ARRAY(const GENERIC_2D_ARRAY< T > &src)
Definition: matrix.h:72
Definition: matrix.h:572
bool DeSerialize(bool swap, tesseract::TFile *fp)
Definition: matrix.h:167
int bandwidth() const
Definition: matrix.h:532
bool Classified(int col, int row, int wildcard_id) const
Definition: matrix.cpp:36
void AssertFinite() const
Definition: matrix.h:384
const T * operator[](int column) const
Definition: matrix.h:246
bool Valid(const MATRIX &m) const
Definition: matrix.h:610
bool WithinBounds(const T &rangemin, const T &rangemax) const
Definition: matrix.h:305
void operator=(const GENERIC_2D_ARRAY< T > &src)
Definition: matrix.h:79
virtual int index(int column, int row) const
Definition: matrix.h:537
bool Serialize(tesseract::TFile *fp) const
Definition: matrix.h:144
MATRIX * ConsumeAndMakeBigger(int ind)
Definition: matrix.cpp:58
MATRIX(int dimension, int bandwidth)
Definition: matrix.h:574
bool SerializeClasses(FILE *fp) const
Definition: matrix.h:182
void put(ICOORD pos, const T &thing)
Definition: matrix.h:220
MATRIX_COORD()
Definition: matrix.h:606
int FRead(void *buffer, int size, int count)
Definition: serialis.cpp:91
inT16 x() const
access function
Definition: points.h:52
T Max() const
Definition: matrix.h:342
bool DeSerialize(bool swap, FILE *fp)
Definition: matrix.h:155
MATRIX * DeepCopy() const
Definition: matrix.cpp:94
void SumSquares(const GENERIC_2D_ARRAY< T > &src)
Definition: matrix.h:368
#define MAX(x, y)
Definition: ndminx.h:24
bool DeSerializeSize(bool swap, tesseract::TFile *fp)
Definition: matrix.h:490
int inT32
Definition: host.h:35
~MATRIX_COORD()
Definition: matrix.h:608
virtual ~GENERIC_2D_ARRAY()
Definition: matrix.h:77
bool SerializeSize(FILE *fp) const
Definition: matrix.h:463
void delete_matrix_pointers()
Definition: matrix.h:452
void operator*=(const T &factor)
Definition: matrix.h:290
void ResizeWithCopy(int size1, int size2)
Definition: matrix.h:105
T MaxAbs() const
Definition: matrix.h:355
void AttachOnCorner(BandTriMatrix< T > *array2)
Definition: matrix.h:547
tesseract::KDPairInc< float, MATRIX_COORD > MatrixCoordPair
Definition: matrix.h:633
virtual int index(int column, int row) const
Definition: matrix.h:215
void put(int column, int row, const T &thing)
Definition: matrix.h:223
void AdaGradScaling(const GENERIC_2D_ARRAY< T > &sqsum, int num_samples)
Definition: matrix.h:377
void print(const UNICHARSET &unicharset) const
Definition: matrix.cpp:112
void ReverseN(void *ptr, int num_bytes)
Definition: helpers.h:177
BandTriMatrix(int dim1, int dim2, const T &empty)
Definition: matrix.h:523
bool Serialize(FILE *fp) const
Definition: matrix.h:137
#define ASSERT_HOST(x)
Definition: errcode.h:84
GENERIC_2D_ARRAY(int dim1, int dim2, const T &empty)
Definition: matrix.h:59
int size_allocated_
Definition: matrix.h:509
void operator+=(const T &addend)
Definition: matrix.h:283
double Normalize()
Definition: matrix.h:315
inT16 y() const
access_function
Definition: points.h:56
void operator-=(const GENERIC_2D_ARRAY< T > &minuend)
Definition: matrix.h:267