LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sal/rtl - math.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 283 525 53.9 %
Date: 2013-07-09 Functions: 19 31 61.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      21             : #include "rtl/math.h"
      22             : 
      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"
      33             : 
      34             : #include <algorithm>
      35             : #include <float.h>
      36             : #include <limits.h>
      37             : #include <math.h>
      38             : #include <stdlib.h>
      39             : 
      40             : 
      41             : static int const n10Count = 16;
      42             : static double const n10s[2][n10Count] = {
      43             :     { 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8,
      44             :       1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16 },
      45             :     { 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8,
      46             :       1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16 }
      47             : };
      48             : 
      49             : // return pow(10.0,nExp) optimized for exponents in the interval [-16,16]
      50     1454580 : static double getN10Exp( int nExp )
      51             : {
      52     1454580 :     if ( nExp < 0 )
      53             :     {
      54             :         // && -nExp > 0 necessary for std::numeric_limits<int>::min()
      55             :         // because -nExp = nExp
      56      148935 :         if ( -nExp <= n10Count && -nExp > 0 )
      57      148921 :             return n10s[1][-nExp-1];
      58             :         else
      59          14 :             return pow( 10.0, static_cast<double>( nExp ) );
      60             :     }
      61     1305645 :     else if ( nExp > 0 )
      62             :     {
      63     1297472 :         if ( nExp <= n10Count )
      64     1297468 :             return n10s[0][nExp-1];
      65             :         else
      66           4 :             return pow( 10.0, static_cast<double>( nExp ) );
      67             :     }
      68             :     else // ( nExp == 0 )
      69        8173 :         return 1.0;
      70             : }
      71             : 
      72             : /** Approximation algorithm for erf for 0 < x < 0.65. */
      73           0 : static void lcl_Erf0065( double x, double& fVal )
      74             : {
      75             :     static const double pn[] = {
      76             :         1.12837916709551256,
      77             :         1.35894887627277916E-1,
      78             :         4.03259488531795274E-2,
      79             :         1.20339380863079457E-3,
      80             :         6.49254556481904354E-5
      81             :     };
      82             :     static const double qn[] = {
      83             :         1.00000000000000000,
      84             :         4.53767041780002545E-1,
      85             :         8.69936222615385890E-2,
      86             :         8.49717371168693357E-3,
      87             :         3.64915280629351082E-4
      88             :     };
      89           0 :     double fPSum = 0.0;
      90           0 :     double fQSum = 0.0;
      91           0 :     double fXPow = 1.0;
      92           0 :     for ( unsigned int i = 0; i <= 4; ++i )
      93             :     {
      94           0 :         fPSum += pn[i]*fXPow;
      95           0 :         fQSum += qn[i]*fXPow;
      96           0 :         fXPow *= x*x;
      97             :     }
      98           0 :     fVal = x * fPSum / fQSum;
      99           0 : }
     100             : 
     101             : /** Approximation algorithm for erfc for 0.65 < x < 6.0. */
     102           0 : static void lcl_Erfc0600( double x, double& fVal )
     103             : {
     104           0 :     double fPSum = 0.0;
     105           0 :     double fQSum = 0.0;
     106           0 :     double fXPow = 1.0;
     107             :     const double *pn;
     108             :     const double *qn;
     109             : 
     110           0 :     if ( x < 2.2 )
     111             :     {
     112             :         static const double pn22[] = {
     113             :             9.99999992049799098E-1,
     114             :             1.33154163936765307,
     115             :             8.78115804155881782E-1,
     116             :             3.31899559578213215E-1,
     117             :             7.14193832506776067E-2,
     118             :             7.06940843763253131E-3
     119             :         };
     120             :         static const double qn22[] = {
     121             :             1.00000000000000000,
     122             :             2.45992070144245533,
     123             :             2.65383972869775752,
     124             :             1.61876655543871376,
     125             :             5.94651311286481502E-1,
     126             :             1.26579413030177940E-1,
     127             :             1.25304936549413393E-2
     128             :         };
     129           0 :         pn = pn22;
     130           0 :         qn = qn22;
     131             :     }
     132             :     else /* if ( x < 6.0 )  this is true, but the compiler does not know */
     133             :     {
     134             :         static const double pn60[] = {
     135             :             9.99921140009714409E-1,
     136             :             1.62356584489366647,
     137             :             1.26739901455873222,
     138             :             5.81528574177741135E-1,
     139             :             1.57289620742838702E-1,
     140             :             2.25716982919217555E-2
     141             :         };
     142             :         static const double qn60[] = {
     143             :             1.00000000000000000,
     144             :             2.75143870676376208,
     145             :             3.37367334657284535,
     146             :             2.38574194785344389,
     147             :             1.05074004614827206,
     148             :             2.78788439273628983E-1,
     149             :             4.00072964526861362E-2
     150             :         };
     151           0 :         pn = pn60;
     152           0 :         qn = qn60;
     153             :     }
     154             : 
     155           0 :     for ( unsigned int i = 0; i < 6; ++i )
     156             :     {
     157           0 :         fPSum += pn[i]*fXPow;
     158           0 :         fQSum += qn[i]*fXPow;
     159           0 :         fXPow *= x;
     160             :     }
     161           0 :     fQSum += qn[6]*fXPow;
     162           0 :     fVal = exp( -1.0*x*x )* fPSum / fQSum;
     163           0 : }
     164             : 
     165             : /** Approximation algorithm for erfc for 6.0 < x < 26.54 (but used for all
     166             :     x > 6.0). */
     167           0 : static void lcl_Erfc2654( double x, double& fVal )
     168             : {
     169             :     static const double pn[] = {
     170             :         5.64189583547756078E-1,
     171             :         8.80253746105525775,
     172             :         3.84683103716117320E1,
     173             :         4.77209965874436377E1,
     174             :         8.08040729052301677
     175             :     };
     176             :     static const double qn[] = {
     177             :         1.00000000000000000,
     178             :         1.61020914205869003E1,
     179             :         7.54843505665954743E1,
     180             :         1.12123870801026015E2,
     181             :         3.73997570145040850E1
     182             :     };
     183             : 
     184           0 :     double fPSum = 0.0;
     185           0 :     double fQSum = 0.0;
     186           0 :     double fXPow = 1.0;
     187             : 
     188           0 :     for ( unsigned int i = 0; i <= 4; ++i )
     189             :     {
     190           0 :         fPSum += pn[i]*fXPow;
     191           0 :         fQSum += qn[i]*fXPow;
     192           0 :         fXPow /= x*x;
     193             :     }
     194           0 :     fVal = exp(-1.0*x*x)*fPSum / (x*fQSum);
     195           0 : }
     196             : 
     197             : namespace {
     198             : 
     199             : double const nKorrVal[] = {
     200             :     0, 9e-1, 9e-2, 9e-3, 9e-4, 9e-5, 9e-6, 9e-7, 9e-8,
     201             :     9e-9, 9e-10, 9e-11, 9e-12, 9e-13, 9e-14, 9e-15
     202             : };
     203             : 
     204             : struct StringTraits
     205             : {
     206             :     typedef sal_Char Char;
     207             : 
     208             :     typedef rtl_String String;
     209             : 
     210         816 :     static inline void createString(rtl_String ** pString,
     211             :                                     sal_Char const * pChars, sal_Int32 nLen)
     212             :     {
     213         816 :         rtl_string_newFromStr_WithLength(pString, pChars, nLen);
     214         816 :     }
     215             : 
     216           0 :     static inline void createBuffer(rtl_String ** pBuffer,
     217             :                                     sal_Int32 * pCapacity)
     218             :     {
     219           0 :         rtl_string_new_WithLength(pBuffer, *pCapacity);
     220           0 :     }
     221             : 
     222             :     static inline void appendChar(rtl_String ** pBuffer, sal_Int32 * pCapacity,
     223             :                                   sal_Int32 * pOffset, sal_Char cChar)
     224             :     {
     225             :         rtl_stringbuffer_insert(pBuffer, pCapacity, *pOffset, &cChar, 1);
     226             :         ++*pOffset;
     227             :     }
     228             : 
     229           0 :     static inline void appendChars(rtl_String ** pBuffer, sal_Int32 * pCapacity,
     230             :                                    sal_Int32 * pOffset, sal_Char const * pChars,
     231             :                                    sal_Int32 nLen)
     232             :     {
     233           0 :         rtl_stringbuffer_insert(pBuffer, pCapacity, *pOffset, pChars, nLen);
     234           0 :         *pOffset += nLen;
     235           0 :     }
     236             : 
     237           0 :     static inline void appendAscii(rtl_String ** pBuffer, sal_Int32 * pCapacity,
     238             :                                    sal_Int32 * pOffset, sal_Char const * pStr,
     239             :                                    sal_Int32 nLen)
     240             :     {
     241           0 :         rtl_stringbuffer_insert(pBuffer, pCapacity, *pOffset, pStr, nLen);
     242           0 :         *pOffset += nLen;
     243           0 :     }
     244             : };
     245             : 
     246             : struct UStringTraits
     247             : {
     248             :     typedef sal_Unicode Char;
     249             : 
     250             :     typedef rtl_uString String;
     251             : 
     252       48001 :     static inline void createString(rtl_uString ** pString,
     253             :                                     sal_Unicode const * pChars, sal_Int32 nLen)
     254             :     {
     255       48001 :         rtl_uString_newFromStr_WithLength(pString, pChars, nLen);
     256       48001 :     }
     257             : 
     258          10 :     static inline void createBuffer(rtl_uString ** pBuffer,
     259             :                                     sal_Int32 * pCapacity)
     260             :     {
     261          10 :         rtl_uString_new_WithLength(pBuffer, *pCapacity);
     262          10 :     }
     263             : 
     264             :     static inline void appendChar(rtl_uString ** pBuffer, sal_Int32 * pCapacity,
     265             :                                   sal_Int32 * pOffset, sal_Unicode cChar)
     266             :     {
     267             :         rtl_uStringbuffer_insert(pBuffer, pCapacity, *pOffset, &cChar, 1);
     268             :         ++*pOffset;
     269             :     }
     270             : 
     271        1109 :     static inline void appendChars(rtl_uString ** pBuffer,
     272             :                                    sal_Int32 * pCapacity, sal_Int32 * pOffset,
     273             :                                    sal_Unicode const * pChars, sal_Int32 nLen)
     274             :     {
     275        1109 :         rtl_uStringbuffer_insert(pBuffer, pCapacity, *pOffset, pChars, nLen);
     276        1109 :         *pOffset += nLen;
     277        1109 :     }
     278             : 
     279          10 :     static inline void appendAscii(rtl_uString ** pBuffer,
     280             :                                    sal_Int32 * pCapacity, sal_Int32 * pOffset,
     281             :                                    sal_Char const * pStr, sal_Int32 nLen)
     282             :     {
     283             :         rtl_uStringbuffer_insert_ascii(pBuffer, pCapacity, *pOffset, pStr,
     284          10 :                                        nLen);
     285          10 :         *pOffset += nLen;
     286          10 :     }
     287             : };
     288             : 
     289             : 
     290             : // Solaris C++ 5.2 compiler has problems when "StringT ** pResult" is
     291             : // "typename T::String ** pResult" instead:
     292             : template< typename T, typename StringT >
     293       49936 : inline void doubleToString(StringT ** pResult,
     294             :                            sal_Int32 * pResultCapacity, sal_Int32 nResultOffset,
     295             :                            double fValue, rtl_math_StringFormat eFormat,
     296             :                            sal_Int32 nDecPlaces, typename T::Char cDecSeparator,
     297             :                            sal_Int32 const * pGroups,
     298             :                            typename T::Char cGroupSeparator,
     299             :                            bool bEraseTrailingDecZeros)
     300             : {
     301             :     static double const nRoundVal[] = {
     302             :         5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6,
     303             :         0.5e-7, 0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14
     304             :     };
     305             : 
     306             :     // sign adjustment, instead of testing for fValue<0.0 this will also fetch
     307             :     // -0.0
     308       49936 :     bool bSign = rtl::math::isSignBitSet( fValue );
     309       49936 :     if( bSign )
     310        1461 :         fValue = -fValue;
     311             : 
     312       49936 :     if ( rtl::math::isNan( fValue ) )
     313             :     {
     314             :         // #i112652# XMLSchema-2
     315          10 :         sal_Int32 nCapacity = RTL_CONSTASCII_LENGTH("NaN");
     316          10 :         if (pResultCapacity == 0)
     317             :         {
     318          10 :             pResultCapacity = &nCapacity;
     319          10 :             T::createBuffer(pResult, pResultCapacity);
     320          10 :             nResultOffset = 0;
     321             :         }
     322          10 :         T::appendAscii(pResult, pResultCapacity, &nResultOffset,
     323          10 :                        RTL_CONSTASCII_STRINGPARAM("NaN"));
     324             : 
     325          10 :         return;
     326             :     }
     327             : 
     328       49926 :     bool bHuge = fValue == HUGE_VAL; // g++ 3.0.1 requires it this way...
     329       49926 :     if ( bHuge || rtl::math::isInf( fValue ) )
     330             :     {
     331             :         // #i112652# XMLSchema-2
     332           0 :         sal_Int32 nCapacity = RTL_CONSTASCII_LENGTH("-INF");
     333           0 :         if (pResultCapacity == 0)
     334             :         {
     335           0 :             pResultCapacity = &nCapacity;
     336           0 :             T::createBuffer(pResult, pResultCapacity);
     337           0 :             nResultOffset = 0;
     338             :         }
     339           0 :         if ( bSign )
     340           0 :             T::appendAscii(pResult, pResultCapacity, &nResultOffset,
     341           0 :                            RTL_CONSTASCII_STRINGPARAM("-"));
     342           0 :         T::appendAscii(pResult, pResultCapacity, &nResultOffset,
     343           0 :                        RTL_CONSTASCII_STRINGPARAM("INF"));
     344             : 
     345           0 :         return;
     346             :     }
     347             : 
     348             :     // find the exponent
     349       49926 :     int nExp = 0;
     350       49926 :     if ( fValue > 0.0 )
     351             :     {
     352       47105 :         nExp = static_cast< int >( floor( log10( fValue ) ) );
     353       47105 :         fValue /= getN10Exp( nExp );
     354             :     }
     355             : 
     356       49926 :     switch ( eFormat )
     357             :     {
     358             :         case rtl_math_StringFormat_Automatic :
     359             :         {   // E or F depending on exponent magnitude
     360             :             int nPrec;
     361        1604 :             if ( nExp <= -15 || nExp >= 15 )        // #58531# was <-16, >16
     362             :             {
     363           0 :                 nPrec = 14;
     364           0 :                 eFormat = rtl_math_StringFormat_E;
     365             :             }
     366             :             else
     367             :             {
     368        1604 :                 if ( nExp < 14 )
     369             :                 {
     370        1604 :                     nPrec = 15 - nExp - 1;
     371        1604 :                     eFormat = rtl_math_StringFormat_F;
     372             :                 }
     373             :                 else
     374             :                 {
     375           0 :                     nPrec = 15;
     376           0 :                     eFormat = rtl_math_StringFormat_F;
     377             :                 }
     378             :             }
     379        1604 :             if ( nDecPlaces == rtl_math_DecimalPlaces_Max )
     380        1604 :                 nDecPlaces = nPrec;
     381             :         }
     382        1604 :         break;
     383             :         case rtl_math_StringFormat_G :
     384             :         {   // G-Point, similar to sprintf %G
     385        5142 :             if ( nDecPlaces == rtl_math_DecimalPlaces_DefaultSignificance )
     386           0 :                 nDecPlaces = 6;
     387        5142 :             if ( nExp < -4 || nExp >= nDecPlaces )
     388             :             {
     389           0 :                 nDecPlaces = std::max< sal_Int32 >( 1, nDecPlaces - 1 );
     390           0 :                 eFormat = rtl_math_StringFormat_E;
     391             :             }
     392             :             else
     393             :             {
     394        5142 :                 nDecPlaces = std::max< sal_Int32 >( 0, nDecPlaces - nExp - 1 );
     395        5142 :                 eFormat = rtl_math_StringFormat_F;
     396             :             }
     397             :         }
     398        5142 :         break;
     399             :         default:
     400       43180 :         break;
     401             :     }
     402             : 
     403       49926 :     sal_Int32 nDigits = nDecPlaces + 1;
     404             : 
     405       49926 :     if( eFormat == rtl_math_StringFormat_F )
     406       49848 :         nDigits += nExp;
     407             : 
     408             :     // Round the number
     409       49926 :     if( nDigits >= 0 )
     410             :     {
     411       49924 :         if( ( fValue += nRoundVal[ nDigits > 15 ? 15 : nDigits ] ) >= 10 )
     412             :         {
     413           0 :             fValue = 1.0;
     414           0 :             nExp++;
     415           0 :             if( eFormat == rtl_math_StringFormat_F )
     416           0 :                 nDigits++;
     417             :         }
     418             :     }
     419             : 
     420             :     static sal_Int32 const nBufMax = 256;
     421             :     typename T::Char aBuf[nBufMax];
     422             :     typename T::Char * pBuf;
     423             :     sal_Int32 nBuf = static_cast< sal_Int32 >
     424       49932 :         ( nDigits <= 0 ? std::max< sal_Int32 >( nDecPlaces, abs(nExp) )
     425       99854 :           : nDigits + nDecPlaces ) + 10 + (pGroups ? abs(nDigits) * 2 : 0);
     426       49926 :     if ( nBuf > nBufMax )
     427             :     {
     428           2 :         pBuf = reinterpret_cast< typename T::Char * >(
     429           2 :             rtl_allocateMemory(nBuf * sizeof (typename T::Char)));
     430             :         OSL_ENSURE(pBuf != 0, "Out of memory");
     431             :     }
     432             :     else
     433       49924 :         pBuf = aBuf;
     434       49926 :     typename T::Char * p = pBuf;
     435       49926 :     if ( bSign )
     436        1461 :         *p++ = static_cast< typename T::Char >('-');
     437             : 
     438       49926 :     bool bHasDec = false;
     439             : 
     440             :     int nDecPos;
     441             :     // Check for F format and number < 1
     442       49926 :     if( eFormat == rtl_math_StringFormat_F )
     443             :     {
     444       49848 :         if( nExp < 0 )
     445             :         {
     446         899 :             *p++ = static_cast< typename T::Char >('0');
     447         899 :             if ( nDecPlaces > 0 )
     448             :             {
     449         899 :                 *p++ = cDecSeparator;
     450         899 :                 bHasDec = true;
     451             :             }
     452         899 :             sal_Int32 i = ( nDigits <= 0 ? nDecPlaces : -nExp - 1 );
     453        1999 :             while( (i--) > 0 )
     454         201 :                 *p++ = static_cast< typename T::Char >('0');
     455         899 :             nDecPos = 0;
     456             :         }
     457             :         else
     458       48949 :             nDecPos = nExp + 1;
     459             :     }
     460             :     else
     461          78 :         nDecPos = 1;
     462             : 
     463       49926 :     int nGrouping = 0, nGroupSelector = 0, nGroupExceed = 0;
     464       49926 :     if ( nDecPos > 1 && pGroups && pGroups[0] && cGroupSeparator )
     465             :     {
     466           0 :         while ( nGrouping + pGroups[nGroupSelector] < nDecPos )
     467             :         {
     468           0 :             nGrouping += pGroups[ nGroupSelector ];
     469           0 :             if ( pGroups[nGroupSelector+1] )
     470             :             {
     471           0 :                 if ( nGrouping + pGroups[nGroupSelector+1] >= nDecPos )
     472           0 :                     break;  // while
     473           0 :                 ++nGroupSelector;
     474             :             }
     475           0 :             else if ( !nGroupExceed )
     476           0 :                 nGroupExceed = nGrouping;
     477             :         }
     478             :     }
     479             : 
     480             :     // print the number
     481       49926 :     if( nDigits > 0 )
     482             :     {
     483      595544 :         for ( int i = 0; ; i++ )
     484             :         {
     485      595544 :             if( i < 15 )
     486             :             {
     487             :                 int nDigit;
     488      583202 :                 if (nDigits-1 == 0 && i > 0 && i < 14)
     489       42020 :                     nDigit = static_cast< int >( floor( fValue
     490       42020 :                                                         + nKorrVal[15-i] ) );
     491             :                 else
     492      541182 :                     nDigit = static_cast< int >( fValue + 1E-15 );
     493      583202 :                 if (nDigit >= 10)
     494             :                 {   // after-treatment of up-rounding to the next decade
     495           0 :                     sal_Int32 sLen = static_cast< long >(p-pBuf)-1;
     496           0 :                     if (sLen == -1)
     497             :                     {
     498           0 :                         p = pBuf;
     499           0 :                         if ( eFormat == rtl_math_StringFormat_F )
     500             :                         {
     501           0 :                             *p++ = static_cast< typename T::Char >('1');
     502           0 :                             *p++ = static_cast< typename T::Char >('0');
     503             :                         }
     504             :                         else
     505             :                         {
     506           0 :                             *p++ = static_cast< typename T::Char >('1');
     507           0 :                             *p++ = cDecSeparator;
     508           0 :                             *p++ = static_cast< typename T::Char >('0');
     509           0 :                             nExp++;
     510           0 :                             bHasDec = true;
     511             :                         }
     512             :                     }
     513             :                     else
     514             :                     {
     515           0 :                         for (sal_Int32 j = sLen; j >= 0; j--)
     516             :                         {
     517           0 :                             typename T::Char cS = pBuf[j];
     518           0 :                             if (cS != cDecSeparator)
     519             :                             {
     520           0 :                                 if ( cS != static_cast< typename T::Char >('9'))
     521             :                                 {
     522           0 :                                     pBuf[j] = ++cS;
     523           0 :                                     j = -1;                 // break loop
     524             :                                 }
     525             :                                 else
     526             :                                 {
     527           0 :                                     pBuf[j]
     528             :                                         = static_cast< typename T::Char >('0');
     529           0 :                                     if (j == 0)
     530             :                                     {
     531           0 :                                         if ( eFormat == rtl_math_StringFormat_F)
     532             :                                         {   // insert '1'
     533           0 :                                             typename T::Char * px = p++;
     534           0 :                                             while ( pBuf < px )
     535             :                                             {
     536           0 :                                                 *px = *(px-1);
     537           0 :                                                 px--;
     538             :                                             }
     539           0 :                                             pBuf[0] = static_cast<
     540             :                                                 typename T::Char >('1');
     541             :                                         }
     542             :                                         else
     543             :                                         {
     544           0 :                                             pBuf[j] = static_cast<
     545             :                                                 typename T::Char >('1');
     546           0 :                                             nExp++;
     547             :                                         }
     548             :                                     }
     549             :                                 }
     550             :                             }
     551             :                         }
     552           0 :                         *p++ = static_cast< typename T::Char >('0');
     553             :                     }
     554           0 :                     fValue = 0.0;
     555             :                 }
     556             :                 else
     557             :                 {
     558      583202 :                     *p++ = static_cast< typename T::Char >(
     559             :                         nDigit + static_cast< typename T::Char >('0') );
     560      583202 :                     fValue = ( fValue - nDigit ) * 10.0;
     561             :                 }
     562             :             }
     563             :             else
     564       12342 :                 *p++ = static_cast< typename T::Char >('0');
     565      595544 :             if( !--nDigits )
     566       49924 :                 break;  // for
     567      545620 :             if( nDecPos )
     568             :             {
     569      115769 :                 if( !--nDecPos )
     570             :                 {
     571       47924 :                     *p++ = cDecSeparator;
     572       47924 :                     bHasDec = true;
     573             :                 }
     574       67845 :                 else if ( nDecPos == nGrouping )
     575             :                 {
     576           0 :                     *p++ = cGroupSeparator;
     577           0 :                     nGrouping -= pGroups[ nGroupSelector ];
     578           0 :                     if ( nGroupSelector && nGrouping < nGroupExceed )
     579           0 :                         --nGroupSelector;
     580             :                 }
     581             :             }
     582             :         }
     583             :     }
     584             : 
     585       49926 :     if ( !bHasDec && eFormat == rtl_math_StringFormat_F )
     586             :     {   // nDecPlaces < 0 did round the value
     587        2062 :         while ( --nDecPos > 0 )
     588             :         {   // fill before decimal point
     589           0 :             if ( nDecPos == nGrouping )
     590             :             {
     591           0 :                 *p++ = cGroupSeparator;
     592           0 :                 nGrouping -= pGroups[ nGroupSelector ];
     593           0 :                 if ( nGroupSelector && nGrouping < nGroupExceed )
     594           0 :                     --nGroupSelector;
     595             :             }
     596           0 :             *p++ = static_cast< typename T::Char >('0');
     597             :         }
     598             :     }
     599             : 
     600       49926 :     if ( bEraseTrailingDecZeros && bHasDec && p > pBuf )
     601             :     {
     602      535191 :         while ( *(p-1) == static_cast< typename T::Char >('0') )
     603      439535 :             p--;
     604       47828 :         if ( *(p-1) == cDecSeparator )
     605       41543 :             p--;
     606             :     }
     607             : 
     608             :     // Print the exponent ('E', followed by '+' or '-', followed by exactly
     609             :     // three digits).  The code in rtl_[u]str_valueOf{Float|Double} relies on
     610             :     // this format.
     611       49926 :     if( eFormat == rtl_math_StringFormat_E )
     612             :     {
     613          78 :         if ( p == pBuf )
     614           0 :             *p++ = static_cast< typename T::Char >('1');
     615             :                 // maybe no nDigits if nDecPlaces < 0
     616          78 :         *p++ = static_cast< typename T::Char >('E');
     617          78 :         if( nExp < 0 )
     618             :         {
     619           0 :             nExp = -nExp;
     620           0 :             *p++ = static_cast< typename T::Char >('-');
     621             :         }
     622             :         else
     623          78 :             *p++ = static_cast< typename T::Char >('+');
     624             : //      if (nExp >= 100 )
     625          78 :         *p++ = static_cast< typename T::Char >(
     626             :             nExp / 100 + static_cast< typename T::Char >('0') );
     627          78 :         nExp %= 100;
     628          78 :         *p++ = static_cast< typename T::Char >(
     629             :             nExp / 10 + static_cast< typename T::Char >('0') );
     630          78 :         *p++ = static_cast< typename T::Char >(
     631             :             nExp % 10 + static_cast< typename T::Char >('0') );
     632             :     }
     633             : 
     634       49926 :     if (pResultCapacity == 0)
     635       48817 :         T::createString(pResult, pBuf, p - pBuf);
     636             :     else
     637        1109 :         T::appendChars(pResult, pResultCapacity, &nResultOffset, pBuf,
     638        1109 :                        p - pBuf);
     639             : 
     640       49926 :     if ( pBuf != &aBuf[0] )
     641           2 :         rtl_freeMemory(pBuf);
     642             : }
     643             : 
     644             : }
     645             : 
     646         816 : void SAL_CALL rtl_math_doubleToString(rtl_String ** pResult,
     647             :                                       sal_Int32 * pResultCapacity,
     648             :                                       sal_Int32 nResultOffset, double fValue,
     649             :                                       rtl_math_StringFormat eFormat,
     650             :                                       sal_Int32 nDecPlaces,
     651             :                                       sal_Char cDecSeparator,
     652             :                                       sal_Int32 const * pGroups,
     653             :                                       sal_Char cGroupSeparator,
     654             :                                       sal_Bool bEraseTrailingDecZeros)
     655             :     SAL_THROW_EXTERN_C()
     656             : {
     657             :     doubleToString< StringTraits, StringTraits::String >(
     658             :         pResult, pResultCapacity, nResultOffset, fValue, eFormat, nDecPlaces,
     659         816 :         cDecSeparator, pGroups, cGroupSeparator, bEraseTrailingDecZeros);
     660         816 : }
     661             : 
     662       49120 : void SAL_CALL rtl_math_doubleToUString(rtl_uString ** pResult,
     663             :                                        sal_Int32 * pResultCapacity,
     664             :                                        sal_Int32 nResultOffset, double fValue,
     665             :                                        rtl_math_StringFormat eFormat,
     666             :                                        sal_Int32 nDecPlaces,
     667             :                                        sal_Unicode cDecSeparator,
     668             :                                        sal_Int32 const * pGroups,
     669             :                                        sal_Unicode cGroupSeparator,
     670             :                                        sal_Bool bEraseTrailingDecZeros)
     671             :     SAL_THROW_EXTERN_C()
     672             : {
     673             :     doubleToString< UStringTraits, UStringTraits::String >(
     674             :         pResult, pResultCapacity, nResultOffset, fValue, eFormat, nDecPlaces,
     675       49120 :         cDecSeparator, pGroups, cGroupSeparator, bEraseTrailingDecZeros);
     676       49120 : }
     677             : 
     678             : 
     679             : namespace {
     680             : 
     681             : // if nExp * 10 + nAdd would result in overflow
     682         111 : inline bool long10Overflow( long& nExp, int nAdd )
     683             : {
     684         111 :     if ( nExp > (LONG_MAX/10)
     685         111 :          || (nExp == (LONG_MAX/10) && nAdd > (LONG_MAX%10)) )
     686             :     {
     687           0 :         nExp = LONG_MAX;
     688           0 :         return true;
     689             :     }
     690         111 :     return false;
     691             : }
     692             : 
     693             : template< typename CharT >
     694      202168 : inline double stringToDouble(CharT const * pBegin, CharT const * pEnd,
     695             :                              CharT cDecSeparator, CharT cGroupSeparator,
     696             :                              rtl_math_ConversionStatus * pStatus,
     697             :                              CharT const ** pParsedEnd)
     698             : {
     699      202168 :     double fVal = 0.0;
     700      202168 :     rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
     701             : 
     702      202168 :     CharT const * p0 = pBegin;
     703      404340 :     while (p0 != pEnd && (*p0 == CharT(' ') || *p0 == CharT('\t')))
     704           4 :         ++p0;
     705             :     bool bSign;
     706      202168 :     if (p0 != pEnd && *p0 == CharT('-'))
     707             :     {
     708       50882 :         bSign = true;
     709       50882 :         ++p0;
     710             :     }
     711             :     else
     712             :     {
     713      151286 :         bSign = false;
     714      151286 :         if (p0 != pEnd && *p0 == CharT('+'))
     715           2 :             ++p0;
     716             :     }
     717      202168 :     CharT const * p = p0;
     718      202168 :     bool bDone = false;
     719             : 
     720             :     // #i112652# XMLSchema-2
     721      202168 :     if (3 >= (pEnd - p))
     722             :     {
     723       50487 :         if ((CharT('N') == p[0]) && (CharT('a') == p[1])
     724           0 :             && (CharT('N') == p[2]))
     725             :         {
     726           0 :             p += 3;
     727           0 :             rtl::math::setNan( &fVal );
     728           0 :             bDone = true;
     729             :         }
     730       50487 :         else if ((CharT('I') == p[0]) && (CharT('N') == p[1])
     731           0 :                  && (CharT('F') == p[2]))
     732             :         {
     733           0 :             p += 3;
     734           0 :             fVal = HUGE_VAL;
     735           0 :             eStatus = rtl_math_ConversionStatus_OutOfRange;
     736           0 :             bDone = true;
     737             :         }
     738             :     }
     739             : 
     740      202168 :     if (!bDone) // do not recognize e.g. NaN1.23
     741             :     {
     742             :         // leading zeros and group separators may be safely ignored
     743      458526 :         while (p != pEnd && (*p == CharT('0') || *p == cGroupSeparator))
     744       54190 :             ++p;
     745             : 
     746      202168 :         long nValExp = 0;       // carry along exponent of mantissa
     747             : 
     748             :         // integer part of mantissa
     749      460828 :         for (; p != pEnd; ++p)
     750             :         {
     751      412279 :             CharT c = *p;
     752      412279 :             if (rtl::isAsciiDigit(c))
     753             :             {
     754      258651 :                 fVal = fVal * 10.0 + static_cast< double >( c - CharT('0') );
     755      258651 :                 ++nValExp;
     756             :             }
     757      153628 :             else if (c != cGroupSeparator)
     758      153619 :                 break;
     759             :         }
     760             : 
     761             :         // fraction part of mantissa
     762      202168 :         if (p != pEnd && *p == cDecSeparator)
     763             :         {
     764      150425 :             ++p;
     765      150425 :             double fFrac = 0.0;
     766      150425 :             long nFracExp = 0;
     767      339453 :             while (p != pEnd && *p == CharT('0'))
     768             :             {
     769       38603 :                 --nFracExp;
     770       38603 :                 ++p;
     771             :             }
     772      150425 :             if ( nValExp == 0 )
     773       30908 :                 nValExp = nFracExp - 1; // no integer part => fraction exponent
     774             :             // one decimal digit needs ld(10) ~= 3.32 bits
     775             :             static const int nSigs = (DBL_MANT_DIG / 3) + 1;
     776      150425 :             int nDigs = 0;
     777      554498 :             for (; p != pEnd; ++p)
     778             :             {
     779      404538 :                 CharT c = *p;
     780      404538 :                 if (!rtl::isAsciiDigit(c))
     781         465 :                     break;
     782      404073 :                 if ( nDigs < nSigs )
     783             :                 {   // further digits (more than nSigs) don't have any
     784             :                     // significance
     785      404073 :                     fFrac = fFrac * 10.0 + static_cast<double>(c - CharT('0'));
     786      404073 :                     --nFracExp;
     787      404073 :                     ++nDigs;
     788             :                 }
     789             :             }
     790      150425 :             if ( fFrac != 0.0 )
     791      146733 :                 fVal += rtl::math::pow10Exp( fFrac, nFracExp );
     792        3692 :             else if ( nValExp < 0 )
     793        2088 :                 nValExp = 0;    // no digit other than 0 after decimal point
     794             :         }
     795             : 
     796      202168 :         if ( nValExp > 0 )
     797      147333 :             --nValExp;  // started with offset +1 at the first mantissa digit
     798             : 
     799             :         // Exponent
     800      202168 :         if (p != p0 && p != pEnd && (*p == CharT('E') || *p == CharT('e')))
     801             :         {
     802          49 :             ++p;
     803             :             bool bExpSign;
     804          49 :             if (p != pEnd && *p == CharT('-'))
     805             :             {
     806          42 :                 bExpSign = true;
     807          42 :                 ++p;
     808             :             }
     809             :             else
     810             :             {
     811           7 :                 bExpSign = false;
     812           7 :                 if (p != pEnd && *p == CharT('+'))
     813           0 :                     ++p;
     814             :             }
     815          49 :             if ( fVal == 0.0 )
     816             :             {   // no matter what follows, zero stays zero, but carry on the
     817             :                 // offset
     818           0 :                 while (p != pEnd && rtl::isAsciiDigit(*p))
     819           0 :                     ++p;
     820             :             }
     821             :             else
     822             :             {
     823          49 :                 bool bOverFlow = false;
     824          49 :                 long nExp = 0;
     825         160 :                 for (; p != pEnd; ++p)
     826             :                 {
     827         112 :                     CharT c = *p;
     828         112 :                     if (!rtl::isAsciiDigit(c))
     829           1 :                         break;
     830         111 :                     int i = c - CharT('0');
     831         111 :                     if ( long10Overflow( nExp, i ) )
     832           0 :                         bOverFlow = true;
     833             :                     else
     834         111 :                         nExp = nExp * 10 + i;
     835             :                 }
     836          49 :                 if ( nExp )
     837             :                 {
     838          48 :                     if ( bExpSign )
     839          42 :                         nExp = -nExp;
     840          48 :                     long nAllExp = ( bOverFlow ? 0 : nExp + nValExp );
     841          48 :                     if ( nAllExp > DBL_MAX_10_EXP || (bOverFlow && !bExpSign) )
     842             :                     {   // overflow
     843           1 :                         fVal = HUGE_VAL;
     844           1 :                         eStatus = rtl_math_ConversionStatus_OutOfRange;
     845             :                     }
     846          47 :                     else if ((nAllExp < DBL_MIN_10_EXP) ||
     847             :                              (bOverFlow && bExpSign) )
     848             :                     {   // underflow
     849           0 :                         fVal = 0.0;
     850           0 :                         eStatus = rtl_math_ConversionStatus_OutOfRange;
     851             :                     }
     852          47 :                     else if ( nExp > DBL_MAX_10_EXP || nExp < DBL_MIN_10_EXP )
     853             :                     {   // compensate exponents
     854           0 :                         fVal = rtl::math::pow10Exp( fVal, -nValExp );
     855           0 :                         fVal = rtl::math::pow10Exp( fVal, nAllExp );
     856             :                     }
     857             :                     else
     858          47 :                         fVal = rtl::math::pow10Exp( fVal, nExp );  // normal
     859             :                 }
     860          49 :             }
     861             :         }
     862      202119 :         else if (p - p0 == 2 && p != pEnd && p[0] == CharT('#')
     863           0 :                  && p[-1] == cDecSeparator && p[-2] == CharT('1'))
     864             :         {
     865           0 :             if (pEnd - p >= 4 && p[1] == CharT('I') && p[2] == CharT('N')
     866           0 :                 && p[3] == CharT('F'))
     867             :             {
     868             :                 // "1.#INF", "+1.#INF", "-1.#INF"
     869           0 :                 p += 4;
     870           0 :                 fVal = HUGE_VAL;
     871           0 :                 eStatus = rtl_math_ConversionStatus_OutOfRange;
     872             :                 // Eat any further digits:
     873           0 :                 while (p != pEnd && rtl::isAsciiDigit(*p))
     874           0 :                     ++p;
     875             :             }
     876           0 :             else if (pEnd - p >= 4 && p[1] == CharT('N') && p[2] == CharT('A')
     877           0 :                 && p[3] == CharT('N'))
     878             :             {
     879             :                 // "1.#NAN", "+1.#NAN", "-1.#NAN"
     880           0 :                 p += 4;
     881           0 :                 rtl::math::setNan( &fVal );
     882           0 :                 if (bSign)
     883             :                 {
     884             :                     union {
     885             :                         double sd;
     886             :                         sal_math_Double md;
     887             :                     } m;
     888           0 :                     m.sd = fVal;
     889           0 :                     m.md.w32_parts.msw |= 0x80000000; // create negative NaN
     890           0 :                     fVal = m.sd;
     891           0 :                     bSign = false; // don't negate again
     892             :                 }
     893             :                 // Eat any further digits:
     894           0 :                 while (p != pEnd && rtl::isAsciiDigit(*p))
     895           0 :                     ++p;
     896             :             }
     897             :         }
     898             :     }
     899             : 
     900             :     // overflow also if more than DBL_MAX_10_EXP digits without decimal
     901             :     // separator, or 0. and more than DBL_MIN_10_EXP digits, ...
     902      202168 :     bool bHuge = fVal == HUGE_VAL; // g++ 3.0.1 requires it this way...
     903      202168 :     if ( bHuge )
     904           1 :         eStatus = rtl_math_ConversionStatus_OutOfRange;
     905             : 
     906      202168 :     if ( bSign )
     907       50882 :         fVal = -fVal;
     908             : 
     909      202168 :     if (pStatus != 0)
     910      167995 :         *pStatus = eStatus;
     911      202168 :     if (pParsedEnd != 0)
     912      183434 :         *pParsedEnd = p == p0 ? pBegin : p;
     913             : 
     914      202168 :     return fVal;
     915             : }
     916             : 
     917             : }
     918             : 
     919       29254 : double SAL_CALL rtl_math_stringToDouble(sal_Char const * pBegin,
     920             :                                         sal_Char const * pEnd,
     921             :                                         sal_Char cDecSeparator,
     922             :                                         sal_Char cGroupSeparator,
     923             :                                         rtl_math_ConversionStatus * pStatus,
     924             :                                         sal_Char const ** pParsedEnd)
     925             :     SAL_THROW_EXTERN_C()
     926             : {
     927             :     return stringToDouble(pBegin, pEnd, cDecSeparator, cGroupSeparator, pStatus,
     928       29254 :                           pParsedEnd);
     929             : }
     930             : 
     931      172914 : double SAL_CALL rtl_math_uStringToDouble(sal_Unicode const * pBegin,
     932             :                                          sal_Unicode const * pEnd,
     933             :                                          sal_Unicode cDecSeparator,
     934             :                                          sal_Unicode cGroupSeparator,
     935             :                                          rtl_math_ConversionStatus * pStatus,
     936             :                                          sal_Unicode const ** pParsedEnd)
     937             :     SAL_THROW_EXTERN_C()
     938             : {
     939             :     return stringToDouble(pBegin, pEnd, cDecSeparator, cGroupSeparator, pStatus,
     940      172914 :                           pParsedEnd);
     941             : }
     942             : 
     943   110321971 : double SAL_CALL rtl_math_round(double fValue, int nDecPlaces,
     944             :                                enum rtl_math_RoundingMode eMode)
     945             :     SAL_THROW_EXTERN_C()
     946             : {
     947             :     OSL_ASSERT(nDecPlaces >= -20 && nDecPlaces <= 20);
     948             : 
     949   110321971 :     if ( fValue == 0.0  )
     950   109059320 :         return fValue;
     951             : 
     952             :     // sign adjustment
     953     1262651 :     bool bSign = rtl::math::isSignBitSet( fValue );
     954     1262651 :     if ( bSign )
     955        1360 :         fValue = -fValue;
     956             : 
     957     1262651 :     double fFac = 0;
     958     1262651 :     if ( nDecPlaces != 0 )
     959             :     {
     960             :         // max 20 decimals, we don't have unlimited precision
     961             :         // #38810# and no overflow on fValue*=fFac
     962     1236585 :         if ( nDecPlaces < -20 || 20 < nDecPlaces || fValue > (DBL_MAX / 1e20) )
     963           0 :             return bSign ? -fValue : fValue;
     964             : 
     965     1236585 :         fFac = getN10Exp( nDecPlaces );
     966     1236585 :         fValue *= fFac;
     967             :     }
     968             :     //else  //! uninitialized fFac, not needed
     969             : 
     970     1262651 :     switch ( eMode )
     971             :     {
     972             :         case rtl_math_RoundingMode_Corrected :
     973             :         {
     974             :             int nExp;       // exponent for correction
     975     1262341 :             if ( fValue > 0.0 )
     976     1262341 :                 nExp = static_cast<int>( floor( log10( fValue ) ) );
     977             :             else
     978           0 :                 nExp = 0;
     979     1262341 :             int nIndex = 15 - nExp;
     980     1262341 :             if ( nIndex > 15 )
     981           8 :                 nIndex = 15;
     982     1262333 :             else if ( nIndex <= 1 )
     983       22307 :                 nIndex = 0;
     984     1262341 :             fValue = floor( fValue + 0.5 + nKorrVal[nIndex] );
     985             :         }
     986     1262341 :         break;
     987             :         case rtl_math_RoundingMode_Down :
     988           0 :             fValue = rtl::math::approxFloor( fValue );
     989           0 :         break;
     990             :         case rtl_math_RoundingMode_Up :
     991           0 :             fValue = rtl::math::approxCeil( fValue );
     992           0 :         break;
     993             :         case rtl_math_RoundingMode_Floor :
     994             :             fValue = bSign ? rtl::math::approxCeil( fValue )
     995         310 :                 : rtl::math::approxFloor( fValue );
     996         310 :         break;
     997             :         case rtl_math_RoundingMode_Ceiling :
     998             :             fValue = bSign ? rtl::math::approxFloor( fValue )
     999           0 :                 : rtl::math::approxCeil( fValue );
    1000           0 :         break;
    1001             :         case rtl_math_RoundingMode_HalfDown :
    1002             :         {
    1003           0 :             double f = floor( fValue );
    1004           0 :             fValue = ((fValue - f) <= 0.5) ? f : ceil( fValue );
    1005             :         }
    1006           0 :         break;
    1007             :         case rtl_math_RoundingMode_HalfUp :
    1008             :         {
    1009           0 :             double f = floor( fValue );
    1010           0 :             fValue = ((fValue - f) < 0.5) ? f : ceil( fValue );
    1011             :         }
    1012           0 :         break;
    1013             :         case rtl_math_RoundingMode_HalfEven :
    1014             : #if defined FLT_ROUNDS
    1015             : /*
    1016             :     Use fast version. FLT_ROUNDS may be defined to a function by some compilers!
    1017             : 
    1018             :     DBL_EPSILON is the smallest fractional number which can be represented,
    1019             :     its reciprocal is therefore the smallest number that cannot have a
    1020             :     fractional part. Once you add this reciprocal to `x', its fractional part
    1021             :     is stripped off. Simply subtracting the reciprocal back out returns `x'
    1022             :     without its fractional component.
    1023             :     Simple, clever, and elegant - thanks to Ross Cottrell, the original author,
    1024             :     who placed it into public domain.
    1025             : 
    1026             :     volatile: prevent compiler from being too smart
    1027             : */
    1028             :             if ( FLT_ROUNDS == 1 )
    1029             :             {
    1030           0 :                 volatile double x = fValue + 1.0 / DBL_EPSILON;
    1031           0 :                 fValue = x - 1.0 / DBL_EPSILON;
    1032             :             }
    1033             :             else
    1034             : #endif // FLT_ROUNDS
    1035             :             {
    1036             :                 double f = floor( fValue );
    1037             :                 if ( (fValue - f) != 0.5 )
    1038             :                     fValue = floor( fValue + 0.5 );
    1039             :                 else
    1040             :                 {
    1041             :                     double g = f / 2.0;
    1042             :                     fValue = (g == floor( g )) ? f : (f + 1.0);
    1043             :                 }
    1044             :             }
    1045           0 :         break;
    1046             :         default:
    1047             :             OSL_ASSERT(false);
    1048           0 :         break;
    1049             :     }
    1050             : 
    1051     1262651 :     if ( nDecPlaces != 0 )
    1052     1236585 :         fValue /= fFac;
    1053             : 
    1054     1262651 :     return bSign ? -fValue : fValue;
    1055             : }
    1056             : 
    1057             : 
    1058      148583 : double SAL_CALL rtl_math_pow10Exp(double fValue, int nExp) SAL_THROW_EXTERN_C()
    1059             : {
    1060      148583 :     return fValue * getN10Exp( nExp );
    1061             : }
    1062             : 
    1063             : 
    1064       23208 : double SAL_CALL rtl_math_approxValue( double fValue ) SAL_THROW_EXTERN_C()
    1065             : {
    1066       23208 :     if (fValue == 0.0 || fValue == HUGE_VAL || !::rtl::math::isFinite( fValue))
    1067             :         // We don't handle these conditions.  Bail out.
    1068         901 :         return fValue;
    1069             : 
    1070       22307 :     double fOrigValue = fValue;
    1071             : 
    1072       22307 :     bool bSign = ::rtl::math::isSignBitSet( fValue);
    1073       22307 :     if (bSign)
    1074        1155 :         fValue = -fValue;
    1075             : 
    1076       22307 :     int nExp = static_cast<int>( floor( log10( fValue)));
    1077       22307 :     nExp = 14 - nExp;
    1078       22307 :     double fExpValue = getN10Exp( nExp);
    1079             : 
    1080       22307 :     fValue *= fExpValue;
    1081             :     // If the original value was near DBL_MIN we got an overflow. Restore and
    1082             :     // bail out.
    1083       22307 :     if (!rtl::math::isFinite( fValue))
    1084           0 :         return fOrigValue;
    1085       22307 :     fValue = rtl_math_round( fValue, 0, rtl_math_RoundingMode_Corrected);
    1086       22307 :     fValue /= fExpValue;
    1087             :     // If the original value was near DBL_MAX we got an overflow. Restore and
    1088             :     // bail out.
    1089       22307 :     if (!rtl::math::isFinite( fValue))
    1090           0 :         return fOrigValue;
    1091             : 
    1092       22307 :     return bSign ? -fValue : fValue;
    1093             : }
    1094             : 
    1095             : 
    1096           0 : double SAL_CALL rtl_math_expm1( double fValue ) SAL_THROW_EXTERN_C()
    1097             : {
    1098           0 :     double fe = exp( fValue );
    1099           0 :     if (fe == 1.0)
    1100           0 :         return fValue;
    1101           0 :     if (fe-1.0 == -1.0)
    1102           0 :         return -1.0;
    1103           0 :     return (fe-1.0) * fValue / log(fe);
    1104             : }
    1105             : 
    1106             : 
    1107           0 : double SAL_CALL rtl_math_log1p( double fValue ) SAL_THROW_EXTERN_C()
    1108             : {
    1109             :     // Use volatile because a compiler may be too smart "optimizing" the
    1110             :     // condition such that in certain cases the else path was called even if
    1111             :     // (fp==1.0) was true, where the term (fp-1.0) then resulted in 0.0 and
    1112             :     // hence the entire expression resulted in NaN.
    1113             :     // Happened with g++ 3.4.1 and an input value of 9.87E-18
    1114           0 :     volatile double fp = 1.0 + fValue;
    1115           0 :     if (fp == 1.0)
    1116           0 :         return fValue;
    1117             :     else
    1118           0 :         return log(fp) * fValue / (fp-1.0);
    1119             : }
    1120             : 
    1121             : 
    1122           0 : double SAL_CALL rtl_math_atanh( double fValue ) SAL_THROW_EXTERN_C()
    1123             : {
    1124           0 :    return 0.5 * rtl_math_log1p( 2.0 * fValue / (1.0-fValue) );
    1125             : }
    1126             : 
    1127             : 
    1128             : /** Parent error function (erf) that calls different algorithms based on the
    1129             :     value of x.  It takes care of cases where x is negative as erf is an odd
    1130             :     function i.e. erf(-x) = -erf(x).
    1131             : 
    1132             :     Kramer, W., and Blomquist, F., 2000, Algorithms with Guaranteed Error Bounds
    1133             :     for the Error Function and the Complementary Error Function
    1134             : 
    1135             :     http://www.math.uni-wuppertal.de/wrswt/literatur_en.html
    1136             : 
    1137             :     @author Kohei Yoshida <kohei@openoffice.org>
    1138             : 
    1139             :     @see #i55735#
    1140             :  */
    1141           0 : double SAL_CALL rtl_math_erf( double x ) SAL_THROW_EXTERN_C()
    1142             : {
    1143           0 :     if( x == 0.0 )
    1144           0 :         return 0.0;
    1145             : 
    1146           0 :     bool bNegative = false;
    1147           0 :     if ( x < 0.0 )
    1148             :     {
    1149           0 :         x = fabs( x );
    1150           0 :         bNegative = true;
    1151             :     }
    1152             : 
    1153           0 :     double fErf = 1.0;
    1154           0 :     if ( x < 1.0e-10 )
    1155           0 :         fErf = (double) (x*1.1283791670955125738961589031215452L);
    1156           0 :     else if ( x < 0.65 )
    1157           0 :         lcl_Erf0065( x, fErf );
    1158             :     else
    1159           0 :         fErf = 1.0 - rtl_math_erfc( x );
    1160             : 
    1161           0 :     if ( bNegative )
    1162           0 :         fErf *= -1.0;
    1163             : 
    1164           0 :     return fErf;
    1165             : }
    1166             : 
    1167             : 
    1168             : /** Parent complementary error function (erfc) that calls different algorithms
    1169             :     based on the value of x.  It takes care of cases where x is negative as erfc
    1170             :     satisfies relationship erfc(-x) = 2 - erfc(x).  See the comment for Erf(x)
    1171             :     for the source publication.
    1172             : 
    1173             :     @author Kohei Yoshida <kohei@openoffice.org>
    1174             : 
    1175             :     @see #i55735#, moved from module scaddins (#i97091#)
    1176             : 
    1177             :  */
    1178           0 : double SAL_CALL rtl_math_erfc( double x ) SAL_THROW_EXTERN_C()
    1179             : {
    1180           0 :     if ( x == 0.0 )
    1181           0 :         return 1.0;
    1182             : 
    1183           0 :     bool bNegative = false;
    1184           0 :     if ( x < 0.0 )
    1185             :     {
    1186           0 :         x = fabs( x );
    1187           0 :         bNegative = true;
    1188             :     }
    1189             : 
    1190           0 :     double fErfc = 0.0;
    1191           0 :     if ( x >= 0.65 )
    1192             :     {
    1193           0 :         if ( x < 6.0 )
    1194           0 :             lcl_Erfc0600( x, fErfc );
    1195             :         else
    1196           0 :             lcl_Erfc2654( x, fErfc );
    1197             :     }
    1198             :     else
    1199           0 :         fErfc = 1.0 - rtl_math_erf( x );
    1200             : 
    1201           0 :     if ( bNegative )
    1202           0 :         fErfc = 2.0 - fErfc;
    1203             : 
    1204           0 :     return fErfc;
    1205             : }
    1206             : 
    1207             : /** improved accuracy of asinh for |x| large and for x near zero
    1208             :     @see #i97605#
    1209             :  */
    1210           0 : double SAL_CALL rtl_math_asinh( double fX ) SAL_THROW_EXTERN_C()
    1211             : {
    1212           0 :     if ( fX == 0.0 )
    1213           0 :         return 0.0;
    1214             :     else
    1215             :     {
    1216           0 :         double fSign = 1.0;
    1217           0 :         if ( fX < 0.0 )
    1218             :         {
    1219           0 :             fX = - fX;
    1220           0 :             fSign = -1.0;
    1221             :         }
    1222           0 :         if ( fX < 0.125 )
    1223           0 :             return fSign * rtl_math_log1p( fX + fX*fX / (1.0 + sqrt( 1.0 + fX*fX)));
    1224           0 :         else if ( fX < 1.25e7 )
    1225           0 :             return fSign * log( fX + sqrt( 1.0 + fX*fX));
    1226             :         else
    1227           0 :             return fSign * log( 2.0*fX);
    1228             :     }
    1229             : }
    1230             : 
    1231             : /** improved accuracy of acosh for x large and for x near 1
    1232             :     @see #i97605#
    1233             :  */
    1234           2 : double SAL_CALL rtl_math_acosh( double fX ) SAL_THROW_EXTERN_C()
    1235             : {
    1236           2 :     volatile double fZ = fX - 1.0;
    1237           2 :     if ( fX < 1.0 )
    1238             :     {
    1239             :         double fResult;
    1240           0 :         ::rtl::math::setNan( &fResult );
    1241           0 :         return fResult;
    1242             :     }
    1243           2 :     else if ( fX == 1.0 )
    1244           2 :         return 0.0;
    1245           0 :     else if ( fX < 1.1 )
    1246           0 :         return rtl_math_log1p( fZ + sqrt( fZ*fZ + 2.0*fZ));
    1247           0 :     else if ( fX < 1.25e7 )
    1248           0 :         return log( fX + sqrt( fX*fX - 1.0));
    1249             :     else
    1250           0 :         return log( 2.0*fX);
    1251             : }
    1252             : 
    1253             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10