Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / lib / msun / src / e_fmodf.c
1 /* e_fmodf.c -- float version of e_fmod.c.
2  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
3  *
4  * $FreeBSD: src/lib/msun/src/e_fmodf.c,v 1.5 1999/08/28 00:06:30 peter Exp $
5  * $DragonFly: src/lib/msun/src/Attic/e_fmodf.c,v 1.2 2003/06/17 04:26:52 dillon Exp $
6  */
7
8 /*
9  * ====================================================
10  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
11  *
12  * Developed at SunPro, a Sun Microsystems, Inc. business.
13  * Permission to use, copy, modify, and distribute this
14  * software is freely granted, provided that this notice
15  * is preserved.
16  * ====================================================
17  */
18
19 /*
20  * __ieee754_fmodf(x,y)
21  * Return x mod y in exact arithmetic
22  * Method: shift and subtract
23  */
24
25 #include "math.h"
26 #include "math_private.h"
27
28 #ifdef __STDC__
29 static const float one = 1.0, Zero[] = {0.0, -0.0,};
30 #else
31 static float one = 1.0, Zero[] = {0.0, -0.0,};
32 #endif
33
34 #ifdef __STDC__
35         float __ieee754_fmodf(float x, float y)
36 #else
37         float __ieee754_fmodf(x,y)
38         float x,y ;
39 #endif
40 {
41         int32_t n,hx,hy,hz,ix,iy,sx,i;
42
43         GET_FLOAT_WORD(hx,x);
44         GET_FLOAT_WORD(hy,y);
45         sx = hx&0x80000000;             /* sign of x */
46         hx ^=sx;                /* |x| */
47         hy &= 0x7fffffff;       /* |y| */
48
49     /* purge off exception values */
50         if(hy==0||(hx>=0x7f800000)||            /* y=0,or x not finite */
51            (hy>0x7f800000))                     /* or y is NaN */
52             return (x*y)/(x*y);
53         if(hx<hy) return x;                     /* |x|<|y| return x */
54         if(hx==hy)
55             return Zero[(u_int32_t)sx>>31];     /* |x|=|y| return x*0*/
56
57     /* determine ix = ilogb(x) */
58         if(hx<0x00800000) {     /* subnormal x */
59             for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1;
60         } else ix = (hx>>23)-127;
61
62     /* determine iy = ilogb(y) */
63         if(hy<0x00800000) {     /* subnormal y */
64             for (iy = -126,i=(hy<<8); i>=0; i<<=1) iy -=1;
65         } else iy = (hy>>23)-127;
66
67     /* set up {hx,lx}, {hy,ly} and align y to x */
68         if(ix >= -126)
69             hx = 0x00800000|(0x007fffff&hx);
70         else {          /* subnormal x, shift x to normal */
71             n = -126-ix;
72             hx = hx<<n;
73         }
74         if(iy >= -126)
75             hy = 0x00800000|(0x007fffff&hy);
76         else {          /* subnormal y, shift y to normal */
77             n = -126-iy;
78             hy = hy<<n;
79         }
80
81     /* fix point fmod */
82         n = ix - iy;
83         while(n--) {
84             hz=hx-hy;
85             if(hz<0){hx = hx+hx;}
86             else {
87                 if(hz==0)               /* return sign(x)*0 */
88                     return Zero[(u_int32_t)sx>>31];
89                 hx = hz+hz;
90             }
91         }
92         hz=hx-hy;
93         if(hz>=0) {hx=hz;}
94
95     /* convert back to floating value and restore the sign */
96         if(hx==0)                       /* return sign(x)*0 */
97             return Zero[(u_int32_t)sx>>31];
98         while(hx<0x00800000) {          /* normalize x */
99             hx = hx+hx;
100             iy -= 1;
101         }
102         if(iy>= -126) {         /* normalize output */
103             hx = ((hx-0x00800000)|((iy+127)<<23));
104             SET_FLOAT_WORD(x,hx|sx);
105         } else {                /* subnormal output */
106             n = -126 - iy;
107             hx >>= n;
108             SET_FLOAT_WORD(x,hx|sx);
109             x *= one;           /* create necessary signal */
110         }
111         return x;               /* exact output */
112 }