LCOV - code coverage report
Current view: top level - sal/rtl/source - math.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 277 511 54.2 %
Date: 2012-08-25 Functions: 21 33 63.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 361 809 44.6 %

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

Generated by: LCOV version 1.10