📄 math.c
字号:
/* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Jim Winstead <jimw@php.net> | | Stig S鎡her Bakken <ssb@fast.no> | | Zeev Suraski <zeev@zend.com> | | PHP 4.0 patches by Thies C. Arntzen <thies@thieso.net> | +----------------------------------------------------------------------+*//* $Id: math.c,v 1.97.2.13.2.5 2007/01/01 09:46:48 sebastian Exp $ */#include "php.h"#include "php_math.h"#include "zend_multiply.h"#include <math.h>#include <float.h>#include <stdlib.h>#ifndef M_PI#define M_PI 3.14159265358979323846#endif#ifndef PHP_ROUND_FUZZ# ifndef PHP_WIN32# define PHP_ROUND_FUZZ 0.50000000001# else# define PHP_ROUND_FUZZ 0.5# endif#endif#define PHP_ROUND_WITH_FUZZ(val, places) { \ double tmp_val=val, f = pow(10.0, (double) places); \ tmp_val *= f; \ if (tmp_val >= 0.0) { \ tmp_val = floor(tmp_val + PHP_ROUND_FUZZ); \ } else { \ tmp_val = ceil(tmp_val - PHP_ROUND_FUZZ); \ } \ tmp_val /= f; \ val = !zend_isnan(tmp_val) ? tmp_val : val; \} \/* {{{ proto int abs(int number) Return the absolute value of the number */PHP_FUNCTION(abs){ zval **value; if (ZEND_NUM_ARGS()!=1||zend_get_parameters_ex(1, &value)==FAILURE) { WRONG_PARAM_COUNT; } convert_scalar_to_number_ex(value); if (Z_TYPE_PP(value) == IS_DOUBLE) { RETURN_DOUBLE(fabs(Z_DVAL_PP(value))); } else if (Z_TYPE_PP(value) == IS_LONG) { if (Z_LVAL_PP(value) == LONG_MIN) { RETURN_DOUBLE(-(double)LONG_MIN); } else { RETURN_LONG(Z_LVAL_PP(value) < 0 ? -Z_LVAL_PP(value) : Z_LVAL_PP(value)); } } RETURN_FALSE;}/* }}} *//* {{{ proto float ceil(float number) Returns the next highest integer value of the number */PHP_FUNCTION(ceil){ zval **value; if (ZEND_NUM_ARGS()!=1||zend_get_parameters_ex(1, &value)==FAILURE) { WRONG_PARAM_COUNT; } convert_scalar_to_number_ex(value); if (Z_TYPE_PP(value) == IS_DOUBLE) { RETURN_DOUBLE(ceil(Z_DVAL_PP(value))); } else if (Z_TYPE_PP(value) == IS_LONG) { convert_to_double_ex(value); RETURN_DOUBLE(Z_DVAL_PP(value)); } RETURN_FALSE;}/* }}} *//* {{{ proto float floor(float number) Returns the next lowest integer value from the number */PHP_FUNCTION(floor){ zval **value; if (ZEND_NUM_ARGS()!=1||zend_get_parameters_ex(1, &value)==FAILURE) { WRONG_PARAM_COUNT; } convert_scalar_to_number_ex(value); if (Z_TYPE_PP(value) == IS_DOUBLE) { RETURN_DOUBLE(floor(Z_DVAL_PP(value))); } else if (Z_TYPE_PP(value) == IS_LONG) { convert_to_double_ex(value); RETURN_DOUBLE(Z_DVAL_PP(value)); } RETURN_FALSE;}/* }}} *//* {{{ proto float round(float number [, int precision]) Returns the number rounded to specified precision */PHP_FUNCTION(round){ zval **value, **precision; int places = 0; double return_val; if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 2 || zend_get_parameters_ex(ZEND_NUM_ARGS(), &value, &precision) == FAILURE) { WRONG_PARAM_COUNT; } if (ZEND_NUM_ARGS() == 2) { convert_to_long_ex(precision); places = (int) Z_LVAL_PP(precision); } convert_scalar_to_number_ex(value); switch (Z_TYPE_PP(value)) { case IS_LONG: /* Simple case - long that doesn't need to be rounded. */ if (places >= 0) { RETURN_DOUBLE((double) Z_LVAL_PP(value)); } /* break omitted intentionally */ case IS_DOUBLE: return_val = (Z_TYPE_PP(value) == IS_LONG) ? (double)Z_LVAL_PP(value) : Z_DVAL_PP(value); PHP_ROUND_WITH_FUZZ(return_val, places); RETURN_DOUBLE(return_val); break; default: RETURN_FALSE; break; }}/* }}} *//* {{{ proto float sin(float number) Returns the sine of the number in radians */PHP_FUNCTION(sin){ zval **num; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &num) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num); Z_DVAL_P(return_value) = sin(Z_DVAL_PP(num)); Z_TYPE_P(return_value) = IS_DOUBLE;}/* }}} *//* {{{ proto float cos(float number) Returns the cosine of the number in radians */PHP_FUNCTION(cos){ zval **num; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &num) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num); Z_DVAL_P(return_value) = cos(Z_DVAL_PP(num)); Z_TYPE_P(return_value) = IS_DOUBLE;}/* }}} *//* {{{ proto float tan(float number) Returns the tangent of the number in radians */PHP_FUNCTION(tan){ zval **num; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &num) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num); Z_DVAL_P(return_value) = tan(Z_DVAL_PP(num)); Z_TYPE_P(return_value) = IS_DOUBLE;}/* }}} *//* {{{ proto float asin(float number) Returns the arc sine of the number in radians */PHP_FUNCTION(asin){ zval **num; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &num) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num); Z_DVAL_P(return_value) = asin(Z_DVAL_PP(num)); Z_TYPE_P(return_value) = IS_DOUBLE;}/* }}} *//* {{{ proto float acos(float number) Return the arc cosine of the number in radians */PHP_FUNCTION(acos){ zval **num; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &num) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num); Z_DVAL_P(return_value) = acos(Z_DVAL_PP(num)); Z_TYPE_P(return_value) = IS_DOUBLE;}/* }}} *//* {{{ proto float atan(float number) Returns the arc tangent of the number in radians */PHP_FUNCTION(atan){ zval **num; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &num) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num); Z_DVAL_P(return_value) = atan(Z_DVAL_PP(num)); Z_TYPE_P(return_value) = IS_DOUBLE;}/* }}} *//* {{{ proto float atan2(float y, float x) Returns the arc tangent of y/x, with the resulting quadrant determined by the signs of y and x */PHP_FUNCTION(atan2){ zval **num1, **num2; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &num1, &num2) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num1); convert_to_double_ex(num2); Z_DVAL_P(return_value) = atan2(Z_DVAL_PP(num1), Z_DVAL_PP(num2)); Z_TYPE_P(return_value) = IS_DOUBLE;}/* }}} *//* {{{ proto float sinh(float number) Returns the hyperbolic sine of the number, defined as (exp(number) - exp(-number))/2 */PHP_FUNCTION(sinh){ zval **num; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &num) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num); Z_DVAL_P(return_value) = sinh(Z_DVAL_PP(num)); Z_TYPE_P(return_value) = IS_DOUBLE;}/* }}} *//* {{{ proto float cosh(float number) Returns the hyperbolic cosine of the number, defined as (exp(number) + exp(-number))/2 */PHP_FUNCTION(cosh){ zval **num; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &num) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num); Z_DVAL_P(return_value) = cosh(Z_DVAL_PP(num)); Z_TYPE_P(return_value) = IS_DOUBLE;}/* }}} *//* {{{ proto float tanh(float number) Returns the hyperbolic tangent of the number, defined as sinh(number)/cosh(number) */PHP_FUNCTION(tanh){ zval **num; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &num) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num); Z_DVAL_P(return_value) = tanh(Z_DVAL_PP(num)); Z_TYPE_P(return_value) = IS_DOUBLE;}/* }}} */#ifndef PHP_WIN32#ifdef HAVE_ASINH/* {{{ proto float asinh(float number) Returns the inverse hyperbolic sine of the number, i.e. the value whose hyperbolic sine is number */PHP_FUNCTION(asinh){ zval **num; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &num) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num); Z_DVAL_P(return_value) = asinh(Z_DVAL_PP(num)); Z_TYPE_P(return_value) = IS_DOUBLE;}/* }}} */#endif /* HAVE_ASINH */#ifdef HAVE_ACOSH/* {{{ proto float acosh(float number) Returns the inverse hyperbolic cosine of the number, i.e. the value whose hyperbolic cosine is number */PHP_FUNCTION(acosh){ zval **num; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &num) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num); Z_DVAL_P(return_value) = acosh(Z_DVAL_PP(num)); Z_TYPE_P(return_value) = IS_DOUBLE;}/* }}} */#endif /* HAVE_ACOSH */#ifdef HAVE_ATANH/* {{{ proto float atanh(float number) Returns the inverse hyperbolic tangent of the number, i.e. the value whose hyperbolic tangent is number */PHP_FUNCTION(atanh){ zval **num; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &num) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num); Z_DVAL_P(return_value) = atanh(Z_DVAL_PP(num)); Z_TYPE_P(return_value) = IS_DOUBLE;}/* }}} */#endif /* HAVE_ATANH */#endif /* ifndf PHP_WIN32 *//* {{{ proto float pi(void) Returns an approximation of pi */PHP_FUNCTION(pi){ Z_DVAL_P(return_value) = M_PI; Z_TYPE_P(return_value) = IS_DOUBLE;}/* }}} *//* {{{ proto bool is_finite(float val) Returns whether argument is finite */PHP_FUNCTION(is_finite){ double dval; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) { return; } RETURN_BOOL(zend_finite(dval));}/* }}} *//* {{{ proto bool is_infinite(float val) Returns whether argument is infinite */PHP_FUNCTION(is_infinite){ double dval; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) { return; } RETURN_BOOL(zend_isinf(dval));}/* }}} *//* {{{ proto bool is_nan(float val) Returns whether argument is not a number */PHP_FUNCTION(is_nan){ double dval; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) { return; } RETURN_BOOL(zend_isnan(dval));}/* }}} *//* {{{ proto number pow(number base, number exponent) Returns base raised to the power of exponent. Returns integer result when possible */PHP_FUNCTION(pow){ zval *zbase, *zexp; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/z/", &zbase, &zexp) == FAILURE) { return; } /* make sure we're dealing with numbers */ convert_scalar_to_number(zbase TSRMLS_CC); convert_scalar_to_number(zexp TSRMLS_CC); /* if both base and exponent were longs, we'll try to get a long out */ if (Z_TYPE_P(zbase) == IS_LONG && Z_TYPE_P(zexp) == IS_LONG && Z_LVAL_P(zexp) >= 0) { long l1 = 1, l2 = Z_LVAL_P(zbase), i = Z_LVAL_P(zexp); if (i == 0) { RETURN_LONG(1L); } else if (l2 == 0) { RETURN_LONG(0); } /* calculate pow(long,long) in O(log exp) operations, bail if overflow */ while (i >= 1) { int overflow; double dval; if (i % 2) { --i; ZEND_SIGNED_MULTIPLY_LONG(l1,l2,l1,dval,overflow); if (overflow) RETURN_DOUBLE(dval * pow(l2,i)); } else { i /= 2; ZEND_SIGNED_MULTIPLY_LONG(l2,l2,l2,dval,overflow); if (overflow) RETURN_DOUBLE((double)l1 * pow(dval,i)); } if (i == 0) { RETURN_LONG(l1); } } } convert_to_double(zbase); convert_to_double(zexp); RETURN_DOUBLE( pow(Z_DVAL_P(zbase),Z_DVAL_P(zexp)) );}/* }}} *//* {{{ proto float exp(float number) Returns e raised to the power of the number */PHP_FUNCTION(exp){ zval **num; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &num) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num); Z_DVAL_P(return_value) = exp(Z_DVAL_PP(num)); Z_TYPE_P(return_value) = IS_DOUBLE;}/* }}} */#if !defined(PHP_WIN32) && !defined(NETWARE)/* {{{ proto float expm1(float number) Returns exp(number) - 1, computed in a way that accurate even when the value of number is close to zero *//* WARNING: this function is expermental: it could change its name or disappear in the next version of PHP!*/PHP_FUNCTION(expm1){ zval **num; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &num) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num); Z_DVAL_P(return_value) = expm1(Z_DVAL_PP(num)); Z_TYPE_P(return_value) = IS_DOUBLE;}/* }}} *//* {{{ proto float log1p(float number) Returns log(1 + number), computed in a way that accurate even when the value of number is close to zero *//* WARNING: this function is expermental: it could change its name or disappear in the next version of PHP!*/PHP_FUNCTION(log1p){#ifdef HAVE_LOG1P zval **num; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &num) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num); Z_DVAL_P(return_value) = log1p(Z_DVAL_PP(num)); Z_TYPE_P(return_value) = IS_DOUBLE;#endif}/* }}} */#endif/* {{{ proto float log(float number, [float base]) Returns the natural logarithm of the number, or the base log if base is specified */PHP_FUNCTION(log){ zval **num, **base; switch (ZEND_NUM_ARGS()) { case 1: if (zend_get_parameters_ex(1, &num) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num); RETURN_DOUBLE(log(Z_DVAL_PP(num))); case 2: if (zend_get_parameters_ex(2, &num, &base) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num); convert_to_double_ex(base); if (Z_DVAL_PP(base) <= 0.0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "base must be greater than 0"); RETURN_FALSE; } RETURN_DOUBLE(log(Z_DVAL_PP(num)) / log(Z_DVAL_PP(base))); default: WRONG_PARAM_COUNT; }}/* }}} *//* {{{ proto float log10(float number) Returns the base-10 logarithm of the number */PHP_FUNCTION(log10){ zval **num; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &num) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_double_ex(num); Z_DVAL_P(return_value) = log10(Z_DVAL_PP(num)); Z_TYPE_P(return_value) = IS_DOUBLE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -