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