00001 ///////////////////////////////////////////////////////////////////////////////////////// 00002 /// \file sparkmath.h 00003 /// \brief Math functions 00004 /// 00005 /// Declares constant variables : 00006 /// - SPARK::TINY 00007 /// - SPARK::SQRT_UROUND 00008 /// 00009 /// Declares functions : 00010 /// - SPARK::min() 00011 /// - SPARK::max() 00012 /// - SPARK::sign() 00013 /// - SPARK::abs() 00014 /// - SPARK::InfiniteOrNaN() 00015 /// - SPARK::log2() 00016 /// 00017 ///////////////////////////////////////////////////////////////////////////////////////// 00018 /// 00019 /// \author Dimitri Curtil (LBNL/SRG) 00020 /// \date May 21, 2002 00021 /// 00022 ///////////////////////////////////////////////////////////////////////////////////////// 00023 /// \attention 00024 /// PORTIONS COPYRIGHT (C) 2003 AYRES SOWELL ASSOCIATES, INC. \n 00025 /// PORTIONS COPYRIGHT (C) 2003 THE REGENTS OF THE UNIVERSITY OF CALIFORNIA . 00026 /// PENDING APPROVAL BY THE US DEPARTMENT OF ENERGY. ALL RIGHTS RESERVED. 00027 /// 00028 ///////////////////////////////////////////////////////////////////////////////////////// 00029 00030 00031 #if !defined(__SPARKMATH_H__) 00032 #define __SPARKMATH_H__ 00033 00034 00035 // Gets rid of warning messages about dll-interface for private data member 00036 // Message shows typically with std classes, e.g., std::string 00037 #pragma warning(disable:4251) 00038 00039 00040 #include <cmath> // for sqrt, fabs 00041 #include <limits> 00042 00043 #include "compat.h" // for UROUND 00044 00045 00046 00047 ///////////////////////////////////////////////////////////////////////////////////////// 00048 namespace SPARK { 00049 00050 ///////////////////////////////////////////////////////////////////////////////////// 00051 /// \name Constant Declaration 00052 //@{ 00053 00054 /// Considered essentially as zero in solver (e.g., used to detect singularity) 00055 const double TINY = 1.0E-30; 00056 00057 /// Square root of the unit round-off error 00058 const double SQRT_UROUND = sqrt(UROUND); 00059 00060 //@} 00061 ///////////////////////////////////////////////////////////////////////////////////// 00062 00063 00064 /////////////////////////// 00065 // Function declarations // 00066 /////////////////////////// 00067 00068 ///////////////////////////////////////////////////////////////////////////////////// 00069 /// \name Functions used in HVAC toolkit 00070 //@{ 00071 00072 /// Returns the absolute value of x 00073 /// 00074 /// \warning Use SPARK::abs() to avoid possible confusion with abs(), fabs() 00075 /// defined in the system include files <math.h> or <cmath>. 00076 /// The abs() function has the prototype int abs(int x) which forces 00077 /// a type conversion from double to int. Usually, this is not the 00078 /// desired effect and it is a tricky bug hard to detect. 00079 /// Therefore, we recommend using SPARK::abs() to avoid any confusion. 00080 inline API_DECLSPEC(double) abs(double x) { return fabs(x); } 00081 00082 /// Returns the min of two variables that can be compared using < 00083 /// 00084 /// \warning Use SPARK::min() to avoid possible confusion with std::min() 00085 inline API_DECLSPEC(double) min(double x, double y) { return (x < y ? x : y); } 00086 00087 /// Returns the max of two variables that can be compared using > 00088 /// 00089 /// \warning Use SPARK::max() to avoid possible confusion with std::max() 00090 inline API_DECLSPEC(double) max(double x, double y) { return (x > y ? x : y); } 00091 00092 /// Returns the +1.0 if \c x is positive, -1.0 otherwise 00093 inline API_DECLSPEC(double) sign(double x) { return (x < 0.0 ? -1.0 : 1.0); } 00094 00095 /// Returns the \c a if \c b is strictly positive, \c -a otherwise 00096 inline API_DECLSPEC(double) sign(double retval, double test) { return (test > 0.0 ? fabs(retval) : -fabs(retval)); } 00097 00098 /// Returns the log in base 2 of the double x 00099 /// 00100 /// \note Use log() and log10() declared in <cmath> to compute the logarithms in base 00101 /// e and 10 respectively 00102 inline API_DECLSPEC(double) log2(double x) { return (1.4426950408889634074*log(x)); } 00103 00104 //@} 00105 ///////////////////////////////////////////////////////////////////////////////////// 00106 00107 00108 ///////////////////////////////////////////////////////////////////////////////////// 00109 /// \name Functions used inside the solver code 00110 //@{ 00111 00112 /// Codes returned by SPARK::InfiniteOrNaN() function 00113 enum NumericalValueTypes { 00114 NumericalValueType_VALID = 0, ///< numerical value is valid 00115 NumericalValueType_INF = 1, ///< numerical value is positive infinite 00116 NumericalValueType_NAN = 2 ///< numerical value is not a number 00117 }; 00118 00119 00120 /// \brief Checks whether the floating-point number \c scalar is infinite or NaN or a valid numerical scalar 00121 /// 00122 /// \return Numerical type as enum NumericalValueTypes 00123 /// \param scalar floating-point value of type T to check 00124 /// 00125 template<typename T> 00126 API_DECLSPEC(NumericalValueTypes) InfiniteOrNaN(T scalar) 00127 { 00128 // NaN Floating-Point Behavior (from MS website) 00129 // NaN comparisons have changed to better support IEEE 754. 00130 // · NaN equality rules have changed: NaN == NaN tests now return false, NaN != NaN tests now return true. 00131 // · NaN ordering tests always return false: NaN [<, <=, >, >=] [any number] will be false. 00132 // For more information, see the section "Not a Number (NAN)" in the topic "C++ Compiler, Linker, and C++ Language" in the Visual C++ online documentation. 00133 00134 // Some compilers also implement the following non-standard functions: 00135 // #include <math.h> 00136 // double nan(const char *tagp); 00137 // float nanf(const char *tagp); 00138 // long double nanl(const char *tagp); 00139 // int _isnan(double ); 00140 // => does not catch a quiet NaN though 00141 00142 /// \bug g++ 3.2 does not like the definition of INFINITY from std::numeric_limits<T>::max() !! 00143 // const T INFINITY = std::numeric_limits<T>::max(); 00144 00145 static T ZERO(0); 00146 00147 // Probably NaN according to standard IEEE 754. 00148 // This might also catch the positive inifinte and negative infinite cases! 00149 if (scalar != scalar || !(scalar >= scalar) || !(scalar <= scalar)) { 00150 return SPARK::NumericalValueType_NAN; 00151 } 00152 else if ( (scalar < ZERO ? -scalar : scalar) >= std::numeric_limits<T>::max() ) { 00153 return SPARK::NumericalValueType_INF; 00154 } 00155 else { 00156 return SPARK::NumericalValueType_VALID; 00157 } 00158 } 00159 00160 //@} 00161 ///////////////////////////////////////////////////////////////////////////////////// 00162 00163 00164 }; // namespace SPARK 00165 ///////////////////////////////////////////////////////////////////////////////////////// 00166 00167 00168 #endif // __SPARKMATH_H__ 00169 00170