xref: /csrg-svn/lib/libm/common_source/fmod.c (revision 61295)
138203Sbostic /*
2*61295Sbostic  * Copyright (c) 1989, 1993
3*61295Sbostic  *	The Regents of the University of California.  All rights reserved.
438203Sbostic  *
542657Sbostic  * %sccs.include.redist.c%
638203Sbostic  */
738203Sbostic 
838203Sbostic #ifndef lint
9*61295Sbostic static char sccsid[] = "@(#)fmod.c	8.1 (Berkeley) 06/04/93";
1038203Sbostic #endif /* not lint */
1138203Sbostic 
1238203Sbostic /* fmod.c
1338203Sbostic  *
1438203Sbostic  * SYNOPSIS
1538203Sbostic  *
1638203Sbostic  *    #include <math.h>
1738203Sbostic  *    double fmod(double x, double y)
1838203Sbostic  *
1938203Sbostic  * DESCRIPTION
2038203Sbostic  *
2138203Sbostic  *    The fmod function computes the floating-point remainder of x/y.
2238203Sbostic  *
2338203Sbostic  * RETURNS
2438203Sbostic  *
2538203Sbostic  *    The fmod function returns the value x-i*y, for some integer i
2638203Sbostic  * such that, if y is nonzero, the result has the same sign as x and
2738203Sbostic  * magnitude less than the magnitude of y.
2838203Sbostic  *
2938203Sbostic  * On a VAX or CCI,
3038203Sbostic  *
3138203Sbostic  *    fmod(x,0) traps/faults on floating-point divided-by-zero.
3238203Sbostic  *
3338203Sbostic  * On IEEE-754 conforming machines with "isnan()" primitive,
3438203Sbostic  *
3538203Sbostic  *    fmod(x,0), fmod(INF,y) are invalid operations and NaN is returned.
3638203Sbostic  *
3738203Sbostic  */
3838203Sbostic #if !defined(vax) && !defined(tahoe)
3938203Sbostic extern int isnan(),finite();
4038203Sbostic #endif	/* !defined(vax) && !defined(tahoe) */
4138203Sbostic extern double frexp(),ldexp(),fabs();
4238203Sbostic 
4338203Sbostic #ifdef TEST_FMOD
4438203Sbostic static double
_fmod(x,y)4538203Sbostic _fmod(x,y)
4638203Sbostic #else	/* TEST_FMOD */
4738203Sbostic double
4838203Sbostic fmod(x,y)
4938203Sbostic #endif	/* TEST_FMOD */
5038203Sbostic double x,y;
5138203Sbostic {
5238203Sbostic 	int ir,iy;
5338203Sbostic 	double r,w;
5438203Sbostic 
5538203Sbostic 	if (y == (double)0
5638203Sbostic #if !defined(vax) && !defined(tahoe)	/* per "fmod" manual entry, SunOS 4.0 */
5738203Sbostic 		|| isnan(y) || !finite(x)
5838203Sbostic #endif	/* !defined(vax) && !defined(tahoe) */
5938203Sbostic 	    )
6038203Sbostic 	    return (x*y)/(x*y);
6138203Sbostic 
6238203Sbostic 	r = fabs(x);
6338203Sbostic 	y = fabs(y);
6438203Sbostic 	(void)frexp(y,&iy);
6538203Sbostic 	while (r >= y) {
6638203Sbostic 		(void)frexp(r,&ir);
6738203Sbostic 		w = ldexp(y,ir-iy);
6838203Sbostic 		r -= w <= r ? w : w*(double)0.5;
6938203Sbostic 	}
7038203Sbostic 	return x >= (double)0 ? r : -r;
7138203Sbostic }
7238203Sbostic 
7338203Sbostic #ifdef TEST_FMOD
7438203Sbostic extern long random();
7538203Sbostic extern double fmod();
7638203Sbostic 
7738203Sbostic #define	NTEST	10000
7838203Sbostic #define	NCASES	3
7938203Sbostic 
8038203Sbostic static int nfail = 0;
8138203Sbostic 
8238203Sbostic static void
doit(x,y)8338203Sbostic doit(x,y)
8438203Sbostic double x,y;
8538203Sbostic {
8638203Sbostic 	double ro = fmod(x,y),rn = _fmod(x,y);
8738203Sbostic 	if (ro != rn) {
8838203Sbostic 		(void)printf(" x    = 0x%08.8x %08.8x (%24.16e)\n",x,x);
8938203Sbostic 		(void)printf(" y    = 0x%08.8x %08.8x (%24.16e)\n",y,y);
9038203Sbostic 		(void)printf(" fmod = 0x%08.8x %08.8x (%24.16e)\n",ro,ro);
9138203Sbostic 		(void)printf("_fmod = 0x%08.8x %08.8x (%24.16e)\n",rn,rn);
9238203Sbostic 		(void)printf("\n");
9338203Sbostic 	}
9438203Sbostic }
9538203Sbostic 
main()9638203Sbostic main()
9738203Sbostic {
9838203Sbostic 	register int i,cases;
9938203Sbostic 	double x,y;
10038203Sbostic 
10138203Sbostic 	srandom(12345);
10238203Sbostic 	for (i = 0; i < NTEST; i++) {
10338203Sbostic 		x = (double)random();
10438203Sbostic 		y = (double)random();
10538203Sbostic 		for (cases = 0; cases < NCASES; cases++) {
10638203Sbostic 			switch (cases) {
10738203Sbostic 			case 0:
10838203Sbostic 				break;
10938203Sbostic 			case 1:
11038203Sbostic 				y = (double)1/y; break;
11138203Sbostic 			case 2:
11238203Sbostic 				x = (double)1/x; break;
11338203Sbostic 			default:
11438203Sbostic 				abort(); break;
11538203Sbostic 			}
11638203Sbostic 			doit(x,y);
11738203Sbostic 			doit(x,-y);
11838203Sbostic 			doit(-x,y);
11938203Sbostic 			doit(-x,-y);
12038203Sbostic 		}
12138203Sbostic 	}
12238203Sbostic 	if (nfail)
12338203Sbostic 		(void)printf("Number of failures: %d (out of a total of %d)\n",
12438203Sbostic 			nfail,NTEST*NCASES*4);
12538203Sbostic 	else
12638203Sbostic 		(void)printf("No discrepancies were found\n");
12738203Sbostic 	exit(0);
12838203Sbostic }
12938203Sbostic #endif	/* TEST_FMOD */
130