138203Sbostic /* 238203Sbostic * Copyright (c) 1989 The Regents of the University of California. 338203Sbostic * All rights reserved. 438203Sbostic * 5*42657Sbostic * %sccs.include.redist.c% 638203Sbostic */ 738203Sbostic 838203Sbostic #ifndef lint 9*42657Sbostic static char sccsid[] = "@(#)fmod.c 5.2 (Berkeley) 06/01/90"; 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 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 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 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