#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; \
} \
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;
}
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;
}
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;
}
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:
if (places >= 0) {
RETURN_DOUBLE((double) Z_LVAL_PP(value));
}
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;
}
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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
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
#ifdef HAVE_ACOSH
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
#ifdef HAVE_ATANH
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
#endif
PHP_FUNCTION(pi)
{
Z_DVAL_P(return_value) = M_PI;
Z_TYPE_P(return_value) = IS_DOUBLE;
}
PHP_FUNCTION(is_finite)
{
double dval;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) {
return;
}
RETURN_BOOL(zend_finite(dval));
}
PHP_FUNCTION(is_infinite)
{
double dval;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) {
return;
}
RETURN_BOOL(zend_isinf(dval));
}
PHP_FUNCTION(is_nan)
{
double dval;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) {
return;
}
RETURN_BOOL(zend_isnan(dval));
}
PHP_FUNCTION(pow)
{
zval *zbase, *zexp;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/z/", &zbase, &zexp) == FAILURE) {
return;
}
convert_scalar_to_number(zbase TSRMLS_CC);
convert_scalar_to_number(zexp TSRMLS_CC);
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);
}
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)) );
}
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)
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;
}
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
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;
}
}
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;
}
PHP_FUNCTION(sqrt)
{
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) = sqrt(Z_DVAL_PP(num));
Z_TYPE_P(return_value) = IS_DOUBLE;
}
#ifdef HAVE_HYPOT
PHP_FUNCTION(hypot)
{
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) = hypot(Z_DVAL_PP(num1), Z_DVAL_PP(num2));
Z_TYPE_P(return_value) = IS_DOUBLE;
}
#endif
PHP_FUNCTION(deg2rad)
{
zval **deg;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, °) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_double_ex(deg);
RETVAL_DOUBLE((Z_DVAL_PP(deg) / 180.0) * M_PI);
}
PHP_FUNCTION(rad2deg)
{
zval **rad;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &rad) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_double_ex(rad);
RETVAL_DOUBLE((Z_DVAL_PP(rad) / M_PI) * 180);
}
PHPAPI long
_php_math_basetolong(zval *arg, int base) {
long num = 0, digit, onum;
int i;
char c, *s;
if (Z_TYPE_P(arg) != IS_STRING || base < 2 || base > 36) {
return 0;
}
s = Z_STRVAL_P(arg);
for (i = Z_STRLEN_P(arg); i > 0; i--) {
c = *s++;
digit = (c >= '0' && c <= '9') ? c - '0'
: (c >= 'A' && c <= 'Z') ? c - 'A' + 10
: (c >= 'a' && c <= 'z') ? c - 'a' + 10
: base;
if (digit >= base) {
continue;
}
onum = num;
num = num * base + digit;
if (num > onum)
continue;
{
TSRMLS_FETCH();
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number '%s' is too big to fit in long", s);
return LONG_MAX;
}
}
return num;
}
PHPAPI int
_php_math_basetozval(zval *arg, int base, zval *ret) {
long num = 0;
double fnum = 0;
int i;
int mode = 0;
char c, *s;
long cutoff;
int cutlim;
if (Z_TYPE_P(arg) != IS_STRING || base < 2 || base > 36) {
return FAILURE;
}
s = Z_STRVAL_P(arg);
cutoff = LONG_MAX / base;
cutlim = LONG_MAX % base;
for (i = Z_STRLEN_P(arg); i > 0; i--) {
c = *s++;
if (c >= '0' && c <= '9')
c -= '0';
else if (c >= 'A' && c <= 'Z')
c -= 'A' - 10;
else if (c >= 'a' && c <= 'z')
c -= 'a' - 10;
else
continue;
if (c >= base)
continue;
switch (mode) {
case 0:
if (num < cutoff || (num == cutoff && c <= cutlim)) {
num = num * base + c;
break;
} else {
fnum = num;
mode = 1;
}
case 1:
fnum = fnum * base + c;
}
}
if (mode == 1) {
ZVAL_DOUBLE(ret, fnum);
} else {
ZVAL_LONG(ret, num);
}
return SUCCESS;
}
PHPAPI char *
_php_math_longtobase(zval *arg, int base)
{
static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
char buf[(sizeof(unsigned long) << 3) + 1];
char *ptr, *end;
unsigned long value;
if (Z_TYPE_P(arg) != IS_LONG || base < 2 || base > 36) {
return empty_string;
}
value = Z_LVAL_P(arg);
end = ptr = buf + sizeof(buf) - 1;
*ptr = '\0';
do {
*--ptr = digits[value % base];
value /= base;
} while (ptr > buf && value);
return estrndup(ptr, end - ptr);
}
PHPAPI char *
_php_math_zvaltobase(zval *arg, int base TSRMLS_DC)
{
static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
if ((Z_TYPE_P(arg) != IS_LONG && Z_TYPE_P(arg) != IS_DOUBLE) || base < 2 || base > 36) {
return empty_string;
}
if (Z_TYPE_P(arg) == IS_DOUBLE) {
double fvalue = floor(Z_DVAL_P(arg));
char *ptr, *end;
char buf[(sizeof(double) << 3) + 1];
if (fvalue == HUGE_VAL || fvalue == -HUGE_VAL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number too large");
return empty_string;
}
end = ptr = buf + sizeof(buf) - 1;
*ptr = '\0';
do {
*--ptr = digits[(int) fmod(fvalue, base)];
fvalue /= base;
} while (ptr > buf && fabs(fvalue) >= 1);
return estrndup(ptr, end - ptr);
}
return _php_math_longtobase(arg, base);
}
PHP_FUNCTION(bindec)
{
zval **arg;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_string_ex(arg);
if(_php_math_basetozval(*arg, 2, return_value) != SUCCESS) {
RETURN_FALSE;
}
}
PHP_FUNCTION(hexdec)
{
zval **arg;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_string_ex(arg);
if(_php_math_basetozval(*arg, 16, return_value) != SUCCESS) {
RETURN_FALSE;
}
}
PHP_FUNCTION(octdec)
{
zval **arg;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_string_ex(arg);
if(_php_math_basetozval(*arg, 8, return_value) != SUCCESS) {
RETURN_FALSE;
}
}
PHP_FUNCTION(decbin)
{
zval **arg;
char *result;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long_ex(arg);
result = _php_math_longtobase(*arg, 2);
Z_TYPE_P(return_value) = IS_STRING;
Z_STRLEN_P(return_value) = strlen(result);
Z_STRVAL_P(return_value) = result;
}
PHP_FUNCTION(decoct)
{
zval **arg;
char *result;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long_ex(arg);
result = _php_math_longtobase(*arg, 8);
Z_TYPE_P(return_value) = IS_STRING;
Z_STRLEN_P(return_value) = strlen(result);
Z_STRVAL_P(return_value) = result;
}
PHP_FUNCTION(dechex)
{
zval **arg;
char *result;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_long_ex(arg);
result = _php_math_longtobase(*arg, 16);
Z_TYPE_P(return_value) = IS_STRING;
Z_STRLEN_P(return_value) = strlen(result);
Z_STRVAL_P(return_value) = result;
}
PHP_FUNCTION(base_convert)
{
zval **number, **frombase, **tobase, temp;
char *result;
if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &number, &frombase, &tobase) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_string_ex(number);
convert_to_long_ex(frombase);
convert_to_long_ex(tobase);
if (Z_LVAL_PP(frombase) < 2 || Z_LVAL_PP(frombase) > 36) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid `from base' (%ld)", Z_LVAL_PP(frombase));
RETURN_FALSE;
}
if (Z_LVAL_PP(tobase) < 2 || Z_LVAL_PP(tobase) > 36) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid `to base' (%ld)", Z_LVAL_PP(tobase));
RETURN_FALSE;
}
if(_php_math_basetozval(*number, Z_LVAL_PP(frombase), &temp) != SUCCESS) {
RETURN_FALSE;
}
result = _php_math_zvaltobase(&temp, Z_LVAL_PP(tobase) TSRMLS_CC);
RETVAL_STRING(result, 0);
}
PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char thousand_sep)
{
char *tmpbuf = NULL, *resbuf;
char *s, *t;
char *dp;
int integral;
int tmplen, reslen=0;
int count=0;
int is_negative=0;
if (d < 0) {
is_negative = 1;
d = -d;
}
dec = MAX(0, dec);
PHP_ROUND_WITH_FUZZ(d, dec);
tmplen = spprintf(&tmpbuf, 0, "%.*f", dec, d);
if (tmpbuf == NULL || !isdigit((int)tmpbuf[0])) {
return tmpbuf;
}
dp = dec ? strchr(tmpbuf, '.') : NULL;
if (dp) {
integral = dp - tmpbuf;
} else {
integral = tmplen;
}
if (thousand_sep) {
integral += (integral-1) / 3;
}
reslen = integral;
if (dec) {
reslen += dec;
if (dec_point) {
reslen++;
}
}
if (is_negative) {
reslen++;
}
resbuf = (char *) emalloc(reslen+1);
s = tmpbuf+tmplen-1;
t = resbuf+reslen;
*t-- = '\0';
if (dec) {
int declen = dp ? s - dp : 0;
int topad = dec > declen ? dec - declen : 0;
while (topad--) {
*t-- = '0';
}
if (dp) {
s -= declen + 1;
t -= declen;
memcpy(t + 1, dp + 1, declen);
}
if (dec_point) {
*t-- = dec_point;
}
}
while(s >= tmpbuf) {
*t-- = *s--;
if (thousand_sep && (++count%3)==0 && s>=tmpbuf) {
*t-- = thousand_sep;
}
}
if (is_negative) {
*t-- = '-';
}
efree(tmpbuf);
return resbuf;
}
PHP_FUNCTION(number_format)
{
zval **num, **dec, **t_s, **d_p;
char thousand_sep=',', dec_point='.';
switch(ZEND_NUM_ARGS()) {
case 1:
if (zend_get_parameters_ex(1, &num)==FAILURE) {
RETURN_FALSE;
}
convert_to_double_ex(num);
RETURN_STRING(_php_math_number_format(Z_DVAL_PP(num), 0, dec_point, thousand_sep), 0);
break;
case 2:
if (zend_get_parameters_ex(2, &num, &dec)==FAILURE) {
RETURN_FALSE;
}
convert_to_double_ex(num);
convert_to_long_ex(dec);
RETURN_STRING(_php_math_number_format(Z_DVAL_PP(num), Z_LVAL_PP(dec), dec_point, thousand_sep), 0);
break;
case 4:
if (zend_get_parameters_ex(4, &num, &dec, &d_p, &t_s)==FAILURE) {
RETURN_FALSE;
}
convert_to_double_ex(num);
convert_to_long_ex(dec);
if (Z_TYPE_PP(d_p) != IS_NULL) {
convert_to_string_ex(d_p);
if (Z_STRLEN_PP(d_p)>=1) {
dec_point=Z_STRVAL_PP(d_p)[0];
} else if (Z_STRLEN_PP(d_p)==0) {
dec_point=0;
}
}
if (Z_TYPE_PP(t_s) != IS_NULL) {
convert_to_string_ex(t_s);
if (Z_STRLEN_PP(t_s)>=1) {
thousand_sep=Z_STRVAL_PP(t_s)[0];
} else if(Z_STRLEN_PP(t_s)==0) {
thousand_sep=0;
}
}
RETURN_STRING(_php_math_number_format(Z_DVAL_PP(num), Z_LVAL_PP(dec), dec_point, thousand_sep), 0);
break;
default:
WRONG_PARAM_COUNT;
break;
}
}
PHP_FUNCTION(fmod)
{
double num1, num2;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &num1, &num2) == FAILURE) {
return;
}
Z_DVAL_P(return_value) = fmod(num1, num2);
Z_TYPE_P(return_value) = IS_DOUBLE;
}