1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #if !defined INCLUDED_RTL_MATH_HXX 29 #define INCLUDED_RTL_MATH_HXX 30 31 #include "rtl/math.h" 32 #include "rtl/string.hxx" 33 #include "rtl/ustring.hxx" 34 #include "rtl/ustrbuf.hxx" 35 #include "sal/mathconf.h" 36 #include "sal/types.h" 37 38 #include <math.h> 39 40 namespace rtl { 41 42 namespace math { 43 44 /** A wrapper around rtl_math_doubleToString. 45 */ 46 inline rtl::OString doubleToString(double fValue, rtl_math_StringFormat eFormat, 47 sal_Int32 nDecPlaces, 48 sal_Char cDecSeparator, 49 sal_Int32 const * pGroups, 50 sal_Char cGroupSeparator, 51 bool bEraseTrailingDecZeros = false) 52 { 53 rtl::OString aResult; 54 rtl_math_doubleToString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces, 55 cDecSeparator, pGroups, cGroupSeparator, 56 bEraseTrailingDecZeros); 57 return aResult; 58 } 59 60 /** A wrapper around rtl_math_doubleToString, with no grouping. 61 */ 62 inline rtl::OString doubleToString(double fValue, rtl_math_StringFormat eFormat, 63 sal_Int32 nDecPlaces, 64 sal_Char cDecSeparator, 65 bool bEraseTrailingDecZeros = false) 66 { 67 rtl::OString aResult; 68 rtl_math_doubleToString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces, 69 cDecSeparator, 0, 0, bEraseTrailingDecZeros); 70 return aResult; 71 } 72 73 /** A wrapper around rtl_math_doubleToUString. 74 */ 75 inline rtl::OUString doubleToUString(double fValue, 76 rtl_math_StringFormat eFormat, 77 sal_Int32 nDecPlaces, 78 sal_Unicode cDecSeparator, 79 sal_Int32 const * pGroups, 80 sal_Unicode cGroupSeparator, 81 bool bEraseTrailingDecZeros = false) 82 { 83 rtl::OUString aResult; 84 rtl_math_doubleToUString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces, 85 cDecSeparator, pGroups, cGroupSeparator, 86 bEraseTrailingDecZeros); 87 return aResult; 88 } 89 90 /** A wrapper around rtl_math_doubleToUString, with no grouping. 91 */ 92 inline rtl::OUString doubleToUString(double fValue, 93 rtl_math_StringFormat eFormat, 94 sal_Int32 nDecPlaces, 95 sal_Unicode cDecSeparator, 96 bool bEraseTrailingDecZeros = false) 97 { 98 rtl::OUString aResult; 99 rtl_math_doubleToUString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces, 100 cDecSeparator, 0, 0, bEraseTrailingDecZeros); 101 return aResult; 102 } 103 104 /** A wrapper around rtl_math_doubleToUString that appends to an 105 rtl::OUStringBuffer. 106 */ 107 inline void doubleToUStringBuffer( rtl::OUStringBuffer& rBuffer, double fValue, 108 rtl_math_StringFormat eFormat, 109 sal_Int32 nDecPlaces, 110 sal_Unicode cDecSeparator, 111 sal_Int32 const * pGroups, 112 sal_Unicode cGroupSeparator, 113 bool bEraseTrailingDecZeros = false) 114 { 115 rtl_uString ** pData; 116 sal_Int32 * pCapacity; 117 rBuffer.accessInternals( &pData, &pCapacity ); 118 rtl_math_doubleToUString( pData, pCapacity, rBuffer.getLength(), fValue, 119 eFormat, nDecPlaces, cDecSeparator, pGroups, 120 cGroupSeparator, bEraseTrailingDecZeros); 121 } 122 123 /** A wrapper around rtl_math_doubleToUString that appends to an 124 rtl::OUStringBuffer, with no grouping. 125 */ 126 inline void doubleToUStringBuffer( rtl::OUStringBuffer& rBuffer, double fValue, 127 rtl_math_StringFormat eFormat, 128 sal_Int32 nDecPlaces, 129 sal_Unicode cDecSeparator, 130 bool bEraseTrailingDecZeros = false) 131 { 132 rtl_uString ** pData; 133 sal_Int32 * pCapacity; 134 rBuffer.accessInternals( &pData, &pCapacity ); 135 rtl_math_doubleToUString( pData, pCapacity, rBuffer.getLength(), fValue, 136 eFormat, nDecPlaces, cDecSeparator, 0, 0, 137 bEraseTrailingDecZeros); 138 } 139 140 /** A wrapper around rtl_math_stringToDouble. 141 */ 142 inline double stringToDouble(rtl::OString const & rString, 143 sal_Char cDecSeparator, sal_Char cGroupSeparator, 144 rtl_math_ConversionStatus * pStatus, 145 sal_Int32 * pParsedEnd) 146 { 147 sal_Char const * pBegin = rString.getStr(); 148 sal_Char const * pEnd; 149 double fResult = rtl_math_stringToDouble(pBegin, 150 pBegin + rString.getLength(), 151 cDecSeparator, cGroupSeparator, 152 pStatus, &pEnd); 153 if (pParsedEnd != 0) 154 *pParsedEnd = (sal_Int32)(pEnd - pBegin); 155 return fResult; 156 } 157 158 /** A wrapper around rtl_math_uStringToDouble. 159 */ 160 inline double stringToDouble(rtl::OUString const & rString, 161 sal_Unicode cDecSeparator, 162 sal_Unicode cGroupSeparator, 163 rtl_math_ConversionStatus * pStatus, 164 sal_Int32 * pParsedEnd) 165 { 166 sal_Unicode const * pBegin = rString.getStr(); 167 sal_Unicode const * pEnd; 168 double fResult = rtl_math_uStringToDouble(pBegin, 169 pBegin + rString.getLength(), 170 cDecSeparator, cGroupSeparator, 171 pStatus, &pEnd); 172 if (pParsedEnd != 0) 173 *pParsedEnd = (sal_Int32)(pEnd - pBegin); 174 return fResult; 175 } 176 177 /** A wrapper around rtl_math_round. 178 */ 179 inline double round( 180 double fValue, int nDecPlaces = 0, 181 rtl_math_RoundingMode eMode = rtl_math_RoundingMode_Corrected) 182 { 183 return rtl_math_round(fValue, nDecPlaces, eMode); 184 } 185 186 /** A wrapper around rtl_math_pow10Exp. 187 */ 188 inline double pow10Exp(double fValue, int nExp) 189 { 190 return rtl_math_pow10Exp(fValue, nExp); 191 } 192 193 /** A wrapper around rtl_math_approxValue. 194 */ 195 inline double approxValue(double fValue) 196 { 197 return rtl_math_approxValue(fValue); 198 } 199 200 /** A wrapper around rtl_math_expm1. 201 */ 202 inline double expm1(double fValue) 203 { 204 return rtl_math_expm1(fValue); 205 } 206 207 /** A wrapper around rtl_math_log1p. 208 */ 209 inline double log1p(double fValue) 210 { 211 return rtl_math_log1p(fValue); 212 } 213 214 /** A wrapper around rtl_math_atanh. 215 */ 216 inline double atanh(double fValue) 217 { 218 return rtl_math_atanh(fValue); 219 } 220 221 /** A wrapper around rtl_math_erf. 222 */ 223 inline double erf(double fValue) 224 { 225 return rtl_math_erf(fValue); 226 } 227 228 /** A wrapper around rtl_math_erfc. 229 */ 230 inline double erfc(double fValue) 231 { 232 return rtl_math_erfc(fValue); 233 } 234 235 /** A wrapper around rtl_math_asinh. 236 */ 237 inline double asinh(double fValue) 238 { 239 return rtl_math_asinh(fValue); 240 } 241 242 /** A wrapper around rtl_math_acosh. 243 */ 244 inline double acosh(double fValue) 245 { 246 return rtl_math_acosh(fValue); 247 } 248 249 250 /** Test equality of two values with an accuracy of the magnitude of the 251 given values scaled by 2^-48 (4 bits roundoff stripped). 252 253 @ATTENTION 254 approxEqual( value!=0.0, 0.0 ) _never_ yields true. 255 */ 256 inline bool approxEqual(double a, double b) 257 { 258 if ( a == b ) 259 return true; 260 double x = a - b; 261 return (x < 0.0 ? -x : x) 262 < ((a < 0.0 ? -a : a) * (1.0 / (16777216.0 * 16777216.0))); 263 } 264 265 /** Add two values. 266 267 If signs differ and the absolute values are equal according to approxEqual() 268 the method returns 0.0 instead of calculating the sum. 269 270 If you wanted to sum up multiple values it would be convenient not to call 271 approxAdd() for each value but instead remember the first value not equal to 272 0.0, add all other values using normal + operator, and with the result and 273 the remembered value call approxAdd(). 274 */ 275 inline double approxAdd(double a, double b) 276 { 277 if ( ((a < 0.0 && b > 0.0) || (b < 0.0 && a > 0.0)) 278 && approxEqual( a, -b ) ) 279 return 0.0; 280 return a + b; 281 } 282 283 /** Substract two values (a-b). 284 285 If signs are identical and the values are equal according to approxEqual() 286 the method returns 0.0 instead of calculating the substraction. 287 */ 288 inline double approxSub(double a, double b) 289 { 290 if ( ((a < 0.0 && b < 0.0) || (a > 0.0 && b > 0.0)) && approxEqual( a, b ) ) 291 return 0.0; 292 return a - b; 293 } 294 295 /** floor() method taking approxValue() into account. 296 297 Use for expected integer values being calculated by double functions. 298 */ 299 inline double approxFloor(double a) 300 { 301 return floor( approxValue( a )); 302 } 303 304 /** ceil() method taking approxValue() into account. 305 306 Use for expected integer values being calculated by double functions. 307 */ 308 inline double approxCeil(double a) 309 { 310 return ceil( approxValue( a )); 311 } 312 313 /** Tests whether a value is neither INF nor NAN. 314 */ 315 inline bool isFinite(double d) 316 { 317 return SAL_MATH_FINITE(d) != 0; 318 } 319 320 /** If a value represents +INF or -INF. 321 322 The sign bit may be queried with isSignBitSet(). 323 324 If isFinite(d)==false and isInf(d)==false then NAN. 325 */ 326 inline bool isInf(double d) 327 { 328 // exponent==0x7ff fraction==0 329 return (SAL_MATH_FINITE(d) == 0) && 330 (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_hi == 0) 331 && (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_lo 332 == 0); 333 } 334 335 /** Test on any QNAN or SNAN. 336 */ 337 inline bool isNan(double d) 338 { 339 // exponent==0x7ff fraction!=0 340 return (SAL_MATH_FINITE(d) == 0) && ( 341 (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_hi != 0) 342 || (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_lo 343 != 0) ); 344 } 345 346 /** If the sign bit is set. 347 */ 348 inline bool isSignBitSet(double d) 349 { 350 return reinterpret_cast< sal_math_Double * >(&d)->inf_parts.sign != 0; 351 } 352 353 /** Set to +INF if bNegative==false or -INF if bNegative==true. 354 */ 355 inline void setInf(double * pd, bool bNegative) 356 { 357 union 358 { 359 double sd; 360 sal_math_Double md; 361 }; 362 md.w32_parts.msw = bNegative ? 0xFFF00000 : 0x7FF00000; 363 md.w32_parts.lsw = 0; 364 *pd = sd; 365 } 366 367 /** Set a QNAN. 368 */ 369 inline void setNan(double * pd) 370 { 371 union 372 { 373 double sd; 374 sal_math_Double md; 375 }; 376 md.w32_parts.msw = 0x7FFFFFFF; 377 md.w32_parts.lsw = 0xFFFFFFFF; 378 *pd = sd; 379 } 380 381 /** If a value is a valid argument for sin(), cos(), tan(). 382 383 IEEE 754 specifies that absolute values up to 2^64 (=1.844e19) for the 384 radian must be supported by trigonometric functions. Unfortunately, at 385 least on x86 architectures, the FPU doesn't generate an error pattern for 386 values >2^64 but produces erroneous results instead and sets only the 387 "invalid operation" (IM) flag in the status word :-( Thus the application 388 has to handle it itself. 389 */ 390 inline bool isValidArcArg(double d) 391 { 392 return fabs(d) 393 <= (static_cast< double >(static_cast< unsigned long >(0x80000000)) 394 * static_cast< double >(static_cast< unsigned long >(0x80000000)) 395 * 2); 396 } 397 398 /** Safe sin(), returns NAN if not valid. 399 */ 400 inline double sin(double d) 401 { 402 if ( isValidArcArg( d ) ) 403 return ::sin( d ); 404 setNan( &d ); 405 return d; 406 } 407 408 /** Safe cos(), returns NAN if not valid. 409 */ 410 inline double cos(double d) 411 { 412 if ( isValidArcArg( d ) ) 413 return ::cos( d ); 414 setNan( &d ); 415 return d; 416 } 417 418 /** Safe tan(), returns NAN if not valid. 419 */ 420 inline double tan(double d) 421 { 422 if ( isValidArcArg( d ) ) 423 return ::tan( d ); 424 setNan( &d ); 425 return d; 426 } 427 428 } 429 430 } 431 432 #endif // INCLUDED_RTL_MATH_HXX 433