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 .
22 #include <o3tl/safeint.hxx>
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>
45 int const n10Count
= 16;
46 double const n10s
[2][n10Count
] = {
47 { 1e1
, 1e2
, 1e3
, 1e4
, 1e5
, 1e6
, 1e7
, 1e8
,
48 1e9
, 1e10
, 1e11
, 1e12
, 1e13
, 1e14
, 1e15
, 1e16
},
49 { 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8,
50 1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16 }
53 // return pow(10.0,nExp) optimized for exponents in the interval [-16,16]
54 static double getN10Exp(int nExp
)
58 // && -nExp > 0 necessary for std::numeric_limits<int>::min()
59 // because -nExp = nExp
60 if (-nExp
<= n10Count
&& -nExp
> 0)
61 return n10s
[1][-nExp
-1];
62 return pow(10.0, static_cast<double>(nExp
));
67 return n10s
[0][nExp
-1];
69 return pow(10.0, static_cast<double>(nExp
));
76 double const nCorrVal
[] = {
77 0, 9e-1, 9e-2, 9e-3, 9e-4, 9e-5, 9e-6, 9e-7, 9e-8,
78 9e-9, 9e-10, 9e-11, 9e-12, 9e-13, 9e-14, 9e-15
85 typedef rtl_String String
;
87 static void createString(rtl_String
** pString
,
88 char const * pChars
, sal_Int32 nLen
)
90 rtl_string_newFromStr_WithLength(pString
, pChars
, nLen
);
93 static void createBuffer(rtl_String
** pBuffer
,
94 const sal_Int32
* pCapacity
)
96 rtl_string_new_WithLength(pBuffer
, *pCapacity
);
99 static void appendChars(rtl_String
** pBuffer
, sal_Int32
* pCapacity
,
100 sal_Int32
* pOffset
, char const * pChars
,
104 rtl_stringbuffer_insert(pBuffer
, pCapacity
, *pOffset
, pChars
, nLen
);
108 static void appendAscii(rtl_String
** pBuffer
, sal_Int32
* pCapacity
,
109 sal_Int32
* pOffset
, char const * pStr
,
113 rtl_stringbuffer_insert(pBuffer
, pCapacity
, *pOffset
, pStr
, nLen
);
120 typedef sal_Unicode Char
;
122 typedef rtl_uString String
;
124 static void createString(rtl_uString
** pString
,
125 sal_Unicode
const * pChars
, sal_Int32 nLen
)
127 rtl_uString_newFromStr_WithLength(pString
, pChars
, nLen
);
130 static void createBuffer(rtl_uString
** pBuffer
,
131 const sal_Int32
* pCapacity
)
133 rtl_uString_new_WithLength(pBuffer
, *pCapacity
);
136 static void appendChars(rtl_uString
** pBuffer
,
137 sal_Int32
* pCapacity
, sal_Int32
* pOffset
,
138 sal_Unicode
const * pChars
, sal_Int32 nLen
)
141 rtl_uStringbuffer_insert(pBuffer
, pCapacity
, *pOffset
, pChars
, nLen
);
145 static void appendAscii(rtl_uString
** pBuffer
,
146 sal_Int32
* pCapacity
, sal_Int32
* pOffset
,
147 char const * pStr
, sal_Int32 nLen
)
149 rtl_uStringbuffer_insert_ascii(pBuffer
, pCapacity
, *pOffset
, pStr
,
155 /** If value (passed as absolute value) is an integer representable as double,
156 which we handle explicitly at some places.
158 bool isRepresentableInteger(double fAbsValue
)
160 assert(fAbsValue
>= 0.0);
161 const sal_Int64 kMaxInt
= (static_cast< sal_Int64
>(1) << 53) - 1;
162 if (fAbsValue
<= static_cast< double >(kMaxInt
))
164 sal_Int64 nInt
= static_cast< sal_Int64
>(fAbsValue
);
165 // Check the integer range again because double comparison may yield
166 // true within the precision range.
167 // XXX loplugin:fpcomparison complains about floating-point comparison
168 // for static_cast<double>(nInt) == fAbsValue, though we actually want
172 double fInt
= static_cast< double >(nInt
);
173 return !(fInt
< fAbsValue
) && !(fInt
> fAbsValue
);
178 // Returns 1-based index of least significant bit in a number, or zero if number is zero
179 int findFirstSetBit(unsigned n
)
183 unsigned char bNonZero
= _BitScanForward(&pos
, n
);
184 return (bNonZero
== 0) ? 0 : pos
+ 1;
186 return __builtin_ffs(n
);
190 /** Returns number of binary bits for fractional part of the number
191 Expects a proper non-negative double value, not +-INF, not NAN
193 int getBitsInFracPart(double fAbsValue
)
195 assert(std::isfinite(fAbsValue
) && fAbsValue
>= 0.0);
196 if (fAbsValue
== 0.0)
198 auto pValParts
= reinterpret_cast< const sal_math_Double
* >(&fAbsValue
);
199 int nExponent
= pValParts
->inf_parts
.exponent
- 1023;
201 return 0; // All bits in fraction are in integer part of the number
202 int nLeastSignificant
= findFirstSetBit(pValParts
->inf_parts
.fraction_lo
);
203 if (nLeastSignificant
== 0)
205 nLeastSignificant
= findFirstSetBit(pValParts
->inf_parts
.fraction_hi
);
206 if (nLeastSignificant
== 0)
207 nLeastSignificant
= 53; // the implied leading 1 is the least significant
209 nLeastSignificant
+= 32;
211 int nFracSignificant
= 53 - nLeastSignificant
;
212 int nBitsInFracPart
= nFracSignificant
- nExponent
;
214 return std::max(nBitsInFracPart
, 0);
217 template< typename T
>
218 void doubleToString(typename
T::String
** pResult
,
219 sal_Int32
* pResultCapacity
, sal_Int32 nResultOffset
,
220 double fValue
, rtl_math_StringFormat eFormat
,
221 sal_Int32 nDecPlaces
, typename
T::Char cDecSeparator
,
222 sal_Int32
const * pGroups
,
223 typename
T::Char cGroupSeparator
,
224 bool bEraseTrailingDecZeros
)
226 static double const nRoundVal
[] = {
227 5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6,
228 0.5e-7, 0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14
231 // sign adjustment, instead of testing for fValue<0.0 this will also fetch
233 bool bSign
= std::signbit(fValue
);
238 if (std::isnan(fValue
))
240 // #i112652# XMLSchema-2
241 sal_Int32 nCapacity
= RTL_CONSTASCII_LENGTH("NaN");
242 if (!pResultCapacity
)
244 pResultCapacity
= &nCapacity
;
245 T::createBuffer(pResult
, pResultCapacity
);
249 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
,
250 RTL_CONSTASCII_STRINGPARAM("NaN"));
255 bool bHuge
= fValue
== HUGE_VAL
; // g++ 3.0.1 requires it this way...
256 if (bHuge
|| std::isinf(fValue
))
258 // #i112652# XMLSchema-2
259 sal_Int32 nCapacity
= RTL_CONSTASCII_LENGTH("-INF");
260 if (!pResultCapacity
)
262 pResultCapacity
= &nCapacity
;
263 T::createBuffer(pResult
, pResultCapacity
);
268 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
,
269 RTL_CONSTASCII_STRINGPARAM("-"));
271 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
,
272 RTL_CONSTASCII_STRINGPARAM("INF"));
277 // Unfortunately the old rounding below writes 1.79769313486232e+308 for
278 // DBL_MAX and 4 subsequent nextafter(...,0).
279 static const double fB1
= std::nextafter( DBL_MAX
, 0);
280 static const double fB2
= std::nextafter( fB1
, 0);
281 static const double fB3
= std::nextafter( fB2
, 0);
282 static const double fB4
= std::nextafter( fB3
, 0);
283 if ((fValue
>= fB4
) && eFormat
!= rtl_math_StringFormat_F
)
285 // 1.7976931348623157e+308 instead of rounded 1.79769313486232e+308
286 // that can't be converted back as out of range. For rounded values if
287 // they exceed range they should not be written to exchange strings or
290 // Writing pDig up to decimals(-1,-2) then appending one digit from
291 // pRou xor one or two digits from pSlot[].
292 constexpr char pDig
[] = "7976931348623157";
293 constexpr char pRou
[] = "8087931359623267"; // the only up-carry is 80
294 static_assert(SAL_N_ELEMENTS(pDig
) == SAL_N_ELEMENTS(pRou
), "digit count mismatch");
295 constexpr sal_Int32 nDig2
= RTL_CONSTASCII_LENGTH(pRou
) - 2;
296 sal_Int32 nCapacity
= RTL_CONSTASCII_LENGTH(pRou
) + 8; // + "-1.E+308"
297 const char pSlot
[5][2][3] =
299 "67", "57", // DBL_MAX
306 if (!pResultCapacity
)
308 pResultCapacity
= &nCapacity
;
309 T::createBuffer(pResult
, pResultCapacity
);
314 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
,
315 RTL_CONSTASCII_STRINGPARAM("-"));
317 nDecPlaces
= std::clamp
<sal_Int32
>( nDecPlaces
, 0, RTL_CONSTASCII_LENGTH(pRou
));
320 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
,
321 RTL_CONSTASCII_STRINGPARAM("2"));
325 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
,
326 RTL_CONSTASCII_STRINGPARAM("1"));
327 T::appendChars(pResult
, pResultCapacity
, &nResultOffset
, &cDecSeparator
, 1);
330 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
, pRou
, nDecPlaces
);
332 else if (nDecPlaces
<= nDig2
)
334 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
, pDig
, nDecPlaces
- 1);
335 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
, pRou
+ nDecPlaces
- 1, 1);
339 const sal_Int32 nDec
= nDecPlaces
- nDig2
;
341 // nDec-1 is also offset into slot, rounded(1-1=0) or not(2-1=1)
342 const size_t nSlot
= ((fValue
< fB3
) ? 4 : ((fValue
< fB2
) ? 3
343 : ((fValue
< fB1
) ? 2 : ((fValue
< DBL_MAX
) ? 1 : 0))));
345 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
, pDig
, nDecPlaces
);
346 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
, pSlot
[nSlot
][nDec
-1], nDec
);
349 T::appendAscii(pResult
, pResultCapacity
, &nResultOffset
,
350 RTL_CONSTASCII_STRINGPARAM("E+308"));
355 // Use integer representation for integer values that fit into the
356 // mantissa (1.((2^53)-1)) with a precision of 1 for highest accuracy.
357 const sal_Int64 kMaxInt
= (static_cast< sal_Int64
>(1) << 53) - 1;
358 if ((eFormat
== rtl_math_StringFormat_Automatic
||
359 eFormat
== rtl_math_StringFormat_F
) && fValue
<= static_cast< double >(kMaxInt
))
361 sal_Int64 nInt
= static_cast< sal_Int64
>(fValue
);
362 // Check the integer range again because double comparison may yield
363 // true within the precision range.
364 if (nInt
<= kMaxInt
&& static_cast< double >(nInt
) == fValue
)
366 if (nDecPlaces
== rtl_math_DecimalPlaces_Max
)
369 nDecPlaces
= ::std::clamp
< sal_Int32
>(nDecPlaces
, -15, 15);
371 if (bEraseTrailingDecZeros
&& nDecPlaces
> 0)
374 // Round before decimal position.
377 sal_Int64 nRounding
= static_cast< sal_Int64
>(getN10Exp(-nDecPlaces
- 1));
378 sal_Int64 nTemp
= nInt
/ nRounding
;
379 int nDigit
= nTemp
% 10;
391 // Max 1 sign, 16 integer digits, 15 group separators, 1 decimal
392 // separator, 15 decimals digits.
393 typename
T::Char aBuf
[64];
394 typename
T::Char
* pBuf
= aBuf
;
395 typename
T::Char
* p
= pBuf
;
398 size_t nGrouping
= 0;
399 sal_Int32 nGroupDigits
= 0;
402 typename
T::Char nDigit
= nInt
% 10;
405 if (pGroups
&& pGroups
[nGrouping
] == ++nGroupDigits
&& nInt
> 0 && cGroupSeparator
)
407 *p
++ = cGroupSeparator
;
408 if (pGroups
[nGrouping
+1])
417 // Reverse buffer content.
418 sal_Int32 n
= (p
- pBuf
) / 2;
419 for (sal_Int32 i
=0; i
< n
; ++i
)
421 ::std::swap( pBuf
[i
], p
[-i
-1]);
427 *p
++ = cDecSeparator
;
432 if (!pResultCapacity
)
433 T::createString(pResult
, pBuf
, p
- pBuf
);
435 T::appendChars(pResult
, pResultCapacity
, &nResultOffset
, pBuf
, p
- pBuf
);
445 // Cap nExp at a small value beyond which "fValue /= N10Exp" would lose precision (or N10Exp
446 // might even be zero); that will produce output with the decimal point in a non-normalized
447 // position, but the current quality of output for such small values is probably abysmal,
450 static_cast< int >(floor(log10(fValue
))), std::numeric_limits
<double>::min_exponent10
);
451 double const N10Exp
= getN10Exp(nExp
);
458 case rtl_math_StringFormat_Automatic
:
459 { // E or F depending on exponent magnitude
461 if (nExp
<= -15 || nExp
>= 15) // was <-16, >16 in ancient versions, which leads to inaccuracies
464 eFormat
= rtl_math_StringFormat_E
;
470 nPrec
= 15 - nExp
- 1;
471 eFormat
= rtl_math_StringFormat_F
;
476 eFormat
= rtl_math_StringFormat_F
;
480 if (nDecPlaces
== rtl_math_DecimalPlaces_Max
)
485 case rtl_math_StringFormat_G
:
486 case rtl_math_StringFormat_G1
:
487 case rtl_math_StringFormat_G2
:
488 { // G-Point, similar to sprintf %G
489 if (nDecPlaces
== rtl_math_DecimalPlaces_DefaultSignificance
)
492 if (nExp
< -4 || nExp
>= nDecPlaces
)
494 nDecPlaces
= std::max
< sal_Int32
>(1, nDecPlaces
- 1);
496 if (eFormat
== rtl_math_StringFormat_G
)
497 eFormat
= rtl_math_StringFormat_E
;
498 else if (eFormat
== rtl_math_StringFormat_G2
)
499 eFormat
= rtl_math_StringFormat_E2
;
500 else if (eFormat
== rtl_math_StringFormat_G1
)
501 eFormat
= rtl_math_StringFormat_E1
;
505 nDecPlaces
= std::max
< sal_Int32
>(0, nDecPlaces
- nExp
- 1);
506 eFormat
= rtl_math_StringFormat_F
;
514 // Too large values for nDecPlaces make no sense; it might also be
515 // rtl_math_DecimalPlaces_Max was passed with rtl_math_StringFormat_F or
516 // others, but we don't want to allocate/deallocate 2GB just to fill it
517 // with trailing '0' characters..
518 nDecPlaces
= std::clamp
<sal_Int32
>(nDecPlaces
, -20, 20);
520 sal_Int32 nDigits
= nDecPlaces
+ 1;
522 if (eFormat
== rtl_math_StringFormat_F
)
528 fValue
+= nRoundVal
[std::min
<sal_Int32
>(nDigits
, 15)];
534 if (eFormat
== rtl_math_StringFormat_F
)
539 static sal_Int32
const nBufMax
= 256;
540 typename
T::Char aBuf
[nBufMax
];
541 typename
T::Char
* pBuf
;
542 sal_Int32 nBuf
= static_cast< sal_Int32
>
543 (nDigits
<= 0 ? std::max
< sal_Int32
>(nDecPlaces
, abs(nExp
))
544 : nDigits
+ nDecPlaces
) + 10 + (pGroups
? abs(nDigits
) * 2 : 0);
548 pBuf
= static_cast< typename
T::Char
* >(
549 malloc(nBuf
* sizeof (typename
T::Char
)));
550 OSL_ENSURE(pBuf
, "Out of memory");
557 typename
T::Char
* p
= pBuf
;
559 *p
++ = static_cast< typename
T::Char
>('-');
561 bool bHasDec
= false;
564 // Check for F format and number < 1
565 if(eFormat
== rtl_math_StringFormat_F
)
569 *p
++ = static_cast< typename
T::Char
>('0');
572 *p
++ = cDecSeparator
;
576 sal_Int32 i
= (nDigits
<= 0 ? nDecPlaces
: -nExp
- 1);
580 *p
++ = static_cast< typename
T::Char
>('0');
595 int nGrouping
= 0, nGroupSelector
= 0, nGroupExceed
= 0;
596 if (nDecPos
> 1 && pGroups
&& pGroups
[0] && cGroupSeparator
)
598 while (nGrouping
+ pGroups
[nGroupSelector
] < nDecPos
)
600 nGrouping
+= pGroups
[nGroupSelector
];
601 if (pGroups
[nGroupSelector
+1])
603 if (nGrouping
+ pGroups
[nGroupSelector
+1] >= nDecPos
)
608 else if (!nGroupExceed
)
610 nGroupExceed
= nGrouping
;
618 for (int i
= 0; ; i
++)
620 if (i
< 15) // was 16 in ancient versions, which leads to inaccuracies
623 if (nDigits
-1 == 0 && i
> 0 && i
< 14)
624 nDigit
= static_cast< int >(floor( fValue
+ nCorrVal
[15-i
]));
626 nDigit
= static_cast< int >(fValue
+ 1E-15);
629 { // after-treatment of up-rounding to the next decade
630 sal_Int32 sLen
= static_cast< long >(p
-pBuf
)-1;
631 if (sLen
== -1 || (sLen
== 0 && bSign
))
633 // Assert that no one changed the logic we rely on.
634 assert(!bSign
|| *pBuf
== static_cast< typename
T::Char
>('-'));
638 if (eFormat
== rtl_math_StringFormat_F
)
640 *p
++ = static_cast< typename
T::Char
>('1');
641 *p
++ = static_cast< typename
T::Char
>('0');
645 *p
++ = static_cast< typename
T::Char
>('1');
646 *p
++ = cDecSeparator
;
647 *p
++ = static_cast< typename
T::Char
>('0');
654 for (sal_Int32 j
= sLen
; j
>= 0; j
--)
656 typename
T::Char cS
= pBuf
[j
];
659 // Do not touch leading minus sign put earlier.
660 assert(cS
== static_cast< typename
T::Char
>('-'));
661 break; // for, this is the last character backwards.
663 if (cS
!= cDecSeparator
)
665 if (cS
!= static_cast< typename
T::Char
>('9'))
668 j
= -1; // break loop
672 pBuf
[j
] = static_cast< typename
T::Char
>('0');
673 if (j
== 0 || (j
== 1 && bSign
))
675 if (eFormat
== rtl_math_StringFormat_F
)
677 typename
T::Char
* px
= p
++;
684 pBuf
[0] = static_cast< typename
T::Char
>('1');
688 pBuf
[j
] = static_cast< typename
T::Char
>('1');
696 *p
++ = static_cast< typename
T::Char
>('0');
702 *p
++ = static_cast< typename
T::Char
>(
703 nDigit
+ static_cast< typename
T::Char
>('0') );
704 fValue
= (fValue
- nDigit
) * 10.0;
709 *p
++ = static_cast< typename
T::Char
>('0');
719 *p
++ = cDecSeparator
;
722 else if (nDecPos
== nGrouping
)
724 *p
++ = cGroupSeparator
;
725 nGrouping
-= pGroups
[nGroupSelector
];
727 if (nGroupSelector
&& nGrouping
< nGroupExceed
)
734 if (!bHasDec
&& eFormat
== rtl_math_StringFormat_F
)
735 { // nDecPlaces < 0 did round the value
736 while (--nDecPos
> 0)
737 { // fill before decimal point
738 if (nDecPos
== nGrouping
)
740 *p
++ = cGroupSeparator
;
741 nGrouping
-= pGroups
[nGroupSelector
];
743 if (nGroupSelector
&& nGrouping
< nGroupExceed
)
747 *p
++ = static_cast< typename
T::Char
>('0');
751 if (bEraseTrailingDecZeros
&& bHasDec
&& p
> pBuf
)
753 while (*(p
-1) == static_cast< typename
T::Char
>('0'))
758 if (*(p
-1) == cDecSeparator
)
762 // Print the exponent ('E', followed by '+' or '-', followed by exactly
763 // three digits for rtl_math_StringFormat_E). The code in
764 // rtl_[u]str_valueOf{Float|Double} relies on this format.
765 if (eFormat
== rtl_math_StringFormat_E
|| eFormat
== rtl_math_StringFormat_E2
|| eFormat
== rtl_math_StringFormat_E1
)
768 *p
++ = static_cast< typename
T::Char
>('1');
769 // maybe no nDigits if nDecPlaces < 0
771 *p
++ = static_cast< typename
T::Char
>('E');
775 *p
++ = static_cast< typename
T::Char
>('-');
779 *p
++ = static_cast< typename
T::Char
>('+');
782 if (eFormat
== rtl_math_StringFormat_E
|| nExp
>= 100)
783 *p
++ = static_cast< typename
T::Char
>(
784 nExp
/ 100 + static_cast< typename
T::Char
>('0') );
788 if (eFormat
== rtl_math_StringFormat_E
|| eFormat
== rtl_math_StringFormat_E2
|| nExp
>= 10)
789 *p
++ = static_cast< typename
T::Char
>(
790 nExp
/ 10 + static_cast< typename
T::Char
>('0') );
792 *p
++ = static_cast< typename
T::Char
>(
793 nExp
% 10 + static_cast< typename
T::Char
>('0') );
796 if (!pResultCapacity
)
797 T::createString(pResult
, pBuf
, p
- pBuf
);
799 T::appendChars(pResult
, pResultCapacity
, &nResultOffset
, pBuf
, p
- pBuf
);
801 if (pBuf
!= &aBuf
[0])
807 void SAL_CALL
rtl_math_doubleToString(rtl_String
** pResult
,
808 sal_Int32
* pResultCapacity
,
809 sal_Int32 nResultOffset
, double fValue
,
810 rtl_math_StringFormat eFormat
,
811 sal_Int32 nDecPlaces
,
813 sal_Int32
const * pGroups
,
814 char cGroupSeparator
,
815 sal_Bool bEraseTrailingDecZeros
)
818 doubleToString
< StringTraits
>(
819 pResult
, pResultCapacity
, nResultOffset
, fValue
, eFormat
, nDecPlaces
,
820 cDecSeparator
, pGroups
, cGroupSeparator
, bEraseTrailingDecZeros
);
823 void SAL_CALL
rtl_math_doubleToUString(rtl_uString
** pResult
,
824 sal_Int32
* pResultCapacity
,
825 sal_Int32 nResultOffset
, double fValue
,
826 rtl_math_StringFormat eFormat
,
827 sal_Int32 nDecPlaces
,
828 sal_Unicode cDecSeparator
,
829 sal_Int32
const * pGroups
,
830 sal_Unicode cGroupSeparator
,
831 sal_Bool bEraseTrailingDecZeros
)
834 doubleToString
< UStringTraits
>(
835 pResult
, pResultCapacity
, nResultOffset
, fValue
, eFormat
, nDecPlaces
,
836 cDecSeparator
, pGroups
, cGroupSeparator
, bEraseTrailingDecZeros
);
841 template< typename CharT
>
842 double stringToDouble(CharT
const * pBegin
, CharT
const * pEnd
,
843 CharT cDecSeparator
, CharT cGroupSeparator
,
844 rtl_math_ConversionStatus
* pStatus
,
845 CharT
const ** pParsedEnd
)
848 rtl_math_ConversionStatus eStatus
= rtl_math_ConversionStatus_Ok
;
850 CharT
const * p0
= pBegin
;
851 while (p0
!= pEnd
&& (*p0
== CharT(' ') || *p0
== CharT('\t')))
857 if (p0
!= pEnd
&& *p0
== CharT('-'))
865 if (p0
!= pEnd
&& *p0
== CharT('+'))
869 CharT
const * p
= p0
;
872 // #i112652# XMLSchema-2
875 if ((CharT('N') == p
[0]) && (CharT('a') == p
[1])
876 && (CharT('N') == p
[2]))
879 rtl::math::setNan( &fVal
);
882 else if ((CharT('I') == p
[0]) && (CharT('N') == p
[1])
883 && (CharT('F') == p
[2]))
887 eStatus
= rtl_math_ConversionStatus_OutOfRange
;
892 if (!bDone
) // do not recognize e.g. NaN1.23
894 std::unique_ptr
<char[]> bufInHeap
;
895 std::unique_ptr
<const CharT
* []> bufInHeapMap
;
896 constexpr int bufOnStackSize
= 256;
897 char bufOnStack
[bufOnStackSize
];
898 const CharT
* bufOnStackMap
[bufOnStackSize
];
899 char* buf
= bufOnStack
;
900 const CharT
** bufmap
= bufOnStackMap
;
902 const size_t bufsize
= pEnd
- p
+ (bSign
? 2 : 1);
903 if (bufsize
> bufOnStackSize
)
905 bufInHeap
= std::make_unique
<char[]>(bufsize
);
906 bufInHeapMap
= std::make_unique
<const CharT
*[]>(bufsize
);
907 buf
= bufInHeap
.get();
908 bufmap
= bufInHeapMap
.get();
914 bufmap
[0] = p
; // yes, this may be the same pointer as for the next mapping
917 // Put first zero to buffer for strings like "-0"
918 if (p
!= pEnd
&& *p
== CharT('0'))
925 // Leading zeros and group separators between digits may be safely
926 // ignored. p0 < p implies that there was a leading 0 already,
927 // consecutive group separators may not happen as *(p+1) is checked for
929 while (p
!= pEnd
&& (*p
== CharT('0') || (*p
== cGroupSeparator
930 && p0
< p
&& p
+1 < pEnd
&& rtl::isAsciiDigit(*(p
+1)))))
935 // integer part of mantissa
936 for (; p
!= pEnd
; ++p
)
939 if (rtl::isAsciiDigit(c
))
941 buf
[bufpos
] = static_cast<char>(c
);
945 else if (c
!= cGroupSeparator
)
949 else if (p
== p0
|| (p
+1 == pEnd
) || !rtl::isAsciiDigit(*(p
+1)))
951 // A leading or trailing (not followed by a digit) group
952 // separator character is not a group separator.
957 // fraction part of mantissa
958 if (p
!= pEnd
&& *p
== cDecSeparator
)
965 for (; p
!= pEnd
; ++p
)
968 if (!rtl::isAsciiDigit(c
))
972 buf
[bufpos
] = static_cast<char>(c
);
979 if (p
!= p0
&& p
!= pEnd
&& (*p
== CharT('E') || *p
== CharT('e')))
985 if (p
!= pEnd
&& *p
== CharT('-'))
992 else if (p
!= pEnd
&& *p
== CharT('+'))
995 for (; p
!= pEnd
; ++p
)
998 if (!rtl::isAsciiDigit(c
))
1001 buf
[bufpos
] = static_cast<char>(c
);
1006 else if (p
- p0
== 2 && p
!= pEnd
&& p
[0] == CharT('#')
1007 && p
[-1] == cDecSeparator
&& p
[-2] == CharT('1'))
1009 if (pEnd
- p
>= 4 && p
[1] == CharT('I') && p
[2] == CharT('N')
1010 && p
[3] == CharT('F'))
1012 // "1.#INF", "+1.#INF", "-1.#INF"
1015 eStatus
= rtl_math_ConversionStatus_OutOfRange
;
1016 // Eat any further digits:
1017 while (p
!= pEnd
&& rtl::isAsciiDigit(*p
))
1021 else if (pEnd
- p
>= 4 && p
[1] == CharT('N') && p
[2] == CharT('A')
1022 && p
[3] == CharT('N'))
1024 // "1.#NAN", "+1.#NAN", "-1.#NAN"
1026 rtl::math::setNan( &fVal
);
1035 m
.md
.w32_parts
.msw
|= 0x80000000; // create negative NaN
1037 bSign
= false; // don't negate again
1040 // Eat any further digits:
1041 while (p
!= pEnd
&& rtl::isAsciiDigit(*p
))
1053 char* pCharParseEnd
;
1055 fVal
= strtod_nolocale(buf
, &pCharParseEnd
);
1056 if (errno
== ERANGE
)
1058 // Check for the dreaded rounded to 15 digits max value
1059 // 1.79769313486232e+308 for 1.7976931348623157e+308 we wrote
1060 // everywhere, accept with or without plus sign in exponent.
1061 const char* b
= buf
;
1064 if (((pCharParseEnd
- b
== 21) || (pCharParseEnd
- b
== 20))
1065 && !strncmp( b
, "1.79769313486232", 16)
1066 && (b
[16] == 'e' || b
[16] == 'E')
1067 && (((pCharParseEnd
- b
== 21) && !strncmp( b
+17, "+308", 4))
1068 || ((pCharParseEnd
- b
== 20) && !strncmp( b
+17, "308", 3))))
1070 fVal
= (buf
< b
) ? -DBL_MAX
: DBL_MAX
;
1074 eStatus
= rtl_math_ConversionStatus_OutOfRange
;
1077 p
= bufmap
[pCharParseEnd
- buf
];
1082 // overflow also if more than DBL_MAX_10_EXP digits without decimal
1083 // separator, or 0. and more than DBL_MIN_10_EXP digits, ...
1084 bool bHuge
= fVal
== HUGE_VAL
; // g++ 3.0.1 requires it this way...
1086 eStatus
= rtl_math_ConversionStatus_OutOfRange
;
1095 *pParsedEnd
= p
== p0
? pBegin
: p
;
1102 double SAL_CALL
rtl_math_stringToDouble(char const * pBegin
,
1105 char cGroupSeparator
,
1106 rtl_math_ConversionStatus
* pStatus
,
1107 char const ** pParsedEnd
)
1108 SAL_THROW_EXTERN_C()
1110 return stringToDouble(
1111 reinterpret_cast<unsigned char const *>(pBegin
),
1112 reinterpret_cast<unsigned char const *>(pEnd
),
1113 static_cast<unsigned char>(cDecSeparator
),
1114 static_cast<unsigned char>(cGroupSeparator
), pStatus
,
1115 reinterpret_cast<unsigned char const **>(pParsedEnd
));
1118 double SAL_CALL
rtl_math_uStringToDouble(sal_Unicode
const * pBegin
,
1119 sal_Unicode
const * pEnd
,
1120 sal_Unicode cDecSeparator
,
1121 sal_Unicode cGroupSeparator
,
1122 rtl_math_ConversionStatus
* pStatus
,
1123 sal_Unicode
const ** pParsedEnd
)
1124 SAL_THROW_EXTERN_C()
1126 return stringToDouble(pBegin
, pEnd
, cDecSeparator
, cGroupSeparator
, pStatus
,
1130 double SAL_CALL
rtl_math_round(double fValue
, int nDecPlaces
,
1131 enum rtl_math_RoundingMode eMode
)
1132 SAL_THROW_EXTERN_C()
1134 OSL_ASSERT(nDecPlaces
>= -20 && nDecPlaces
<= 20);
1136 if (!std::isfinite(fValue
))
1142 if ( nDecPlaces
== 0 && eMode
== rtl_math_RoundingMode_Corrected
)
1143 return std::round( fValue
);
1146 bool bSign
= std::signbit( fValue
);
1150 // Rounding to decimals between integer distance precision (gaps) does not
1151 // make sense, do not even try to multiply/divide and introduce inaccuracy.
1152 // For same reasons, do not attempt to round integers to decimals.
1154 && (fValue
>= (static_cast<sal_Int64
>(1) << 52)
1155 || isRepresentableInteger(fValue
)))
1156 return bSign
? -fValue
: fValue
;
1159 if (nDecPlaces
!= 0)
1161 if (nDecPlaces
> 1 && fValue
> 4294967296.0)
1163 // 4294967296 is 2^32 with room for at least 20 decimals, checking
1164 // smaller values is not necessary. Lower the limit if more than 20
1165 // decimals were to be allowed.
1167 // Determine how many decimals are representable in the precision.
1168 // Anything greater 2^52 and 0.0 was already ruled out above.
1169 // Theoretically 0.5, 0.25, 0.125, 0.0625, 0.03125, ...
1170 const sal_math_Double
* pd
= reinterpret_cast<const sal_math_Double
*>(&fValue
);
1171 const sal_Int32 nDec
= 52 - (pd
->parts
.exponent
- 1023);
1172 if (nDec
< nDecPlaces
)
1176 /* TODO: this was without the inverse factor and determining max
1177 * possible decimals, it could now be adjusted to be more lenient. */
1178 // max 20 decimals, we don't have unlimited precision
1179 // #38810# and no overflow on fValue*=fFac
1180 if (nDecPlaces
< -20 || 20 < nDecPlaces
|| fValue
> (DBL_MAX
/ 1e20
))
1181 return bSign
? -fValue
: fValue
;
1183 // Avoid 1e-5 (1.0000000000000001e-05) and such inaccurate fractional
1184 // factors that later when dividing back spoil things. For negative
1185 // decimals divide first with the inverse, then multiply the rounded
1187 fFac
= getN10Exp(abs(nDecPlaces
));
1194 // Round only if not already in distance precision gaps of integers, where
1195 // for [2^52,2^53) adding 0.5 would even yield the next representable
1197 if (fValue
< (static_cast<sal_Int64
>(1) << 52))
1201 case rtl_math_RoundingMode_Corrected
:
1202 fValue
= rtl::math::approxFloor(fValue
+ 0.5);
1204 case rtl_math_RoundingMode_Down
:
1205 fValue
= rtl::math::approxFloor(fValue
);
1207 case rtl_math_RoundingMode_Up
:
1208 fValue
= rtl::math::approxCeil(fValue
);
1210 case rtl_math_RoundingMode_Floor
:
1211 fValue
= bSign
? rtl::math::approxCeil(fValue
)
1212 : rtl::math::approxFloor( fValue
);
1214 case rtl_math_RoundingMode_Ceiling
:
1215 fValue
= bSign
? rtl::math::approxFloor(fValue
)
1216 : rtl::math::approxCeil(fValue
);
1218 case rtl_math_RoundingMode_HalfDown
:
1220 double f
= floor(fValue
);
1221 fValue
= ((fValue
- f
) <= 0.5) ? f
: ceil(fValue
);
1224 case rtl_math_RoundingMode_HalfUp
:
1226 double f
= floor(fValue
);
1227 fValue
= ((fValue
- f
) < 0.5) ? f
: ceil(fValue
);
1230 case rtl_math_RoundingMode_HalfEven
:
1231 #if defined FLT_ROUNDS
1233 Use fast version. FLT_ROUNDS may be defined to a function by some compilers!
1235 DBL_EPSILON is the smallest fractional number which can be represented,
1236 its reciprocal is therefore the smallest number that cannot have a
1237 fractional part. Once you add this reciprocal to `x', its fractional part
1238 is stripped off. Simply subtracting the reciprocal back out returns `x'
1239 without its fractional component.
1240 Simple, clever, and elegant - thanks to Ross Cottrell, the original author,
1241 who placed it into public domain.
1243 volatile: prevent compiler from being too smart
1245 if (FLT_ROUNDS
== 1)
1247 volatile double x
= fValue
+ 1.0 / DBL_EPSILON
;
1248 fValue
= x
- 1.0 / DBL_EPSILON
;
1251 #endif // FLT_ROUNDS
1253 double f
= floor(fValue
);
1254 if ((fValue
- f
) != 0.5)
1256 fValue
= floor( fValue
+ 0.5 );
1261 fValue
= (g
== floor( g
)) ? f
: (f
+ 1.0);
1271 if (nDecPlaces
!= 0)
1279 return bSign
? -fValue
: fValue
;
1282 double SAL_CALL
rtl_math_pow10Exp(double fValue
, int nExp
) SAL_THROW_EXTERN_C()
1284 return fValue
* getN10Exp(nExp
);
1287 double SAL_CALL
rtl_math_approxValue( double fValue
) SAL_THROW_EXTERN_C()
1289 const double fBigInt
= 2199023255552.0; // 2^41 -> only 11 bits left for fractional part, fine as decimal
1290 if (fValue
== 0.0 || fValue
== HUGE_VAL
|| !std::isfinite( fValue
) || fValue
> fBigInt
)
1292 // We don't handle these conditions. Bail out.
1296 double fOrigValue
= fValue
;
1298 bool bSign
= std::signbit(fValue
);
1302 // If the value is either integer representable as double,
1303 // or only has small number of bits in fraction part, then we need not do any approximation
1304 if (isRepresentableInteger(fValue
) || getBitsInFracPart(fValue
) <= 11)
1307 int nExp
= static_cast< int >(floor(log10(fValue
)));
1309 double fExpValue
= getN10Exp(abs(nExp
));
1312 fValue
/= fExpValue
;
1314 fValue
*= fExpValue
;
1316 // If the original value was near DBL_MIN we got an overflow. Restore and
1318 if (!std::isfinite(fValue
))
1321 fValue
= std::round(fValue
);
1324 fValue
*= fExpValue
;
1326 fValue
/= fExpValue
;
1328 // If the original value was near DBL_MAX we got an overflow. Restore and
1330 if (!std::isfinite(fValue
))
1333 return bSign
? -fValue
: fValue
;
1336 bool SAL_CALL
rtl_math_approxEqual(double a
, double b
) SAL_THROW_EXTERN_C()
1338 static const double e48
= 1.0 / (16777216.0 * 16777216.0);
1339 static const double e44
= e48
* 16.0;
1344 if (a
== 0.0 || b
== 0.0)
1347 const double d
= fabs(a
- b
);
1348 if (!std::isfinite(d
))
1349 return false; // Nan or Inf involved
1358 if (isRepresentableInteger(d
) && isRepresentableInteger(a
) && isRepresentableInteger(b
))
1359 return false; // special case for representable integers.
1361 return (d
< a
* e48
&& d
< b
* e48
);
1364 double SAL_CALL
rtl_math_expm1(double fValue
) SAL_THROW_EXTERN_C()
1366 return expm1(fValue
);
1369 double SAL_CALL
rtl_math_log1p(double fValue
) SAL_THROW_EXTERN_C()
1373 return fValue
; // macOS 10.8 libc returns 0.0 for -0.0
1376 return log1p(fValue
);
1379 double SAL_CALL
rtl_math_atanh(double fValue
) SAL_THROW_EXTERN_C()
1380 #if defined __clang__
1381 __attribute__((no_sanitize("float-divide-by-zero"))) // atahn(1) -> inf
1384 return 0.5 * rtl_math_log1p(2.0 * fValue
/ (1.0-fValue
));
1387 /** Parent error function (erf) */
1388 double SAL_CALL
rtl_math_erf(double x
) SAL_THROW_EXTERN_C()
1393 /** Parent complementary error function (erfc) */
1394 double SAL_CALL
rtl_math_erfc(double x
) SAL_THROW_EXTERN_C()
1399 /** improved accuracy of asinh for |x| large and for x near zero
1402 double SAL_CALL
rtl_math_asinh(double fX
) SAL_THROW_EXTERN_C()
1415 return fSign
* rtl_math_log1p( fX
+ fX
*fX
/ (1.0 + sqrt( 1.0 + fX
*fX
)));
1418 return fSign
* log( fX
+ sqrt( 1.0 + fX
*fX
));
1420 return fSign
* log( 2.0*fX
);
1423 /** improved accuracy of acosh for x large and for x near 1
1426 double SAL_CALL
rtl_math_acosh(double fX
) SAL_THROW_EXTERN_C()
1428 volatile double fZ
= fX
- 1.0;
1432 ::rtl::math::setNan( &fResult
);
1439 return rtl_math_log1p( fZ
+ sqrt( fZ
*fZ
+ 2.0*fZ
));
1442 return log( fX
+ sqrt( fX
*fX
- 1.0));
1444 return log( 2.0*fX
);
1447 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */