php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #15811 pow() in 4.1.2
Submitted: 2002-03-01 10:23 UTC Modified: 2002-03-01 15:42 UTC
From: jbriss at utk dot edu Assigned:
Status: Closed Package: *Math Functions
PHP Version: 4.1.2 OS: linux redhat
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: jbriss at utk dot edu
New email:
PHP Version: OS:

 

 [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. 

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2002-03-01 10:25 UTC] derick@php.net
It's fixed for 4.2.0 already:

[derick@kossu dev]$ php
<?php
echo pow (0, 80);
?>
X-Powered-By: PHP/4.2.0-dev
Content-type: text/html

0



Derick
 [2002-03-01 14:28 UTC] jbriss at utk dot edu
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 */
	}
}
 [2002-03-01 15:42 UTC] jimw@php.net
this function was rewritten completely in the 4.2/HEAD branch. (it's now about eight times shorter, and actually correct.)
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Dec 12 16:01:27 2024 UTC