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

Generated by: LCOV version 1.10

Generated at Wed, 27 Apr 2016 15:51:50 +0000 (46 hours ago)

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