e_fmodf.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       e_fmodf.c (2704B)
       ---
            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 
            5 /*
            6  * ====================================================
            7  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
            8  *
            9  * Developed at SunPro, a Sun Microsystems, Inc. business.
           10  * Permission to use, copy, modify, and distribute this
           11  * software is freely granted, provided that this notice
           12  * is preserved.
           13  * ====================================================
           14  */
           15 
           16 #ifndef lint
           17 static char rcsid[] = "$FreeBSD: src/lib/msun/src/e_fmodf.c,v 1.6 2002/05/28 17:03:12 alfred Exp $";
           18 #endif
           19 
           20 /*
           21  * __ieee754_fmodf(x,y)
           22  * Return x mod y in exact arithmetic
           23  * Method: shift and subtract
           24  */
           25 
           26 #include "math.h"
           27 #include "math_private.h"
           28 
           29 static const float one = 1.0, Zero[] = {0.0, -0.0,};
           30 
           31 float
           32 __ieee754_fmodf(float x, float y)
           33 {
           34         int32_t n,hx,hy,hz,ix,iy,sx,i;
           35 
           36         GET_FLOAT_WORD(hx,x);
           37         GET_FLOAT_WORD(hy,y);
           38         sx = hx&0x80000000;                /* sign of x */
           39         hx ^=sx;                /* |x| */
           40         hy &= 0x7fffffff;        /* |y| */
           41 
           42     /* purge off exception values */
           43         if(hy==0||(hx>=0x7f800000)||                /* y=0,or x not finite */
           44            (hy>0x7f800000))                        /* or y is NaN */
           45             return (x*y)/(x*y);
           46         if(hx<hy) return x;                        /* |x|<|y| return x */
           47         if(hx==hy)
           48             return Zero[(u_int32_t)sx>>31];        /* |x|=|y| return x*0*/
           49 
           50     /* determine ix = ilogb(x) */
           51         if(hx<0x00800000) {        /* subnormal x */
           52             for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1;
           53         } else ix = (hx>>23)-127;
           54 
           55     /* determine iy = ilogb(y) */
           56         if(hy<0x00800000) {        /* subnormal y */
           57             for (iy = -126,i=(hy<<8); i>=0; i<<=1) iy -=1;
           58         } else iy = (hy>>23)-127;
           59 
           60     /* set up {hx,lx}, {hy,ly} and align y to x */
           61         if(ix >= -126)
           62             hx = 0x00800000|(0x007fffff&hx);
           63         else {                /* subnormal x, shift x to normal */
           64             n = -126-ix;
           65             hx = hx<<n;
           66         }
           67         if(iy >= -126)
           68             hy = 0x00800000|(0x007fffff&hy);
           69         else {                /* subnormal y, shift y to normal */
           70             n = -126-iy;
           71             hy = hy<<n;
           72         }
           73 
           74     /* fix point fmod */
           75         n = ix - iy;
           76         while(n--) {
           77             hz=hx-hy;
           78             if(hz<0){hx = hx+hx;}
           79             else {
           80                     if(hz==0)                 /* return sign(x)*0 */
           81                     return Zero[(u_int32_t)sx>>31];
           82                     hx = hz+hz;
           83             }
           84         }
           85         hz=hx-hy;
           86         if(hz>=0) {hx=hz;}
           87 
           88     /* convert back to floating value and restore the sign */
           89         if(hx==0)                         /* return sign(x)*0 */
           90             return Zero[(u_int32_t)sx>>31];
           91         while(hx<0x00800000) {                /* normalize x */
           92             hx = hx+hx;
           93             iy -= 1;
           94         }
           95         if(iy>= -126) {                /* normalize output */
           96             hx = ((hx-0x00800000)|((iy+127)<<23));
           97             SET_FLOAT_WORD(x,hx|sx);
           98         } else {                /* subnormal output */
           99             n = -126 - iy;
          100             hx >>= n;
          101             SET_FLOAT_WORD(x,hx|sx);
          102             x *= one;                /* create necessary signal */
          103         }
          104         return x;                /* exact output */
          105 }