1 1.11 martin /* $NetBSD: n_fmod.c,v 1.11 2018/11/09 10:19:47 martin Exp $ */ 2 1.1 ragge /* 3 1.1 ragge * Copyright (c) 1989, 1993 4 1.1 ragge * The Regents of the University of California. All rights reserved. 5 1.1 ragge * 6 1.1 ragge * Redistribution and use in source and binary forms, with or without 7 1.1 ragge * modification, are permitted provided that the following conditions 8 1.1 ragge * are met: 9 1.1 ragge * 1. Redistributions of source code must retain the above copyright 10 1.1 ragge * notice, this list of conditions and the following disclaimer. 11 1.1 ragge * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 ragge * notice, this list of conditions and the following disclaimer in the 13 1.1 ragge * documentation and/or other materials provided with the distribution. 14 1.5 agc * 3. Neither the name of the University nor the names of its contributors 15 1.1 ragge * may be used to endorse or promote products derived from this software 16 1.1 ragge * without specific prior written permission. 17 1.1 ragge * 18 1.1 ragge * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 1.1 ragge * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 1.1 ragge * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 1.1 ragge * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 1.1 ragge * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 1.1 ragge * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 1.1 ragge * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 1.1 ragge * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 1.1 ragge * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 1.1 ragge * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 1.1 ragge * SUCH DAMAGE. 29 1.1 ragge */ 30 1.1 ragge 31 1.1 ragge #ifndef lint 32 1.2 ragge #if 0 33 1.1 ragge static char sccsid[] = "@(#)fmod.c 8.1 (Berkeley) 6/4/93"; 34 1.2 ragge #endif 35 1.1 ragge #endif /* not lint */ 36 1.1 ragge 37 1.1 ragge #include "mathimpl.h" 38 1.1 ragge 39 1.1 ragge /* fmod.c 40 1.1 ragge * 41 1.1 ragge * SYNOPSIS 42 1.1 ragge * 43 1.1 ragge * #include <math.h> 44 1.1 ragge * double fmod(double x, double y) 45 1.1 ragge * 46 1.1 ragge * DESCRIPTION 47 1.1 ragge * 48 1.1 ragge * The fmod function computes the floating-point remainder of x/y. 49 1.1 ragge * 50 1.1 ragge * RETURNS 51 1.1 ragge * 52 1.1 ragge * The fmod function returns the value x-i*y, for some integer i 53 1.1 ragge * such that, if y is nonzero, the result has the same sign as x and 54 1.1 ragge * magnitude less than the magnitude of y. 55 1.1 ragge * 56 1.1 ragge * On a VAX or CCI, 57 1.1 ragge * 58 1.1 ragge * fmod(x,0) traps/faults on floating-point divided-by-zero. 59 1.1 ragge * 60 1.1 ragge * On IEEE-754 conforming machines with "isnan()" primitive, 61 1.1 ragge * 62 1.1 ragge * fmod(x,0), fmod(INF,y) are invalid operations and NaN is returned. 63 1.1 ragge * 64 1.1 ragge */ 65 1.3 matt #if !defined(__vax__) && !defined(tahoe) 66 1.1 ragge extern int isnan(),finite(); 67 1.3 matt #endif /* !defined(__vax__) && !defined(tahoe) */ 68 1.1 ragge 69 1.6 martin #if DBL_MANT_DIG == LDBL_MANT_DIG && DBL_MIN_EXP == LDBL_MIN_EXP \ 70 1.6 martin && DBL_MIN_EXP == LDBL_MIN_EXP 71 1.6 martin #ifdef __weak_alias 72 1.6 martin __weak_alias(fmodl, fmod); 73 1.11 martin __weak_alias(modfl, fmod); 74 1.6 martin #endif 75 1.6 martin #endif 76 1.6 martin 77 1.1 ragge #ifdef TEST_FMOD 78 1.1 ragge static double 79 1.4 matt _fmod(double x, double y) 80 1.1 ragge #else /* TEST_FMOD */ 81 1.1 ragge double 82 1.4 matt fmod(double x, double y) 83 1.1 ragge #endif /* TEST_FMOD */ 84 1.1 ragge { 85 1.1 ragge int ir,iy; 86 1.1 ragge double r,w; 87 1.1 ragge 88 1.1 ragge if (y == (double)0 89 1.3 matt #if !defined(__vax__) && !defined(tahoe) /* per "fmod" manual entry, SunOS 4.0 */ 90 1.1 ragge || isnan(y) || !finite(x) 91 1.3 matt #endif /* !defined(__vax__) && !defined(tahoe) */ 92 1.1 ragge ) 93 1.1 ragge return (x*y)/(x*y); 94 1.1 ragge 95 1.1 ragge r = fabs(x); 96 1.1 ragge y = fabs(y); 97 1.1 ragge (void)frexp(y,&iy); 98 1.1 ragge while (r >= y) { 99 1.1 ragge (void)frexp(r,&ir); 100 1.1 ragge w = ldexp(y,ir-iy); 101 1.1 ragge r -= w <= r ? w : w*(double)0.5; 102 1.1 ragge } 103 1.1 ragge return x >= (double)0 ? r : -r; 104 1.1 ragge } 105 1.1 ragge 106 1.6 martin float 107 1.7 martin fmodf(float x, float y) 108 1.6 martin { 109 1.7 martin return fmod(x, y); 110 1.6 martin } 111 1.6 martin 112 1.1 ragge #ifdef TEST_FMOD 113 1.10 christos #include <math.h> 114 1.10 christos #include <stdio.h> 115 1.10 christos #include <stdlib.h> 116 1.1 ragge 117 1.1 ragge #define NTEST 10000 118 1.1 ragge #define NCASES 3 119 1.1 ragge 120 1.1 ragge static int nfail = 0; 121 1.8 christos static void 122 1.8 christos prf(const char *s, double d) 123 1.8 christos { 124 1.8 christos union { 125 1.8 christos double d; 126 1.8 christos unsigned long long u; 127 1.8 christos } x; 128 1.8 christos x.d = d; 129 1.9 christos printf("%s = %#016.16llx (%24.16e)\n", s, x.u, x.d); 130 1.8 christos } 131 1.1 ragge 132 1.1 ragge static void 133 1.4 matt doit(double x, double y) 134 1.1 ragge { 135 1.1 ragge double ro = fmod(x,y),rn = _fmod(x,y); 136 1.1 ragge if (ro != rn) { 137 1.8 christos prf(" x ", x); 138 1.8 christos prf(" y ", y); 139 1.8 christos prf(" fmod", ro); 140 1.8 christos prf("_fmod", rn); 141 1.1 ragge (void)printf("\n"); 142 1.1 ragge } 143 1.1 ragge } 144 1.1 ragge 145 1.4 matt int 146 1.4 matt main(int argc, char **argv) 147 1.1 ragge { 148 1.4 matt int i,cases; 149 1.1 ragge double x,y; 150 1.1 ragge 151 1.1 ragge srandom(12345); 152 1.1 ragge for (i = 0; i < NTEST; i++) { 153 1.1 ragge x = (double)random(); 154 1.1 ragge y = (double)random(); 155 1.1 ragge for (cases = 0; cases < NCASES; cases++) { 156 1.1 ragge switch (cases) { 157 1.1 ragge case 0: 158 1.1 ragge break; 159 1.1 ragge case 1: 160 1.1 ragge y = (double)1/y; break; 161 1.1 ragge case 2: 162 1.1 ragge x = (double)1/x; break; 163 1.1 ragge default: 164 1.1 ragge abort(); break; 165 1.1 ragge } 166 1.1 ragge doit(x,y); 167 1.1 ragge doit(x,-y); 168 1.1 ragge doit(-x,y); 169 1.1 ragge doit(-x,-y); 170 1.1 ragge } 171 1.1 ragge } 172 1.1 ragge if (nfail) 173 1.1 ragge (void)printf("Number of failures: %d (out of a total of %d)\n", 174 1.1 ragge nfail,NTEST*NCASES*4); 175 1.1 ragge else 176 1.1 ragge (void)printf("No discrepancies were found\n"); 177 1.1 ragge exit(0); 178 1.1 ragge } 179 1.1 ragge #endif /* TEST_FMOD */ 180