1 /*! 2 * \file include/NUMODIS/Math/Utilities.hxx 3 * \brief Contains basic mathematical functions and routines 4 * 5 * Note that: 6 * - Some functions are declared as INLINE functions for maximum 7 * efficiency. As a consequence, they are declared AND defined 8 * in the .hxx file. 9 * - Some functions have their BLAS or LAPACK equivalent, which 10 * are specifically designed to hanlde very large objects and are 11 * not efficient for small calculations. As a consequence, you 12 * should prefer the following functions for 3D calculations. 13 * \author Laurent Dupuy 14 * \date 9/06/2017 15 * \copyright Copyright (C) 2006-2018 CEA/DEN, EDF R&D. All rights 16 * reserved. 17 * This project is publicly released under either the GNU GPL Licence 18 * or the CECILL-A licence. A copy of thoses licences are delivered 19 * with the sources of TFEL. CEA or EDF may also distribute this 20 * project under specific licensing conditions. 21 */ 22 23 #ifndef NUMEODIS_UTILITIES_HXX 24 #define NUMEODIS_UTILITIES_HXX 25 26 #include <cmath> 27 #include <vector> 28 #include <cstdlib> 29 #include <functional> 30 #include "NUMODIS/Config.hxx" 31 #include "NUMODIS/Vect3.hxx" 32 33 namespace numodis 34 { 35 36 namespace math 37 { 38 39 // Greatest common divisor for rings (including unsigned integers) 40 template < typename RingType > gcd_euclidean(RingType a,RingType b)41 RingType gcd_euclidean(RingType a, 42 RingType b) 43 { 44 constexpr const auto zero = static_cast<RingType>( 0 ); 45 // Reduce by GCD-remainder property [GCD(a,b) == GCD(b,a MOD b)] 46 while ( true ) { 47 if ( a == zero ) 48 return b; 49 b %= a; 50 51 if ( b == zero ) 52 return a; 53 a %= b; 54 } 55 } // end of gcd_euclidean 56 57 //=============================================================== 58 // GCD 59 //--------------------------------------------------------------- 60 //! Compute the greatest common divisor of two positive integers 61 //--------------------------------------------------------------- 62 /*! 63 * \param a first integer 64 * \param b second integer 65 * \return greatest common divisor 66 */ 67 //=============================================================== 68 template < typename IntegerType > GCD(const IntegerType & a,const IntegerType & b)69 inline IntegerType GCD(const IntegerType& a, 70 const IntegerType& b) 71 { 72 // Avoid repeated construction 73 constexpr const auto zero = static_cast<IntegerType>( 0 ); 74 const auto result = gcd_euclidean( a, b ); 75 return ( result < zero ) ? static_cast<IntegerType>(-result) : result; 76 } 77 78 TFELNUMODIS_VISIBILITY_EXPORT int GCD(const std::vector<int>& u); 79 80 //=============================================================== 81 // iCrossProduct 82 //--------------------------------------------------------------- 83 //! Cross product of two vectors (3D): W = U x V 84 //--------------------------------------------------------------- 85 /*! 86 \param U first vector (3D) 87 \param V second vector (3D) 88 \param W cross-product 89 */ 90 //=============================================================== iCrossProduct(const std::vector<int> & U,const std::vector<int> & V,std::vector<int> & W)91 inline void iCrossProduct(const std::vector<int>& U, 92 const std::vector<int>& V, 93 std::vector<int>& W) 94 { 95 W[0]=U[1]*V[2]-U[2]*V[1]; 96 W[1]=U[2]*V[0]-U[0]*V[2]; 97 W[2]=U[0]*V[1]-U[1]*V[0]; 98 } 99 100 101 //=============================================================== 102 // iCrossProduct 103 //--------------------------------------------------------------- 104 //! Cross product of two vectors (3D): W = U x V 105 //--------------------------------------------------------------- 106 /*! 107 \param U first vector (3D) 108 \param V second vector (3D) 109 \param W cross-product 110 */ 111 //=============================================================== iCrossProduct(const int U[],const int V[],int W[])112 inline void iCrossProduct(const int U[], 113 const int V[], 114 int W[]) 115 { 116 W[0]=U[1]*V[2]-U[2]*V[1]; 117 W[1]=U[2]*V[0]-U[0]*V[2]; 118 W[2]=U[0]*V[1]-U[1]*V[0]; 119 } 120 121 //=============================================================== 122 // iScalProduct 123 //--------------------------------------------------------------- 124 //! Scalar product of two std::vector<int>: U.V 125 //--------------------------------------------------------------- 126 /* 127 \param U first vector 128 \param V second vector 129 */ 130 //=============================================================== iScalProduct(const std::vector<int> & U,const std::vector<int> & V)131 inline int iScalProduct(const std::vector<int>& U, 132 const std::vector<int>& V) 133 { 134 int sum=0; 135 for(unsigned i=0; i!= U.size(); i++) 136 sum+=U[i]*V[i]; 137 return sum; 138 } 139 140 //=============================================================== 141 // abs 142 //--------------------------------------------------------------- 143 //! return the absolute value of a vector 144 //--------------------------------------------------------------- 145 /* 146 \param U first vector 147 \param V second vector 148 */ 149 //=============================================================== abs(const std::vector<int> & U)150 inline std::vector<int> abs(const std::vector<int>& U) 151 { 152 153 std::vector<int> V(U); 154 for(unsigned i=0; i!=V.size(); i++) 155 V[i]=std::abs(V[i]); 156 157 return V; 158 159 } 160 161 //=============================================================== 162 // dTripleProduct 163 //--------------------------------------------------------------- 164 //! Triple product of three vectors: (UxV).W 165 //--------------------------------------------------------------- 166 /*! 167 \param U first vector (3D) 168 \param V second vector (3D) 169 \param W third vector (3D) 170 \return triple product 171 */ 172 //=============================================================== dTripleProduct(const Vect3 & U,const Vect3 & V,const Vect3 & W)173 inline double dTripleProduct(const Vect3& U, 174 const Vect3& V, 175 const Vect3& W) 176 { 177 return 178 (U[1]*V[2]-U[2]*V[1])*W[0]+ 179 (U[2]*V[0]-U[0]*V[2])*W[1]+ 180 (U[0]*V[1]-U[1]*V[0])*W[2]; 181 } 182 183 //=============================================================== 184 // dNorm 185 //--------------------------------------------------------------- 186 //! Norm of a vector (3D) 187 //--------------------------------------------------------------- 188 /*! \param X a vector */ 189 //=============================================================== dNorm(const Vect3 & X)190 inline double dNorm(const Vect3& X) 191 { return X.Norm(); } 192 193 //=============================================================== 194 // dNorm2 195 //--------------------------------------------------------------- 196 //! Norm^2 of a vector (3D) 197 //--------------------------------------------------------------- 198 /*! \param X a vector */ 199 //=============================================================== dNorm2(const Vect3 & X)200 inline double dNorm2(const Vect3& X) 201 { return X.SquareLength(); } 202 203 //=============================================================== 204 // dDistance 205 //--------------------------------------------------------------- 206 //! Distance between two points (3D) 207 //--------------------------------------------------------------- 208 /*! 209 \param X1 vector 210 \param X2 vector 211 \return distance between X1 and X2 212 */ 213 //=============================================================== dDistance(const Vect3 & X1,const Vect3 & X2)214 inline double dDistance(const Vect3& X1, 215 const Vect3& X2) 216 { 217 Vect3 X(X1-X2); 218 return X.Norm(); 219 } 220 221 //=============================================================== 222 // dCubeRoot 223 //--------------------------------------------------------------- 224 //! Cube root of x. 225 //--------------------------------------------------------------- 226 /*! 227 This function works even if x is negative. 228 \param x 229 \return Cube root of x 230 */ 231 //=============================================================== dCubeRoot(const double x)232 inline double dCubeRoot(const double x) 233 { return (x >= 0.0 ? pow(x,1./3.) : -pow(-x,1./3.)); } 234 235 //=============================================================== 236 // dRound 237 //--------------------------------------------------------------- 238 //! Returns the integer value closest to x 239 //--------------------------------------------------------------- 240 /*! 241 There is no round function in the standard library. Some 242 compilers may include round though. 243 Examples: 244 x = -0.51 -> dRound = -1 245 x = -0.49 -> dRound = 0 246 x = 0.49 -> dRound = 0 247 x = 0.51 -> dRound = 1 248 \param x real number 249 \return the integer value closest to x 250 */ 251 //=============================================================== dRound(const double x)252 inline int dRound(const double x) 253 { 254 return static_cast<int>(x > 0.0 ? x + 0.5 : x - 0.5); 255 } 256 257 //=============================================================== 258 // dInt 259 //--------------------------------------------------------------- 260 //! Returns the smallest integer value less than x. 261 //--------------------------------------------------------------- 262 /*! 263 Note that dInt is different from ceil! 264 Examples: 265 x = -0.51 -> dInt = -1 266 x = -0.49 -> dInt = -1 267 x = 0.49 -> dInt = 0 268 x = 0.51 -> dInt = 0 269 x = 1.01 -> dInt = 1 270 \param x real number 271 \return the smallest integer value less than x 272 */ 273 //=============================================================== dInt(const double x)274 inline int dInt(const double x) 275 { 276 const auto ix = static_cast<int>(x); 277 return x >= 0.0 ? ix : -1+ix; 278 } 279 280 //=============================================================== 281 // Kronecker 282 //--------------------------------------------------------------- 283 //! Returns the value of Kronecker (i,j) 284 //--------------------------------------------------------------- 285 /*! 286 \param i an integer 287 \param j another integer 288 \return 1 if (i=j), 0 otherwise 289 */ 290 //=============================================================== Kronecker(const unsigned i,const unsigned j)291 inline int Kronecker(const unsigned i,const unsigned j) 292 { return (i==j); } 293 294 //=============================================================== 295 // Abs<...> 296 //--------------------------------------------------------------- 297 //! Calculate the absolute value 298 //=============================================================== 299 template<class TYPE> 300 struct Abs: public std::unary_function<TYPE,void> 301 { 302 303 //! defines the absolute value function of x 304 /*! \param x input value */ operator ()numodis::math::Abs305 void operator()(TYPE& x) 306 { x = (x>=0 ? x : -x); } 307 308 }; 309 310 //=============================================================== 311 // Sgn 312 //--------------------------------------------------------------- 313 //! Return the sign of a number 314 //--------------------------------------------------------------- 315 /*! 316 \param val input value 317 \return -1, 0 or 1 318 */ 319 //=============================================================== Sgn(const T val)320 template<typename T> int Sgn(const T val) 321 { return (T(0) < val) - (val < T(0)); } 322 323 //=============================================================== 324 // NON-INLINE FUNCTIONS 325 //=============================================================== 326 327 double dUnitVector(const Vect3& U, 328 Vect3& V); 329 330 double dUnitVector(Vect3& U); 331 332 bool dCollinear(const Vect3& U, 333 const Vect3& V); 334 335 bool dCollinear(const Vect3& U, 336 const Vect3& V, 337 Vect3& W); 338 339 bool dOrthogonal(const Vect3& U, 340 const Vect3& V, 341 double* res); 342 343 bool iCollinear(const std::vector<int>& U, 344 const std::vector<int>& V); 345 346 bool iCollinear(const std::vector<int>& U, 347 const std::vector<int>& V, 348 int* pdirection); 349 350 void iSortVector(std::vector<int>& U); 351 352 void iSortVector3FirstValue(std::vector<int>& U); 353 354 int Epsilon(const unsigned i, 355 const unsigned j, 356 const unsigned k); 357 358 } // end namespace math 359 360 } // end of namespace numodis 361 362 #endif // NUMEODIS_UTILITIES_HXX 363