1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
23 #include "osl/diagnose.h"
24 #include "rtl/alloc.h"
25 #include "rtl/character.hxx"
26 #include "rtl/math.hxx"
27 #include "rtl/strbuf.h"
28 #include "rtl/string.h"
29 #include "rtl/ustrbuf.h"
30 #include "rtl/ustring.h"
31 #include "sal/mathconf.h"
32 #include "sal/types.h"
41 static int const n10Count
= 16;
42 static double const n10s
[2][n10Count
] = {
43 { 1e1
, 1e2
, 1e3
, 1e4
, 1e5
, 1e6
, 1e7
, 1e8
,
44 1e9
, 1e10
, 1e11
, 1e12
, 1e13
, 1e14
, 1e15
, 1e16
},
45 { 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8,
46 1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16 }
49 // return pow(10.0,nExp) optimized for exponents in the interval [-16,16]
50 static double getN10Exp( int nExp
)
54 // && -nExp > 0 necessary for std::numeric_limits<int>::min()
55 // because -nExp = nExp
56 if ( -nExp
<= n10Count
&& -nExp
> 0 )
57 return n10s
[1][-nExp
-1];
59 return pow( 10.0, static_cast<double>( nExp
) );
63 if ( nExp
<= n10Count
)
64 return n10s
[0][nExp
-1];
66 return pow( 10.0, static_cast<double>( nExp
) );
72 /** Approximation algorithm for erf for 0 < x < 0.65. */
73 static void lcl_Erf0065( double x
, double& fVal
)
75 static const double pn
[] = {
77 1.35894887627277916E-1,
78 4.03259488531795274E-2,
79 1.20339380863079457E-3,
80 6.49254556481904354E-5
82 static const double qn
[] = {
84 4.53767041780002545E-1,
85 8.69936222615385890E-2,
86 8.49717371168693357E-3,
87 3.64915280629351082E-4
92 for ( unsigned int i
= 0; i
<= 4; ++i
)
98 fVal
= x
* fPSum
/ fQSum
;
101 /** Approximation algorithm for erfc for 0.65 < x < 6.0. */
102 static void lcl_Erfc0600( double x
, double& fVal
)
112 static const double pn22
[] = {
113 9.99999992049799098E-1,
115 8.78115804155881782E-1,
116 3.31899559578213215E-1,
117 7.14193832506776067E-2,
118 7.06940843763253131E-3
120 static const double qn22
[] = {
125 5.94651311286481502E-1,
126 1.26579413030177940E-1,
127 1.25304936549413393E-2
132 else /* if ( x < 6.0 ) this is true, but the compiler does not know */
134 static const double pn60
[] = {
135 9.99921140009714409E-1,
138 5.81528574177741135E-1,
139 1.57289620742838702E-1,
140 2.25716982919217555E-2
142 static const double qn60
[] = {
148 2.78788439273628983E-1,
149 4.00072964526861362E-2
155 for ( unsigned int i
= 0; i
< 6; ++i
)
157 fPSum
+= pn
[i
]*fXPow
;
158 fQSum
+= qn
[i
]*fXPow
;
161 fQSum
+= qn
[6]*fXPow
;
162 fVal
= exp( -1.0*x
*x
)* fPSum
/ fQSum
;
165 /** Approximation algorithm for erfc for 6.0 < x < 26.54 (but used for all
167 static void lcl_Erfc2654( double x
, double& fVal
)
169 static const double pn
[] = {
170 5.64189583547756078E-1,
172 3.84683103716117320E1
,
173 4.77209965874436377E1
,
176 static const double qn
[] = {
178 1.61020914205869003E1
,
179 7.54843505665954743E1
,
180 1.12123870801026015E2
,
181 3.73997570145040850E1
188 for ( unsigned int i
= 0; i
<= 4; ++i
)
190 fPSum
+= pn
[i
]*fXPow
;
191 fQSum
+= qn
[i
]*fXPow
;
194 fVal
= exp(-1.0*x
*x
)*fPSum
/ (x
*fQSum
);
199 double const nKorrVal
[] = {
200 0, 9e-1, 9e-2, 9e-3, 9e-4, 9e-5, 9e-6, 9e-7, 9e-8,
201 9e-9, 9e-10, 9e-11, 9e-12, 9e-13, 9e-14, 9e-15
206 typedef sal_Char Char
;
208 typedef rtl_String String
;
210 static inline void createString(rtl_String
** pString
,
211 sal_Char
const * pChars
, sal_Int32 nLen
)
213 rtl_string_newFromStr_WithLength(pString
, pChars
, nLen
);
216 static inline void createBuffer(rtl_String
** pBuffer
,
217 sal_Int32
* pCapacity
)
219 rtl_string_new_WithLength(pBuffer
, *pCapacity
);
222 static inline void appendChar(rtl_String
** pBuffer
, sal_Int32
* pCapacity
,
223 sal_Int32
* pOffset
, sal_Char cChar
)
225 rtl_stringbuffer_insert(pBuffer
, pCapacity
, *pOffset
, &cChar
, 1);
229 static inline void appendChars(rtl_String
** pBuffer
, sal_Int32
* pCapacity
,
230 sal_Int32
* pOffset
, sal_Char
const * pChars
,
233 rtl_stringbuffer_insert(pBuffer
, pCapacity
, *pOffset
, pChars
, nLen
);
237 static inline void appendAscii(rtl_String
** pBuffer
, sal_Int32
* pCapacity
,
238 sal_Int32
* pOffset
, sal_Char
const * pStr
,
241 rtl_stringbuffer_insert(pBuffer
, pCapacity
, *pOffset
, pStr
, nLen
);
248 typedef sal_Unicode Char
;
250 typedef rtl_uString String
;
252 static inline void createString(rtl_uString
** pString
,
253 sal_Unicode
const * pChars
, sal_Int32 nLen
)
255 rtl_uString_newFromStr_WithLength(pString
, pChars
, nLen
);
258 static inline void createBuffer(rtl_uString
** pBuffer
,
259 sal_Int32
* pCapacity
)
261 rtl_uString_new_WithLength(pBuffer
, *pCapacity
);
264 static inline void appendChar(rtl_uString
** pBuffer
, sal_Int32
* pCapacity
,
265 sal_Int32
* pOffset
, sal_Unicode cChar
)
267 rtl_uStringbuffer_insert(pBuffer
, pCapacity
, *pOffset
, &cChar
, 1);
271 static inline void appendChars(rtl_uString
** pBuffer
,
272 sal_Int32
* pCapacity
, sal_Int32
* pOffset
,
273 sal_Unicode
const * pChars
, sal_Int32 nLen
)
275 rtl_uStringbuffer_insert(pBuffer
, pCapacity
, *pOffset
, pChars
, nLen
);
279 static inline void appendAscii(rtl_uString
** pBuffer
,
280 sal_Int32
* pCapacity
, sal_Int32
* pOffset
,
281 sal_Char
const * pStr
, sal_Int32 nLen
)
283 rtl_uStringbuffer_insert_ascii(pBuffer
, pCapacity
, *pOffset
, pStr
,
290 // Solaris C++ 5.2 compiler has problems when "StringT ** pResult" is
291 // "typename T::String ** pResult" instead:
292 template< typename T
, typename StringT
>
293 inline void doubleToString(StringT
** pResult
,
294 sal_Int32
* pResultCapacity
, sal_Int32 nResultOffset
,
295 double fValue
, rtl_math_StringFormat eFormat
,
296 sal_Int32 nDecPlaces
, typename
T::Char cDecSeparator
,
297 sal_Int32
const * pGroups
,
298 typename
T::Char cGroupSeparator
,
299 bool bEraseTrailingDecZeros
)
301 static double const nRoundVal
[] = {
302 5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6,
303 0.5e-7, 0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14
306 // sign adjustment, instead of testing for fValue<0.0 this will also fetch
308 bool bSign
= rtl::math::isSignBitSet( fValue
);
312 if ( rtl::math::isNan( fValue
) )
314 // #i112652# XMLSchema-2
315 sal_Int32 nCapacity
= RTL_CONSTASCII_LENGTH("NaN");
316 if (pResultCapacity
== 0)
318 pResultCapacity
= &nCapacity
;
319 T::createBuffer(pResult
, pResultCapacity
);
322 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
,
323 RTL_CONSTASCII_STRINGPARAM("NaN"));
328 bool bHuge
= fValue
== HUGE_VAL
; // g++ 3.0.1 requires it this way...
329 if ( bHuge
|| rtl::math::isInf( fValue
) )
331 // #i112652# XMLSchema-2
332 sal_Int32 nCapacity
= RTL_CONSTASCII_LENGTH("-INF");
333 if (pResultCapacity
== 0)
335 pResultCapacity
= &nCapacity
;
336 T::createBuffer(pResult
, pResultCapacity
);
340 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
,
341 RTL_CONSTASCII_STRINGPARAM("-"));
342 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
,
343 RTL_CONSTASCII_STRINGPARAM("INF"));
352 nExp
= static_cast< int >( floor( log10( fValue
) ) );
353 fValue
/= getN10Exp( nExp
);
358 case rtl_math_StringFormat_Automatic
:
359 { // E or F depending on exponent magnitude
361 if ( nExp
<= -15 || nExp
>= 15 ) // #58531# was <-16, >16
364 eFormat
= rtl_math_StringFormat_E
;
370 nPrec
= 15 - nExp
- 1;
371 eFormat
= rtl_math_StringFormat_F
;
376 eFormat
= rtl_math_StringFormat_F
;
379 if ( nDecPlaces
== rtl_math_DecimalPlaces_Max
)
383 case rtl_math_StringFormat_G
:
384 { // G-Point, similar to sprintf %G
385 if ( nDecPlaces
== rtl_math_DecimalPlaces_DefaultSignificance
)
387 if ( nExp
< -4 || nExp
>= nDecPlaces
)
389 nDecPlaces
= std::max
< sal_Int32
>( 1, nDecPlaces
- 1 );
390 eFormat
= rtl_math_StringFormat_E
;
394 nDecPlaces
= std::max
< sal_Int32
>( 0, nDecPlaces
- nExp
- 1 );
395 eFormat
= rtl_math_StringFormat_F
;
403 sal_Int32 nDigits
= nDecPlaces
+ 1;
405 if( eFormat
== rtl_math_StringFormat_F
)
411 if( ( fValue
+= nRoundVal
[ nDigits
> 15 ? 15 : nDigits
] ) >= 10 )
415 if( eFormat
== rtl_math_StringFormat_F
)
420 static sal_Int32
const nBufMax
= 256;
421 typename
T::Char aBuf
[nBufMax
];
422 typename
T::Char
* pBuf
;
423 sal_Int32 nBuf
= static_cast< sal_Int32
>
424 ( nDigits
<= 0 ? std::max
< sal_Int32
>( nDecPlaces
, abs(nExp
) )
425 : nDigits
+ nDecPlaces
) + 10 + (pGroups
? abs(nDigits
) * 2 : 0);
426 if ( nBuf
> nBufMax
)
428 pBuf
= reinterpret_cast< typename
T::Char
* >(
429 rtl_allocateMemory(nBuf
* sizeof (typename
T::Char
)));
430 OSL_ENSURE(pBuf
!= 0, "Out of memory");
434 typename
T::Char
* p
= pBuf
;
436 *p
++ = static_cast< typename
T::Char
>('-');
438 bool bHasDec
= false;
441 // Check for F format and number < 1
442 if( eFormat
== rtl_math_StringFormat_F
)
446 *p
++ = static_cast< typename
T::Char
>('0');
447 if ( nDecPlaces
> 0 )
449 *p
++ = cDecSeparator
;
452 sal_Int32 i
= ( nDigits
<= 0 ? nDecPlaces
: -nExp
- 1 );
454 *p
++ = static_cast< typename
T::Char
>('0');
463 int nGrouping
= 0, nGroupSelector
= 0, nGroupExceed
= 0;
464 if ( nDecPos
> 1 && pGroups
&& pGroups
[0] && cGroupSeparator
)
466 while ( nGrouping
+ pGroups
[nGroupSelector
] < nDecPos
)
468 nGrouping
+= pGroups
[ nGroupSelector
];
469 if ( pGroups
[nGroupSelector
+1] )
471 if ( nGrouping
+ pGroups
[nGroupSelector
+1] >= nDecPos
)
475 else if ( !nGroupExceed
)
476 nGroupExceed
= nGrouping
;
483 for ( int i
= 0; ; i
++ )
488 if (nDigits
-1 == 0 && i
> 0 && i
< 14)
489 nDigit
= static_cast< int >( floor( fValue
490 + nKorrVal
[15-i
] ) );
492 nDigit
= static_cast< int >( fValue
+ 1E-15 );
494 { // after-treatment of up-rounding to the next decade
495 sal_Int32 sLen
= static_cast< long >(p
-pBuf
)-1;
499 if ( eFormat
== rtl_math_StringFormat_F
)
501 *p
++ = static_cast< typename
T::Char
>('1');
502 *p
++ = static_cast< typename
T::Char
>('0');
506 *p
++ = static_cast< typename
T::Char
>('1');
507 *p
++ = cDecSeparator
;
508 *p
++ = static_cast< typename
T::Char
>('0');
515 for (sal_Int32 j
= sLen
; j
>= 0; j
--)
517 typename
T::Char cS
= pBuf
[j
];
518 if (cS
!= cDecSeparator
)
520 if ( cS
!= static_cast< typename
T::Char
>('9'))
523 j
= -1; // break loop
528 = static_cast< typename
T::Char
>('0');
531 if ( eFormat
== rtl_math_StringFormat_F
)
533 typename
T::Char
* px
= p
++;
539 pBuf
[0] = static_cast<
540 typename
T::Char
>('1');
544 pBuf
[j
] = static_cast<
545 typename
T::Char
>('1');
552 *p
++ = static_cast< typename
T::Char
>('0');
558 *p
++ = static_cast< typename
T::Char
>(
559 nDigit
+ static_cast< typename
T::Char
>('0') );
560 fValue
= ( fValue
- nDigit
) * 10.0;
564 *p
++ = static_cast< typename
T::Char
>('0');
571 *p
++ = cDecSeparator
;
574 else if ( nDecPos
== nGrouping
)
576 *p
++ = cGroupSeparator
;
577 nGrouping
-= pGroups
[ nGroupSelector
];
578 if ( nGroupSelector
&& nGrouping
< nGroupExceed
)
585 if ( !bHasDec
&& eFormat
== rtl_math_StringFormat_F
)
586 { // nDecPlaces < 0 did round the value
587 while ( --nDecPos
> 0 )
588 { // fill before decimal point
589 if ( nDecPos
== nGrouping
)
591 *p
++ = cGroupSeparator
;
592 nGrouping
-= pGroups
[ nGroupSelector
];
593 if ( nGroupSelector
&& nGrouping
< nGroupExceed
)
596 *p
++ = static_cast< typename
T::Char
>('0');
600 if ( bEraseTrailingDecZeros
&& bHasDec
&& p
> pBuf
)
602 while ( *(p
-1) == static_cast< typename
T::Char
>('0') )
604 if ( *(p
-1) == cDecSeparator
)
608 // Print the exponent ('E', followed by '+' or '-', followed by exactly
609 // three digits). The code in rtl_[u]str_valueOf{Float|Double} relies on
611 if( eFormat
== rtl_math_StringFormat_E
)
614 *p
++ = static_cast< typename
T::Char
>('1');
615 // maybe no nDigits if nDecPlaces < 0
616 *p
++ = static_cast< typename
T::Char
>('E');
620 *p
++ = static_cast< typename
T::Char
>('-');
623 *p
++ = static_cast< typename
T::Char
>('+');
625 *p
++ = static_cast< typename
T::Char
>(
626 nExp
/ 100 + static_cast< typename
T::Char
>('0') );
628 *p
++ = static_cast< typename
T::Char
>(
629 nExp
/ 10 + static_cast< typename
T::Char
>('0') );
630 *p
++ = static_cast< typename
T::Char
>(
631 nExp
% 10 + static_cast< typename
T::Char
>('0') );
634 if (pResultCapacity
== 0)
635 T::createString(pResult
, pBuf
, p
- pBuf
);
637 T::appendChars(pResult
, pResultCapacity
, &nResultOffset
, pBuf
,
640 if ( pBuf
!= &aBuf
[0] )
641 rtl_freeMemory(pBuf
);
646 void SAL_CALL
rtl_math_doubleToString(rtl_String
** pResult
,
647 sal_Int32
* pResultCapacity
,
648 sal_Int32 nResultOffset
, double fValue
,
649 rtl_math_StringFormat eFormat
,
650 sal_Int32 nDecPlaces
,
651 sal_Char cDecSeparator
,
652 sal_Int32
const * pGroups
,
653 sal_Char cGroupSeparator
,
654 sal_Bool bEraseTrailingDecZeros
)
657 doubleToString
< StringTraits
, StringTraits::String
>(
658 pResult
, pResultCapacity
, nResultOffset
, fValue
, eFormat
, nDecPlaces
,
659 cDecSeparator
, pGroups
, cGroupSeparator
, bEraseTrailingDecZeros
);
662 void SAL_CALL
rtl_math_doubleToUString(rtl_uString
** pResult
,
663 sal_Int32
* pResultCapacity
,
664 sal_Int32 nResultOffset
, double fValue
,
665 rtl_math_StringFormat eFormat
,
666 sal_Int32 nDecPlaces
,
667 sal_Unicode cDecSeparator
,
668 sal_Int32
const * pGroups
,
669 sal_Unicode cGroupSeparator
,
670 sal_Bool bEraseTrailingDecZeros
)
673 doubleToString
< UStringTraits
, UStringTraits::String
>(
674 pResult
, pResultCapacity
, nResultOffset
, fValue
, eFormat
, nDecPlaces
,
675 cDecSeparator
, pGroups
, cGroupSeparator
, bEraseTrailingDecZeros
);
681 // if nExp * 10 + nAdd would result in overflow
682 inline bool long10Overflow( long& nExp
, int nAdd
)
684 if ( nExp
> (LONG_MAX
/10)
685 || (nExp
== (LONG_MAX
/10) && nAdd
> (LONG_MAX
%10)) )
693 template< typename CharT
>
694 inline double stringToDouble(CharT
const * pBegin
, CharT
const * pEnd
,
695 CharT cDecSeparator
, CharT cGroupSeparator
,
696 rtl_math_ConversionStatus
* pStatus
,
697 CharT
const ** pParsedEnd
)
700 rtl_math_ConversionStatus eStatus
= rtl_math_ConversionStatus_Ok
;
702 CharT
const * p0
= pBegin
;
703 while (p0
!= pEnd
&& (*p0
== CharT(' ') || *p0
== CharT('\t')))
706 if (p0
!= pEnd
&& *p0
== CharT('-'))
714 if (p0
!= pEnd
&& *p0
== CharT('+'))
717 CharT
const * p
= p0
;
720 // #i112652# XMLSchema-2
723 if ((CharT('N') == p
[0]) && (CharT('a') == p
[1])
724 && (CharT('N') == p
[2]))
727 rtl::math::setNan( &fVal
);
730 else if ((CharT('I') == p
[0]) && (CharT('N') == p
[1])
731 && (CharT('F') == p
[2]))
735 eStatus
= rtl_math_ConversionStatus_OutOfRange
;
740 if (!bDone
) // do not recognize e.g. NaN1.23
742 // leading zeros and group separators may be safely ignored
743 while (p
!= pEnd
&& (*p
== CharT('0') || *p
== cGroupSeparator
))
746 long nValExp
= 0; // carry along exponent of mantissa
748 // integer part of mantissa
749 for (; p
!= pEnd
; ++p
)
752 if (rtl::isAsciiDigit(c
))
754 fVal
= fVal
* 10.0 + static_cast< double >( c
- CharT('0') );
757 else if (c
!= cGroupSeparator
)
761 // fraction part of mantissa
762 if (p
!= pEnd
&& *p
== cDecSeparator
)
767 while (p
!= pEnd
&& *p
== CharT('0'))
773 nValExp
= nFracExp
- 1; // no integer part => fraction exponent
774 // one decimal digit needs ld(10) ~= 3.32 bits
775 static const int nSigs
= (DBL_MANT_DIG
/ 3) + 1;
777 for (; p
!= pEnd
; ++p
)
780 if (!rtl::isAsciiDigit(c
))
783 { // further digits (more than nSigs) don't have any
785 fFrac
= fFrac
* 10.0 + static_cast<double>(c
- CharT('0'));
791 fVal
+= rtl::math::pow10Exp( fFrac
, nFracExp
);
792 else if ( nValExp
< 0 )
793 nValExp
= 0; // no digit other than 0 after decimal point
797 --nValExp
; // started with offset +1 at the first mantissa digit
800 if (p
!= p0
&& p
!= pEnd
&& (*p
== CharT('E') || *p
== CharT('e')))
802 CharT
const * const pExponent
= p
;
805 if (p
!= pEnd
&& *p
== CharT('-'))
813 if (p
!= pEnd
&& *p
== CharT('+'))
816 CharT
const * const pFirstExpDigit
= p
;
818 { // no matter what follows, zero stays zero, but carry on the
820 while (p
!= pEnd
&& rtl::isAsciiDigit(*p
))
822 if (p
== pFirstExpDigit
)
823 { // no digits in exponent, reset end of scan
829 bool bOverFlow
= false;
831 for (; p
!= pEnd
; ++p
)
834 if (!rtl::isAsciiDigit(c
))
836 int i
= c
- CharT('0');
837 if ( long10Overflow( nExp
, i
) )
840 nExp
= nExp
* 10 + i
;
846 long nAllExp
= ( bOverFlow
? 0 : nExp
+ nValExp
);
847 if ( nAllExp
> DBL_MAX_10_EXP
|| (bOverFlow
&& !bExpSign
) )
850 eStatus
= rtl_math_ConversionStatus_OutOfRange
;
852 else if ((nAllExp
< DBL_MIN_10_EXP
) ||
853 (bOverFlow
&& bExpSign
) )
856 eStatus
= rtl_math_ConversionStatus_OutOfRange
;
858 else if ( nExp
> DBL_MAX_10_EXP
|| nExp
< DBL_MIN_10_EXP
)
859 { // compensate exponents
860 fVal
= rtl::math::pow10Exp( fVal
, -nValExp
);
861 fVal
= rtl::math::pow10Exp( fVal
, nAllExp
);
864 fVal
= rtl::math::pow10Exp( fVal
, nExp
); // normal
866 else if (p
== pFirstExpDigit
)
867 { // no digits in exponent, reset end of scan
872 else if (p
- p0
== 2 && p
!= pEnd
&& p
[0] == CharT('#')
873 && p
[-1] == cDecSeparator
&& p
[-2] == CharT('1'))
875 if (pEnd
- p
>= 4 && p
[1] == CharT('I') && p
[2] == CharT('N')
876 && p
[3] == CharT('F'))
878 // "1.#INF", "+1.#INF", "-1.#INF"
881 eStatus
= rtl_math_ConversionStatus_OutOfRange
;
882 // Eat any further digits:
883 while (p
!= pEnd
&& rtl::isAsciiDigit(*p
))
886 else if (pEnd
- p
>= 4 && p
[1] == CharT('N') && p
[2] == CharT('A')
887 && p
[3] == CharT('N'))
889 // "1.#NAN", "+1.#NAN", "-1.#NAN"
891 rtl::math::setNan( &fVal
);
899 m
.md
.w32_parts
.msw
|= 0x80000000; // create negative NaN
901 bSign
= false; // don't negate again
903 // Eat any further digits:
904 while (p
!= pEnd
&& rtl::isAsciiDigit(*p
))
910 // overflow also if more than DBL_MAX_10_EXP digits without decimal
911 // separator, or 0. and more than DBL_MIN_10_EXP digits, ...
912 bool bHuge
= fVal
== HUGE_VAL
; // g++ 3.0.1 requires it this way...
914 eStatus
= rtl_math_ConversionStatus_OutOfRange
;
922 *pParsedEnd
= p
== p0
? pBegin
: p
;
929 double SAL_CALL
rtl_math_stringToDouble(sal_Char
const * pBegin
,
930 sal_Char
const * pEnd
,
931 sal_Char cDecSeparator
,
932 sal_Char cGroupSeparator
,
933 rtl_math_ConversionStatus
* pStatus
,
934 sal_Char
const ** pParsedEnd
)
937 return stringToDouble(pBegin
, pEnd
, cDecSeparator
, cGroupSeparator
, pStatus
,
941 double SAL_CALL
rtl_math_uStringToDouble(sal_Unicode
const * pBegin
,
942 sal_Unicode
const * pEnd
,
943 sal_Unicode cDecSeparator
,
944 sal_Unicode cGroupSeparator
,
945 rtl_math_ConversionStatus
* pStatus
,
946 sal_Unicode
const ** pParsedEnd
)
949 return stringToDouble(pBegin
, pEnd
, cDecSeparator
, cGroupSeparator
, pStatus
,
953 double SAL_CALL
rtl_math_round(double fValue
, int nDecPlaces
,
954 enum rtl_math_RoundingMode eMode
)
957 OSL_ASSERT(nDecPlaces
>= -20 && nDecPlaces
<= 20);
963 bool bSign
= rtl::math::isSignBitSet( fValue
);
968 if ( nDecPlaces
!= 0 )
970 // max 20 decimals, we don't have unlimited precision
971 // #38810# and no overflow on fValue*=fFac
972 if ( nDecPlaces
< -20 || 20 < nDecPlaces
|| fValue
> (DBL_MAX
/ 1e20
) )
973 return bSign
? -fValue
: fValue
;
975 fFac
= getN10Exp( nDecPlaces
);
978 //else //! uninitialized fFac, not needed
982 case rtl_math_RoundingMode_Corrected
:
984 int nExp
; // exponent for correction
986 nExp
= static_cast<int>( floor( log10( fValue
) ) );
989 int nIndex
= 15 - nExp
;
992 else if ( nIndex
<= 1 )
994 fValue
= floor( fValue
+ 0.5 + nKorrVal
[nIndex
] );
997 case rtl_math_RoundingMode_Down
:
998 fValue
= rtl::math::approxFloor( fValue
);
1000 case rtl_math_RoundingMode_Up
:
1001 fValue
= rtl::math::approxCeil( fValue
);
1003 case rtl_math_RoundingMode_Floor
:
1004 fValue
= bSign
? rtl::math::approxCeil( fValue
)
1005 : rtl::math::approxFloor( fValue
);
1007 case rtl_math_RoundingMode_Ceiling
:
1008 fValue
= bSign
? rtl::math::approxFloor( fValue
)
1009 : rtl::math::approxCeil( fValue
);
1011 case rtl_math_RoundingMode_HalfDown
:
1013 double f
= floor( fValue
);
1014 fValue
= ((fValue
- f
) <= 0.5) ? f
: ceil( fValue
);
1017 case rtl_math_RoundingMode_HalfUp
:
1019 double f
= floor( fValue
);
1020 fValue
= ((fValue
- f
) < 0.5) ? f
: ceil( fValue
);
1023 case rtl_math_RoundingMode_HalfEven
:
1024 #if defined FLT_ROUNDS
1026 Use fast version. FLT_ROUNDS may be defined to a function by some compilers!
1028 DBL_EPSILON is the smallest fractional number which can be represented,
1029 its reciprocal is therefore the smallest number that cannot have a
1030 fractional part. Once you add this reciprocal to `x', its fractional part
1031 is stripped off. Simply subtracting the reciprocal back out returns `x'
1032 without its fractional component.
1033 Simple, clever, and elegant - thanks to Ross Cottrell, the original author,
1034 who placed it into public domain.
1036 volatile: prevent compiler from being too smart
1038 if ( FLT_ROUNDS
== 1 )
1040 volatile double x
= fValue
+ 1.0 / DBL_EPSILON
;
1041 fValue
= x
- 1.0 / DBL_EPSILON
;
1044 #endif // FLT_ROUNDS
1046 double f
= floor( fValue
);
1047 if ( (fValue
- f
) != 0.5 )
1048 fValue
= floor( fValue
+ 0.5 );
1052 fValue
= (g
== floor( g
)) ? f
: (f
+ 1.0);
1061 if ( nDecPlaces
!= 0 )
1064 return bSign
? -fValue
: fValue
;
1068 double SAL_CALL
rtl_math_pow10Exp(double fValue
, int nExp
) SAL_THROW_EXTERN_C()
1070 return fValue
* getN10Exp( nExp
);
1074 double SAL_CALL
rtl_math_approxValue( double fValue
) SAL_THROW_EXTERN_C()
1076 if (fValue
== 0.0 || fValue
== HUGE_VAL
|| !::rtl::math::isFinite( fValue
))
1077 // We don't handle these conditions. Bail out.
1080 double fOrigValue
= fValue
;
1082 bool bSign
= ::rtl::math::isSignBitSet( fValue
);
1086 int nExp
= static_cast<int>( floor( log10( fValue
)));
1088 double fExpValue
= getN10Exp( nExp
);
1090 fValue
*= fExpValue
;
1091 // If the original value was near DBL_MIN we got an overflow. Restore and
1093 if (!rtl::math::isFinite( fValue
))
1095 fValue
= rtl_math_round( fValue
, 0, rtl_math_RoundingMode_Corrected
);
1096 fValue
/= fExpValue
;
1097 // If the original value was near DBL_MAX we got an overflow. Restore and
1099 if (!rtl::math::isFinite( fValue
))
1102 return bSign
? -fValue
: fValue
;
1106 double SAL_CALL
rtl_math_expm1( double fValue
) SAL_THROW_EXTERN_C()
1108 double fe
= exp( fValue
);
1113 return (fe
-1.0) * fValue
/ log(fe
);
1117 double SAL_CALL
rtl_math_log1p( double fValue
) SAL_THROW_EXTERN_C()
1119 // Use volatile because a compiler may be too smart "optimizing" the
1120 // condition such that in certain cases the else path was called even if
1121 // (fp==1.0) was true, where the term (fp-1.0) then resulted in 0.0 and
1122 // hence the entire expression resulted in NaN.
1123 // Happened with g++ 3.4.1 and an input value of 9.87E-18
1124 volatile double fp
= 1.0 + fValue
;
1128 return log(fp
) * fValue
/ (fp
-1.0);
1132 double SAL_CALL
rtl_math_atanh( double fValue
) SAL_THROW_EXTERN_C()
1134 return 0.5 * rtl_math_log1p( 2.0 * fValue
/ (1.0-fValue
) );
1138 /** Parent error function (erf) that calls different algorithms based on the
1139 value of x. It takes care of cases where x is negative as erf is an odd
1140 function i.e. erf(-x) = -erf(x).
1142 Kramer, W., and Blomquist, F., 2000, Algorithms with Guaranteed Error Bounds
1143 for the Error Function and the Complementary Error Function
1145 http://www.math.uni-wuppertal.de/wrswt/literatur_en.html
1147 @author Kohei Yoshida <kohei@openoffice.org>
1151 double SAL_CALL
rtl_math_erf( double x
) SAL_THROW_EXTERN_C()
1156 bool bNegative
= false;
1165 fErf
= (double) (x
*1.1283791670955125738961589031215452L);
1166 else if ( x
< 0.65 )
1167 lcl_Erf0065( x
, fErf
);
1169 fErf
= 1.0 - rtl_math_erfc( x
);
1178 /** Parent complementary error function (erfc) that calls different algorithms
1179 based on the value of x. It takes care of cases where x is negative as erfc
1180 satisfies relationship erfc(-x) = 2 - erfc(x). See the comment for Erf(x)
1181 for the source publication.
1183 @author Kohei Yoshida <kohei@openoffice.org>
1185 @see #i55735#, moved from module scaddins (#i97091#)
1188 double SAL_CALL
rtl_math_erfc( double x
) SAL_THROW_EXTERN_C()
1193 bool bNegative
= false;
1204 lcl_Erfc0600( x
, fErfc
);
1206 lcl_Erfc2654( x
, fErfc
);
1209 fErfc
= 1.0 - rtl_math_erf( x
);
1212 fErfc
= 2.0 - fErfc
;
1217 /** improved accuracy of asinh for |x| large and for x near zero
1220 double SAL_CALL
rtl_math_asinh( double fX
) SAL_THROW_EXTERN_C()
1233 return fSign
* rtl_math_log1p( fX
+ fX
*fX
/ (1.0 + sqrt( 1.0 + fX
*fX
)));
1234 else if ( fX
< 1.25e7
)
1235 return fSign
* log( fX
+ sqrt( 1.0 + fX
*fX
));
1237 return fSign
* log( 2.0*fX
);
1241 /** improved accuracy of acosh for x large and for x near 1
1244 double SAL_CALL
rtl_math_acosh( double fX
) SAL_THROW_EXTERN_C()
1246 volatile double fZ
= fX
- 1.0;
1250 ::rtl::math::setNan( &fResult
);
1253 else if ( fX
== 1.0 )
1255 else if ( fX
< 1.1 )
1256 return rtl_math_log1p( fZ
+ sqrt( fZ
*fZ
+ 2.0*fZ
));
1257 else if ( fX
< 1.25e7
)
1258 return log( fX
+ sqrt( fX
*fX
- 1.0));
1260 return log( 2.0*fX
);
1263 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */