ID:               15811
 Updated by:       [EMAIL PROTECTED]
 Reported By:      [EMAIL PROTECTED]
 Status:           Closed
 Bug Type:         *Math Functions
 Operating System: linux redhat
 PHP Version:      4.1.2
 New Comment:

this function was rewritten completely in the 4.2/HEAD branch. (it's
now about eight times shorter, and actually correct.)


Previous Comments:
------------------------------------------------------------------------

[2002-03-01 14:28:50] [EMAIL PROTECTED]

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 10:25:19] [EMAIL PROTECTED]

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 10:23:27] [EMAIL PROTECTED]

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. 

------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=15811&edit=1

Reply via email to