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