|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2002-03-01 10:23 UTC] jbriss at utk dot edu
function pow() in version 4.0.6 function pow(0,x),x!=0 always returns 0. in version 4.1.2 function pow(0,x) x!=0 always returns nan, i think that is not correct. PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Oct 24 19:00:01 2025 UTC |
i looked little bit to your function pow (in math.c) and added some comments make sure you fixed it also for exponent type double. PHP_FUNCTION(pow) { /* FIXME: What is our policy on float-overflow? With pow, it's * extremely easy to request results that won't fit in any double. */ zval **zbase, **zexp; long lbase, lexp; double dval; if (ZEND_NUM_ARGS() != 2) { WRONG_PARAM_COUNT; } zend_get_parameters_ex(ZEND_NUM_ARGS(), &zbase, &zexp); convert_scalar_to_number_ex(zbase); convert_scalar_to_number_ex(zexp); if ((Z_TYPE_PP(zbase) != IS_LONG && Z_TYPE_PP(zbase) != IS_DOUBLE) || (Z_TYPE_PP(zexp ) != IS_LONG && Z_TYPE_PP(zexp ) != IS_DOUBLE)) { php_error(E_WARNING, "Invalid argument(s) passed to pow()"); RETURN_FALSE; } if (Z_TYPE_PP(zexp) == IS_DOUBLE) { /* pow(?, float), this is the ^^ case */ convert_to_double_ex(zbase); if (Z_DVAL_PP(zbase) < 0.0) { /* Note that with the old behaviour, php pow() returned bogus results. Try pow(-1, 2.5) in PHP <= 4.0.6 ... */ php_error(E_WARNING, "Trying to raise a nonpositive value to a broken power"); RETURN_FALSE; } /* !!!!!!!!!!!!!!!!!!!! Here you are missing part of the code */ RETURN_DOUBLE(exp(log(Z_DVAL_PP(zbase)) * Z_DVAL_PP(zexp))); /* !!!!!!!!!!!!!!!!!!!! It should look like */ if (Z_DVAL_PP(zbase) == 0.0) { if (lexp < 0) { php_error(E_WARNING, "Division by zero: pow(0.0, [negative integer])"); RETURN_FALSE; } else { RETURN_DOUBLE(0.0); } } else { RETURN_DOUBLE(exp(log(Z_DVAL_PP(zbase)) * Z_DVAL_PP(zexp))); } } /* !!!!!!!!!!!!!!!!!!!! This is an end, please look at the end */ /* pow(?, int), this is the ** case */ lexp = Z_LVAL_PP(zexp); if (Z_TYPE_PP(zbase) == IS_DOUBLE) { /* pow(float, int) */ if (lexp == 0) { RETURN_DOUBLE(1.0); } if (Z_DVAL_PP(zbase) > 0.0) { RETURN_DOUBLE(exp(log(Z_DVAL_PP(zbase)) * lexp)); } else if (Z_DVAL_PP(zbase) == 0.0) { if (lexp < 0) { php_error(E_WARNING, "Division by zero: pow(0.0, [negative integer])"); RETURN_FALSE; } else { RETURN_DOUBLE(0.0); } } else { /* lbase < 0.0 */ dval = exp(log(-Z_DVAL_PP(zbase)) * (double)lexp); RETURN_DOUBLE(lexp & 1 ? -dval : dval); } } /* pow(int, int) */ if (lexp == 0) { RETURN_LONG(1); } lbase = Z_LVAL_PP(zbase); /* lexp != 0 */ switch (lbase) { case -1: RETURN_LONG( lexp & 1 ? -1 : 1 ); /* if lexp=odd ... */ case 0: if (lexp < 0) { php_error(E_WARNING, "Division by zero: pow(0, [negative integer])"); RETURN_FALSE; } else { RETURN_LONG(0); } case 1: RETURN_LONG(1); default: /* abs(lbase) > 1 */ dval = exp(log(lbase>0? (double)lbase : -(double)lbase ) * (double) lexp); if (lexp < 0 || dval > (double) LONG_MAX) { /* 1/n ( abs(n) > 1 ) || overflow */ RETURN_DOUBLE(((lexp & 1) && lbase<0) ? -dval : dval); } Z_TYPE_P(return_value) = IS_LONG; Z_LVAL_P(return_value) = 1; /* loop runs at most log(log(LONG_MAX)) times, i.e. ~ 5 */ while (lexp > 0) { if (lexp & 1) /* odd */ Z_LVAL_P(return_value) *= lbase; lexp >>= 1; lbase *= lbase; } /* !!!!!!!!!!!!!!!!!!!! This is nice that you want to return integer when possible, but this is probably the slowest algorithm you could use */ /* return */ } }