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

LCOV - code coverage report
Current view: top level - ext/standard - math.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 423 461 91.8 %
Date: 2014-04-18 Functions: 54 55 98.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Fri, 18 Apr 2014 07:01:36 +0000 (5 days ago)

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