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: 455 497 91.5 %
Date: 2016-09-18 Functions: 55 56 98.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 18 Sep 2016 08:20:16 +0000 (8 days ago)

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