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: 447 489 91.4 %
Date: 2014-09-27 Functions: 56 57 98.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sat, 27 Sep 2014 16:43:18 +0000 (2 days ago)

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