xref: /inferno-os/libmath/fdlibm/e_remainder.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /* derived from /netlib/fdlibm */
2*37da2899SCharles.Forsyth 
3*37da2899SCharles.Forsyth /* @(#)e_remainder.c 1.3 95/01/18 */
4*37da2899SCharles.Forsyth /*
5*37da2899SCharles.Forsyth  * ====================================================
6*37da2899SCharles.Forsyth  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
7*37da2899SCharles.Forsyth  *
8*37da2899SCharles.Forsyth  * Developed at SunSoft, a Sun Microsystems, Inc. business.
9*37da2899SCharles.Forsyth  * Permission to use, copy, modify, and distribute this
10*37da2899SCharles.Forsyth  * software is freely granted, provided that this notice
11*37da2899SCharles.Forsyth  * is preserved.
12*37da2899SCharles.Forsyth  * ====================================================
13*37da2899SCharles.Forsyth  */
14*37da2899SCharles.Forsyth 
15*37da2899SCharles.Forsyth /* __ieee754_remainder(x,p)
16*37da2899SCharles.Forsyth  * Return :
17*37da2899SCharles.Forsyth  * 	returns  x REM p  =  x - [x/p]*p as if in infinite
18*37da2899SCharles.Forsyth  * 	precise arithmetic, where [x/p] is the (infinite bit)
19*37da2899SCharles.Forsyth  *	integer nearest x/p (in half way case choose the even one).
20*37da2899SCharles.Forsyth  * Method :
21*37da2899SCharles.Forsyth  *	Based on fmod() return x-[x/p]chopped*p exactlp.
22*37da2899SCharles.Forsyth  */
23*37da2899SCharles.Forsyth 
24*37da2899SCharles.Forsyth #include "fdlibm.h"
25*37da2899SCharles.Forsyth 
26*37da2899SCharles.Forsyth static const double zero = 0.0;
27*37da2899SCharles.Forsyth 
28*37da2899SCharles.Forsyth 
__ieee754_remainder(double x,double p)29*37da2899SCharles.Forsyth 	double __ieee754_remainder(double x, double p)
30*37da2899SCharles.Forsyth {
31*37da2899SCharles.Forsyth 	int hx,hp;
32*37da2899SCharles.Forsyth 	unsigned sx,lx,lp;
33*37da2899SCharles.Forsyth 	double p_half;
34*37da2899SCharles.Forsyth 
35*37da2899SCharles.Forsyth 	hx = __HI(x);		/* high word of x */
36*37da2899SCharles.Forsyth 	lx = __LO(x);		/* low  word of x */
37*37da2899SCharles.Forsyth 	hp = __HI(p);		/* high word of p */
38*37da2899SCharles.Forsyth 	lp = __LO(p);		/* low  word of p */
39*37da2899SCharles.Forsyth 	sx = hx&0x80000000;
40*37da2899SCharles.Forsyth 	hp &= 0x7fffffff;
41*37da2899SCharles.Forsyth 	hx &= 0x7fffffff;
42*37da2899SCharles.Forsyth 
43*37da2899SCharles.Forsyth     /* purge off exception values */
44*37da2899SCharles.Forsyth 	if((hp|lp)==0) return (x*p)/(x*p); 	/* p = 0 */
45*37da2899SCharles.Forsyth 	if((hx>=0x7ff00000)||			/* x not finite */
46*37da2899SCharles.Forsyth 	  ((hp>=0x7ff00000)&&			/* p is NaN */
47*37da2899SCharles.Forsyth 	  (((hp-0x7ff00000)|lp)!=0)))
48*37da2899SCharles.Forsyth 	    return (x*p)/(x*p);
49*37da2899SCharles.Forsyth 
50*37da2899SCharles.Forsyth 
51*37da2899SCharles.Forsyth 	if (hp<=0x7fdfffff) x = __ieee754_fmod(x,p+p);	/* now x < 2p */
52*37da2899SCharles.Forsyth 	if (((hx-hp)|(lx-lp))==0) return zero*x;
53*37da2899SCharles.Forsyth 	x  = fabs(x);
54*37da2899SCharles.Forsyth 	p  = fabs(p);
55*37da2899SCharles.Forsyth 	if (hp<0x00200000) {
56*37da2899SCharles.Forsyth 	    if(x+x>p) {
57*37da2899SCharles.Forsyth 		x-=p;
58*37da2899SCharles.Forsyth 		if(x+x>=p) x -= p;
59*37da2899SCharles.Forsyth 	    }
60*37da2899SCharles.Forsyth 	} else {
61*37da2899SCharles.Forsyth 	    p_half = 0.5*p;
62*37da2899SCharles.Forsyth 	    if(x>p_half) {
63*37da2899SCharles.Forsyth 		x-=p;
64*37da2899SCharles.Forsyth 		if(x>=p_half) x -= p;
65*37da2899SCharles.Forsyth 	    }
66*37da2899SCharles.Forsyth 	}
67*37da2899SCharles.Forsyth 	__HI(x) ^= sx;
68*37da2899SCharles.Forsyth 	return x;
69*37da2899SCharles.Forsyth }
70