Commit 56e87318 for tesseract

commit 56e873189891ba28d9b009445c2f65e0ae5c0496
Author: Stefan Weil <sw@weilnetz.de>
Date:   Fri Jun 5 06:07:37 2026 +0200

    Use more `constexpr`

    Assisted-by: OpenCode / BigPickle
    Signed-off-by: Stefan Weil <sw@weilnetz.de>

diff --git a/src/ccstruct/points.h b/src/ccstruct/points.h
index 3110a017..87aa48b7 100644
--- a/src/ccstruct/points.h
+++ b/src/ccstruct/points.h
@@ -38,16 +38,11 @@ class ICOORD {

 public:
   /// empty constructor
-  ICOORD() {
-    xcoord = ycoord = 0; // default zero
-  }
+  constexpr ICOORD() : xcoord(0), ycoord(0) {}
   /// constructor
   ///@param xin x value
   ///@param yin y value
-  ICOORD(TDimension xin, TDimension yin) {
-    xcoord = xin;
-    ycoord = yin;
-  }
+  constexpr ICOORD(TDimension xin, TDimension yin) : xcoord(xin), ycoord(yin) {}
   /// destructor
   ~ICOORD() = default;

@@ -113,31 +108,31 @@ public:
     return xcoord != other.xcoord || ycoord != other.ycoord;
   }
   /// rotate 90 deg anti
-  friend ICOORD operator!(const ICOORD &);
+  friend constexpr ICOORD operator!(const ICOORD &);
   /// unary minus
-  friend ICOORD operator-(const ICOORD &);
+  friend constexpr ICOORD operator-(const ICOORD &);
   /// add
-  friend ICOORD operator+(const ICOORD &, const ICOORD &);
+  friend constexpr ICOORD operator+(const ICOORD &, const ICOORD &);
   /// add
-  friend ICOORD &operator+=(ICOORD &, const ICOORD &);
+  friend constexpr ICOORD &operator+=(ICOORD &, const ICOORD &);
   /// subtract
-  friend ICOORD operator-(const ICOORD &, const ICOORD &);
+  friend constexpr ICOORD operator-(const ICOORD &, const ICOORD &);
   /// subtract
-  friend ICOORD &operator-=(ICOORD &, const ICOORD &);
+  friend constexpr ICOORD &operator-=(ICOORD &, const ICOORD &);
   /// scalar product
-  friend int32_t operator%(const ICOORD &, const ICOORD &);
+  friend constexpr int32_t operator%(const ICOORD &, const ICOORD &);
   /// cross product
-  friend int32_t operator*(const ICOORD &, const ICOORD &);
+  friend constexpr int32_t operator*(const ICOORD &, const ICOORD &);
   /// multiply
-  friend ICOORD operator*(const ICOORD &, TDimension);
+  friend constexpr ICOORD operator*(const ICOORD &, TDimension);
   /// multiply
-  friend ICOORD operator*(TDimension, const ICOORD &);
+  friend constexpr ICOORD operator*(TDimension, const ICOORD &);
   /// multiply
-  friend ICOORD &operator*=(ICOORD &, TDimension);
+  friend constexpr ICOORD &operator*=(ICOORD &, TDimension);
   /// divide
-  friend ICOORD operator/(const ICOORD &, TDimension);
+  friend constexpr ICOORD operator/(const ICOORD &, TDimension);
   /// divide
-  friend ICOORD &operator/=(ICOORD &, TDimension);
+  friend constexpr ICOORD &operator/=(ICOORD &, TDimension);
   /// rotate
   ///@param vec by vector
   void rotate(const FCOORD &vec);
@@ -197,16 +192,13 @@ public:
     xcoord = xvalue; // set coords
     ycoord = yvalue;
   }
-  FCOORD(              // make from ICOORD
-      ICOORD icoord) { // coords to set
-    xcoord = icoord.xcoord;
-    ycoord = icoord.ycoord;
-  }
+  constexpr FCOORD(              // make from ICOORD
+      ICOORD icoord) : xcoord(icoord.xcoord), ycoord(icoord.ycoord) {}

-  float x() const { // get coords
+  constexpr float x() const { // get coords
     return xcoord;
   }
-  float y() const {
+  constexpr float y() const {
     return ycoord;
   }
   /// rewrite function
@@ -277,28 +269,28 @@ public:
     return xcoord != other.xcoord || ycoord != other.ycoord;
   }
   /// rotate 90 deg anti
-  friend FCOORD operator!(const FCOORD &);
+  friend constexpr FCOORD operator!(const FCOORD &);
   /// unary minus
-  friend FCOORD operator-(const FCOORD &);
+  friend constexpr FCOORD operator-(const FCOORD &);
   /// add
-  friend FCOORD operator+(const FCOORD &, const FCOORD &);
+  friend constexpr FCOORD operator+(const FCOORD &, const FCOORD &);
   /// add
-  friend FCOORD &operator+=(FCOORD &, const FCOORD &);
+  friend constexpr FCOORD &operator+=(FCOORD &, const FCOORD &);
   /// subtract
-  friend FCOORD operator-(const FCOORD &, const FCOORD &);
+  friend constexpr FCOORD operator-(const FCOORD &, const FCOORD &);
   /// subtract
-  friend FCOORD &operator-=(FCOORD &, const FCOORD &);
+  friend constexpr FCOORD &operator-=(FCOORD &, const FCOORD &);
   /// scalar product
-  friend float operator%(const FCOORD &, const FCOORD &);
+  friend constexpr float operator%(const FCOORD &, const FCOORD &);
   /// cross product
-  friend float operator*(const FCOORD &, const FCOORD &);
+  friend constexpr float operator*(const FCOORD &, const FCOORD &);
   /// multiply
-  friend FCOORD operator*(const FCOORD &, float);
+  friend constexpr FCOORD operator*(const FCOORD &, float);
   /// multiply
-  friend FCOORD operator*(float, const FCOORD &);
+  friend constexpr FCOORD operator*(float, const FCOORD &);

   /// multiply
-  friend FCOORD &operator*=(FCOORD &, float);
+  friend constexpr FCOORD &operator*=(FCOORD &, float);
   /// divide
   friend FCOORD operator/(const FCOORD &, float);
   /// rotate
@@ -321,7 +313,7 @@ private:
  * Rotate an ICOORD 90 degrees anticlockwise.
  **********************************************************************/

-inline ICOORD operator!( // rotate 90 deg anti
+constexpr inline ICOORD operator!( // rotate 90 deg anti
     const ICOORD &src    // thing to rotate
 ) {
   ICOORD result; // output
@@ -337,7 +329,7 @@ inline ICOORD operator!( // rotate 90 deg anti
  * Unary minus of an ICOORD.
  **********************************************************************/

-inline ICOORD operator-( // unary minus
+constexpr inline ICOORD operator-( // unary minus
     const ICOORD &src    // thing to minus
 ) {
   ICOORD result; // output
@@ -353,7 +345,7 @@ inline ICOORD operator-( // unary minus
  * Add 2 ICOORDS.
  **********************************************************************/

-inline ICOORD operator+( // sum vectors
+constexpr inline ICOORD operator+( // sum vectors
     const ICOORD &op1,   // operands
     const ICOORD &op2) {
   ICOORD sum; // result
@@ -369,7 +361,7 @@ inline ICOORD operator+( // sum vectors
  * Add 2 ICOORDS.
  **********************************************************************/

-inline ICOORD &operator+=( // sum vectors
+constexpr inline ICOORD &operator+=( // sum vectors
     ICOORD &op1,           // operands
     const ICOORD &op2) {
   op1.xcoord += op2.xcoord;
@@ -383,7 +375,7 @@ inline ICOORD &operator+=( // sum vectors
  * Subtract 2 ICOORDS.
  **********************************************************************/

-inline ICOORD operator-( // subtract vectors
+constexpr inline ICOORD operator-( // subtract vectors
     const ICOORD &op1,   // operands
     const ICOORD &op2) {
   ICOORD sum; // result
@@ -399,7 +391,7 @@ inline ICOORD operator-( // subtract vectors
  * Subtract 2 ICOORDS.
  **********************************************************************/

-inline ICOORD &operator-=( // subtract vectors
+constexpr inline ICOORD &operator-=( // subtract vectors
     ICOORD &op1,           // operands
     const ICOORD &op2) {
   op1.xcoord -= op2.xcoord;
@@ -413,7 +405,7 @@ inline ICOORD &operator-=( // subtract vectors
  * Scalar product of 2 ICOORDS.
  **********************************************************************/

-inline int32_t operator%( // scalar product
+constexpr inline int32_t operator%( // scalar product
     const ICOORD &op1,    // operands
     const ICOORD &op2) {
   return op1.xcoord * op2.xcoord + op1.ycoord * op2.ycoord;
@@ -425,7 +417,7 @@ inline int32_t operator%( // scalar product
  * Cross product of 2 ICOORDS.
  **********************************************************************/

-inline int32_t operator*( // cross product
+constexpr inline int32_t operator*( // cross product
     const ICOORD &op1,    // operands
     const ICOORD &op2) {
   return op1.xcoord * op2.ycoord - op1.ycoord * op2.xcoord;
@@ -437,7 +429,7 @@ inline int32_t operator*( // cross product
  * Scalar multiply of an ICOORD.
  **********************************************************************/

-inline ICOORD operator*( // scalar multiply
+constexpr inline ICOORD operator*( // scalar multiply
     const ICOORD &op1,   // operands
     TDimension scale) {
   ICOORD result; // output
@@ -447,7 +439,7 @@ inline ICOORD operator*( // scalar multiply
   return result;
 }

-inline ICOORD operator*( // scalar multiply
+constexpr inline ICOORD operator*( // scalar multiply
     TDimension scale,
     const ICOORD &op1 // operands
 ) {
@@ -464,7 +456,7 @@ inline ICOORD operator*( // scalar multiply
  * Scalar multiply of an ICOORD.
  **********************************************************************/

-inline ICOORD &operator*=( // scalar multiply
+constexpr inline ICOORD &operator*=( // scalar multiply
     ICOORD &op1,           // operands
     TDimension scale) {
   op1.xcoord *= scale;
@@ -478,7 +470,7 @@ inline ICOORD &operator*=( // scalar multiply
  * Scalar divide of an ICOORD.
  **********************************************************************/

-inline ICOORD operator/( // scalar divide
+constexpr inline ICOORD operator/( // scalar divide
     const ICOORD &op1,   // operands
     TDimension scale) {
   ICOORD result; // output
@@ -494,7 +486,7 @@ inline ICOORD operator/( // scalar divide
  * Scalar divide of an ICOORD.
  **********************************************************************/

-inline ICOORD &operator/=( // scalar divide
+constexpr inline ICOORD &operator/=( // scalar divide
     ICOORD &op1,           // operands
     TDimension scale) {
   op1.xcoord /= scale;
@@ -521,7 +513,7 @@ inline void ICOORD::rotate( // rotate by vector
  * Rotate an FCOORD 90 degrees anticlockwise.
  **********************************************************************/

-inline FCOORD operator!( // rotate 90 deg anti
+constexpr inline FCOORD operator!( // rotate 90 deg anti
     const FCOORD &src    // thing to rotate
 ) {
   FCOORD result; // output
@@ -537,7 +529,7 @@ inline FCOORD operator!( // rotate 90 deg anti
  * Unary minus of an FCOORD.
  **********************************************************************/

-inline FCOORD operator-( // unary minus
+constexpr inline FCOORD operator-( // unary minus
     const FCOORD &src    // thing to minus
 ) {
   FCOORD result; // output
@@ -553,7 +545,7 @@ inline FCOORD operator-( // unary minus
  * Add 2 FCOORDS.
  **********************************************************************/

-inline FCOORD operator+( // sum vectors
+constexpr inline FCOORD operator+( // sum vectors
     const FCOORD &op1,   // operands
     const FCOORD &op2) {
   FCOORD sum; // result
@@ -569,7 +561,7 @@ inline FCOORD operator+( // sum vectors
  * Add 2 FCOORDS.
  **********************************************************************/

-inline FCOORD &operator+=( // sum vectors
+constexpr inline FCOORD &operator+=( // sum vectors
     FCOORD &op1,           // operands
     const FCOORD &op2) {
   op1.xcoord += op2.xcoord;
@@ -583,7 +575,7 @@ inline FCOORD &operator+=( // sum vectors
  * Subtract 2 FCOORDS.
  **********************************************************************/

-inline FCOORD operator-( // subtract vectors
+constexpr inline FCOORD operator-( // subtract vectors
     const FCOORD &op1,   // operands
     const FCOORD &op2) {
   FCOORD sum; // result
@@ -599,7 +591,7 @@ inline FCOORD operator-( // subtract vectors
  * Subtract 2 FCOORDS.
  **********************************************************************/

-inline FCOORD &operator-=( // subtract vectors
+constexpr inline FCOORD &operator-=( // subtract vectors
     FCOORD &op1,           // operands
     const FCOORD &op2) {
   op1.xcoord -= op2.xcoord;
@@ -613,7 +605,7 @@ inline FCOORD &operator-=( // subtract vectors
  * Scalar product of 2 FCOORDS.
  **********************************************************************/

-inline float operator%( // scalar product
+constexpr inline float operator%( // scalar product
     const FCOORD &op1,  // operands
     const FCOORD &op2) {
   return op1.xcoord * op2.xcoord + op1.ycoord * op2.ycoord;
@@ -625,7 +617,7 @@ inline float operator%( // scalar product
  * Cross product of 2 FCOORDS.
  **********************************************************************/

-inline float operator*( // cross product
+constexpr inline float operator*( // cross product
     const FCOORD &op1,  // operands
     const FCOORD &op2) {
   return op1.xcoord * op2.ycoord - op1.ycoord * op2.xcoord;
@@ -637,7 +629,7 @@ inline float operator*( // cross product
  * Scalar multiply of an FCOORD.
  **********************************************************************/

-inline FCOORD operator*( // scalar multiply
+constexpr inline FCOORD operator*( // scalar multiply
     const FCOORD &op1,   // operands
     float scale) {
   FCOORD result; // output
@@ -647,7 +639,7 @@ inline FCOORD operator*( // scalar multiply
   return result;
 }

-inline FCOORD operator*( // scalar multiply
+constexpr inline FCOORD operator*( // scalar multiply
     float scale,
     const FCOORD &op1 // operands
 ) {
@@ -664,7 +656,7 @@ inline FCOORD operator*( // scalar multiply
  * Scalar multiply of an FCOORD.
  **********************************************************************/

-inline FCOORD &operator*=( // scalar multiply
+constexpr inline FCOORD &operator*=( // scalar multiply
     FCOORD &op1,           // operands
     float scale) {
   op1.xcoord *= scale;
diff --git a/src/ccstruct/rect.h b/src/ccstruct/rect.h
index b6bb7fbf..6ca80ac3 100644
--- a/src/ccstruct/rect.h
+++ b/src/ccstruct/rect.h
@@ -57,65 +57,65 @@ public:
   TBOX( // box around FCOORD
       const FCOORD pt);

-  bool null_box() const { // Is box null
+  constexpr bool null_box() const { // Is box null
     return ((left() >= right()) || (top() <= bottom()));
   }

-  bool operator==(const TBOX &other) const {
+  constexpr bool operator==(const TBOX &other) const {
     return bot_left == other.bot_left && top_right == other.top_right;
   }

-  TDimension top() const { // coord of top
+  constexpr TDimension top() const { // coord of top
     return top_right.y();
   }
   void set_top(int y) {
     top_right.set_y(y);
   }

-  TDimension bottom() const { // coord of bottom
+  constexpr TDimension bottom() const { // coord of bottom
     return bot_left.y();
   }
   void set_bottom(int y) {
     bot_left.set_y(y);
   }

-  TDimension left() const { // coord of left
+  constexpr TDimension left() const { // coord of left
     return bot_left.x();
   }
   void set_left(int x) {
     bot_left.set_x(x);
   }

-  TDimension right() const { // coord of right
+  constexpr TDimension right() const { // coord of right
     return top_right.x();
   }
   void set_right(int x) {
     top_right.set_x(x);
   }
-  int x_middle() const {
+  constexpr int x_middle() const {
     return (bot_left.x() + top_right.x()) / 2;
   }
-  int y_middle() const {
+  constexpr int y_middle() const {
     return (bot_left.y() + top_right.y()) / 2;
   }

-  const ICOORD &botleft() const { // access function
+  constexpr const ICOORD &botleft() const { // access function
     return bot_left;
   }

-  ICOORD botright() const { // ~ access function
+  constexpr ICOORD botright() const { // ~ access function
     return ICOORD(top_right.x(), bot_left.y());
   }

-  ICOORD topleft() const { // ~ access function
+  constexpr ICOORD topleft() const { // ~ access function
     return ICOORD(bot_left.x(), top_right.y());
   }

-  const ICOORD &topright() const { // access function
+  constexpr const ICOORD &topright() const { // access function
     return top_right;
   }

-  TDimension height() const { // how high is it?
+  constexpr TDimension height() const { // how high is it?
     if (!null_box()) {
       return top_right.y() - bot_left.y();
     } else {
@@ -123,7 +123,7 @@ public:
     }
   }

-  TDimension width() const { // how wide is it?
+  constexpr TDimension width() const { // how wide is it?
     if (!null_box()) {
       return top_right.x() - bot_left.x();
     } else {
@@ -131,7 +131,7 @@ public:
     }
   }

-  int32_t area() const { // what is the area?
+  constexpr int32_t area() const { // what is the area?
     if (!null_box()) {
       return width() * height();
     } else {
@@ -217,54 +217,54 @@ public:
   // original content is contained within, but also slightly enlarges the box.
   void rotate_large(const FCOORD &vec);

-  bool contains( // is pt inside box
+  constexpr bool contains( // is pt inside box
       const FCOORD pt) const;

-  bool contains( // is box inside box
+  constexpr bool contains( // is box inside box
       const TBOX &box) const;

-  bool overlap( // do boxes overlap
+  constexpr bool overlap( // do boxes overlap
       const TBOX &box) const;

-  bool major_overlap( // do boxes overlap more than half
+  constexpr bool major_overlap( // do boxes overlap more than half
       const TBOX &box) const;

   // Do boxes overlap on x axis.
-  bool x_overlap(const TBOX &box) const;
+  constexpr bool x_overlap(const TBOX &box) const;

   // Return the horizontal gap between the boxes. If the boxes
   // overlap horizontally then the return value is negative, indicating
   // the amount of the overlap.
-  int x_gap(const TBOX &box) const {
+  constexpr int x_gap(const TBOX &box) const {
     return std::max(bot_left.x(), box.bot_left.x()) - std::min(top_right.x(), box.top_right.x());
   }

   // Return the vertical gap between the boxes. If the boxes
   // overlap vertically then the return value is negative, indicating
   // the amount of the overlap.
-  int y_gap(const TBOX &box) const {
+  constexpr int y_gap(const TBOX &box) const {
     return std::max(bot_left.y(), box.bot_left.y()) - std::min(top_right.y(), box.top_right.y());
   }

   // Do boxes overlap on x axis by more than
   // half of the width of the narrower box.
-  bool major_x_overlap(const TBOX &box) const;
+  constexpr bool major_x_overlap(const TBOX &box) const;

   // Do boxes overlap on y axis.
-  bool y_overlap(const TBOX &box) const;
+  constexpr bool y_overlap(const TBOX &box) const;

   // Do boxes overlap on y axis by more than
   // half of the height of the shorter box.
-  bool major_y_overlap(const TBOX &box) const;
+  constexpr bool major_y_overlap(const TBOX &box) const;

   // fraction of current box's area covered by other
   double overlap_fraction(const TBOX &box) const;

   // fraction of the current box's projected area covered by the other's
-  double x_overlap_fraction(const TBOX &box) const;
+  constexpr double x_overlap_fraction(const TBOX &box) const;

   // fraction of the current box's projected area covered by the other's
-  double y_overlap_fraction(const TBOX &box) const;
+  constexpr double y_overlap_fraction(const TBOX &box) const;

   // Returns true if the boxes are almost equal on x axis.
   bool x_almost_equal(const TBOX &box, int tolerance) const;
@@ -341,7 +341,7 @@ inline TBOX::TBOX(  // constructor
  *
  **********************************************************************/

-inline bool TBOX::contains(const FCOORD pt) const {
+inline constexpr bool TBOX::contains(const FCOORD pt) const {
   return ((pt.x() >= bot_left.x()) && (pt.x() <= top_right.x()) && (pt.y() >= bot_left.y()) &&
           (pt.y() <= top_right.y()));
 }
@@ -351,7 +351,7 @@ inline bool TBOX::contains(const FCOORD pt) const {
  *
  **********************************************************************/

-inline bool TBOX::contains(const TBOX &box) const {
+inline constexpr bool TBOX::contains(const TBOX &box) const {
   return (contains(box.bot_left) && contains(box.top_right));
 }

@@ -360,7 +360,7 @@ inline bool TBOX::contains(const TBOX &box) const {
  *
  **********************************************************************/

-inline bool TBOX::overlap( // do boxes overlap
+inline constexpr bool TBOX::overlap( // do boxes overlap
     const TBOX &box) const {
   return ((box.bot_left.x() <= top_right.x()) && (box.top_right.x() >= bot_left.x()) &&
           (box.bot_left.y() <= top_right.y()) && (box.top_right.y() >= bot_left.y()));
@@ -371,7 +371,7 @@ inline bool TBOX::overlap( // do boxes overlap
  *
  **********************************************************************/

-inline bool TBOX::major_overlap( // Do boxes overlap more that half.
+inline constexpr bool TBOX::major_overlap( // Do boxes overlap more that half.
     const TBOX &box) const {
   int overlap = std::min(box.top_right.x(), top_right.x());
   overlap -= std::max(box.bot_left.x(), bot_left.x());
@@ -406,7 +406,7 @@ inline double TBOX::overlap_fraction(const TBOX &box) const {
  *
  **********************************************************************/

-inline bool TBOX::x_overlap(const TBOX &box) const {
+inline constexpr bool TBOX::x_overlap(const TBOX &box) const {
   return ((box.bot_left.x() <= top_right.x()) && (box.top_right.x() >= bot_left.x()));
 }

@@ -416,7 +416,7 @@ inline bool TBOX::x_overlap(const TBOX &box) const {
  *
  **********************************************************************/

-inline bool TBOX::major_x_overlap(const TBOX &box) const {
+inline constexpr bool TBOX::major_x_overlap(const TBOX &box) const {
   TDimension overlap = box.width();
   if (this->left() > box.left()) {
     overlap -= this->left() - box.left();
@@ -432,7 +432,7 @@ inline bool TBOX::major_x_overlap(const TBOX &box) const {
  *
  **********************************************************************/

-inline bool TBOX::y_overlap(const TBOX &box) const {
+inline constexpr bool TBOX::y_overlap(const TBOX &box) const {
   return ((box.bot_left.y() <= top_right.y()) && (box.top_right.y() >= bot_left.y()));
 }

@@ -442,7 +442,7 @@ inline bool TBOX::y_overlap(const TBOX &box) const {
  *
  **********************************************************************/

-inline bool TBOX::major_y_overlap(const TBOX &box) const {
+inline constexpr bool TBOX::major_y_overlap(const TBOX &box) const {
   TDimension overlap = box.height();
   if (this->bottom() > box.bottom()) {
     overlap -= this->bottom() - box.bottom();
@@ -460,7 +460,7 @@ inline bool TBOX::major_y_overlap(const TBOX &box) const {
  *
  **********************************************************************/

-inline double TBOX::x_overlap_fraction(const TBOX &other) const {
+inline constexpr double TBOX::x_overlap_fraction(const TBOX &other) const {
   int low = std::max(left(), other.left());
   int high = std::min(right(), other.right());
   int width = right() - left();
@@ -483,7 +483,7 @@ inline double TBOX::x_overlap_fraction(const TBOX &other) const {
  *
  **********************************************************************/

-inline double TBOX::y_overlap_fraction(const TBOX &other) const {
+inline constexpr double TBOX::y_overlap_fraction(const TBOX &other) const {
   int low = std::max(bottom(), other.bottom());
   int high = std::min(top(), other.top());
   int height = top() - bottom();
diff --git a/src/classify/cluster.cpp b/src/classify/cluster.cpp
index b926f7e4..ed5a8b5d 100644
--- a/src/classify/cluster.cpp
+++ b/src/classify/cluster.cpp
@@ -32,13 +32,13 @@

 namespace tesseract {

-#define HOTELLING 1  // If true use Hotelling's test to decide where to split.
-#define FTABLE_X 10  // Size of FTable.
-#define FTABLE_Y 100 // Size of FTable.
+constexpr int HOTELLING = 1;  // If true use Hotelling's test to decide where to split.
+constexpr int FTABLE_X = 10;  // Size of FTable.
+constexpr int FTABLE_Y = 100; // Size of FTable.

 // Table of values approximating the cumulative F-distribution for a confidence
 // of 1%.
-const double FTable[FTABLE_Y][FTABLE_X] = {
+constexpr double FTable[FTABLE_Y][FTABLE_X] = {
     {
         4052.19,
         4999.52,
@@ -1233,7 +1233,7 @@ const double FTable[FTABLE_Y][FTABLE_X] = {
   dimension of any feature. Since most features are calculated from numbers
   with a precision no better than 1 in 128, the variance should never be
   less than the square of this number for parameters whose range is 1. */
-#define MINVARIANCE 0.0004
+constexpr double MINVARIANCE = 0.0004;

 /** define the absolute minimum number of samples which must be present in
   order to accurately test hypotheses about underlying probability
@@ -1241,9 +1241,9 @@ const double FTable[FTABLE_Y][FTABLE_X] = {
   before a statistical analysis is attempted; this number should be
   equal to MINSAMPLES but can be set to a lower number for early testing
   when very few samples are available. */
-#define MINSAMPLESPERBUCKET 5
-#define MINSAMPLES (MINBUCKETS * MINSAMPLESPERBUCKET)
-#define MINSAMPLESNEEDED 1
+constexpr int MINSAMPLESPERBUCKET = 5;
+constexpr int MINSAMPLES = MINBUCKETS * MINSAMPLESPERBUCKET;
+constexpr int MINSAMPLESNEEDED = 1;

 /** define the size of the table which maps normalized samples to
   histogram buckets.  Also define the number of standard deviations
@@ -1251,8 +1251,8 @@ const double FTable[FTABLE_Y][FTABLE_X] = {
   The mapping table will be defined in such a way that it covers
   the specified number of standard deviations on either side of
   the mean.  BUCKETTABLESIZE should always be even. */
-#define BUCKETTABLESIZE 1024
-#define NORMALEXTENT 3.0
+constexpr int BUCKETTABLESIZE = 1024;
+constexpr double NORMALEXTENT = 3.0;

 struct TEMPCLUSTER {
   CLUSTER *Cluster;
@@ -1311,9 +1311,18 @@ struct ClusteringContext {
 using DENSITYFUNC = double (*)(int32_t);
 using SOLVEFUNC = double (*)(CHISTRUCT *, double);

-#define Odd(N) ((N) % 2)
-#define Mirror(N, R) ((R) - (N)-1)
-#define Abs(N) (((N) < 0) ? (-(N)) : (N))
+template <typename T>
+inline constexpr bool Odd(T N) {
+  return (N % 2) != 0;
+}
+template <typename T>
+inline constexpr T Mirror(T N, T R) {
+  return R - N - 1;
+}
+template <typename T>
+inline constexpr T Abs(T N) {
+  return N < 0 ? -N : N;
+}

 //--------------Global Data Definitions and Declarations----------------------
 /** the following variables describe a discrete normal distribution
@@ -1323,22 +1332,22 @@ using SOLVEFUNC = double (*)(CHISTRUCT *, double);
   discrete range of x.  x=0 is mapped to -NORMALEXTENT standard
   deviations and x=BUCKETTABLESIZE is mapped to
   +NORMALEXTENT standard deviations. */
-#define SqrtOf2Pi 2.506628275
-static const double kNormalStdDev = BUCKETTABLESIZE / (2.0 * NORMALEXTENT);
-static const double kNormalVariance =
+constexpr double SqrtOf2Pi = 2.506628275;
+static constexpr double kNormalStdDev = BUCKETTABLESIZE / (2.0 * NORMALEXTENT);
+static constexpr double kNormalVariance =
     (BUCKETTABLESIZE * BUCKETTABLESIZE) / (4.0 * NORMALEXTENT * NORMALEXTENT);
-static const double kNormalMagnitude = (2.0 * NORMALEXTENT) / (SqrtOf2Pi * BUCKETTABLESIZE);
-static const double kNormalMean = BUCKETTABLESIZE / 2;
+static constexpr double kNormalMagnitude = (2.0 * NORMALEXTENT) / (SqrtOf2Pi * BUCKETTABLESIZE);
+static constexpr double kNormalMean = BUCKETTABLESIZE / 2;

 /** define lookup tables used to compute the number of histogram buckets
   that should be used for a given number of samples. */
-#define LOOKUPTABLESIZE 8
-#define MAXDEGREESOFFREEDOM MAXBUCKETS
+constexpr int LOOKUPTABLESIZE = 8;
+constexpr int MAXDEGREESOFFREEDOM = MAXBUCKETS;

-static const uint32_t kCountTable[LOOKUPTABLESIZE] = {MINSAMPLES, 200,  400, 600, 800,
-                                                      1000,       1500, 2000}; // number of samples
+static constexpr uint32_t kCountTable[LOOKUPTABLESIZE] = {MINSAMPLES, 200,  400, 600, 800,
+                                                          1000,       1500, 2000}; // number of samples

-static const uint16_t kBucketsTable[LOOKUPTABLESIZE] = {
+static constexpr uint16_t kBucketsTable[LOOKUPTABLESIZE] = {
     MINBUCKETS, 16, 20, 24, 27, 30, 35, MAXBUCKETS}; // number of buckets

 /*-------------------------------------------------------------------------
@@ -1795,10 +1804,9 @@ static void MakePotentialClusters(ClusteringContext *context, CLUSTER *Cluster,
  * @param Distance  ptr to variable to report distance found
  * @return  Pointer to the nearest neighbor of Cluster, or nullptr
  */
-static CLUSTER *FindNearestNeighbor(KDTREE *Tree, CLUSTER *Cluster, float *Distance)
-#define MAXNEIGHBORS 2
-#define MAXDISTANCE FLT_MAX
-{
+static CLUSTER *FindNearestNeighbor(KDTREE *Tree, CLUSTER *Cluster, float *Distance) {
+  constexpr int MAXNEIGHBORS = 2;
+  constexpr float MAXDISTANCE = FLT_MAX;
   CLUSTER *Neighbor[MAXNEIGHBORS];
   float Dist[MAXNEIGHBORS];
   int NumberOfNeighbors;
@@ -2758,10 +2766,9 @@ static uint16_t OptimumNumberOfBuckets(uint32_t SampleCount) {
  * @param Alpha probability of right tail
  * @return Desired chi-squared value
  */
-static double ComputeChiSquared(uint16_t DegreesOfFreedom, double Alpha)
-#define CHIACCURACY 0.01
-#define MINALPHA (1e-200)
-{
+static double ComputeChiSquared(uint16_t DegreesOfFreedom, double Alpha) {
+  constexpr double CHIACCURACY = 0.01;
+  constexpr double MINALPHA = 1e-200;
   static LIST ChiWith[MAXDEGREESOFFREEDOM + 1];

   // limit the minimum alpha that can be used - if alpha is too small
@@ -3106,10 +3113,9 @@ static int AlphaMatch(void *arg1,   // CHISTRUCT *ChiStruct,
  * @param Accuracy  maximum allowed error
  * @return Solution of function (x for which f(x) = 0).
  */
-static double Solve(SOLVEFUNC Function, void *FunctionParams, double InitialGuess, double Accuracy)
-#define INITIALDELTA 0.1
-#define DELTARATIO 0.1
-{
+static double Solve(SOLVEFUNC Function, void *FunctionParams, double InitialGuess, double Accuracy) {
+  constexpr double INITIALDELTA = 0.1;
+  constexpr double DELTARATIO = 0.1;
   double x;
   double f;
   double Slope;
@@ -3212,9 +3218,8 @@ static double ChiArea(CHISTRUCT *ChiParams, double x) {
  *        more than 1 feature in the cluster
  * @return true if the cluster should be split, false otherwise.
  */
-static bool MultipleCharSamples(CLUSTERER *Clusterer, CLUSTER *Cluster, float MaxIllegal)
-#define ILLEGAL_CHAR 2
-{
+static bool MultipleCharSamples(CLUSTERER *Clusterer, CLUSTER *Cluster, float MaxIllegal) {
+  constexpr int ILLEGAL_CHAR = 2;
   static std::vector<uint8_t> CharFlags;
   LIST SearchState;
   SAMPLE *Sample;
diff --git a/src/classify/cluster.h b/src/classify/cluster.h
index 33f0afda..3caf7474 100644
--- a/src/classify/cluster.h
+++ b/src/classify/cluster.h
@@ -25,8 +25,8 @@ namespace tesseract {

 struct BUCKETS;

-#define MINBUCKETS 5
-#define MAXBUCKETS 39
+constexpr int MINBUCKETS = 5;
+constexpr int MAXBUCKETS = 39;

 /*----------------------------------------------------------------------
           Types
diff --git a/src/classify/fpoint.h b/src/classify/fpoint.h
index 69f13d0d..ccca05f1 100644
--- a/src/classify/fpoint.h
+++ b/src/classify/fpoint.h
@@ -34,13 +34,22 @@ using FVECTOR = FPOINT;
 /**----------------------------------------------------------------------------
             Macros
 ----------------------------------------------------------------------------**/
-/* macros for computing miscellaneous functions of 2 points */
-#define XDelta(A, B) ((B).x - (A).x)
-#define YDelta(A, B) ((B).y - (A).y)
-#define SlopeFrom(A, B) (YDelta(A, B) / XDelta(A, B))
-#define AngleFrom(A, B) (atan2(static_cast<double>(YDelta(A, B)), static_cast<double>(XDelta(A, B))))
-
-#define XIntersectionOf(A, B, X) (SlopeFrom(A, B) * ((X)-A.x) + A.y)
+/* functions for computing miscellaneous properties of 2 points */
+inline constexpr float XDelta(const FPOINT &A, const FPOINT &B) {
+  return B.x - A.x;
+}
+inline constexpr float YDelta(const FPOINT &A, const FPOINT &B) {
+  return B.y - A.y;
+}
+inline constexpr float SlopeFrom(const FPOINT &A, const FPOINT &B) {
+  return YDelta(A, B) / XDelta(A, B);
+}
+inline double AngleFrom(const FPOINT &A, const FPOINT &B) {
+  return std::atan2(static_cast<double>(YDelta(A, B)), static_cast<double>(XDelta(A, B)));
+}
+inline constexpr float XIntersectionOf(const FPOINT &A, const FPOINT &B, float X) {
+  return SlopeFrom(A, B) * (X - A.x) + A.y;
+}

 /*-------------------------------------------------------------------------
         Public Function Prototypes
diff --git a/src/classify/intmatcher.cpp b/src/classify/intmatcher.cpp
index d32aee57..5e5d1a0e 100644
--- a/src/classify/intmatcher.cpp
+++ b/src/classify/intmatcher.cpp
@@ -38,11 +38,6 @@ namespace tesseract {
 /*----------------------------------------------------------------------------
                     Global Data Definitions and Declarations
 ----------------------------------------------------------------------------*/
-// Parameters of the sigmoid used to convert similarity to evidence in the
-// similarity_evidence_table_ that is used to convert distance metric to an
-// 8 bit evidence value in the secondary matcher. (See IntMatcher::Init).
-const float IntegerMatcher::kSEExponentialMultiplier = 0.0f;
-const float IntegerMatcher::kSimilarityCenter = 0.0075f;

 static const uint8_t offset_table[] = {
     255, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,
@@ -668,8 +663,8 @@ int IntegerMatcher::FindBadFeatures(INT_CLASS_STRUCT *ClassTemplate, BIT_VECTOR
 IntegerMatcher::IntegerMatcher(tesseract::IntParam *classify_debug_level)
     : classify_debug_level_(classify_debug_level) {
   /* Initialize table for evidence to similarity lookup */
-  for (int i = 0; i < SE_TABLE_SIZE; i++) {
-    uint32_t IntSimilarity = i << (27 - SE_TABLE_BITS);
+  for (int i = 0; i < kSETableSize; i++) {
+    uint32_t IntSimilarity = i << (27 - kSETableBits);
     double Similarity = (static_cast<double>(IntSimilarity)) / 65536.0 / 65536.0;
     double evidence = Similarity / kSimilarityCenter;
     evidence = 255.0 / (evidence * evidence + 1.0);
@@ -677,17 +672,17 @@ IntegerMatcher::IntegerMatcher(tesseract::IntParam *classify_debug_level)
     if (kSEExponentialMultiplier > 0.0) {
       double scale =
           1.0 - std::exp(-kSEExponentialMultiplier) *
-                    exp(kSEExponentialMultiplier * (static_cast<double>(i) / SE_TABLE_SIZE));
+                    exp(kSEExponentialMultiplier * (static_cast<double>(i) / kSETableSize));
       evidence *= ClipToRange(scale, 0.0, 1.0);
     }

     similarity_evidence_table_[i] = static_cast<uint8_t>(evidence + 0.5);
   }

-  /* Initialize evidence computation variables */
+  // Initialize evidence computation variables
   evidence_table_mask_ = ((1 << kEvidenceTableBits) - 1) << (9 - kEvidenceTableBits);
   mult_trunc_shift_bits_ = (14 - kIntEvidenceTruncBits);
-  table_trunc_shift_bits_ = (27 - SE_TABLE_BITS - (mult_trunc_shift_bits_ << 1));
+  table_trunc_shift_bits_ = (27 - kSETableBits - (mult_trunc_shift_bits_ << 1));
   evidence_mult_mask_ = ((1 << kIntEvidenceTruncBits) - 1);
 }

diff --git a/src/classify/intmatcher.h b/src/classify/intmatcher.h
index 167e87a5..d7dd0c1f 100644
--- a/src/classify/intmatcher.h
+++ b/src/classify/intmatcher.h
@@ -43,8 +43,8 @@ struct CP_RESULT_STRUCT {
           Public Function Prototypes
 ----------------------------------------------------------------------------**/

-#define SE_TABLE_BITS 9
-#define SE_TABLE_SIZE 512
+constexpr int kSETableBits = 9;
+constexpr int kSETableSize = 512;

 struct ScratchEvidence {
   uint8_t feature_evidence_[MAX_NUM_CONFIGS];
@@ -60,15 +60,20 @@ struct ScratchEvidence {
 class IntegerMatcher {
 public:
   // Integer Matcher Theta Fudge (0-255).
-  static const int kIntThetaFudge = 128;
+  static constexpr int kIntThetaFudge = 128;
   // Bits in Similarity to Evidence Lookup (8-9).
-  static const int kEvidenceTableBits = 9;
+  static constexpr int kEvidenceTableBits = 9;
   // Integer Evidence Truncation Bits (8-14).
-  static const int kIntEvidenceTruncBits = 14;
+  static constexpr int kIntEvidenceTruncBits = 14;
+
+  // Parameters of the sigmoid used to convert similarity to evidence in the
+  // similarity_evidence_table_ that is used to convert distance metric to an
+  // 8 bit evidence value in the secondary matcher. (See IntMatcher::Init).
+
   // Similarity to Evidence Table Exponential Multiplier.
-  static const float kSEExponentialMultiplier;
+  static constexpr float kSEExponentialMultiplier = 0.0f;
   // Center of Similarity Curve.
-  static const float kSimilarityCenter;
+  static constexpr float kSimilarityCenter = 0.0075f;

   IntegerMatcher(tesseract::IntParam *classify_debug_level);

@@ -112,7 +117,7 @@ private:

 private:
   tesseract::IntParam *classify_debug_level_;
-  uint8_t similarity_evidence_table_[SE_TABLE_SIZE];
+  uint8_t similarity_evidence_table_[kSETableSize];
   uint32_t evidence_table_mask_;
   uint32_t mult_trunc_shift_bits_;
   uint32_t table_trunc_shift_bits_;
diff --git a/src/classify/intproto.h b/src/classify/intproto.h
index 35a1c75e..a90e43cb 100644
--- a/src/classify/intproto.h
+++ b/src/classify/intproto.h
@@ -32,37 +32,37 @@ namespace tesseract {
 class FCOORD;

 /* define order of params in pruners */
-#define PRUNER_X 0
-#define PRUNER_Y 1
-#define PRUNER_ANGLE 2
+constexpr int PRUNER_X = 0;
+constexpr int PRUNER_Y = 1;
+constexpr int PRUNER_ANGLE = 2;

 /* definition of coordinate system offsets for each table parameter */
-#define ANGLE_SHIFT (0.0)
-#define X_SHIFT (0.5)
-#define Y_SHIFT (0.5)
+constexpr double ANGLE_SHIFT = 0.0;
+constexpr double X_SHIFT = 0.5;
+constexpr double Y_SHIFT = 0.5;

-#define MAX_PROTO_INDEX 24
-#define BITS_PER_WERD static_cast<int>(8 * sizeof(uint32_t))
+constexpr int MAX_PROTO_INDEX = 24;
+constexpr int BITS_PER_WERD = static_cast<int>(8 * sizeof(uint32_t));
 /* Script detection: increase this number to 128 */
-#define MAX_NUM_CONFIGS 64
-#define MAX_NUM_PROTOS 512
-#define PROTOS_PER_PROTO_SET 64
-#define MAX_NUM_PROTO_SETS (MAX_NUM_PROTOS / PROTOS_PER_PROTO_SET)
-#define NUM_PP_PARAMS 3
-#define NUM_PP_BUCKETS 64
-#define NUM_CP_BUCKETS 24
-#define CLASSES_PER_CP 32
-#define NUM_BITS_PER_CLASS 2
-#define CLASS_PRUNER_CLASS_MASK (~(~0u << NUM_BITS_PER_CLASS))
-#define CLASSES_PER_CP_WERD (CLASSES_PER_CP / NUM_BITS_PER_CLASS)
-#define PROTOS_PER_PP_WERD BITS_PER_WERD
-#define BITS_PER_CP_VECTOR (CLASSES_PER_CP * NUM_BITS_PER_CLASS)
-#define MAX_NUM_CLASS_PRUNERS ((MAX_NUM_CLASSES + CLASSES_PER_CP - 1) / CLASSES_PER_CP)
-#define WERDS_PER_CP_VECTOR (BITS_PER_CP_VECTOR / BITS_PER_WERD)
-#define WERDS_PER_PP_VECTOR ((PROTOS_PER_PROTO_SET + BITS_PER_WERD - 1) / BITS_PER_WERD)
-#define WERDS_PER_PP (NUM_PP_PARAMS * NUM_PP_BUCKETS * WERDS_PER_PP_VECTOR)
-#define WERDS_PER_CP (NUM_CP_BUCKETS * NUM_CP_BUCKETS * NUM_CP_BUCKETS * WERDS_PER_CP_VECTOR)
-#define WERDS_PER_CONFIG_VEC ((MAX_NUM_CONFIGS + BITS_PER_WERD - 1) / BITS_PER_WERD)
+constexpr int MAX_NUM_CONFIGS = 64;
+constexpr int MAX_NUM_PROTOS = 512;
+constexpr int PROTOS_PER_PROTO_SET = 64;
+constexpr int MAX_NUM_PROTO_SETS = MAX_NUM_PROTOS / PROTOS_PER_PROTO_SET;
+constexpr int NUM_PP_PARAMS = 3;
+constexpr int NUM_PP_BUCKETS = 64;
+constexpr int NUM_CP_BUCKETS = 24;
+constexpr int CLASSES_PER_CP = 32;
+constexpr int NUM_BITS_PER_CLASS = 2;
+constexpr uint32_t CLASS_PRUNER_CLASS_MASK = ~(~0u << NUM_BITS_PER_CLASS);
+constexpr int CLASSES_PER_CP_WERD = CLASSES_PER_CP / NUM_BITS_PER_CLASS;
+constexpr int PROTOS_PER_PP_WERD = BITS_PER_WERD;
+constexpr int BITS_PER_CP_VECTOR = CLASSES_PER_CP * NUM_BITS_PER_CLASS;
+constexpr int MAX_NUM_CLASS_PRUNERS = (MAX_NUM_CLASSES + CLASSES_PER_CP - 1) / CLASSES_PER_CP;
+constexpr int WERDS_PER_CP_VECTOR = BITS_PER_CP_VECTOR / BITS_PER_WERD;
+constexpr int WERDS_PER_PP_VECTOR = (PROTOS_PER_PROTO_SET + BITS_PER_WERD - 1) / BITS_PER_WERD;
+constexpr int WERDS_PER_PP = NUM_PP_PARAMS * NUM_PP_BUCKETS * WERDS_PER_PP_VECTOR;
+constexpr int WERDS_PER_CP = NUM_CP_BUCKETS * NUM_CP_BUCKETS * NUM_CP_BUCKETS * WERDS_PER_CP_VECTOR;
+constexpr int WERDS_PER_CONFIG_VEC = (MAX_NUM_CONFIGS + BITS_PER_WERD - 1) / BITS_PER_WERD;

 /* The first 3 dimensions of the CLASS_PRUNER_STRUCT are the
  * 3 axes of the quantized feature space.
@@ -113,8 +113,8 @@ struct TESS_API INT_TEMPLATES_STRUCT {
 };

 /* definitions of integer features*/
-#define MAX_NUM_INT_FEATURES 512
-#define INT_CHAR_NORM_RANGE 256
+constexpr int MAX_NUM_INT_FEATURES = 512;
+constexpr int INT_CHAR_NORM_RANGE = 256;

 struct INT_FEATURE_STRUCT {
   INT_FEATURE_STRUCT() : X(0), Y(0), Theta(0), CP_misses(0) {}
@@ -142,40 +142,46 @@ enum IntmatcherDebugAction { IDA_ADAPTIVE, IDA_STATIC, IDA_SHAPE_INDEX, IDA_BOTH
             Macros
 ----------------------------------------------------------------------------**/

-#define MaxNumIntProtosIn(C) (C->NumProtoSets * PROTOS_PER_PROTO_SET)
-#define SetForProto(P) (P / PROTOS_PER_PROTO_SET)
-#define IndexForProto(P) (P % PROTOS_PER_PROTO_SET)
-#define ProtoForProtoId(C, P) (&((C->ProtoSets[SetForProto(P)])->Protos[IndexForProto(P)]))
-#define PPrunerWordIndexFor(I) (((I) % PROTOS_PER_PROTO_SET) / PROTOS_PER_PP_WERD)
-#define PPrunerBitIndexFor(I) ((I) % PROTOS_PER_PP_WERD)
-#define PPrunerMaskFor(I) (1 << PPrunerBitIndexFor(I))
-
-#define MaxNumClassesIn(T) (T->NumClassPruners * CLASSES_PER_CP)
-#define LegalClassId(c) ((c) >= 0 && (c) < MAX_NUM_CLASSES)
-#define UnusedClassIdIn(T, c) ((T)->Class[c] == nullptr)
-#define ClassForClassId(T, c) ((T)->Class[c])
-#define ClassPrunersFor(T) ((T)->ClassPruner)
-#define CPrunerIdFor(c) ((c) / CLASSES_PER_CP)
-#define CPrunerFor(T, c) ((T)->ClassPruners[CPrunerIdFor(c)])
-#define CPrunerWordIndexFor(c) (((c) % CLASSES_PER_CP) / CLASSES_PER_CP_WERD)
-#define CPrunerBitIndexFor(c) (((c) % CLASSES_PER_CP) % CLASSES_PER_CP_WERD)
-#define CPrunerMaskFor(L, c) (((L) + 1) << CPrunerBitIndexFor(c) * NUM_BITS_PER_CLASS)
-
-/* DEBUG macros*/
-#define PRINT_MATCH_SUMMARY 0x001
-#define DISPLAY_FEATURE_MATCHES 0x002
-#define DISPLAY_PROTO_MATCHES 0x004
-#define PRINT_FEATURE_MATCHES 0x008
-#define PRINT_PROTO_MATCHES 0x010
-#define CLIP_MATCH_EVIDENCE 0x020
-
-#define MatchDebuggingOn(D) (D)
-#define PrintMatchSummaryOn(D) ((D)&PRINT_MATCH_SUMMARY)
-#define DisplayFeatureMatchesOn(D) ((D)&DISPLAY_FEATURE_MATCHES)
-#define DisplayProtoMatchesOn(D) ((D)&DISPLAY_PROTO_MATCHES)
-#define PrintFeatureMatchesOn(D) ((D)&PRINT_FEATURE_MATCHES)
-#define PrintProtoMatchesOn(D) ((D)&PRINT_PROTO_MATCHES)
-#define ClipMatchEvidenceOn(D) ((D)&CLIP_MATCH_EVIDENCE)
+inline constexpr int MaxNumIntProtosIn(const INT_CLASS_STRUCT *C) { return C->NumProtoSets * PROTOS_PER_PROTO_SET; }
+inline constexpr int SetForProto(int P) { return P / PROTOS_PER_PROTO_SET; }
+inline constexpr int IndexForProto(int P) { return P % PROTOS_PER_PROTO_SET; }
+inline constexpr INT_PROTO_STRUCT *ProtoForProtoId(INT_CLASS_STRUCT *C, int P) {
+  return &(C->ProtoSets[SetForProto(P)]->Protos[IndexForProto(P)]);
+}
+inline constexpr int PPrunerWordIndexFor(int I) { return (I % PROTOS_PER_PROTO_SET) / PROTOS_PER_PP_WERD; }
+inline constexpr int PPrunerBitIndexFor(int I) { return I % PROTOS_PER_PP_WERD; }
+inline constexpr uint32_t PPrunerMaskFor(int I) { return 1u << PPrunerBitIndexFor(I); }
+
+inline constexpr int MaxNumClassesIn(const INT_TEMPLATES_STRUCT *T) { return T->NumClassPruners * CLASSES_PER_CP; }
+inline constexpr bool LegalClassId(int c) { return c >= 0 && c < MAX_NUM_CLASSES; }
+inline constexpr bool UnusedClassIdIn(INT_TEMPLATES_STRUCT *T, int c) { return T->Class[c] == nullptr; }
+inline constexpr INT_CLASS_STRUCT *&ClassForClassId(INT_TEMPLATES_STRUCT *T, int c) { return T->Class[c]; }
+
+inline constexpr int CPrunerIdFor(int c) { return c / CLASSES_PER_CP; }
+inline constexpr CLASS_PRUNER_STRUCT *CPrunerFor(INT_TEMPLATES_STRUCT *T, int c) {
+  return T->ClassPruners[CPrunerIdFor(c)];
+}
+inline constexpr int CPrunerWordIndexFor(int c) { return (c % CLASSES_PER_CP) / CLASSES_PER_CP_WERD; }
+inline constexpr int CPrunerBitIndexFor(int c) { return (c % CLASSES_PER_CP) % CLASSES_PER_CP_WERD; }
+inline constexpr uint32_t CPrunerMaskFor(int L, int c) {
+  return (static_cast<uint32_t>(L) + 1) << (CPrunerBitIndexFor(c) * NUM_BITS_PER_CLASS);
+}
+
+/* DEBUG constants */
+constexpr int PRINT_MATCH_SUMMARY = 0x001;
+constexpr int DISPLAY_FEATURE_MATCHES = 0x002;
+constexpr int DISPLAY_PROTO_MATCHES = 0x004;
+constexpr int PRINT_FEATURE_MATCHES = 0x008;
+constexpr int PRINT_PROTO_MATCHES = 0x010;
+constexpr int CLIP_MATCH_EVIDENCE = 0x020;
+
+inline constexpr int MatchDebuggingOn(int D) { return D; }
+inline constexpr bool PrintMatchSummaryOn(int D) { return (D & PRINT_MATCH_SUMMARY) != 0; }
+inline constexpr bool DisplayFeatureMatchesOn(int D) { return (D & DISPLAY_FEATURE_MATCHES) != 0; }
+inline constexpr bool DisplayProtoMatchesOn(int D) { return (D & DISPLAY_PROTO_MATCHES) != 0; }
+inline constexpr bool PrintFeatureMatchesOn(int D) { return (D & PRINT_FEATURE_MATCHES) != 0; }
+inline constexpr bool PrintProtoMatchesOn(int D) { return (D & PRINT_PROTO_MATCHES) != 0; }
+inline constexpr bool ClipMatchEvidenceOn(int D) { return (D & CLIP_MATCH_EVIDENCE) != 0; }

 /**----------------------------------------------------------------------------
           Public Function Prototypes
diff --git a/src/classify/mfoutline.h b/src/classify/mfoutline.h
index dece79ef..3aa318e7 100644
--- a/src/classify/mfoutline.h
+++ b/src/classify/mfoutline.h
@@ -55,10 +55,13 @@ enum NORM_METHOD { baseline, character };
 /**----------------------------------------------------------------------------
           Macros
 ----------------------------------------------------------------------------**/
-#define AverageOf(A, B) (((A) + (B)) / 2)
+template <typename T>
+inline constexpr T AverageOf(T A, T B) {
+  return (A + B) / T{2};
+}

 // Constant for computing the scale factor to use to normalize characters.
-const float MF_SCALE_FACTOR = 0.5f / kBlnXHeight;
+constexpr float MF_SCALE_FACTOR = 0.5f / kBlnXHeight;

 // Inline functions for manipulating micro-feature outlines.

diff --git a/src/classify/normfeat.h b/src/classify/normfeat.h
index 05f0ae8b..0b9b1867 100644
--- a/src/classify/normfeat.h
+++ b/src/classify/normfeat.h
@@ -23,7 +23,7 @@

 namespace tesseract {

-#define LENGTH_COMPRESSION (10.0)
+constexpr double LENGTH_COMPRESSION = 10.0;

 struct INT_FX_RESULT_STRUCT;

diff --git a/src/classify/ocrfeatures.h b/src/classify/ocrfeatures.h
index e9aa4d5e..a22b6f4b 100644
--- a/src/classify/ocrfeatures.h
+++ b/src/classify/ocrfeatures.h
@@ -29,7 +29,7 @@ class DENORM;

 #undef Min
 #undef Max
-#define FEAT_NAME_SIZE 80
+constexpr int FEAT_NAME_SIZE = 80;

 // A character is described by multiple sets of extracted features.  Each
 // set contains a number of features of a particular type, for example, a
diff --git a/src/classify/picofeat.h b/src/classify/picofeat.h
index 391aaa2f..443a7109 100644
--- a/src/classify/picofeat.h
+++ b/src/classify/picofeat.h
@@ -51,14 +51,14 @@ typedef enum { PicoFeatY, PicoFeatDir, PicoFeatX } PICO_FEAT_PARAM_NAME;
 extern double_VAR_H(classify_pico_feature_length);

 /**----------------------------------------------------------------------------
-          Public Function Prototypes
+        Global Data Definitions and Declarations
 ----------------------------------------------------------------------------**/
-#define GetPicoFeatureLength() (PicoFeatureLength)
+extern TESS_API float PicoFeatureLength;

 /**----------------------------------------------------------------------------
-        Global Data Definitions and Declarations
+          Public Function Prototypes
 ----------------------------------------------------------------------------**/
-extern TESS_API float PicoFeatureLength;
+inline float GetPicoFeatureLength() { return PicoFeatureLength; }

 } // namespace tesseract

diff --git a/src/dict/matchdefs.h b/src/dict/matchdefs.h
index 2228968f..3e5aeac8 100644
--- a/src/dict/matchdefs.h
+++ b/src/dict/matchdefs.h
@@ -28,17 +28,17 @@ namespace tesseract {
 /* define the maximum number of classes defined for any matcher
   and the maximum class id for any matcher. This must be changed
   if more different classes need to be classified */
-#define MAX_NUM_CLASSES INT16_MAX
+constexpr int MAX_NUM_CLASSES = INT16_MAX;

 /** a CLASS_ID is the ascii character to be associated with a class */
 using CLASS_ID = UNICHAR_ID;
-#define NO_CLASS (0)
+constexpr CLASS_ID NO_CLASS = 0;

 /** a PROTO_ID is the index of a prototype within it's class.  Valid proto
   id's are 0 to N-1 where N is the number of prototypes that make up the
   class. */
 using PROTO_ID = int16_t;
-#define NO_PROTO (-1)
+constexpr PROTO_ID NO_PROTO = -1;

 /** FEATURE_ID is the index of a feature within a character description
   The feature id ranges from 0 to N-1 where N is the number
diff --git a/src/wordrec/outlines.h b/src/wordrec/outlines.h
index c099d7e6..1d8afef0 100644
--- a/src/wordrec/outlines.h
+++ b/src/wordrec/outlines.h
@@ -28,9 +28,9 @@
 /*----------------------------------------------------------------------
               C o n s t a n t s
 ----------------------------------------------------------------------*/
-#define LARGE_DISTANCE 100000 /* Used for closest dist */
-#define MIN_BLOB_SIZE 10      /* Big units */
-#define MAX_ASPECT_RATIO 2.5  /* Widest character */
+constexpr int LARGE_DISTANCE = 100000; /* Used for closest dist */
+constexpr int MIN_BLOB_SIZE = 10;      /* Big units */
+constexpr double MAX_ASPECT_RATIO = 2.5; /* Widest character */

 /*----------------------------------------------------------------------
               M a c r o s
@@ -51,7 +51,10 @@
  * parameters must be of type POINT.
  **********************************************************************/

-#define dist_square(p1, p2) ((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y))
+template <typename Point>
+inline constexpr auto dist_square(const Point &p1, const Point &p2) {
+  return (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y);
+}

 /**********************************************************************
  * closest
@@ -60,10 +63,12 @@
  * question.  All three parameters must be of type EDGEPT.
  **********************************************************************/

-#define closest(test_p, p1, p2)                                                                   \
-  (p1 ? (p2 ? ((dist_square(test_p->pos, p1->pos) < dist_square(test_p->pos, p2->pos)) ? p1 : p2) \
-            : p1)                                                                                 \
-      : p2)
+template <typename Edgept>
+inline Edgept *closest(Edgept *test_p, Edgept *p1, Edgept *p2) {
+  if (!p1) return p2;
+  if (!p2) return p1;
+  return dist_square(test_p->pos, p1->pos) < dist_square(test_p->pos, p2->pos) ? p1 : p2;
+}

 /**********************************************************************
  * edgept_dist
@@ -71,7 +76,10 @@
  * Return the distance (squared) between the two edge points.
  **********************************************************************/

-#define edgept_dist(p1, p2) (dist_square((p1)->pos, (p2)->pos))
+template <typename Edgept>
+inline constexpr auto edgept_dist(const Edgept *p1, const Edgept *p2) {
+  return dist_square(p1->pos, p2->pos);
+}

 /**********************************************************************
  * is_exterior_point
@@ -90,7 +98,10 @@
  * Return true if the POINTs are equal.
  **********************************************************************/

-#define is_equal(p1, p2) (((p1).x == (p2).x) && ((p1).y == (p2).y))
+template <typename Point>
+inline constexpr bool is_equal(const Point &p1, const Point &p2) {
+  return p1.x == p2.x && p1.y == p2.y;
+}

 /**********************************************************************
  * is_on_line
@@ -100,16 +111,14 @@
  * parameters must be of type POINT.
  **********************************************************************/

-#define is_on_line(p, p0, p1) \
-  (within_range((p).x, (p0).x, (p1).x) && within_range((p).y, (p0).y, (p1).y))
+template <typename T>
+inline constexpr bool within_range(T x, T x0, T x1) {
+  return (x0 <= x && x <= x1) || (x1 <= x && x <= x0);
+}

-/**********************************************************************
- * within_range
- *
- * Return true if the first number is in between the second two numbers.
- * Return false otherwise.
- **********************************************************************/
-
-#define within_range(x, x0, x1) (((x0 <= x) && (x <= x1)) || ((x1 <= x) && (x <= x0)))
+template <typename Point>
+inline constexpr bool is_on_line(const Point &p, const Point &p0, const Point &p1) {
+  return within_range(p.x, p0.x, p1.x) && within_range(p.y, p0.y, p1.y);
+}

 #endif