OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [newlib/] [newlib/] [libm/] [mathfp/] [s_fmod.c] - Blame information for rev 1767

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 56 joel
 
2
/* @(#)z_fmod.c 1.0 98/08/13 */
3
/*
4
 * ====================================================
5
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
6
 *
7
 * Developed at SunPro, 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
/*
15
FUNCTION
16
<<fmod>>, <<fmodf>>---floating-point remainder (modulo)
17
 
18
INDEX
19
fmod
20
INDEX
21
fmodf
22
 
23
ANSI_SYNOPSIS
24
#include <math.h>
25
double fmod(double <[x]>, double <[y]>)
26
float fmodf(float <[x]>, float <[y]>)
27
 
28
TRAD_SYNOPSIS
29
#include <math.h>
30
double fmod(<[x]>, <[y]>)
31
double (<[x]>, <[y]>);
32
 
33
float fmodf(<[x]>, <[y]>)
34
float (<[x]>, <[y]>);
35
 
36
DESCRIPTION
37
The <<fmod>> and <<fmodf>> functions compute the floating-point
38
remainder of <[x]>/<[y]> (<[x]> modulo <[y]>).
39
 
40
RETURNS
41
The <<fmod>> function returns the value
42
@ifinfo
43
<[x]>-<[i]>*<[y]>,
44
@end ifinfo
45
@tex
46
$x-i\times y$,
47
@end tex
48
for the largest integer <[i]> such that, if <[y]> is nonzero, the
49
result has the same sign as <[x]> and magnitude less than the
50
magnitude of <[y]>.
51
 
52
<<fmod(<[x]>,0)>> returns NaN, and sets <<errno>> to <<EDOM>>.
53
 
54
You can modify error treatment for these functions using <<matherr>>.
55
 
56
PORTABILITY
57
<<fmod>> is ANSI C. <<fmodf>> is an extension.
58
*/
59
 
60
/*
61
 * fmod(x,y)
62
 * Return x mod y in exact arithmetic
63
 * Method: shift and subtract
64
 */
65
 
66
#include "fdlibm.h"
67
#include "zmath.h"
68
 
69
#ifndef _DOUBLE_IS_32BITS
70
 
71
#ifdef __STDC__
72
static const double one = 1.0, Zero[] = {0.0, -0.0,};
73
#else
74
static double one = 1.0, Zero[] = {0.0, -0.0,};
75
#endif
76
 
77
#ifdef __STDC__
78
        double fmod(double x, double y)
79
#else
80
        double fmod(x,y)
81
        double x,y ;
82
#endif
83
{
84
        __int32_t n,hx,hy,hz,ix,iy,sx,i;
85
        __uint32_t lx,ly,lz;
86
 
87
        EXTRACT_WORDS(hx,lx,x);
88
        EXTRACT_WORDS(hy,ly,y);
89
        sx = hx&0x80000000;             /* sign of x */
90
        hx ^=sx;                /* |x| */
91
        hy &= 0x7fffffff;       /* |y| */
92
 
93
    /* purge off exception values */
94
        if((hy|ly)==0||(hx>=0x7ff00000)||        /* y=0,or x not finite */
95
          ((hy|((ly|-ly)>>31))>0x7ff00000))     /* or y is NaN */
96
            return (x*y)/(x*y);
97
        if(hx<=hy) {
98
            if((hx<hy)||(lx<ly)) return x;      /* |x|<|y| return x */
99
            if(lx==ly)
100
                return Zero[(__uint32_t)sx>>31];        /* |x|=|y| return x*0*/
101
        }
102
 
103
    /* determine ix = ilogb(x) */
104
        if(hx<0x00100000) {     /* subnormal x */
105
            if(hx==0) {
106
                for (ix = -1043, i=lx; i>0; i<<=1) ix -=1;
107
            } else {
108
                for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1;
109
            }
110
        } else ix = (hx>>20)-1023;
111
 
112
    /* determine iy = ilogb(y) */
113
        if(hy<0x00100000) {     /* subnormal y */
114
            if(hy==0) {
115
                for (iy = -1043, i=ly; i>0; i<<=1) iy -=1;
116
            } else {
117
                for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1;
118
            }
119
        } else iy = (hy>>20)-1023;
120
 
121
    /* set up {hx,lx}, {hy,ly} and align y to x */
122
        if(ix >= -1022)
123
            hx = 0x00100000|(0x000fffff&hx);
124
        else {          /* subnormal x, shift x to normal */
125
            n = -1022-ix;
126
            if(n<=31) {
127
                hx = (hx<<n)|(lx>>(32-n));
128
                lx <<= n;
129
            } else {
130
                hx = lx<<(n-32);
131
                lx = 0;
132
            }
133
        }
134
        if(iy >= -1022)
135
            hy = 0x00100000|(0x000fffff&hy);
136
        else {          /* subnormal y, shift y to normal */
137
            n = -1022-iy;
138
            if(n<=31) {
139
                hy = (hy<<n)|(ly>>(32-n));
140
                ly <<= n;
141
            } else {
142
                hy = ly<<(n-32);
143
                ly = 0;
144
            }
145
        }
146
 
147
    /* fix point fmod */
148
        n = ix - iy;
149
        while(n--) {
150
            hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
151
            if(hz<0){hx = hx+hx+(lx>>31); lx = lx+lx;}
152
            else {
153
                if((hz|lz)==0)           /* return sign(x)*0 */
154
                    return Zero[(__uint32_t)sx>>31];
155
                hx = hz+hz+(lz>>31); lx = lz+lz;
156
            }
157
        }
158
        hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
159
        if(hz>=0) {hx=hz;lx=lz;}
160
 
161
    /* convert back to floating value and restore the sign */
162
        if((hx|lx)==0)                   /* return sign(x)*0 */
163
            return Zero[(__uint32_t)sx>>31];
164
        while(hx<0x00100000) {          /* normalize x */
165
            hx = hx+hx+(lx>>31); lx = lx+lx;
166
            iy -= 1;
167
        }
168
        if(iy>= -1022) {        /* normalize output */
169
            hx = ((hx-0x00100000)|((iy+1023)<<20));
170
            INSERT_WORDS(x,hx|sx,lx);
171
        } else {                /* subnormal output */
172
            n = -1022 - iy;
173
            if(n<=20) {
174
                lx = (lx>>n)|((__uint32_t)hx<<(32-n));
175
                hx >>= n;
176
            } else if (n<=31) {
177
                lx = (hx<<(32-n))|(lx>>n); hx = sx;
178
            } else {
179
                lx = hx>>(n-32); hx = sx;
180
            }
181
            INSERT_WORDS(x,hx|sx,lx);
182
            x *= one;           /* create necessary signal */
183
        }
184
        return x;               /* exact output */
185
}
186
 
187
#endif /* defined(_DOUBLE_IS_32BITS) */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.