OSDN Git Service

libjava/classpath/
[pf3gnuchains/gcc-fork.git] / libjava / classpath / native / fdlibm / e_remainder.c
1
2 /* @(#)e_remainder.c 1.3 95/01/18 */
3 /*
4  * ====================================================
5  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
6  *
7  * Developed at SunSoft, a Sun Microsystems, Inc. business.
8  * Permission to use, copy, modify, and distribute this
9  * software is freely granted, provided that this notice 
10  * is preserved.
11  * ====================================================
12  */
13
14 /* __ieee754_remainder(x,p)
15  * Return :                  
16  *      returns  x REM p  =  x - [x/p]*p as if in infinite 
17  *      precise arithmetic, where [x/p] is the (infinite bit) 
18  *      integer nearest x/p (in half way case choose the even one).
19  * Method : 
20  *      Based on fmod() return x-[x/p]chopped*p exactlp.
21  */
22
23 #include "fdlibm.h"
24
25 #ifndef _DOUBLE_IS_32BITS
26
27 #ifdef __STDC__
28 static const double zero = 0.0;
29 #else
30 static double zero = 0.0;
31 #endif
32
33
34 #ifdef __STDC__
35         double __ieee754_remainder(double x, double p)
36 #else
37         double __ieee754_remainder(x,p)
38         double x,p;
39 #endif
40 {
41         int32_t hx,hp;
42         uint32_t sx,lx,lp;
43         double p_half;
44
45         EXTRACT_WORDS(hx,lx,x);
46         EXTRACT_WORDS(hp,lp,p);
47         sx = hx&0x80000000;
48         hp &= 0x7fffffff;
49         hx &= 0x7fffffff;
50
51     /* purge off exception values */
52         if((hp|lp)==0) return (x*p)/(x*p);      /* p = 0 */
53         if((hx>=0x7ff00000)||                   /* x not finite */
54           ((hp>=0x7ff00000)&&                   /* p is NaN */
55           (((hp-0x7ff00000)|lp)!=0)))
56             return (x*p)/(x*p);
57
58
59         if (hp<=0x7fdfffff) x = __ieee754_fmod(x,p+p);  /* now x < 2p */
60         if (((hx-hp)|(lx-lp))==0) return zero*x;
61         x  = fabs(x);
62         p  = fabs(p);
63         if (hp<0x00200000) {
64             if(x+x>p) {
65                 x-=p;
66                 if(x+x>=p) x -= p;
67             }
68         } else {
69             p_half = 0.5*p;
70             if(x>p_half) {
71                 x-=p;
72                 if(x>=p_half) x -= p;
73             }
74         }
75         GET_HIGH_WORD(hx,x);
76         SET_HIGH_WORD(x,hx ^ sx);
77         return x;
78 }
79 #endif /* defined(_DOUBLE_IS_32BITS) */