Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sal / rtl / math.cxx
blobd9ad08dfaf52a0bdd4052b6d230783bbecd90197
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 <config_global.h>
23 #include <o3tl/safeint.hxx>
24 #include <osl/diagnose.h>
25 #include <rtl/alloc.h>
26 #include <rtl/character.hxx>
27 #include <rtl/math.hxx>
28 #include <rtl/strbuf.h>
29 #include <rtl/string.h>
30 #include <rtl/ustrbuf.h>
31 #include <rtl/ustring.h>
32 #include <sal/mathconf.h>
33 #include <sal/types.h>
35 #include <algorithm>
36 #include <cassert>
37 #include <float.h>
38 #include <limits>
39 #include <limits.h>
40 #include <math.h>
41 #include <stdlib.h>
43 #if !HAVE_GCC_BUILTIN_FFS && !defined _WIN32
44 #include <strings.h>
45 #endif
47 static int const n10Count = 16;
48 static double const n10s[2][n10Count] = {
49 { 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8,
50 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16 },
51 { 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8,
52 1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16 }
55 // return pow(10.0,nExp) optimized for exponents in the interval [-16,16]
56 static double getN10Exp(int nExp)
58 if (nExp < 0)
60 // && -nExp > 0 necessary for std::numeric_limits<int>::min()
61 // because -nExp = nExp
62 if (-nExp <= n10Count && -nExp > 0)
63 return n10s[1][-nExp-1];
64 return pow(10.0, static_cast<double>(nExp));
66 if (nExp > 0)
68 if (nExp <= n10Count)
69 return n10s[0][nExp-1];
71 return pow(10.0, static_cast<double>(nExp));
73 return 1.0;
76 namespace {
78 double const nCorrVal[] = {
79 0, 9e-1, 9e-2, 9e-3, 9e-4, 9e-5, 9e-6, 9e-7, 9e-8,
80 9e-9, 9e-10, 9e-11, 9e-12, 9e-13, 9e-14, 9e-15
83 struct StringTraits
85 typedef sal_Char Char;
87 typedef rtl_String String;
89 static void createString(rtl_String ** pString,
90 sal_Char const * pChars, sal_Int32 nLen)
92 rtl_string_newFromStr_WithLength(pString, pChars, nLen);
95 static void createBuffer(rtl_String ** pBuffer,
96 const sal_Int32 * pCapacity)
98 rtl_string_new_WithLength(pBuffer, *pCapacity);
101 static void appendChars(rtl_String ** pBuffer, sal_Int32 * pCapacity,
102 sal_Int32 * pOffset, sal_Char const * pChars,
103 sal_Int32 nLen)
105 assert(pChars);
106 rtl_stringbuffer_insert(pBuffer, pCapacity, *pOffset, pChars, nLen);
107 *pOffset += nLen;
110 static void appendAscii(rtl_String ** pBuffer, sal_Int32 * pCapacity,
111 sal_Int32 * pOffset, sal_Char const * pStr,
112 sal_Int32 nLen)
114 assert(pStr);
115 rtl_stringbuffer_insert(pBuffer, pCapacity, *pOffset, pStr, nLen);
116 *pOffset += nLen;
120 struct UStringTraits
122 typedef sal_Unicode Char;
124 typedef rtl_uString String;
126 static void createString(rtl_uString ** pString,
127 sal_Unicode const * pChars, sal_Int32 nLen)
129 rtl_uString_newFromStr_WithLength(pString, pChars, nLen);
132 static void createBuffer(rtl_uString ** pBuffer,
133 const sal_Int32 * pCapacity)
135 rtl_uString_new_WithLength(pBuffer, *pCapacity);
138 static void appendChars(rtl_uString ** pBuffer,
139 sal_Int32 * pCapacity, sal_Int32 * pOffset,
140 sal_Unicode const * pChars, sal_Int32 nLen)
142 assert(pChars);
143 rtl_uStringbuffer_insert(pBuffer, pCapacity, *pOffset, pChars, nLen);
144 *pOffset += nLen;
147 static void appendAscii(rtl_uString ** pBuffer,
148 sal_Int32 * pCapacity, sal_Int32 * pOffset,
149 sal_Char const * pStr, sal_Int32 nLen)
151 rtl_uStringbuffer_insert_ascii(pBuffer, pCapacity, *pOffset, pStr,
152 nLen);
153 *pOffset += nLen;
157 /** If value (passed as absolute value) is an integer representable as double,
158 which we handle explicitly at some places.
160 bool isRepresentableInteger(double fAbsValue)
162 assert(fAbsValue >= 0.0);
163 const sal_Int64 kMaxInt = (static_cast< sal_Int64 >(1) << 53) - 1;
164 if (fAbsValue <= static_cast< double >(kMaxInt))
166 sal_Int64 nInt = static_cast< sal_Int64 >(fAbsValue);
167 // Check the integer range again because double comparison may yield
168 // true within the precision range.
169 // XXX loplugin:fpcomparison complains about floating-point comparison
170 // for static_cast<double>(nInt) == fAbsValue, though we actually want
171 // this here.
172 double fInt;
173 return (nInt <= kMaxInt &&
174 (!((fInt = static_cast< double >(nInt)) < fAbsValue) && !(fInt > fAbsValue)));
176 return false;
179 // Returns 1-based index of least significant bit in a number, or zero if number is zero
180 int findFirstSetBit(unsigned n)
182 #if HAVE_GCC_BUILTIN_FFS
183 return __builtin_ffs(n);
184 #elif defined _WIN32
185 unsigned long pos;
186 unsigned char bNonZero = _BitScanForward(&pos, n);
187 return (bNonZero == 0) ? 0 : pos + 1;
188 #else
189 return ffs(n);
190 #endif
193 /** Returns number of binary bits for fractional part of the number
194 Expects a proper non-negative double value, not +-INF, not NAN
196 int getBitsInFracPart(double fAbsValue)
198 assert(rtl::math::isFinite(fAbsValue) && fAbsValue >= 0.0);
199 if (fAbsValue == 0.0)
200 return 0;
201 auto pValParts = reinterpret_cast< const sal_math_Double * >(&fAbsValue);
202 int nExponent = pValParts->inf_parts.exponent - 1023;
203 if (nExponent >= 52)
204 return 0; // All bits in fraction are in integer part of the number
205 int nLeastSignificant = findFirstSetBit(pValParts->inf_parts.fraction_lo);
206 if (nLeastSignificant == 0)
208 nLeastSignificant = findFirstSetBit(pValParts->inf_parts.fraction_hi);
209 if (nLeastSignificant == 0)
210 nLeastSignificant = 53; // the implied leading 1 is the least significant
211 else
212 nLeastSignificant += 32;
214 int nFracSignificant = 53 - nLeastSignificant;
215 int nBitsInFracPart = nFracSignificant - nExponent;
217 return std::max(nBitsInFracPart, 0);
220 template< typename T >
221 void doubleToString(typename T::String ** pResult,
222 sal_Int32 * pResultCapacity, sal_Int32 nResultOffset,
223 double fValue, rtl_math_StringFormat eFormat,
224 sal_Int32 nDecPlaces, typename T::Char cDecSeparator,
225 sal_Int32 const * pGroups,
226 typename T::Char cGroupSeparator,
227 bool bEraseTrailingDecZeros)
229 static double const nRoundVal[] = {
230 5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6,
231 0.5e-7, 0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14
234 // sign adjustment, instead of testing for fValue<0.0 this will also fetch
235 // -0.0
236 bool bSign = rtl::math::isSignBitSet(fValue);
238 if (bSign)
239 fValue = -fValue;
241 if (rtl::math::isNan(fValue))
243 // #i112652# XMLSchema-2
244 sal_Int32 nCapacity = RTL_CONSTASCII_LENGTH("NaN");
245 if (!pResultCapacity)
247 pResultCapacity = &nCapacity;
248 T::createBuffer(pResult, pResultCapacity);
249 nResultOffset = 0;
252 T::appendAscii(pResult, pResultCapacity, &nResultOffset,
253 RTL_CONSTASCII_STRINGPARAM("NaN"));
255 return;
258 bool bHuge = fValue == HUGE_VAL; // g++ 3.0.1 requires it this way...
259 if (bHuge || rtl::math::isInf(fValue))
261 // #i112652# XMLSchema-2
262 sal_Int32 nCapacity = RTL_CONSTASCII_LENGTH("-INF");
263 if (!pResultCapacity)
265 pResultCapacity = &nCapacity;
266 T::createBuffer(pResult, pResultCapacity);
267 nResultOffset = 0;
270 if ( bSign )
271 T::appendAscii(pResult, pResultCapacity, &nResultOffset,
272 RTL_CONSTASCII_STRINGPARAM("-"));
274 T::appendAscii(pResult, pResultCapacity, &nResultOffset,
275 RTL_CONSTASCII_STRINGPARAM("INF"));
277 return;
280 // Use integer representation for integer values that fit into the
281 // mantissa (1.((2^53)-1)) with a precision of 1 for highest accuracy.
282 const sal_Int64 kMaxInt = (static_cast< sal_Int64 >(1) << 53) - 1;
283 if ((eFormat == rtl_math_StringFormat_Automatic ||
284 eFormat == rtl_math_StringFormat_F) && fValue <= static_cast< double >(kMaxInt))
286 sal_Int64 nInt = static_cast< sal_Int64 >(fValue);
287 // Check the integer range again because double comparison may yield
288 // true within the precision range.
289 if (nInt <= kMaxInt && static_cast< double >(nInt) == fValue)
291 if (nDecPlaces == rtl_math_DecimalPlaces_Max)
292 nDecPlaces = 0;
293 else
294 nDecPlaces = ::std::max< sal_Int32 >(::std::min<sal_Int32>(nDecPlaces, 15), -15);
296 if (bEraseTrailingDecZeros && nDecPlaces > 0)
297 nDecPlaces = 0;
299 // Round before decimal position.
300 if (nDecPlaces < 0)
302 sal_Int64 nRounding = static_cast< sal_Int64 >(getN10Exp(-nDecPlaces - 1));
303 sal_Int64 nTemp = nInt / nRounding;
304 int nDigit = nTemp % 10;
305 nTemp /= 10;
307 if (nDigit >= 5)
308 ++nTemp;
310 nTemp *= 10;
311 nTemp *= nRounding;
312 nInt = nTemp;
313 nDecPlaces = 0;
316 // Max 1 sign, 16 integer digits, 15 group separators, 1 decimal
317 // separator, 15 decimals digits.
318 typename T::Char aBuf[64];
319 typename T::Char * pBuf = aBuf;
320 typename T::Char * p = pBuf;
322 // Backward fill.
323 size_t nGrouping = 0;
324 sal_Int32 nGroupDigits = 0;
327 typename T::Char nDigit = nInt % 10;
328 nInt /= 10;
329 *p++ = nDigit + '0';
330 if (pGroups && pGroups[nGrouping] == ++nGroupDigits && nInt > 0 && cGroupSeparator)
332 *p++ = cGroupSeparator;
333 if (pGroups[nGrouping+1])
334 ++nGrouping;
335 nGroupDigits = 0;
338 while (nInt > 0);
339 if (bSign)
340 *p++ = '-';
342 // Reverse buffer content.
343 sal_Int32 n = (p - pBuf) / 2;
344 for (sal_Int32 i=0; i < n; ++i)
346 ::std::swap( pBuf[i], p[-i-1]);
349 // Append decimals.
350 if (nDecPlaces > 0)
352 *p++ = cDecSeparator;
353 while (nDecPlaces--)
354 *p++ = '0';
357 if (!pResultCapacity)
358 T::createString(pResult, pBuf, p - pBuf);
359 else
360 T::appendChars(pResult, pResultCapacity, &nResultOffset, pBuf, p - pBuf);
362 return;
366 // find the exponent
367 int nExp = 0;
368 if ( fValue > 0.0 )
370 // Cap nExp at a small value beyond which "fValue /= N10Exp" would lose precision (or N10Exp
371 // might even be zero); that will produce output with the decimal point in a non-normalized
372 // position, but the current quality of output for such small values is probably abysmal,
373 // anyway:
374 nExp = std::max(
375 static_cast< int >(floor(log10(fValue))), std::numeric_limits<double>::min_exponent10);
376 double const N10Exp = getN10Exp(nExp);
377 assert(N10Exp != 0);
378 fValue /= N10Exp;
381 switch (eFormat)
383 case rtl_math_StringFormat_Automatic:
384 { // E or F depending on exponent magnitude
385 int nPrec;
386 if (nExp <= -15 || nExp >= 15) // was <-16, >16 in ancient versions, which leads to inaccuracies
388 nPrec = 14;
389 eFormat = rtl_math_StringFormat_E;
391 else
393 if (nExp < 14)
395 nPrec = 15 - nExp - 1;
396 eFormat = rtl_math_StringFormat_F;
398 else
400 nPrec = 15;
401 eFormat = rtl_math_StringFormat_F;
405 if (nDecPlaces == rtl_math_DecimalPlaces_Max)
406 nDecPlaces = nPrec;
408 break;
410 case rtl_math_StringFormat_G :
411 case rtl_math_StringFormat_G1 :
412 case rtl_math_StringFormat_G2 :
413 { // G-Point, similar to sprintf %G
414 if (nDecPlaces == rtl_math_DecimalPlaces_DefaultSignificance)
415 nDecPlaces = 6;
417 if (nExp < -4 || nExp >= nDecPlaces)
419 nDecPlaces = std::max< sal_Int32 >(1, nDecPlaces - 1);
421 if (eFormat == rtl_math_StringFormat_G)
422 eFormat = rtl_math_StringFormat_E;
423 else if (eFormat == rtl_math_StringFormat_G2)
424 eFormat = rtl_math_StringFormat_E2;
425 else if (eFormat == rtl_math_StringFormat_G1)
426 eFormat = rtl_math_StringFormat_E1;
428 else
430 nDecPlaces = std::max< sal_Int32 >(0, nDecPlaces - nExp - 1);
431 eFormat = rtl_math_StringFormat_F;
434 break;
435 default:
436 break;
439 sal_Int32 nDigits = nDecPlaces + 1;
441 if (eFormat == rtl_math_StringFormat_F)
442 nDigits += nExp;
444 // Round the number
445 if(nDigits >= 0)
447 if ((fValue += nRoundVal[std::min<sal_Int32>(nDigits, 15)] ) >= 10)
449 fValue = 1.0;
450 nExp++;
452 if (eFormat == rtl_math_StringFormat_F)
453 nDigits++;
457 static sal_Int32 const nBufMax = 256;
458 typename T::Char aBuf[nBufMax];
459 typename T::Char * pBuf;
460 sal_Int32 nBuf = static_cast< sal_Int32 >
461 (nDigits <= 0 ? std::max< sal_Int32 >(nDecPlaces, abs(nExp))
462 : nDigits + nDecPlaces ) + 10 + (pGroups ? abs(nDigits) * 2 : 0);
464 if (nBuf > nBufMax)
466 pBuf = static_cast< typename T::Char * >(
467 malloc(nBuf * sizeof (typename T::Char)));
468 OSL_ENSURE(pBuf, "Out of memory");
470 else
472 pBuf = aBuf;
475 typename T::Char * p = pBuf;
476 if ( bSign )
477 *p++ = static_cast< typename T::Char >('-');
479 bool bHasDec = false;
481 int nDecPos;
482 // Check for F format and number < 1
483 if(eFormat == rtl_math_StringFormat_F)
485 if(nExp < 0)
487 *p++ = static_cast< typename T::Char >('0');
488 if (nDecPlaces > 0)
490 *p++ = cDecSeparator;
491 bHasDec = true;
494 sal_Int32 i = (nDigits <= 0 ? nDecPlaces : -nExp - 1);
496 while((i--) > 0)
498 *p++ = static_cast< typename T::Char >('0');
501 nDecPos = 0;
503 else
505 nDecPos = nExp + 1;
508 else
510 nDecPos = 1;
513 int nGrouping = 0, nGroupSelector = 0, nGroupExceed = 0;
514 if (nDecPos > 1 && pGroups && pGroups[0] && cGroupSeparator)
516 while (nGrouping + pGroups[nGroupSelector] < nDecPos)
518 nGrouping += pGroups[nGroupSelector];
519 if (pGroups[nGroupSelector+1])
521 if (nGrouping + pGroups[nGroupSelector+1] >= nDecPos)
522 break; // while
524 ++nGroupSelector;
526 else if (!nGroupExceed)
528 nGroupExceed = nGrouping;
533 // print the number
534 if (nDigits > 0)
536 for (int i = 0; ; i++)
538 if (i < 15) // was 16 in ancient versions, which leads to inaccuracies
540 int nDigit;
541 if (nDigits-1 == 0 && i > 0 && i < 14)
542 nDigit = static_cast< int >(floor( fValue + nCorrVal[15-i]));
543 else
544 nDigit = static_cast< int >(fValue + 1E-15);
546 if (nDigit >= 10)
547 { // after-treatment of up-rounding to the next decade
548 sal_Int32 sLen = static_cast< long >(p-pBuf)-1;
549 if (sLen == -1 || (sLen == 0 && bSign))
551 // Assert that no one changed the logic we rely on.
552 assert(!bSign || *pBuf == static_cast< typename T::Char >('-'));
553 p = pBuf;
554 if (bSign)
555 ++p;
556 if (eFormat == rtl_math_StringFormat_F)
558 *p++ = static_cast< typename T::Char >('1');
559 *p++ = static_cast< typename T::Char >('0');
561 else
563 *p++ = static_cast< typename T::Char >('1');
564 *p++ = cDecSeparator;
565 *p++ = static_cast< typename T::Char >('0');
566 nExp++;
567 bHasDec = true;
570 else
572 for (sal_Int32 j = sLen; j >= 0; j--)
574 typename T::Char cS = pBuf[j];
575 if (j == 0 && bSign)
577 // Do not touch leading minus sign put earlier.
578 assert(cS == static_cast< typename T::Char >('-'));
579 break; // for, this is the last character backwards.
581 if (cS != cDecSeparator)
583 if (cS != static_cast< typename T::Char >('9'))
585 pBuf[j] = ++cS;
586 j = -1; // break loop
588 else
590 pBuf[j] = static_cast< typename T::Char >('0');
591 if (j == 0 || (j == 1 && bSign))
593 if (eFormat == rtl_math_StringFormat_F)
594 { // insert '1'
595 typename T::Char * px = p++;
596 while (pBuf < px)
598 *px = *(px-1);
599 px--;
602 pBuf[0] = static_cast< typename T::Char >('1');
604 else
606 pBuf[j] = static_cast< typename T::Char >('1');
607 nExp++;
614 *p++ = static_cast< typename T::Char >('0');
616 fValue = 0.0;
618 else
620 *p++ = static_cast< typename T::Char >(
621 nDigit + static_cast< typename T::Char >('0') );
622 fValue = (fValue - nDigit) * 10.0;
625 else
627 *p++ = static_cast< typename T::Char >('0');
630 if (!--nDigits)
631 break; // for
633 if (nDecPos)
635 if(!--nDecPos)
637 *p++ = cDecSeparator;
638 bHasDec = true;
640 else if (nDecPos == nGrouping)
642 *p++ = cGroupSeparator;
643 nGrouping -= pGroups[nGroupSelector];
645 if (nGroupSelector && nGrouping < nGroupExceed)
646 --nGroupSelector;
652 if (!bHasDec && eFormat == rtl_math_StringFormat_F)
653 { // nDecPlaces < 0 did round the value
654 while (--nDecPos > 0)
655 { // fill before decimal point
656 if (nDecPos == nGrouping)
658 *p++ = cGroupSeparator;
659 nGrouping -= pGroups[nGroupSelector];
661 if (nGroupSelector && nGrouping < nGroupExceed)
662 --nGroupSelector;
665 *p++ = static_cast< typename T::Char >('0');
669 if (bEraseTrailingDecZeros && bHasDec && p > pBuf)
671 while (*(p-1) == static_cast< typename T::Char >('0'))
673 p--;
676 if (*(p-1) == cDecSeparator)
677 p--;
680 // Print the exponent ('E', followed by '+' or '-', followed by exactly
681 // three digits for rtl_math_StringFormat_E). The code in
682 // rtl_[u]str_valueOf{Float|Double} relies on this format.
683 if (eFormat == rtl_math_StringFormat_E || eFormat == rtl_math_StringFormat_E2 || eFormat == rtl_math_StringFormat_E1)
685 if (p == pBuf)
686 *p++ = static_cast< typename T::Char >('1');
687 // maybe no nDigits if nDecPlaces < 0
689 *p++ = static_cast< typename T::Char >('E');
690 if(nExp < 0)
692 nExp = -nExp;
693 *p++ = static_cast< typename T::Char >('-');
695 else
697 *p++ = static_cast< typename T::Char >('+');
700 if (eFormat == rtl_math_StringFormat_E || nExp >= 100)
701 *p++ = static_cast< typename T::Char >(
702 nExp / 100 + static_cast< typename T::Char >('0') );
704 nExp %= 100;
706 if (eFormat == rtl_math_StringFormat_E || eFormat == rtl_math_StringFormat_E2 || nExp >= 10)
707 *p++ = static_cast< typename T::Char >(
708 nExp / 10 + static_cast< typename T::Char >('0') );
710 *p++ = static_cast< typename T::Char >(
711 nExp % 10 + static_cast< typename T::Char >('0') );
714 if (!pResultCapacity)
715 T::createString(pResult, pBuf, p - pBuf);
716 else
717 T::appendChars(pResult, pResultCapacity, &nResultOffset, pBuf, p - pBuf);
719 if (pBuf != &aBuf[0])
720 free(pBuf);
725 void SAL_CALL rtl_math_doubleToString(rtl_String ** pResult,
726 sal_Int32 * pResultCapacity,
727 sal_Int32 nResultOffset, double fValue,
728 rtl_math_StringFormat eFormat,
729 sal_Int32 nDecPlaces,
730 sal_Char cDecSeparator,
731 sal_Int32 const * pGroups,
732 sal_Char cGroupSeparator,
733 sal_Bool bEraseTrailingDecZeros)
734 SAL_THROW_EXTERN_C()
736 doubleToString< StringTraits >(
737 pResult, pResultCapacity, nResultOffset, fValue, eFormat, nDecPlaces,
738 cDecSeparator, pGroups, cGroupSeparator, bEraseTrailingDecZeros);
741 void SAL_CALL rtl_math_doubleToUString(rtl_uString ** pResult,
742 sal_Int32 * pResultCapacity,
743 sal_Int32 nResultOffset, double fValue,
744 rtl_math_StringFormat eFormat,
745 sal_Int32 nDecPlaces,
746 sal_Unicode cDecSeparator,
747 sal_Int32 const * pGroups,
748 sal_Unicode cGroupSeparator,
749 sal_Bool bEraseTrailingDecZeros)
750 SAL_THROW_EXTERN_C()
752 doubleToString< UStringTraits >(
753 pResult, pResultCapacity, nResultOffset, fValue, eFormat, nDecPlaces,
754 cDecSeparator, pGroups, cGroupSeparator, bEraseTrailingDecZeros);
757 namespace {
759 // if nExp * 10 + nAdd would result in overflow
760 bool long10Overflow( long& nExp, int nAdd )
762 if ( nExp > (LONG_MAX/10)
763 || (nExp == (LONG_MAX/10) && nAdd > (LONG_MAX%10)) )
765 nExp = LONG_MAX;
766 return true;
768 return false;
771 template< typename CharT >
772 double stringToDouble(CharT const * pBegin, CharT const * pEnd,
773 CharT cDecSeparator, CharT cGroupSeparator,
774 rtl_math_ConversionStatus * pStatus,
775 CharT const ** pParsedEnd)
777 double fVal = 0.0;
778 rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
780 CharT const * p0 = pBegin;
781 while (p0 != pEnd && (*p0 == CharT(' ') || *p0 == CharT('\t')))
783 ++p0;
786 bool bSign;
787 if (p0 != pEnd && *p0 == CharT('-'))
789 bSign = true;
790 ++p0;
792 else
794 bSign = false;
795 if (p0 != pEnd && *p0 == CharT('+'))
796 ++p0;
799 CharT const * p = p0;
800 bool bDone = false;
802 // #i112652# XMLSchema-2
803 if ((pEnd - p) >= 3)
805 if ((CharT('N') == p[0]) && (CharT('a') == p[1])
806 && (CharT('N') == p[2]))
808 p += 3;
809 rtl::math::setNan( &fVal );
810 bDone = true;
812 else if ((CharT('I') == p[0]) && (CharT('N') == p[1])
813 && (CharT('F') == p[2]))
815 p += 3;
816 fVal = HUGE_VAL;
817 eStatus = rtl_math_ConversionStatus_OutOfRange;
818 bDone = true;
822 if (!bDone) // do not recognize e.g. NaN1.23
824 // Leading zeros and group separators between digits may be safely
825 // ignored. p0 < p implies that there was a leading 0 already,
826 // consecutive group separators may not happen as *(p+1) is checked for
827 // digit.
828 while (p != pEnd && (*p == CharT('0') || (*p == cGroupSeparator
829 && p0 < p && p+1 < pEnd && rtl::isAsciiDigit(*(p+1)))))
831 ++p;
834 CharT const * pFirstSignificant = ((p > pBegin && *(p-1) == CharT('0')) ? p-1 : p);
835 long nValExp = 0; // carry along exponent of mantissa
837 // integer part of mantissa
838 for (; p != pEnd; ++p)
840 CharT c = *p;
841 if (rtl::isAsciiDigit(c))
843 fVal = fVal * 10.0 + static_cast< double >( c - CharT('0') );
844 ++nValExp;
846 else if (c != cGroupSeparator)
848 break;
850 else if (p == p0 || (p+1 == pEnd) || !rtl::isAsciiDigit(*(p+1)))
852 // A leading or trailing (not followed by a digit) group
853 // separator character is not a group separator.
854 break;
858 // fraction part of mantissa
859 if (p != pEnd && *p == cDecSeparator)
861 ++p;
862 double fFrac = 0.0;
863 long nFracExp = 0;
864 while (p != pEnd && *p == CharT('0'))
866 --nFracExp;
867 ++p;
870 if (nValExp == 0)
871 nValExp = nFracExp - 1; // no integer part => fraction exponent
873 // one decimal digit needs ld(10) ~= 3.32 bits
874 static const int nSigs = (DBL_MANT_DIG / 3) + 1;
875 int nDigs = 0;
876 for (; p != pEnd; ++p)
878 CharT c = *p;
879 if (!rtl::isAsciiDigit(c))
881 break;
883 if ( nDigs < nSigs )
884 { // further digits (more than nSigs) don't have any
885 // significance
886 fFrac = fFrac * 10.0 + static_cast<double>(c - CharT('0'));
887 --nFracExp;
888 ++nDigs;
892 if (fFrac != 0.0)
894 fVal += rtl::math::pow10Exp( fFrac, nFracExp );
896 else if (nValExp < 0)
898 if (pFirstSignificant + 1 == p)
900 // No digit at all, only separator(s) without integer or
901 // fraction part. Bail out. No number. No error.
902 if (pStatus)
903 *pStatus = eStatus;
905 if (pParsedEnd)
906 *pParsedEnd = pBegin;
908 return fVal;
910 nValExp = 0; // no digit other than 0 after decimal point
914 if (nValExp > 0)
915 --nValExp; // started with offset +1 at the first mantissa digit
917 // Exponent
918 if (p != p0 && p != pEnd && (*p == CharT('E') || *p == CharT('e')))
920 CharT const * const pExponent = p;
921 ++p;
922 bool bExpSign;
923 if (p != pEnd && *p == CharT('-'))
925 bExpSign = true;
926 ++p;
928 else
930 bExpSign = false;
931 if (p != pEnd && *p == CharT('+'))
932 ++p;
934 CharT const * const pFirstExpDigit = p;
935 if ( fVal == 0.0 )
936 { // no matter what follows, zero stays zero, but carry on the
937 // offset
938 while (p != pEnd && rtl::isAsciiDigit(*p))
940 ++p;
943 if (p == pFirstExpDigit)
944 { // no digits in exponent, reset end of scan
945 p = pExponent;
948 else
950 bool bOverflow = false;
951 long nExp = 0;
952 for (; p != pEnd; ++p)
954 CharT c = *p;
955 if (!rtl::isAsciiDigit(c))
956 break;
958 int i = c - CharT('0');
960 if ( long10Overflow( nExp, i ) )
961 bOverflow = true;
962 else
963 nExp = nExp * 10 + i;
966 if ( nExp )
968 if ( bExpSign )
969 nExp = -nExp;
971 long nAllExp(0);
972 if (!bOverflow)
973 bOverflow = o3tl::checked_add(nExp, nValExp, nAllExp);
974 if ( nAllExp > DBL_MAX_10_EXP || (bOverflow && !bExpSign) )
975 { // overflow
976 fVal = HUGE_VAL;
977 eStatus = rtl_math_ConversionStatus_OutOfRange;
979 else if ((nAllExp < DBL_MIN_10_EXP) ||
980 (bOverflow && bExpSign) )
981 { // underflow
982 fVal = 0.0;
983 eStatus = rtl_math_ConversionStatus_OutOfRange;
985 else if ( nExp > DBL_MAX_10_EXP || nExp < DBL_MIN_10_EXP )
986 { // compensate exponents
987 fVal = rtl::math::pow10Exp( fVal, -nValExp );
988 fVal = rtl::math::pow10Exp( fVal, nAllExp );
990 else
992 fVal = rtl::math::pow10Exp( fVal, nExp ); // normal
995 else if (p == pFirstExpDigit)
996 { // no digits in exponent, reset end of scan
997 p = pExponent;
1001 else if (p - p0 == 2 && p != pEnd && p[0] == CharT('#')
1002 && p[-1] == cDecSeparator && p[-2] == CharT('1'))
1004 if (pEnd - p >= 4 && p[1] == CharT('I') && p[2] == CharT('N')
1005 && p[3] == CharT('F'))
1007 // "1.#INF", "+1.#INF", "-1.#INF"
1008 p += 4;
1009 fVal = HUGE_VAL;
1010 eStatus = rtl_math_ConversionStatus_OutOfRange;
1011 // Eat any further digits:
1012 while (p != pEnd && rtl::isAsciiDigit(*p))
1013 ++p;
1015 else if (pEnd - p >= 4 && p[1] == CharT('N') && p[2] == CharT('A')
1016 && p[3] == CharT('N'))
1018 // "1.#NAN", "+1.#NAN", "-1.#NAN"
1019 p += 4;
1020 rtl::math::setNan( &fVal );
1021 if (bSign)
1023 union {
1024 double sd;
1025 sal_math_Double md;
1026 } m;
1028 m.sd = fVal;
1029 m.md.w32_parts.msw |= 0x80000000; // create negative NaN
1030 fVal = m.sd;
1031 bSign = false; // don't negate again
1034 // Eat any further digits:
1035 while (p != pEnd && rtl::isAsciiDigit(*p))
1037 ++p;
1043 // overflow also if more than DBL_MAX_10_EXP digits without decimal
1044 // separator, or 0. and more than DBL_MIN_10_EXP digits, ...
1045 bool bHuge = fVal == HUGE_VAL; // g++ 3.0.1 requires it this way...
1046 if (bHuge)
1047 eStatus = rtl_math_ConversionStatus_OutOfRange;
1049 if (bSign)
1050 fVal = -fVal;
1052 if (pStatus)
1053 *pStatus = eStatus;
1055 if (pParsedEnd)
1056 *pParsedEnd = p == p0 ? pBegin : p;
1058 return fVal;
1063 double SAL_CALL rtl_math_stringToDouble(sal_Char const * pBegin,
1064 sal_Char const * pEnd,
1065 sal_Char cDecSeparator,
1066 sal_Char cGroupSeparator,
1067 rtl_math_ConversionStatus * pStatus,
1068 sal_Char const ** pParsedEnd)
1069 SAL_THROW_EXTERN_C()
1071 return stringToDouble(
1072 reinterpret_cast<unsigned char const *>(pBegin),
1073 reinterpret_cast<unsigned char const *>(pEnd),
1074 static_cast<unsigned char>(cDecSeparator),
1075 static_cast<unsigned char>(cGroupSeparator), pStatus,
1076 reinterpret_cast<unsigned char const **>(pParsedEnd));
1079 double SAL_CALL rtl_math_uStringToDouble(sal_Unicode const * pBegin,
1080 sal_Unicode const * pEnd,
1081 sal_Unicode cDecSeparator,
1082 sal_Unicode cGroupSeparator,
1083 rtl_math_ConversionStatus * pStatus,
1084 sal_Unicode const ** pParsedEnd)
1085 SAL_THROW_EXTERN_C()
1087 return stringToDouble(pBegin, pEnd, cDecSeparator, cGroupSeparator, pStatus,
1088 pParsedEnd);
1091 double SAL_CALL rtl_math_round(double fValue, int nDecPlaces,
1092 enum rtl_math_RoundingMode eMode)
1093 SAL_THROW_EXTERN_C()
1095 OSL_ASSERT(nDecPlaces >= -20 && nDecPlaces <= 20);
1097 if (fValue == 0.0)
1098 return fValue;
1100 if ( nDecPlaces == 0 && eMode == rtl_math_RoundingMode_Corrected )
1101 return std::round( fValue );
1103 // sign adjustment
1104 bool bSign = rtl::math::isSignBitSet( fValue );
1105 if (bSign)
1106 fValue = -fValue;
1108 double fFac = 0;
1109 if (nDecPlaces != 0)
1111 // max 20 decimals, we don't have unlimited precision
1112 // #38810# and no overflow on fValue*=fFac
1113 if (nDecPlaces < -20 || 20 < nDecPlaces || fValue > (DBL_MAX / 1e20))
1114 return bSign ? -fValue : fValue;
1116 fFac = getN10Exp(nDecPlaces);
1117 fValue *= fFac;
1120 switch ( eMode )
1122 case rtl_math_RoundingMode_Corrected :
1124 int nExp; // exponent for correction
1125 if ( fValue > 0.0 )
1126 nExp = static_cast<int>( floor( log10( fValue ) ) );
1127 else
1128 nExp = 0;
1130 int nIndex;
1132 if (nExp < 0)
1133 nIndex = 15;
1134 else if (nExp >= 14)
1135 nIndex = 0;
1136 else
1137 nIndex = 15 - nExp;
1139 fValue = floor(fValue + 0.5 + nCorrVal[nIndex]);
1141 break;
1142 case rtl_math_RoundingMode_Down:
1143 fValue = rtl::math::approxFloor(fValue);
1144 break;
1145 case rtl_math_RoundingMode_Up:
1146 fValue = rtl::math::approxCeil(fValue);
1147 break;
1148 case rtl_math_RoundingMode_Floor:
1149 fValue = bSign ? rtl::math::approxCeil(fValue)
1150 : rtl::math::approxFloor( fValue );
1151 break;
1152 case rtl_math_RoundingMode_Ceiling:
1153 fValue = bSign ? rtl::math::approxFloor(fValue)
1154 : rtl::math::approxCeil(fValue);
1155 break;
1156 case rtl_math_RoundingMode_HalfDown :
1158 double f = floor(fValue);
1159 fValue = ((fValue - f) <= 0.5) ? f : ceil(fValue);
1161 break;
1162 case rtl_math_RoundingMode_HalfUp:
1164 double f = floor(fValue);
1165 fValue = ((fValue - f) < 0.5) ? f : ceil(fValue);
1167 break;
1168 case rtl_math_RoundingMode_HalfEven:
1169 #if defined FLT_ROUNDS
1171 Use fast version. FLT_ROUNDS may be defined to a function by some compilers!
1173 DBL_EPSILON is the smallest fractional number which can be represented,
1174 its reciprocal is therefore the smallest number that cannot have a
1175 fractional part. Once you add this reciprocal to `x', its fractional part
1176 is stripped off. Simply subtracting the reciprocal back out returns `x'
1177 without its fractional component.
1178 Simple, clever, and elegant - thanks to Ross Cottrell, the original author,
1179 who placed it into public domain.
1181 volatile: prevent compiler from being too smart
1183 if (FLT_ROUNDS == 1)
1185 volatile double x = fValue + 1.0 / DBL_EPSILON;
1186 fValue = x - 1.0 / DBL_EPSILON;
1188 else
1189 #endif // FLT_ROUNDS
1191 double f = floor(fValue);
1192 if ((fValue - f) != 0.5)
1194 fValue = floor( fValue + 0.5 );
1196 else
1198 double g = f / 2.0;
1199 fValue = (g == floor( g )) ? f : (f + 1.0);
1202 break;
1203 default:
1204 OSL_ASSERT(false);
1205 break;
1208 if (nDecPlaces != 0)
1209 fValue /= fFac;
1211 return bSign ? -fValue : fValue;
1214 double SAL_CALL rtl_math_pow10Exp(double fValue, int nExp) SAL_THROW_EXTERN_C()
1216 return fValue * getN10Exp(nExp);
1219 double SAL_CALL rtl_math_approxValue( double fValue ) SAL_THROW_EXTERN_C()
1221 const double fBigInt = 2199023255552.0; // 2^41 -> only 11 bits left for fractional part, fine as decimal
1222 if (fValue == 0.0 || fValue == HUGE_VAL || !::rtl::math::isFinite( fValue) || fValue > fBigInt)
1224 // We don't handle these conditions. Bail out.
1225 return fValue;
1228 double fOrigValue = fValue;
1230 bool bSign = ::rtl::math::isSignBitSet(fValue);
1231 if (bSign)
1232 fValue = -fValue;
1234 // If the value is either integer representable as double,
1235 // or only has small number of bits in fraction part, then we need not do any approximation
1236 if (isRepresentableInteger(fValue) || getBitsInFracPart(fValue) <= 11)
1237 return fOrigValue;
1239 int nExp = static_cast< int >(floor(log10(fValue)));
1240 nExp = 14 - nExp;
1241 double fExpValue = getN10Exp(nExp);
1243 fValue *= fExpValue;
1244 // If the original value was near DBL_MIN we got an overflow. Restore and
1245 // bail out.
1246 if (!rtl::math::isFinite(fValue))
1247 return fOrigValue;
1249 fValue = rtl_math_round(fValue, 0, rtl_math_RoundingMode_Corrected);
1250 fValue /= fExpValue;
1252 // If the original value was near DBL_MAX we got an overflow. Restore and
1253 // bail out.
1254 if (!rtl::math::isFinite(fValue))
1255 return fOrigValue;
1257 return bSign ? -fValue : fValue;
1260 bool SAL_CALL rtl_math_approxEqual(double a, double b) SAL_THROW_EXTERN_C()
1262 static const double e48 = 1.0 / (16777216.0 * 16777216.0);
1263 static const double e44 = e48 * 16.0;
1265 if (a == b)
1266 return true;
1268 if (a == 0.0 || b == 0.0)
1269 return false;
1271 const double d = fabs(a - b);
1272 if (!rtl::math::isFinite(d))
1273 return false; // Nan or Inf involved
1275 if (d > ((a = fabs(a)) * e44) || d > ((b = fabs(b)) * e44))
1276 return false;
1278 if (isRepresentableInteger(d) && isRepresentableInteger(a) && isRepresentableInteger(b))
1279 return false; // special case for representable integers.
1281 return (d < a * e48 && d < b * e48);
1284 double SAL_CALL rtl_math_expm1(double fValue) SAL_THROW_EXTERN_C()
1286 return expm1(fValue);
1289 double SAL_CALL rtl_math_log1p(double fValue) SAL_THROW_EXTERN_C()
1291 #ifdef __APPLE__
1292 if (fValue == -0.0)
1293 return fValue; // macOS 10.8 libc returns 0.0 for -0.0
1294 #endif
1296 return log1p(fValue);
1299 double SAL_CALL rtl_math_atanh(double fValue) SAL_THROW_EXTERN_C()
1300 #if defined __clang__
1301 __attribute__((no_sanitize("float-divide-by-zero"))) // atahn(1) -> inf
1302 #endif
1304 return 0.5 * rtl_math_log1p(2.0 * fValue / (1.0-fValue));
1307 /** Parent error function (erf) */
1308 double SAL_CALL rtl_math_erf(double x) SAL_THROW_EXTERN_C()
1310 return erf(x);
1313 /** Parent complementary error function (erfc) */
1314 double SAL_CALL rtl_math_erfc(double x) SAL_THROW_EXTERN_C()
1316 return erfc(x);
1319 /** improved accuracy of asinh for |x| large and for x near zero
1320 @see #i97605#
1322 double SAL_CALL rtl_math_asinh(double fX) SAL_THROW_EXTERN_C()
1324 if ( fX == 0.0 )
1325 return 0.0;
1327 double fSign = 1.0;
1328 if ( fX < 0.0 )
1330 fX = - fX;
1331 fSign = -1.0;
1334 if ( fX < 0.125 )
1335 return fSign * rtl_math_log1p( fX + fX*fX / (1.0 + sqrt( 1.0 + fX*fX)));
1337 if ( fX < 1.25e7 )
1338 return fSign * log( fX + sqrt( 1.0 + fX*fX));
1340 return fSign * log( 2.0*fX);
1343 /** improved accuracy of acosh for x large and for x near 1
1344 @see #i97605#
1346 double SAL_CALL rtl_math_acosh(double fX) SAL_THROW_EXTERN_C()
1348 volatile double fZ = fX - 1.0;
1349 if (fX < 1.0)
1351 double fResult;
1352 ::rtl::math::setNan( &fResult );
1353 return fResult;
1355 if ( fX == 1.0 )
1356 return 0.0;
1358 if ( fX < 1.1 )
1359 return rtl_math_log1p( fZ + sqrt( fZ*fZ + 2.0*fZ));
1361 if ( fX < 1.25e7 )
1362 return log( fX + sqrt( fX*fX - 1.0));
1364 return log( 2.0*fX);
1367 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */