f936a72de78c3d5796d4c664206ebc1babc708c4
[platform/upstream/glibc.git] / sysdeps / ieee754 / dbl-64 / e_pow.c
1 /*
2  * IBM Accurate Mathematical Library
3  * written by International Business Machines Corp.
4  * Copyright (C) 2001-2012 Free Software Foundation
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19 /***************************************************************************/
20 /*  MODULE_NAME: upow.c                                                    */
21 /*                                                                         */
22 /*  FUNCTIONS: upow                                                        */
23 /*             power1                                                      */
24 /*             my_log2                                                     */
25 /*             log1                                                        */
26 /*             checkint                                                    */
27 /* FILES NEEDED: dla.h endian.h mpa.h mydefs.h                             */
28 /*               halfulp.c mpexp.c mplog.c slowexp.c slowpow.c mpa.c       */
29 /*                          uexp.c  upow.c                                 */
30 /*               root.tbl uexp.tbl upow.tbl                                */
31 /* An ultimate power routine. Given two IEEE double machine numbers y,x    */
32 /* it computes the correctly rounded (to nearest) value of x^y.            */
33 /* Assumption: Machine arithmetic operations are performed in              */
34 /* round to nearest mode of IEEE 754 standard.                             */
35 /*                                                                         */
36 /***************************************************************************/
37 #include "endian.h"
38 #include "upow.h"
39 #include <dla.h>
40 #include "mydefs.h"
41 #include "MathLib.h"
42 #include "upow.tbl"
43 #include <math_private.h>
44 #include <fenv.h>
45
46 #ifndef SECTION
47 # define SECTION
48 #endif
49
50
51 double __exp1(double x, double xx, double error);
52 static double log1(double x, double *delta, double *error);
53 static double my_log2(double x, double *delta, double *error);
54 double __slowpow(double x, double y,double z);
55 static double power1(double x, double y);
56 static int checkint(double x);
57
58 /***************************************************************************/
59 /* An ultimate power routine. Given two IEEE double machine numbers y,x    */
60 /* it computes the correctly rounded (to nearest) value of X^y.            */
61 /***************************************************************************/
62 double
63 SECTION
64 __ieee754_pow(double x, double y) {
65   double z,a,aa,error, t,a1,a2,y1,y2;
66 #if 0
67   double gor=1.0;
68 #endif
69   mynumber u,v;
70   int k;
71   int4 qx,qy;
72   v.x=y;
73   u.x=x;
74   if (v.i[LOW_HALF] == 0) { /* of y */
75     qx = u.i[HIGH_HALF]&0x7fffffff;
76     /* Checking  if x is not too small to compute */
77     if (((qx==0x7ff00000)&&(u.i[LOW_HALF]!=0))||(qx>0x7ff00000)) return NaNQ.x;
78     if (y == 1.0) return x;
79     if (y == 2.0) return x*x;
80     if (y == -1.0) return 1.0/x;
81     if (y == 0) return 1.0;
82   }
83   /* else */
84   if(((u.i[HIGH_HALF]>0 && u.i[HIGH_HALF]<0x7ff00000)||        /* x>0 and not x->0 */
85        (u.i[HIGH_HALF]==0 && u.i[LOW_HALF]!=0))  &&
86                                       /*   2^-1023< x<= 2^-1023 * 0x1.0000ffffffff */
87       (v.i[HIGH_HALF]&0x7fffffff) < 0x4ff00000) {              /* if y<-1 or y>1   */
88     double retval;
89
90     SET_RESTORE_ROUND (FE_TONEAREST);
91
92     z = log1(x,&aa,&error);                                 /* x^y  =e^(y log (X)) */
93     t = y*134217729.0;
94     y1 = t - (t-y);
95     y2 = y - y1;
96     t = z*134217729.0;
97     a1 = t - (t-z);
98     a2 = (z - a1)+aa;
99     a = y1*a1;
100     aa = y2*a1 + y*a2;
101     a1 = a+aa;
102     a2 = (a-a1)+aa;
103     error = error*ABS(y);
104     t = __exp1(a1,a2,1.9e16*error);     /* return -10 or 0 if wasn't computed exactly */
105     retval = (t>0)?t:power1(x,y);
106
107     return retval;
108   }
109
110   if (x == 0) {
111     if (((v.i[HIGH_HALF] & 0x7fffffff) == 0x7ff00000 && v.i[LOW_HALF] != 0)
112         || (v.i[HIGH_HALF] & 0x7fffffff) > 0x7ff00000)
113       return y;
114     if (ABS(y) > 1.0e20) return (y>0)?0:INF.x;
115     k = checkint(y);
116     if (k == -1)
117       return y < 0 ? 1.0/x : x;
118     else
119       return y < 0 ? 1.0/ABS(x) : 0.0;                               /* return 0 */
120   }
121
122   qx = u.i[HIGH_HALF]&0x7fffffff;  /*   no sign   */
123   qy = v.i[HIGH_HALF]&0x7fffffff;  /*   no sign   */
124
125   if (qx >= 0x7ff00000 && (qx > 0x7ff00000 || u.i[LOW_HALF] != 0)) return NaNQ.x;
126   if (qy >= 0x7ff00000 && (qy > 0x7ff00000 || v.i[LOW_HALF] != 0))
127     return x == 1.0 ? 1.0 : NaNQ.x;
128
129   /* if x<0 */
130   if (u.i[HIGH_HALF] < 0) {
131     k = checkint(y);
132     if (k==0) {
133       if (qy == 0x7ff00000) {
134         if (x == -1.0) return 1.0;
135         else if (x > -1.0) return v.i[HIGH_HALF] < 0 ? INF.x : 0.0;
136         else return v.i[HIGH_HALF] < 0 ? 0.0 : INF.x;
137       }
138       else if (qx == 0x7ff00000)
139         return y < 0 ? 0.0 : INF.x;
140       return NaNQ.x;                              /* y not integer and x<0 */
141     }
142     else if (qx == 0x7ff00000)
143       {
144         if (k < 0)
145           return y < 0 ? nZERO.x : nINF.x;
146         else
147           return y < 0 ? 0.0 : INF.x;
148       }
149     return (k==1)?__ieee754_pow(-x,y):-__ieee754_pow(-x,y); /* if y even or odd */
150   }
151   /* x>0 */
152
153   if (qx == 0x7ff00000)                              /* x= 2^-0x3ff */
154     {if (y == 0) return NaNQ.x;
155     return (y>0)?x:0; }
156
157   if (qy > 0x45f00000 && qy < 0x7ff00000) {
158     if (x == 1.0) return 1.0;
159     if (y>0) return (x>1.0)?INF.x:0;
160     if (y<0) return (x<1.0)?INF.x:0;
161   }
162
163   if (x == 1.0) return 1.0;
164   if (y>0) return (x>1.0)?INF.x:0;
165   if (y<0) return (x<1.0)?INF.x:0;
166   return 0;     /* unreachable, to make the compiler happy */
167 }
168 #ifndef __ieee754_pow
169 strong_alias (__ieee754_pow, __pow_finite)
170 #endif
171
172 /**************************************************************************/
173 /* Computing x^y using more accurate but more slow log routine            */
174 /**************************************************************************/
175 static double
176 SECTION
177 power1(double x, double y) {
178   double z,a,aa,error, t,a1,a2,y1,y2;
179   z = my_log2(x,&aa,&error);
180   t = y*134217729.0;
181   y1 = t - (t-y);
182   y2 = y - y1;
183   t = z*134217729.0;
184   a1 = t - (t-z);
185   a2 = z - a1;
186   a = y*z;
187   aa = ((y1*a1-a)+y1*a2+y2*a1)+y2*a2+aa*y;
188   a1 = a+aa;
189   a2 = (a-a1)+aa;
190   error = error*ABS(y);
191   t = __exp1(a1,a2,1.9e16*error);
192   return (t >= 0)?t:__slowpow(x,y,z);
193 }
194
195 /****************************************************************************/
196 /* Computing log(x) (x is left argument). The result is the returned double */
197 /* + the parameter delta.                                                   */
198 /* The result is bounded by error (rightmost argument)                      */
199 /****************************************************************************/
200 static double
201 SECTION
202 log1(double x, double *delta, double *error) {
203   int i,j,m;
204 #if 0
205   int n;
206 #endif
207   double uu,vv,eps,nx,e,e1,e2,t,t1,t2,res,add=0;
208 #if 0
209   double cor;
210 #endif
211   mynumber u,v;
212 #ifdef BIG_ENDI
213   mynumber
214 /**/ two52          = {{0x43300000, 0x00000000}}; /* 2**52         */
215 #else
216 #ifdef LITTLE_ENDI
217   mynumber
218 /**/ two52          = {{0x00000000, 0x43300000}}; /* 2**52         */
219 #endif
220 #endif
221
222   u.x = x;
223   m = u.i[HIGH_HALF];
224   *error = 0;
225   *delta = 0;
226   if (m < 0x00100000)             /*  1<x<2^-1007 */
227     { x = x*t52.x; add = -52.0; u.x = x; m = u.i[HIGH_HALF];}
228
229   if ((m&0x000fffff) < 0x0006a09e)
230     {u.i[HIGH_HALF] = (m&0x000fffff)|0x3ff00000; two52.i[LOW_HALF]=(m>>20); }
231   else
232     {u.i[HIGH_HALF] = (m&0x000fffff)|0x3fe00000; two52.i[LOW_HALF]=(m>>20)+1; }
233
234   v.x = u.x + bigu.x;
235   uu = v.x - bigu.x;
236   i = (v.i[LOW_HALF]&0x000003ff)<<2;
237   if (two52.i[LOW_HALF] == 1023)         /* nx = 0              */
238   {
239       if (i > 1192 && i < 1208)          /* |x-1| < 1.5*2**-10  */
240       {
241           t = x - 1.0;
242           t1 = (t+5.0e6)-5.0e6;
243           t2 = t-t1;
244           e1 = t - 0.5*t1*t1;
245           e2 = t*t*t*(r3+t*(r4+t*(r5+t*(r6+t*(r7+t*r8)))))-0.5*t2*(t+t1);
246           res = e1+e2;
247           *error = 1.0e-21*ABS(t);
248           *delta = (e1-res)+e2;
249           return res;
250       }                  /* |x-1| < 1.5*2**-10  */
251       else
252       {
253           v.x = u.x*(ui.x[i]+ui.x[i+1])+bigv.x;
254           vv = v.x-bigv.x;
255           j = v.i[LOW_HALF]&0x0007ffff;
256           j = j+j+j;
257           eps = u.x - uu*vv;
258           e1 = eps*ui.x[i];
259           e2 = eps*(ui.x[i+1]+vj.x[j]*(ui.x[i]+ui.x[i+1]));
260           e = e1+e2;
261           e2 =  ((e1-e)+e2);
262           t=ui.x[i+2]+vj.x[j+1];
263           t1 = t+e;
264           t2 = (((t-t1)+e)+(ui.x[i+3]+vj.x[j+2]))+e2+e*e*(p2+e*(p3+e*p4));
265           res=t1+t2;
266           *error = 1.0e-24;
267           *delta = (t1-res)+t2;
268           return res;
269       }
270   }   /* nx = 0 */
271   else                            /* nx != 0   */
272   {
273       eps = u.x - uu;
274       nx = (two52.x - two52e.x)+add;
275       e1 = eps*ui.x[i];
276       e2 = eps*ui.x[i+1];
277       e=e1+e2;
278       e2 = (e1-e)+e2;
279       t=nx*ln2a.x+ui.x[i+2];
280       t1=t+e;
281       t2=(((t-t1)+e)+nx*ln2b.x+ui.x[i+3]+e2)+e*e*(q2+e*(q3+e*(q4+e*(q5+e*q6))));
282       res = t1+t2;
283       *error = 1.0e-21;
284       *delta = (t1-res)+t2;
285       return res;
286   }                                /* nx != 0   */
287 }
288
289 /****************************************************************************/
290 /* More slow but more accurate routine of log                               */
291 /* Computing log(x)(x is left argument).The result is return double + delta.*/
292 /* The result is bounded by error (right argument)                           */
293 /****************************************************************************/
294 static double
295 SECTION
296 my_log2(double x, double *delta, double *error) {
297   int i,j,m;
298 #if 0
299   int n;
300 #endif
301   double uu,vv,eps,nx,e,e1,e2,t,t1,t2,res,add=0;
302 #if 0
303   double cor;
304 #endif
305   double ou1,ou2,lu1,lu2,ov,lv1,lv2,a,a1,a2;
306   double y,yy,z,zz,j1,j2,j7,j8;
307 #ifndef DLA_FMS
308   double j3,j4,j5,j6;
309 #endif
310   mynumber u,v;
311 #ifdef BIG_ENDI
312   mynumber
313 /**/ two52          = {{0x43300000, 0x00000000}}; /* 2**52         */
314 #else
315 #ifdef LITTLE_ENDI
316   mynumber
317 /**/ two52          = {{0x00000000, 0x43300000}}; /* 2**52         */
318 #endif
319 #endif
320
321   u.x = x;
322   m = u.i[HIGH_HALF];
323   *error = 0;
324   *delta = 0;
325   add=0;
326   if (m<0x00100000) {  /* x < 2^-1022 */
327     x = x*t52.x;  add = -52.0; u.x = x; m = u.i[HIGH_HALF]; }
328
329   if ((m&0x000fffff) < 0x0006a09e)
330     {u.i[HIGH_HALF] = (m&0x000fffff)|0x3ff00000; two52.i[LOW_HALF]=(m>>20); }
331   else
332     {u.i[HIGH_HALF] = (m&0x000fffff)|0x3fe00000; two52.i[LOW_HALF]=(m>>20)+1; }
333
334   v.x = u.x + bigu.x;
335   uu = v.x - bigu.x;
336   i = (v.i[LOW_HALF]&0x000003ff)<<2;
337   /*------------------------------------- |x-1| < 2**-11-------------------------------  */
338   if ((two52.i[LOW_HALF] == 1023)  && (i == 1200))
339   {
340       t = x - 1.0;
341       EMULV(t,s3,y,yy,j1,j2,j3,j4,j5);
342       ADD2(-0.5,0,y,yy,z,zz,j1,j2);
343       MUL2(t,0,z,zz,y,yy,j1,j2,j3,j4,j5,j6,j7,j8);
344       MUL2(t,0,y,yy,z,zz,j1,j2,j3,j4,j5,j6,j7,j8);
345
346       e1 = t+z;
347       e2 = (((t-e1)+z)+zz)+t*t*t*(ss3+t*(s4+t*(s5+t*(s6+t*(s7+t*s8)))));
348       res = e1+e2;
349       *error = 1.0e-25*ABS(t);
350       *delta = (e1-res)+e2;
351       return res;
352   }
353   /*----------------------------- |x-1| > 2**-11  --------------------------  */
354   else
355   {          /*Computing log(x) according to log table                        */
356       nx = (two52.x - two52e.x)+add;
357       ou1 = ui.x[i];
358       ou2 = ui.x[i+1];
359       lu1 = ui.x[i+2];
360       lu2 = ui.x[i+3];
361       v.x = u.x*(ou1+ou2)+bigv.x;
362       vv = v.x-bigv.x;
363       j = v.i[LOW_HALF]&0x0007ffff;
364       j = j+j+j;
365       eps = u.x - uu*vv;
366       ov  = vj.x[j];
367       lv1 = vj.x[j+1];
368       lv2 = vj.x[j+2];
369       a = (ou1+ou2)*(1.0+ov);
370       a1 = (a+1.0e10)-1.0e10;
371       a2 = a*(1.0-a1*uu*vv);
372       e1 = eps*a1;
373       e2 = eps*a2;
374       e = e1+e2;
375       e2 = (e1-e)+e2;
376       t=nx*ln2a.x+lu1+lv1;
377       t1 = t+e;
378       t2 = (((t-t1)+e)+(lu2+lv2+nx*ln2b.x+e2))+e*e*(p2+e*(p3+e*p4));
379       res=t1+t2;
380       *error = 1.0e-27;
381       *delta = (t1-res)+t2;
382       return res;
383   }
384 }
385
386 /**********************************************************************/
387 /* Routine receives a double x and checks if it is an integer. If not */
388 /* it returns 0, else it returns 1 if even or -1 if odd.              */
389 /**********************************************************************/
390 static int
391 SECTION
392 checkint(double x) {
393   union {int4 i[2]; double x;} u;
394   int k,m,n;
395 #if 0
396   int l;
397 #endif
398   u.x = x;
399   m = u.i[HIGH_HALF]&0x7fffffff;    /* no sign */
400   if (m >= 0x7ff00000) return 0;    /*  x is +/-inf or NaN  */
401   if (m >= 0x43400000) return 1;    /*  |x| >= 2**53   */
402   if (m < 0x40000000) return 0;     /* |x| < 2,  can not be 0 or 1  */
403   n = u.i[LOW_HALF];
404   k = (m>>20)-1023;                 /*  1 <= k <= 52   */
405   if (k == 52) return (n&1)? -1:1;  /* odd or even*/
406   if (k>20) {
407     if (n<<(k-20)) return 0;        /* if not integer */
408     return (n<<(k-21))?-1:1;
409   }
410   if (n) return 0;                  /*if  not integer*/
411   if (k == 20) return (m&1)? -1:1;
412   if (m<<(k+12)) return 0;
413   return (m<<(k+11))?-1:1;
414 }