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