• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ====================================================
3  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
4  *
5  * Developed at SunPro, a Sun Microsystems, Inc. business.
6  * Permission to use, copy, modify, and distribute this
7  * software is freely granted, provided that this notice
8  * is preserved.
9  * ====================================================
10  */
11 
12 /*
13  * __ieee754_fmodf(x,y)
14  * Return x mod y in exact arithmetic
15  * Method: shift and subtract
16  */
17 
18 #include "bsd_privatef.h"
19 
bsd__ieee754_fmodf(float x,float y)20 float bsd__ieee754_fmodf(float x, float y)
21 {
22     int32_t n,hx,hy,hz,ix,iy,sx,i;
23 
24     GET_FLOAT_WORD(hx,x);
25     GET_FLOAT_WORD(hy,y);
26     sx = hx&0x80000000;        /* sign of x */
27     hx ^=sx;                   /* |x| */
28     hy &= 0x7fffffff;          /* |y| */
29 
30     /* purge off exception values */
31     if(hy==0||(hx>=0x7f800000)||           /* y=0,or x not finite */
32        (hy>0x7f800000))                    /* or y is NaN */
33         return (x*y)/(x*y);
34     if(hx<hy) return x;                    /* |x|<|y| return x */
35     if(hx==hy)
36         return Zero[(u_int32_t)sx>>31];    /* |x|=|y| return x*0*/
37 
38     /* determine ix = ilogb(x) */
39     if(hx<0x00800000) {    /* subnormal x */
40         for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1;
41     } else ix = (hx>>23)-127;
42 
43     /* determine iy = ilogb(y) */
44     if(hy<0x00800000) {    /* subnormal y */
45         for (iy = -126,i=(hy<<8); i>=0; i<<=1) iy -=1;
46     } else iy = (hy>>23)-127;
47 
48     /* set up {hx,lx}, {hy,ly} and align y to x */
49     if(ix >= -126)
50         hx = 0x00800000|(0x007fffff&hx);
51     else {        /* subnormal x, shift x to normal */
52         n = -126-ix;
53         hx = hx<<n;
54     }
55     if(iy >= -126)
56         hy = 0x00800000|(0x007fffff&hy);
57     else {        /* subnormal y, shift y to normal */
58         n = -126-iy;
59         hy = hy<<n;
60     }
61 
62     /* fix point fmod */
63     n = ix - iy;
64     while(n--) {
65         hz=hx-hy;
66         if(hz<0){hx = hx+hx;}
67         else {
68             if(hz==0)         /* return sign(x)*0 */
69             return Zero[(u_int32_t)sx>>31];
70             hx = hz+hz;
71         }
72     }
73     hz=hx-hy;
74     if(hz>=0) {hx=hz;}
75 
76     /* convert back to floating value and restore the sign */
77     if(hx==0)                     /* return sign(x)*0 */
78         return Zero[(u_int32_t)sx>>31];
79     while(hx<0x00800000) {        /* normalize x */
80         hx = hx+hx;
81         iy -= 1;
82     }
83     if(iy>= -126) {      /* normalize output */
84         hx = ((hx-0x00800000)|((iy+127)<<23));
85         SET_FLOAT_WORD(x,hx|sx);
86     } else {             /* subnormal output */
87         n = -126 - iy;
88         hx >>= n;
89         SET_FLOAT_WORD(x,hx|sx);
90         x *= one;        /* create necessary signal */
91     }
92     return x;            /* exact output */
93 }
94