OSDN Git Service

mkostemp: fix implementation
[uclinux-h8/uClibc.git] / libm / e_remainder.c
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 /* __ieee754_remainder(x,p)
13  * Return :
14  *      returns  x REM p  =  x - [x/p]*p as if in infinite
15  *      precise arithmetic, where [x/p] is the (infinite bit)
16  *      integer nearest x/p (in half way case choose the even one).
17  * Method :
18  *      Based on fmod() return x-[x/p]chopped*p exactlp.
19  */
20
21 #include "math.h"
22 #include "math_private.h"
23
24 static const double zero = 0.0;
25
26 double __ieee754_remainder(double x, double p)
27 {
28         int32_t hx,hp;
29         u_int32_t sx,lx,lp;
30         double p_half;
31
32         EXTRACT_WORDS(hx,lx,x);
33         EXTRACT_WORDS(hp,lp,p);
34         sx = hx&0x80000000;
35         hp &= 0x7fffffff;
36         hx &= 0x7fffffff;
37
38     /* purge off exception values */
39         if((hp|lp)==0) return (x*p)/(x*p);      /* p = 0 */
40         if((hx>=0x7ff00000)||                   /* x not finite */
41           ((hp>=0x7ff00000)&&                   /* p is NaN */
42           (((hp-0x7ff00000)|lp)!=0)))
43             return (x*p)/(x*p);
44
45
46         if (hp<=0x7fdfffff) x = __ieee754_fmod(x,p+p);  /* now x < 2p */
47         if (((hx-hp)|(lx-lp))==0) return zero*x;
48         x  = fabs(x);
49         p  = fabs(p);
50         if (hp<0x00200000) {
51             if(x+x>p) {
52                 x-=p;
53                 if(x+x>=p) x -= p;
54             }
55         } else {
56             p_half = 0.5*p;
57             if(x>p_half) {
58                 x-=p;
59                 if(x>=p_half) x -= p;
60             }
61         }
62         GET_HIGH_WORD(hx,x);
63         SET_HIGH_WORD(x,hx^sx);
64         return x;
65 }
66
67 /*
68  * wrapper remainder(x,p)
69  */
70 #ifndef _IEEE_LIBM
71 double remainder(double x, double y)
72 {
73         double z = __ieee754_remainder(x, y);
74         if (_LIB_VERSION == _IEEE_ || isnan(y))
75                 return z;
76         if (y == 0.0)
77                 return __kernel_standard(x, y, 28); /* remainder(x,0) */
78         return z;
79 }
80 strong_alias(remainder, drem)
81 #else
82 strong_alias(__ieee754_remainder, remainder)
83 strong_alias(__ieee754_remainder, drem)
84 #endif
85 libm_hidden_def(remainder)