13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier
43e12c5d1SDavid du Colombier double
pow(double x,double y)53e12c5d1SDavid du Colombier pow(double x, double y) /* return x ^ y (exponentiation) */
63e12c5d1SDavid du Colombier {
73e12c5d1SDavid du Colombier double xy, y1, ye;
83e12c5d1SDavid du Colombier long i;
93e12c5d1SDavid du Colombier int ex, ey, flip;
103e12c5d1SDavid du Colombier
113e12c5d1SDavid du Colombier if(y == 0.0)
123e12c5d1SDavid du Colombier return 1.0;
133e12c5d1SDavid du Colombier
14*678a9e3dSDavid du Colombier /* prevent infinite loop */
15*678a9e3dSDavid du Colombier if(isNaN(x) || isNaN(y))
16*678a9e3dSDavid du Colombier return NaN();
17*678a9e3dSDavid du Colombier if(isInf(x, 0))
18*678a9e3dSDavid du Colombier return x;
19*678a9e3dSDavid du Colombier if(isInf(y, 0))
20*678a9e3dSDavid du Colombier return x == 0 || x == 1? x: y;
21*678a9e3dSDavid du Colombier
223e12c5d1SDavid du Colombier flip = 0;
233e12c5d1SDavid du Colombier if(y < 0.){
243e12c5d1SDavid du Colombier y = -y;
253e12c5d1SDavid du Colombier flip = 1;
263e12c5d1SDavid du Colombier }
273e12c5d1SDavid du Colombier y1 = modf(y, &ye);
283e12c5d1SDavid du Colombier if(y1 != 0.0){
293e12c5d1SDavid du Colombier if(x <= 0.)
303e12c5d1SDavid du Colombier goto zreturn;
313e12c5d1SDavid du Colombier if(y1 > 0.5) {
323e12c5d1SDavid du Colombier y1 -= 1.;
333e12c5d1SDavid du Colombier ye += 1.;
343e12c5d1SDavid du Colombier }
353e12c5d1SDavid du Colombier xy = exp(y1 * log(x));
363e12c5d1SDavid du Colombier }else
373e12c5d1SDavid du Colombier xy = 1.0;
383e12c5d1SDavid du Colombier if(ye > 0x7FFFFFFF){ /* should be ~0UL but compiler can't convert double to ulong */
393e12c5d1SDavid du Colombier if(x <= 0.){
403e12c5d1SDavid du Colombier zreturn:
413e12c5d1SDavid du Colombier if(x==0. && !flip)
423e12c5d1SDavid du Colombier return 0.;
433e12c5d1SDavid du Colombier return NaN();
443e12c5d1SDavid du Colombier }
453e12c5d1SDavid du Colombier if(flip){
463e12c5d1SDavid du Colombier if(y == .5)
473e12c5d1SDavid du Colombier return 1./sqrt(x);
483e12c5d1SDavid du Colombier y = -y;
493e12c5d1SDavid du Colombier }else if(y == .5)
503e12c5d1SDavid du Colombier return sqrt(x);
513e12c5d1SDavid du Colombier return exp(y * log(x));
523e12c5d1SDavid du Colombier }
533e12c5d1SDavid du Colombier x = frexp(x, &ex);
543e12c5d1SDavid du Colombier ey = 0;
553e12c5d1SDavid du Colombier i = ye;
563e12c5d1SDavid du Colombier if(i)
573e12c5d1SDavid du Colombier for(;;){
583e12c5d1SDavid du Colombier if(i & 1){
593e12c5d1SDavid du Colombier xy *= x;
603e12c5d1SDavid du Colombier ey += ex;
613e12c5d1SDavid du Colombier }
623e12c5d1SDavid du Colombier i >>= 1;
633e12c5d1SDavid du Colombier if(i == 0)
643e12c5d1SDavid du Colombier break;
653e12c5d1SDavid du Colombier x *= x;
663e12c5d1SDavid du Colombier ex <<= 1;
673e12c5d1SDavid du Colombier if(x < .5){
683e12c5d1SDavid du Colombier x += x;
693e12c5d1SDavid du Colombier ex -= 1;
703e12c5d1SDavid du Colombier }
713e12c5d1SDavid du Colombier }
723e12c5d1SDavid du Colombier if(flip){
733e12c5d1SDavid du Colombier xy = 1. / xy;
743e12c5d1SDavid du Colombier ey = -ey;
753e12c5d1SDavid du Colombier }
763e12c5d1SDavid du Colombier return ldexp(xy, ey);
773e12c5d1SDavid du Colombier }
78