Update ooo320-m1
[ooovba.git] / sal / rtl / source / math.cxx
blob731ab18c604cf3ac9000f1641401cccf29da2943
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: math.cxx,v $
10 * $Revision: 1.14 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sal.hxx"
34 #include "rtl/math.h"
36 #include "osl/diagnose.h"
37 #include "rtl/alloc.h"
38 #include "rtl/math.hxx"
39 #include "rtl/strbuf.h"
40 #include "rtl/string.h"
41 #include "rtl/ustrbuf.h"
42 #include "rtl/ustring.h"
43 #include "sal/mathconf.h"
44 #include "sal/types.h"
46 #include <algorithm>
47 #include <float.h>
48 #include <limits.h>
49 #include <math.h>
50 #include <stdlib.h>
53 static int const n10Count = 16;
54 static double const n10s[2][n10Count] = {
55 { 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8,
56 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16 },
57 { 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8,
58 1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16 }
61 // return pow(10.0,nExp) optimized for exponents in the interval [-16,16]
62 static double getN10Exp( int nExp )
64 if ( nExp < 0 )
66 if ( -nExp <= n10Count )
67 return n10s[1][-nExp-1];
68 else
69 return pow( 10.0, static_cast<double>( nExp ) );
71 else if ( nExp > 0 )
73 if ( nExp <= n10Count )
74 return n10s[0][nExp-1];
75 else
76 return pow( 10.0, static_cast<double>( nExp ) );
78 else // ( nExp == 0 )
79 return 1.0;
82 /** Approximation algorithm for erf for 0 < x < 0.65. */
83 void lcl_Erf0065( double x, double& fVal )
85 static const double pn[] = {
86 1.12837916709551256,
87 1.35894887627277916E-1,
88 4.03259488531795274E-2,
89 1.20339380863079457E-3,
90 6.49254556481904354E-5
92 static const double qn[] = {
93 1.00000000000000000,
94 4.53767041780002545E-1,
95 8.69936222615385890E-2,
96 8.49717371168693357E-3,
97 3.64915280629351082E-4
99 double fPSum = 0.0;
100 double fQSum = 0.0;
101 double fXPow = 1.0;
102 for ( unsigned int i = 0; i <= 4; ++i )
104 fPSum += pn[i]*fXPow;
105 fQSum += qn[i]*fXPow;
106 fXPow *= x*x;
108 fVal = x * fPSum / fQSum;
111 /** Approximation algorithm for erfc for 0.65 < x < 6.0. */
112 void lcl_Erfc0600( double x, double& fVal )
114 double fPSum = 0.0;
115 double fQSum = 0.0;
116 double fXPow = 1.0;
117 const double *pn;
118 const double *qn;
120 if ( x < 2.2 )
122 static const double pn22[] = {
123 9.99999992049799098E-1,
124 1.33154163936765307,
125 8.78115804155881782E-1,
126 3.31899559578213215E-1,
127 7.14193832506776067E-2,
128 7.06940843763253131E-3
130 static const double qn22[] = {
131 1.00000000000000000,
132 2.45992070144245533,
133 2.65383972869775752,
134 1.61876655543871376,
135 5.94651311286481502E-1,
136 1.26579413030177940E-1,
137 1.25304936549413393E-2
139 pn = pn22;
140 qn = qn22;
142 else /* if ( x < 6.0 ) this is true, but the compiler does not know */
144 static const double pn60[] = {
145 9.99921140009714409E-1,
146 1.62356584489366647,
147 1.26739901455873222,
148 5.81528574177741135E-1,
149 1.57289620742838702E-1,
150 2.25716982919217555E-2
152 static const double qn60[] = {
153 1.00000000000000000,
154 2.75143870676376208,
155 3.37367334657284535,
156 2.38574194785344389,
157 1.05074004614827206,
158 2.78788439273628983E-1,
159 4.00072964526861362E-2
161 pn = pn60;
162 qn = qn60;
165 for ( unsigned int i = 0; i < 6; ++i )
167 fPSum += pn[i]*fXPow;
168 fQSum += qn[i]*fXPow;
169 fXPow *= x;
171 fQSum += qn[6]*fXPow;
172 fVal = exp( -1.0*x*x )* fPSum / fQSum;
175 /** Approximation algorithm for erfc for 6.0 < x < 26.54 (but used for all
176 x > 6.0). */
177 void lcl_Erfc2654( double x, double& fVal )
179 static const double pn[] = {
180 5.64189583547756078E-1,
181 8.80253746105525775,
182 3.84683103716117320E1,
183 4.77209965874436377E1,
184 8.08040729052301677
186 static const double qn[] = {
187 1.00000000000000000,
188 1.61020914205869003E1,
189 7.54843505665954743E1,
190 1.12123870801026015E2,
191 3.73997570145040850E1
194 double fPSum = 0.0;
195 double fQSum = 0.0;
196 double fXPow = 1.0;
198 for ( unsigned int i = 0; i <= 4; ++i )
200 fPSum += pn[i]*fXPow;
201 fQSum += qn[i]*fXPow;
202 fXPow /= x*x;
204 fVal = exp(-1.0*x*x)*fPSum / (x*fQSum);
207 namespace {
209 double const nKorrVal[] = {
210 0, 9e-1, 9e-2, 9e-3, 9e-4, 9e-5, 9e-6, 9e-7, 9e-8,
211 9e-9, 9e-10, 9e-11, 9e-12, 9e-13, 9e-14, 9e-15
214 struct StringTraits
216 typedef sal_Char Char;
218 typedef rtl_String String;
220 static inline void createString(rtl_String ** pString,
221 sal_Char const * pChars, sal_Int32 nLen)
223 rtl_string_newFromStr_WithLength(pString, pChars, nLen);
226 static inline void createBuffer(rtl_String ** pBuffer,
227 sal_Int32 * pCapacity)
229 rtl_string_new_WithLength(pBuffer, *pCapacity);
232 static inline void appendChar(rtl_String ** pBuffer, sal_Int32 * pCapacity,
233 sal_Int32 * pOffset, sal_Char cChar)
235 rtl_stringbuffer_insert(pBuffer, pCapacity, *pOffset, &cChar, 1);
236 ++*pOffset;
239 static inline void appendChars(rtl_String ** pBuffer, sal_Int32 * pCapacity,
240 sal_Int32 * pOffset, sal_Char const * pChars,
241 sal_Int32 nLen)
243 rtl_stringbuffer_insert(pBuffer, pCapacity, *pOffset, pChars, nLen);
244 *pOffset += nLen;
247 static inline void appendAscii(rtl_String ** pBuffer, sal_Int32 * pCapacity,
248 sal_Int32 * pOffset, sal_Char const * pStr,
249 sal_Int32 nLen)
251 rtl_stringbuffer_insert(pBuffer, pCapacity, *pOffset, pStr, nLen);
252 *pOffset += nLen;
256 struct UStringTraits
258 typedef sal_Unicode Char;
260 typedef rtl_uString String;
262 static inline void createString(rtl_uString ** pString,
263 sal_Unicode const * pChars, sal_Int32 nLen)
265 rtl_uString_newFromStr_WithLength(pString, pChars, nLen);
268 static inline void createBuffer(rtl_uString ** pBuffer,
269 sal_Int32 * pCapacity)
271 rtl_uString_new_WithLength(pBuffer, *pCapacity);
274 static inline void appendChar(rtl_uString ** pBuffer, sal_Int32 * pCapacity,
275 sal_Int32 * pOffset, sal_Unicode cChar)
277 rtl_uStringbuffer_insert(pBuffer, pCapacity, *pOffset, &cChar, 1);
278 ++*pOffset;
281 static inline void appendChars(rtl_uString ** pBuffer,
282 sal_Int32 * pCapacity, sal_Int32 * pOffset,
283 sal_Unicode const * pChars, sal_Int32 nLen)
285 rtl_uStringbuffer_insert(pBuffer, pCapacity, *pOffset, pChars, nLen);
286 *pOffset += nLen;
289 static inline void appendAscii(rtl_uString ** pBuffer,
290 sal_Int32 * pCapacity, sal_Int32 * pOffset,
291 sal_Char const * pStr, sal_Int32 nLen)
293 rtl_uStringbuffer_insert_ascii(pBuffer, pCapacity, *pOffset, pStr,
294 nLen);
295 *pOffset += nLen;
300 // Solaris C++ 5.2 compiler has problems when "StringT ** pResult" is
301 // "typename T::String ** pResult" instead:
302 template< typename T, typename StringT >
303 inline void doubleToString(StringT ** pResult,
304 sal_Int32 * pResultCapacity, sal_Int32 nResultOffset,
305 double fValue, rtl_math_StringFormat eFormat,
306 sal_Int32 nDecPlaces, typename T::Char cDecSeparator,
307 sal_Int32 const * pGroups,
308 typename T::Char cGroupSeparator,
309 bool bEraseTrailingDecZeros)
311 static double const nRoundVal[] = {
312 5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6,
313 0.5e-7, 0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14
316 // sign adjustment, instead of testing for fValue<0.0 this will also fetch
317 // -0.0
318 bool bSign = rtl::math::isSignBitSet( fValue );
319 if( bSign )
320 fValue = -fValue;
322 if ( rtl::math::isNan( fValue ) )
324 sal_Int32 nCapacity = RTL_CONSTASCII_LENGTH("-1.#NAN");
325 if (pResultCapacity == 0)
327 pResultCapacity = &nCapacity;
328 T::createBuffer(pResult, pResultCapacity);
329 nResultOffset = 0;
332 if ( bSign )
333 T::appendAscii(pResult, pResultCapacity, &nResultOffset,
334 RTL_CONSTASCII_STRINGPARAM("-"));
335 T::appendAscii(pResult, pResultCapacity, &nResultOffset,
336 RTL_CONSTASCII_STRINGPARAM("1"));
337 T::appendChar(pResult, pResultCapacity, &nResultOffset, cDecSeparator);
338 T::appendAscii(pResult, pResultCapacity, &nResultOffset,
339 RTL_CONSTASCII_STRINGPARAM("#NAN"));
340 return;
343 bool bHuge = fValue == HUGE_VAL; // g++ 3.0.1 requires it this way...
344 if ( bHuge || rtl::math::isInf( fValue ) )
346 sal_Int32 nCapacity = RTL_CONSTASCII_LENGTH("-1.#INF");
347 if (pResultCapacity == 0)
349 pResultCapacity = &nCapacity;
350 T::createBuffer(pResult, pResultCapacity);
351 nResultOffset = 0;
354 if ( bSign )
355 T::appendAscii(pResult, pResultCapacity, &nResultOffset,
356 RTL_CONSTASCII_STRINGPARAM("-"));
357 T::appendAscii(pResult, pResultCapacity, &nResultOffset,
358 RTL_CONSTASCII_STRINGPARAM("1"));
359 T::appendChar(pResult, pResultCapacity, &nResultOffset, cDecSeparator);
360 T::appendAscii(pResult, pResultCapacity, &nResultOffset,
361 RTL_CONSTASCII_STRINGPARAM("#INF"));
362 return;
365 // find the exponent
366 int nExp = 0;
367 if ( fValue > 0.0 )
369 nExp = static_cast< int >( floor( log10( fValue ) ) );
370 fValue /= getN10Exp( nExp );
373 switch ( eFormat )
375 case rtl_math_StringFormat_Automatic :
376 { // E or F depending on exponent magnitude
377 int nPrec;
378 if ( nExp <= -15 || nExp >= 15 ) // #58531# was <-16, >16
380 nPrec = 14;
381 eFormat = rtl_math_StringFormat_E;
383 else
385 if ( nExp < 14 )
387 nPrec = 15 - nExp - 1;
388 eFormat = rtl_math_StringFormat_F;
390 else
392 nPrec = 15;
393 eFormat = rtl_math_StringFormat_F;
396 if ( nDecPlaces == rtl_math_DecimalPlaces_Max )
397 nDecPlaces = nPrec;
399 break;
400 case rtl_math_StringFormat_G :
401 { // G-Point, similar to sprintf %G
402 if ( nDecPlaces == rtl_math_DecimalPlaces_DefaultSignificance )
403 nDecPlaces = 6;
404 if ( nExp < -4 || nExp >= nDecPlaces )
406 nDecPlaces = std::max< sal_Int32 >( 1, nDecPlaces - 1 );
407 eFormat = rtl_math_StringFormat_E;
409 else
411 nDecPlaces = std::max< sal_Int32 >( 0, nDecPlaces - nExp - 1 );
412 eFormat = rtl_math_StringFormat_F;
415 break;
416 default:
417 break;
420 sal_Int32 nDigits = nDecPlaces + 1;
422 if( eFormat == rtl_math_StringFormat_F )
423 nDigits += nExp;
425 // Round the number
426 if( nDigits >= 0 )
428 if( ( fValue += nRoundVal[ nDigits > 15 ? 15 : nDigits ] ) >= 10 )
430 fValue = 1.0;
431 nExp++;
432 if( eFormat == rtl_math_StringFormat_F )
433 nDigits++;
437 static sal_Int32 const nBufMax = 256;
438 typename T::Char aBuf[nBufMax];
439 typename T::Char * pBuf;
440 sal_Int32 nBuf = static_cast< sal_Int32 >
441 ( nDigits <= 0 ? std::max< sal_Int32 >( nDecPlaces, abs(nExp) )
442 : nDigits + nDecPlaces ) + 10 + (pGroups ? abs(nDigits) * 2 : 0);
443 if ( nBuf > nBufMax )
445 pBuf = reinterpret_cast< typename T::Char * >(
446 rtl_allocateMemory(nBuf * sizeof (typename T::Char)));
447 OSL_ENSURE(pBuf != 0, "Out of memory");
449 else
450 pBuf = aBuf;
451 typename T::Char * p = pBuf;
452 if ( bSign )
453 *p++ = static_cast< typename T::Char >('-');
455 bool bHasDec = false;
457 int nDecPos;
458 // Check for F format and number < 1
459 if( eFormat == rtl_math_StringFormat_F )
461 if( nExp < 0 )
463 *p++ = static_cast< typename T::Char >('0');
464 if ( nDecPlaces > 0 )
466 *p++ = cDecSeparator;
467 bHasDec = true;
469 sal_Int32 i = ( nDigits <= 0 ? nDecPlaces : -nExp - 1 );
470 while( (i--) > 0 )
471 *p++ = static_cast< typename T::Char >('0');
472 nDecPos = 0;
474 else
475 nDecPos = nExp + 1;
477 else
478 nDecPos = 1;
480 int nGrouping = 0, nGroupSelector = 0, nGroupExceed = 0;
481 if ( nDecPos > 1 && pGroups && pGroups[0] && cGroupSeparator )
483 while ( nGrouping + pGroups[nGroupSelector] < nDecPos )
485 nGrouping += pGroups[ nGroupSelector ];
486 if ( pGroups[nGroupSelector+1] )
488 if ( nGrouping + pGroups[nGroupSelector+1] >= nDecPos )
489 break; // while
490 ++nGroupSelector;
492 else if ( !nGroupExceed )
493 nGroupExceed = nGrouping;
497 // print the number
498 if( nDigits > 0 )
500 for ( int i = 0; ; i++ )
502 if( i < 15 )
504 int nDigit;
505 if (nDigits-1 == 0 && i > 0 && i < 14)
506 nDigit = static_cast< int >( floor( fValue
507 + nKorrVal[15-i] ) );
508 else
509 nDigit = static_cast< int >( fValue + 1E-15 );
510 if (nDigit >= 10)
511 { // after-treatment of up-rounding to the next decade
512 sal_Int32 sLen = static_cast< long >(p-pBuf)-1;
513 if (sLen == -1)
515 p = pBuf;
516 if ( eFormat == rtl_math_StringFormat_F )
518 *p++ = static_cast< typename T::Char >('1');
519 *p++ = static_cast< typename T::Char >('0');
521 else
523 *p++ = static_cast< typename T::Char >('1');
524 *p++ = cDecSeparator;
525 *p++ = static_cast< typename T::Char >('0');
526 nExp++;
527 bHasDec = true;
530 else
532 for (sal_Int32 j = sLen; j >= 0; j--)
534 typename T::Char cS = pBuf[j];
535 if (cS != cDecSeparator)
537 if ( cS != static_cast< typename T::Char >('9'))
539 pBuf[j] = ++cS;
540 j = -1; // break loop
542 else
544 pBuf[j]
545 = static_cast< typename T::Char >('0');
546 if (j == 0)
548 if ( eFormat == rtl_math_StringFormat_F)
549 { // insert '1'
550 typename T::Char * px = p++;
551 while ( pBuf < px )
553 *px = *(px-1);
554 px--;
556 pBuf[0] = static_cast<
557 typename T::Char >('1');
559 else
561 pBuf[j] = static_cast<
562 typename T::Char >('1');
563 nExp++;
569 *p++ = static_cast< typename T::Char >('0');
571 fValue = 0.0;
573 else
575 *p++ = static_cast< typename T::Char >(
576 nDigit + static_cast< typename T::Char >('0') );
577 fValue = ( fValue - nDigit ) * 10.0;
580 else
581 *p++ = static_cast< typename T::Char >('0');
582 if( !--nDigits )
583 break; // for
584 if( nDecPos )
586 if( !--nDecPos )
588 *p++ = cDecSeparator;
589 bHasDec = true;
591 else if ( nDecPos == nGrouping )
593 *p++ = cGroupSeparator;
594 nGrouping -= pGroups[ nGroupSelector ];
595 if ( nGroupSelector && nGrouping < nGroupExceed )
596 --nGroupSelector;
602 if ( !bHasDec && eFormat == rtl_math_StringFormat_F )
603 { // nDecPlaces < 0 did round the value
604 while ( --nDecPos > 0 )
605 { // fill before decimal point
606 if ( nDecPos == nGrouping )
608 *p++ = cGroupSeparator;
609 nGrouping -= pGroups[ nGroupSelector ];
610 if ( nGroupSelector && nGrouping < nGroupExceed )
611 --nGroupSelector;
613 *p++ = static_cast< typename T::Char >('0');
617 if ( bEraseTrailingDecZeros && bHasDec && p > pBuf )
619 while ( *(p-1) == static_cast< typename T::Char >('0') )
620 p--;
621 if ( *(p-1) == cDecSeparator )
622 p--;
625 // Print the exponent ('E', followed by '+' or '-', followed by exactly
626 // three digits). The code in rtl_[u]str_valueOf{Float|Double} relies on
627 // this format.
628 if( eFormat == rtl_math_StringFormat_E )
630 if ( p == pBuf )
631 *p++ = static_cast< typename T::Char >('1');
632 // maybe no nDigits if nDecPlaces < 0
633 *p++ = static_cast< typename T::Char >('E');
634 if( nExp < 0 )
636 nExp = -nExp;
637 *p++ = static_cast< typename T::Char >('-');
639 else
640 *p++ = static_cast< typename T::Char >('+');
641 // if (nExp >= 100 )
642 *p++ = static_cast< typename T::Char >(
643 nExp / 100 + static_cast< typename T::Char >('0') );
644 nExp %= 100;
645 *p++ = static_cast< typename T::Char >(
646 nExp / 10 + static_cast< typename T::Char >('0') );
647 *p++ = static_cast< typename T::Char >(
648 nExp % 10 + static_cast< typename T::Char >('0') );
651 if (pResultCapacity == 0)
652 T::createString(pResult, pBuf, p - pBuf);
653 else
654 T::appendChars(pResult, pResultCapacity, &nResultOffset, pBuf,
655 p - pBuf);
657 if ( pBuf != &aBuf[0] )
658 rtl_freeMemory(pBuf);
663 void SAL_CALL rtl_math_doubleToString(rtl_String ** pResult,
664 sal_Int32 * pResultCapacity,
665 sal_Int32 nResultOffset, double fValue,
666 rtl_math_StringFormat eFormat,
667 sal_Int32 nDecPlaces,
668 sal_Char cDecSeparator,
669 sal_Int32 const * pGroups,
670 sal_Char cGroupSeparator,
671 sal_Bool bEraseTrailingDecZeros)
672 SAL_THROW_EXTERN_C()
674 doubleToString< StringTraits, StringTraits::String >(
675 pResult, pResultCapacity, nResultOffset, fValue, eFormat, nDecPlaces,
676 cDecSeparator, pGroups, cGroupSeparator, bEraseTrailingDecZeros);
679 void SAL_CALL rtl_math_doubleToUString(rtl_uString ** pResult,
680 sal_Int32 * pResultCapacity,
681 sal_Int32 nResultOffset, double fValue,
682 rtl_math_StringFormat eFormat,
683 sal_Int32 nDecPlaces,
684 sal_Unicode cDecSeparator,
685 sal_Int32 const * pGroups,
686 sal_Unicode cGroupSeparator,
687 sal_Bool bEraseTrailingDecZeros)
688 SAL_THROW_EXTERN_C()
690 doubleToString< UStringTraits, UStringTraits::String >(
691 pResult, pResultCapacity, nResultOffset, fValue, eFormat, nDecPlaces,
692 cDecSeparator, pGroups, cGroupSeparator, bEraseTrailingDecZeros);
696 namespace {
698 // if nExp * 10 + nAdd would result in overflow
699 inline bool long10Overflow( long& nExp, int nAdd )
701 if ( nExp > (LONG_MAX/10)
702 || (nExp == (LONG_MAX/10) && nAdd > (LONG_MAX%10)) )
704 nExp = LONG_MAX;
705 return true;
707 return false;
710 // We are only concerned about ASCII arabic numerical digits here
711 template< typename CharT >
712 inline bool isDigit( CharT c )
714 return 0x30 <= c && c <= 0x39;
717 template< typename CharT >
718 inline double stringToDouble(CharT const * pBegin, CharT const * pEnd,
719 CharT cDecSeparator, CharT cGroupSeparator,
720 rtl_math_ConversionStatus * pStatus,
721 CharT const ** pParsedEnd)
723 double fVal = 0.0;
724 rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
726 CharT const * p0 = pBegin;
727 while (p0 != pEnd && (*p0 == CharT(' ') || *p0 == CharT('\t')))
728 ++p0;
729 bool bSign;
730 if (p0 != pEnd && *p0 == CharT('-'))
732 bSign = true;
733 ++p0;
735 else
737 bSign = false;
738 if (p0 != pEnd && *p0 == CharT('+'))
739 ++p0;
741 CharT const * p = p0;
743 // leading zeros and group separators may be safely ignored
744 while (p != pEnd && (*p == CharT('0') || *p == cGroupSeparator))
745 ++p;
747 long nValExp = 0; // carry along exponent of mantissa
749 // integer part of mantissa
750 for (; p != pEnd; ++p)
752 CharT c = *p;
753 if (isDigit(c))
755 fVal = fVal * 10.0 + static_cast< double >( c - CharT('0') );
756 ++nValExp;
758 else if (c != cGroupSeparator)
759 break;
762 // fraction part of mantissa
763 if (p != pEnd && *p == cDecSeparator)
765 ++p;
766 double fFrac = 0.0;
767 long nFracExp = 0;
768 while (p != pEnd && *p == CharT('0'))
770 --nFracExp;
771 ++p;
773 if ( nValExp == 0 )
774 nValExp = nFracExp - 1; // no integer part => fraction exponent
775 // one decimal digit needs ld(10) ~= 3.32 bits
776 static const int nSigs = (DBL_MANT_DIG / 3) + 1;
777 int nDigs = 0;
778 for (; p != pEnd; ++p)
780 CharT c = *p;
781 if (!isDigit(c))
782 break;
783 if ( nDigs < nSigs )
784 { // further digits (more than nSigs) don't have any significance
785 fFrac = fFrac * 10.0 + static_cast< double >( c - CharT('0') );
786 --nFracExp;
787 ++nDigs;
790 if ( fFrac != 0.0 )
791 fVal += rtl::math::pow10Exp( fFrac, nFracExp );
792 else if ( nValExp < 0 )
793 nValExp = 0; // no digit other than 0 after decimal point
796 if ( nValExp > 0 )
797 --nValExp; // started with offset +1 at the first mantissa digit
799 // Exponent
800 if (p != p0 && p != pEnd && (*p == CharT('E') || *p == CharT('e')))
802 ++p;
803 bool bExpSign;
804 if (p != pEnd && *p == CharT('-'))
806 bExpSign = true;
807 ++p;
809 else
811 bExpSign = false;
812 if (p != pEnd && *p == CharT('+'))
813 ++p;
815 if ( fVal == 0.0 )
816 { // no matter what follows, zero stays zero, but carry on the offset
817 while (p != pEnd && isDigit(*p))
818 ++p;
820 else
822 bool bOverFlow = false;
823 long nExp = 0;
824 for (; p != pEnd; ++p)
826 CharT c = *p;
827 if (!isDigit(c))
828 break;
829 int i = c - CharT('0');
830 if ( long10Overflow( nExp, i ) )
831 bOverFlow = true;
832 else
833 nExp = nExp * 10 + i;
835 if ( nExp )
837 if ( bExpSign )
838 nExp = -nExp;
839 long nAllExp = ( bOverFlow ? 0 : nExp + nValExp );
840 if ( nAllExp > DBL_MAX_10_EXP || (bOverFlow && !bExpSign) )
841 { // overflow
842 fVal = HUGE_VAL;
843 eStatus = rtl_math_ConversionStatus_OutOfRange;
845 else if ( nAllExp < DBL_MIN_10_EXP || (bOverFlow && bExpSign) )
846 { // underflow
847 fVal = 0.0;
848 eStatus = rtl_math_ConversionStatus_OutOfRange;
850 else if ( nExp > DBL_MAX_10_EXP || nExp < DBL_MIN_10_EXP )
851 { // compensate exponents
852 fVal = rtl::math::pow10Exp( fVal, -nValExp );
853 fVal = rtl::math::pow10Exp( fVal, nAllExp );
855 else
856 fVal = rtl::math::pow10Exp( fVal, nExp ); // normal
860 else if (p - p0 == 2 && p != pEnd && p[0] == CharT('#')
861 && p[-1] == cDecSeparator && p[-2] == CharT('1'))
863 if (pEnd - p >= 4 && p[1] == CharT('I') && p[2] == CharT('N')
864 && p[3] == CharT('F'))
866 // "1.#INF", "+1.#INF", "-1.#INF"
867 p += 4;
868 fVal = HUGE_VAL;
869 eStatus = rtl_math_ConversionStatus_OutOfRange;
870 // Eat any further digits:
871 while (p != pEnd && isDigit(*p))
872 ++p;
874 else if (pEnd - p >= 4 && p[1] == CharT('N') && p[2] == CharT('A')
875 && p[3] == CharT('N'))
877 // "1.#NAN", "+1.#NAN", "-1.#NAN"
878 p += 4;
879 rtl::math::setNan( &fVal );
880 if (bSign)
882 reinterpret_cast< sal_math_Double * >(&fVal)->w32_parts.msw
883 |= 0x80000000; // create negative NaN
884 bSign = false; // don't negate again
886 // Eat any further digits:
887 while (p != pEnd && isDigit(*p))
888 ++p;
892 // overflow also if more than DBL_MAX_10_EXP digits without decimal
893 // separator, or 0. and more than DBL_MIN_10_EXP digits, ...
894 bool bHuge = fVal == HUGE_VAL; // g++ 3.0.1 requires it this way...
895 if ( bHuge )
896 eStatus = rtl_math_ConversionStatus_OutOfRange;
898 if ( bSign )
899 fVal = -fVal;
901 if (pStatus != 0)
902 *pStatus = eStatus;
903 if (pParsedEnd != 0)
904 *pParsedEnd = p;
906 return fVal;
911 double SAL_CALL rtl_math_stringToDouble(sal_Char const * pBegin,
912 sal_Char const * pEnd,
913 sal_Char cDecSeparator,
914 sal_Char cGroupSeparator,
915 rtl_math_ConversionStatus * pStatus,
916 sal_Char const ** pParsedEnd)
917 SAL_THROW_EXTERN_C()
919 return stringToDouble(pBegin, pEnd, cDecSeparator, cGroupSeparator, pStatus,
920 pParsedEnd);
923 double SAL_CALL rtl_math_uStringToDouble(sal_Unicode const * pBegin,
924 sal_Unicode const * pEnd,
925 sal_Unicode cDecSeparator,
926 sal_Unicode cGroupSeparator,
927 rtl_math_ConversionStatus * pStatus,
928 sal_Unicode const ** pParsedEnd)
929 SAL_THROW_EXTERN_C()
931 return stringToDouble(pBegin, pEnd, cDecSeparator, cGroupSeparator, pStatus,
932 pParsedEnd);
935 double SAL_CALL rtl_math_round(double fValue, int nDecPlaces,
936 enum rtl_math_RoundingMode eMode)
937 SAL_THROW_EXTERN_C()
939 OSL_ASSERT(nDecPlaces >= -20 && nDecPlaces <= 20);
941 if ( fValue == 0.0 )
942 return fValue;
944 // sign adjustment
945 bool bSign = rtl::math::isSignBitSet( fValue );
946 if ( bSign )
947 fValue = -fValue;
949 double fFac = 0;
950 if ( nDecPlaces != 0 )
952 // max 20 decimals, we don't have unlimited precision
953 // #38810# and no overflow on fValue*=fFac
954 if ( nDecPlaces < -20 || 20 < nDecPlaces || fValue > (DBL_MAX / 1e20) )
955 return bSign ? -fValue : fValue;
957 fFac = getN10Exp( nDecPlaces );
958 fValue *= fFac;
960 //else //! uninitialized fFac, not needed
962 switch ( eMode )
964 case rtl_math_RoundingMode_Corrected :
966 int nExp; // exponent for correction
967 if ( fValue > 0.0 )
968 nExp = static_cast<int>( floor( log10( fValue ) ) );
969 else
970 nExp = 0;
971 int nIndex = 15 - nExp;
972 if ( nIndex > 15 )
973 nIndex = 15;
974 else if ( nIndex <= 1 )
975 nIndex = 0;
976 fValue = floor( fValue + 0.5 + nKorrVal[nIndex] );
978 break;
979 case rtl_math_RoundingMode_Down :
980 fValue = rtl::math::approxFloor( fValue );
981 break;
982 case rtl_math_RoundingMode_Up :
983 fValue = rtl::math::approxCeil( fValue );
984 break;
985 case rtl_math_RoundingMode_Floor :
986 fValue = bSign ? rtl::math::approxCeil( fValue )
987 : rtl::math::approxFloor( fValue );
988 break;
989 case rtl_math_RoundingMode_Ceiling :
990 fValue = bSign ? rtl::math::approxFloor( fValue )
991 : rtl::math::approxCeil( fValue );
992 break;
993 case rtl_math_RoundingMode_HalfDown :
995 double f = floor( fValue );
996 fValue = ((fValue - f) <= 0.5) ? f : ceil( fValue );
998 break;
999 case rtl_math_RoundingMode_HalfUp :
1001 double f = floor( fValue );
1002 fValue = ((fValue - f) < 0.5) ? f : ceil( fValue );
1004 break;
1005 case rtl_math_RoundingMode_HalfEven :
1006 #if defined FLT_ROUNDS
1008 Use fast version. FLT_ROUNDS may be defined to a function by some compilers!
1010 DBL_EPSILON is the smallest fractional number which can be represented,
1011 its reciprocal is therefore the smallest number that cannot have a
1012 fractional part. Once you add this reciprocal to `x', its fractional part
1013 is stripped off. Simply subtracting the reciprocal back out returns `x'
1014 without its fractional component.
1015 Simple, clever, and elegant - thanks to Ross Cottrell, the original author,
1016 who placed it into public domain.
1018 volatile: prevent compiler from being too smart
1020 if ( FLT_ROUNDS == 1 )
1022 volatile double x = fValue + 1.0 / DBL_EPSILON;
1023 fValue = x - 1.0 / DBL_EPSILON;
1025 else
1026 #endif // FLT_ROUNDS
1028 double f = floor( fValue );
1029 if ( (fValue - f) != 0.5 )
1030 fValue = floor( fValue + 0.5 );
1031 else
1033 double g = f / 2.0;
1034 fValue = (g == floor( g )) ? f : (f + 1.0);
1037 break;
1038 default:
1039 OSL_ASSERT(false);
1040 break;
1043 if ( nDecPlaces != 0 )
1044 fValue /= fFac;
1046 return bSign ? -fValue : fValue;
1050 double SAL_CALL rtl_math_pow10Exp(double fValue, int nExp) SAL_THROW_EXTERN_C()
1052 return fValue * getN10Exp( nExp );
1056 double SAL_CALL rtl_math_approxValue( double fValue ) SAL_THROW_EXTERN_C()
1058 if (fValue == 0.0 || fValue == HUGE_VAL || !::rtl::math::isFinite( fValue))
1059 // We don't handle these conditions. Bail out.
1060 return fValue;
1062 double fOrigValue = fValue;
1064 bool bSign = ::rtl::math::isSignBitSet( fValue);
1065 if (bSign)
1066 fValue = -fValue;
1068 int nExp = static_cast<int>( floor( log10( fValue)));
1069 nExp = 14 - nExp;
1070 double fExpValue = getN10Exp( nExp);
1072 fValue *= fExpValue;
1073 // If the original value was near DBL_MIN we got an overflow. Restore and
1074 // bail out.
1075 if (!rtl::math::isFinite( fValue))
1076 return fOrigValue;
1077 fValue = rtl_math_round( fValue, 0, rtl_math_RoundingMode_Corrected);
1078 fValue /= fExpValue;
1079 // If the original value was near DBL_MAX we got an overflow. Restore and
1080 // bail out.
1081 if (!rtl::math::isFinite( fValue))
1082 return fOrigValue;
1084 return bSign ? -fValue : fValue;
1088 double SAL_CALL rtl_math_expm1( double fValue ) SAL_THROW_EXTERN_C()
1090 double fe = exp( fValue );
1091 if (fe == 1.0)
1092 return fValue;
1093 if (fe-1.0 == -1.0)
1094 return -1.0;
1095 return (fe-1.0) * fValue / log(fe);
1099 double SAL_CALL rtl_math_log1p( double fValue ) SAL_THROW_EXTERN_C()
1101 // Use volatile because a compiler may be too smart "optimizing" the
1102 // condition such that in certain cases the else path was called even if
1103 // (fp==1.0) was true, where the term (fp-1.0) then resulted in 0.0 and
1104 // hence the entire expression resulted in NaN.
1105 // Happened with g++ 3.4.1 and an input value of 9.87E-18
1106 volatile double fp = 1.0 + fValue;
1107 if (fp == 1.0)
1108 return fValue;
1109 else
1110 return log(fp) * fValue / (fp-1.0);
1114 double SAL_CALL rtl_math_atanh( double fValue ) SAL_THROW_EXTERN_C()
1116 return 0.5 * rtl_math_log1p( 2.0 * fValue / (1.0-fValue) );
1120 /** Parent error function (erf) that calls different algorithms based on the
1121 value of x. It takes care of cases where x is negative as erf is an odd
1122 function i.e. erf(-x) = -erf(x).
1124 Kramer, W., and Blomquist, F., 2000, Algorithms with Guaranteed Error Bounds
1125 for the Error Function and the Complementary Error Function
1127 http://www.math.uni-wuppertal.de/wrswt/literatur_en.html
1129 @author Kohei Yoshida <kohei@openoffice.org>
1131 @see #i55735#
1133 double SAL_CALL rtl_math_erf( double x ) SAL_THROW_EXTERN_C()
1135 if( x == 0.0 )
1136 return 0.0;
1138 bool bNegative = false;
1139 if ( x < 0.0 )
1141 x = fabs( x );
1142 bNegative = true;
1145 double fErf = 1.0;
1146 if ( x < 1.0e-10 )
1147 fErf = (double) (x*1.1283791670955125738961589031215452L);
1148 else if ( x < 0.65 )
1149 lcl_Erf0065( x, fErf );
1150 else
1151 fErf = 1.0 - rtl_math_erfc( x );
1153 if ( bNegative )
1154 fErf *= -1.0;
1156 return fErf;
1160 /** Parent complementary error function (erfc) that calls different algorithms
1161 based on the value of x. It takes care of cases where x is negative as erfc
1162 satisfies relationship erfc(-x) = 2 - erfc(x). See the comment for Erf(x)
1163 for the source publication.
1165 @author Kohei Yoshida <kohei@openoffice.org>
1167 @see #i55735#, moved from module scaddins (#i97091#)
1170 double SAL_CALL rtl_math_erfc( double x ) SAL_THROW_EXTERN_C()
1172 if ( x == 0.0 )
1173 return 1.0;
1175 bool bNegative = false;
1176 if ( x < 0.0 )
1178 x = fabs( x );
1179 bNegative = true;
1182 double fErfc = 0.0;
1183 if ( x >= 0.65 )
1185 if ( x < 6.0 )
1186 lcl_Erfc0600( x, fErfc );
1187 else
1188 lcl_Erfc2654( x, fErfc );
1190 else
1191 fErfc = 1.0 - rtl_math_erf( x );
1193 if ( bNegative )
1194 fErfc = 2.0 - fErfc;
1196 return fErfc;
1199 /** improved accuracy of asinh for |x| large and for x near zero
1200 @see #i97605#
1202 double SAL_CALL rtl_math_asinh( double fX ) SAL_THROW_EXTERN_C()
1204 double fSign = 1.0;
1205 if ( fX == 0.0 )
1206 return 0.0;
1207 else
1209 if ( fX < 0.0 )
1211 fX = - fX;
1212 fSign = -1.0;
1214 if ( fX < 0.125 )
1215 return fSign * rtl_math_log1p( fX + fX*fX / (1.0 + sqrt( 1.0 + fX*fX)));
1216 else if ( fX < 1.25e7 )
1217 return fSign * log( fX + sqrt( 1.0 + fX*fX));
1218 else
1219 return fSign * log( 2.0*fX);
1223 /** improved accuracy of acosh for x large and for x near 1
1224 @see #i97605#
1226 double SAL_CALL rtl_math_acosh( double fX ) SAL_THROW_EXTERN_C()
1228 volatile double fZ = fX - 1.0;
1229 if ( fX < 1.0 )
1231 double fResult;
1232 ::rtl::math::setNan( &fResult );
1233 return fResult;
1235 else if ( fX == 1.0 )
1236 return 0.0;
1237 else if ( fX < 1.1 )
1238 return rtl_math_log1p( fZ + sqrt( fZ*fZ + 2.0*fZ));
1239 else if ( fX < 1.25e7 )
1240 return log( fX + sqrt( fX*fX - 1.0));
1241 else
1242 return log( 2.0*fX);