nearbyint_test.c revision 251241
1178825Sdfr/*- 2178825Sdfr * Copyright (c) 2010 David Schultz <das@FreeBSD.org> 3178825Sdfr * All rights reserved. 4178825Sdfr * 5178825Sdfr * Redistribution and use in source and binary forms, with or without 6178825Sdfr * modification, are permitted provided that the following conditions 7178825Sdfr * are met: 8178825Sdfr * 1. Redistributions of source code must retain the above copyright 9178825Sdfr * notice, this list of conditions and the following disclaimer. 10178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright 11178825Sdfr * notice, this list of conditions and the following disclaimer in the 12178825Sdfr * documentation and/or other materials provided with the distribution. 13178825Sdfr * 14178825Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17178825Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24178825Sdfr * SUCH DAMAGE. 25178825Sdfr */ 26178825Sdfr 27178825Sdfr/* 28178825Sdfr * Tests for nearbyint{,f,l}() 29178825Sdfr * 30178825Sdfr * TODO: 31178825Sdfr * - adapt tests for rint(3) 32178825Sdfr * - tests for harder values (more mantissa bits than float) 33178825Sdfr */ 34178825Sdfr 35178825Sdfr#include <sys/cdefs.h> 36178825Sdfr__FBSDID("$FreeBSD: head/tools/regression/lib/msun/test-nearbyint.c 251241 2013-06-02 04:30:03Z das $"); 37178825Sdfr 38178825Sdfr#include <assert.h> 39178825Sdfr#include <fenv.h> 40178825Sdfr#include <math.h> 41178825Sdfr#include <stdio.h> 42178825Sdfr 43178825Sdfr#include "test-utils.h" 44178825Sdfr 45178825Sdfrstatic int testnum; 46178825Sdfr 47178825Sdfrstatic const int rmodes[] = { 48178825Sdfr FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZERO, 49178825Sdfr}; 50178825Sdfr 51178825Sdfr/* Make sure we're testing the library, not some broken compiler built-ins. */ 52178825Sdfrdouble (*libnearbyint)(double) = nearbyint; 53178825Sdfrfloat (*libnearbyintf)(float) = nearbyintf; 54178825Sdfrlong double (*libnearbyintl)(long double) = nearbyintl; 55178825Sdfr#define nearbyintf libnearbyintf 56178825Sdfr#define nearbyint libnearbyint 57178825Sdfr#define nearbyintl libnearbyintl 58178825Sdfr 59178825Sdfrstatic const struct { 60178825Sdfr float in; 61178825Sdfr float out[3]; /* one answer per rounding mode except towardzero */ 62178825Sdfr} tests[] = { 63178825Sdfr/* input output (expected) */ 64178825Sdfr { 0.0, { 0.0, 0.0, 0.0 }}, 65178825Sdfr { 0.5, { 0.0, 0.0, 1.0 }}, 66178825Sdfr { M_PI, { 3.0, 3.0, 4.0 }}, 67178825Sdfr { 65536.5, { 65536, 65536, 65537 }}, 68178825Sdfr { INFINITY, { INFINITY, INFINITY, INFINITY }}, 69178825Sdfr { NAN, { NAN, NAN, NAN }}, 70178825Sdfr}; 71178825Sdfr 72178825Sdfrstatic const int ntests = sizeof(tests) / sizeof(tests[0]); 73178825Sdfr 74178825Sdfr/* Get the appropriate result for the current rounding mode. */ 75178825Sdfrstatic float 76178825Sdfrget_output(int testindex, int rmodeindex, int negative) 77178825Sdfr{ 78178825Sdfr double out; 79178825Sdfr 80178825Sdfr if (negative) { /* swap downwards and upwards if input is negative */ 81178825Sdfr if (rmodeindex == 1) 82178825Sdfr rmodeindex = 2; 83178825Sdfr else if (rmodeindex == 2) 84178825Sdfr rmodeindex = 1; 85178825Sdfr } 86 if (rmodeindex == 3) /* FE_TOWARDZERO uses the value for downwards */ 87 rmodeindex = 1; 88 out = tests[testindex].out[rmodeindex]; 89 return (negative ? -out : out); 90} 91 92static void 93test_nearby(int testindex) 94{ 95 float in, out; 96 int i; 97 98 for (i = 0; i < sizeof(rmodes) / sizeof(rmodes[0]); i++) { 99 fesetround(rmodes[i]); 100 feclearexcept(ALL_STD_EXCEPT); 101 102 in = tests[testindex].in; 103 out = get_output(testindex, i, 0); 104 assert(fpequal(out, libnearbyintf(in))); 105 assert(fpequal(out, nearbyint(in))); 106 assert(fpequal(out, nearbyintl(in))); 107 assert(fetestexcept(ALL_STD_EXCEPT) == 0); 108 109 in = -tests[testindex].in; 110 out = get_output(testindex, i, 1); 111 assert(fpequal(out, nearbyintf(in))); 112 assert(fpequal(out, nearbyint(in))); 113 assert(fpequal(out, nearbyintl(in))); 114 assert(fetestexcept(ALL_STD_EXCEPT) == 0); 115 } 116 117 printf("ok %d\t\t# nearbyint(+%g)\n", testnum++, in); 118} 119 120static void 121test_modf(int testindex) 122{ 123 float in, out; 124 float ipartf, ipart_expected; 125 double ipart; 126 long double ipartl; 127 int i; 128 129 for (i = 0; i < sizeof(rmodes) / sizeof(rmodes[0]); i++) { 130 fesetround(rmodes[i]); 131 feclearexcept(ALL_STD_EXCEPT); 132 133 in = tests[testindex].in; 134 ipart_expected = tests[testindex].out[1]; 135 out = copysignf( 136 isinf(ipart_expected) ? 0.0 : in - ipart_expected, in); 137 ipartl = ipart = ipartf = 42.0; 138 139 assert(fpequal(out, modff(in, &ipartf))); 140 assert(fpequal(ipart_expected, ipartf)); 141 assert(fpequal(out, modf(in, &ipart))); 142 assert(fpequal(ipart_expected, ipart)); 143 assert(fpequal(out, modfl(in, &ipartl))); 144 assert(fpequal(ipart_expected, ipartl)); 145 assert(fetestexcept(ALL_STD_EXCEPT) == 0); 146 147 in = -in; 148 ipart_expected = -ipart_expected; 149 out = -out; 150 ipartl = ipart = ipartf = 42.0; 151 assert(fpequal(out, modff(in, &ipartf))); 152 assert(fpequal(ipart_expected, ipartf)); 153 assert(fpequal(out, modf(in, &ipart))); 154 assert(fpequal(ipart_expected, ipart)); 155 assert(fpequal(out, modfl(in, &ipartl))); 156 assert(fpequal(ipart_expected, ipartl)); 157 assert(fetestexcept(ALL_STD_EXCEPT) == 0); 158 } 159 160 printf("ok %d\t\t# modf(+%g)\n", testnum++, in); 161} 162 163int 164main(int argc, char *argv[]) 165{ 166 int i; 167 168 printf("1..%d\n", ntests * 2); 169 testnum = 1; 170 for (i = 0; i < ntests; i++) { 171 test_nearby(i); 172 test_modf(i); 173 } 174 175 return (0); 176} 177