xref: /core/sal/rtl/math.cxx (revision 1782810f)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <rtl/math.h>
21 
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>
34 
35 #include <algorithm>
36 #include <cassert>
37 #include <float.h>
38 #include <limits>
39 #include <limits.h>
40 #include <math.h>
41 #include <memory>
42 #include <stdlib.h>
43 
44 #include <dtoa.h>
45 
46 #if !HAVE_GCC_BUILTIN_FFS && !defined _WIN32
47     #include <strings.h>
48 #endif
49 
50 static int const n10Count = 16;
51 static double const n10s[2][n10Count] = {
52     { 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8,
53       1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16 },
54     { 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8,
55       1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16 }
56 };
57 
58 // return pow(10.0,nExp) optimized for exponents in the interval [-16,16]
59 static double getN10Exp(int nExp)
60 {
61     if (nExp < 0)
62     {
63         // && -nExp > 0 necessary for std::numeric_limits<int>::min()
64         // because -nExp = nExp
65         if (-nExp <= n10Count && -nExp > 0)
66             return n10s[1][-nExp-1];
67         return pow(10.0, static_cast<double>(nExp));
68     }
69     if (nExp > 0)
70     {
71         if (nExp <= n10Count)
72             return n10s[0][nExp-1];
73 
74         return pow(10.0, static_cast<double>(nExp));
75     }
76     return 1.0;
77 }
78 
79 namespace {
80 
81 double const nCorrVal[] = {
82     0, 9e-1, 9e-2, 9e-3, 9e-4, 9e-5, 9e-6, 9e-7, 9e-8,
83     9e-9, 9e-10, 9e-11, 9e-12, 9e-13, 9e-14, 9e-15
84 };
85 
86 struct StringTraits
87 {
88     typedef sal_Char Char;
89 
90     typedef rtl_String String;
91 
92     static void createString(rtl_String ** pString,
93                                     char const * pChars, sal_Int32 nLen)
94     {
95         rtl_string_newFromStr_WithLength(pString, pChars, nLen);
96     }
97 
98     static void createBuffer(rtl_String ** pBuffer,
99                                     const sal_Int32 * pCapacity)
100     {
101         rtl_string_new_WithLength(pBuffer, *pCapacity);
102     }
103 
104     static void appendChars(rtl_String ** pBuffer, sal_Int32 * pCapacity,
105                                    sal_Int32 * pOffset, char const * pChars,
106                                    sal_Int32 nLen)
107     {
108         assert(pChars);
109         rtl_stringbuffer_insert(pBuffer, pCapacity, *pOffset, pChars, nLen);
110         *pOffset += nLen;
111     }
112 
113     static void appendAscii(rtl_String ** pBuffer, sal_Int32 * pCapacity,
114                                    sal_Int32 * pOffset, char const * pStr,
115                                    sal_Int32 nLen)
116     {
117         assert(pStr);
118         rtl_stringbuffer_insert(pBuffer, pCapacity, *pOffset, pStr, nLen);
119         *pOffset += nLen;
120     }
121 };
122 
123 struct UStringTraits
124 {
125     typedef sal_Unicode Char;
126 
127     typedef rtl_uString String;
128 
129     static void createString(rtl_uString ** pString,
130                                     sal_Unicode const * pChars, sal_Int32 nLen)
131     {
132         rtl_uString_newFromStr_WithLength(pString, pChars, nLen);
133     }
134 
135     static void createBuffer(rtl_uString ** pBuffer,
136                                     const sal_Int32 * pCapacity)
137     {
138         rtl_uString_new_WithLength(pBuffer, *pCapacity);
139     }
140 
141     static void appendChars(rtl_uString ** pBuffer,
142                                    sal_Int32 * pCapacity, sal_Int32 * pOffset,
143                                    sal_Unicode const * pChars, sal_Int32 nLen)
144     {
145         assert(pChars);
146         rtl_uStringbuffer_insert(pBuffer, pCapacity, *pOffset, pChars, nLen);
147         *pOffset += nLen;
148     }
149 
150     static void appendAscii(rtl_uString ** pBuffer,
151                                    sal_Int32 * pCapacity, sal_Int32 * pOffset,
152                                    char const * pStr, sal_Int32 nLen)
153     {
154         rtl_uStringbuffer_insert_ascii(pBuffer, pCapacity, *pOffset, pStr,
155                                        nLen);
156         *pOffset += nLen;
157     }
158 };
159 
160 /** If value (passed as absolute value) is an integer representable as double,
161     which we handle explicitly at some places.
162  */
163 bool isRepresentableInteger(double fAbsValue)
164 {
165     assert(fAbsValue >= 0.0);
166     const sal_Int64 kMaxInt = (static_cast< sal_Int64 >(1) << 53) - 1;
167     if (fAbsValue <= static_cast< double >(kMaxInt))
168     {
169         sal_Int64 nInt = static_cast< sal_Int64 >(fAbsValue);
170         // Check the integer range again because double comparison may yield
171         // true within the precision range.
172         // XXX loplugin:fpcomparison complains about floating-point comparison
173         // for static_cast<double>(nInt) == fAbsValue, though we actually want
174         // this here.
175         double fInt;
176         return (nInt <= kMaxInt &&
177                 (!((fInt = static_cast< double >(nInt)) < fAbsValue) && !(fInt > fAbsValue)));
178     }
179     return false;
180 }
181 
182 // Returns 1-based index of least significant bit in a number, or zero if number is zero
183 int findFirstSetBit(unsigned n)
184 {
185 #if HAVE_GCC_BUILTIN_FFS
186     return __builtin_ffs(n);
187 #elif defined _WIN32
188     unsigned long pos;
189     unsigned char bNonZero = _BitScanForward(&pos, n);
190     return (bNonZero == 0) ? 0 : pos + 1;
191 #else
192     return ffs(n);
193 #endif
194 }
195 
196 /** Returns number of binary bits for fractional part of the number
197     Expects a proper non-negative double value, not +-INF, not NAN
198  */
199 int getBitsInFracPart(double fAbsValue)
200 {
201     assert(rtl::math::isFinite(fAbsValue) && fAbsValue >= 0.0);
202     if (fAbsValue == 0.0)
203         return 0;
204     auto pValParts = reinterpret_cast< const sal_math_Double * >(&fAbsValue);
205     int nExponent = pValParts->inf_parts.exponent - 1023;
206     if (nExponent >= 52)
207         return 0; // All bits in fraction are in integer part of the number
208     int nLeastSignificant = findFirstSetBit(pValParts->inf_parts.fraction_lo);
209     if (nLeastSignificant == 0)
210     {
211         nLeastSignificant = findFirstSetBit(pValParts->inf_parts.fraction_hi);
212         if (nLeastSignificant == 0)
213             nLeastSignificant = 53; // the implied leading 1 is the least significant
214         else
215             nLeastSignificant += 32;
216     }
217     int nFracSignificant = 53 - nLeastSignificant;
218     int nBitsInFracPart = nFracSignificant - nExponent;
219 
220     return std::max(nBitsInFracPart, 0);
221 }
222 
223 template< typename T >
224 void doubleToString(typename T::String ** pResult,
225                            sal_Int32 * pResultCapacity, sal_Int32 nResultOffset,
226                            double fValue, rtl_math_StringFormat eFormat,
227                            sal_Int32 nDecPlaces, typename T::Char cDecSeparator,
228                            sal_Int32 const * pGroups,
229                            typename T::Char cGroupSeparator,
230                            bool bEraseTrailingDecZeros)
231 {
232     static double const nRoundVal[] = {
233         5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6,
234         0.5e-7, 0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14
235     };
236 
237     // sign adjustment, instead of testing for fValue<0.0 this will also fetch
238     // -0.0
239     bool bSign = rtl::math::isSignBitSet(fValue);
240 
241     if (bSign)
242         fValue = -fValue;
243 
244     if (rtl::math::isNan(fValue))
245     {
246         // #i112652# XMLSchema-2
247         sal_Int32 nCapacity = RTL_CONSTASCII_LENGTH("NaN");
248         if (!pResultCapacity)
249         {
250             pResultCapacity = &nCapacity;
251             T::createBuffer(pResult, pResultCapacity);
252             nResultOffset = 0;
253         }
254 
255         T::appendAscii(pResult, pResultCapacity, &nResultOffset,
256                        RTL_CONSTASCII_STRINGPARAM("NaN"));
257 
258         return;
259     }
260 
261     bool bHuge = fValue == HUGE_VAL; // g++ 3.0.1 requires it this way...
262     if (bHuge || rtl::math::isInf(fValue))
263     {
264         // #i112652# XMLSchema-2
265         sal_Int32 nCapacity = RTL_CONSTASCII_LENGTH("-INF");
266         if (!pResultCapacity)
267         {
268             pResultCapacity = &nCapacity;
269             T::createBuffer(pResult, pResultCapacity);
270             nResultOffset = 0;
271         }
272 
273         if ( bSign )
274             T::appendAscii(pResult, pResultCapacity, &nResultOffset,
275                            RTL_CONSTASCII_STRINGPARAM("-"));
276 
277         T::appendAscii(pResult, pResultCapacity, &nResultOffset,
278                        RTL_CONSTASCII_STRINGPARAM("INF"));
279 
280         return;
281     }
282 
283     // Use integer representation for integer values that fit into the
284     // mantissa (1.((2^53)-1)) with a precision of 1 for highest accuracy.
285     const sal_Int64 kMaxInt = (static_cast< sal_Int64 >(1) << 53) - 1;
286     if ((eFormat == rtl_math_StringFormat_Automatic ||
287          eFormat == rtl_math_StringFormat_F) && fValue <= static_cast< double >(kMaxInt))
288     {
289         sal_Int64 nInt = static_cast< sal_Int64 >(fValue);
290         // Check the integer range again because double comparison may yield
291         // true within the precision range.
292         if (nInt <= kMaxInt && static_cast< double >(nInt) == fValue)
293         {
294             if (nDecPlaces == rtl_math_DecimalPlaces_Max)
295                 nDecPlaces = 0;
296             else
297                 nDecPlaces = ::std::max< sal_Int32 >(::std::min<sal_Int32>(nDecPlaces, 15), -15);
298 
299             if (bEraseTrailingDecZeros && nDecPlaces > 0)
300                 nDecPlaces = 0;
301 
302             // Round before decimal position.
303             if (nDecPlaces < 0)
304             {
305                 sal_Int64 nRounding = static_cast< sal_Int64 >(getN10Exp(-nDecPlaces - 1));
306                 sal_Int64 nTemp = nInt / nRounding;
307                 int nDigit = nTemp % 10;
308                 nTemp /= 10;
309 
310                 if (nDigit >= 5)
311                     ++nTemp;
312 
313                 nTemp *= 10;
314                 nTemp *= nRounding;
315                 nInt = nTemp;
316                 nDecPlaces = 0;
317             }
318 
319             // Max 1 sign, 16 integer digits, 15 group separators, 1 decimal
320             // separator, 15 decimals digits.
321             typename T::Char aBuf[64];
322             typename T::Char * pBuf = aBuf;
323             typename T::Char * p = pBuf;
324 
325             // Backward fill.
326             size_t nGrouping = 0;
327             sal_Int32 nGroupDigits = 0;
328             do
329             {
330                 typename T::Char nDigit = nInt % 10;
331                 nInt /= 10;
332                 *p++ = nDigit + '0';
333                 if (pGroups && pGroups[nGrouping] == ++nGroupDigits && nInt > 0 && cGroupSeparator)
334                 {
335                     *p++ = cGroupSeparator;
336                     if (pGroups[nGrouping+1])
337                         ++nGrouping;
338                     nGroupDigits = 0;
339                 }
340             }
341             while (nInt > 0);
342             if (bSign)
343                 *p++ = '-';
344 
345             // Reverse buffer content.
346             sal_Int32 n = (p - pBuf) / 2;
347             for (sal_Int32 i=0; i < n; ++i)
348             {
349                 ::std::swap( pBuf[i], p[-i-1]);
350             }
351 
352             // Append decimals.
353             if (nDecPlaces > 0)
354             {
355                 *p++ = cDecSeparator;
356                 while (nDecPlaces--)
357                     *p++ = '0';
358             }
359 
360             if (!pResultCapacity)
361                 T::createString(pResult, pBuf, p - pBuf);
362             else
363                 T::appendChars(pResult, pResultCapacity, &nResultOffset, pBuf, p - pBuf);
364 
365             return;
366         }
367     }
368 
369     // find the exponent
370     int nExp = 0;
371     if ( fValue > 0.0 )
372     {
373         // Cap nExp at a small value beyond which "fValue /= N10Exp" would lose precision (or N10Exp
374         // might even be zero); that will produce output with the decimal point in a non-normalized
375         // position, but the current quality of output for such small values is probably abysmal,
376         // anyway:
377         nExp = std::max(
378             static_cast< int >(floor(log10(fValue))), std::numeric_limits<double>::min_exponent10);
379         double const N10Exp = getN10Exp(nExp);
380         assert(N10Exp != 0);
381         fValue /= N10Exp;
382     }
383 
384     switch (eFormat)
385     {
386         case rtl_math_StringFormat_Automatic:
387         {   // E or F depending on exponent magnitude
388             int nPrec;
389             if (nExp <= -15 || nExp >= 15)  // was <-16, >16 in ancient versions, which leads to inaccuracies
390             {
391                 nPrec = 14;
392                 eFormat = rtl_math_StringFormat_E;
393             }
394             else
395             {
396                 if (nExp < 14)
397                 {
398                     nPrec = 15 - nExp - 1;
399                     eFormat = rtl_math_StringFormat_F;
400                 }
401                 else
402                 {
403                     nPrec = 15;
404                     eFormat = rtl_math_StringFormat_F;
405                 }
406             }
407 
408             if (nDecPlaces == rtl_math_DecimalPlaces_Max)
409                 nDecPlaces = nPrec;
410         }
411         break;
412 
413         case rtl_math_StringFormat_G :
414         case rtl_math_StringFormat_G1 :
415         case rtl_math_StringFormat_G2 :
416         {   // G-Point, similar to sprintf %G
417             if (nDecPlaces == rtl_math_DecimalPlaces_DefaultSignificance)
418                 nDecPlaces = 6;
419 
420             if (nExp < -4 || nExp >= nDecPlaces)
421             {
422                 nDecPlaces = std::max< sal_Int32 >(1, nDecPlaces - 1);
423 
424                 if (eFormat == rtl_math_StringFormat_G)
425                     eFormat = rtl_math_StringFormat_E;
426                 else if (eFormat == rtl_math_StringFormat_G2)
427                     eFormat = rtl_math_StringFormat_E2;
428                 else if (eFormat == rtl_math_StringFormat_G1)
429                     eFormat = rtl_math_StringFormat_E1;
430             }
431             else
432             {
433                 nDecPlaces = std::max< sal_Int32 >(0, nDecPlaces - nExp - 1);
434                 eFormat = rtl_math_StringFormat_F;
435             }
436         }
437         break;
438         default:
439         break;
440     }
441 
442     sal_Int32 nDigits = nDecPlaces + 1;
443 
444     if (eFormat == rtl_math_StringFormat_F)
445         nDigits += nExp;
446 
447     // Round the number
448     if(nDigits >= 0)
449     {
450         if ((fValue += nRoundVal[std::min<sal_Int32>(nDigits, 15)] ) >= 10)
451         {
452             fValue = 1.0;
453             nExp++;
454 
455             if (eFormat == rtl_math_StringFormat_F)
456                 nDigits++;
457         }
458     }
459 
460     static sal_Int32 const nBufMax = 256;
461     typename T::Char aBuf[nBufMax];
462     typename T::Char * pBuf;
463     sal_Int32 nBuf = static_cast< sal_Int32 >
464         (nDigits <= 0 ? std::max< sal_Int32 >(nDecPlaces, abs(nExp))
465           : nDigits + nDecPlaces ) + 10 + (pGroups ? abs(nDigits) * 2 : 0);
466 
467     if (nBuf > nBufMax)
468     {
469         pBuf = static_cast< typename T::Char * >(
470             malloc(nBuf * sizeof (typename T::Char)));
471         OSL_ENSURE(pBuf, "Out of memory");
472     }
473     else
474     {
475         pBuf = aBuf;
476     }
477 
478     typename T::Char * p = pBuf;
479     if ( bSign )
480         *p++ = static_cast< typename T::Char >('-');
481 
482     bool bHasDec = false;
483 
484     int nDecPos;
485     // Check for F format and number < 1
486     if(eFormat == rtl_math_StringFormat_F)
487     {
488         if(nExp < 0)
489         {
490             *p++ = static_cast< typename T::Char >('0');
491             if (nDecPlaces > 0)
492             {
493                 *p++ = cDecSeparator;
494                 bHasDec = true;
495             }
496 
497             sal_Int32 i = (nDigits <= 0 ? nDecPlaces : -nExp - 1);
498 
499             while((i--) > 0)
500             {
501                 *p++ = static_cast< typename T::Char >('0');
502             }
503 
504             nDecPos = 0;
505         }
506         else
507         {
508             nDecPos = nExp + 1;
509         }
510     }
511     else
512     {
513         nDecPos = 1;
514     }
515 
516     int nGrouping = 0, nGroupSelector = 0, nGroupExceed = 0;
517     if (nDecPos > 1 && pGroups && pGroups[0] && cGroupSeparator)
518     {
519         while (nGrouping + pGroups[nGroupSelector] < nDecPos)
520         {
521             nGrouping += pGroups[nGroupSelector];
522             if (pGroups[nGroupSelector+1])
523             {
524                 if (nGrouping + pGroups[nGroupSelector+1] >= nDecPos)
525                     break;  // while
526 
527                 ++nGroupSelector;
528             }
529             else if (!nGroupExceed)
530             {
531                 nGroupExceed = nGrouping;
532             }
533         }
534     }
535 
536     // print the number
537     if (nDigits > 0)
538     {
539         for (int i = 0; ; i++)
540         {
541             if (i < 15)     // was 16 in ancient versions, which leads to inaccuracies
542             {
543                 int nDigit;
544                 if (nDigits-1 == 0 && i > 0 && i < 14)
545                     nDigit = static_cast< int >(floor( fValue + nCorrVal[15-i]));
546                 else
547                     nDigit = static_cast< int >(fValue + 1E-15);
548 
549                 if (nDigit >= 10)
550                 {   // after-treatment of up-rounding to the next decade
551                     sal_Int32 sLen = static_cast< long >(p-pBuf)-1;
552                     if (sLen == -1 || (sLen == 0 && bSign))
553                     {
554                         // Assert that no one changed the logic we rely on.
555                         assert(!bSign || *pBuf == static_cast< typename T::Char >('-'));
556                         p = pBuf;
557                         if (bSign)
558                             ++p;
559                         if (eFormat == rtl_math_StringFormat_F)
560                         {
561                             *p++ = static_cast< typename T::Char >('1');
562                             *p++ = static_cast< typename T::Char >('0');
563                         }
564                         else
565                         {
566                             *p++ = static_cast< typename T::Char >('1');
567                             *p++ = cDecSeparator;
568                             *p++ = static_cast< typename T::Char >('0');
569                             nExp++;
570                             bHasDec = true;
571                         }
572                     }
573                     else
574                     {
575                         for (sal_Int32 j = sLen; j >= 0; j--)
576                         {
577                             typename T::Char cS = pBuf[j];
578                             if (j == 0 && bSign)
579                             {
580                                 // Do not touch leading minus sign put earlier.
581                                 assert(cS == static_cast< typename T::Char >('-'));
582                                 break;  // for, this is the last character backwards.
583                             }
584                             if (cS != cDecSeparator)
585                             {
586                                 if (cS != static_cast< typename T::Char >('9'))
587                                 {
588                                     pBuf[j] = ++cS;
589                                     j = -1;                 // break loop
590                                 }
591                                 else
592                                 {
593                                     pBuf[j] = static_cast< typename T::Char >('0');
594                                     if (j == 0 || (j == 1 && bSign))
595                                     {
596                                         if (eFormat == rtl_math_StringFormat_F)
597                                         {   // insert '1'
598                                             typename T::Char * px = p++;
599                                             while (pBuf < px)
600                                             {
601                                                 *px = *(px-1);
602                                                 px--;
603                                             }
604 
605                                             pBuf[0] = static_cast< typename T::Char >('1');
606                                         }
607                                         else
608                                         {
609                                             pBuf[j] = static_cast< typename T::Char >('1');
610                                             nExp++;
611                                         }
612                                     }
613                                 }
614                             }
615                         }
616 
617                         *p++ = static_cast< typename T::Char >('0');
618                     }
619                     fValue = 0.0;
620                 }
621                 else
622                 {
623                     *p++ = static_cast< typename T::Char >(
624                         nDigit + static_cast< typename T::Char >('0') );
625                     fValue = (fValue - nDigit) * 10.0;
626                 }
627             }
628             else
629             {
630                 *p++ = static_cast< typename T::Char >('0');
631             }
632 
633             if (!--nDigits)
634                 break;  // for
635 
636             if (nDecPos)
637             {
638                 if(!--nDecPos)
639                 {
640                     *p++ = cDecSeparator;
641                     bHasDec = true;
642                 }
643                 else if (nDecPos == nGrouping)
644                 {
645                     *p++ = cGroupSeparator;
646                     nGrouping -= pGroups[nGroupSelector];
647 
648                     if (nGroupSelector && nGrouping < nGroupExceed)
649                         --nGroupSelector;
650                 }
651             }
652         }
653     }
654 
655     if (!bHasDec && eFormat == rtl_math_StringFormat_F)
656     {   // nDecPlaces < 0 did round the value
657         while (--nDecPos > 0)
658         {   // fill before decimal point
659             if (nDecPos == nGrouping)
660             {
661                 *p++ = cGroupSeparator;
662                 nGrouping -= pGroups[nGroupSelector];
663 
664                 if (nGroupSelector && nGrouping < nGroupExceed)
665                     --nGroupSelector;
666             }
667 
668             *p++ = static_cast< typename T::Char >('0');
669         }
670     }
671 
672     if (bEraseTrailingDecZeros && bHasDec && p > pBuf)
673     {
674         while (*(p-1) == static_cast< typename T::Char >('0'))
675         {
676             p--;
677         }
678 
679         if (*(p-1) == cDecSeparator)
680             p--;
681     }
682 
683     // Print the exponent ('E', followed by '+' or '-', followed by exactly
684     // three digits for rtl_math_StringFormat_E).  The code in
685     // rtl_[u]str_valueOf{Float|Double} relies on this format.
686     if (eFormat == rtl_math_StringFormat_E || eFormat == rtl_math_StringFormat_E2 || eFormat == rtl_math_StringFormat_E1)
687     {
688         if (p == pBuf)
689             *p++ = static_cast< typename T::Char >('1');
690                 // maybe no nDigits if nDecPlaces < 0
691 
692         *p++ = static_cast< typename T::Char >('E');
693         if(nExp < 0)
694         {
695             nExp = -nExp;
696             *p++ = static_cast< typename T::Char >('-');
697         }
698         else
699         {
700             *p++ = static_cast< typename T::Char >('+');
701         }
702 
703         if (eFormat == rtl_math_StringFormat_E || nExp >= 100)
704             *p++ = static_cast< typename T::Char >(
705                 nExp / 100 + static_cast< typename T::Char >('0') );
706 
707         nExp %= 100;
708 
709         if (eFormat == rtl_math_StringFormat_E || eFormat == rtl_math_StringFormat_E2 || nExp >= 10)
710             *p++ = static_cast< typename T::Char >(
711                 nExp / 10 + static_cast< typename T::Char >('0') );
712 
713         *p++ = static_cast< typename T::Char >(
714             nExp % 10 + static_cast< typename T::Char >('0') );
715     }
716 
717     if (!pResultCapacity)
718         T::createString(pResult, pBuf, p - pBuf);
719     else
720         T::appendChars(pResult, pResultCapacity, &nResultOffset, pBuf, p - pBuf);
721 
722     if (pBuf != &aBuf[0])
723         free(pBuf);
724 }
725 
726 }
727 
728 void SAL_CALL rtl_math_doubleToString(rtl_String ** pResult,
729                                       sal_Int32 * pResultCapacity,
730                                       sal_Int32 nResultOffset, double fValue,
731                                       rtl_math_StringFormat eFormat,
732                                       sal_Int32 nDecPlaces,
733                                       char cDecSeparator,
734                                       sal_Int32 const * pGroups,
735                                       char cGroupSeparator,
736                                       sal_Bool bEraseTrailingDecZeros)
737     SAL_THROW_EXTERN_C()
738 {
739     doubleToString< StringTraits >(
740         pResult, pResultCapacity, nResultOffset, fValue, eFormat, nDecPlaces,
741         cDecSeparator, pGroups, cGroupSeparator, bEraseTrailingDecZeros);
742 }
743 
744 void SAL_CALL rtl_math_doubleToUString(rtl_uString ** pResult,
745                                        sal_Int32 * pResultCapacity,
746                                        sal_Int32 nResultOffset, double fValue,
747                                        rtl_math_StringFormat eFormat,
748                                        sal_Int32 nDecPlaces,
749                                        sal_Unicode cDecSeparator,
750                                        sal_Int32 const * pGroups,
751                                        sal_Unicode cGroupSeparator,
752                                        sal_Bool bEraseTrailingDecZeros)
753     SAL_THROW_EXTERN_C()
754 {
755     doubleToString< UStringTraits >(
756         pResult, pResultCapacity, nResultOffset, fValue, eFormat, nDecPlaces,
757         cDecSeparator, pGroups, cGroupSeparator, bEraseTrailingDecZeros);
758 }
759 
760 namespace {
761 
762 template< typename CharT >
763 double stringToDouble(CharT const * pBegin, CharT const * pEnd,
764                              CharT cDecSeparator, CharT cGroupSeparator,
765                              rtl_math_ConversionStatus * pStatus,
766                              CharT const ** pParsedEnd)
767 {
768     double fVal = 0.0;
769     rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
770 
771     CharT const * p0 = pBegin;
772     while (p0 != pEnd && (*p0 == CharT(' ') || *p0 == CharT('\t')))
773     {
774         ++p0;
775     }
776 
777     bool bSign;
778     if (p0 != pEnd && *p0 == CharT('-'))
779     {
780         bSign = true;
781         ++p0;
782     }
783     else
784     {
785         bSign = false;
786         if (p0 != pEnd && *p0 == CharT('+'))
787             ++p0;
788     }
789 
790     CharT const * p = p0;
791     bool bDone = false;
792 
793     // #i112652# XMLSchema-2
794     if ((pEnd - p) >= 3)
795     {
796         if ((CharT('N') == p[0]) && (CharT('a') == p[1])
797             && (CharT('N') == p[2]))
798         {
799             p += 3;
800             rtl::math::setNan( &fVal );
801             bDone = true;
802         }
803         else if ((CharT('I') == p[0]) && (CharT('N') == p[1])
804                  && (CharT('F') == p[2]))
805         {
806             p += 3;
807             fVal = HUGE_VAL;
808             eStatus = rtl_math_ConversionStatus_OutOfRange;
809             bDone = true;
810         }
811     }
812 
813     if (!bDone) // do not recognize e.g. NaN1.23
814     {
815         std::unique_ptr<char[]> bufInHeap;
816         std::unique_ptr<const CharT * []> bufInHeapMap;
817         constexpr int bufOnStackSize = 256;
818         char bufOnStack[bufOnStackSize];
819         const CharT* bufOnStackMap[bufOnStackSize];
820         char* buf = bufOnStack;
821         const CharT** bufmap = bufOnStackMap;
822         int bufpos = 0;
823         const size_t bufsize = pEnd - p + (bSign ? 2 : 1);
824         if (bufsize > bufOnStackSize)
825         {
826             bufInHeap = std::make_unique<char[]>(bufsize);
827             bufInHeapMap = std::make_unique<const CharT*[]>(bufsize);
828             buf = bufInHeap.get();
829             bufmap = bufInHeapMap.get();
830         }
831 
832         if (bSign)
833         {
834             buf[0] = '-';
835             bufmap[0] = p; // yes, this may be the same pointer as for the next mapping
836             bufpos = 1;
837         }
838         // Put first zero to buffer for strings like "-0"
839         if (p != pEnd && *p == CharT('0'))
840         {
841             buf[bufpos] = '0';
842             bufmap[bufpos] = p;
843             ++bufpos;
844             ++p;
845         }
846         // Leading zeros and group separators between digits may be safely
847         // ignored. p0 < p implies that there was a leading 0 already,
848         // consecutive group separators may not happen as *(p+1) is checked for
849         // digit.
850         while (p != pEnd && (*p == CharT('0') || (*p == cGroupSeparator
851                         && p0 < p && p+1 < pEnd && rtl::isAsciiDigit(*(p+1)))))
852         {
853             ++p;
854         }
855 
856         // integer part of mantissa
857         for (; p != pEnd; ++p)
858         {
859             CharT c = *p;
860             if (rtl::isAsciiDigit(c))
861             {
862                 buf[bufpos] = static_cast<char>(c);
863                 bufmap[bufpos] = p;
864                 ++bufpos;
865             }
866             else if (c != cGroupSeparator)
867             {
868                 break;
869             }
870             else if (p == p0 || (p+1 == pEnd) || !rtl::isAsciiDigit(*(p+1)))
871             {
872                 // A leading or trailing (not followed by a digit) group
873                 // separator character is not a group separator.
874                 break;
875             }
876         }
877 
878         // fraction part of mantissa
879         if (p != pEnd && *p == cDecSeparator)
880         {
881             buf[bufpos] = '.';
882             bufmap[bufpos] = p;
883             ++bufpos;
884             ++p;
885 
886             for (; p != pEnd; ++p)
887             {
888                 CharT c = *p;
889                 if (!rtl::isAsciiDigit(c))
890                 {
891                     break;
892                 }
893                 buf[bufpos] = static_cast<char>(c);
894                 bufmap[bufpos] = p;
895                 ++bufpos;
896             }
897         }
898 
899         // Exponent
900         if (p != p0 && p != pEnd && (*p == CharT('E') || *p == CharT('e')))
901         {
902             buf[bufpos] = 'E';
903             bufmap[bufpos] = p;
904             ++bufpos;
905             ++p;
906             if (p != pEnd && *p == CharT('-'))
907             {
908                 buf[bufpos] = '-';
909                 bufmap[bufpos] = p;
910                 ++bufpos;
911                 ++p;
912             }
913             else if (p != pEnd && *p == CharT('+'))
914                 ++p;
915 
916             for (; p != pEnd; ++p)
917             {
918                 CharT c = *p;
919                 if (!rtl::isAsciiDigit(c))
920                     break;
921 
922                 buf[bufpos] = static_cast<char>(c);
923                 bufmap[bufpos] = p;
924                 ++bufpos;
925             }
926         }
927         else if (p - p0 == 2 && p != pEnd && p[0] == CharT('#')
928                  && p[-1] == cDecSeparator && p[-2] == CharT('1'))
929         {
930             if (pEnd - p >= 4 && p[1] == CharT('I') && p[2] == CharT('N')
931                 && p[3] == CharT('F'))
932             {
933                 // "1.#INF", "+1.#INF", "-1.#INF"
934                 p += 4;
935                 fVal = HUGE_VAL;
936                 eStatus = rtl_math_ConversionStatus_OutOfRange;
937                 // Eat any further digits:
938                 while (p != pEnd && rtl::isAsciiDigit(*p))
939                     ++p;
940                 bDone = true;
941             }
942             else if (pEnd - p >= 4 && p[1] == CharT('N') && p[2] == CharT('A')
943                 && p[3] == CharT('N'))
944             {
945                 // "1.#NAN", "+1.#NAN", "-1.#NAN"
946                 p += 4;
947                 rtl::math::setNan( &fVal );
948                 if (bSign)
949                 {
950                     union {
951                         double sd;
952                         sal_math_Double md;
953                     } m;
954 
955                     m.sd = fVal;
956                     m.md.w32_parts.msw |= 0x80000000; // create negative NaN
957                     fVal = m.sd;
958                     bSign = false; // don't negate again
959                 }
960 
961                 // Eat any further digits:
962                 while (p != pEnd && rtl::isAsciiDigit(*p))
963                 {
964                     ++p;
965                 }
966                 bDone = true;
967             }
968         }
969 
970         if (!bDone)
971         {
972             buf[bufpos] = '\0';
973             bufmap[bufpos] = p;
974             char* pCharParseEnd;
975             errno = 0;
976             fVal = strtod_nolocale(buf, &pCharParseEnd);
977             if (errno == ERANGE)
978                 eStatus = rtl_math_ConversionStatus_OutOfRange;
979             p = bufmap[pCharParseEnd - buf];
980             bSign = false;
981         }
982     }
983 
984     // overflow also if more than DBL_MAX_10_EXP digits without decimal
985     // separator, or 0. and more than DBL_MIN_10_EXP digits, ...
986     bool bHuge = fVal == HUGE_VAL; // g++ 3.0.1 requires it this way...
987     if (bHuge)
988         eStatus = rtl_math_ConversionStatus_OutOfRange;
989 
990     if (bSign)
991         fVal = -fVal;
992 
993     if (pStatus)
994         *pStatus = eStatus;
995 
996     if (pParsedEnd)
997         *pParsedEnd = p == p0 ? pBegin : p;
998 
999     return fVal;
1000 }
1001 
1002 }
1003 
1004 double SAL_CALL rtl_math_stringToDouble(char const * pBegin,
1005                                         char const * pEnd,
1006                                         char cDecSeparator,
1007                                         char cGroupSeparator,
1008                                         rtl_math_ConversionStatus * pStatus,
1009                                         char const ** pParsedEnd)
1010     SAL_THROW_EXTERN_C()
1011 {
1012     return stringToDouble(
1013         reinterpret_cast<unsigned char const *>(pBegin),
1014         reinterpret_cast<unsigned char const *>(pEnd),
1015         static_cast<unsigned char>(cDecSeparator),
1016         static_cast<unsigned char>(cGroupSeparator), pStatus,
1017         reinterpret_cast<unsigned char const **>(pParsedEnd));
1018 }
1019 
1020 double SAL_CALL rtl_math_uStringToDouble(sal_Unicode const * pBegin,
1021                                          sal_Unicode const * pEnd,
1022                                          sal_Unicode cDecSeparator,
1023                                          sal_Unicode cGroupSeparator,
1024                                          rtl_math_ConversionStatus * pStatus,
1025                                          sal_Unicode const ** pParsedEnd)
1026     SAL_THROW_EXTERN_C()
1027 {
1028     return stringToDouble(pBegin, pEnd, cDecSeparator, cGroupSeparator, pStatus,
1029                           pParsedEnd);
1030 }
1031 
1032 double SAL_CALL rtl_math_round(double fValue, int nDecPlaces,
1033                                enum rtl_math_RoundingMode eMode)
1034     SAL_THROW_EXTERN_C()
1035 {
1036     OSL_ASSERT(nDecPlaces >= -20 && nDecPlaces <= 20);
1037 
1038     if (fValue == 0.0)
1039         return fValue;
1040 
1041     if ( nDecPlaces == 0 && eMode == rtl_math_RoundingMode_Corrected )
1042         return std::round( fValue );
1043 
1044     // sign adjustment
1045     bool bSign = rtl::math::isSignBitSet( fValue );
1046     if (bSign)
1047         fValue = -fValue;
1048 
1049     double fFac = 0;
1050     if (nDecPlaces != 0)
1051     {
1052         // max 20 decimals, we don't have unlimited precision
1053         // #38810# and no overflow on fValue*=fFac
1054         if (nDecPlaces < -20 || 20 < nDecPlaces || fValue > (DBL_MAX / 1e20))
1055             return bSign ? -fValue : fValue;
1056 
1057         fFac = getN10Exp(nDecPlaces);
1058         fValue *= fFac;
1059     }
1060 
1061     switch ( eMode )
1062     {
1063         case rtl_math_RoundingMode_Corrected :
1064         {
1065             int nExp;       // exponent for correction
1066             if ( fValue > 0.0 )
1067                 nExp = static_cast<int>( floor( log10( fValue ) ) );
1068             else
1069                 nExp = 0;
1070 
1071             int nIndex;
1072 
1073             if (nExp < 0)
1074                 nIndex = 15;
1075             else if (nExp >= 14)
1076                 nIndex = 0;
1077             else
1078                 nIndex = 15 - nExp;
1079 
1080             fValue = floor(fValue + 0.5 + nCorrVal[nIndex]);
1081         }
1082         break;
1083         case rtl_math_RoundingMode_Down:
1084             fValue = rtl::math::approxFloor(fValue);
1085         break;
1086         case rtl_math_RoundingMode_Up:
1087             fValue = rtl::math::approxCeil(fValue);
1088         break;
1089         case rtl_math_RoundingMode_Floor:
1090             fValue = bSign ? rtl::math::approxCeil(fValue)
1091                 : rtl::math::approxFloor( fValue );
1092         break;
1093         case rtl_math_RoundingMode_Ceiling:
1094             fValue = bSign ? rtl::math::approxFloor(fValue)
1095                 : rtl::math::approxCeil(fValue);
1096         break;
1097         case rtl_math_RoundingMode_HalfDown :
1098         {
1099             double f = floor(fValue);
1100             fValue = ((fValue - f) <= 0.5) ? f : ceil(fValue);
1101         }
1102         break;
1103         case rtl_math_RoundingMode_HalfUp:
1104         {
1105             double f = floor(fValue);
1106             fValue = ((fValue - f) < 0.5) ? f : ceil(fValue);
1107         }
1108         break;
1109         case rtl_math_RoundingMode_HalfEven:
1110 #if defined FLT_ROUNDS
1111 /*
1112     Use fast version. FLT_ROUNDS may be defined to a function by some compilers!
1113 
1114     DBL_EPSILON is the smallest fractional number which can be represented,
1115     its reciprocal is therefore the smallest number that cannot have a
1116     fractional part. Once you add this reciprocal to `x', its fractional part
1117     is stripped off. Simply subtracting the reciprocal back out returns `x'
1118     without its fractional component.
1119     Simple, clever, and elegant - thanks to Ross Cottrell, the original author,
1120     who placed it into public domain.
1121 
1122     volatile: prevent compiler from being too smart
1123 */
1124             if (FLT_ROUNDS == 1)
1125             {
1126                 volatile double x = fValue + 1.0 / DBL_EPSILON;
1127                 fValue = x - 1.0 / DBL_EPSILON;
1128             }
1129             else
1130 #endif // FLT_ROUNDS
1131             {
1132                 double f = floor(fValue);
1133                 if ((fValue - f) != 0.5)
1134                 {
1135                     fValue = floor( fValue + 0.5 );
1136                 }
1137                 else
1138                 {
1139                     double g = f / 2.0;
1140                     fValue = (g == floor( g )) ? f : (f + 1.0);
1141                 }
1142             }
1143         break;
1144         default:
1145             OSL_ASSERT(false);
1146         break;
1147     }
1148 
1149     if (nDecPlaces != 0)
1150         fValue /= fFac;
1151 
1152     return bSign ? -fValue : fValue;
1153 }
1154 
1155 double SAL_CALL rtl_math_pow10Exp(double fValue, int nExp) SAL_THROW_EXTERN_C()
1156 {
1157     return fValue * getN10Exp(nExp);
1158 }
1159 
1160 double SAL_CALL rtl_math_approxValue( double fValue ) SAL_THROW_EXTERN_C()
1161 {
1162     const double fBigInt = 2199023255552.0; // 2^41 -> only 11 bits left for fractional part, fine as decimal
1163     if (fValue == 0.0 || fValue == HUGE_VAL || !::rtl::math::isFinite( fValue) || fValue > fBigInt)
1164     {
1165         // We don't handle these conditions.  Bail out.
1166         return fValue;
1167     }
1168 
1169     double fOrigValue = fValue;
1170 
1171     bool bSign = ::rtl::math::isSignBitSet(fValue);
1172     if (bSign)
1173         fValue = -fValue;
1174 
1175     // If the value is either integer representable as double,
1176     // or only has small number of bits in fraction part, then we need not do any approximation
1177     if (isRepresentableInteger(fValue) || getBitsInFracPart(fValue) <= 11)
1178         return fOrigValue;
1179 
1180     int nExp = static_cast< int >(floor(log10(fValue)));
1181     nExp = 14 - nExp;
1182     double fExpValue = getN10Exp(nExp);
1183 
1184     fValue *= fExpValue;
1185     // If the original value was near DBL_MIN we got an overflow. Restore and
1186     // bail out.
1187     if (!rtl::math::isFinite(fValue))
1188         return fOrigValue;
1189 
1190     fValue = rtl_math_round(fValue, 0, rtl_math_RoundingMode_Corrected);
1191     fValue /= fExpValue;
1192 
1193     // If the original value was near DBL_MAX we got an overflow. Restore and
1194     // bail out.
1195     if (!rtl::math::isFinite(fValue))
1196         return fOrigValue;
1197 
1198     return bSign ? -fValue : fValue;
1199 }
1200 
1201 bool SAL_CALL rtl_math_approxEqual(double a, double b) SAL_THROW_EXTERN_C()
1202 {
1203     static const double e48 = 1.0 / (16777216.0 * 16777216.0);
1204     static const double e44 = e48 * 16.0;
1205 
1206     if (a == b)
1207         return true;
1208 
1209     if (a == 0.0 || b == 0.0)
1210         return false;
1211 
1212     const double d = fabs(a - b);
1213     if (!rtl::math::isFinite(d))
1214         return false;   // Nan or Inf involved
1215 
1216     if (d > ((a = fabs(a)) * e44) || d > ((b = fabs(b)) * e44))
1217         return false;
1218 
1219     if (isRepresentableInteger(d) && isRepresentableInteger(a) && isRepresentableInteger(b))
1220         return false;   // special case for representable integers.
1221 
1222     return (d < a * e48 && d < b * e48);
1223 }
1224 
1225 double SAL_CALL rtl_math_expm1(double fValue) SAL_THROW_EXTERN_C()
1226 {
1227     return expm1(fValue);
1228 }
1229 
1230 double SAL_CALL rtl_math_log1p(double fValue) SAL_THROW_EXTERN_C()
1231 {
1232 #ifdef __APPLE__
1233     if (fValue == -0.0)
1234         return fValue; // macOS 10.8 libc returns 0.0 for -0.0
1235 #endif
1236 
1237     return log1p(fValue);
1238 }
1239 
1240 double SAL_CALL rtl_math_atanh(double fValue) SAL_THROW_EXTERN_C()
1241 #if defined __clang__
1242     __attribute__((no_sanitize("float-divide-by-zero"))) // atahn(1) -> inf
1243 #endif
1244 {
1245    return 0.5 * rtl_math_log1p(2.0 * fValue / (1.0-fValue));
1246 }
1247 
1248 /** Parent error function (erf) */
1249 double SAL_CALL rtl_math_erf(double x) SAL_THROW_EXTERN_C()
1250 {
1251     return erf(x);
1252 }
1253 
1254 /** Parent complementary error function (erfc) */
1255 double SAL_CALL rtl_math_erfc(double x) SAL_THROW_EXTERN_C()
1256 {
1257     return erfc(x);
1258 }
1259 
1260 /** improved accuracy of asinh for |x| large and for x near zero
1261     @see #i97605#
1262  */
1263 double SAL_CALL rtl_math_asinh(double fX) SAL_THROW_EXTERN_C()
1264 {
1265     if ( fX == 0.0 )
1266         return 0.0;
1267 
1268     double fSign = 1.0;
1269     if ( fX < 0.0 )
1270     {
1271         fX = - fX;
1272         fSign = -1.0;
1273     }
1274 
1275     if ( fX < 0.125 )
1276         return fSign * rtl_math_log1p( fX + fX*fX / (1.0 + sqrt( 1.0 + fX*fX)));
1277 
1278     if ( fX < 1.25e7 )
1279         return fSign * log( fX + sqrt( 1.0 + fX*fX));
1280 
1281     return fSign * log( 2.0*fX);
1282 }
1283 
1284 /** improved accuracy of acosh for x large and for x near 1
1285     @see #i97605#
1286  */
1287 double SAL_CALL rtl_math_acosh(double fX) SAL_THROW_EXTERN_C()
1288 {
1289     volatile double fZ = fX - 1.0;
1290     if (fX < 1.0)
1291     {
1292         double fResult;
1293         ::rtl::math::setNan( &fResult );
1294         return fResult;
1295     }
1296     if ( fX == 1.0 )
1297         return 0.0;
1298 
1299     if ( fX < 1.1 )
1300         return rtl_math_log1p( fZ + sqrt( fZ*fZ + 2.0*fZ));
1301 
1302     if ( fX < 1.25e7 )
1303         return log( fX + sqrt( fX*fX - 1.0));
1304 
1305     return log( 2.0*fX);
1306 }
1307 
1308 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1309