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

Generated by: LCOV version 1.10

Generated at Wed, 31 Aug 2016 04:11:15 +0000 (25 hours ago)

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