rem_test.c revision 165856
1/*- 2 * Copyright (c) 2005 David Schultz <das@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27/* 28 * Test for remainder functions: remainder, remainderf, remquo, remquof. 29 * Missing tests: fmod, fmodf. 30 */ 31 32#include <sys/cdefs.h> 33__FBSDID("$FreeBSD: head/tools/regression/lib/msun/test-rem.c 165856 2007-01-07 09:25:22Z das $"); 34 35#include <assert.h> 36#include <math.h> 37#include <stdio.h> 38#include <stdlib.h> 39#include <strings.h> 40 41static void test_invalid(double, double); 42static void testd(double, double, double, int); 43static void testf(float, float, float, int); 44 45#define test(x, y, e_r, e_q) do { \ 46 testd(x, y, e_r, e_q); \ 47 testf(x, y, e_r, e_q); \ 48} while (0) 49 50int 51main(int argc, char *argv[]) 52{ 53 54 printf("1..2\n"); 55 56 test_invalid(0.0, 0.0); 57 test_invalid(1.0, 0.0); 58 test_invalid(INFINITY, 0.0); 59 test_invalid(INFINITY, 1.0); 60 test_invalid(-INFINITY, 1.0); 61 test_invalid(NAN, 1.0); 62 test_invalid(1.0, NAN); 63 64 test(4, 4, 0, 1); 65 test(0, 3.0, 0, 0); 66 testd(0x1p-1074, 1, 0x1p-1074, 0x1p-1074); 67 testf(0x1p-149, 1, 0x1p-149, 0x1p-149); 68 test(3.0, 4, -1, 1); 69 test(3.0, -4, -1, -1); 70 testd(275 * 1193040, 275, 0, 1193040); 71 test(4.5 * 7.5, 4.5, -2.25, 8); /* we should get the even one */ 72 testf(0x1.9044f6p-1, 0x1.ce662ep-1, -0x1.f109cp-4, 1); 73 74 printf("ok 1 - rem\n"); 75 76 /* 77 * The actual quotient here is 864062210.50000003..., but 78 * double-precision division gets -8.64062210.5, which rounds 79 * the wrong way. This test ensures that remquo() is smart 80 * enough to get the low-order bit right. 81 */ 82 testd(-0x1.98260f22fc6dep-302, 0x1.fb3167c430a13p-332, 83 0x1.fb3165b82de72p-333, -864062211); 84 /* Even harder cases with greater exponent separation */ 85 test(0x1.fp100, 0x1.ep-40, -0x1.cp-41, 143165577); 86 testd(-0x1.abcdefp120, 0x1.87654321p-120, 87 -0x1.69c78ec4p-121, -63816414); 88 89 printf("ok 2 - rem\n"); 90 91 return (0); 92} 93 94static void 95test_invalid(double x, double y) 96{ 97 int q; 98 99 q = 0xdeadbeef; 100 101 assert(isnan(remainder(x, y))); 102 assert(isnan(remquo(x, y, &q))); 103#ifdef STRICT 104 assert(q == 0xdeadbeef); 105#endif 106 107 assert(isnan(remainderf(x, y))); 108 assert(isnan(remquof(x, y, &q))); 109#ifdef STRICT 110 assert(q == 0xdeadbeef); 111#endif 112} 113 114/* 0x012345 ==> 0x01ffff */ 115static inline int 116mask(int x) 117{ 118 return ((unsigned)~0 >> (32 - fls(x))); 119} 120 121static void 122testd(double x, double y, double expected_rem, int expected_quo) 123{ 124 int q; 125 126 q = random(); 127 assert(remainder(x, y) == expected_rem); 128 assert(remquo(x, y, &q) == expected_rem); 129 assert((q & 0x7) == (expected_quo & 0x7)); 130 if (q != 0) { 131 assert((q > 0) ^ !(expected_quo > 0)); 132 q = abs(q); 133 assert(q == (abs(expected_quo) & mask(q))); 134 } 135} 136 137static void 138testf(float x, float y, float expected_rem, int expected_quo) 139{ 140 int q; 141 142 q = random(); 143 assert(remainderf(x, y) == expected_rem); 144 assert(remquof(x, y, &q) == expected_rem); 145 assert((q & 0x7) == (expected_quo & 0x7)); 146 if (q != 0) { 147 assert((q > 0) ^ !(expected_quo > 0)); 148 q = abs(q); 149 assert((q & mask(q)) == (abs(expected_quo) & mask(q))); 150 } 151} 152