1216139Sdas/*- 2216139Sdas * Copyright (c) 2010 David Schultz <das@FreeBSD.org> 3216139Sdas * All rights reserved. 4216139Sdas * 5216139Sdas * Redistribution and use in source and binary forms, with or without 6216139Sdas * modification, are permitted provided that the following conditions 7216139Sdas * are met: 8216139Sdas * 1. Redistributions of source code must retain the above copyright 9216139Sdas * notice, this list of conditions and the following disclaimer. 10216139Sdas * 2. Redistributions in binary form must reproduce the above copyright 11216139Sdas * notice, this list of conditions and the following disclaimer in the 12216139Sdas * documentation and/or other materials provided with the distribution. 13216139Sdas * 14216139Sdas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15216139Sdas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16216139Sdas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17216139Sdas * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18216139Sdas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19216139Sdas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20216139Sdas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21216139Sdas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22216139Sdas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23216139Sdas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24216139Sdas * SUCH DAMAGE. 25216139Sdas */ 26216139Sdas 27216139Sdas/* 28216139Sdas * Tests for nearbyint{,f,l}() 29216139Sdas * 30216139Sdas * TODO: 31216139Sdas * - adapt tests for rint(3) 32216139Sdas * - tests for harder values (more mantissa bits than float) 33216139Sdas */ 34216139Sdas 35216139Sdas#include <sys/cdefs.h> 36216139Sdas__FBSDID("$FreeBSD: releng/11.0/lib/msun/tests/nearbyint_test.c 292328 2015-12-16 09:11:11Z ngie $"); 37216139Sdas 38216139Sdas#include <assert.h> 39216139Sdas#include <fenv.h> 40216139Sdas#include <math.h> 41216139Sdas#include <stdio.h> 42216139Sdas 43251241Sdas#include "test-utils.h" 44216139Sdas 45226605Sdasstatic int testnum; 46226605Sdas 47226605Sdasstatic const int rmodes[] = { 48226605Sdas FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZERO, 49226605Sdas}; 50226605Sdas 51251241Sdas/* Make sure we're testing the library, not some broken compiler built-ins. */ 52251241Sdasdouble (*libnearbyint)(double) = nearbyint; 53251241Sdasfloat (*libnearbyintf)(float) = nearbyintf; 54251241Sdaslong double (*libnearbyintl)(long double) = nearbyintl; 55251241Sdas#define nearbyintf libnearbyintf 56251241Sdas#define nearbyint libnearbyint 57251241Sdas#define nearbyintl libnearbyintl 58251241Sdas 59226605Sdasstatic const struct { 60226605Sdas float in; 61226605Sdas float out[3]; /* one answer per rounding mode except towardzero */ 62226605Sdas} tests[] = { 63226605Sdas/* input output (expected) */ 64226605Sdas { 0.0, { 0.0, 0.0, 0.0 }}, 65226605Sdas { 0.5, { 0.0, 0.0, 1.0 }}, 66226605Sdas { M_PI, { 3.0, 3.0, 4.0 }}, 67226605Sdas { 65536.5, { 65536, 65536, 65537 }}, 68226605Sdas { INFINITY, { INFINITY, INFINITY, INFINITY }}, 69226605Sdas { NAN, { NAN, NAN, NAN }}, 70226605Sdas}; 71226605Sdas 72226605Sdasstatic const int ntests = sizeof(tests) / sizeof(tests[0]); 73226605Sdas 74226605Sdas/* Get the appropriate result for the current rounding mode. */ 75226605Sdasstatic float 76226605Sdasget_output(int testindex, int rmodeindex, int negative) 77216139Sdas{ 78226605Sdas double out; 79216139Sdas 80226605Sdas if (negative) { /* swap downwards and upwards if input is negative */ 81226605Sdas if (rmodeindex == 1) 82226605Sdas rmodeindex = 2; 83226605Sdas else if (rmodeindex == 2) 84226605Sdas rmodeindex = 1; 85226605Sdas } 86226605Sdas if (rmodeindex == 3) /* FE_TOWARDZERO uses the value for downwards */ 87226605Sdas rmodeindex = 1; 88226605Sdas out = tests[testindex].out[rmodeindex]; 89226605Sdas return (negative ? -out : out); 90226605Sdas} 91216139Sdas 92226605Sdasstatic void 93226605Sdastest_nearby(int testindex) 94226605Sdas{ 95226605Sdas float in, out; 96226605Sdas int i; 97216139Sdas 98226605Sdas for (i = 0; i < sizeof(rmodes) / sizeof(rmodes[0]); i++) { 99226605Sdas fesetround(rmodes[i]); 100226605Sdas feclearexcept(ALL_STD_EXCEPT); 101216139Sdas 102226605Sdas in = tests[testindex].in; 103226605Sdas out = get_output(testindex, i, 0); 104251241Sdas assert(fpequal(out, libnearbyintf(in))); 105226605Sdas assert(fpequal(out, nearbyint(in))); 106226605Sdas assert(fpequal(out, nearbyintl(in))); 107226605Sdas assert(fetestexcept(ALL_STD_EXCEPT) == 0); 108226605Sdas 109226605Sdas in = -tests[testindex].in; 110226605Sdas out = get_output(testindex, i, 1); 111226605Sdas assert(fpequal(out, nearbyintf(in))); 112226605Sdas assert(fpequal(out, nearbyint(in))); 113226605Sdas assert(fpequal(out, nearbyintl(in))); 114226605Sdas assert(fetestexcept(ALL_STD_EXCEPT) == 0); 115226605Sdas } 116226605Sdas 117226605Sdas printf("ok %d\t\t# nearbyint(+%g)\n", testnum++, in); 118216139Sdas} 119216139Sdas 120226605Sdasstatic void 121226605Sdastest_modf(int testindex) 122226605Sdas{ 123226605Sdas float in, out; 124226605Sdas float ipartf, ipart_expected; 125226605Sdas double ipart; 126226605Sdas long double ipartl; 127226605Sdas int i; 128216139Sdas 129226605Sdas for (i = 0; i < sizeof(rmodes) / sizeof(rmodes[0]); i++) { 130226605Sdas fesetround(rmodes[i]); 131226605Sdas feclearexcept(ALL_STD_EXCEPT); 132226605Sdas 133226605Sdas in = tests[testindex].in; 134226605Sdas ipart_expected = tests[testindex].out[1]; 135226605Sdas out = copysignf( 136226605Sdas isinf(ipart_expected) ? 0.0 : in - ipart_expected, in); 137226605Sdas ipartl = ipart = ipartf = 42.0; 138226605Sdas 139226605Sdas assert(fpequal(out, modff(in, &ipartf))); 140226605Sdas assert(fpequal(ipart_expected, ipartf)); 141226605Sdas assert(fpequal(out, modf(in, &ipart))); 142226605Sdas assert(fpequal(ipart_expected, ipart)); 143226605Sdas assert(fpequal(out, modfl(in, &ipartl))); 144226605Sdas assert(fpequal(ipart_expected, ipartl)); 145226605Sdas assert(fetestexcept(ALL_STD_EXCEPT) == 0); 146226605Sdas 147226605Sdas in = -in; 148226605Sdas ipart_expected = -ipart_expected; 149226605Sdas out = -out; 150226605Sdas ipartl = ipart = ipartf = 42.0; 151226605Sdas assert(fpequal(out, modff(in, &ipartf))); 152226605Sdas assert(fpequal(ipart_expected, ipartf)); 153226605Sdas assert(fpequal(out, modf(in, &ipart))); 154226605Sdas assert(fpequal(ipart_expected, ipart)); 155226605Sdas assert(fpequal(out, modfl(in, &ipartl))); 156226605Sdas assert(fpequal(ipart_expected, ipartl)); 157226605Sdas assert(fetestexcept(ALL_STD_EXCEPT) == 0); 158226605Sdas } 159226605Sdas 160226605Sdas printf("ok %d\t\t# modf(+%g)\n", testnum++, in); 161226605Sdas} 162226605Sdas 163216139Sdasint 164216139Sdasmain(int argc, char *argv[]) 165216139Sdas{ 166216139Sdas int i; 167216139Sdas 168226605Sdas printf("1..%d\n", ntests * 2); 169226605Sdas testnum = 1; 170226605Sdas for (i = 0; i < ntests; i++) { 171226605Sdas test_nearby(i); 172226605Sdas test_modf(i); 173226605Sdas } 174216139Sdas 175216139Sdas return (0); 176216139Sdas} 177