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

Generated by: LCOV version 1.10

Generated at Tue, 14 Apr 2015 11:48:52 +0000 (13 days ago)

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