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-23 Instrumented lines: 438
Code covered: 92.0 % Executed lines: 403
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 6                                                        |
       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 277403 2009-03-18 10:49:36Z 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            1501 :         if (value < 1e-8 || value > 1e23) {
      39              32 :                 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            1437 :                 result = 16;
      48            1437 :                 if (value < values[result]) {
      49            1388 :                         result -= 8;
      50                 :                 } else {
      51              49 :                         result += 8;
      52                 :                 }
      53            1437 :                 if (value < values[result]) {
      54              64 :                         result -= 4;
      55                 :                 } else {
      56            1373 :                         result += 4;
      57                 :                 }
      58            1437 :                 if (value < values[result]) {
      59            1204 :                         result -= 2;
      60                 :                 } else {
      61             233 :                         result += 2;
      62                 :                 }
      63            1437 :                 if (value < values[result]) {
      64             362 :                         result -= 1;
      65                 :                 } else {
      66            1075 :                         result += 1;
      67                 :                 }
      68            1437 :                 if (value < values[result]) {
      69             767 :                         result -= 1;
      70                 :                 }
      71            1437 :                 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            4325 : 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            4325 :         if (power < 0 || power > 22) {
      87              20 :                 return pow(10.0, (double)power);
      88                 :         }
      89            4305 :         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            2879 : static inline double php_round_helper(double value, int mode) {
      96                 :         double tmp_value;
      97                 : 
      98            2879 :         if (value >= 0.0) {
      99            2807 :                 tmp_value = floor(value + 0.5);
     100            2807 :                 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            2879 :         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            2897 :         if (precision_places > places && precision_places - places < 15) {
     138            1428 :                 f2 = php_intpow10(abs(precision_places));
     139            1428 :                 if (precision_places >= 0) {
     140            1422 :                         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            1428 :                 tmp_value = php_round_helper(tmp_value, mode);
     147                 :                 /* now correctly move the decimal point */
     148            1428 :                 f2 = php_intpow10(abs(places - precision_places));
     149                 :                 /* because places < precision_places */
     150            1428 :                 tmp_value = tmp_value / f2;
     151                 :         } else {
     152                 :                 /* adjust the value */
     153              41 :                 if (places >= 0) {
     154              39 :                         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              41 :                 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) U
     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                 : 
     267              67 :         convert_scalar_to_number(value TSRMLS_CC);
     268                 :         
     269              67 :         if (Z_TYPE_P(value) == IS_DOUBLE) {
     270              38 :                 RETURN_DOUBLE(fabs(Z_DVAL_P(value)));
     271              29 :         } else if (Z_TYPE_P(value) == IS_LONG) {
     272              28 :                 if (Z_LVAL_P(value) == LONG_MIN) {
     273               1 :                         RETURN_DOUBLE(-(double)LONG_MIN);
     274                 :                 } else {
     275              27 :                         RETURN_LONG(Z_LVAL_P(value) < 0 ? -Z_LVAL_P(value) : Z_LVAL_P(value));
     276                 :                 }
     277                 :         }
     278               1 :         RETURN_FALSE;
     279                 : }
     280                 : /* }}} */ 
     281                 : 
     282                 : /* {{{ proto float ceil(float number) U
     283                 :    Returns the next highest integer value of the number */
     284                 : PHP_FUNCTION(ceil) 
     285              56 : {
     286                 :         zval *value;
     287                 :         
     288              56 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &value) == FAILURE) {
     289               2 :                 return;
     290                 :         }
     291                 : 
     292              54 :         convert_scalar_to_number(value TSRMLS_CC);
     293                 : 
     294              54 :         if (Z_TYPE_P(value) == IS_DOUBLE) {
     295              23 :                 RETURN_DOUBLE(ceil(Z_DVAL_P(value)));
     296              31 :         } else if (Z_TYPE_P(value) == IS_LONG) {
     297              30 :                 RETURN_DOUBLE((double)Z_LVAL_P(value));
     298                 :         }
     299                 : 
     300               1 :         RETURN_FALSE;
     301                 : }
     302                 : /* }}} */
     303                 : 
     304                 : /* {{{ proto float floor(float number) U
     305                 :    Returns the next lowest integer value from the number */
     306                 : PHP_FUNCTION(floor)
     307             420 : {
     308                 :         zval *value;
     309                 :         
     310             420 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &value) == FAILURE) {
     311               2 :                 return;
     312                 :         }
     313                 : 
     314             418 :         convert_scalar_to_number(value TSRMLS_CC);
     315                 : 
     316             418 :         if (Z_TYPE_P(value) == IS_DOUBLE) {
     317             384 :                 RETURN_DOUBLE(floor(Z_DVAL_P(value)));
     318              34 :         } else if (Z_TYPE_P(value) == IS_LONG) {
     319              33 :                 RETURN_DOUBLE((double)Z_LVAL_P(value));
     320                 :         }
     321                 : 
     322               1 :         RETURN_FALSE;
     323                 : }
     324                 : /* }}} */
     325                 : 
     326                 : /* {{{ proto float round(float number [, int precision [, int mode]]) U
     327                 :    Returns the number rounded to specified precision */
     328                 : PHP_FUNCTION(round)
     329            1436 : {
     330                 :         zval *value;
     331            1436 :         long places = 0;
     332            1436 :         long mode = PHP_ROUND_HALF_UP;
     333                 :         double return_val;
     334                 :         
     335            1436 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/|ll", &value, &places, &mode) == FAILURE) {
     336               9 :                 return;
     337                 :         }
     338                 : 
     339            1427 :         convert_scalar_to_number(value TSRMLS_CC);
     340                 : 
     341            1427 :         switch (Z_TYPE_P(value)) {
     342                 :                 case IS_LONG:
     343                 :                         /* Simple case - long that doesn't need to be rounded. */
     344            1273 :                         if (places >= 0) {
     345            1273 :                                 RETURN_DOUBLE((double) Z_LVAL_P(value));
     346                 :                         }
     347                 :                         /* break omitted intentionally */
     348                 : 
     349                 :                 case IS_DOUBLE:
     350             153 :                         return_val = (Z_TYPE_P(value) == IS_LONG) ?
     351                 :                                                         (double)Z_LVAL_P(value) : Z_DVAL_P(value);
     352                 : 
     353             153 :                         return_val = _php_math_round(return_val, places, mode);
     354                 : 
     355             153 :                         RETURN_DOUBLE(return_val);
     356                 :                         break;
     357                 : 
     358                 :                 default:
     359               1 :                         RETURN_FALSE;
     360                 :                         break;
     361                 :         }
     362                 : }
     363                 : /* }}} */
     364                 : 
     365                 : /* {{{ proto float sin(float number) U
     366                 :    Returns the sine of the number in radians */
     367                 : PHP_FUNCTION(sin)
     368              30 : {
     369                 :         double num;
     370                 : 
     371              30 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     372               3 :                 return;
     373                 :         }
     374                 : 
     375              27 :         RETURN_DOUBLE(sin(num));
     376                 : }
     377                 : /* }}} */
     378                 : 
     379                 : /* {{{ proto float cos(float number) U
     380                 :    Returns the cosine of the number in radians */
     381                 : PHP_FUNCTION(cos)
     382              32 : {
     383                 :         double num;
     384                 : 
     385              32 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     386               3 :                 return;
     387                 :         }
     388                 : 
     389              29 :         RETURN_DOUBLE(cos(num));
     390                 : }
     391                 : /* }}} */
     392                 : 
     393                 : /* {{{ proto float tan(float number) U
     394                 :    Returns the tangent of the number in radians */
     395                 : PHP_FUNCTION(tan)
     396              22 : {
     397                 :         double num;
     398                 : 
     399              22 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     400               3 :                 return;
     401                 :         }
     402                 : 
     403              19 :         RETURN_DOUBLE(tan(num));
     404                 : }
     405                 : /* }}} */
     406                 : 
     407                 : /* {{{ proto float asin(float number) U
     408                 :    Returns the arc sine of the number in radians */
     409                 : PHP_FUNCTION(asin)
     410              21 : {
     411                 :         double num;
     412                 : 
     413              21 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     414               3 :                 return;
     415                 :         }
     416                 : 
     417              18 :         RETURN_DOUBLE(asin(num));
     418                 : }
     419                 : /* }}} */
     420                 : 
     421                 : /* {{{ proto float acos(float number) U
     422                 :    Return the arc cosine of the number in radians */
     423                 : PHP_FUNCTION(acos)
     424              26 : {
     425                 :         double num;
     426                 : 
     427              26 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     428               3 :                 return;
     429                 :         }
     430                 : 
     431              23 :         RETURN_DOUBLE(acos(num));
     432                 : }
     433                 : /* }}} */
     434                 : 
     435                 : /* {{{ proto float atan(float number) U
     436                 :    Returns the arc tangent of the number in radians */
     437                 : PHP_FUNCTION(atan)
     438              19 : {
     439                 :         double num;
     440                 : 
     441              19 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     442               3 :                 return;
     443                 :         }
     444                 : 
     445              16 :         RETURN_DOUBLE(atan(num));
     446                 : }
     447                 : /* }}} */
     448                 : 
     449                 : /* {{{ proto float atan2(float y, float x) U
     450                 :    Returns the arc tangent of y/x, with the resulting quadrant determined by the signs of y and x */
     451                 : PHP_FUNCTION(atan2)
     452             199 : {
     453                 :         double y, x;
     454                 : 
     455             199 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &y, &x) == FAILURE) {
     456              19 :                 return;
     457                 :         }
     458             180 :         RETURN_DOUBLE(atan2(y, x));
     459                 : }
     460                 : /* }}} */
     461                 : 
     462                 : /* {{{ proto float sinh(float number) U
     463                 :    Returns the hyperbolic sine of the number, defined as (exp(number) - exp(-number))/2 */
     464                 : PHP_FUNCTION(sinh)
     465              25 : {
     466                 :         double num;
     467                 : 
     468              25 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     469               3 :                 return;
     470                 :         }
     471                 : 
     472              22 :         RETURN_DOUBLE(sinh(num));
     473                 : }
     474                 : /* }}} */
     475                 : 
     476                 : /* {{{ proto float cosh(float number) U
     477                 :    Returns the hyperbolic cosine of the number, defined as (exp(number) + exp(-number))/2 */
     478                 : PHP_FUNCTION(cosh)
     479              25 : {
     480                 :         double num;
     481                 : 
     482              25 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     483               3 :                 return;
     484                 :         }
     485                 : 
     486              22 :         RETURN_DOUBLE(cosh(num));
     487                 : }
     488                 : /* }}} */
     489                 : 
     490                 : /* {{{ proto float tanh(float number) U
     491                 :    Returns the hyperbolic tangent of the number, defined as sinh(number)/cosh(number) */
     492                 : PHP_FUNCTION(tanh)
     493              25 : {
     494                 :         double num;
     495                 : 
     496              25 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     497               3 :                 return;
     498                 :         }
     499                 : 
     500              22 :         RETURN_DOUBLE(tanh(num));
     501                 : }
     502                 : /* }}} */
     503                 : 
     504                 : /* {{{ proto float asinh(float number) U
     505                 :    Returns the inverse hyperbolic sine of the number, i.e. the value whose hyperbolic sine is number */
     506                 : PHP_FUNCTION(asinh)
     507              21 : {
     508                 :         double num;
     509                 : 
     510              21 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     511               3 :                 return;
     512                 :         }
     513                 : 
     514              18 :         RETURN_DOUBLE(php_asinh(num));
     515                 : }
     516                 : /* }}} */
     517                 : 
     518                 : /* {{{ proto float acosh(float number) U
     519                 :    Returns the inverse hyperbolic cosine of the number, i.e. the value whose hyperbolic cosine is number */
     520                 : PHP_FUNCTION(acosh)
     521              21 : {
     522                 :         double num;
     523                 : 
     524              21 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     525               3 :                 return;
     526                 :         }
     527                 : 
     528              18 :         RETURN_DOUBLE(php_acosh(num));
     529                 : }
     530                 : /* }}} */
     531                 : 
     532                 : /* {{{ proto float atanh(float number) U
     533                 :    Returns the inverse hyperbolic tangent of the number, i.e. the value whose hyperbolic tangent is number */
     534                 : PHP_FUNCTION(atanh)
     535              21 : {
     536                 :         double num;
     537                 : 
     538              21 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     539               3 :                 return;
     540                 :         }
     541                 : 
     542              18 :         RETURN_DOUBLE(php_atanh(num));
     543                 : }
     544                 : /* }}} */
     545                 : 
     546                 : /* {{{ proto float pi(void) U
     547                 :    Returns an approximation of pi */
     548                 : PHP_FUNCTION(pi)
     549               1 : {
     550               1 :         RETURN_DOUBLE(M_PI);
     551                 : }
     552                 : /* }}} */
     553                 : 
     554                 : /* {{{ proto bool is_finite(float val) U
     555                 :    Returns whether argument is finite */
     556                 : PHP_FUNCTION(is_finite)
     557              43 : {
     558                 :         double dval;
     559                 : 
     560              43 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) {
     561              10 :                 return;
     562                 :         }
     563              33 :         RETURN_BOOL(zend_finite(dval));
     564                 : }
     565                 : /* }}} */
     566                 : 
     567                 : /* {{{ proto bool is_infinite(float val) U
     568                 :    Returns whether argument is infinite */
     569                 : PHP_FUNCTION(is_infinite)
     570              51 : {
     571                 :         double dval;
     572                 : 
     573              51 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) {
     574              10 :                 return;
     575                 :         }
     576                 : 
     577              41 :         RETURN_BOOL(zend_isinf(dval));
     578                 : }
     579                 : /* }}} */
     580                 : 
     581                 : /* {{{ proto bool is_nan(float val) U
     582                 :    Returns whether argument is not a number */
     583                 : PHP_FUNCTION(is_nan)
     584              45 : {
     585                 :         double dval;
     586                 : 
     587              45 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) {
     588              10 :                 return;
     589                 :         }
     590                 : 
     591              35 :         RETURN_BOOL(zend_isnan(dval));
     592                 : }
     593                 : /* }}} */
     594                 : 
     595                 : /* {{{ proto number pow(number base, number exponent) U
     596                 :    Returns base raised to the power of exponent. Returns integer result when possible */
     597                 : PHP_FUNCTION(pow)
     598            1472 : {
     599                 :         zval *zbase, *zexp;
     600                 : 
     601            1472 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/z/", &zbase, &zexp) == FAILURE) {
     602               6 :                 return;
     603                 :         }
     604                 : 
     605                 :         /* make sure we're dealing with numbers */
     606            1466 :         convert_scalar_to_number(zbase TSRMLS_CC);
     607            1466 :         convert_scalar_to_number(zexp TSRMLS_CC);
     608                 : 
     609                 :         /* if both base and exponent were longs, we'll try to get a long out */
     610            1466 :         if (Z_TYPE_P(zbase) == IS_LONG && Z_TYPE_P(zexp) == IS_LONG && Z_LVAL_P(zexp) >= 0) {
     611             725 :                 long l1 = 1, l2 = Z_LVAL_P(zbase), i = Z_LVAL_P(zexp);
     612                 :                 
     613             725 :                 if (i == 0) {
     614              13 :                         RETURN_LONG(1);
     615             712 :                 } else if (l2 == 0) {
     616              14 :                         RETURN_LONG(0);
     617                 :                 }
     618                 : 
     619                 :                 /* calculate pow(long,long) in O(log exp) operations, bail if overflow */
     620            5118 :                 while (i >= 1) {
     621                 :                         int overflow;
     622            4420 :                         double dval = 0.0;
     623                 : 
     624            4420 :                         if (i % 2) {
     625            1385 :                                 --i;
     626            1385 :                                 ZEND_SIGNED_MULTIPLY_LONG(l1,l2,l1,dval,overflow);
     627            1385 :                                 if (overflow) RETURN_DOUBLE(dval * pow(l2,i));
     628                 :                         } else {
     629            3035 :                                 i /= 2;
     630            3035 :                                 ZEND_SIGNED_MULTIPLY_LONG(l2,l2,l2,dval,overflow);
     631            3035 :                                 if (overflow) RETURN_DOUBLE((double)l1 * pow(dval,i));
     632                 :                         }
     633            3892 :                         if (i == 0) {
     634             170 :                                 RETURN_LONG(l1);
     635                 :                         }
     636                 :                 }
     637                 :         }
     638             741 :         convert_to_double(zbase);
     639             741 :         convert_to_double(zexp);
     640                 :         
     641             741 :         RETURN_DOUBLE( pow(Z_DVAL_P(zbase),Z_DVAL_P(zexp)) );
     642                 : }
     643                 : /* }}} */
     644                 : 
     645                 : /* {{{ proto float exp(float number) U
     646                 :    Returns e raised to the power of the number */
     647                 : PHP_FUNCTION(exp)
     648             241 : {
     649                 :         double num;
     650                 : 
     651             241 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     652              10 :                 return;
     653                 :         }
     654                 : 
     655             231 :         RETURN_DOUBLE(exp(num));
     656                 : }
     657                 : /* }}} */
     658                 : 
     659                 : /* {{{ proto float expm1(float number) U
     660                 :    Returns exp(number) - 1, computed in a way that accurate even when the value of number is close to zero */
     661                 : /*
     662                 :    WARNING: this function is expermental: it could change its name or 
     663                 :    disappear in the next version of PHP!
     664                 : */
     665                 : PHP_FUNCTION(expm1)
     666              42 : {
     667                 :         double num;
     668                 : 
     669              42 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     670              12 :                 return;
     671                 :         }
     672                 : 
     673              30 :         RETURN_DOUBLE(php_expm1(num));
     674                 : }
     675                 : /* }}} */
     676                 : 
     677                 : /* {{{ proto float log1p(float number) U
     678                 :    Returns log(1 + number), computed in a way that accurate even when the value of number is close to zero */ 
     679                 : /*
     680                 :    WARNING: this function is expermental: it could change its name or 
     681                 :    disappear in the next version of PHP!
     682                 : */
     683                 : PHP_FUNCTION(log1p)
     684              41 : {
     685                 :         double num;
     686                 : 
     687              41 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     688              10 :                 return;
     689                 :         }
     690                 : 
     691              31 :         RETURN_DOUBLE(php_log1p(num));
     692                 : }
     693                 : /* }}} */
     694                 : 
     695                 : /* {{{ proto float log(float number, [float base]) U
     696                 :    Returns the natural logarithm of the number, or the base log if base is specified */
     697                 : PHP_FUNCTION(log)
     698             731 : {
     699             731 :         double num, base=0, result;
     700                 : 
     701             731 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|d", &num, &base) == FAILURE) {
     702              18 :                 return;
     703                 :         }
     704                 : 
     705             713 :         if (base < 0) {
     706               3 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "base must be greater than 0");
     707               3 :                 RETURN_FALSE;
     708                 :         }
     709                 : 
     710             710 :         result = log(num);
     711                 : 
     712             710 :         if (base > 0) {
     713             489 :                 result /= log(base);
     714                 :         } /* else base is default: e, log(e) == 1 */
     715                 : 
     716             710 :         RETURN_DOUBLE(result);
     717                 : }
     718                 : /* }}} */
     719                 : 
     720                 : /* {{{ proto float log10(float number) U
     721                 :    Returns the base-10 logarithm of the number */
     722                 : PHP_FUNCTION(log10)
     723              24 : {
     724                 :         double num;
     725                 : 
     726              24 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     727               3 :                 return;
     728                 :         }
     729                 : 
     730              21 :         RETURN_DOUBLE(log10(num));
     731                 : }
     732                 : /* }}} */
     733                 : 
     734                 : /* {{{ proto float sqrt(float number) U
     735                 :    Returns the square root of the number */
     736                 : PHP_FUNCTION(sqrt)
     737              22 : {
     738                 :         double num;
     739                 : 
     740              22 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     741               3 :                 return;
     742                 :         }
     743                 : 
     744              19 :         RETURN_DOUBLE(sqrt(num));
     745                 : }
     746                 : /* }}} */
     747                 : 
     748                 : /* {{{ proto float hypot(float num1, float num2) U
     749                 :    Returns sqrt(num1*num1 + num2*num2) */ 
     750                 : PHP_FUNCTION(hypot)
     751             224 : {
     752                 :         /* A^2 + B^2 == C^2 */
     753                 :         double A, B;
     754                 : 
     755             224 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &A, &B) == FAILURE) {
     756              19 :                 return;
     757                 :         }
     758                 : 
     759                 : #if HAVE_HYPOT
     760             205 :         RETURN_DOUBLE(hypot(A, B));
     761                 : #elif defined(_MSC_VER)
     762                 :         RETURN_DOUBLE(_hypot(A, B));
     763                 : #else
     764                 :         /* Fallback on manual approach */
     765                 :         RETURN_DOUBLE(sqrt( (A * A) + (B * B) ));
     766                 : #endif
     767                 : }
     768                 : /* }}} */
     769                 : 
     770                 : /* {{{ proto float deg2rad(float number) U
     771                 :    Converts the number in degrees to the radian equivalent */
     772                 : PHP_FUNCTION(deg2rad)
     773              24 : {
     774                 :         double num;
     775                 : 
     776              24 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     777               3 :                 return;
     778                 :         }
     779                 : 
     780              21 :         RETVAL_DOUBLE((num / 180.0) * M_PI);
     781                 : }
     782                 : /* }}} */
     783                 : 
     784                 : /* {{{ proto float rad2deg(float number) U
     785                 :    Converts the radian number to the equivalent number in degrees */
     786                 : PHP_FUNCTION(rad2deg)
     787              21 : {
     788                 :         double num;
     789                 : 
     790              21 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
     791               3 :                 return;
     792                 :         }
     793                 : 
     794              18 :         RETVAL_DOUBLE((num / M_PI) * 180);
     795                 : }
     796                 : /* }}} */
     797                 : 
     798                 : /* {{{ _php_math_basetolong */
     799                 : /*
     800                 :  * Convert a string representation of a base(2-36) number to a long.
     801                 :  */
     802                 : PHPAPI long _php_math_basetolong(zval *arg, int base)
     803               0 : {
     804               0 :         long num = 0, digit, onum;
     805                 :         int i;
     806                 :         char c, *s;
     807                 : 
     808               0 :         if (Z_TYPE_P(arg) != IS_STRING || base < 2 || base > 36) {
     809               0 :                 return 0;
     810                 :         }
     811                 : 
     812               0 :         s = Z_STRVAL_P(arg);
     813                 : 
     814               0 :         for (i = Z_STRLEN_P(arg); i > 0; i--) {
     815               0 :                 c = *s++;
     816                 :                 
     817               0 :                 digit = (c >= '0' && c <= '9') ? c - '0'
     818                 :                         : (c >= 'A' && c <= 'Z') ? c - 'A' + 10
     819                 :                         : (c >= 'a' && c <= 'z') ? c - 'a' + 10
     820                 :                         : base;
     821                 :                 
     822               0 :                 if (digit >= base) {
     823               0 :                         continue;
     824                 :                 }
     825                 : 
     826               0 :                 onum = num;
     827               0 :                 num = num * base + digit;
     828               0 :                 if (num > onum)
     829               0 :                         continue;
     830                 : 
     831                 :                 {
     832                 :                         TSRMLS_FETCH();
     833                 : 
     834               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number '%s' is too big to fit in long", s);
     835               0 :                         return LONG_MAX;
     836                 :                 }
     837                 :         }
     838                 : 
     839               0 :         return num;
     840                 : }
     841                 : /* }}} */
     842                 : 
     843                 : /* {{{ _php_math_basetozval */
     844                 : /*
     845                 :  * Convert a string representation of a base(2-36) number to a zval.
     846                 :  */
     847                 : PHPAPI int _php_math_basetozval(zval *arg, int base, zval *ret)
     848             414 : {
     849             414 :         long num = 0;
     850             414 :         double fnum = 0;
     851                 :         int i;
     852             414 :         int mode = 0;
     853                 :         char c, *s;
     854                 :         long cutoff;
     855                 :         int cutlim;
     856                 : 
     857             414 :         if (Z_TYPE_P(arg) != IS_STRING || base < 2 || base > 36) {
     858               0 :                 return FAILURE;
     859                 :         }
     860                 : 
     861             414 :         s = Z_STRVAL_P(arg);
     862                 : 
     863             414 :         cutoff = LONG_MAX / base;
     864             414 :         cutlim = LONG_MAX % base;
     865                 :         
     866            1792 :         for (i = Z_STRLEN_P(arg); i > 0; i--) {
     867            1378 :                 c = *s++;
     868                 : 
     869                 :                 /* might not work for EBCDIC */
     870            2421 :                 if (c >= '0' && c <= '9') 
     871            1043 :                         c -= '0';
     872             467 :                 else if (c >= 'A' && c <= 'Z') 
     873             132 :                         c -= 'A' - 10;
     874             203 :                 else if (c >= 'a' && c <= 'z') 
     875             149 :                         c -= 'a' - 10;
     876                 :                 else
     877                 :                         continue;
     878                 : 
     879            1324 :                 if (c >= base)
     880             368 :                         continue;
     881                 :                 
     882             956 :                 switch (mode) {
     883                 :                 case 0: /* Integer */
     884             946 :                         if (num < cutoff || (num == cutoff && c <= cutlim)) {
     885             935 :                                 num = num * base + c;
     886             935 :                                 break;
     887                 :                         } else {
     888              11 :                                 fnum = num;
     889              11 :                                 mode = 1;
     890                 :                         }
     891                 :                         /* fall-through */
     892                 :                 case 1: /* Float */
     893              21 :                         fnum = fnum * base + c;
     894                 :                 }       
     895                 :         }
     896                 : 
     897             414 :         if (mode == 1) {
     898              11 :                 ZVAL_DOUBLE(ret, fnum);
     899                 :         } else {
     900             403 :                 ZVAL_LONG(ret, num);
     901                 :         }
     902             414 :         return SUCCESS;
     903                 : }
     904                 : /* }}} */
     905                 : 
     906                 : /* {{{ _php_math_longtobase */
     907                 : /*
     908                 :  * Convert a long to a string containing a base(2-36) representation of
     909                 :  * the number.
     910                 :  */
     911                 : PHPAPI char * _php_math_longtobase(zval *arg, int base)
     912          134351 : {
     913                 :         static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
     914                 :         char buf[(sizeof(unsigned long) << 3) + 1];
     915                 :         char *ptr, *end;
     916                 :         unsigned long value;
     917                 : 
     918          134351 :         if (Z_TYPE_P(arg) != IS_LONG || base < 2 || base > 36) {
     919               0 :                 return STR_EMPTY_ALLOC();
     920                 :         }
     921                 : 
     922          134351 :         value = Z_LVAL_P(arg);
     923                 : 
     924          134351 :         end = ptr = buf + sizeof(buf) - 1;
     925          134351 :         *ptr = '\0';
     926                 : 
     927                 :         do {
     928          547438 :                 *--ptr = digits[value % base];
     929          547438 :                 value /= base;
     930          547438 :         } while (ptr > buf && value);
     931                 : 
     932          134351 :         return estrndup(ptr, end - ptr);
     933                 : }
     934                 : /* }}} */
     935                 : 
     936                 : /* {{{ _php_math_zvaltobase */
     937                 : /*
     938                 :  * Convert a zval to a string containing a base(2-36) representation of
     939                 :  * the number.
     940                 :  */
     941                 : PHPAPI char * _php_math_zvaltobase(zval *arg, int base TSRMLS_DC)
     942             277 : {
     943                 :         static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
     944                 : 
     945             277 :         if ((Z_TYPE_P(arg) != IS_LONG && Z_TYPE_P(arg) != IS_DOUBLE) || base < 2 || base > 36) {
     946               0 :                 return STR_EMPTY_ALLOC();
     947                 :         }
     948                 : 
     949             277 :         if (Z_TYPE_P(arg) == IS_DOUBLE) {
     950               0 :                 double fvalue = floor(Z_DVAL_P(arg)); /* floor it just in case */
     951                 :                 char *ptr, *end;
     952                 :                 char buf[(sizeof(double) << 3) + 1];
     953                 : 
     954                 :                 /* Don't try to convert +/- infinity */
     955               0 :                 if (fvalue == HUGE_VAL || fvalue == -HUGE_VAL) {
     956               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number too large");
     957               0 :                         return STR_EMPTY_ALLOC();
     958                 :                 }
     959                 : 
     960               0 :                 end = ptr = buf + sizeof(buf) - 1;
     961               0 :                 *ptr = '\0';
     962                 : 
     963                 :                 do {
     964               0 :                         *--ptr = digits[(int) fmod(fvalue, base)];
     965               0 :                         fvalue /= base;
     966               0 :                 } while (ptr > buf && fabs(fvalue) >= 1);
     967                 : 
     968               0 :                 return estrndup(ptr, end - ptr);
     969                 :         }
     970                 :         
     971             277 :         return _php_math_longtobase(arg, base);
     972                 : }       
     973                 : /* }}} */
     974                 : 
     975                 : /* {{{ proto int bindec(string binary_number) U
     976                 :    Returns the decimal equivalent of the binary number */
     977                 : PHP_FUNCTION(bindec)
     978              46 : {
     979                 :         zval *arg;
     980                 : 
     981              46 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &arg) == FAILURE) {
     982               2 :                 return;
     983                 :         }
     984              44 :         convert_to_string(arg);
     985                 : 
     986              43 :         if(_php_math_basetozval(arg, 2, return_value) != SUCCESS) {
     987               0 :                 RETURN_FALSE;
     988                 :         }
     989                 : }
     990                 : /* }}} */
     991                 : 
     992                 : /* {{{ proto int hexdec(string hexadecimal_number) U
     993                 :    Returns the decimal equivalent of the hexadecimal number */
     994                 : PHP_FUNCTION(hexdec)
     995              54 : {
     996                 :         zval *arg;
     997                 : 
     998              54 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &arg) == FAILURE) {
     999               2 :                 return;
    1000                 :         }
    1001              52 :         convert_to_string(arg);
    1002                 : 
    1003              51 :         if(_php_math_basetozval(arg, 16, return_value) != SUCCESS) {
    1004               0 :                 RETURN_FALSE;
    1005                 :         }
    1006                 : }
    1007                 : /* }}} */
    1008                 : 
    1009                 : /* {{{ proto int octdec(string octal_number) U
    1010                 :    Returns the decimal equivalent of an octal string */
    1011                 : PHP_FUNCTION(octdec)
    1012              46 : {
    1013                 :         zval *arg;
    1014                 : 
    1015              46 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &arg) == FAILURE) {
    1016               2 :                 return;
    1017                 :         }
    1018              44 :         convert_to_string(arg);
    1019                 : 
    1020              43 :         if(_php_math_basetozval(arg, 8, return_value) != SUCCESS) {
    1021               0 :                 RETURN_FALSE;
    1022                 :         }
    1023                 : }
    1024                 : /* }}} */
    1025                 : 
    1026                 : /* {{{ proto string decbin(int decimal_number) U
    1027                 :    Returns a string containing a binary representation of the number */
    1028                 : PHP_FUNCTION(decbin)
    1029            2569 : {
    1030                 :         zval *arg;
    1031                 : 
    1032            2569 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &arg) == FAILURE) {
    1033               2 :                 return;
    1034                 :         }
    1035            2567 :         convert_to_long(arg);
    1036                 : 
    1037            2567 :         RETURN_RT_STRING(_php_math_longtobase(arg, 2), ZSTR_AUTOFREE);
    1038                 : }
    1039                 : /* }}} */
    1040                 : 
    1041                 : /* {{{ proto string decoct(int decimal_number) U
    1042                 :    Returns a string containing an octal representation of the given number */
    1043                 : PHP_FUNCTION(decoct)
    1044             304 : {
    1045                 :         zval *arg;
    1046                 : 
    1047             304 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &arg) == FAILURE) {
    1048               2 :                 return;
    1049                 :         }
    1050             302 :         convert_to_long(arg);
    1051                 : 
    1052             302 :         RETURN_RT_STRING(_php_math_longtobase(arg, 8), ZSTR_AUTOFREE);
    1053                 : }
    1054                 : /* }}} */
    1055                 : 
    1056                 : /* {{{ proto string dechex(int decimal_number) U
    1057                 :    Returns a string containing a hexadecimal representation of the given number */
    1058                 : PHP_FUNCTION(dechex)
    1059          131207 : {
    1060                 :         zval *arg;
    1061                 : 
    1062          131207 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &arg) == FAILURE) {
    1063               2 :                 return;
    1064                 :         }
    1065          131205 :         convert_to_long(arg);
    1066                 : 
    1067          131205 :         RETURN_RT_STRING(_php_math_longtobase(arg, 16), ZSTR_AUTOFREE);
    1068                 : }
    1069                 : /* }}} */
    1070                 : 
    1071                 : /* {{{ proto string base_convert(string number, int frombase, int tobase) U
    1072                 :    Converts a number in a string from any base <= 36 to any base <= 36 */
    1073                 : PHP_FUNCTION(base_convert)
    1074             329 : {
    1075                 :         zval *number, temp;
    1076                 :         long frombase, tobase;
    1077                 : 
    1078             329 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/ll", &number, &frombase, &tobase) == FAILURE) {
    1079              15 :                 return;
    1080                 :         }
    1081             314 :         convert_to_string(number);
    1082                 : 
    1083             313 :         if (frombase < 2 || frombase > 36) {
    1084              18 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid `from base' (%ld)", frombase);
    1085              18 :                 RETURN_FALSE;
    1086                 :         }
    1087             295 :         if (tobase < 2 || tobase > 36) {
    1088              18 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid `to base' (%ld)", tobase);
    1089              18 :                 RETURN_FALSE;
    1090                 :         }
    1091                 : 
    1092             277 :         if(_php_math_basetozval(number, frombase, &temp) != SUCCESS) {
    1093               0 :                 RETURN_FALSE;
    1094                 :         }
    1095             277 :         RETURN_RT_STRING(_php_math_zvaltobase(&temp, tobase TSRMLS_CC), ZSTR_AUTOFREE);
    1096                 : } 
    1097                 : /* }}} */
    1098                 : 
    1099                 : /* {{{ _php_math_number_format 
    1100                 : */
    1101                 : PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char thousand_sep)
    1102            1316 : {
    1103            1316 :         char *tmpbuf = NULL, *resbuf;
    1104                 :         char *s, *t;  /* source, target */
    1105                 :         char *dp;
    1106                 :         int integral;
    1107            1316 :         int tmplen, reslen=0;
    1108            1316 :         int count=0;
    1109            1316 :         int is_negative=0;
    1110                 : 
    1111            1316 :         if (d < 0) {
    1112             377 :                 is_negative = 1;
    1113             377 :                 d = -d;
    1114                 :         }
    1115                 : 
    1116            1316 :         dec = MAX(0, dec);
    1117            1316 :         d = _php_math_round(d, dec, PHP_ROUND_HALF_UP);
    1118                 : 
    1119            1316 :         tmplen = spprintf(&tmpbuf, 0, "%.*f", dec, d);
    1120                 : 
    1121            1316 :         if (tmpbuf == NULL || !isdigit((int)tmpbuf[0])) {
    1122               2 :                 return tmpbuf;
    1123                 :         }
    1124                 : 
    1125                 :         /* find decimal point, if expected */
    1126            1314 :         if (dec) {
    1127              87 :                 dp = strpbrk(tmpbuf, ".,");
    1128                 :         } else {
    1129            1227 :                 dp = NULL;
    1130                 :         }
    1131                 : 
    1132                 :         /* calculate the length of the return buffer */
    1133            1314 :         if (dp) {
    1134              87 :                 integral = dp - tmpbuf;
    1135                 :         } else {
    1136                 :                 /* no decimal point was found */
    1137            1227 :                 integral = tmplen;
    1138                 :         }
    1139                 : 
    1140                 :         /* allow for thousand separators */
    1141            1314 :         if (thousand_sep) {
    1142            1312 :                 integral += (integral-1) / 3;
    1143                 :         }
    1144                 :         
    1145            1314 :         reslen = integral;
    1146                 :         
    1147            1314 :         if (dec) {
    1148              87 :                 reslen += dec;
    1149                 : 
    1150              87 :                 if (dec_point) {
    1151              84 :                         reslen++;
    1152                 :                 }
    1153                 :         }
    1154                 : 
    1155                 :         /* add a byte for minus sign */
    1156            1314 :         if (is_negative) {
    1157             377 :                 reslen++;
    1158                 :         }
    1159            1314 :         resbuf = (char *) emalloc(reslen+1); /* +1 for NUL terminator */
    1160                 : 
    1161            1314 :         s = tmpbuf+tmplen-1;
    1162            1314 :         t = resbuf+reslen;
    1163            1314 :         *t-- = '\0';
    1164                 : 
    1165                 :         /* copy the decimal places.
    1166                 :          * Take care, as the sprintf implementation may return less places than
    1167                 :          * we requested due to internal buffer limitations */
    1168            1314 :         if (dec) {
    1169              87 :                 int declen = dp ? s - dp : 0;
    1170              87 :                 int topad = dec > declen ? dec - declen : 0;
    1171                 : 
    1172                 :                 /* pad with '0's */
    1173            2624 :                 while (topad--) {
    1174            2450 :                         *t-- = '0';
    1175                 :                 }
    1176                 :                 
    1177              87 :                 if (dp) {
    1178              87 :                         s -= declen + 1; /* +1 to skip the point */
    1179              87 :                         t -= declen;
    1180                 : 
    1181                 :                         /* now copy the chars after the point */
    1182              87 :                         memcpy(t + 1, dp + 1, declen);
    1183                 :                 }
    1184                 : 
    1185                 :                 /* add decimal point */
    1186              87 :                 if (dec_point) {
    1187              84 :                         *t-- = dec_point;
    1188                 :                 }
    1189                 :         }
    1190                 : 
    1191                 :         /* copy the numbers before the decimal point, adding thousand
    1192                 :          * separator every three digits */
    1193            7973 :         while(s >= tmpbuf) {
    1194            5345 :                 *t-- = *s--;
    1195            5345 :                 if (thousand_sep && (++count%3)==0 && s>=tmpbuf) {
    1196             949 :                         *t-- = thousand_sep;
    1197                 :                 }
    1198                 :         }
    1199                 : 
    1200                 :         /* and a minus sign, if needed */
    1201            1314 :         if (is_negative) {
    1202             377 :                 *t-- = '-';
    1203                 :         }
    1204                 : 
    1205            1314 :         efree(tmpbuf);
    1206                 :         
    1207            1314 :         return resbuf;
    1208                 : }
    1209                 : /* }}} */
    1210                 : 
    1211                 : /* {{{ proto string number_format(float number [, int num_decimal_places [, string dec_seperator, string thousands_seperator]]) U
    1212                 :    Formats a number with grouped thousands */
    1213                 : PHP_FUNCTION(number_format)
    1214            1318 : {
    1215            1318 :         zval *sep1 = NULL, *sep2 = NULL;
    1216                 :         double num;
    1217            1318 :         long dec = 0;
    1218            1318 :         char thousand_sep=',', dec_point='.';
    1219                 :         char *tmp;
    1220                 :         
    1221            1318 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|lzz", &num, &dec, &sep1, &sep2) == FAILURE) {
    1222               2 :                 return;
    1223                 :         }
    1224                 : 
    1225            1316 :         if (sep1 && Z_TYPE_P(sep1) != IS_NULL) {
    1226            1256 :                 convert_to_string_with_converter(sep1, UG(ascii_conv));
    1227            1256 :                 if (Z_STRLEN_P(sep1)) {
    1228            1249 :                         dec_point  = Z_STRVAL_P(sep1)[0];
    1229                 :                 } else {
    1230               7 :                         dec_point = 0;
    1231                 :                 }
    1232                 :         }
    1233                 : 
    1234            1316 :         if (sep2 && Z_TYPE_P(sep2) != IS_NULL) {
    1235            1257 :                 convert_to_string_with_converter(sep2, UG(ascii_conv));
    1236            1257 :                 if (Z_STRLEN_P(sep2)) {
    1237            1255 :                         thousand_sep = Z_STRVAL_P(sep2)[0];
    1238                 :                 } else {
    1239               2 :                         thousand_sep = 0;
    1240                 :                 }
    1241                 :         }
    1242                 : 
    1243            1316 :         tmp = _php_math_number_format(num, dec, dec_point, thousand_sep);
    1244            1316 :         RETVAL_ASCII_STRING(tmp, ZSTR_AUTOFREE);
    1245                 : }
    1246                 : /* }}} */
    1247                 : 
    1248                 : /* {{{ proto float fmod(float x, float y) U
    1249                 :    Returns the remainder of dividing x by y as a float */
    1250                 : PHP_FUNCTION(fmod)
    1251             199 : {
    1252                 :         double num1, num2;
    1253                 : 
    1254             199 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd",  &num1, &num2) == FAILURE) {
    1255              19 :                 return;
    1256                 :         }
    1257                 :         
    1258             180 :         RETURN_DOUBLE(fmod(num1, num2));
    1259                 : }
    1260                 : /* }}} */
    1261                 : 
    1262                 : /*
    1263                 :  * Local variables:
    1264                 :  * tab-width: 4
    1265                 :  * c-basic-offset: 4
    1266                 :  * End:
    1267                 :  * vim600: fdm=marker
    1268                 :  * vim: noet sw=4 ts=4
    1269                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:40 +0000 (33 hours ago)

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