rem_test.c revision 144094
1144094Sdas/*- 2144094Sdas * Copyright (c) 2005 David Schultz <das@FreeBSD.org> 3144094Sdas * All rights reserved. 4144094Sdas * 5144094Sdas * Redistribution and use in source and binary forms, with or without 6144094Sdas * modification, are permitted provided that the following conditions 7144094Sdas * are met: 8144094Sdas * 1. Redistributions of source code must retain the above copyright 9144094Sdas * notice, this list of conditions and the following disclaimer. 10144094Sdas * 2. Redistributions in binary form must reproduce the above copyright 11144094Sdas * notice, this list of conditions and the following disclaimer in the 12144094Sdas * documentation and/or other materials provided with the distribution. 13144094Sdas * 14144094Sdas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15144094Sdas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16144094Sdas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17144094Sdas * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18144094Sdas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19144094Sdas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20144094Sdas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21144094Sdas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22144094Sdas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23144094Sdas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24144094Sdas * SUCH DAMAGE. 25144094Sdas */ 26144094Sdas 27144094Sdas/* 28144094Sdas * Test for remainder functions: remainder, remainderf, remquo, remquof. 29144094Sdas * Missing tests: fmod, fmodf. 30144094Sdas */ 31144094Sdas 32144094Sdas#include <sys/cdefs.h> 33144094Sdas__FBSDID("$FreeBSD: head/tools/regression/lib/msun/test-rem.c 144094 2005-03-25 06:24:46Z das $"); 34144094Sdas 35144094Sdas#include <assert.h> 36144094Sdas#include <math.h> 37144094Sdas#include <stdio.h> 38144094Sdas#include <stdlib.h> 39144094Sdas#include <strings.h> 40144094Sdas 41144094Sdasstatic void test_invalid(double, double); 42144094Sdasstatic void testd(double, double, double, int); 43144094Sdasstatic void testf(float, float, float, int); 44144094Sdas 45144094Sdas#define test(x, y, e_r, e_q) do { \ 46144094Sdas testd(x, y, e_r, e_q); \ 47144094Sdas testf(x, y, e_r, e_q); \ 48144094Sdas} while (0) 49144094Sdas 50144094Sdasint 51144094Sdasmain(int argc, char *argv[]) 52144094Sdas{ 53144094Sdas 54144094Sdas printf("1..2\n"); 55144094Sdas 56144094Sdas test_invalid(0.0, 0.0); 57144094Sdas test_invalid(1.0, 0.0); 58144094Sdas test_invalid(INFINITY, 0.0); 59144094Sdas test_invalid(INFINITY, 1.0); 60144094Sdas test_invalid(-INFINITY, 1.0); 61144094Sdas test_invalid(NAN, 1.0); 62144094Sdas test_invalid(1.0, NAN); 63144094Sdas 64144094Sdas test(4, 4, 0, 1); 65144094Sdas test(0, 3.0, 0, 0); 66144094Sdas testd(0x1p-1074, 1, 0x1p-1074, 0x1p-1074); 67144094Sdas testf(0x1p-149, 1, 0x1p-149, 0x1p-149); 68144094Sdas test(3.0, 4, -1, 1); 69144094Sdas test(3.0, -4, -1, -1); 70144094Sdas testd(275 * 1193040, 275, 0, 1193040); 71144094Sdas test(4.5 * 7.5, 4.5, -2.25, 8); /* we should get the even one */ 72144094Sdas testf(0x1.9044f6p-1, 0x1.ce662ep-1, -0x1.f109cp-4, 1); 73144094Sdas 74144094Sdas printf("ok 1 - rem\n"); 75144094Sdas 76144094Sdas /* 77144094Sdas * The actual quotient here is 864062210.50000003..., but 78144094Sdas * double-precision division gets -8.64062210.5, which rounds 79144094Sdas * the wrong way. This test ensures that remquo() is smart 80144094Sdas * enough to get the low-order bit right. 81144094Sdas */ 82144094Sdas testd(-0x1.98260f22fc6dep-302, 0x1.fb3167c430a13p-332, 83144094Sdas 0x1.fb3165b82de72p-333, -864062211); 84144094Sdas /* Even harder cases with greater exponent separation */ 85144094Sdas test(0x1.fp100, 0x1.ep-40, -0x1.cp-41, 143165577); 86144094Sdas testd(-0x1.abcdefp120, 0x1.87654321p-120, 87144094Sdas -0x1.69c78ec4p-121, -63816414); 88144094Sdas 89144094Sdas printf("ok 2 - rem\n"); 90144094Sdas 91144094Sdas return (0); 92144094Sdas} 93144094Sdas 94144094Sdasstatic void 95144094Sdastest_invalid(double x, double y) 96144094Sdas{ 97144094Sdas int q; 98144094Sdas 99144094Sdas q = 0xdeadbeef; 100144094Sdas 101144094Sdas assert(isnan(remainder(x, y))); 102144094Sdas assert(isnan(remquo(x, y, &q))); 103144094Sdas assert(q == 0xdeadbeef); 104144094Sdas 105144094Sdas assert(isnan(remainderf(x, y))); 106144094Sdas assert(isnan(remquof(x, y, &q))); 107144094Sdas assert(q == 0xdeadbeef); 108144094Sdas} 109144094Sdas 110144094Sdas/* 0x012345 ==> 0x01ffff */ 111144094Sdasstatic inline int 112144094Sdasmask(int x) 113144094Sdas{ 114144094Sdas return ((unsigned)~0 >> (32 - fls(x))); 115144094Sdas} 116144094Sdas 117144094Sdasstatic void 118144094Sdastestd(double x, double y, double expected_rem, int expected_quo) 119144094Sdas{ 120144094Sdas int q; 121144094Sdas 122144094Sdas q = random(); 123144094Sdas assert(remainder(x, y) == expected_rem); 124144094Sdas assert(remquo(x, y, &q) == expected_rem); 125144094Sdas assert((q & 0x7) == (expected_quo & 0x7)); 126144094Sdas assert((q > 0) ^ !(expected_quo > 0)); 127144094Sdas q = abs(q); 128144094Sdas assert((q & mask(q)) == (abs(expected_quo) & mask(q))); 129144094Sdas} 130144094Sdas 131144094Sdasstatic void 132144094Sdastestf(float x, float y, float expected_rem, int expected_quo) 133144094Sdas{ 134144094Sdas int q; 135144094Sdas 136144094Sdas q = random(); 137144094Sdas assert(remainderf(x, y) == expected_rem); 138144094Sdas assert(remquof(x, y, &q) == expected_rem); 139144094Sdas assert((q & 0x7) == (expected_quo & 0x7)); 140144094Sdas assert((q > 0) ^ !(expected_quo > 0)); 141144094Sdas q = abs(q); 142144094Sdas assert((q & mask(q)) == (abs(expected_quo) & mask(q))); 143144094Sdas} 144