t_acos.c revision 1.7
1/* $NetBSD: t_acos.c,v 1.7 2014/03/03 10:38:36 martin Exp $ */ 2 3/*- 4 * Copyright (c) 2011 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jukka Ruohonen. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <atf-c.h> 33#include <math.h> 34 35#ifdef HAVE_FENV_H 36#include <fenv.h> 37#endif 38 39/* 40 * Check result of fn(arg) is correct within the bounds. 41 * Should be ok to do the checks using 'double' for 'float' functions. 42 */ 43#ifdef HAVE_FENV_H 44#define T_LIBM_CHECK(subtest, fn, arg, expect, epsilon) do { \ 45 double r = fn(arg); \ 46 double e = fabs(r - expect); \ 47 if (e > epsilon) \ 48 atf_tc_fail_nonfatal( \ 49 "subtest %zu: " #fn "(%g) is %g not %g (error %g > %g), roundmode %x", \ 50 subtest, arg, r, expect, e, epsilon, fegetround()); \ 51 } while (0) 52#else 53#define T_LIBM_CHECK(subtest, fn, arg, expect, epsilon) do { \ 54 double r = fn(arg); \ 55 double e = fabs(r - expect); \ 56 if (e > epsilon) \ 57 atf_tc_fail_nonfatal( \ 58 "subtest %zu: " #fn "(%g) is %g not %g (error %g > %g)", \ 59 subtest, arg, r, expect, e, epsilon); \ 60 } while (0) 61#endif 62 63/* Check that the result of fn(arg) is NaN */ 64#ifndef __vax__ 65#define T_LIBM_CHECK_NAN(subtest, fn, arg) do { \ 66 double r = fn(arg); \ 67 if (!isnan(r)) \ 68 atf_tc_fail_nonfatal("subtest %zu: " #fn "(%g) is %g not NaN", \ 69 subtest, arg, r); \ 70 } while (0) 71#else 72/* vax doesn't support NaN */ 73#define T_LIBM_CHECK_NAN(subtest, fn, arg) (void)(arg) 74#endif 75 76#define AFT_LIBM_TEST(name, description) \ 77ATF_TC(name); \ 78ATF_TC_HEAD(name, tc) { atf_tc_set_md_var(tc, "descr", description); } \ 79ATF_TC_BODY(name, tc) 80 81/* 82 * acos(3) and acosf(3) 83 */ 84 85AFT_LIBM_TEST(acos_nan, "Test acos/acosf(x) == NaN, x = NaN, +/-Inf, ![-1..1]") 86{ 87 static const double x[] = { 88 -1.000000001, 1.000000001, 89 -1.0000001, 1.0000001, 90 -1.1, 1.1, 91#ifndef __vax__ 92 0.0L / 0.0L, /* NAN */ 93 -1.0L / 0.0L, /* -Inf */ 94 +1.0L / 0.0L, /* +Inf */ 95#endif 96 }; 97 size_t i; 98 99 for (i = 0; i < __arraycount(x); i++) { 100 T_LIBM_CHECK_NAN(i, acos, x[i]); 101 if (i < 2) 102 /* Values are too small for float */ 103 continue; 104 T_LIBM_CHECK_NAN(i, acosf, x[i]); 105 } 106} 107 108AFT_LIBM_TEST(acos_inrange, "Test acos/acosf(x) for some valid values") 109{ 110 static const struct { 111 double x; 112 double y; 113 } values[] = { 114 { -1, M_PI, }, 115 { -0.99, 3.000053180265366, }, 116 { -0.5, 2.094395102393195, }, 117 { -0.1, 1.670963747956456, }, 118 { 0, M_PI / 2, }, 119 { 0.1, 1.470628905633337, }, 120 { 0.5, 1.047197551196598, }, 121 { 0.99, 0.141539473324427, }, 122 }; 123 size_t i; 124 125 /* 126 * Note that acos(x) might be calculated as atan2(sqrt(1-x*x),x). 127 * This means that acos(-1) is atan2(+0,-1), if the sign is wrong 128 * the value will be -M_PI (atan2(-0,-1)) not M_PI. 129 */ 130 131 for (i = 0; i < __arraycount(values); i++) { 132 T_LIBM_CHECK(i, acos, values[i].x, values[i].y, 1.0e-15); 133 T_LIBM_CHECK(i, acosf, values[i].x, values[i].y, 1.0e-5); 134 } 135} 136 137AFT_LIBM_TEST(acos_one_pos, "Test acos(1.0) == +0.0") 138{ 139 const double y = acos(1.0); 140 141 if (fabs(y) > 0.0 || signbit(y) != 0) 142 atf_tc_fail_nonfatal("acos(1.0) != +0.0"); 143} 144 145AFT_LIBM_TEST(acosf_one_pos, "Test acosf(1.0) == +0.0") 146{ 147 const float y = acosf(1.0); 148 149 if (fabsf(y) > 0.0 || signbit(y) != 0) 150 atf_tc_fail_nonfatal("acosf(1.0) != +0.0"); 151} 152 153ATF_TP_ADD_TCS(tp) 154{ 155 156 ATF_TP_ADD_TC(tp, acos_nan); 157 ATF_TP_ADD_TC(tp, acos_inrange); 158 ATF_TP_ADD_TC(tp, acos_one_pos); 159 ATF_TP_ADD_TC(tp, acosf_one_pos); 160 161 return atf_no_error(); 162} 163