PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - standard - math.c
Test: PHP Code Coverage
Date: 2009-11-21 Instrumented lines: 448
Code covered: 92.0 % Executed lines: 412
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 The PHP Group                                |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 3.01 of the PHP license,      |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.php.net/license/3_01.txt                                  |
      11                 :    | If you did not receive a copy of the PHP license and are unable to   |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@php.net so we can mail you a copy immediately.               |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Authors: Jim Winstead <jimw@php.net>                                 |
      16                 :    |          Stig Sæther Bakken <ssb@php.net>                            |
      17                 :    |          Zeev Suraski <zeev@zend.com>                                |
      18                 :    | PHP 4.0 patches by Thies C. Arntzen <thies@thieso.net>               |
      19                 :    +----------------------------------------------------------------------+
      20                 : */
      21                 : 
      22                 : /* $Id: math.c 277398 2009-03-18 10:18:10Z dmitry $ */
      23                 : 
      24                 : #include "php.h"
      25                 : #include "php_math.h"
      26                 : #include "zend_multiply.h"
      27                 : 
      28                 : #include <math.h>
      29                 : #include <float.h>
      30                 : #include <stdlib.h>
      31                 : 
      32                 : /* {{{ php_intlog10abs
      33                 :    Returns floor(log10(fabs(val))), uses fast binary search */
      34            1469 : static inline int php_intlog10abs(double value) {
      35                 :         int result;
      36            1469 :         value = fabs(value);
      37                 : 
      38            1500 :         if (value < 1e-8 || value > 1e23) {
      39              31 :                 result = (int)floor(log10(value));
      40                 :         } else {
      41                 :                 static const double values[] = {
      42                 :                         1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1,
      43                 :                         1e0,  1e1,  1e2,  1e3,  1e4,  1e5,  1e6,  1e7,
      44                 :                         1e8,  1e9,  1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
      45                 :                         1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
      46                 :                 /* Do a binary search with 5 steps */
      47            1438 :                 result = 16;
      48            1438 :                 if (value < values[result]) {
      49            1389 :                         result -= 8;
      50                 :                 } else {
      51              49 :                         result += 8;
      52                 :                 }
      53            1438 :                 if (value < values[result]) {
      54              64 :                         result -= 4;
      55                 :                 } else {
      56            1374 :                         result += 4;
      57                 :                 }
      58            1438 :                 if (value < values[result]) {
      59            1200 :                         result -= 2;
      60                 :                 } else {
      61             238 :                         result += 2;
      62                 :                 }
      63            1438 :                 if (value < values[result]) {
      64             347 :                         result -= 1;
      65                 :                 } else {
      66            1091 :                         result += 1;
      67                 :                 }
      68            1438 :                 if (value < values[result]) {
      69             777 :                         result -= 1;
      70                 :                 }
      71            1438 :                 result -= 8;
      72                 :         }
      73            1469 :         return result;
      74                 : }
      75                 : /* }}} */
      76                 : 
      77                 : /* {{{ php_intpow10
      78                 :        Returns pow(10.0, (double)power), uses fast lookup table for exact powers */
      79            4327 : static inline double php_intpow10(int power) {
      80                 :         static const double powers[] = {
      81                 :                 1e0,  1e1,  1e2,  1e3,  1e4,  1e5,  1e6,  1e7,
      82                 :                 1e8,  1e9,  1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
      83                 :                 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
      84                 : 
      85                 :         /* Not in lookup table */
      86            4327 :         if (power < 0 || power > 22) {
      87              20 :                 return pow(10.0, (double)power);
      88                 :         }
      89            4307 :         return powers[power];
      90                 : }
      91                 : /* }}} */
      92                 : 
      93                 : /* {{{ php_round_helper
      94                 :        Actually performs the rounding of a value to integer in a certain mode */
      95            2880 : static inline double php_round_helper(double value, int mode) {
      96                 :         double tmp_value;
      97                 : 
      98            2880 :         if (value >= 0.0) {
      99            2808 :                 tmp_value = floor(value + 0.5);
     100            2808 :                 if ((mode == PHP_ROUND_HALF_DOWN && value == (-0.5 + tmp_value)) ||
     101                 :                         (mode == PHP_ROUND_HALF_EVEN && value == (0.5 + 2 * floor(tmp_value/2.0))) ||
     102                 :                         (mode == PHP_ROUND_HALF_ODD  && value == (0.5 + 2 * floor(tmp_value/2.0) - 1.0)))
     103                 :                 {
     104               4 :                         tmp_value = tmp_value - 1.0;
     105                 :                 }
     106                 :         } else {
     107              72 :                 tmp_value = ceil(value - 0.5);
     108              72 :                 if ((mode == PHP_ROUND_HALF_DOWN && value == (0.5 + tmp_value)) ||
     109                 :                         (mode == PHP_ROUND_HALF_EVEN && value == (-0.5 + 2 * ceil(tmp_value/2.0))) ||
     110                 :                         (mode == PHP_ROUND_HALF_ODD  && value == (-0.5 + 2 * ceil(tmp_value/2.0) + 1.0)))
     111                 :                 {
     112               4 :                         tmp_value = tmp_value + 1.0;
     113                 :                 }
     114                 :         }
     115                 : 
     116            2880 :         return tmp_value;
     117                 : }
     118                 : /* }}} */
     119                 : 
     120                 : /* {{{ _php_math_round */
     121                 : /*
     122                 :  * Rounds a number to a certain number of decimal places in a certain rounding
     123                 :  * mode. For the specifics of the algorithm, see http://wiki.php.net/rfc/rounding
     124                 :  */
     125            1469 : PHPAPI double _php_math_round(double value, int places, int mode) {
     126                 :         double f1, f2;
     127                 :         double tmp_value;
     128                 :         int precision_places;
     129                 : 
     130            1469 :         precision_places = 14 - php_intlog10abs(value);
     131                 : 
     132            1469 :         f1 = php_intpow10(abs(places));
     133                 : 
     134                 :         /* If the decimal precision guaranteed by FP arithmetic is higher than
     135                 :            the requested places BUT is small enough to make sure a non-zero value
     136                 :            is returned, pre-round the result to the precision */
     137            2898 :         if (precision_places > places && precision_places - places < 15) {
     138            1429 :                 f2 = php_intpow10(abs(precision_places));
     139            1429 :                 if (precision_places >= 0) {
     140            1423 :                         tmp_value = value * f2;
     141                 :                 } else {
     142               6 :                         tmp_value = value / f2;
     143                 :                 }
     144                 :                 /* preround the result (tmp_value will always be something * 1e14,
     145                 :                    thus never larger than 1e15 here) */
     146            1429 :                 tmp_value = php_round_helper(tmp_value, mode);
     147                 :                 /* now correctly move the decimal point */
     148            1429 :                 f2 = php_intpow10(abs(places - precision_places));
     149                 :                 /* because places < precision_places */
     150            1429 :                 tmp_value = tmp_value / f2;
     151                 :         } else {
     152                 :                 /* adjust the value */
     153              40 :                 if (places >= 0) {
     154              38 :                         tmp_value = value * f1;
     155                 :                 } else {
     156               2 :                         tmp_value = value / f1;
     157                 :                 }
     158                 :                 /* This value is beyond our precision, so rounding it is pointless */
     159              40 :                 if (fabs(tmp_value) >= 1e15) {
     160              18 :                         return value;
     161                 :                 }
     162                 :         }
     163                 : 
     164                 :         /* round the temp value */
     165            1451 :         tmp_value = php_round_helper(tmp_value, mode);
     166                 :         
     167                 :         /* see if it makes sense to use simple division to round the value */
     168            2893 :         if (abs(places) < 23) {
     169            1442 :                 if (places > 0) {
     170             169 :                         tmp_value = tmp_value / f1;
     171                 :                 } else {
     172            1273 :                         tmp_value = tmp_value * f1;
     173                 :                 }
     174                 :         } else {
     175                 :                 /* Simple division can't be used since that will cause wrong results.
     176                 :                    Instead, the number is converted to a string and back again using
     177                 :                    strtod(). strtod() will return the nearest possible FP value for
     178                 :                    that string. */
     179                 : 
     180                 :                 /* 40 Bytes should be more than enough for this format string. The
     181                 :                    float won't be larger than 1e15 anyway. But just in case, use
     182                 :                    snprintf() and make sure the buffer is zero-terminated */
     183                 :                 char buf[40];
     184               9 :                 snprintf(buf, 39, "%15fe%d", tmp_value, -places);
     185               9 :                 buf[39] = '\0';
     186               9 :                 tmp_value = zend_strtod(buf, NULL);
     187                 :                 /* couldn't convert to string and back */
     188               9 :                 if (!zend_finite(tmp_value) || zend_isnan(tmp_value)) {
     189               0 :                         tmp_value = value;
     190                 :                 }
     191                 :         }
     192                 : 
     193            1451 :         return tmp_value;
     194                 : }
     195                 : /* }}} */
     196                 : 
     197                 : /* {{{ php_asinh
     198                 : */
     199                 : static double php_asinh(double z)
     200              18 : {
     201                 : #ifdef HAVE_ASINH
     202              18 :         return(asinh(z));
     203                 : #else
     204                 :         return(log(z + sqrt(1 + pow(z, 2))) / log(M_E));
     205                 : #endif
     206                 : }
     207                 : /* }}} */
     208                 : 
     209                 : /* {{{ php_acosh
     210                 : */
     211                 : static double php_acosh(double x)
     212              18 : {
     213                 : #ifdef HAVE_ACOSH
     214              18 :         return(acosh(x));
     215                 : #else
     216                 :         return(log(x + sqrt(x * x - 1)));
     217                 : #endif
     218                 : }
     219                 : /* }}} */
     220                 : 
     221                 : /* {{{ php_atanh
     222                 : */
     223                 : static double php_atanh(double z)
     224              18 : {
     225                 : #ifdef HAVE_ATANH
     226              18 :         return(atanh(z));
     227                 : #else
     228                 :         return(0.5 * log((1 + z) / (1 - z)));
     229                 : #endif
     230                 : }
     231                 : /* }}} */
     232                 : 
     233                 : /* {{{ php_log1p
     234                 : */
     235                 : static double php_log1p(double x)
     236              31 : {
     237                 : #ifdef HAVE_LOG1P
     238              31 :         return(log1p(x));
     239                 : #else
     240                 :         return(log(1 + x));
     241                 : #endif
     242                 : }
     243                 : /* }}} */
     244                 : 
     245                 : /* {{{ php_expm1
     246                 : */
     247                 : static double php_expm1(double x)
     248              30 : {
     249                 : #if !defined(PHP_WIN32) && !defined(NETWARE)
     250              30 :         return(expm1(x));
     251                 : #else
     252                 :         return(exp(x) - 1);
     253                 : #endif
     254                 : }
     255                 : /* }}}*/
     256                 : 
     257                 : /* {{{ proto int abs(int number)
     258                 :    Return the absolute value of the number */
     259                 : PHP_FUNCTION(abs) 
     260              69 : {
     261                 :         zval **value;
     262                 :         
     263              69 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &value) == FAILURE) {
     264               2 :                 return;
     265                 :         }
     266              67 :         convert_scalar_to_number_ex(value);
     267                 :         
     268              67 :         if (Z_TYPE_PP(value) == IS_DOUBLE) {
     269              38 :                 RETURN_DOUBLE(fabs(Z_DVAL_PP(value)));
     270              29 :         } else if (Z_TYPE_PP(value) == IS_LONG) {
     271              28 :                 if (Z_LVAL_PP(value) == LONG_MIN) {
     272               1 :                         RETURN_DOUBLE(-(double)LONG_MIN);
     273                 :                 } else {
     274              27 :                         RETURN_LONG(Z_LVAL_PP(value) < 0 ? -Z_LVAL_PP(value) : Z_LVAL_PP(value));
     275                 :                 }
     276                 :         }
     277               1 :         RETURN_FALSE;
     278                 : }
     279                 : /* }}} */ 
     280                 : 
     281                 : /* {{{ proto float ceil(float number)
     282                 :    Returns the next highest integer value of the number */
     283                 : PHP_FUNCTION(ceil) 
     284              56 : {
     285                 :         zval **value;
     286                 :         
     287              56 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &value) == FAILURE) {
     288               2 :                 return;
     289                 :         }
     290              54 :         convert_scalar_to_number_ex(value);
     291                 : 
     292              54 :         if (Z_TYPE_PP(value) == IS_DOUBLE) {
     293              23 :                 RETURN_DOUBLE(ceil(Z_DVAL_PP(value)));
     294              31 :         } else if (Z_TYPE_PP(value) == IS_LONG) {
     295              30 :                 convert_to_double_ex(value);
     296              30 :                 RETURN_DOUBLE(Z_DVAL_PP(value));
     297                 :         }
     298               1 :         RETURN_FALSE;
     299                 : }
     300                 : /* }}} */
     301                 : 
     302                 : /* {{{ proto float floor(float number)
     303                 :    Returns the next lowest integer value from the number */
     304                 : PHP_FUNCTION(floor)
     305             420 : {
     306                 :         zval **value;
     307                 :         
     308             420 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &value) == FAILURE) {
     309               2 :                 return;
     310                 :         }
     311             418 :         convert_scalar_to_number_ex(value);
     312                 : 
     313             418 :         if (Z_TYPE_PP(value) == IS_DOUBLE) {
     314             384 :                 RETURN_DOUBLE(floor(Z_DVAL_PP(value)));
     315              34 :         } else if (Z_TYPE_PP(value) == IS_LONG) {
     316              33 :                 convert_to_double_ex(value);
     317              33 :                 RETURN_DOUBLE(Z_DVAL_PP(value));
     318                 :         }
     319               1 :         RETURN_FALSE;
     320                 : }
     321                 : /* }}} */
     322                 : 
     323                 : /* {{{ proto float round(float number [, int precision [, int mode]])
     324                 :    Returns the number rounded to specified precision */
     325                 : PHP_FUNCTION(round)
     326            1436 : {
     327                 :         zval **value;
     328            1436 :         int places = 0;
     329            1436 :         long precision = 0;
     330            1436 :         long mode = PHP_ROUND_HALF_UP;
     331                 :         double return_val;
     332                 :         
     333            1436 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|ll", &value, &precision, &mode) == FAILURE) {
     334               9 :                 return;
     335                 :         }
     336                 : 
     337            1427 :         if (ZEND_NUM_ARGS() >= 2) {
     338             219 :                 places = (int) precision;
     339                 :         }
     340            1427 :         convert_scalar_to_number_ex(value);
     341                 : 
     342            1427 :         switch (Z_TYPE_PP(value)) {
     343                 :                 case IS_LONG:
     344                 :                         /* Simple case - long that doesn't need to be rounded. */
     345            1273 :                         if (places >= 0) {
     346            1273 :                                 RETURN_DOUBLE((double) Z_LVAL_PP(value));
     347                 :                         }
     348                 :                         /* break omitted intentionally */
     349                 : 
     350                 :                 case IS_DOUBLE:
     351             153 :                         return_val = (Z_TYPE_PP(value) == IS_LONG) ? (double)Z_LVAL_PP(value) : Z_DVAL_PP(value);
     352             153 :                         return_val = _php_math_round(return_val, places, mode);
     353             153 :                         RETURN_DOUBLE(return_val);
     354                 :                         break;
     355                 : 
     356                 :                 default:
     357               1 :                         RETURN_FALSE;
     358                 :                         break;
     359                 :         }
     360                 : }
     361                 : /* }}} */
     362                 : 
     363                 : /* {{{ proto float sin(float number)
     364                 :    Returns the sine of the number in radians */
     365                 : PHP_FUNCTION(sin)
     366              30 : {
     367                 :         double num;
     368                 : 
     369              30 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     370               3 :                 return;
     371                 :         }
     372              27 :         RETURN_DOUBLE(sin(num));
     373                 : }
     374                 : /* }}} */
     375                 : 
     376                 : /* {{{ proto float cos(float number)
     377                 :    Returns the cosine of the number in radians */
     378                 : PHP_FUNCTION(cos)
     379              32 : {
     380                 :         double num;
     381                 :         
     382              32 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     383               3 :                 return;
     384                 :         }
     385              29 :         RETURN_DOUBLE(cos(num));
     386                 : }
     387                 : /* }}} */
     388                 : 
     389                 : /* {{{ proto float tan(float number)
     390                 :    Returns the tangent of the number in radians */
     391                 : PHP_FUNCTION(tan)
     392              22 : {
     393                 :         double num;
     394                 : 
     395              22 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     396               3 :                 return;
     397                 :         }
     398              19 :         RETURN_DOUBLE(tan(num));
     399                 : }
     400                 : /* }}} */
     401                 : 
     402                 : /* {{{ proto float asin(float number)
     403                 :    Returns the arc sine of the number in radians */
     404                 : PHP_FUNCTION(asin)
     405              21 : {
     406                 :         double num;
     407                 : 
     408              21 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     409               3 :                 return;
     410                 :         }
     411              18 :         RETURN_DOUBLE(asin(num));
     412                 : }
     413                 : /* }}} */
     414                 : 
     415                 : /* {{{ proto float acos(float number)
     416                 :    Return the arc cosine of the number in radians */
     417                 : PHP_FUNCTION(acos)
     418              26 : {
     419                 :         double num;
     420                 : 
     421              26 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     422               3 :                 return;
     423                 :         }
     424              23 :         RETURN_DOUBLE(acos(num));
     425                 : }
     426                 : /* }}} */
     427                 : 
     428                 : /* {{{ proto float atan(float number)
     429                 :    Returns the arc tangent of the number in radians */
     430                 : PHP_FUNCTION(atan)
     431              19 : {
     432                 :         double num;
     433                 : 
     434              19 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     435               3 :                 return;
     436                 :         }
     437              16 :         RETURN_DOUBLE(atan(num));
     438                 : }
     439                 : /* }}} */
     440                 : 
     441                 : /* {{{ proto float atan2(float y, float x)
     442                 :    Returns the arc tangent of y/x, with the resulting quadrant determined by the signs of y and x */
     443                 : PHP_FUNCTION(atan2)
     444             199 : {
     445                 :         double num1, num2;
     446                 : 
     447             199 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &num1, &num2) == FAILURE) {
     448              19 :                 return;
     449                 :         }
     450             180 :         RETURN_DOUBLE(atan2(num1, num2));
     451                 : }
     452                 : /* }}} */
     453                 : 
     454                 : /* {{{ proto float sinh(float number)
     455                 :    Returns the hyperbolic sine of the number, defined as (exp(number) - exp(-number))/2 */
     456                 : PHP_FUNCTION(sinh)
     457              25 : {
     458                 :         double num;
     459                 : 
     460              25 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     461               3 :                 return;
     462                 :         }
     463              22 :         RETURN_DOUBLE(sinh(num));
     464                 : }
     465                 : /* }}} */
     466                 : 
     467                 : /* {{{ proto float cosh(float number)
     468                 :    Returns the hyperbolic cosine of the number, defined as (exp(number) + exp(-number))/2 */
     469                 : PHP_FUNCTION(cosh)
     470              25 : {
     471                 :         double num;
     472                 : 
     473              25 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     474               3 :                 return;
     475                 :         }
     476              22 :         RETURN_DOUBLE(cosh(num));
     477                 : }
     478                 : /* }}} */
     479                 : 
     480                 : /* {{{ proto float tanh(float number)
     481                 :    Returns the hyperbolic tangent of the number, defined as sinh(number)/cosh(number) */
     482                 : PHP_FUNCTION(tanh)
     483              25 : {
     484                 :         double num;
     485                 : 
     486              25 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     487               3 :                 return;
     488                 :         }
     489              22 :         RETURN_DOUBLE(tanh(num));
     490                 : }
     491                 : /* }}} */
     492                 : 
     493                 : /* {{{ proto float asinh(float number)
     494                 :    Returns the inverse hyperbolic sine of the number, i.e. the value whose hyperbolic sine is number */
     495                 : PHP_FUNCTION(asinh)
     496              21 : {
     497                 :         double num;
     498                 : 
     499              21 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     500               3 :                 return;
     501                 :         }
     502              18 :         RETURN_DOUBLE(php_asinh(num));
     503                 : }
     504                 : /* }}} */
     505                 : 
     506                 : /* {{{ proto float acosh(float number)
     507                 :    Returns the inverse hyperbolic cosine of the number, i.e. the value whose hyperbolic cosine is number */
     508                 : PHP_FUNCTION(acosh)
     509              21 : {
     510                 :         double num;
     511                 :         
     512              21 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     513               3 :                 return;
     514                 :         }
     515              18 :         RETURN_DOUBLE(php_acosh(num));
     516                 : }
     517                 : /* }}} */
     518                 : 
     519                 : /* {{{ proto float atanh(float number)
     520                 :    Returns the inverse hyperbolic tangent of the number, i.e. the value whose hyperbolic tangent is number */
     521                 : PHP_FUNCTION(atanh)
     522              21 : {
     523                 :         double num;
     524                 : 
     525              21 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     526               3 :                 return;
     527                 :         }
     528              18 :         RETURN_DOUBLE(php_atanh(num));
     529                 : }
     530                 : /* }}} */
     531                 : 
     532                 : /* {{{ proto float pi(void)
     533                 :    Returns an approximation of pi */
     534                 : PHP_FUNCTION(pi)
     535               1 : {
     536               1 :         RETURN_DOUBLE(M_PI);
     537                 : }
     538                 : /* }}} */
     539                 : 
     540                 : /* {{{ proto bool is_finite(float val)
     541                 :    Returns whether argument is finite */
     542                 : PHP_FUNCTION(is_finite)
     543              43 : {
     544                 :         double dval;
     545                 : 
     546              43 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) {
     547              10 :                 return;
     548                 :         }
     549              33 :         RETURN_BOOL(zend_finite(dval));
     550                 : }
     551                 : /* }}} */
     552                 : 
     553                 : /* {{{ proto bool is_infinite(float val)
     554                 :    Returns whether argument is infinite */
     555                 : PHP_FUNCTION(is_infinite)
     556              51 : {
     557                 :         double dval;
     558                 : 
     559              51 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) {
     560              10 :                 return;
     561                 :         }
     562              41 :         RETURN_BOOL(zend_isinf(dval));
     563                 : }
     564                 : /* }}} */
     565                 : 
     566                 : /* {{{ proto bool is_nan(float val)
     567                 :    Returns whether argument is not a number */
     568                 : PHP_FUNCTION(is_nan)
     569              45 : {
     570                 :         double dval;
     571                 : 
     572              45 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) {
     573              10 :                 return;
     574                 :         }
     575              35 :         RETURN_BOOL(zend_isnan(dval));
     576                 : }
     577                 : /* }}} */
     578                 : 
     579                 : /* {{{ proto number pow(number base, number exponent)
     580                 :    Returns base raised to the power of exponent. Returns integer result when possible */
     581                 : PHP_FUNCTION(pow)
     582            1472 : {
     583                 :         zval *zbase, *zexp;
     584                 : 
     585            1472 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/z/", &zbase, &zexp) == FAILURE) {
     586               6 :                 return;
     587                 :         }
     588                 : 
     589                 :         /* make sure we're dealing with numbers */
     590            1466 :         convert_scalar_to_number(zbase TSRMLS_CC);
     591            1466 :         convert_scalar_to_number(zexp TSRMLS_CC);
     592                 : 
     593                 :         /* if both base and exponent were longs, we'll try to get a long out */
     594            1466 :         if (Z_TYPE_P(zbase) == IS_LONG && Z_TYPE_P(zexp) == IS_LONG && Z_LVAL_P(zexp) >= 0) {
     595             725 :                 long l1 = 1, l2 = Z_LVAL_P(zbase), i = Z_LVAL_P(zexp);
     596                 :                 
     597             725 :                 if (i == 0) {
     598              13 :                         RETURN_LONG(1L);
     599             712 :                 } else if (l2 == 0) {
     600              14 :                         RETURN_LONG(0);
     601                 :                 }
     602                 : 
     603                 :                 /* calculate pow(long,long) in O(log exp) operations, bail if overflow */
     604            5118 :                 while (i >= 1) {
     605                 :                         int overflow;
     606            4420 :                         double dval = 0.0;
     607                 : 
     608            4420 :                         if (i % 2) {
     609            1385 :                                 --i;
     610            1385 :                                 ZEND_SIGNED_MULTIPLY_LONG(l1,l2,l1,dval,overflow);
     611            1385 :                                 if (overflow) RETURN_DOUBLE(dval * pow(l2,i));
     612                 :                         } else {
     613            3035 :                                 i /= 2;
     614            3035 :                                 ZEND_SIGNED_MULTIPLY_LONG(l2,l2,l2,dval,overflow);
     615            3035 :                                 if (overflow) RETURN_DOUBLE((double)l1 * pow(dval,i));
     616                 :                         }
     617            3892 :                         if (i == 0) {
     618             170 :                                 RETURN_LONG(l1);
     619                 :                         }
     620                 :                 }
     621                 :         }
     622             741 :         convert_to_double(zbase);
     623             741 :         convert_to_double(zexp);
     624                 :         
     625             741 :         RETURN_DOUBLE(pow(Z_DVAL_P(zbase), Z_DVAL_P(zexp)));
     626                 : }
     627                 : /* }}} */
     628                 : 
     629                 : /* {{{ proto float exp(float number)
     630                 :    Returns e raised to the power of the number */
     631                 : PHP_FUNCTION(exp)
     632             241 : {
     633                 :         double num;
     634                 : 
     635             241 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     636              10 :                 return;
     637                 :         }
     638                 : 
     639             231 :         RETURN_DOUBLE(exp(num));
     640                 : }
     641                 : /* }}} */
     642                 : 
     643                 : /* {{{ proto float expm1(float number)
     644                 :    Returns exp(number) - 1, computed in a way that accurate even when the value of number is close to zero */
     645                 : /*
     646                 :    WARNING: this function is expermental: it could change its name or 
     647                 :    disappear in the next version of PHP!
     648                 : */
     649                 : PHP_FUNCTION(expm1)
     650              44 : {
     651                 :         double num;
     652                 : 
     653              44 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     654              14 :                 return;
     655                 :         }
     656              30 :         RETURN_DOUBLE(php_expm1(num));
     657                 : }
     658                 : /* }}} */
     659                 : 
     660                 : /* {{{ proto float log1p(float number)
     661                 :    Returns log(1 + number), computed in a way that accurate even when the value of number is close to zero */ 
     662                 : /*
     663                 :    WARNING: this function is expermental: it could change its name or 
     664                 :    disappear in the next version of PHP!
     665                 : */
     666                 : PHP_FUNCTION(log1p)
     667              41 : {
     668                 :         double num;
     669                 : 
     670              41 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     671              10 :                 return;
     672                 :         }
     673              31 :         RETURN_DOUBLE(php_log1p(num));
     674                 : }
     675                 : /* }}} */
     676                 : 
     677                 : /* {{{ proto float log(float number, [float base])
     678                 :    Returns the natural logarithm of the number, or the base log if base is specified */
     679                 : PHP_FUNCTION(log)
     680             731 : {
     681             731 :         double num, base = 0;
     682                 :         
     683             731 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|d", &num, &base) == FAILURE) {
     684              18 :                 return;
     685                 :         }
     686             713 :         if (ZEND_NUM_ARGS() == 1) {
     687             214 :                 RETURN_DOUBLE(log(num));
     688                 :         }
     689             499 :         if (base <= 0.0) {
     690              10 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "base must be greater than 0");                           
     691              10 :                 RETURN_FALSE;
     692                 :         }
     693             489 :         RETURN_DOUBLE(log(num) / log(base));
     694                 : }
     695                 : /* }}} */
     696                 : 
     697                 : /* {{{ proto float log10(float number)
     698                 :    Returns the base-10 logarithm of the number */
     699                 : PHP_FUNCTION(log10)
     700              24 : {
     701                 :         double num;
     702                 : 
     703              24 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     704               3 :                 return;
     705                 :         }
     706              21 :         RETURN_DOUBLE(log10(num));
     707                 : }
     708                 : /* }}} */
     709                 : 
     710                 : /* {{{ proto float sqrt(float number)
     711                 :    Returns the square root of the number */
     712                 : PHP_FUNCTION(sqrt)
     713              22 : {
     714                 :         double num;
     715                 : 
     716              22 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     717               3 :                 return;
     718                 :         }
     719              19 :         RETURN_DOUBLE(sqrt(num));
     720                 : }
     721                 : /* }}} */
     722                 : 
     723                 : /* {{{ proto float hypot(float num1, float num2)
     724                 :    Returns sqrt(num1*num1 + num2*num2) */ 
     725                 : PHP_FUNCTION(hypot)
     726             224 : {
     727                 :         double num1, num2;
     728                 : 
     729             224 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &num1, &num2) == FAILURE) {
     730              19 :                 return;
     731                 :         }
     732                 : #if HAVE_HYPOT
     733             205 :         RETURN_DOUBLE(hypot(num1, num2));
     734                 : #elif defined(_MSC_VER)
     735                 :         RETURN_DOUBLE(_hypot(num1, num2));
     736                 : #else
     737                 :         RETURN_DOUBLE(sqrt((num1 * num1) + (num2 * num2)));
     738                 : #endif
     739                 : }
     740                 : /* }}} */
     741                 : 
     742                 : /* {{{ proto float deg2rad(float number)
     743                 :    Converts the number in degrees to the radian equivalent */
     744                 : PHP_FUNCTION(deg2rad)
     745              24 : {
     746                 :         double deg;
     747                 : 
     748              24 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &deg) == FAILURE) {
     749               3 :                 return;
     750                 :         }
     751              21 :         RETURN_DOUBLE((deg / 180.0) * M_PI);
     752                 : }
     753                 : /* }}} */
     754                 : 
     755                 : /* {{{ proto float rad2deg(float number)
     756                 :    Converts the radian number to the equivalent number in degrees */
     757                 : PHP_FUNCTION(rad2deg)
     758              21 : {
     759                 :         double rad;
     760                 : 
     761              21 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &rad) == FAILURE) {
     762               3 :                 return;
     763                 :         }
     764              18 :         RETURN_DOUBLE((rad / M_PI) * 180);
     765                 : }
     766                 : /* }}} */
     767                 : 
     768                 : /* {{{ _php_math_basetolong */
     769                 : /*
     770                 :  * Convert a string representation of a base(2-36) number to a long.
     771                 :  */
     772                 : PHPAPI long _php_math_basetolong(zval *arg, int base)
     773               0 : {
     774               0 :         long num = 0, digit, onum;
     775                 :         int i;
     776                 :         char c, *s;
     777                 : 
     778               0 :         if (Z_TYPE_P(arg) != IS_STRING || base < 2 || base > 36) {
     779               0 :                 return 0;
     780                 :         }
     781                 : 
     782               0 :         s = Z_STRVAL_P(arg);
     783                 : 
     784               0 :         for (i = Z_STRLEN_P(arg); i > 0; i--) {
     785               0 :                 c = *s++;
     786                 :                 
     787               0 :                 digit = (c >= '0' && c <= '9') ? c - '0'
     788                 :                         : (c >= 'A' && c <= 'Z') ? c - 'A' + 10
     789                 :                         : (c >= 'a' && c <= 'z') ? c - 'a' + 10
     790                 :                         : base;
     791                 :                 
     792               0 :                 if (digit >= base) {
     793               0 :                         continue;
     794                 :                 }
     795                 : 
     796               0 :                 onum = num;
     797               0 :                 num = num * base + digit;
     798               0 :                 if (num > onum)
     799               0 :                         continue;
     800                 : 
     801                 :                 {
     802                 :                         TSRMLS_FETCH();
     803                 : 
     804               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number '%s' is too big to fit in long", s);
     805               0 :                         return LONG_MAX;
     806                 :                 }
     807                 :         }
     808                 : 
     809               0 :         return num;
     810                 : }
     811                 : /* }}} */
     812                 : 
     813                 : /* {{{ _php_math_basetozval */
     814                 : /*
     815                 :  * Convert a string representation of a base(2-36) number to a zval.
     816                 :  */
     817                 : PHPAPI int _php_math_basetozval(zval *arg, int base, zval *ret)
     818             414 : {
     819             414 :         long num = 0;
     820             414 :         double fnum = 0;
     821                 :         int i;
     822             414 :         int mode = 0;
     823                 :         char c, *s;
     824                 :         long cutoff;
     825                 :         int cutlim;
     826                 : 
     827             414 :         if (Z_TYPE_P(arg) != IS_STRING || base < 2 || base > 36) {
     828               0 :                 return FAILURE;
     829                 :         }
     830                 : 
     831             414 :         s = Z_STRVAL_P(arg);
     832                 : 
     833             414 :         cutoff = LONG_MAX / base;
     834             414 :         cutlim = LONG_MAX % base;
     835                 :         
     836            1792 :         for (i = Z_STRLEN_P(arg); i > 0; i--) {
     837            1378 :                 c = *s++;
     838                 : 
     839                 :                 /* might not work for EBCDIC */
     840            2421 :                 if (c >= '0' && c <= '9') 
     841            1043 :                         c -= '0';
     842             467 :                 else if (c >= 'A' && c <= 'Z') 
     843             132 :                         c -= 'A' - 10;
     844             203 :                 else if (c >= 'a' && c <= 'z') 
     845             149 :                         c -= 'a' - 10;
     846                 :                 else
     847                 :                         continue;
     848                 : 
     849            1324 :                 if (c >= base)
     850             368 :                         continue;
     851                 :                 
     852             956 :                 switch (mode) {
     853                 :                 case 0: /* Integer */
     854             946 :                         if (num < cutoff || (num == cutoff && c <= cutlim)) {
     855             935 :                                 num = num * base + c;
     856             935 :                                 break;
     857                 :                         } else {
     858              11 :                                 fnum = num;
     859              11 :                                 mode = 1;
     860                 :                         }
     861                 :                         /* fall-through */
     862                 :                 case 1: /* Float */
     863              21 :                         fnum = fnum * base + c;
     864                 :                 }       
     865                 :         }
     866                 : 
     867             414 :         if (mode == 1) {
     868              11 :                 ZVAL_DOUBLE(ret, fnum);
     869                 :         } else {
     870             403 :                 ZVAL_LONG(ret, num);
     871                 :         }
     872             414 :         return SUCCESS;
     873                 : }
     874                 : /* }}} */
     875                 : 
     876                 : /* {{{ _php_math_longtobase */
     877                 : /*
     878                 :  * Convert a long to a string containing a base(2-36) representation of
     879                 :  * the number.
     880                 :  */
     881                 : PHPAPI char * _php_math_longtobase(zval *arg, int base)
     882          134350 : {
     883                 :         static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
     884                 :         char buf[(sizeof(unsigned long) << 3) + 1];
     885                 :         char *ptr, *end;
     886                 :         unsigned long value;
     887                 : 
     888          134350 :         if (Z_TYPE_P(arg) != IS_LONG || base < 2 || base > 36) {
     889               0 :                 return STR_EMPTY_ALLOC();
     890                 :         }
     891                 : 
     892          134350 :         value = Z_LVAL_P(arg);
     893                 : 
     894          134350 :         end = ptr = buf + sizeof(buf) - 1;
     895          134350 :         *ptr = '\0';
     896                 : 
     897                 :         do {
     898          547345 :                 *--ptr = digits[value % base];
     899          547345 :                 value /= base;
     900          547345 :         } while (ptr > buf && value);
     901                 : 
     902          134350 :         return estrndup(ptr, end - ptr);
     903                 : }
     904                 : /* }}} */
     905                 : 
     906                 : /* {{{ _php_math_zvaltobase */
     907                 : /*
     908                 :  * Convert a zval to a string containing a base(2-36) representation of
     909                 :  * the number.
     910                 :  */
     911                 : PHPAPI char * _php_math_zvaltobase(zval *arg, int base TSRMLS_DC)
     912             277 : {
     913                 :         static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
     914                 : 
     915             277 :         if ((Z_TYPE_P(arg) != IS_LONG && Z_TYPE_P(arg) != IS_DOUBLE) || base < 2 || base > 36) {
     916               0 :                 return STR_EMPTY_ALLOC();
     917                 :         }
     918                 : 
     919             277 :         if (Z_TYPE_P(arg) == IS_DOUBLE) {
     920               0 :                 double fvalue = floor(Z_DVAL_P(arg)); /* floor it just in case */
     921                 :                 char *ptr, *end;
     922                 :                 char buf[(sizeof(double) << 3) + 1];
     923                 : 
     924                 :                 /* Don't try to convert +/- infinity */
     925               0 :                 if (fvalue == HUGE_VAL || fvalue == -HUGE_VAL) {
     926               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number too large");
     927               0 :                         return STR_EMPTY_ALLOC();
     928                 :                 }
     929                 : 
     930               0 :                 end = ptr = buf + sizeof(buf) - 1;
     931               0 :                 *ptr = '\0';
     932                 : 
     933                 :                 do {
     934               0 :                         *--ptr = digits[(int) fmod(fvalue, base)];
     935               0 :                         fvalue /= base;
     936               0 :                 } while (ptr > buf && fabs(fvalue) >= 1);
     937                 : 
     938               0 :                 return estrndup(ptr, end - ptr);
     939                 :         }
     940                 :         
     941             277 :         return _php_math_longtobase(arg, base);
     942                 : }       
     943                 : /* }}} */
     944                 : 
     945                 : /* {{{ proto int bindec(string binary_number)
     946                 :    Returns the decimal equivalent of the binary number */
     947                 : PHP_FUNCTION(bindec)
     948              46 : {
     949                 :         zval **arg;
     950                 :         
     951              46 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
     952               2 :                 return;
     953                 :         }
     954              44 :         convert_to_string_ex(arg);
     955              43 :         if (_php_math_basetozval(*arg, 2, return_value) == FAILURE) {
     956               0 :                 RETURN_FALSE;
     957                 :         }
     958                 : }
     959                 : /* }}} */
     960                 : 
     961                 : /* {{{ proto int hexdec(string hexadecimal_number)
     962                 :    Returns the decimal equivalent of the hexadecimal number */
     963                 : PHP_FUNCTION(hexdec)
     964              54 : {
     965                 :         zval **arg;
     966                 :         
     967              54 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
     968               2 :                 return;
     969                 :         }
     970              52 :         convert_to_string_ex(arg);
     971              51 :         if (_php_math_basetozval(*arg, 16, return_value) == FAILURE) {
     972               0 :                 RETURN_FALSE;
     973                 :         }
     974                 : }
     975                 : /* }}} */
     976                 : 
     977                 : /* {{{ proto int octdec(string octal_number)
     978                 :    Returns the decimal equivalent of an octal string */
     979                 : PHP_FUNCTION(octdec)
     980              46 : {
     981                 :         zval **arg;
     982                 :         
     983              46 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
     984               2 :                 return;
     985                 :         }
     986              44 :         convert_to_string_ex(arg);
     987              43 :         if (_php_math_basetozval(*arg, 8, return_value) == FAILURE) {
     988               0 :                 RETURN_FALSE;
     989                 :         }
     990                 : }
     991                 : /* }}} */
     992                 : 
     993                 : /* {{{ proto string decbin(int decimal_number)
     994                 :    Returns a string containing a binary representation of the number */
     995                 : PHP_FUNCTION(decbin)
     996            2566 : {
     997                 :         zval **arg;
     998                 :         char *result;
     999                 : 
    1000            2566 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
    1001               0 :                 return;
    1002                 :         }
    1003            2566 :         convert_to_long_ex(arg);
    1004            2566 :         result = _php_math_longtobase(*arg, 2);
    1005            2566 :         RETURN_STRING(result, 0);
    1006                 : }
    1007                 : /* }}} */
    1008                 : 
    1009                 : /* {{{ proto string decoct(int decimal_number)
    1010                 :    Returns a string containing an octal representation of the given number */
    1011                 : PHP_FUNCTION(decoct)
    1012             304 : {
    1013                 :         zval **arg;
    1014                 :         char *result;
    1015                 : 
    1016             304 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
    1017               2 :                 return;
    1018                 :         }
    1019             302 :         convert_to_long_ex(arg);
    1020             302 :         result = _php_math_longtobase(*arg, 8);
    1021             302 :         RETURN_STRING(result, 0);
    1022                 : }
    1023                 : /* }}} */
    1024                 : 
    1025                 : /* {{{ proto string dechex(int decimal_number)
    1026                 :    Returns a string containing a hexadecimal representation of the given number */
    1027                 : PHP_FUNCTION(dechex)
    1028          131207 : {
    1029                 :         zval **arg;
    1030                 :         char *result;
    1031                 : 
    1032          131207 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
    1033               2 :                 return;
    1034                 :         }
    1035          131205 :         convert_to_long_ex(arg);
    1036          131205 :         result = _php_math_longtobase(*arg, 16);
    1037          131205 :         RETURN_STRING(result, 0);
    1038                 : }
    1039                 : /* }}} */
    1040                 : 
    1041                 : /* {{{ proto string base_convert(string number, int frombase, int tobase)
    1042                 :    Converts a number in a string from any base <= 36 to any base <= 36 */
    1043                 : PHP_FUNCTION(base_convert)
    1044             329 : {
    1045                 :         zval **number, temp;
    1046                 :         long frombase, tobase;
    1047                 :         char *result;
    1048                 : 
    1049             329 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zll", &number, &frombase, &tobase) == FAILURE) {
    1050              15 :                 return;
    1051                 :         }
    1052             314 :         convert_to_string_ex(number);
    1053                 :         
    1054             313 :         if (frombase < 2 || frombase > 36) {
    1055              18 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid `from base' (%ld)", frombase);
    1056              18 :                 RETURN_FALSE;
    1057                 :         }
    1058             295 :         if (tobase < 2 || tobase > 36) {
    1059              18 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid `to base' (%ld)", tobase);
    1060              18 :                 RETURN_FALSE;
    1061                 :         }
    1062                 : 
    1063             277 :         if(_php_math_basetozval(*number, frombase, &temp) == FAILURE) {
    1064               0 :                 RETURN_FALSE;
    1065                 :         }
    1066             277 :         result = _php_math_zvaltobase(&temp, tobase TSRMLS_CC);
    1067             277 :         RETVAL_STRING(result, 0);
    1068                 : } 
    1069                 : /* }}} */
    1070                 : 
    1071                 : /* {{{ _php_math_number_format 
    1072                 : */
    1073                 : PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char thousand_sep)
    1074            1316 : {
    1075            1316 :         char *tmpbuf = NULL, *resbuf;
    1076                 :         char *s, *t;  /* source, target */
    1077                 :         char *dp;
    1078                 :         int integral;
    1079            1316 :         int tmplen, reslen=0;
    1080            1316 :         int count=0;
    1081            1316 :         int is_negative=0;
    1082                 : 
    1083            1316 :         if (d < 0) {
    1084             352 :                 is_negative = 1;
    1085             352 :                 d = -d;
    1086                 :         }
    1087                 : 
    1088            1316 :         dec = MAX(0, dec);
    1089            1316 :         d = _php_math_round(d, dec, PHP_ROUND_HALF_UP);
    1090                 : 
    1091            1316 :         tmplen = spprintf(&tmpbuf, 0, "%.*F", dec, d);
    1092                 : 
    1093            1316 :         if (tmpbuf == NULL || !isdigit((int)tmpbuf[0])) {
    1094               2 :                 return tmpbuf;
    1095                 :         }
    1096                 : 
    1097                 :         /* find decimal point, if expected */
    1098            1314 :         if (dec) {
    1099              87 :                 dp = strpbrk(tmpbuf, ".,");
    1100                 :         } else {
    1101            1227 :                 dp = NULL;
    1102                 :         }
    1103                 : 
    1104                 :         /* calculate the length of the return buffer */
    1105            1314 :         if (dp) {
    1106              87 :                 integral = dp - tmpbuf;
    1107                 :         } else {
    1108                 :                 /* no decimal point was found */
    1109            1227 :                 integral = tmplen;
    1110                 :         }
    1111                 : 
    1112                 :         /* allow for thousand separators */
    1113            1314 :         if (thousand_sep) {
    1114            1312 :                 integral += (integral-1) / 3;
    1115                 :         }
    1116                 :         
    1117            1314 :         reslen = integral;
    1118                 :         
    1119            1314 :         if (dec) {
    1120              87 :                 reslen += dec;
    1121                 : 
    1122              87 :                 if (dec_point) {
    1123              84 :                         reslen++;
    1124                 :                 }
    1125                 :         }
    1126                 : 
    1127                 :         /* add a byte for minus sign */
    1128            1314 :         if (is_negative) {
    1129             352 :                 reslen++;
    1130                 :         }
    1131            1314 :         resbuf = (char *) emalloc(reslen+1); /* +1 for NUL terminator */
    1132                 : 
    1133            1314 :         s = tmpbuf+tmplen-1;
    1134            1314 :         t = resbuf+reslen;
    1135            1314 :         *t-- = '\0';
    1136                 : 
    1137                 :         /* copy the decimal places.
    1138                 :          * Take care, as the sprintf implementation may return less places than
    1139                 :          * we requested due to internal buffer limitations */
    1140            1314 :         if (dec) {
    1141              87 :                 int declen = dp ? s - dp : 0;
    1142              87 :                 int topad = dec > declen ? dec - declen : 0;
    1143                 : 
    1144                 :                 /* pad with '0's */
    1145            2624 :                 while (topad--) {
    1146            2450 :                         *t-- = '0';
    1147                 :                 }
    1148                 :                 
    1149              87 :                 if (dp) {
    1150              87 :                         s -= declen + 1; /* +1 to skip the point */
    1151              87 :                         t -= declen;
    1152                 : 
    1153                 :                         /* now copy the chars after the point */
    1154              87 :                         memcpy(t + 1, dp + 1, declen);
    1155                 :                 }
    1156                 : 
    1157                 :                 /* add decimal point */
    1158              87 :                 if (dec_point) {
    1159              84 :                         *t-- = dec_point;
    1160                 :                 }
    1161                 :         }
    1162                 : 
    1163                 :         /* copy the numbers before the decimal point, adding thousand
    1164                 :          * separator every three digits */
    1165            8016 :         while(s >= tmpbuf) {
    1166            5388 :                 *t-- = *s--;
    1167            5388 :                 if (thousand_sep && (++count%3)==0 && s>=tmpbuf) {
    1168             962 :                         *t-- = thousand_sep;
    1169                 :                 }
    1170                 :         }
    1171                 : 
    1172                 :         /* and a minus sign, if needed */
    1173            1314 :         if (is_negative) {
    1174             352 :                 *t-- = '-';
    1175                 :         }
    1176                 : 
    1177            1314 :         efree(tmpbuf);
    1178                 :         
    1179            1314 :         return resbuf;
    1180                 : }
    1181                 : /* }}} */
    1182                 : 
    1183                 : /* {{{ proto string number_format(float number [, int num_decimal_places [, string dec_seperator, string thousands_seperator]])
    1184                 :    Formats a number with grouped thousands */
    1185                 : PHP_FUNCTION(number_format)
    1186            1319 : {
    1187                 :         double num;
    1188            1319 :         long dec = 0;
    1189            1319 :         char *thousand_sep = NULL, *dec_point = NULL;
    1190            1319 :         char thousand_sep_chr = ',', dec_point_chr = '.';
    1191            1319 :         int thousand_sep_len = 0, dec_point_len = 0;
    1192                 :         
    1193            1319 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|ls!s!", &num, &dec, &dec_point, &dec_point_len, &thousand_sep, &thousand_sep_len) == FAILURE) {
    1194               2 :                 return;
    1195                 :         }
    1196                 : 
    1197            1317 :         switch(ZEND_NUM_ARGS()) {
    1198                 :         case 1:
    1199              24 :                 RETURN_STRING(_php_math_number_format(num, 0, dec_point_chr, thousand_sep_chr), 0);
    1200                 :                 break;
    1201                 :         case 2:
    1202              35 :                 RETURN_STRING(_php_math_number_format(num, dec, dec_point_chr, thousand_sep_chr), 0);
    1203                 :                 break;
    1204                 :         case 4:
    1205            1257 :                 if (dec_point != NULL) {
    1206            1256 :                         if (dec_point_len) {
    1207            1249 :                                 dec_point_chr = dec_point[0];
    1208                 :                         } else {
    1209               7 :                                 dec_point_chr = 0;
    1210                 :                         }
    1211                 :                 }
    1212            1257 :                 if (thousand_sep != NULL) {
    1213            1257 :                         if (thousand_sep_len) {
    1214            1255 :                                 thousand_sep_chr = thousand_sep[0];
    1215                 :                         } else {
    1216               2 :                                 thousand_sep_chr = 0;   
    1217                 :                         }
    1218                 :                 }
    1219            1257 :                 RETURN_STRING(_php_math_number_format(num, dec, dec_point_chr, thousand_sep_chr), 0);
    1220                 :                 break;
    1221                 :         default:
    1222               1 :                 WRONG_PARAM_COUNT;
    1223                 :                 break;
    1224                 :         }
    1225                 : }
    1226                 : /* }}} */
    1227                 : 
    1228                 : /* {{{ proto float fmod(float x, float y)
    1229                 :    Returns the remainder of dividing x by y as a float */
    1230                 : PHP_FUNCTION(fmod)
    1231             199 : {
    1232                 :         double num1, num2;
    1233                 : 
    1234             199 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd",  &num1, &num2) == FAILURE) {
    1235              19 :                 return;
    1236                 :         }
    1237             180 :         RETURN_DOUBLE(fmod(num1, num2));
    1238                 : }
    1239                 : /* }}} */
    1240                 : 
    1241                 : 
    1242                 : 
    1243                 : /*
    1244                 :  * Local variables:
    1245                 :  * tab-width: 4
    1246                 :  * c-basic-offset: 4
    1247                 :  * End:
    1248                 :  * vim600: fdm=marker
    1249                 :  * vim: noet sw=4 ts=4
    1250                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Sat, 21 Nov 2009 12:27:11 +0000 (3 days ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.