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

Generated by: LCOV version 1.10

Generated at Thu, 21 May 2015 19:59:04 +0000 (3 days ago)

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