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

Generated by: LCOV version 1.10