nss: upgrade to release 3.73
[LibreOffice.git] / sal / rtl / math.cxx
bloba85c8ac6e95940188de708987f49e7141f4f2b6b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <rtl/math.h>
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>
34 #include <algorithm>
35 #include <cassert>
36 #include <float.h>
37 #include <limits>
38 #include <limits.h>
39 #include <math.h>
40 #include <memory>
41 #include <stdlib.h>
43 #include <dtoa.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)
56 if (nExp < 0)
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));
64 if (nExp > 0)
66 if (nExp <= n10Count)
67 return n10s[0][nExp-1];
69 return pow(10.0, static_cast<double>(nExp));
71 return 1.0;
74 namespace {
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
81 struct StringTraits
83 typedef char Char;
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,
101 sal_Int32 nLen)
103 assert(pChars);
104 rtl_stringbuffer_insert(pBuffer, pCapacity, *pOffset, pChars, nLen);
105 *pOffset += nLen;
108 static void appendAscii(rtl_String ** pBuffer, sal_Int32 * pCapacity,
109 sal_Int32 * pOffset, char const * pStr,
110 sal_Int32 nLen)
112 assert(pStr);
113 rtl_stringbuffer_insert(pBuffer, pCapacity, *pOffset, pStr, nLen);
114 *pOffset += nLen;
118 struct UStringTraits
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)
140 assert(pChars);
141 rtl_uStringbuffer_insert(pBuffer, pCapacity, *pOffset, pChars, nLen);
142 *pOffset += 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,
150 nLen);
151 *pOffset += nLen;
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
169 // this here.
170 if (nInt > kMaxInt)
171 return false;
172 double fInt = static_cast< double >(nInt);
173 return !(fInt < fAbsValue) && !(fInt > fAbsValue);
175 return false;
178 // Returns 1-based index of least significant bit in a number, or zero if number is zero
179 int findFirstSetBit(unsigned n)
181 #if defined _WIN32
182 unsigned long pos;
183 unsigned char bNonZero = _BitScanForward(&pos, n);
184 return (bNonZero == 0) ? 0 : pos + 1;
185 #else
186 return __builtin_ffs(n);
187 #endif
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)
197 return 0;
198 auto pValParts = reinterpret_cast< const sal_math_Double * >(&fAbsValue);
199 int nExponent = pValParts->inf_parts.exponent - 1023;
200 if (nExponent >= 52)
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
208 else
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
232 // -0.0
233 bool bSign = std::signbit(fValue);
235 if (bSign)
236 fValue = -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);
246 nResultOffset = 0;
249 T::appendAscii(pResult, pResultCapacity, &nResultOffset,
250 RTL_CONSTASCII_STRINGPARAM("NaN"));
252 return;
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);
264 nResultOffset = 0;
267 if ( bSign )
268 T::appendAscii(pResult, pResultCapacity, &nResultOffset,
269 RTL_CONSTASCII_STRINGPARAM("-"));
271 T::appendAscii(pResult, pResultCapacity, &nResultOffset,
272 RTL_CONSTASCII_STRINGPARAM("INF"));
274 return;
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
288 // file formats.
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] =
298 { // rounded, not
299 "67", "57", // DBL_MAX
300 "65", "55",
301 "53", "53",
302 "51", "51",
303 "59", "49",
306 if (!pResultCapacity)
308 pResultCapacity = &nCapacity;
309 T::createBuffer(pResult, pResultCapacity);
310 nResultOffset = 0;
313 if (bSign)
314 T::appendAscii(pResult, pResultCapacity, &nResultOffset,
315 RTL_CONSTASCII_STRINGPARAM("-"));
317 nDecPlaces = std::clamp<sal_Int32>( nDecPlaces, 0, RTL_CONSTASCII_LENGTH(pRou));
318 if (nDecPlaces == 0)
320 T::appendAscii(pResult, pResultCapacity, &nResultOffset,
321 RTL_CONSTASCII_STRINGPARAM("2"));
323 else
325 T::appendAscii(pResult, pResultCapacity, &nResultOffset,
326 RTL_CONSTASCII_STRINGPARAM("1"));
327 T::appendChars(pResult, pResultCapacity, &nResultOffset, &cDecSeparator, 1);
328 if (nDecPlaces <= 2)
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);
337 else
339 const sal_Int32 nDec = nDecPlaces - nDig2;
340 nDecPlaces -= nDec;
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"));
352 return;
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)
367 nDecPlaces = 0;
368 else
369 nDecPlaces = ::std::clamp< sal_Int32 >(nDecPlaces, -15, 15);
371 if (bEraseTrailingDecZeros && nDecPlaces > 0)
372 nDecPlaces = 0;
374 // Round before decimal position.
375 if (nDecPlaces < 0)
377 sal_Int64 nRounding = static_cast< sal_Int64 >(getN10Exp(-nDecPlaces - 1));
378 sal_Int64 nTemp = nInt / nRounding;
379 int nDigit = nTemp % 10;
380 nTemp /= 10;
382 if (nDigit >= 5)
383 ++nTemp;
385 nTemp *= 10;
386 nTemp *= nRounding;
387 nInt = nTemp;
388 nDecPlaces = 0;
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;
397 // Backward fill.
398 size_t nGrouping = 0;
399 sal_Int32 nGroupDigits = 0;
402 typename T::Char nDigit = nInt % 10;
403 nInt /= 10;
404 *p++ = nDigit + '0';
405 if (pGroups && pGroups[nGrouping] == ++nGroupDigits && nInt > 0 && cGroupSeparator)
407 *p++ = cGroupSeparator;
408 if (pGroups[nGrouping+1])
409 ++nGrouping;
410 nGroupDigits = 0;
413 while (nInt > 0);
414 if (bSign)
415 *p++ = '-';
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]);
424 // Append decimals.
425 if (nDecPlaces > 0)
427 *p++ = cDecSeparator;
428 while (nDecPlaces--)
429 *p++ = '0';
432 if (!pResultCapacity)
433 T::createString(pResult, pBuf, p - pBuf);
434 else
435 T::appendChars(pResult, pResultCapacity, &nResultOffset, pBuf, p - pBuf);
437 return;
441 // find the exponent
442 int nExp = 0;
443 if ( fValue > 0.0 )
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,
448 // anyway:
449 nExp = std::max(
450 static_cast< int >(floor(log10(fValue))), std::numeric_limits<double>::min_exponent10);
451 double const N10Exp = getN10Exp(nExp);
452 assert(N10Exp != 0);
453 fValue /= N10Exp;
456 switch (eFormat)
458 case rtl_math_StringFormat_Automatic:
459 { // E or F depending on exponent magnitude
460 int nPrec;
461 if (nExp <= -15 || nExp >= 15) // was <-16, >16 in ancient versions, which leads to inaccuracies
463 nPrec = 14;
464 eFormat = rtl_math_StringFormat_E;
466 else
468 if (nExp < 14)
470 nPrec = 15 - nExp - 1;
471 eFormat = rtl_math_StringFormat_F;
473 else
475 nPrec = 15;
476 eFormat = rtl_math_StringFormat_F;
480 if (nDecPlaces == rtl_math_DecimalPlaces_Max)
481 nDecPlaces = nPrec;
483 break;
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)
490 nDecPlaces = 6;
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;
503 else
505 nDecPlaces = std::max< sal_Int32 >(0, nDecPlaces - nExp - 1);
506 eFormat = rtl_math_StringFormat_F;
509 break;
510 default:
511 break;
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)
523 nDigits += nExp;
525 // Round the number
526 if(nDigits >= 0)
528 fValue += nRoundVal[std::min<sal_Int32>(nDigits, 15)];
529 if (fValue >= 10)
531 fValue = 1.0;
532 nExp++;
534 if (eFormat == rtl_math_StringFormat_F)
535 nDigits++;
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);
546 if (nBuf > nBufMax)
548 pBuf = static_cast< typename T::Char * >(
549 malloc(nBuf * sizeof (typename T::Char)));
550 OSL_ENSURE(pBuf, "Out of memory");
552 else
554 pBuf = aBuf;
557 typename T::Char * p = pBuf;
558 if ( bSign )
559 *p++ = static_cast< typename T::Char >('-');
561 bool bHasDec = false;
563 int nDecPos;
564 // Check for F format and number < 1
565 if(eFormat == rtl_math_StringFormat_F)
567 if(nExp < 0)
569 *p++ = static_cast< typename T::Char >('0');
570 if (nDecPlaces > 0)
572 *p++ = cDecSeparator;
573 bHasDec = true;
576 sal_Int32 i = (nDigits <= 0 ? nDecPlaces : -nExp - 1);
578 while((i--) > 0)
580 *p++ = static_cast< typename T::Char >('0');
583 nDecPos = 0;
585 else
587 nDecPos = nExp + 1;
590 else
592 nDecPos = 1;
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)
604 break; // while
606 ++nGroupSelector;
608 else if (!nGroupExceed)
610 nGroupExceed = nGrouping;
615 // print the number
616 if (nDigits > 0)
618 for (int i = 0; ; i++)
620 if (i < 15) // was 16 in ancient versions, which leads to inaccuracies
622 int nDigit;
623 if (nDigits-1 == 0 && i > 0 && i < 14)
624 nDigit = static_cast< int >(floor( fValue + nCorrVal[15-i]));
625 else
626 nDigit = static_cast< int >(fValue + 1E-15);
628 if (nDigit >= 10)
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 >('-'));
635 p = pBuf;
636 if (bSign)
637 ++p;
638 if (eFormat == rtl_math_StringFormat_F)
640 *p++ = static_cast< typename T::Char >('1');
641 *p++ = static_cast< typename T::Char >('0');
643 else
645 *p++ = static_cast< typename T::Char >('1');
646 *p++ = cDecSeparator;
647 *p++ = static_cast< typename T::Char >('0');
648 nExp++;
649 bHasDec = true;
652 else
654 for (sal_Int32 j = sLen; j >= 0; j--)
656 typename T::Char cS = pBuf[j];
657 if (j == 0 && bSign)
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'))
667 pBuf[j] = ++cS;
668 j = -1; // break loop
670 else
672 pBuf[j] = static_cast< typename T::Char >('0');
673 if (j == 0 || (j == 1 && bSign))
675 if (eFormat == rtl_math_StringFormat_F)
676 { // insert '1'
677 typename T::Char * px = p++;
678 while (pBuf < px)
680 *px = *(px-1);
681 px--;
684 pBuf[0] = static_cast< typename T::Char >('1');
686 else
688 pBuf[j] = static_cast< typename T::Char >('1');
689 nExp++;
696 *p++ = static_cast< typename T::Char >('0');
698 fValue = 0.0;
700 else
702 *p++ = static_cast< typename T::Char >(
703 nDigit + static_cast< typename T::Char >('0') );
704 fValue = (fValue - nDigit) * 10.0;
707 else
709 *p++ = static_cast< typename T::Char >('0');
712 if (!--nDigits)
713 break; // for
715 if (nDecPos)
717 if(!--nDecPos)
719 *p++ = cDecSeparator;
720 bHasDec = true;
722 else if (nDecPos == nGrouping)
724 *p++ = cGroupSeparator;
725 nGrouping -= pGroups[nGroupSelector];
727 if (nGroupSelector && nGrouping < nGroupExceed)
728 --nGroupSelector;
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)
744 --nGroupSelector;
747 *p++ = static_cast< typename T::Char >('0');
751 if (bEraseTrailingDecZeros && bHasDec && p > pBuf)
753 while (*(p-1) == static_cast< typename T::Char >('0'))
755 p--;
758 if (*(p-1) == cDecSeparator)
759 p--;
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)
767 if (p == pBuf)
768 *p++ = static_cast< typename T::Char >('1');
769 // maybe no nDigits if nDecPlaces < 0
771 *p++ = static_cast< typename T::Char >('E');
772 if(nExp < 0)
774 nExp = -nExp;
775 *p++ = static_cast< typename T::Char >('-');
777 else
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') );
786 nExp %= 100;
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);
798 else
799 T::appendChars(pResult, pResultCapacity, &nResultOffset, pBuf, p - pBuf);
801 if (pBuf != &aBuf[0])
802 free(pBuf);
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,
812 char cDecSeparator,
813 sal_Int32 const * pGroups,
814 char cGroupSeparator,
815 sal_Bool bEraseTrailingDecZeros)
816 SAL_THROW_EXTERN_C()
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)
832 SAL_THROW_EXTERN_C()
834 doubleToString< UStringTraits >(
835 pResult, pResultCapacity, nResultOffset, fValue, eFormat, nDecPlaces,
836 cDecSeparator, pGroups, cGroupSeparator, bEraseTrailingDecZeros);
839 namespace {
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)
847 double fVal = 0.0;
848 rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
850 CharT const * p0 = pBegin;
851 while (p0 != pEnd && (*p0 == CharT(' ') || *p0 == CharT('\t')))
853 ++p0;
856 bool bSign;
857 if (p0 != pEnd && *p0 == CharT('-'))
859 bSign = true;
860 ++p0;
862 else
864 bSign = false;
865 if (p0 != pEnd && *p0 == CharT('+'))
866 ++p0;
869 CharT const * p = p0;
870 bool bDone = false;
872 // #i112652# XMLSchema-2
873 if ((pEnd - p) >= 3)
875 if ((CharT('N') == p[0]) && (CharT('a') == p[1])
876 && (CharT('N') == p[2]))
878 p += 3;
879 rtl::math::setNan( &fVal );
880 bDone = true;
882 else if ((CharT('I') == p[0]) && (CharT('N') == p[1])
883 && (CharT('F') == p[2]))
885 p += 3;
886 fVal = HUGE_VAL;
887 eStatus = rtl_math_ConversionStatus_OutOfRange;
888 bDone = true;
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;
901 int bufpos = 0;
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();
911 if (bSign)
913 buf[0] = '-';
914 bufmap[0] = p; // yes, this may be the same pointer as for the next mapping
915 bufpos = 1;
917 // Put first zero to buffer for strings like "-0"
918 if (p != pEnd && *p == CharT('0'))
920 buf[bufpos] = '0';
921 bufmap[bufpos] = p;
922 ++bufpos;
923 ++p;
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
928 // digit.
929 while (p != pEnd && (*p == CharT('0') || (*p == cGroupSeparator
930 && p0 < p && p+1 < pEnd && rtl::isAsciiDigit(*(p+1)))))
932 ++p;
935 // integer part of mantissa
936 for (; p != pEnd; ++p)
938 CharT c = *p;
939 if (rtl::isAsciiDigit(c))
941 buf[bufpos] = static_cast<char>(c);
942 bufmap[bufpos] = p;
943 ++bufpos;
945 else if (c != cGroupSeparator)
947 break;
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.
953 break;
957 // fraction part of mantissa
958 if (p != pEnd && *p == cDecSeparator)
960 buf[bufpos] = '.';
961 bufmap[bufpos] = p;
962 ++bufpos;
963 ++p;
965 for (; p != pEnd; ++p)
967 CharT c = *p;
968 if (!rtl::isAsciiDigit(c))
970 break;
972 buf[bufpos] = static_cast<char>(c);
973 bufmap[bufpos] = p;
974 ++bufpos;
978 // Exponent
979 if (p != p0 && p != pEnd && (*p == CharT('E') || *p == CharT('e')))
981 buf[bufpos] = 'E';
982 bufmap[bufpos] = p;
983 ++bufpos;
984 ++p;
985 if (p != pEnd && *p == CharT('-'))
987 buf[bufpos] = '-';
988 bufmap[bufpos] = p;
989 ++bufpos;
990 ++p;
992 else if (p != pEnd && *p == CharT('+'))
993 ++p;
995 for (; p != pEnd; ++p)
997 CharT c = *p;
998 if (!rtl::isAsciiDigit(c))
999 break;
1001 buf[bufpos] = static_cast<char>(c);
1002 bufmap[bufpos] = p;
1003 ++bufpos;
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"
1013 p += 4;
1014 fVal = HUGE_VAL;
1015 eStatus = rtl_math_ConversionStatus_OutOfRange;
1016 // Eat any further digits:
1017 while (p != pEnd && rtl::isAsciiDigit(*p))
1018 ++p;
1019 bDone = true;
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"
1025 p += 4;
1026 rtl::math::setNan( &fVal );
1027 if (bSign)
1029 union {
1030 double sd;
1031 sal_math_Double md;
1032 } m;
1034 m.sd = fVal;
1035 m.md.w32_parts.msw |= 0x80000000; // create negative NaN
1036 fVal = m.sd;
1037 bSign = false; // don't negate again
1040 // Eat any further digits:
1041 while (p != pEnd && rtl::isAsciiDigit(*p))
1043 ++p;
1045 bDone = true;
1049 if (!bDone)
1051 buf[bufpos] = '\0';
1052 bufmap[bufpos] = p;
1053 char* pCharParseEnd;
1054 errno = 0;
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;
1062 if (b[0] == '-')
1063 ++b;
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;
1072 else
1074 eStatus = rtl_math_ConversionStatus_OutOfRange;
1077 p = bufmap[pCharParseEnd - buf];
1078 bSign = false;
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...
1085 if (bHuge)
1086 eStatus = rtl_math_ConversionStatus_OutOfRange;
1088 if (bSign)
1089 fVal = -fVal;
1091 if (pStatus)
1092 *pStatus = eStatus;
1094 if (pParsedEnd)
1095 *pParsedEnd = p == p0 ? pBegin : p;
1097 return fVal;
1102 double SAL_CALL rtl_math_stringToDouble(char const * pBegin,
1103 char const * pEnd,
1104 char cDecSeparator,
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,
1127 pParsedEnd);
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))
1137 return fValue;
1139 if (fValue == 0.0)
1140 return fValue;
1142 if ( nDecPlaces == 0 && eMode == rtl_math_RoundingMode_Corrected )
1143 return std::round( fValue );
1145 // sign adjustment
1146 bool bSign = std::signbit( fValue );
1147 if (bSign)
1148 fValue = -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.
1153 if (nDecPlaces >= 0
1154 && (fValue >= (static_cast<sal_Int64>(1) << 52)
1155 || isRepresentableInteger(fValue)))
1156 return bSign ? -fValue : fValue;
1158 double fFac = 0;
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)
1173 nDecPlaces = nDec;
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
1186 // value back.
1187 fFac = getN10Exp(abs(nDecPlaces));
1188 if (nDecPlaces < 0)
1189 fValue /= fFac;
1190 else
1191 fValue *= fFac;
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
1196 // integer.
1197 if (fValue < (static_cast<sal_Int64>(1) << 52))
1199 switch ( eMode )
1201 case rtl_math_RoundingMode_Corrected :
1202 fValue = rtl::math::approxFloor(fValue + 0.5);
1203 break;
1204 case rtl_math_RoundingMode_Down:
1205 fValue = rtl::math::approxFloor(fValue);
1206 break;
1207 case rtl_math_RoundingMode_Up:
1208 fValue = rtl::math::approxCeil(fValue);
1209 break;
1210 case rtl_math_RoundingMode_Floor:
1211 fValue = bSign ? rtl::math::approxCeil(fValue)
1212 : rtl::math::approxFloor( fValue );
1213 break;
1214 case rtl_math_RoundingMode_Ceiling:
1215 fValue = bSign ? rtl::math::approxFloor(fValue)
1216 : rtl::math::approxCeil(fValue);
1217 break;
1218 case rtl_math_RoundingMode_HalfDown :
1220 double f = floor(fValue);
1221 fValue = ((fValue - f) <= 0.5) ? f : ceil(fValue);
1223 break;
1224 case rtl_math_RoundingMode_HalfUp:
1226 double f = floor(fValue);
1227 fValue = ((fValue - f) < 0.5) ? f : ceil(fValue);
1229 break;
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;
1250 else
1251 #endif // FLT_ROUNDS
1253 double f = floor(fValue);
1254 if ((fValue - f) != 0.5)
1256 fValue = floor( fValue + 0.5 );
1258 else
1260 double g = f / 2.0;
1261 fValue = (g == floor( g )) ? f : (f + 1.0);
1264 break;
1265 default:
1266 OSL_ASSERT(false);
1267 break;
1271 if (nDecPlaces != 0)
1273 if (nDecPlaces < 0)
1274 fValue *= fFac;
1275 else
1276 fValue /= fFac;
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.
1293 return fValue;
1296 double fOrigValue = fValue;
1298 bool bSign = std::signbit(fValue);
1299 if (bSign)
1300 fValue = -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)
1305 return fOrigValue;
1307 int nExp = static_cast< int >(floor(log10(fValue)));
1308 nExp = 14 - nExp;
1309 double fExpValue = getN10Exp(abs(nExp));
1311 if (nExp < 0)
1312 fValue /= fExpValue;
1313 else
1314 fValue *= fExpValue;
1316 // If the original value was near DBL_MIN we got an overflow. Restore and
1317 // bail out.
1318 if (!std::isfinite(fValue))
1319 return fOrigValue;
1321 fValue = std::round(fValue);
1323 if (nExp < 0)
1324 fValue *= fExpValue;
1325 else
1326 fValue /= fExpValue;
1328 // If the original value was near DBL_MAX we got an overflow. Restore and
1329 // bail out.
1330 if (!std::isfinite(fValue))
1331 return fOrigValue;
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;
1341 if (a == b)
1342 return true;
1344 if (a == 0.0 || b == 0.0)
1345 return false;
1347 const double d = fabs(a - b);
1348 if (!std::isfinite(d))
1349 return false; // Nan or Inf involved
1351 a = fabs(a);
1352 if (d > (a * e44))
1353 return false;
1354 b = fabs(b);
1355 if (d > (b * e44))
1356 return false;
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()
1371 #ifdef __APPLE__
1372 if (fValue == -0.0)
1373 return fValue; // macOS 10.8 libc returns 0.0 for -0.0
1374 #endif
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
1382 #endif
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()
1390 return erf(x);
1393 /** Parent complementary error function (erfc) */
1394 double SAL_CALL rtl_math_erfc(double x) SAL_THROW_EXTERN_C()
1396 return erfc(x);
1399 /** improved accuracy of asinh for |x| large and for x near zero
1400 @see #i97605#
1402 double SAL_CALL rtl_math_asinh(double fX) SAL_THROW_EXTERN_C()
1404 if ( fX == 0.0 )
1405 return 0.0;
1407 double fSign = 1.0;
1408 if ( fX < 0.0 )
1410 fX = - fX;
1411 fSign = -1.0;
1414 if ( fX < 0.125 )
1415 return fSign * rtl_math_log1p( fX + fX*fX / (1.0 + sqrt( 1.0 + fX*fX)));
1417 if ( fX < 1.25e7 )
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
1424 @see #i97605#
1426 double SAL_CALL rtl_math_acosh(double fX) SAL_THROW_EXTERN_C()
1428 volatile double fZ = fX - 1.0;
1429 if (fX < 1.0)
1431 double fResult;
1432 ::rtl::math::setNan( &fResult );
1433 return fResult;
1435 if ( fX == 1.0 )
1436 return 0.0;
1438 if ( fX < 1.1 )
1439 return rtl_math_log1p( fZ + sqrt( fZ*fZ + 2.0*fZ));
1441 if ( fX < 1.25e7 )
1442 return log( fX + sqrt( fX*fX - 1.0));
1444 return log( 2.0*fX);
1447 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */