2009-07-11 10:50:24 +08:00
|
|
|
/* -*-C-*-
|
|
|
|
********************************************************************************
|
|
|
|
*
|
|
|
|
* File: helpers.h
|
|
|
|
* Description: General utility functions
|
|
|
|
* Author: Daria Antonova
|
|
|
|
*
|
|
|
|
* (c) Copyright 2009, Google Inc.
|
|
|
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
** you may not use this file except in compliance with the License.
|
|
|
|
** You may obtain a copy of the License at
|
|
|
|
** http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
** Unless required by applicable law or agreed to in writing, software
|
|
|
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
** See the License for the specific language governing permissions and
|
|
|
|
** limitations under the License.
|
|
|
|
*
|
|
|
|
********************************************************************************/
|
|
|
|
|
|
|
|
#ifndef TESSERACT_CCUTIL_HELPERS_H_
|
|
|
|
#define TESSERACT_CCUTIL_HELPERS_H_
|
|
|
|
|
2018-05-03 13:15:21 +08:00
|
|
|
#include <cassert>
|
2018-05-20 05:52:04 +08:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstring>
|
2016-12-01 07:51:17 +08:00
|
|
|
#include <functional>
|
|
|
|
#include <string>
|
2010-05-20 06:35:35 +08:00
|
|
|
|
2014-04-25 09:07:26 +08:00
|
|
|
#include "host.h"
|
|
|
|
|
|
|
|
// TODO(rays) Put the rest of the helpers in the namespace.
|
|
|
|
namespace tesseract {
|
|
|
|
|
|
|
|
// A simple linear congruential random number generator, using Knuth's
|
|
|
|
// constants from:
|
|
|
|
// http://en.wikipedia.org/wiki/Linear_congruential_generator.
|
|
|
|
class TRand {
|
|
|
|
public:
|
|
|
|
TRand() : seed_(1) {}
|
|
|
|
// Sets the seed to the given value.
|
2018-03-14 02:01:40 +08:00
|
|
|
void set_seed(uint64_t seed) {
|
2014-04-25 09:07:26 +08:00
|
|
|
seed_ = seed;
|
|
|
|
}
|
2016-12-01 07:51:17 +08:00
|
|
|
// Sets the seed using a hash of a string.
|
|
|
|
void set_seed(const std::string& str) {
|
|
|
|
std::hash<std::string> hasher;
|
2018-03-14 02:01:40 +08:00
|
|
|
set_seed(static_cast<uint64_t>(hasher(str)));
|
2016-12-01 07:51:17 +08:00
|
|
|
}
|
2014-04-25 09:07:26 +08:00
|
|
|
|
Use POSIX data types and macros (#878)
* api: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccmain: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccstruct: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* classify: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* cutil: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* dict: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* textord: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* training: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* wordrec: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccutil: Replace Tesseract data types by POSIX data types
Now all Tesseract data types which are no longer needed can be removed
from ccutil/host.h.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccmain: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccstruct: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* classify: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* dict: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* lstm: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* textord: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* wordrec: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccutil: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Remove the macros which are now unused from ccutil/host.h.
Remove also the obsolete history comments.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* Fix build error caused by ambiguous ClipToRange
Error message vom Appveyor CI:
C:\projects\tesseract\ccstruct\coutln.cpp(818): error C2672: 'ClipToRange': no matching overloaded function found [C:\projects\tesseract\build\libtesseract.vcxproj]
C:\projects\tesseract\ccstruct\coutln.cpp(818): error C2782: 'T ClipToRange(const T &,const T &,const T &)': template parameter 'T' is ambiguous [C:\projects\tesseract\build\libtesseract.vcxproj]
c:\projects\tesseract\ccutil\helpers.h(122): note: see declaration of 'ClipToRange'
C:\projects\tesseract\ccstruct\coutln.cpp(818): note: could be 'char'
C:\projects\tesseract\ccstruct\coutln.cpp(818): note: or 'int'
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* unittest: Replace Tesseract's MAX_INT8 by POSIX INT8_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* arch: Replace Tesseract's MAX_INT8 by POSIX INT8_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
2018-03-14 04:36:30 +08:00
|
|
|
// Returns an integer in the range 0 to INT32_MAX.
|
2018-03-14 02:01:40 +08:00
|
|
|
int32_t IntRand() {
|
2014-04-25 09:07:26 +08:00
|
|
|
Iterate();
|
|
|
|
return seed_ >> 33;
|
|
|
|
}
|
|
|
|
// Returns a floating point value in the range [-range, range].
|
|
|
|
double SignedRand(double range) {
|
Use POSIX data types and macros (#878)
* api: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccmain: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccstruct: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* classify: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* cutil: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* dict: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* textord: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* training: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* wordrec: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccutil: Replace Tesseract data types by POSIX data types
Now all Tesseract data types which are no longer needed can be removed
from ccutil/host.h.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccmain: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccstruct: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* classify: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* dict: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* lstm: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* textord: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* wordrec: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccutil: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Remove the macros which are now unused from ccutil/host.h.
Remove also the obsolete history comments.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* Fix build error caused by ambiguous ClipToRange
Error message vom Appveyor CI:
C:\projects\tesseract\ccstruct\coutln.cpp(818): error C2672: 'ClipToRange': no matching overloaded function found [C:\projects\tesseract\build\libtesseract.vcxproj]
C:\projects\tesseract\ccstruct\coutln.cpp(818): error C2782: 'T ClipToRange(const T &,const T &,const T &)': template parameter 'T' is ambiguous [C:\projects\tesseract\build\libtesseract.vcxproj]
c:\projects\tesseract\ccutil\helpers.h(122): note: see declaration of 'ClipToRange'
C:\projects\tesseract\ccstruct\coutln.cpp(818): note: could be 'char'
C:\projects\tesseract\ccstruct\coutln.cpp(818): note: or 'int'
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* unittest: Replace Tesseract's MAX_INT8 by POSIX INT8_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* arch: Replace Tesseract's MAX_INT8 by POSIX INT8_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
2018-03-14 04:36:30 +08:00
|
|
|
return range * 2.0 * IntRand() / INT32_MAX - range;
|
2014-04-25 09:07:26 +08:00
|
|
|
}
|
|
|
|
// Returns a floating point value in the range [0, range].
|
|
|
|
double UnsignedRand(double range) {
|
Use POSIX data types and macros (#878)
* api: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccmain: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccstruct: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* classify: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* cutil: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* dict: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* textord: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* training: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* wordrec: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccutil: Replace Tesseract data types by POSIX data types
Now all Tesseract data types which are no longer needed can be removed
from ccutil/host.h.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccmain: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccstruct: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* classify: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* dict: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* lstm: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* textord: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* wordrec: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccutil: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Remove the macros which are now unused from ccutil/host.h.
Remove also the obsolete history comments.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* Fix build error caused by ambiguous ClipToRange
Error message vom Appveyor CI:
C:\projects\tesseract\ccstruct\coutln.cpp(818): error C2672: 'ClipToRange': no matching overloaded function found [C:\projects\tesseract\build\libtesseract.vcxproj]
C:\projects\tesseract\ccstruct\coutln.cpp(818): error C2782: 'T ClipToRange(const T &,const T &,const T &)': template parameter 'T' is ambiguous [C:\projects\tesseract\build\libtesseract.vcxproj]
c:\projects\tesseract\ccutil\helpers.h(122): note: see declaration of 'ClipToRange'
C:\projects\tesseract\ccstruct\coutln.cpp(818): note: could be 'char'
C:\projects\tesseract\ccstruct\coutln.cpp(818): note: or 'int'
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* unittest: Replace Tesseract's MAX_INT8 by POSIX INT8_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* arch: Replace Tesseract's MAX_INT8 by POSIX INT8_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
2018-03-14 04:36:30 +08:00
|
|
|
return range * IntRand() / INT32_MAX;
|
2014-04-25 09:07:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Steps the generator to the next value.
|
|
|
|
void Iterate() {
|
2015-09-10 04:51:45 +08:00
|
|
|
seed_ *= 6364136223846793005ULL;
|
|
|
|
seed_ += 1442695040888963407ULL;
|
2014-04-25 09:07:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// The current value of the seed.
|
2018-03-14 02:01:40 +08:00
|
|
|
uint64_t seed_;
|
2014-04-25 09:07:26 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace tesseract
|
|
|
|
|
2009-07-11 10:50:24 +08:00
|
|
|
// Remove newline (if any) at the end of the string.
|
2010-05-20 06:35:35 +08:00
|
|
|
inline void chomp_string(char *str) {
|
2016-11-08 02:46:33 +08:00
|
|
|
int last_index = static_cast<int>(strlen(str)) - 1;
|
2012-02-02 11:14:43 +08:00
|
|
|
while (last_index >= 0 &&
|
|
|
|
(str[last_index] == '\n' || str[last_index] == '\r')) {
|
|
|
|
str[last_index--] = '\0';
|
2009-07-11 10:50:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Advance the current pointer of the file if it points to a newline character.
|
|
|
|
inline void SkipNewline(FILE *file) {
|
|
|
|
if (fgetc(file) != '\n') fseek(file, -1, SEEK_CUR);
|
|
|
|
}
|
|
|
|
|
2014-01-10 01:23:21 +08:00
|
|
|
// Swaps the two args pointed to by the pointers.
|
|
|
|
// Operator= and copy constructor must work on T.
|
|
|
|
template<typename T> inline void Swap(T* p1, T* p2) {
|
|
|
|
T tmp(*p2);
|
|
|
|
*p2 = *p1;
|
|
|
|
*p1 = tmp;
|
|
|
|
}
|
|
|
|
|
2010-05-20 06:35:35 +08:00
|
|
|
// return the smallest multiple of block_size greater than or equal to n.
|
|
|
|
inline int RoundUp(int n, int block_size) {
|
|
|
|
return block_size * ((n + block_size - 1) / block_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clip a numeric value to the interval [lower_bound, upper_bound].
|
|
|
|
template<typename T>
|
|
|
|
inline T ClipToRange(const T& x, const T& lower_bound, const T& upper_bound) {
|
|
|
|
if (x < lower_bound)
|
|
|
|
return lower_bound;
|
|
|
|
if (x > upper_bound)
|
|
|
|
return upper_bound;
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extend the range [lower_bound, upper_bound] to include x.
|
|
|
|
template<typename T1, typename T2>
|
|
|
|
inline void UpdateRange(const T1& x, T2* lower_bound, T2* upper_bound) {
|
|
|
|
if (x < *lower_bound)
|
|
|
|
*lower_bound = x;
|
|
|
|
if (x > *upper_bound)
|
|
|
|
*upper_bound = x;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decrease lower_bound to be <= x_lo AND increase upper_bound to be >= x_hi.
|
|
|
|
template<typename T1, typename T2>
|
|
|
|
inline void UpdateRange(const T1& x_lo, const T1& x_hi,
|
|
|
|
T2* lower_bound, T2* upper_bound) {
|
|
|
|
if (x_lo < *lower_bound)
|
|
|
|
*lower_bound = x_lo;
|
|
|
|
if (x_hi > *upper_bound)
|
|
|
|
*upper_bound = x_hi;
|
|
|
|
}
|
|
|
|
|
2012-02-02 11:14:43 +08:00
|
|
|
// Intersect the range [*lower2, *upper2] with the range [lower1, upper1],
|
|
|
|
// putting the result back in [*lower2, *upper2].
|
|
|
|
// If non-intersecting ranges are given, we end up with *lower2 > *upper2.
|
|
|
|
template<typename T>
|
|
|
|
inline void IntersectRange(const T& lower1, const T& upper1,
|
|
|
|
T* lower2, T* upper2) {
|
|
|
|
if (lower1 > *lower2)
|
|
|
|
*lower2 = lower1;
|
|
|
|
if (upper1 < *upper2)
|
|
|
|
*upper2 = upper1;
|
|
|
|
}
|
|
|
|
|
2010-05-20 06:35:35 +08:00
|
|
|
// Proper modulo arithmetic operator. Returns a mod b that works for -ve a.
|
|
|
|
// For any integer a and positive b, returns r : 0<=r<b and a=n*b + r for
|
|
|
|
// some integer n.
|
|
|
|
inline int Modulo(int a, int b) {
|
|
|
|
return (a % b + b) % b;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Integer division operator with rounding that works for negative input.
|
|
|
|
// Returns a divided by b, rounded to the nearest integer, without double
|
|
|
|
// counting at 0. With simple rounding 1/3 = 0, 0/3 = 0 -1/3 = 0, -2/3 = 0,
|
|
|
|
// -3/3 = 0 and -4/3 = -1.
|
|
|
|
// I want 1/3 = 0, 0/3 = 0, -1/3 = 0, -2/3 = -1, -3/3 = -1 and -4/3 = -1.
|
|
|
|
inline int DivRounded(int a, int b) {
|
2012-02-02 11:14:43 +08:00
|
|
|
if (b < 0) return -DivRounded(a, -b);
|
2010-05-20 06:35:35 +08:00
|
|
|
return a >= 0 ? (a + b / 2) / b : (a - b / 2) / b;
|
|
|
|
}
|
|
|
|
|
2010-11-30 08:53:31 +08:00
|
|
|
// Return a double cast to int with rounding.
|
|
|
|
inline int IntCastRounded(double x) {
|
|
|
|
return x >= 0.0 ? static_cast<int>(x + 0.5) : -static_cast<int>(-x + 0.5);
|
|
|
|
}
|
|
|
|
|
2018-03-27 20:34:06 +08:00
|
|
|
// Return a float cast to int with rounding.
|
|
|
|
inline int IntCastRounded(float x) {
|
|
|
|
return x >= 0.0f ? static_cast<int>(x + 0.5f) : -static_cast<int>(-x + 0.5f);
|
|
|
|
}
|
|
|
|
|
2010-05-20 06:35:35 +08:00
|
|
|
// Reverse the order of bytes in a n byte quantity for big/little-endian switch.
|
|
|
|
inline void ReverseN(void* ptr, int num_bytes) {
|
2018-05-03 13:15:21 +08:00
|
|
|
assert(num_bytes == 1 || num_bytes == 2 || num_bytes == 4 || num_bytes == 8);
|
2017-07-15 00:30:14 +08:00
|
|
|
char* cptr = static_cast<char*>(ptr);
|
2010-05-20 06:35:35 +08:00
|
|
|
int halfsize = num_bytes / 2;
|
|
|
|
for (int i = 0; i < halfsize; ++i) {
|
|
|
|
char tmp = cptr[i];
|
|
|
|
cptr[i] = cptr[num_bytes - 1 - i];
|
|
|
|
cptr[num_bytes - 1 - i] = tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reverse the order of bytes in a 16 bit quantity for big/little-endian switch.
|
|
|
|
inline void Reverse16(void *ptr) {
|
|
|
|
ReverseN(ptr, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reverse the order of bytes in a 32 bit quantity for big/little-endian switch.
|
|
|
|
inline void Reverse32(void *ptr) {
|
|
|
|
ReverseN(ptr, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reverse the order of bytes in a 64 bit quantity for big/little-endian switch.
|
|
|
|
inline void Reverse64(void* ptr) {
|
|
|
|
ReverseN(ptr, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif // TESSERACT_CCUTIL_HELPERS_H_
|