Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-28 09:20:53

0001 // Copyright (c) 2025 OPEN CASCADE SAS
0002 //
0003 // This file is part of Open CASCADE Technology software library.
0004 //
0005 // This library is free software; you can redistribute it and/or modify it under
0006 // the terms of the GNU Lesser General Public License version 2.1 as published
0007 // by the Free Software Foundation, with special exception defined in the file
0008 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0009 // distribution for complete text of the license and disclaimer of any warranty.
0010 //
0011 // Alternatively, this file may be used under the terms of Open CASCADE
0012 // commercial license or contractual agreement.
0013 
0014 #ifndef _MathUtils_Core_HeaderFile
0015 #define _MathUtils_Core_HeaderFile
0016 
0017 #include <math_Vector.hxx>
0018 
0019 #include <cmath>
0020 #include <algorithm>
0021 #include <limits>
0022 
0023 //! Modern math solver utilities.
0024 namespace MathUtils
0025 {
0026 
0027 //! Machine epsilon for double precision.
0028 inline constexpr double THE_EPSILON = std::numeric_limits<double>::epsilon();
0029 
0030 //! Small value for zero comparisons (more practical than epsilon).
0031 inline constexpr double THE_ZERO_TOL = 1.0e-15;
0032 
0033 //! Pi constant.
0034 inline constexpr double THE_PI = 3.14159265358979323846;
0035 
0036 //! Two Pi constant.
0037 inline constexpr double THE_2PI = 6.28318530717958647692;
0038 
0039 //! Golden ratio for optimization algorithms.
0040 inline constexpr double THE_GOLDEN_RATIO = 1.618033988749895;
0041 
0042 //! Inverse golden ratio (1 - 1/phi).
0043 inline constexpr double THE_GOLDEN_SECTION = 0.381966011250105;
0044 
0045 //! Clamp value to range [theLower, theUpper].
0046 //! @param theValue value to clamp
0047 //! @param theLower lower bound
0048 //! @param theUpper upper bound
0049 //! @return clamped value
0050 inline constexpr double Clamp(double theValue, double theLower, double theUpper)
0051 {
0052   return (theValue < theLower) ? theLower : ((theValue > theUpper) ? theUpper : theValue);
0053 }
0054 
0055 //! Check if value is effectively zero.
0056 //! @param theValue value to check
0057 //! @param theTolerance tolerance for zero comparison
0058 //! @return true if |theValue| < theTolerance
0059 inline bool IsZero(double theValue, double theTolerance = THE_ZERO_TOL)
0060 {
0061   return std::abs(theValue) < theTolerance;
0062 }
0063 
0064 //! Check if two values are approximately equal.
0065 //! @param theA first value
0066 //! @param theB second value
0067 //! @param theTolerance relative tolerance
0068 //! @return true if values are approximately equal
0069 inline bool IsEqual(double theA, double theB, double theTolerance = THE_ZERO_TOL)
0070 {
0071   const double aDiff  = std::abs(theA - theB);
0072   const double aScale = std::max({1.0, std::abs(theA), std::abs(theB)});
0073   return aDiff < theTolerance * aScale;
0074 }
0075 
0076 //! Safe division avoiding division by zero.
0077 //! @param theNumerator numerator
0078 //! @param theDenominator denominator
0079 //! @param theDefault default value if denominator is zero
0080 //! @return theNumerator / theDenominator or theDefault
0081 inline double SafeDiv(double theNumerator, double theDenominator, double theDefault = 0.0)
0082 {
0083   return IsZero(theDenominator) ? theDefault : theNumerator / theDenominator;
0084 }
0085 
0086 //! Sign function.
0087 //! @param theValue input value
0088 //! @return -1 if negative, 0 if zero, +1 if positive
0089 inline int Sign(double theValue)
0090 {
0091   if (theValue > THE_ZERO_TOL)
0092     return 1;
0093   if (theValue < -THE_ZERO_TOL)
0094     return -1;
0095   return 0;
0096 }
0097 
0098 //! Sign transfer function: returns |theA| with sign of theB.
0099 //! Equivalent to copysign but avoids edge cases with zero.
0100 //! @param theA value whose magnitude is used
0101 //! @param theB value whose sign is used
0102 //! @return |theA| * sign(theB)
0103 inline double SignTransfer(double theA, double theB)
0104 {
0105   return (theB >= 0.0) ? std::abs(theA) : -std::abs(theA);
0106 }
0107 
0108 //! Square of a value.
0109 //! @param theValue input value
0110 //! @return theValue * theValue
0111 inline constexpr double Sqr(double theValue)
0112 {
0113   return theValue * theValue;
0114 }
0115 
0116 //! Cube of a value.
0117 //! @param theValue input value
0118 //! @return theValue^3
0119 inline constexpr double Cube(double theValue)
0120 {
0121   return theValue * theValue * theValue;
0122 }
0123 
0124 //! Cube root with proper sign handling.
0125 //! Unlike std::cbrt, this handles negative values correctly on all platforms.
0126 //! @param theValue input value
0127 //! @return cube root of theValue
0128 inline double CubeRoot(double theValue)
0129 {
0130   return (theValue >= 0.0) ? std::cbrt(theValue) : -std::cbrt(-theValue);
0131 }
0132 
0133 //! Check if value is finite (not NaN or Inf).
0134 //! @param theValue value to check
0135 //! @return true if finite
0136 inline bool IsFinite(double theValue)
0137 {
0138   return std::isfinite(theValue);
0139 }
0140 
0141 //! Compute scaling factor for coefficient normalization.
0142 //! Used to improve numerical stability by scaling coefficients.
0143 //! @param theCoeffs array of coefficients
0144 //! @param theCount number of coefficients
0145 //! @return scaling factor (power of 2 for exact arithmetic)
0146 inline double ComputeScaleFactor(const double* theCoeffs, int theCount)
0147 {
0148   double aMaxAbs = 0.0;
0149   for (int i = 0; i < theCount; ++i)
0150   {
0151     aMaxAbs = std::max(aMaxAbs, std::abs(theCoeffs[i]));
0152   }
0153 
0154   if (aMaxAbs < THE_ZERO_TOL || aMaxAbs > 1.0e15)
0155   {
0156     // Find nearest power of 2 for exact scaling
0157     int anExp = 0;
0158     std::frexp(aMaxAbs, &anExp);
0159     return std::ldexp(1.0, -anExp + 1);
0160   }
0161 
0162   return 1.0;
0163 }
0164 
0165 //! Compute dot product of two vectors.
0166 //! @param theA first vector
0167 //! @param theB second vector
0168 //! @return dot product sum(A[i] * B[i])
0169 inline double DotProduct(const math_Vector& theA, const math_Vector& theB)
0170 {
0171   double    aSum   = 0.0;
0172   const int aLower = theA.Lower();
0173   const int aUpper = theA.Upper();
0174   for (int i = aLower; i <= aUpper; ++i)
0175   {
0176     aSum += theA(i) * theB(i);
0177   }
0178   return aSum;
0179 }
0180 
0181 //! Compute Euclidean norm of a vector.
0182 //! @param theVec input vector
0183 //! @return sqrt(sum(V[i]^2))
0184 inline double VectorNorm(const math_Vector& theVec)
0185 {
0186   double aSum = 0.0;
0187   for (int i = theVec.Lower(); i <= theVec.Upper(); ++i)
0188   {
0189     aSum += theVec(i) * theVec(i);
0190   }
0191   return std::sqrt(aSum);
0192 }
0193 
0194 //! Compute infinity norm (maximum absolute value) of a vector.
0195 //! @param theVec input vector
0196 //! @return max(|V[i]|)
0197 inline double VectorInfNorm(const math_Vector& theVec)
0198 {
0199   double aMax = 0.0;
0200   for (int i = theVec.Lower(); i <= theVec.Upper(); ++i)
0201   {
0202     aMax = std::max(aMax, std::abs(theVec(i)));
0203   }
0204   return aMax;
0205 }
0206 
0207 } // namespace MathUtils
0208 
0209 #endif // _MathUtils_Core_HeaderFile