1 //===========================================================================
5 // Part of the standard mathematical function library
7 //===========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //===========================================================================
41 //#####DESCRIPTIONBEGIN####
43 // Author(s): jlarmour
44 // Contributors: jlarmour
50 //####DESCRIPTIONEND####
52 //===========================================================================
56 #include <pkgconf/libm.h> // Configuration header
58 // Include the Math library?
61 // Derived from code with the following copyright
64 /* @(#)e_fmod.c 1.3 95/01/18 */
66 * ====================================================
67 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
69 * Developed at SunSoft, a Sun Microsystems, Inc. business.
70 * Permission to use, copy, modify, and distribute this
71 * software is freely granted, provided that this notice
73 * ====================================================
78 * Return x mod y in exact arithmetic
79 * Method: shift and subtract
82 #include "mathincl/fdlibm.h"
84 static const double one = 1.0, Zero[] = {0.0, -0.0,};
86 double __ieee754_fmod(double x, double y)
88 int n,hx,hy,hz,ix,iy,sx,i;
91 hx = CYG_LIBM_HI(x); /* high word of x */
92 lx = CYG_LIBM_LO(x); /* low word of x */
93 hy = CYG_LIBM_HI(y); /* high word of y */
94 ly = CYG_LIBM_LO(y); /* low word of y */
95 sx = hx&0x80000000; /* sign of x */
97 hy &= 0x7fffffff; /* |y| */
99 /* purge off exception values */
100 if((hy|ly)==0||(hx>=0x7ff00000)|| /* y=0,or x not finite */
101 ((hy|((ly|-ly)>>31))>0x7ff00000)) /* or y is NaN */
104 if((hx<hy)||(lx<ly)) return x; /* |x|<|y| return x */
106 return Zero[(unsigned)sx>>31]; /* |x|=|y| return x*0*/
109 /* determine ix = ilogb(x) */
110 if(hx<0x00100000) { /* subnormal x */
112 for (ix = -1043, i=lx; i>0; i<<=1) ix -=1;
114 for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1;
116 } else ix = (hx>>20)-1023;
118 /* determine iy = ilogb(y) */
119 if(hy<0x00100000) { /* subnormal y */
121 for (iy = -1043, i=ly; i>0; i<<=1) iy -=1;
123 for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1;
125 } else iy = (hy>>20)-1023;
127 /* set up {hx,lx}, {hy,ly} and align y to x */
129 hx = 0x00100000|(0x000fffff&hx);
130 else { /* subnormal x, shift x to normal */
133 hx = (hx<<n)|(lx>>(32-n));
141 hy = 0x00100000|(0x000fffff&hy);
142 else { /* subnormal y, shift y to normal */
145 hy = (hy<<n)|(ly>>(32-n));
156 hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
157 if(hz<0){hx = hx+hx+(lx>>31); lx = lx+lx;}
159 if((hz|lz)==0) /* return sign(x)*0 */
160 return Zero[(unsigned)sx>>31];
161 hx = hz+hz+(lz>>31); lx = lz+lz;
164 hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
165 if(hz>=0) {hx=hz;lx=lz;}
167 /* convert back to floating value and restore the sign */
168 if((hx|lx)==0) /* return sign(x)*0 */
169 return Zero[(unsigned)sx>>31];
170 while(hx<0x00100000) { /* normalize x */
171 hx = hx+hx+(lx>>31); lx = lx+lx;
174 if(iy>= -1022) { /* normalize output */
175 hx = ((hx-0x00100000)|((iy+1023)<<20));
176 CYG_LIBM_HI(x) = hx|sx;
178 } else { /* subnormal output */
181 lx = (lx>>n)|((unsigned)hx<<(32-n));
184 lx = (hx<<(32-n))|(lx>>n); hx = sx;
186 lx = hx>>(n-32); hx = sx;
188 CYG_LIBM_HI(x) = hx|sx;
190 x *= one; /* create necessary signal */
192 return x; /* exact output */
195 #endif // ifdef CYGPKG_LIBM