1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: math.cxx,v $
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"
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"
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
)
66 if ( -nExp
<= n10Count
)
67 return n10s
[1][-nExp
-1];
69 return pow( 10.0, static_cast<double>( nExp
) );
73 if ( nExp
<= n10Count
)
74 return n10s
[0][nExp
-1];
76 return pow( 10.0, static_cast<double>( nExp
) );
85 double const nKorrVal
[] = {
86 0, 9e-1, 9e-2, 9e-3, 9e-4, 9e-5, 9e-6, 9e-7, 9e-8,
87 9e-9, 9e-10, 9e-11, 9e-12, 9e-13, 9e-14, 9e-15
92 typedef sal_Char Char
;
94 typedef rtl_String String
;
96 static inline void createString(rtl_String
** pString
,
97 sal_Char
const * pChars
, sal_Int32 nLen
)
99 rtl_string_newFromStr_WithLength(pString
, pChars
, nLen
);
102 static inline void createBuffer(rtl_String
** pBuffer
,
103 sal_Int32
* pCapacity
)
105 rtl_string_new_WithLength(pBuffer
, *pCapacity
);
108 static inline void appendChar(rtl_String
** pBuffer
, sal_Int32
* pCapacity
,
109 sal_Int32
* pOffset
, sal_Char cChar
)
111 rtl_stringbuffer_insert(pBuffer
, pCapacity
, *pOffset
, &cChar
, 1);
115 static inline void appendChars(rtl_String
** pBuffer
, sal_Int32
* pCapacity
,
116 sal_Int32
* pOffset
, sal_Char
const * pChars
,
119 rtl_stringbuffer_insert(pBuffer
, pCapacity
, *pOffset
, pChars
, nLen
);
123 static inline void appendAscii(rtl_String
** pBuffer
, sal_Int32
* pCapacity
,
124 sal_Int32
* pOffset
, sal_Char
const * pStr
,
127 rtl_stringbuffer_insert(pBuffer
, pCapacity
, *pOffset
, pStr
, nLen
);
134 typedef sal_Unicode Char
;
136 typedef rtl_uString String
;
138 static inline void createString(rtl_uString
** pString
,
139 sal_Unicode
const * pChars
, sal_Int32 nLen
)
141 rtl_uString_newFromStr_WithLength(pString
, pChars
, nLen
);
144 static inline void createBuffer(rtl_uString
** pBuffer
,
145 sal_Int32
* pCapacity
)
147 rtl_uString_new_WithLength(pBuffer
, *pCapacity
);
150 static inline void appendChar(rtl_uString
** pBuffer
, sal_Int32
* pCapacity
,
151 sal_Int32
* pOffset
, sal_Unicode cChar
)
153 rtl_uStringbuffer_insert(pBuffer
, pCapacity
, *pOffset
, &cChar
, 1);
157 static inline void appendChars(rtl_uString
** pBuffer
,
158 sal_Int32
* pCapacity
, sal_Int32
* pOffset
,
159 sal_Unicode
const * pChars
, sal_Int32 nLen
)
161 rtl_uStringbuffer_insert(pBuffer
, pCapacity
, *pOffset
, pChars
, nLen
);
165 static inline void appendAscii(rtl_uString
** pBuffer
,
166 sal_Int32
* pCapacity
, sal_Int32
* pOffset
,
167 sal_Char
const * pStr
, sal_Int32 nLen
)
169 rtl_uStringbuffer_insert_ascii(pBuffer
, pCapacity
, *pOffset
, pStr
,
176 // Solaris C++ 5.2 compiler has problems when "StringT ** pResult" is
177 // "typename T::String ** pResult" instead:
178 template< typename T
, typename StringT
>
179 inline void doubleToString(StringT
** pResult
,
180 sal_Int32
* pResultCapacity
, sal_Int32 nResultOffset
,
181 double fValue
, rtl_math_StringFormat eFormat
,
182 sal_Int32 nDecPlaces
, typename
T::Char cDecSeparator
,
183 sal_Int32
const * pGroups
,
184 typename
T::Char cGroupSeparator
,
185 bool bEraseTrailingDecZeros
)
187 static double const nRoundVal
[] = {
188 5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6,
189 0.5e-7, 0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14
192 // sign adjustment, instead of testing for fValue<0.0 this will also fetch
194 bool bSign
= rtl::math::isSignBitSet( fValue
);
198 if ( rtl::math::isNan( fValue
) )
200 sal_Int32 nCapacity
= RTL_CONSTASCII_LENGTH("-1.#NAN");
201 if (pResultCapacity
== 0)
203 pResultCapacity
= &nCapacity
;
204 T::createBuffer(pResult
, pResultCapacity
);
209 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
,
210 RTL_CONSTASCII_STRINGPARAM("-"));
211 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
,
212 RTL_CONSTASCII_STRINGPARAM("1"));
213 T::appendChar(pResult
, pResultCapacity
, &nResultOffset
, cDecSeparator
);
214 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
,
215 RTL_CONSTASCII_STRINGPARAM("#NAN"));
219 bool bHuge
= fValue
== HUGE_VAL
; // g++ 3.0.1 requires it this way...
220 if ( bHuge
|| rtl::math::isInf( fValue
) )
222 sal_Int32 nCapacity
= RTL_CONSTASCII_LENGTH("-1.#INF");
223 if (pResultCapacity
== 0)
225 pResultCapacity
= &nCapacity
;
226 T::createBuffer(pResult
, pResultCapacity
);
231 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
,
232 RTL_CONSTASCII_STRINGPARAM("-"));
233 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
,
234 RTL_CONSTASCII_STRINGPARAM("1"));
235 T::appendChar(pResult
, pResultCapacity
, &nResultOffset
, cDecSeparator
);
236 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
,
237 RTL_CONSTASCII_STRINGPARAM("#INF"));
245 nExp
= static_cast< int >( floor( log10( fValue
) ) );
246 fValue
/= getN10Exp( nExp
);
251 case rtl_math_StringFormat_Automatic
:
252 { // E or F depending on exponent magnitude
254 if ( nExp
<= -15 || nExp
>= 15 ) // #58531# was <-16, >16
257 eFormat
= rtl_math_StringFormat_E
;
263 nPrec
= 15 - nExp
- 1;
264 eFormat
= rtl_math_StringFormat_F
;
269 eFormat
= rtl_math_StringFormat_F
;
272 if ( nDecPlaces
== rtl_math_DecimalPlaces_Max
)
276 case rtl_math_StringFormat_G
:
277 { // G-Point, similar to sprintf %G
278 if ( nDecPlaces
== rtl_math_DecimalPlaces_DefaultSignificance
)
280 if ( nExp
< -4 || nExp
>= nDecPlaces
)
282 nDecPlaces
= std::max
< sal_Int32
>( 1, nDecPlaces
- 1 );
283 eFormat
= rtl_math_StringFormat_E
;
287 nDecPlaces
= std::max
< sal_Int32
>( 0, nDecPlaces
- nExp
- 1 );
288 eFormat
= rtl_math_StringFormat_F
;
296 sal_Int32 nDigits
= nDecPlaces
+ 1;
298 if( eFormat
== rtl_math_StringFormat_F
)
304 if( ( fValue
+= nRoundVal
[ nDigits
> 15 ? 15 : nDigits
] ) >= 10 )
308 if( eFormat
== rtl_math_StringFormat_F
)
313 static sal_Int32
const nBufMax
= 256;
314 typename
T::Char aBuf
[nBufMax
];
315 typename
T::Char
* pBuf
;
316 sal_Int32 nBuf
= static_cast< sal_Int32
>
317 ( nDigits
<= 0 ? std::max
< sal_Int32
>( nDecPlaces
, abs(nExp
) )
318 : nDigits
+ nDecPlaces
) + 10 + (pGroups
? abs(nDigits
) * 2 : 0);
319 if ( nBuf
> nBufMax
)
321 pBuf
= reinterpret_cast< typename
T::Char
* >(
322 rtl_allocateMemory(nBuf
* sizeof (typename
T::Char
)));
323 OSL_ENSURE(pBuf
!= 0, "Out of memory");
327 typename
T::Char
* p
= pBuf
;
329 *p
++ = static_cast< typename
T::Char
>('-');
331 bool bHasDec
= false;
334 // Check for F format and number < 1
335 if( eFormat
== rtl_math_StringFormat_F
)
339 *p
++ = static_cast< typename
T::Char
>('0');
340 if ( nDecPlaces
> 0 )
342 *p
++ = cDecSeparator
;
345 sal_Int32 i
= ( nDigits
<= 0 ? nDecPlaces
: -nExp
- 1 );
347 *p
++ = static_cast< typename
T::Char
>('0');
356 int nGrouping
= 0, nGroupSelector
= 0, nGroupExceed
= 0;
357 if ( nDecPos
> 1 && pGroups
&& pGroups
[0] && cGroupSeparator
)
359 while ( nGrouping
+ pGroups
[nGroupSelector
] < nDecPos
)
361 nGrouping
+= pGroups
[ nGroupSelector
];
362 if ( pGroups
[nGroupSelector
+1] )
364 if ( nGrouping
+ pGroups
[nGroupSelector
+1] >= nDecPos
)
368 else if ( !nGroupExceed
)
369 nGroupExceed
= nGrouping
;
376 for ( int i
= 0; ; i
++ )
381 if (nDigits
-1 == 0 && i
> 0 && i
< 14)
382 nDigit
= static_cast< int >( floor( fValue
383 + nKorrVal
[15-i
] ) );
385 nDigit
= static_cast< int >( fValue
+ 1E-15 );
387 { // after-treatment of up-rounding to the next decade
388 sal_Int32 sLen
= static_cast< long >(p
-pBuf
)-1;
392 if ( eFormat
== rtl_math_StringFormat_F
)
394 *p
++ = static_cast< typename
T::Char
>('1');
395 *p
++ = static_cast< typename
T::Char
>('0');
399 *p
++ = static_cast< typename
T::Char
>('1');
400 *p
++ = cDecSeparator
;
401 *p
++ = static_cast< typename
T::Char
>('0');
408 for (sal_Int32 j
= sLen
; j
>= 0; j
--)
410 typename
T::Char cS
= pBuf
[j
];
411 if (cS
!= cDecSeparator
)
413 if ( cS
!= static_cast< typename
T::Char
>('9'))
416 j
= -1; // break loop
421 = static_cast< typename
T::Char
>('0');
424 if ( eFormat
== rtl_math_StringFormat_F
)
426 typename
T::Char
* px
= p
++;
432 pBuf
[0] = static_cast<
433 typename
T::Char
>('1');
437 pBuf
[j
] = static_cast<
438 typename
T::Char
>('1');
445 *p
++ = static_cast< typename
T::Char
>('0');
451 *p
++ = static_cast< typename
T::Char
>(
452 nDigit
+ static_cast< typename
T::Char
>('0') );
453 fValue
= ( fValue
- nDigit
) * 10.0;
457 *p
++ = static_cast< typename
T::Char
>('0');
464 *p
++ = cDecSeparator
;
467 else if ( nDecPos
== nGrouping
)
469 *p
++ = cGroupSeparator
;
470 nGrouping
-= pGroups
[ nGroupSelector
];
471 if ( nGroupSelector
&& nGrouping
< nGroupExceed
)
478 if ( !bHasDec
&& eFormat
== rtl_math_StringFormat_F
)
479 { // nDecPlaces < 0 did round the value
480 while ( --nDecPos
> 0 )
481 { // fill before decimal point
482 if ( nDecPos
== nGrouping
)
484 *p
++ = cGroupSeparator
;
485 nGrouping
-= pGroups
[ nGroupSelector
];
486 if ( nGroupSelector
&& nGrouping
< nGroupExceed
)
489 *p
++ = static_cast< typename
T::Char
>('0');
493 if ( bEraseTrailingDecZeros
&& bHasDec
&& p
> pBuf
)
495 while ( *(p
-1) == static_cast< typename
T::Char
>('0') )
497 if ( *(p
-1) == cDecSeparator
)
501 // Print the exponent ('E', followed by '+' or '-', followed by exactly
502 // three digits). The code in rtl_[u]str_valueOf{Float|Double} relies on
504 if( eFormat
== rtl_math_StringFormat_E
)
507 *p
++ = static_cast< typename
T::Char
>('1');
508 // maybe no nDigits if nDecPlaces < 0
509 *p
++ = static_cast< typename
T::Char
>('E');
513 *p
++ = static_cast< typename
T::Char
>('-');
516 *p
++ = static_cast< typename
T::Char
>('+');
518 *p
++ = static_cast< typename
T::Char
>(
519 nExp
/ 100 + static_cast< typename
T::Char
>('0') );
521 *p
++ = static_cast< typename
T::Char
>(
522 nExp
/ 10 + static_cast< typename
T::Char
>('0') );
523 *p
++ = static_cast< typename
T::Char
>(
524 nExp
% 10 + static_cast< typename
T::Char
>('0') );
527 if (pResultCapacity
== 0)
528 T::createString(pResult
, pBuf
, p
- pBuf
);
530 T::appendChars(pResult
, pResultCapacity
, &nResultOffset
, pBuf
,
533 if ( pBuf
!= &aBuf
[0] )
534 rtl_freeMemory(pBuf
);
539 void SAL_CALL
rtl_math_doubleToString(rtl_String
** pResult
,
540 sal_Int32
* pResultCapacity
,
541 sal_Int32 nResultOffset
, double fValue
,
542 rtl_math_StringFormat eFormat
,
543 sal_Int32 nDecPlaces
,
544 sal_Char cDecSeparator
,
545 sal_Int32
const * pGroups
,
546 sal_Char cGroupSeparator
,
547 sal_Bool bEraseTrailingDecZeros
)
550 doubleToString
< StringTraits
, StringTraits::String
>(
551 pResult
, pResultCapacity
, nResultOffset
, fValue
, eFormat
, nDecPlaces
,
552 cDecSeparator
, pGroups
, cGroupSeparator
, bEraseTrailingDecZeros
);
555 void SAL_CALL
rtl_math_doubleToUString(rtl_uString
** pResult
,
556 sal_Int32
* pResultCapacity
,
557 sal_Int32 nResultOffset
, double fValue
,
558 rtl_math_StringFormat eFormat
,
559 sal_Int32 nDecPlaces
,
560 sal_Unicode cDecSeparator
,
561 sal_Int32
const * pGroups
,
562 sal_Unicode cGroupSeparator
,
563 sal_Bool bEraseTrailingDecZeros
)
566 doubleToString
< UStringTraits
, UStringTraits::String
>(
567 pResult
, pResultCapacity
, nResultOffset
, fValue
, eFormat
, nDecPlaces
,
568 cDecSeparator
, pGroups
, cGroupSeparator
, bEraseTrailingDecZeros
);
574 // if nExp * 10 + nAdd would result in overflow
575 inline bool long10Overflow( long& nExp
, int nAdd
)
577 if ( nExp
> (LONG_MAX
/10)
578 || (nExp
== (LONG_MAX
/10) && nAdd
> (LONG_MAX
%10)) )
586 // We are only concerned about ASCII arabic numerical digits here
587 template< typename CharT
>
588 inline bool isDigit( CharT c
)
590 return 0x30 <= c
&& c
<= 0x39;
593 template< typename CharT
>
594 inline double stringToDouble(CharT
const * pBegin
, CharT
const * pEnd
,
595 CharT cDecSeparator
, CharT cGroupSeparator
,
596 rtl_math_ConversionStatus
* pStatus
,
597 CharT
const ** pParsedEnd
)
600 rtl_math_ConversionStatus eStatus
= rtl_math_ConversionStatus_Ok
;
602 CharT
const * p0
= pBegin
;
603 while (p0
!= pEnd
&& (*p0
== CharT(' ') || *p0
== CharT('\t')))
606 if (p0
!= pEnd
&& *p0
== CharT('-'))
614 if (p0
!= pEnd
&& *p0
== CharT('+'))
617 CharT
const * p
= p0
;
619 // leading zeros and group separators may be safely ignored
620 while (p
!= pEnd
&& (*p
== CharT('0') || *p
== cGroupSeparator
))
623 long nValExp
= 0; // carry along exponent of mantissa
625 // integer part of mantissa
626 for (; p
!= pEnd
; ++p
)
631 fVal
= fVal
* 10.0 + static_cast< double >( c
- CharT('0') );
634 else if (c
!= cGroupSeparator
)
638 // fraction part of mantissa
639 if (p
!= pEnd
&& *p
== cDecSeparator
)
644 while (p
!= pEnd
&& *p
== CharT('0'))
650 nValExp
= nFracExp
- 1; // no integer part => fraction exponent
651 // one decimal digit needs ld(10) ~= 3.32 bits
652 static const int nSigs
= (DBL_MANT_DIG
/ 3) + 1;
654 for (; p
!= pEnd
; ++p
)
660 { // further digits (more than nSigs) don't have any significance
661 fFrac
= fFrac
* 10.0 + static_cast< double >( c
- CharT('0') );
667 fVal
+= rtl::math::pow10Exp( fFrac
, nFracExp
);
668 else if ( nValExp
< 0 )
669 nValExp
= 0; // no digit other than 0 after decimal point
673 --nValExp
; // started with offset +1 at the first mantissa digit
676 if (p
!= p0
&& p
!= pEnd
&& (*p
== CharT('E') || *p
== CharT('e')))
680 if (p
!= pEnd
&& *p
== CharT('-'))
688 if (p
!= pEnd
&& *p
== CharT('+'))
692 { // no matter what follows, zero stays zero, but carry on the offset
693 while (p
!= pEnd
&& isDigit(*p
))
698 bool bOverFlow
= false;
700 for (; p
!= pEnd
; ++p
)
705 int i
= c
- CharT('0');
706 if ( long10Overflow( nExp
, i
) )
709 nExp
= nExp
* 10 + i
;
715 long nAllExp
= ( bOverFlow
? 0 : nExp
+ nValExp
);
716 if ( nAllExp
> DBL_MAX_10_EXP
|| (bOverFlow
&& !bExpSign
) )
719 eStatus
= rtl_math_ConversionStatus_OutOfRange
;
721 else if ( nAllExp
< DBL_MIN_10_EXP
|| (bOverFlow
&& bExpSign
) )
724 eStatus
= rtl_math_ConversionStatus_OutOfRange
;
726 else if ( nExp
> DBL_MAX_10_EXP
|| nExp
< DBL_MIN_10_EXP
)
727 { // compensate exponents
728 fVal
= rtl::math::pow10Exp( fVal
, -nValExp
);
729 fVal
= rtl::math::pow10Exp( fVal
, nAllExp
);
732 fVal
= rtl::math::pow10Exp( fVal
, nExp
); // normal
736 else if (p
- p0
== 2 && p
!= pEnd
&& p
[0] == CharT('#')
737 && p
[-1] == cDecSeparator
&& p
[-2] == CharT('1'))
739 if (pEnd
- p
>= 4 && p
[1] == CharT('I') && p
[2] == CharT('N')
740 && p
[3] == CharT('F'))
742 // "1.#INF", "+1.#INF", "-1.#INF"
745 eStatus
= rtl_math_ConversionStatus_OutOfRange
;
746 // Eat any further digits:
747 while (p
!= pEnd
&& isDigit(*p
))
750 else if (pEnd
- p
>= 4 && p
[1] == CharT('N') && p
[2] == CharT('A')
751 && p
[3] == CharT('N'))
753 // "1.#NAN", "+1.#NAN", "-1.#NAN"
755 rtl::math::setNan( &fVal
);
758 reinterpret_cast< sal_math_Double
* >(&fVal
)->w32_parts
.msw
759 |= 0x80000000; // create negative NaN
760 bSign
= false; // don't negate again
762 // Eat any further digits:
763 while (p
!= pEnd
&& isDigit(*p
))
768 // overflow also if more than DBL_MAX_10_EXP digits without decimal
769 // separator, or 0. and more than DBL_MIN_10_EXP digits, ...
770 bool bHuge
= fVal
== HUGE_VAL
; // g++ 3.0.1 requires it this way...
772 eStatus
= rtl_math_ConversionStatus_OutOfRange
;
787 double SAL_CALL
rtl_math_stringToDouble(sal_Char
const * pBegin
,
788 sal_Char
const * pEnd
,
789 sal_Char cDecSeparator
,
790 sal_Char cGroupSeparator
,
791 rtl_math_ConversionStatus
* pStatus
,
792 sal_Char
const ** pParsedEnd
)
795 return stringToDouble(pBegin
, pEnd
, cDecSeparator
, cGroupSeparator
, pStatus
,
799 double SAL_CALL
rtl_math_uStringToDouble(sal_Unicode
const * pBegin
,
800 sal_Unicode
const * pEnd
,
801 sal_Unicode cDecSeparator
,
802 sal_Unicode cGroupSeparator
,
803 rtl_math_ConversionStatus
* pStatus
,
804 sal_Unicode
const ** pParsedEnd
)
807 return stringToDouble(pBegin
, pEnd
, cDecSeparator
, cGroupSeparator
, pStatus
,
811 double SAL_CALL
rtl_math_round(double fValue
, int nDecPlaces
,
812 enum rtl_math_RoundingMode eMode
)
815 OSL_ASSERT(nDecPlaces
>= -20 && nDecPlaces
<= 20);
821 bool bSign
= rtl::math::isSignBitSet( fValue
);
826 if ( nDecPlaces
!= 0 )
828 // max 20 decimals, we don't have unlimited precision
829 // #38810# and no overflow on fValue*=fFac
830 if ( nDecPlaces
< -20 || 20 < nDecPlaces
|| fValue
> (DBL_MAX
/ 1e20
) )
831 return bSign
? -fValue
: fValue
;
833 fFac
= getN10Exp( nDecPlaces
);
836 //else //! uninitialized fFac, not needed
840 case rtl_math_RoundingMode_Corrected
:
842 int nExp
; // exponent for correction
844 nExp
= static_cast<int>( floor( log10( fValue
) ) );
847 int nIndex
= 15 - nExp
;
850 else if ( nIndex
<= 1 )
852 fValue
= floor( fValue
+ 0.5 + nKorrVal
[nIndex
] );
855 case rtl_math_RoundingMode_Down
:
856 fValue
= rtl::math::approxFloor( fValue
);
858 case rtl_math_RoundingMode_Up
:
859 fValue
= rtl::math::approxCeil( fValue
);
861 case rtl_math_RoundingMode_Floor
:
862 fValue
= bSign
? rtl::math::approxCeil( fValue
)
863 : rtl::math::approxFloor( fValue
);
865 case rtl_math_RoundingMode_Ceiling
:
866 fValue
= bSign
? rtl::math::approxFloor( fValue
)
867 : rtl::math::approxCeil( fValue
);
869 case rtl_math_RoundingMode_HalfDown
:
871 double f
= floor( fValue
);
872 fValue
= ((fValue
- f
) <= 0.5) ? f
: ceil( fValue
);
875 case rtl_math_RoundingMode_HalfUp
:
877 double f
= floor( fValue
);
878 fValue
= ((fValue
- f
) < 0.5) ? f
: ceil( fValue
);
881 case rtl_math_RoundingMode_HalfEven
:
882 #if defined FLT_ROUNDS
884 Use fast version. FLT_ROUNDS may be defined to a function by some compilers!
886 DBL_EPSILON is the smallest fractional number which can be represented,
887 its reciprocal is therefore the smallest number that cannot have a
888 fractional part. Once you add this reciprocal to `x', its fractional part
889 is stripped off. Simply subtracting the reciprocal back out returns `x'
890 without its fractional component.
891 Simple, clever, and elegant - thanks to Ross Cottrell, the original author,
892 who placed it into public domain.
894 volatile: prevent compiler from being too smart
896 if ( FLT_ROUNDS
== 1 )
898 volatile double x
= fValue
+ 1.0 / DBL_EPSILON
;
899 fValue
= x
- 1.0 / DBL_EPSILON
;
904 double f
= floor( fValue
);
905 if ( (fValue
- f
) != 0.5 )
906 fValue
= floor( fValue
+ 0.5 );
910 fValue
= (g
== floor( g
)) ? f
: (f
+ 1.0);
919 if ( nDecPlaces
!= 0 )
922 return bSign
? -fValue
: fValue
;
926 double SAL_CALL
rtl_math_pow10Exp(double fValue
, int nExp
) SAL_THROW_EXTERN_C()
928 return fValue
* getN10Exp( nExp
);
932 double SAL_CALL
rtl_math_approxValue( double fValue
) SAL_THROW_EXTERN_C()
934 if (fValue
== 0.0 || fValue
== HUGE_VAL
|| !::rtl::math::isFinite( fValue
))
935 // We don't handle these conditions. Bail out.
938 double fOrigValue
= fValue
;
940 bool bSign
= ::rtl::math::isSignBitSet( fValue
);
944 int nExp
= static_cast<int>( floor( log10( fValue
)));
946 double fExpValue
= getN10Exp( nExp
);
949 // If the original value was near DBL_MIN we got an overflow. Restore and
951 if (!rtl::math::isFinite( fValue
))
953 fValue
= rtl_math_round( fValue
, 0, rtl_math_RoundingMode_Corrected
);
955 // If the original value was near DBL_MAX we got an overflow. Restore and
957 if (!rtl::math::isFinite( fValue
))
960 return bSign
? -fValue
: fValue
;
964 double SAL_CALL
rtl_math_expm1( double fValue
) SAL_THROW_EXTERN_C()
966 double fe
= exp( fValue
);
971 return (fe
-1.0) * fValue
/ log(fe
);
975 double SAL_CALL
rtl_math_log1p( double fValue
) SAL_THROW_EXTERN_C()
977 // Use volatile because a compiler may be too smart "optimizing" the
978 // condition such that in certain cases the else path was called even if
979 // (fp==1.0) was true, where the term (fp-1.0) then resulted in 0.0 and
980 // hence the entire expression resulted in NaN.
981 // Happened with g++ 3.4.1 and an input value of 9.87E-18
982 volatile double fp
= 1.0 + fValue
;
986 return log(fp
) * fValue
/ (fp
-1.0);
990 double SAL_CALL
rtl_math_atanh( double fValue
) SAL_THROW_EXTERN_C()
992 return 0.5 * rtl_math_log1p( 2.0 * fValue
/ (1.0-fValue
) );