File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / standard / math.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:34:43 2012 UTC (12 years, 2 months ago) by misho
Branches: php, MAIN
CVS tags: v5_4_3elwix, v5_4_17p0, HEAD
php 5.4.3+patches

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | PHP Version 5                                                        |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1997-2012 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: math.c,v 1.1.1.2 2012/05/29 12:34:43 misho Exp $ */
   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: static inline int php_intlog10abs(double value) {
   37: 	int result;
   38: 	value = fabs(value);
   39: 
   40: 	if (value < 1e-8 || value > 1e23) {
   41: 		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: 		result = 16;
   50: 		if (value < values[result]) {
   51: 			result -= 8;
   52: 		} else {
   53: 			result += 8;
   54: 		}
   55: 		if (value < values[result]) {
   56: 			result -= 4;
   57: 		} else {
   58: 			result += 4;
   59: 		}
   60: 		if (value < values[result]) {
   61: 			result -= 2;
   62: 		} else {
   63: 			result += 2;
   64: 		}
   65: 		if (value < values[result]) {
   66: 			result -= 1;
   67: 		} else {
   68: 			result += 1;
   69: 		}
   70: 		if (value < values[result]) {
   71: 			result -= 1;
   72: 		}
   73: 		result -= 8;
   74: 	}
   75: 	return result;
   76: }
   77: /* }}} */
   78: 
   79: /* {{{ php_intpow10
   80:        Returns pow(10.0, (double)power), uses fast lookup table for exact powers */
   81: 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: 	if (power < 0 || power > 22) {
   89: 		return pow(10.0, (double)power);
   90: 	}
   91: 	return powers[power];
   92: }
   93: /* }}} */
   94: 
   95: /* {{{ php_math_is_finite */
   96: static inline int php_math_is_finite(double value) {
   97: #if defined(PHP_WIN32)
   98: 	return _finite(value);
   99: #elif defined(isfinite)
  100: 	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: static inline double php_round_helper(double value, int mode) {
  110: 	double tmp_value;
  111: 
  112: 	if (value >= 0.0) {
  113: 		tmp_value = floor(value + 0.5);
  114: 		if ((mode == PHP_ROUND_HALF_DOWN && value == (-0.5 + tmp_value)) ||
  115: 			(mode == PHP_ROUND_HALF_EVEN && value == (0.5 + 2 * floor(tmp_value/2.0))) ||
  116: 			(mode == PHP_ROUND_HALF_ODD  && value == (0.5 + 2 * floor(tmp_value/2.0) - 1.0)))
  117: 		{
  118: 			tmp_value = tmp_value - 1.0;
  119: 		}
  120: 	} else {
  121: 		tmp_value = ceil(value - 0.5);
  122: 		if ((mode == PHP_ROUND_HALF_DOWN && value == (0.5 + tmp_value)) ||
  123: 			(mode == PHP_ROUND_HALF_EVEN && value == (-0.5 + 2 * ceil(tmp_value/2.0))) ||
  124: 			(mode == PHP_ROUND_HALF_ODD  && value == (-0.5 + 2 * ceil(tmp_value/2.0) + 1.0)))
  125: 		{
  126: 			tmp_value = tmp_value + 1.0;
  127: 		}
  128: 	}
  129: 
  130: 	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: 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: 	if (!php_math_is_finite(value)) {
  145: 		return value;
  146: 	}
  147: 	
  148: 	precision_places = 14 - php_intlog10abs(value);
  149: 
  150: 	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: 	if (precision_places > places && precision_places - places < 15) {
  156: 		f2 = php_intpow10(abs(precision_places));
  157: 		if (precision_places >= 0) {
  158: 			tmp_value = value * f2;
  159: 		} else {
  160: 			tmp_value = value / f2;
  161: 		}
  162: 		/* preround the result (tmp_value will always be something * 1e14,
  163: 		   thus never larger than 1e15 here) */
  164: 		tmp_value = php_round_helper(tmp_value, mode);
  165: 		/* now correctly move the decimal point */
  166: 		f2 = php_intpow10(abs(places - precision_places));
  167: 		/* because places < precision_places */
  168: 		tmp_value = tmp_value / f2;
  169: 	} else {
  170: 		/* adjust the value */
  171: 		if (places >= 0) {
  172: 			tmp_value = value * f1;
  173: 		} else {
  174: 			tmp_value = value / f1;
  175: 		}
  176: 		/* This value is beyond our precision, so rounding it is pointless */
  177: 		if (fabs(tmp_value) >= 1e15) {
  178: 			return value;
  179: 		}
  180: 	}
  181: 
  182: 	/* round the temp value */
  183: 	tmp_value = php_round_helper(tmp_value, mode);
  184: 	
  185: 	/* see if it makes sense to use simple division to round the value */
  186: 	if (abs(places) < 23) {
  187: 		if (places > 0) {
  188: 			tmp_value = tmp_value / f1;
  189: 		} else {
  190: 			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: 		snprintf(buf, 39, "%15fe%d", tmp_value, -places);
  203: 		buf[39] = '\0';
  204: 		tmp_value = zend_strtod(buf, NULL);
  205: 		/* couldn't convert to string and back */
  206: 		if (!zend_finite(tmp_value) || zend_isnan(tmp_value)) {
  207: 			tmp_value = value;
  208: 		}
  209: 	}
  210: 
  211: 	return tmp_value;
  212: }
  213: /* }}} */
  214: 
  215: /* {{{ php_asinh
  216: */
  217: static double php_asinh(double z)
  218: {
  219: #ifdef HAVE_ASINH
  220: 	return(asinh(z));
  221: #else
  222: 	return(log(z + sqrt(1 + pow(z, 2))) / log(M_E));
  223: #endif
  224: }
  225: /* }}} */
  226: 
  227: /* {{{ php_acosh
  228: */
  229: static double php_acosh(double x)
  230: {
  231: #ifdef HAVE_ACOSH
  232: 	return(acosh(x));
  233: #else
  234: 	return(log(x + sqrt(x * x - 1)));
  235: #endif
  236: }
  237: /* }}} */
  238: 
  239: /* {{{ php_atanh
  240: */
  241: static double php_atanh(double z)
  242: {
  243: #ifdef HAVE_ATANH
  244: 	return(atanh(z));
  245: #else
  246: 	return(0.5 * log((1 + z) / (1 - z)));
  247: #endif
  248: }
  249: /* }}} */
  250: 
  251: /* {{{ php_log1p
  252: */
  253: static double php_log1p(double x)
  254: {
  255: #ifdef HAVE_LOG1P
  256: 	return(log1p(x));
  257: #else
  258: 	return(log(1 + x));
  259: #endif
  260: }
  261: /* }}} */
  262: 
  263: /* {{{ php_expm1
  264: */
  265: static double php_expm1(double x)
  266: {
  267: #if !defined(PHP_WIN32) && !defined(NETWARE)
  268: 	return(expm1(x));
  269: #else
  270: 	return(exp(x) - 1);
  271: #endif
  272: }
  273: /* }}}*/
  274: 
  275: /* {{{ proto int abs(int number)
  276:    Return the absolute value of the number */
  277: PHP_FUNCTION(abs) 
  278: {
  279: 	zval **value;
  280: 	
  281: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &value) == FAILURE) {
  282: 		return;
  283: 	}
  284: 	convert_scalar_to_number_ex(value);
  285: 	
  286: 	if (Z_TYPE_PP(value) == IS_DOUBLE) {
  287: 		RETURN_DOUBLE(fabs(Z_DVAL_PP(value)));
  288: 	} else if (Z_TYPE_PP(value) == IS_LONG) {
  289: 		if (Z_LVAL_PP(value) == LONG_MIN) {
  290: 			RETURN_DOUBLE(-(double)LONG_MIN);
  291: 		} else {
  292: 			RETURN_LONG(Z_LVAL_PP(value) < 0 ? -Z_LVAL_PP(value) : Z_LVAL_PP(value));
  293: 		}
  294: 	}
  295: 	RETURN_FALSE;
  296: }
  297: /* }}} */ 
  298: 
  299: /* {{{ proto float ceil(float number)
  300:    Returns the next highest integer value of the number */
  301: PHP_FUNCTION(ceil) 
  302: {
  303: 	zval **value;
  304: 	
  305: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &value) == FAILURE) {
  306: 		return;
  307: 	}
  308: 	convert_scalar_to_number_ex(value);
  309: 
  310: 	if (Z_TYPE_PP(value) == IS_DOUBLE) {
  311: 		RETURN_DOUBLE(ceil(Z_DVAL_PP(value)));
  312: 	} else if (Z_TYPE_PP(value) == IS_LONG) {
  313: 		convert_to_double_ex(value);
  314: 		RETURN_DOUBLE(Z_DVAL_PP(value));
  315: 	}
  316: 	RETURN_FALSE;
  317: }
  318: /* }}} */
  319: 
  320: /* {{{ proto float floor(float number)
  321:    Returns the next lowest integer value from the number */
  322: PHP_FUNCTION(floor)
  323: {
  324: 	zval **value;
  325: 	
  326: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &value) == FAILURE) {
  327: 		return;
  328: 	}
  329: 	convert_scalar_to_number_ex(value);
  330: 
  331: 	if (Z_TYPE_PP(value) == IS_DOUBLE) {
  332: 		RETURN_DOUBLE(floor(Z_DVAL_PP(value)));
  333: 	} else if (Z_TYPE_PP(value) == IS_LONG) {
  334: 		convert_to_double_ex(value);
  335: 		RETURN_DOUBLE(Z_DVAL_PP(value));
  336: 	}
  337: 	RETURN_FALSE;
  338: }
  339: /* }}} */
  340: 
  341: /* {{{ proto float round(float number [, int precision [, int mode]])
  342:    Returns the number rounded to specified precision */
  343: PHP_FUNCTION(round)
  344: {
  345: 	zval **value;
  346: 	int places = 0;
  347: 	long precision = 0;
  348: 	long mode = PHP_ROUND_HALF_UP;
  349: 	double return_val;
  350: 	
  351: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|ll", &value, &precision, &mode) == FAILURE) {
  352: 		return;
  353: 	}
  354: 
  355: 	if (ZEND_NUM_ARGS() >= 2) {
  356: 		places = (int) precision;
  357: 	}
  358: 	convert_scalar_to_number_ex(value);
  359: 
  360: 	switch (Z_TYPE_PP(value)) {
  361: 		case IS_LONG:
  362: 			/* Simple case - long that doesn't need to be rounded. */
  363: 			if (places >= 0) {
  364: 				RETURN_DOUBLE((double) Z_LVAL_PP(value));
  365: 			}
  366: 			/* break omitted intentionally */
  367: 
  368: 		case IS_DOUBLE:
  369: 			return_val = (Z_TYPE_PP(value) == IS_LONG) ? (double)Z_LVAL_PP(value) : Z_DVAL_PP(value);
  370: 			return_val = _php_math_round(return_val, places, mode);
  371: 			RETURN_DOUBLE(return_val);
  372: 			break;
  373: 
  374: 		default:
  375: 			RETURN_FALSE;
  376: 			break;
  377: 	}
  378: }
  379: /* }}} */
  380: 
  381: /* {{{ proto float sin(float number)
  382:    Returns the sine of the number in radians */
  383: PHP_FUNCTION(sin)
  384: {
  385: 	double num;
  386: 
  387: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
  388: 		return;
  389: 	}
  390: 	RETURN_DOUBLE(sin(num));
  391: }
  392: /* }}} */
  393: 
  394: /* {{{ proto float cos(float number)
  395:    Returns the cosine of the number in radians */
  396: PHP_FUNCTION(cos)
  397: {
  398: 	double num;
  399: 	
  400: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
  401: 		return;
  402: 	}
  403: 	RETURN_DOUBLE(cos(num));
  404: }
  405: /* }}} */
  406: 
  407: /* {{{ proto float tan(float number)
  408:    Returns the tangent of the number in radians */
  409: PHP_FUNCTION(tan)
  410: {
  411: 	double num;
  412: 
  413: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
  414: 		return;
  415: 	}
  416: 	RETURN_DOUBLE(tan(num));
  417: }
  418: /* }}} */
  419: 
  420: /* {{{ proto float asin(float number)
  421:    Returns the arc sine of the number in radians */
  422: PHP_FUNCTION(asin)
  423: {
  424: 	double num;
  425: 
  426: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
  427: 		return;
  428: 	}
  429: 	RETURN_DOUBLE(asin(num));
  430: }
  431: /* }}} */
  432: 
  433: /* {{{ proto float acos(float number)
  434:    Return the arc cosine of the number in radians */
  435: PHP_FUNCTION(acos)
  436: {
  437: 	double num;
  438: 
  439: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
  440: 		return;
  441: 	}
  442: 	RETURN_DOUBLE(acos(num));
  443: }
  444: /* }}} */
  445: 
  446: /* {{{ proto float atan(float number)
  447:    Returns the arc tangent of the number in radians */
  448: PHP_FUNCTION(atan)
  449: {
  450: 	double num;
  451: 
  452: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
  453: 		return;
  454: 	}
  455: 	RETURN_DOUBLE(atan(num));
  456: }
  457: /* }}} */
  458: 
  459: /* {{{ proto float atan2(float y, float x)
  460:    Returns the arc tangent of y/x, with the resulting quadrant determined by the signs of y and x */
  461: PHP_FUNCTION(atan2)
  462: {
  463: 	double num1, num2;
  464: 
  465: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &num1, &num2) == FAILURE) {
  466: 		return;
  467: 	}
  468: 	RETURN_DOUBLE(atan2(num1, num2));
  469: }
  470: /* }}} */
  471: 
  472: /* {{{ proto float sinh(float number)
  473:    Returns the hyperbolic sine of the number, defined as (exp(number) - exp(-number))/2 */
  474: PHP_FUNCTION(sinh)
  475: {
  476: 	double num;
  477: 
  478: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
  479: 		return;
  480: 	}
  481: 	RETURN_DOUBLE(sinh(num));
  482: }
  483: /* }}} */
  484: 
  485: /* {{{ proto float cosh(float number)
  486:    Returns the hyperbolic cosine of the number, defined as (exp(number) + exp(-number))/2 */
  487: PHP_FUNCTION(cosh)
  488: {
  489: 	double num;
  490: 
  491: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
  492: 		return;
  493: 	}
  494: 	RETURN_DOUBLE(cosh(num));
  495: }
  496: /* }}} */
  497: 
  498: /* {{{ proto float tanh(float number)
  499:    Returns the hyperbolic tangent of the number, defined as sinh(number)/cosh(number) */
  500: PHP_FUNCTION(tanh)
  501: {
  502: 	double num;
  503: 
  504: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
  505: 		return;
  506: 	}
  507: 	RETURN_DOUBLE(tanh(num));
  508: }
  509: /* }}} */
  510: 
  511: /* {{{ proto float asinh(float number)
  512:    Returns the inverse hyperbolic sine of the number, i.e. the value whose hyperbolic sine is number */
  513: PHP_FUNCTION(asinh)
  514: {
  515: 	double num;
  516: 
  517: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
  518: 		return;
  519: 	}
  520: 	RETURN_DOUBLE(php_asinh(num));
  521: }
  522: /* }}} */
  523: 
  524: /* {{{ proto float acosh(float number)
  525:    Returns the inverse hyperbolic cosine of the number, i.e. the value whose hyperbolic cosine is number */
  526: PHP_FUNCTION(acosh)
  527: {
  528: 	double num;
  529: 	
  530: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
  531: 		return;
  532: 	}
  533: 	RETURN_DOUBLE(php_acosh(num));
  534: }
  535: /* }}} */
  536: 
  537: /* {{{ proto float atanh(float number)
  538:    Returns the inverse hyperbolic tangent of the number, i.e. the value whose hyperbolic tangent is number */
  539: PHP_FUNCTION(atanh)
  540: {
  541: 	double num;
  542: 
  543: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
  544: 		return;
  545: 	}
  546: 	RETURN_DOUBLE(php_atanh(num));
  547: }
  548: /* }}} */
  549: 
  550: /* {{{ proto float pi(void)
  551:    Returns an approximation of pi */
  552: PHP_FUNCTION(pi)
  553: {
  554: 	RETURN_DOUBLE(M_PI);
  555: }
  556: /* }}} */
  557: 
  558: /* {{{ proto bool is_finite(float val)
  559:    Returns whether argument is finite */
  560: PHP_FUNCTION(is_finite)
  561: {
  562: 	double dval;
  563: 
  564: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) {
  565: 		return;
  566: 	}
  567: 	RETURN_BOOL(zend_finite(dval));
  568: }
  569: /* }}} */
  570: 
  571: /* {{{ proto bool is_infinite(float val)
  572:    Returns whether argument is infinite */
  573: PHP_FUNCTION(is_infinite)
  574: {
  575: 	double dval;
  576: 
  577: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) {
  578: 		return;
  579: 	}
  580: 	RETURN_BOOL(zend_isinf(dval));
  581: }
  582: /* }}} */
  583: 
  584: /* {{{ proto bool is_nan(float val)
  585:    Returns whether argument is not a number */
  586: PHP_FUNCTION(is_nan)
  587: {
  588: 	double dval;
  589: 
  590: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) {
  591: 		return;
  592: 	}
  593: 	RETURN_BOOL(zend_isnan(dval));
  594: }
  595: /* }}} */
  596: 
  597: /* {{{ proto number pow(number base, number exponent)
  598:    Returns base raised to the power of exponent. Returns integer result when possible */
  599: PHP_FUNCTION(pow)
  600: {
  601: 	zval *zbase, *zexp;
  602: 
  603: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/z/", &zbase, &zexp) == FAILURE) {
  604: 		return;
  605: 	}
  606: 
  607: 	/* make sure we're dealing with numbers */
  608: 	convert_scalar_to_number(zbase TSRMLS_CC);
  609: 	convert_scalar_to_number(zexp TSRMLS_CC);
  610: 
  611: 	/* if both base and exponent were longs, we'll try to get a long out */
  612: 	if (Z_TYPE_P(zbase) == IS_LONG && Z_TYPE_P(zexp) == IS_LONG && Z_LVAL_P(zexp) >= 0) {
  613: 		long l1 = 1, l2 = Z_LVAL_P(zbase), i = Z_LVAL_P(zexp);
  614: 		
  615: 		if (i == 0) {
  616: 			RETURN_LONG(1L);
  617: 		} else if (l2 == 0) {
  618: 			RETURN_LONG(0);
  619: 		}
  620: 
  621: 		/* calculate pow(long,long) in O(log exp) operations, bail if overflow */
  622: 		while (i >= 1) {
  623: 			long overflow;
  624: 			double dval = 0.0;
  625: 
  626: 			if (i % 2) {
  627: 				--i;
  628: 				ZEND_SIGNED_MULTIPLY_LONG(l1,l2,l1,dval,overflow);
  629: 				if (overflow) RETURN_DOUBLE(dval * pow(l2,i));
  630: 			} else {
  631: 				i /= 2;
  632: 				ZEND_SIGNED_MULTIPLY_LONG(l2,l2,l2,dval,overflow);
  633: 				if (overflow) RETURN_DOUBLE((double)l1 * pow(dval,i));
  634: 			}
  635: 			if (i == 0) {
  636: 				RETURN_LONG(l1);
  637: 			}
  638: 		}
  639: 	}
  640: 	convert_to_double(zbase);
  641: 	convert_to_double(zexp);
  642: 	
  643: 	RETURN_DOUBLE(pow(Z_DVAL_P(zbase), Z_DVAL_P(zexp)));
  644: }
  645: /* }}} */
  646: 
  647: /* {{{ proto float exp(float number)
  648:    Returns e raised to the power of the number */
  649: PHP_FUNCTION(exp)
  650: {
  651: 	double num;
  652: 
  653: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
  654: 		return;
  655: 	}
  656: 
  657: 	RETURN_DOUBLE(exp(num));
  658: }
  659: /* }}} */
  660: 
  661: /* {{{ proto float expm1(float number)
  662:    Returns exp(number) - 1, computed in a way that accurate even when the value of number is close to zero */
  663: /*
  664:    WARNING: this function is expermental: it could change its name or 
  665:    disappear in the next version of PHP!
  666: */
  667: PHP_FUNCTION(expm1)
  668: {
  669: 	double num;
  670: 
  671: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
  672: 		return;
  673: 	}
  674: 	RETURN_DOUBLE(php_expm1(num));
  675: }
  676: /* }}} */
  677: 
  678: /* {{{ proto float log1p(float number)
  679:    Returns log(1 + number), computed in a way that accurate even when the value of number is close to zero */ 
  680: /*
  681:    WARNING: this function is expermental: it could change its name or 
  682:    disappear in the next version of PHP!
  683: */
  684: PHP_FUNCTION(log1p)
  685: {
  686: 	double num;
  687: 
  688: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
  689: 		return;
  690: 	}
  691: 	RETURN_DOUBLE(php_log1p(num));
  692: }
  693: /* }}} */
  694: 
  695: /* {{{ proto float log(float number, [float base])
  696:    Returns the natural logarithm of the number, or the base log if base is specified */
  697: PHP_FUNCTION(log)
  698: {
  699: 	double num, base = 0;
  700: 	
  701: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|d", &num, &base) == FAILURE) {
  702: 		return;
  703: 	}
  704: 	if (ZEND_NUM_ARGS() == 1) {
  705: 		RETURN_DOUBLE(log(num));
  706: 	}
  707: 	if (base <= 0.0) {
  708: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "base must be greater than 0");				
  709: 		RETURN_FALSE;
  710: 	}
  711: 	if (base == 1) {
  712: 		RETURN_DOUBLE(php_get_nan());
  713: 	} else {
  714: 		RETURN_DOUBLE(log(num) / log(base));
  715: 	}
  716: }
  717: /* }}} */
  718: 
  719: /* {{{ proto float log10(float number)
  720:    Returns the base-10 logarithm of the number */
  721: PHP_FUNCTION(log10)
  722: {
  723: 	double num;
  724: 
  725: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
  726: 		return;
  727: 	}
  728: 	RETURN_DOUBLE(log10(num));
  729: }
  730: /* }}} */
  731: 
  732: /* {{{ proto float sqrt(float number)
  733:    Returns the square root of the number */
  734: PHP_FUNCTION(sqrt)
  735: {
  736: 	double num;
  737: 
  738: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
  739: 		return;
  740: 	}
  741: 	RETURN_DOUBLE(sqrt(num));
  742: }
  743: /* }}} */
  744: 
  745: /* {{{ proto float hypot(float num1, float num2)
  746:    Returns sqrt(num1*num1 + num2*num2) */ 
  747: PHP_FUNCTION(hypot)
  748: {
  749: 	double num1, num2;
  750: 
  751: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &num1, &num2) == FAILURE) {
  752: 		return;
  753: 	}
  754: #if HAVE_HYPOT
  755: 	RETURN_DOUBLE(hypot(num1, num2));
  756: #elif defined(_MSC_VER)
  757: 	RETURN_DOUBLE(_hypot(num1, num2));
  758: #else
  759: 	RETURN_DOUBLE(sqrt((num1 * num1) + (num2 * num2)));
  760: #endif
  761: }
  762: /* }}} */
  763: 
  764: /* {{{ proto float deg2rad(float number)
  765:    Converts the number in degrees to the radian equivalent */
  766: PHP_FUNCTION(deg2rad)
  767: {
  768: 	double deg;
  769: 
  770: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &deg) == FAILURE) {
  771: 		return;
  772: 	}
  773: 	RETURN_DOUBLE((deg / 180.0) * M_PI);
  774: }
  775: /* }}} */
  776: 
  777: /* {{{ proto float rad2deg(float number)
  778:    Converts the radian number to the equivalent number in degrees */
  779: PHP_FUNCTION(rad2deg)
  780: {
  781: 	double rad;
  782: 
  783: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &rad) == FAILURE) {
  784: 		return;
  785: 	}
  786: 	RETURN_DOUBLE((rad / M_PI) * 180);
  787: }
  788: /* }}} */
  789: 
  790: /* {{{ _php_math_basetolong */
  791: /*
  792:  * Convert a string representation of a base(2-36) number to a long.
  793:  */
  794: PHPAPI long _php_math_basetolong(zval *arg, int base)
  795: {
  796: 	long num = 0, digit, onum;
  797: 	int i;
  798: 	char c, *s;
  799: 
  800: 	if (Z_TYPE_P(arg) != IS_STRING || base < 2 || base > 36) {
  801: 		return 0;
  802: 	}
  803: 
  804: 	s = Z_STRVAL_P(arg);
  805: 
  806: 	for (i = Z_STRLEN_P(arg); i > 0; i--) {
  807: 		c = *s++;
  808: 		
  809: 		digit = (c >= '0' && c <= '9') ? c - '0'
  810: 			: (c >= 'A' && c <= 'Z') ? c - 'A' + 10
  811: 			: (c >= 'a' && c <= 'z') ? c - 'a' + 10
  812: 			: base;
  813: 		
  814: 		if (digit >= base) {
  815: 			continue;
  816: 		}
  817: 
  818: 		onum = num;
  819: 		num = num * base + digit;
  820: 		if (num > onum)
  821: 			continue;
  822: 
  823: 		{
  824: 			TSRMLS_FETCH();
  825: 
  826: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number '%s' is too big to fit in long", s);
  827: 			return LONG_MAX;
  828: 		}
  829: 	}
  830: 
  831: 	return num;
  832: }
  833: /* }}} */
  834: 
  835: /* {{{ _php_math_basetozval */
  836: /*
  837:  * Convert a string representation of a base(2-36) number to a zval.
  838:  */
  839: PHPAPI int _php_math_basetozval(zval *arg, int base, zval *ret)
  840: {
  841: 	long num = 0;
  842: 	double fnum = 0;
  843: 	int i;
  844: 	int mode = 0;
  845: 	char c, *s;
  846: 	long cutoff;
  847: 	int cutlim;
  848: 
  849: 	if (Z_TYPE_P(arg) != IS_STRING || base < 2 || base > 36) {
  850: 		return FAILURE;
  851: 	}
  852: 
  853: 	s = Z_STRVAL_P(arg);
  854: 
  855: 	cutoff = LONG_MAX / base;
  856: 	cutlim = LONG_MAX % base;
  857: 	
  858: 	for (i = Z_STRLEN_P(arg); i > 0; i--) {
  859: 		c = *s++;
  860: 
  861: 		/* might not work for EBCDIC */
  862: 		if (c >= '0' && c <= '9') 
  863: 			c -= '0';
  864: 		else if (c >= 'A' && c <= 'Z') 
  865: 			c -= 'A' - 10;
  866: 		else if (c >= 'a' && c <= 'z') 
  867: 			c -= 'a' - 10;
  868: 		else
  869: 			continue;
  870: 
  871: 		if (c >= base)
  872: 			continue;
  873: 		
  874: 		switch (mode) {
  875: 		case 0: /* Integer */
  876: 			if (num < cutoff || (num == cutoff && c <= cutlim)) {
  877: 				num = num * base + c;
  878: 				break;
  879: 			} else {
  880: 				fnum = num;
  881: 				mode = 1;
  882: 			}
  883: 			/* fall-through */
  884: 		case 1: /* Float */
  885: 			fnum = fnum * base + c;
  886: 		}	
  887: 	}
  888: 
  889: 	if (mode == 1) {
  890: 		ZVAL_DOUBLE(ret, fnum);
  891: 	} else {
  892: 		ZVAL_LONG(ret, num);
  893: 	}
  894: 	return SUCCESS;
  895: }
  896: /* }}} */
  897: 
  898: /* {{{ _php_math_longtobase */
  899: /*
  900:  * Convert a long to a string containing a base(2-36) representation of
  901:  * the number.
  902:  */
  903: PHPAPI char * _php_math_longtobase(zval *arg, int base)
  904: {
  905: 	static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
  906: 	char buf[(sizeof(unsigned long) << 3) + 1];
  907: 	char *ptr, *end;
  908: 	unsigned long value;
  909: 
  910: 	if (Z_TYPE_P(arg) != IS_LONG || base < 2 || base > 36) {
  911: 		return STR_EMPTY_ALLOC();
  912: 	}
  913: 
  914: 	value = Z_LVAL_P(arg);
  915: 
  916: 	end = ptr = buf + sizeof(buf) - 1;
  917: 	*ptr = '\0';
  918: 
  919: 	do {
  920: 		*--ptr = digits[value % base];
  921: 		value /= base;
  922: 	} while (ptr > buf && value);
  923: 
  924: 	return estrndup(ptr, end - ptr);
  925: }
  926: /* }}} */
  927: 
  928: /* {{{ _php_math_zvaltobase */
  929: /*
  930:  * Convert a zval to a string containing a base(2-36) representation of
  931:  * the number.
  932:  */
  933: PHPAPI char * _php_math_zvaltobase(zval *arg, int base TSRMLS_DC)
  934: {
  935: 	static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
  936: 
  937: 	if ((Z_TYPE_P(arg) != IS_LONG && Z_TYPE_P(arg) != IS_DOUBLE) || base < 2 || base > 36) {
  938: 		return STR_EMPTY_ALLOC();
  939: 	}
  940: 
  941: 	if (Z_TYPE_P(arg) == IS_DOUBLE) {
  942: 		double fvalue = floor(Z_DVAL_P(arg)); /* floor it just in case */
  943: 		char *ptr, *end;
  944: 		char buf[(sizeof(double) << 3) + 1];
  945: 
  946: 		/* Don't try to convert +/- infinity */
  947: 		if (fvalue == HUGE_VAL || fvalue == -HUGE_VAL) {
  948: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number too large");
  949: 			return STR_EMPTY_ALLOC();
  950: 		}
  951: 
  952: 		end = ptr = buf + sizeof(buf) - 1;
  953: 		*ptr = '\0';
  954: 
  955: 		do {
  956: 			*--ptr = digits[(int) fmod(fvalue, base)];
  957: 			fvalue /= base;
  958: 		} while (ptr > buf && fabs(fvalue) >= 1);
  959: 
  960: 		return estrndup(ptr, end - ptr);
  961: 	}
  962: 	
  963: 	return _php_math_longtobase(arg, base);
  964: }	
  965: /* }}} */
  966: 
  967: /* {{{ proto int bindec(string binary_number)
  968:    Returns the decimal equivalent of the binary number */
  969: PHP_FUNCTION(bindec)
  970: {
  971: 	zval **arg;
  972: 	
  973: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
  974: 		return;
  975: 	}
  976: 	convert_to_string_ex(arg);
  977: 	if (_php_math_basetozval(*arg, 2, return_value) == FAILURE) {
  978: 		RETURN_FALSE;
  979: 	}
  980: }
  981: /* }}} */
  982: 
  983: /* {{{ proto int hexdec(string hexadecimal_number)
  984:    Returns the decimal equivalent of the hexadecimal number */
  985: PHP_FUNCTION(hexdec)
  986: {
  987: 	zval **arg;
  988: 	
  989: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
  990: 		return;
  991: 	}
  992: 	convert_to_string_ex(arg);
  993: 	if (_php_math_basetozval(*arg, 16, return_value) == FAILURE) {
  994: 		RETURN_FALSE;
  995: 	}
  996: }
  997: /* }}} */
  998: 
  999: /* {{{ proto int octdec(string octal_number)
 1000:    Returns the decimal equivalent of an octal string */
 1001: PHP_FUNCTION(octdec)
 1002: {
 1003: 	zval **arg;
 1004: 	
 1005: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
 1006: 		return;
 1007: 	}
 1008: 	convert_to_string_ex(arg);
 1009: 	if (_php_math_basetozval(*arg, 8, return_value) == FAILURE) {
 1010: 		RETURN_FALSE;
 1011: 	}
 1012: }
 1013: /* }}} */
 1014: 
 1015: /* {{{ proto string decbin(int decimal_number)
 1016:    Returns a string containing a binary representation of the number */
 1017: PHP_FUNCTION(decbin)
 1018: {
 1019: 	zval **arg;
 1020: 	char *result;
 1021: 
 1022: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
 1023: 		return;
 1024: 	}
 1025: 	convert_to_long_ex(arg);
 1026: 	result = _php_math_longtobase(*arg, 2);
 1027: 	RETURN_STRING(result, 0);
 1028: }
 1029: /* }}} */
 1030: 
 1031: /* {{{ proto string decoct(int decimal_number)
 1032:    Returns a string containing an octal representation of the given number */
 1033: PHP_FUNCTION(decoct)
 1034: {
 1035: 	zval **arg;
 1036: 	char *result;
 1037: 
 1038: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
 1039: 		return;
 1040: 	}
 1041: 	convert_to_long_ex(arg);
 1042: 	result = _php_math_longtobase(*arg, 8);
 1043: 	RETURN_STRING(result, 0);
 1044: }
 1045: /* }}} */
 1046: 
 1047: /* {{{ proto string dechex(int decimal_number)
 1048:    Returns a string containing a hexadecimal representation of the given number */
 1049: PHP_FUNCTION(dechex)
 1050: {
 1051: 	zval **arg;
 1052: 	char *result;
 1053: 
 1054: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
 1055: 		return;
 1056: 	}
 1057: 	convert_to_long_ex(arg);
 1058: 	result = _php_math_longtobase(*arg, 16);
 1059: 	RETURN_STRING(result, 0);
 1060: }
 1061: /* }}} */
 1062: 
 1063: /* {{{ proto string base_convert(string number, int frombase, int tobase)
 1064:    Converts a number in a string from any base <= 36 to any base <= 36 */
 1065: PHP_FUNCTION(base_convert)
 1066: {
 1067: 	zval **number, temp;
 1068: 	long frombase, tobase;
 1069: 	char *result;
 1070: 
 1071: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zll", &number, &frombase, &tobase) == FAILURE) {
 1072: 		return;
 1073: 	}
 1074: 	convert_to_string_ex(number);
 1075: 	
 1076: 	if (frombase < 2 || frombase > 36) {
 1077: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid `from base' (%ld)", frombase);
 1078: 		RETURN_FALSE;
 1079: 	}
 1080: 	if (tobase < 2 || tobase > 36) {
 1081: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid `to base' (%ld)", tobase);
 1082: 		RETURN_FALSE;
 1083: 	}
 1084: 
 1085: 	if(_php_math_basetozval(*number, frombase, &temp) == FAILURE) {
 1086: 		RETURN_FALSE;
 1087: 	}
 1088: 	result = _php_math_zvaltobase(&temp, tobase TSRMLS_CC);
 1089: 	RETVAL_STRING(result, 0);
 1090: } 
 1091: /* }}} */
 1092: 
 1093: /* {{{ _php_math_number_format 
 1094: */
 1095: PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char thousand_sep)
 1096: {
 1097: 	return _php_math_number_format_ex(d, dec, &dec_point, 1, &thousand_sep, 1);
 1098: }
 1099: 
 1100: PHPAPI char *_php_math_number_format_ex(double d, int dec, char *dec_point, size_t dec_point_len, char *thousand_sep, size_t thousand_sep_len)
 1101: {
 1102: 	char *tmpbuf = NULL, *resbuf;
 1103: 	char *s, *t;  /* source, target */
 1104: 	char *dp;
 1105: 	int integral;
 1106: 	int tmplen, reslen=0;
 1107: 	int count=0;
 1108: 	int is_negative=0;
 1109: 
 1110: 	if (d < 0) {
 1111: 		is_negative = 1;
 1112: 		d = -d;
 1113: 	}
 1114: 
 1115: 	dec = MAX(0, dec);
 1116: 	d = _php_math_round(d, dec, PHP_ROUND_HALF_UP);
 1117: 
 1118: 	tmplen = spprintf(&tmpbuf, 0, "%.*F", dec, d);
 1119: 
 1120: 	if (tmpbuf == NULL || !isdigit((int)tmpbuf[0])) {
 1121: 		return tmpbuf;
 1122: 	}
 1123: 
 1124: 	/* find decimal point, if expected */
 1125: 	if (dec) {
 1126: 		dp = strpbrk(tmpbuf, ".,");
 1127: 	} else {
 1128: 		dp = NULL;
 1129: 	}
 1130: 
 1131: 	/* calculate the length of the return buffer */
 1132: 	if (dp) {
 1133: 		integral = dp - tmpbuf;
 1134: 	} else {
 1135: 		/* no decimal point was found */
 1136: 		integral = tmplen;
 1137: 	}
 1138: 
 1139: 	/* allow for thousand separators */
 1140: 	if (thousand_sep) {
 1141: 		integral += thousand_sep_len * ((integral-1) / 3);
 1142: 	}
 1143: 	
 1144: 	reslen = integral;
 1145: 	
 1146: 	if (dec) {
 1147: 		reslen += dec;
 1148: 
 1149: 		if (dec_point) {
 1150: 			reslen += dec_point_len;
 1151: 		}
 1152: 	}
 1153: 
 1154: 	/* add a byte for minus sign */
 1155: 	if (is_negative) {
 1156: 		reslen++;
 1157: 	}
 1158: 	resbuf = (char *) emalloc(reslen+1); /* +1 for NUL terminator */
 1159: 
 1160: 	s = tmpbuf+tmplen-1;
 1161: 	t = resbuf+reslen;
 1162: 	*t-- = '\0';
 1163: 
 1164: 	/* copy the decimal places.
 1165: 	 * Take care, as the sprintf implementation may return less places than
 1166: 	 * we requested due to internal buffer limitations */
 1167: 	if (dec) {
 1168: 		int declen = dp ? s - dp : 0;
 1169: 		int topad = dec > declen ? dec - declen : 0;
 1170: 
 1171: 		/* pad with '0's */
 1172: 		while (topad--) {
 1173: 			*t-- = '0';
 1174: 		}
 1175: 		
 1176: 		if (dp) {
 1177: 			s -= declen + 1; /* +1 to skip the point */
 1178: 			t -= declen;
 1179: 
 1180: 			/* now copy the chars after the point */
 1181: 			memcpy(t + 1, dp + 1, declen);
 1182: 		}
 1183: 
 1184: 		/* add decimal point */
 1185: 		if (dec_point) {
 1186: 			t -= dec_point_len;
 1187: 			memcpy(t + 1, dec_point, dec_point_len);
 1188: 		}
 1189: 	}
 1190: 
 1191: 	/* copy the numbers before the decimal point, adding thousand
 1192: 	 * separator every three digits */
 1193: 	while(s >= tmpbuf) {
 1194: 		*t-- = *s--;
 1195: 		if (thousand_sep && (++count%3)==0 && s>=tmpbuf) {
 1196: 			t -= thousand_sep_len;
 1197: 			memcpy(t + 1, thousand_sep, thousand_sep_len);
 1198: 		}
 1199: 	}
 1200: 
 1201: 	/* and a minus sign, if needed */
 1202: 	if (is_negative) {
 1203: 		*t-- = '-';
 1204: 	}
 1205: 
 1206: 	efree(tmpbuf);
 1207: 	
 1208: 	return resbuf;
 1209: }
 1210: /* }}} */
 1211: 
 1212: /* {{{ proto string number_format(float number [, int num_decimal_places [, string dec_seperator, string thousands_seperator]])
 1213:    Formats a number with grouped thousands */
 1214: PHP_FUNCTION(number_format)
 1215: {
 1216: 	double num;
 1217: 	long dec = 0;
 1218: 	char *thousand_sep = NULL, *dec_point = NULL;
 1219: 	char thousand_sep_chr = ',', dec_point_chr = '.';
 1220: 	int thousand_sep_len = 0, dec_point_len = 0;
 1221: 	
 1222: 	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) {
 1223: 		return;
 1224: 	}
 1225: 
 1226: 	switch(ZEND_NUM_ARGS()) {
 1227: 	case 1:
 1228: 		RETURN_STRING(_php_math_number_format(num, 0, dec_point_chr, thousand_sep_chr), 0);
 1229: 		break;
 1230: 	case 2:
 1231: 		RETURN_STRING(_php_math_number_format(num, dec, dec_point_chr, thousand_sep_chr), 0);
 1232: 		break;
 1233: 	case 4:
 1234: 		if (dec_point == NULL) {
 1235: 			dec_point = &dec_point_chr;
 1236: 			dec_point_len = 1;
 1237: 		}
 1238: 
 1239: 		if (thousand_sep == NULL) {
 1240: 			thousand_sep = &thousand_sep_chr;
 1241: 			thousand_sep_len = 1;
 1242: 		}
 1243: 
 1244: 		RETURN_STRING(_php_math_number_format_ex(num, dec, dec_point, dec_point_len, thousand_sep, thousand_sep_len), 0);
 1245: 		break;
 1246: 	default:
 1247: 		WRONG_PARAM_COUNT;
 1248: 		break;
 1249: 	}
 1250: }
 1251: /* }}} */
 1252: 
 1253: /* {{{ proto float fmod(float x, float y)
 1254:    Returns the remainder of dividing x by y as a float */
 1255: PHP_FUNCTION(fmod)
 1256: {
 1257: 	double num1, num2;
 1258: 
 1259: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd",  &num1, &num2) == FAILURE) {
 1260: 		return;
 1261: 	}
 1262: 	RETURN_DOUBLE(fmod(num1, num2));
 1263: }
 1264: /* }}} */
 1265: 
 1266: 
 1267: 
 1268: /*
 1269:  * Local variables:
 1270:  * tab-width: 4
 1271:  * c-basic-offset: 4
 1272:  * End:
 1273:  * vim600: fdm=marker
 1274:  * vim: noet sw=4 ts=4
 1275:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>