@@ -316,38 +316,74 @@ float_divmod(v, w)
316316 return mkvalue ("(dd)" , div , mod );
317317}
318318
319+ double powu (x , n )
320+ double x ;
321+ long n ;
322+ {
323+ double r = 1. ;
324+ double p = x ;
325+ long mask = 1 ;
326+ while (mask > 0 && n >= mask ) {
327+ if (n & mask )
328+ r *= p ;
329+ mask <<= 1 ;
330+ p *= p ;
331+ }
332+ return r ;
333+ }
334+
335+ double powi (x , n )
336+ double x ;
337+ long n ;
338+ {
339+ if (n > 10000 || n < -10000 )
340+ return pow (x , (double ) n );
341+ else if (n > 0 )
342+ return powu (x , n );
343+ else
344+ return 1. /powu (x , - n );
345+ }
346+
319347static object *
320348float_pow (v , w , z )
321349 floatobject * v ;
322- floatobject * w ;
350+ object * w ;
323351 floatobject * z ;
324352{
325353 double iv , iw , ix ;
326- iv = v -> ob_fval ;
327- iw = w -> ob_fval ;
354+ long intw ;
328355 /* XXX Doesn't handle overflows if z!=None yet; it may never do so :(
329356 * The z parameter is really only going to be useful for integers and
330357 * long integers. Maybe something clever with logarithms could be done.
331358 * [AMK]
332359 */
333- /* Sort out special cases here instead of relying on pow() */
334- if (iw == 0.0 ) { /* x**0 is 1, even 0**0 */
335- if ((object * )z != None ) {
336- ix = fmod (1.0 , z -> ob_fval );
337- if (ix != 0 && z -> ob_fval < 0 ) ix += z -> ob_fval ;
338- }
339- else ix = 1.0 ;
340- return newfloatobject (ix );
360+ iv = v -> ob_fval ;
361+ iw = ((floatobject * )w )-> ob_fval ;
362+ intw = (long )iw ;
363+ if (iw == intw ) {
364+ errno = 0 ;
365+ ix = powi (iv , intw );
341366 }
342- if (iv == 0.0 ) {
343- if (iw < 0.0 ) {
344- err_setstr (ValueError , "0.0 to a negative power" );
345- return NULL ;
367+ else {
368+ /* Sort out special cases here instead of relying on pow() */
369+ if (iw == 0.0 ) { /* x**0 is 1, even 0**0 */
370+ if ((object * )z != None ) {
371+ ix = fmod (1.0 , z -> ob_fval );
372+ if (ix != 0 && z -> ob_fval < 0 ) ix += z -> ob_fval ;
373+ }
374+ else ix = 1.0 ;
375+ return newfloatobject (ix );
376+ }
377+ if (iv == 0.0 ) {
378+ if (iw < 0.0 ) {
379+ err_setstr (ValueError , "0.0 to a negative power" );
380+ return NULL ;
381+ }
382+ return newfloatobject (0.0 );
346383 }
347- return newfloatobject (0.0 );
384+ errno = 0 ;
385+ ix = pow (iv , iw );
348386 }
349- errno = 0 ;
350- ix = pow (iv , iw );
351387 CHECK (ix );
352388 if (errno != 0 ) {
353389 /* XXX could it be another type of error? */
0 commit comments