diff options
Diffstat (limited to 'lib/libm')
-rw-r--r-- | lib/libm/Makefile | 44 | ||||
-rw-r--r-- | lib/libm/t_acos.c | 105 | ||||
-rw-r--r-- | lib/libm/t_asin.c | 296 | ||||
-rw-r--r-- | lib/libm/t_atan.c | 101 | ||||
-rw-r--r-- | lib/libm/t_cbrt.c | 366 | ||||
-rw-r--r-- | lib/libm/t_ceil.c | 931 | ||||
-rw-r--r-- | lib/libm/t_cos.c | 263 | ||||
-rw-r--r-- | lib/libm/t_cosh.c | 270 | ||||
-rw-r--r-- | lib/libm/t_erf.c | 299 | ||||
-rw-r--r-- | lib/libm/t_exp.c | 567 | ||||
-rw-r--r-- | lib/libm/t_fmod.c | 63 | ||||
-rw-r--r-- | lib/libm/t_infinity.c | 119 | ||||
-rw-r--r-- | lib/libm/t_ldexp.c | 481 | ||||
-rw-r--r-- | lib/libm/t_libm.h | 62 | ||||
-rw-r--r-- | lib/libm/t_log.c | 885 | ||||
-rw-r--r-- | lib/libm/t_modf.c | 68 | ||||
-rw-r--r-- | lib/libm/t_pow.c | 669 | ||||
-rw-r--r-- | lib/libm/t_precision.c | 76 | ||||
-rw-r--r-- | lib/libm/t_round.c | 85 | ||||
-rw-r--r-- | lib/libm/t_scalbn.c | 523 | ||||
-rw-r--r-- | lib/libm/t_sin.c | 263 | ||||
-rw-r--r-- | lib/libm/t_sinh.c | 273 | ||||
-rw-r--r-- | lib/libm/t_sqrt.c | 368 | ||||
-rw-r--r-- | lib/libm/t_tan.c | 260 | ||||
-rw-r--r-- | lib/libm/t_tanh.c | 207 |
25 files changed, 7644 insertions, 0 deletions
diff --git a/lib/libm/Makefile b/lib/libm/Makefile new file mode 100644 index 000000000000..d45cb90cbe83 --- /dev/null +++ b/lib/libm/Makefile @@ -0,0 +1,44 @@ +# $NetBSD: Makefile,v 1.26 2014/08/10 11:30:51 martin Exp $ + +.include <bsd.own.mk> + +TESTSDIR= ${TESTSBASE}/lib/libm + +.if ${MACHINE_CPU} == "aarch64" || ${MACHINE_CPU} == "arm" \ + || ${MACHINE_ARCH} == "sparc" || ${MACHINE_ARCH} == "sparc64" \ + || ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "x86_64" +CPPFLAGS+= -DHAVE_FENV_H +.endif + +.if ${MACHINE} == "alpha" +COPTS+= -mfloat-ieee -mieee-with-inexact -mfp-trap-mode=sui -mtrap-precision=i +.endif + +TESTS_C+= t_acos +TESTS_C+= t_asin +TESTS_C+= t_atan +TESTS_C+= t_cbrt +TESTS_C+= t_ceil +TESTS_C+= t_cos +TESTS_C+= t_cosh +TESTS_C+= t_erf +TESTS_C+= t_exp +TESTS_C+= t_fmod +TESTS_C+= t_infinity +TESTS_C+= t_ldexp +TESTS_C+= t_log +TESTS_C+= t_modf +TESTS_C+= t_pow +TESTS_C+= t_precision +TESTS_C+= t_round +TESTS_C+= t_scalbn +TESTS_C+= t_sin +TESTS_C+= t_sinh +TESTS_C+= t_sqrt +TESTS_C+= t_tan +TESTS_C+= t_tanh + +LDADD+= -lm +#COPTS+= -Wfloat-equal + +.include <bsd.test.mk> diff --git a/lib/libm/t_acos.c b/lib/libm/t_acos.c new file mode 100644 index 000000000000..f051fb64df42 --- /dev/null +++ b/lib/libm/t_acos.c @@ -0,0 +1,105 @@ +/* $NetBSD: t_acos.c,v 1.10 2014/03/05 20:14:46 dsl Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <atf-c.h> +#include <math.h> +#include "t_libm.h" + +/* + * acos(3) and acosf(3) + */ + +ATF_LIBM_TEST(acos_is_nan, "Test acos/acosf(x) == NaN, x = NaN, +/-Inf, ![-1..1]") +{ + static const double x[] = { + -1.000000001, 1.000000001, + -1.0000001, 1.0000001, + -1.1, 1.1, +#ifndef __vax__ + T_LIBM_NAN, + T_LIBM_MINUS_INF, T_LIBM_PLUS_INF, +#endif + }; + unsigned int i; + + for (i = 0; i < __arraycount(x); i++) { + T_LIBM_CHECK_NAN(i, acos, x[i]); + if (i < 2) + /* Values are too small for float */ + continue; + T_LIBM_CHECK_NAN(i, acosf, x[i]); + } +} + +ATF_LIBM_TEST(acos_inrange, "Test acos/acosf(x) for some valid values") +{ + static const struct { + double x; + double y; + } values[] = { + { -1, M_PI, }, + { -0.99, 3.000053180265366, }, + { -0.5, 2.094395102393195, }, + { -0.1, 1.670963747956456, }, + { 0, M_PI / 2, }, + { 0.1, 1.470628905633337, }, + { 0.5, 1.047197551196598, }, + { 0.99, 0.141539473324427, }, + }; + unsigned int i; + + /* + * Note that acos(x) might be calculated as atan2(sqrt(1-x*x),x). + * This means that acos(-1) is atan2(+0,-1), if the sign is wrong + * the value will be -M_PI (atan2(-0,-1)) not M_PI. + */ + + for (i = 0; i < __arraycount(values); i++) { + T_LIBM_CHECK(i, acos, values[i].x, values[i].y, 1.0e-15); + T_LIBM_CHECK(i, acosf, values[i].x, values[i].y, 1.0e-5); + } +} + +ATF_LIBM_TEST(acos_is_plus_zero, "Test acosf(1.0) == +0.0") +{ + T_LIBM_CHECK_PLUS_ZERO(0, acos, 1.0); + T_LIBM_CHECK_PLUS_ZERO(0, acosf, 1.0); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, acos_inrange); + ATF_TP_ADD_TC(tp, acos_is_nan); + ATF_TP_ADD_TC(tp, acos_is_plus_zero); + + return atf_no_error(); +} diff --git a/lib/libm/t_asin.c b/lib/libm/t_asin.c new file mode 100644 index 000000000000..06de85216429 --- /dev/null +++ b/lib/libm/t_asin.c @@ -0,0 +1,296 @@ +/* $NetBSD: t_asin.c,v 1.3 2014/03/03 10:39:08 martin Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <atf-c.h> +#include <math.h> + +static const struct { + double x; + double y; +} values[] = { + { -1.0, -M_PI / 2, }, + { -0.9, -1.119769514998634, }, + { -0.5, -M_PI / 6, }, + { -0.1, -0.1001674211615598, }, + { 0.1, 0.1001674211615598, }, + { 0.5, M_PI / 6, }, + { 0.9, 1.119769514998634, }, + { 1.0, M_PI / 2, }, +}; + +/* + * asin(3) + */ +ATF_TC(asin_nan); +ATF_TC_HEAD(asin_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test asin(NaN) == NaN"); +} + +ATF_TC_BODY(asin_nan, tc) +{ + const double x = 0.0L / 0.0L; + + if (isnan(asin(x)) == 0) + atf_tc_fail_nonfatal("asin(NaN) != NaN"); +} + +ATF_TC(asin_inf_neg); +ATF_TC_HEAD(asin_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test asin(-Inf) == NaN"); +} + +ATF_TC_BODY(asin_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + + if (isnan(asin(x)) == 0) + atf_tc_fail_nonfatal("asin(-Inf) != NaN"); +} + +ATF_TC(asin_inf_pos); +ATF_TC_HEAD(asin_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test asin(+Inf) == NaN"); +} + +ATF_TC_BODY(asin_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + + if (isnan(asin(x)) == 0) + atf_tc_fail_nonfatal("asin(+Inf) != NaN"); +} + +ATF_TC(asin_range); +ATF_TC_HEAD(asin_range, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test asin(x) == NaN, x < -1, x > 1"); +} + +ATF_TC_BODY(asin_range, tc) +{ + const double x[] = { -1.1, -1.000000001, 1.1, 1.000000001 }; + size_t i; + + for (i = 0; i < __arraycount(x); i++) { + + if (isnan(asin(x[i])) == 0) + atf_tc_fail_nonfatal("asin(%f) != NaN", x[i]); + } +} + +ATF_TC(asin_inrange); +ATF_TC_HEAD(asin_inrange, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test asin(x) for some values"); +} + +ATF_TC_BODY(asin_inrange, tc) +{ + const double eps = 1.0e-15; + double y; + size_t i; + + for (i = 0; i < __arraycount(values); i++) { + y = asin(values[i].x); + if (fabs(y - values[i].y) > eps) + atf_tc_fail_nonfatal("asin(%g) != %g", + values[i].x, values[i].y); + } +} + +ATF_TC(asin_zero_neg); +ATF_TC_HEAD(asin_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test asin(-0.0) == -0.0"); +} + +ATF_TC_BODY(asin_zero_neg, tc) +{ + const double x = -0.0L; + double y = asin(x); + + if (fabs(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("asin(-0.0) != -0.0"); +} + +ATF_TC(asin_zero_pos); +ATF_TC_HEAD(asin_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test asin(+0.0) == +0.0"); +} + +ATF_TC_BODY(asin_zero_pos, tc) +{ + const double x = 0.0L; + double y = asin(x); + + if (fabs(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("asin(+0.0) != +0.0"); +} + +/* + * asinf(3) + */ +ATF_TC(asinf_nan); +ATF_TC_HEAD(asinf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test asinf(NaN) == NaN"); +} + +ATF_TC_BODY(asinf_nan, tc) +{ + const float x = 0.0L / 0.0L; + + if (isnan(asinf(x)) == 0) + atf_tc_fail_nonfatal("asinf(NaN) != NaN"); +} + +ATF_TC(asinf_inf_neg); +ATF_TC_HEAD(asinf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test asinf(-Inf) == NaN"); +} + +ATF_TC_BODY(asinf_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + + if (isnan(asinf(x)) == 0) + atf_tc_fail_nonfatal("asinf(-Inf) != NaN"); +} + +ATF_TC(asinf_inf_pos); +ATF_TC_HEAD(asinf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test asinf(+Inf) == NaN"); +} + +ATF_TC_BODY(asinf_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + + if (isnan(asinf(x)) == 0) + atf_tc_fail_nonfatal("asinf(+Inf) != NaN"); +} + +ATF_TC(asinf_range); +ATF_TC_HEAD(asinf_range, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test asinf(x) == NaN, x < -1, x > 1"); +} + +ATF_TC_BODY(asinf_range, tc) +{ + const float x[] = { -1.1, -1.0000001, 1.1, 1.0000001 }; + size_t i; + + for (i = 0; i < __arraycount(x); i++) { + + if (isnan(asinf(x[i])) == 0) + atf_tc_fail_nonfatal("asinf(%f) != NaN", x[i]); + } +} + +ATF_TC(asinf_inrange); +ATF_TC_HEAD(asinf_inrange, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test asinf(x) for some values"); +} + +ATF_TC_BODY(asinf_inrange, tc) +{ + const float eps = 1.0e-6; + float x; + float y; + size_t i; + + for (i = 0; i < __arraycount(values); i++) { + x = values[i].x; + y = values[i].y; + if (fabs(asinf(x) - y) > eps) + atf_tc_fail_nonfatal("asinf(%g) != %g", x, y); + } +} + +ATF_TC(asinf_zero_neg); +ATF_TC_HEAD(asinf_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test asinf(-0.0) == -0.0"); +} + +ATF_TC_BODY(asinf_zero_neg, tc) +{ + const float x = -0.0L; + float y = asinf(x); + + if (fabsf(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("asinf(-0.0) != -0.0"); +} + +ATF_TC(asinf_zero_pos); +ATF_TC_HEAD(asinf_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test asinf(+0.0) == +0.0"); +} + +ATF_TC_BODY(asinf_zero_pos, tc) +{ + const float x = 0.0L; + float y = asinf(x); + + if (fabsf(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("asinf(+0.0) != +0.0"); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, asin_nan); + ATF_TP_ADD_TC(tp, asin_inf_neg); + ATF_TP_ADD_TC(tp, asin_inf_pos); + ATF_TP_ADD_TC(tp, asin_range); + ATF_TP_ADD_TC(tp, asin_inrange); + ATF_TP_ADD_TC(tp, asin_zero_neg); + ATF_TP_ADD_TC(tp, asin_zero_pos); + + ATF_TP_ADD_TC(tp, asinf_nan); + ATF_TP_ADD_TC(tp, asinf_inf_neg); + ATF_TP_ADD_TC(tp, asinf_inf_pos); + ATF_TP_ADD_TC(tp, asinf_range); + ATF_TP_ADD_TC(tp, asinf_inrange); + ATF_TP_ADD_TC(tp, asinf_zero_neg); + ATF_TP_ADD_TC(tp, asinf_zero_pos); + + return atf_no_error(); +} diff --git a/lib/libm/t_atan.c b/lib/libm/t_atan.c new file mode 100644 index 000000000000..c3aa15f773c1 --- /dev/null +++ b/lib/libm/t_atan.c @@ -0,0 +1,101 @@ +/* $NetBSD: t_atan.c,v 1.15 2014/03/17 11:08:11 martin Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <atf-c.h> +#include <math.h> +#include "t_libm.h" + +static const struct { + double x; + double y; +} values[] = { +#ifndef __vax__ + /* vax has no +/- INF */ + { T_LIBM_MINUS_INF, -M_PI / 2 }, + { T_LIBM_PLUS_INF, M_PI / 2 }, +#endif + { -100, -1.560796660108231, }, + { -10, -1.471127674303735, }, + { -1, -M_PI / 4, }, + { -0.1, -0.09966865249116204, }, + { 0.1, 0.09966865249116204, }, + { 1, M_PI / 4, }, + { 10, 1.471127674303735, }, + { 100, 1.560796660108231, }, +}; + +/* + * atan(3) + */ +ATF_LIBM_TEST(atan_nan, "Test atan/atanf(NaN) == NaN") +{ +#ifdef T_LIBM_NAN + T_LIBM_CHECK_NAN(0, atan, T_LIBM_NAN); + T_LIBM_CHECK_NAN(0, atanf, T_LIBM_NAN); +#else + atf_tc_skip("no NaN on this machine"); +#endif +} + +ATF_LIBM_TEST(atan_inrange, "Test atan/atanf(x) for some values") +{ + unsigned int i; + + for (i = 0; i < __arraycount(values); i++) { + T_LIBM_CHECK(i, atan, values[i].x, values[i].y, 1.0e-15); + T_LIBM_CHECK(i, atanf, values[i].x, values[i].y, 1.0e-7); + } +} + +ATF_LIBM_TEST(atan_zero_neg, "Test atan/atanf(-0.0) == -0.0") +{ + + T_LIBM_CHECK_MINUS_ZERO(0, atan, -0.0); + T_LIBM_CHECK_MINUS_ZERO(0, atanf, -0.0); +} + +ATF_LIBM_TEST(atan_zero_pos, "Test atan/atanf(+0.0) == +0.0") +{ + + T_LIBM_CHECK_PLUS_ZERO(0, atan, +0.0); + T_LIBM_CHECK_PLUS_ZERO(0, atanf, +0.0); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, atan_nan); + ATF_TP_ADD_TC(tp, atan_inrange); + ATF_TP_ADD_TC(tp, atan_zero_neg); + ATF_TP_ADD_TC(tp, atan_zero_pos); + + return atf_no_error(); +} diff --git a/lib/libm/t_cbrt.c b/lib/libm/t_cbrt.c new file mode 100644 index 000000000000..a7de9f629815 --- /dev/null +++ b/lib/libm/t_cbrt.c @@ -0,0 +1,366 @@ +/* $NetBSD: t_cbrt.c,v 1.3 2014/03/03 10:39:08 martin Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__RCSID("$NetBSD: t_cbrt.c,v 1.3 2014/03/03 10:39:08 martin Exp $"); + +#include <atf-c.h> +#include <math.h> +#include <stdio.h> + +/* + * cbrt(3) + */ +ATF_TC(cbrt_nan); +ATF_TC_HEAD(cbrt_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cbrt(NaN) == NaN"); +} + +ATF_TC_BODY(cbrt_nan, tc) +{ + const double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(cbrt(x)) != 0); +} + +ATF_TC(cbrt_pow); +ATF_TC_HEAD(cbrt_pow, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cbrt(3) vs. pow(3)"); +} + +ATF_TC_BODY(cbrt_pow, tc) +{ + const double x[] = { 0.0, 0.005, 1.0, 99.0, 123.123, 9999.0 }; + const double eps = 1.0e-14; + double y, z; + size_t i; + + for (i = 0; i < __arraycount(x); i++) { + + y = cbrt(x[i]); + z = pow(x[i], 1.0 / 3.0); + + if (fabs(y - z) > eps) + atf_tc_fail_nonfatal("cbrt(%0.03f) != " + "pow(%0.03f, 1/3)\n", x[i], x[i]); + } +} + +ATF_TC(cbrt_inf_neg); +ATF_TC_HEAD(cbrt_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cbrt(-Inf) == -Inf"); +} + +ATF_TC_BODY(cbrt_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + double y = cbrt(x); + + ATF_CHECK(isinf(y) != 0); + ATF_CHECK(signbit(y) != 0); +} + +ATF_TC(cbrt_inf_pos); +ATF_TC_HEAD(cbrt_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cbrt(+Inf) == +Inf"); +} + +ATF_TC_BODY(cbrt_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + double y = cbrt(x); + + ATF_CHECK(isinf(y) != 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TC(cbrt_zero_neg); +ATF_TC_HEAD(cbrt_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cbrt(-0.0) == -0.0"); +} + +ATF_TC_BODY(cbrt_zero_neg, tc) +{ + const double x = -0.0L; + double y = cbrt(x); + + if (fabs(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("cbrt(-0.0) != -0.0"); +} + +ATF_TC(cbrt_zero_pos); +ATF_TC_HEAD(cbrt_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cbrt(+0.0) == +0.0"); +} + +ATF_TC_BODY(cbrt_zero_pos, tc) +{ + const double x = 0.0L; + double y = cbrt(x); + + if (fabs(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("cbrt(+0.0) != +0.0"); +} + +/* + * cbrtf(3) + */ +ATF_TC(cbrtf_nan); +ATF_TC_HEAD(cbrtf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cbrtf(NaN) == NaN"); +} + +ATF_TC_BODY(cbrtf_nan, tc) +{ + const float x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(cbrtf(x)) != 0); +} + +ATF_TC(cbrtf_powf); +ATF_TC_HEAD(cbrtf_powf, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cbrtf(3) vs. powf(3)"); +} + +ATF_TC_BODY(cbrtf_powf, tc) +{ + const float x[] = { 0.0, 0.005, 1.0, 99.0, 123.123, 9999.0 }; + const float eps = 1.0e-5; + float y, z; + size_t i; + + for (i = 0; i < __arraycount(x); i++) { + + y = cbrtf(x[i]); + z = powf(x[i], 1.0 / 3.0); + + if (fabsf(y - z) > eps) + atf_tc_fail_nonfatal("cbrtf(%0.03f) != " + "powf(%0.03f, 1/3)\n", x[i], x[i]); + } +} + +ATF_TC(cbrtf_inf_neg); +ATF_TC_HEAD(cbrtf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cbrtf(-Inf) == -Inf"); +} + +ATF_TC_BODY(cbrtf_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + float y = cbrtf(x); + + ATF_CHECK(isinf(y) != 0); + ATF_CHECK(signbit(y) != 0); +} + +ATF_TC(cbrtf_inf_pos); +ATF_TC_HEAD(cbrtf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cbrtf(+Inf) == +Inf"); +} + +ATF_TC_BODY(cbrtf_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + float y = cbrtf(x); + + ATF_CHECK(isinf(y) != 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TC(cbrtf_zero_neg); +ATF_TC_HEAD(cbrtf_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cbrtf(-0.0) == -0.0"); +} + +ATF_TC_BODY(cbrtf_zero_neg, tc) +{ + const float x = -0.0L; + float y = cbrtf(x); + + if (fabsf(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("cbrtf(-0.0) != -0.0"); +} + +ATF_TC(cbrtf_zero_pos); +ATF_TC_HEAD(cbrtf_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cbrtf(+0.0) == +0.0"); +} + +ATF_TC_BODY(cbrtf_zero_pos, tc) +{ + const float x = 0.0L; + float y = cbrtf(x); + + if (fabsf(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("cbrtf(+0.0) != +0.0"); +} + +/* + * cbrtl(3) + */ +ATF_TC(cbrtl_nan); +ATF_TC_HEAD(cbrtl_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cbrtl(NaN) == NaN"); +} + +ATF_TC_BODY(cbrtl_nan, tc) +{ + const long double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(cbrtl(x)) != 0); +} + +ATF_TC(cbrtl_powl); +ATF_TC_HEAD(cbrtl_powl, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cbrtl(3) vs. powl(3)"); +} + +ATF_TC_BODY(cbrtl_powl, tc) +{ + const long double x[] = { 0.0, 0.005, 1.0, 99.0, 123.123, 9999.0 }; + const long double eps = 1.0e-15; + long double y, z; + size_t i; + + for (i = 0; i < __arraycount(x); i++) { + + y = cbrtl(x[i]); + z = powl(x[i], 1.0 / 3.0); + + if (fabsl(y - z) > eps * fabsl(1 + x[i])) + atf_tc_fail_nonfatal("cbrtl(%0.03Lf) != " + "powl(%0.03Lf, 1/3)\n", x[i], x[i]); + } +} + +ATF_TC(cbrtl_inf_neg); +ATF_TC_HEAD(cbrtl_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cbrtl(-Inf) == -Inf"); +} + +ATF_TC_BODY(cbrtl_inf_neg, tc) +{ + const long double x = -1.0L / 0.0L; + long double y = cbrtl(x); + + ATF_CHECK(isinf(y) != 0); + ATF_CHECK(signbit(y) != 0); +} + +ATF_TC(cbrtl_inf_pos); +ATF_TC_HEAD(cbrtl_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cbrtl(+Inf) == +Inf"); +} + +ATF_TC_BODY(cbrtl_inf_pos, tc) +{ + const long double x = 1.0L / 0.0L; + long double y = cbrtl(x); + + ATF_CHECK(isinf(y) != 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TC(cbrtl_zero_neg); +ATF_TC_HEAD(cbrtl_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cbrtl(-0.0) == -0.0"); +} + +ATF_TC_BODY(cbrtl_zero_neg, tc) +{ + const long double x = -0.0L; + long double y = cbrtl(x); + + if (fabsl(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("cbrtl(-0.0) != -0.0"); +} + +ATF_TC(cbrtl_zero_pos); +ATF_TC_HEAD(cbrtl_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cbrtl(+0.0) == +0.0"); +} + +ATF_TC_BODY(cbrtl_zero_pos, tc) +{ + const long double x = 0.0L; + long double y = cbrtl(x); + + if (fabsl(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("cbrtl(+0.0) != +0.0"); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, cbrt_nan); + ATF_TP_ADD_TC(tp, cbrt_pow); + ATF_TP_ADD_TC(tp, cbrt_inf_neg); + ATF_TP_ADD_TC(tp, cbrt_inf_pos); + ATF_TP_ADD_TC(tp, cbrt_zero_neg); + ATF_TP_ADD_TC(tp, cbrt_zero_pos); + + ATF_TP_ADD_TC(tp, cbrtf_nan); + ATF_TP_ADD_TC(tp, cbrtf_powf); + ATF_TP_ADD_TC(tp, cbrtf_inf_neg); + ATF_TP_ADD_TC(tp, cbrtf_inf_pos); + ATF_TP_ADD_TC(tp, cbrtf_zero_neg); + ATF_TP_ADD_TC(tp, cbrtf_zero_pos); + + ATF_TP_ADD_TC(tp, cbrtl_nan); + ATF_TP_ADD_TC(tp, cbrtl_powl); + ATF_TP_ADD_TC(tp, cbrtl_inf_neg); + ATF_TP_ADD_TC(tp, cbrtl_inf_pos); + ATF_TP_ADD_TC(tp, cbrtl_zero_neg); + ATF_TP_ADD_TC(tp, cbrtl_zero_pos); + + return atf_no_error(); +} diff --git a/lib/libm/t_ceil.c b/lib/libm/t_ceil.c new file mode 100644 index 000000000000..b57f30ebf8b2 --- /dev/null +++ b/lib/libm/t_ceil.c @@ -0,0 +1,931 @@ +/* $NetBSD: t_ceil.c,v 1.10 2014/03/03 10:39:08 martin Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__RCSID("$NetBSD: t_ceil.c,v 1.10 2014/03/03 10:39:08 martin Exp $"); + +#include <atf-c.h> +#include <math.h> +#include <limits.h> +#include <stdio.h> + +#ifdef __vax__ +#define SMALL_NUM 1.0e-38 +#else +#define SMALL_NUM 1.0e-40 +#endif + +/* + * ceil(3) + */ +ATF_TC(ceil_basic); +ATF_TC_HEAD(ceil_basic, tc) +{ + atf_tc_set_md_var(tc, "descr", "A basic test of ceil(3)"); +} + +ATF_TC_BODY(ceil_basic, tc) +{ + const double x = 0.999999999999999; + const double y = 0.000000000000001; + + ATF_CHECK(fabs(ceil(x) - 1) < SMALL_NUM); + ATF_CHECK(fabs(ceil(y) - 1) < SMALL_NUM); +} + +ATF_TC(ceil_nan); +ATF_TC_HEAD(ceil_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ceil(NaN) == NaN"); +} + +ATF_TC_BODY(ceil_nan, tc) +{ + const double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(ceil(x)) != 0); +} + +ATF_TC(ceil_inf_neg); +ATF_TC_HEAD(ceil_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ceil(-Inf) == -Inf"); +} + +ATF_TC_BODY(ceil_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + double y = ceil(x); + + if (isinf(y) == 0 || signbit(y) == 0) + atf_tc_fail_nonfatal("ceil(-Inf) != -Inf"); +} + +ATF_TC(ceil_inf_pos); +ATF_TC_HEAD(ceil_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ceil(+Inf) == +Inf"); +} + +ATF_TC_BODY(ceil_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + double y = ceil(x); + + if (isinf(y) == 0 || signbit(y) != 0) + atf_tc_fail_nonfatal("ceil(+Inf) != +Inf"); +} + +ATF_TC(ceil_zero_neg); +ATF_TC_HEAD(ceil_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ceil(-0.0) == -0.0"); +} + +ATF_TC_BODY(ceil_zero_neg, tc) +{ + const double x = -0.0L; + double y = ceil(x); + + if (fabs(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("ceil(-0.0) != -0.0"); +} + +ATF_TC(ceil_zero_pos); +ATF_TC_HEAD(ceil_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ceil(+0.0) == +0.0"); +} + +ATF_TC_BODY(ceil_zero_pos, tc) +{ + const double x = 0.0L; + double y = ceil(x); + + if (fabs(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("ceil(+0.0) != +0.0"); +} + +/* + * ceilf(3) + */ +ATF_TC(ceilf_basic); +ATF_TC_HEAD(ceilf_basic, tc) +{ + atf_tc_set_md_var(tc, "descr", "A basic test of ceilf(3)"); +} + +ATF_TC_BODY(ceilf_basic, tc) +{ + const float x = 0.9999999; + const float y = 0.0000001; + + ATF_CHECK(fabsf(ceilf(x) - 1) < SMALL_NUM); + ATF_CHECK(fabsf(ceilf(y) - 1) < SMALL_NUM); +} + +ATF_TC(ceilf_nan); +ATF_TC_HEAD(ceilf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ceilf(NaN) == NaN"); +} + +ATF_TC_BODY(ceilf_nan, tc) +{ + const float x = 0.0L / 0.0L; + + ATF_CHECK(isnan(ceilf(x)) != 0); +} + +ATF_TC(ceilf_inf_neg); +ATF_TC_HEAD(ceilf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ceilf(-Inf) == -Inf"); +} + +ATF_TC_BODY(ceilf_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + float y = ceilf(x); + + if (isinf(y) == 0 || signbit(y) == 0) + atf_tc_fail_nonfatal("ceilf(-Inf) != -Inf"); +} + +ATF_TC(ceilf_inf_pos); +ATF_TC_HEAD(ceilf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ceilf(+Inf) == +Inf"); +} + +ATF_TC_BODY(ceilf_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + float y = ceilf(x); + + if (isinf(y) == 0 || signbit(y) != 0) + atf_tc_fail_nonfatal("ceilf(+Inf) != +Inf"); +} + +ATF_TC(ceilf_zero_neg); +ATF_TC_HEAD(ceilf_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ceilf(-0.0) == -0.0"); +} + +ATF_TC_BODY(ceilf_zero_neg, tc) +{ + const float x = -0.0L; + float y = ceilf(x); + + if (fabsf(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("ceilf(-0.0) != -0.0"); +} + +ATF_TC(ceilf_zero_pos); +ATF_TC_HEAD(ceilf_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ceilf(+0.0) == +0.0"); +} + +ATF_TC_BODY(ceilf_zero_pos, tc) +{ + const float x = 0.0L; + float y = ceilf(x); + + if (fabsf(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("ceilf(+0.0) != +0.0"); +} + +/* + * ceill(3) + */ +ATF_TC(ceill_basic); +ATF_TC_HEAD(ceill_basic, tc) +{ + atf_tc_set_md_var(tc, "descr", "A basic test of ceill(3)"); +} + +ATF_TC_BODY(ceill_basic, tc) +{ + const long double x = 0.9999999; + const long double y = 0.0000001; + + ATF_CHECK(fabsl(ceill(x) - 1) < SMALL_NUM); + ATF_CHECK(fabsl(ceill(y) - 1) < SMALL_NUM); +} + +ATF_TC(ceill_nan); +ATF_TC_HEAD(ceill_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ceill(NaN) == NaN"); +} + +ATF_TC_BODY(ceill_nan, tc) +{ + const long double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(ceill(x)) != 0); +} + +ATF_TC(ceill_inf_neg); +ATF_TC_HEAD(ceill_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ceill(-Inf) == -Inf"); +} + +ATF_TC_BODY(ceill_inf_neg, tc) +{ + const long double x = -1.0L / 0.0L; + long double y = ceill(x); + + if (isinf(y) == 0 || signbit(y) == 0) + atf_tc_fail_nonfatal("ceill(-Inf) != -Inf"); +} + +ATF_TC(ceill_inf_pos); +ATF_TC_HEAD(ceill_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ceill(+Inf) == +Inf"); +} + +ATF_TC_BODY(ceill_inf_pos, tc) +{ + const long double x = 1.0L / 0.0L; + long double y = ceill(x); + + if (isinf(y) == 0 || signbit(y) != 0) + atf_tc_fail_nonfatal("ceill(+Inf) != +Inf"); +} + +ATF_TC(ceill_zero_neg); +ATF_TC_HEAD(ceill_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ceill(-0.0) == -0.0"); +} + +ATF_TC_BODY(ceill_zero_neg, tc) +{ + const long double x = -0.0L; + long double y = ceill(x); + + if (fabsl(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("ceill(-0.0) != -0.0"); +} + +ATF_TC(ceill_zero_pos); +ATF_TC_HEAD(ceill_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ceill(+0.0) == +0.0"); +} + +ATF_TC_BODY(ceill_zero_pos, tc) +{ + const long double x = 0.0L; + long double y = ceill(x); + + if (fabsl(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("ceill(+0.0) != +0.0"); +} + +/* + * floor(3) + */ +ATF_TC(floor_basic); +ATF_TC_HEAD(floor_basic, tc) +{ + atf_tc_set_md_var(tc, "descr", "A basic test of floor(3)"); +} + +ATF_TC_BODY(floor_basic, tc) +{ + const double x = 0.999999999999999; + const double y = 0.000000000000001; + + ATF_CHECK(floor(x) < SMALL_NUM); + ATF_CHECK(floor(y) < SMALL_NUM); +} + +ATF_TC(floor_nan); +ATF_TC_HEAD(floor_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test floor(NaN) == NaN"); +} + +ATF_TC_BODY(floor_nan, tc) +{ + const double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(floor(x)) != 0); +} + +ATF_TC(floor_inf_neg); +ATF_TC_HEAD(floor_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test floor(-Inf) == -Inf"); +} + +ATF_TC_BODY(floor_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + double y = floor(x); + + if (isinf(y) == 0 || signbit(y) == 0) + atf_tc_fail_nonfatal("floor(-Inf) != -Inf"); +} + +ATF_TC(floor_inf_pos); +ATF_TC_HEAD(floor_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test floor(+Inf) == +Inf"); +} + +ATF_TC_BODY(floor_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + double y = floor(x); + + if (isinf(y) == 0 || signbit(y) != 0) + atf_tc_fail_nonfatal("floor(+Inf) != +Inf"); +} + +ATF_TC(floor_zero_neg); +ATF_TC_HEAD(floor_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test floor(-0.0) == -0.0"); +} + +ATF_TC_BODY(floor_zero_neg, tc) +{ + const double x = -0.0L; + double y = floor(x); + + if (fabs(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("floor(-0.0) != -0.0"); +} + +ATF_TC(floor_zero_pos); +ATF_TC_HEAD(floor_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test floor(+0.0) == +0.0"); +} + +ATF_TC_BODY(floor_zero_pos, tc) +{ + const double x = 0.0L; + double y = floor(x); + + if (fabs(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("floor(+0.0) != +0.0"); +} + +/* + * floorf(3) + */ +ATF_TC(floorf_basic); +ATF_TC_HEAD(floorf_basic, tc) +{ + atf_tc_set_md_var(tc, "descr", "A basic test of floorf(3)"); +} + +ATF_TC_BODY(floorf_basic, tc) +{ + const float x = 0.9999999; + const float y = 0.0000001; + + ATF_CHECK(floorf(x) < SMALL_NUM); + ATF_CHECK(floorf(y) < SMALL_NUM); +} + +ATF_TC(floorf_nan); +ATF_TC_HEAD(floorf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test floorf(NaN) == NaN"); +} + +ATF_TC_BODY(floorf_nan, tc) +{ + const float x = 0.0L / 0.0L; + + ATF_CHECK(isnan(floorf(x)) != 0); +} + +ATF_TC(floorf_inf_neg); +ATF_TC_HEAD(floorf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test floorf(-Inf) == -Inf"); +} + +ATF_TC_BODY(floorf_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + float y = floorf(x); + + if (isinf(y) == 0 || signbit(y) == 0) + atf_tc_fail_nonfatal("floorf(-Inf) != -Inf"); +} + +ATF_TC(floorf_inf_pos); +ATF_TC_HEAD(floorf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test floorf(+Inf) == +Inf"); +} + +ATF_TC_BODY(floorf_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + float y = floorf(x); + + if (isinf(y) == 0 || signbit(y) != 0) + atf_tc_fail_nonfatal("floorf(+Inf) != +Inf"); +} + +ATF_TC(floorf_zero_neg); +ATF_TC_HEAD(floorf_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test floorf(-0.0) == -0.0"); +} + +ATF_TC_BODY(floorf_zero_neg, tc) +{ + const float x = -0.0L; + float y = floorf(x); + + if (fabsf(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("floorf(-0.0) != -0.0"); +} + +ATF_TC(floorf_zero_pos); +ATF_TC_HEAD(floorf_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test floorf(+0.0) == +0.0"); +} + +ATF_TC_BODY(floorf_zero_pos, tc) +{ + const float x = 0.0L; + float y = floorf(x); + + if (fabsf(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("floorf(+0.0) != +0.0"); +} + +/* + * floorl(3) + */ +ATF_TC(floorl_basic); +ATF_TC_HEAD(floorl_basic, tc) +{ + atf_tc_set_md_var(tc, "descr", "A basic test of floorl(3)"); +} + +ATF_TC_BODY(floorl_basic, tc) +{ + const long double x = 0.9999999; + const long double y = 0.0000001; + + ATF_CHECK(floorl(x) < SMALL_NUM); + ATF_CHECK(floorl(y) < SMALL_NUM); +} + +ATF_TC(floorl_nan); +ATF_TC_HEAD(floorl_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test floorl(NaN) == NaN"); +} + +ATF_TC_BODY(floorl_nan, tc) +{ + const long double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(floorl(x)) != 0); +} + +ATF_TC(floorl_inf_neg); +ATF_TC_HEAD(floorl_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test floorl(-Inf) == -Inf"); +} + +ATF_TC_BODY(floorl_inf_neg, tc) +{ + const long double x = -1.0L / 0.0L; + long double y = floorl(x); + + if (isinf(y) == 0 || signbit(y) == 0) + atf_tc_fail_nonfatal("floorl(-Inf) != -Inf"); +} + +ATF_TC(floorl_inf_pos); +ATF_TC_HEAD(floorl_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test floorl(+Inf) == +Inf"); +} + +ATF_TC_BODY(floorl_inf_pos, tc) +{ + const long double x = 1.0L / 0.0L; + long double y = floorl(x); + + if (isinf(y) == 0 || signbit(y) != 0) + atf_tc_fail_nonfatal("floorl(+Inf) != +Inf"); +} + +ATF_TC(floorl_zero_neg); +ATF_TC_HEAD(floorl_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test floorl(-0.0) == -0.0"); +} + +ATF_TC_BODY(floorl_zero_neg, tc) +{ + const long double x = -0.0L; + long double y = floorl(x); + + if (fabsl(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("floorl(-0.0) != -0.0"); +} + +ATF_TC(floorl_zero_pos); +ATF_TC_HEAD(floorl_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test floorl(+0.0) == +0.0"); +} + +ATF_TC_BODY(floorl_zero_pos, tc) +{ + const long double x = 0.0L; + long double y = floorl(x); + + if (fabsl(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("floorl(+0.0) != +0.0"); +} + +/* + * trunc(3) + */ +ATF_TC(trunc_basic); +ATF_TC_HEAD(trunc_basic, tc) +{ + atf_tc_set_md_var(tc, "descr", "A basic test of trunc(3)"); +} + +ATF_TC_BODY(trunc_basic, tc) +{ + const double x = 0.999999999999999; + const double y = 0.000000000000001; + + ATF_CHECK(trunc(x) < SMALL_NUM); + ATF_CHECK(trunc(y) < SMALL_NUM); +} + +ATF_TC(trunc_nan); +ATF_TC_HEAD(trunc_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test trunc(NaN) == NaN"); +} + +ATF_TC_BODY(trunc_nan, tc) +{ + const double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(trunc(x)) != 0); +} + +ATF_TC(trunc_inf_neg); +ATF_TC_HEAD(trunc_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test trunc(-Inf) == -Inf"); +} + +ATF_TC_BODY(trunc_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + double y = trunc(x); + + if (isinf(y) == 0 || signbit(y) == 0) + atf_tc_fail_nonfatal("trunc(-Inf) != -Inf"); +} + +ATF_TC(trunc_inf_pos); +ATF_TC_HEAD(trunc_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test trunc(+Inf) == +Inf"); +} + +ATF_TC_BODY(trunc_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + double y = trunc(x); + + if (isinf(y) == 0 || signbit(y) != 0) + atf_tc_fail_nonfatal("trunc(+Inf) != +Inf"); +} + +ATF_TC(trunc_zero_neg); +ATF_TC_HEAD(trunc_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test trunc(-0.0) == -0.0"); +} + +ATF_TC_BODY(trunc_zero_neg, tc) +{ + const double x = -0.0L; + double y = trunc(x); + + if (fabs(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("trunc(-0.0) != -0.0"); +} + +ATF_TC(trunc_zero_pos); +ATF_TC_HEAD(trunc_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test trunc(+0.0) == +0.0"); +} + +ATF_TC_BODY(trunc_zero_pos, tc) +{ + const double x = 0.0L; + double y = trunc(x); + + if (fabs(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("trunc(+0.0) != +0.0"); +} + +/* + * truncf(3) + */ +ATF_TC(truncf_basic); +ATF_TC_HEAD(truncf_basic, tc) +{ + atf_tc_set_md_var(tc, "descr", "A basic test of truncf(3)"); +} + +ATF_TC_BODY(truncf_basic, tc) +{ + const float x = 0.9999999; + const float y = 0.0000001; + + ATF_CHECK(truncf(x) < SMALL_NUM); + ATF_CHECK(truncf(y) < SMALL_NUM); +} + +ATF_TC(truncf_nan); +ATF_TC_HEAD(truncf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test truncf(NaN) == NaN"); +} + +ATF_TC_BODY(truncf_nan, tc) +{ + const float x = 0.0L / 0.0L; + + ATF_CHECK(isnan(truncf(x)) != 0); +} + +ATF_TC(truncf_inf_neg); +ATF_TC_HEAD(truncf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test truncf(-Inf) == -Inf"); +} + +ATF_TC_BODY(truncf_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + float y = truncf(x); + + if (isinf(y) == 0 || signbit(y) == 0) + atf_tc_fail_nonfatal("truncf(-Inf) != -Inf"); +} + +ATF_TC(truncf_inf_pos); +ATF_TC_HEAD(truncf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test truncf(+Inf) == +Inf"); +} + +ATF_TC_BODY(truncf_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + float y = truncf(x); + + if (isinf(y) == 0 || signbit(y) != 0) + atf_tc_fail_nonfatal("truncf(+Inf) != +Inf"); +} + +ATF_TC(truncf_zero_neg); +ATF_TC_HEAD(truncf_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test truncf(-0.0) == -0.0"); +} + +ATF_TC_BODY(truncf_zero_neg, tc) +{ + const float x = -0.0L; + float y = truncf(x); + + if (fabsf(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("truncf(-0.0) != -0.0"); +} + +ATF_TC(truncf_zero_pos); +ATF_TC_HEAD(truncf_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test truncf(+0.0) == +0.0"); +} + +ATF_TC_BODY(truncf_zero_pos, tc) +{ + const float x = 0.0L; + float y = truncf(x); + + if (fabsf(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("truncf(+0.0) != +0.0"); +} + +/* + * truncl(3) + */ +ATF_TC(truncl_basic); +ATF_TC_HEAD(truncl_basic, tc) +{ + atf_tc_set_md_var(tc, "descr", "A basic test of truncl(3)"); +} + +ATF_TC_BODY(truncl_basic, tc) +{ + const long double x = 0.9999999; + const long double y = 0.0000001; + + ATF_CHECK(truncl(x) < SMALL_NUM); + ATF_CHECK(truncl(y) < SMALL_NUM); +} + +ATF_TC(truncl_nan); +ATF_TC_HEAD(truncl_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test truncl(NaN) == NaN"); +} + +ATF_TC_BODY(truncl_nan, tc) +{ + const long double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(truncl(x)) != 0); +} + +ATF_TC(truncl_inf_neg); +ATF_TC_HEAD(truncl_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test truncl(-Inf) == -Inf"); +} + +ATF_TC_BODY(truncl_inf_neg, tc) +{ + const long double x = -1.0L / 0.0L; + long double y = truncl(x); + + if (isinf(y) == 0 || signbit(y) == 0) + atf_tc_fail_nonfatal("truncl(-Inf) != -Inf"); +} + +ATF_TC(truncl_inf_pos); +ATF_TC_HEAD(truncl_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test truncl(+Inf) == +Inf"); +} + +ATF_TC_BODY(truncl_inf_pos, tc) +{ + const long double x = 1.0L / 0.0L; + long double y = truncl(x); + + if (isinf(y) == 0 || signbit(y) != 0) + atf_tc_fail_nonfatal("truncl(+Inf) != +Inf"); +} + +ATF_TC(truncl_zero_neg); +ATF_TC_HEAD(truncl_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test truncl(-0.0) == -0.0"); +} + +ATF_TC_BODY(truncl_zero_neg, tc) +{ + const long double x = -0.0L; + long double y = truncl(x); + + if (fabsl(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("truncl(-0.0) != -0.0"); +} + +ATF_TC(truncl_zero_pos); +ATF_TC_HEAD(truncl_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test truncl(+0.0) == +0.0"); +} + +ATF_TC_BODY(truncl_zero_pos, tc) +{ + const long double x = 0.0L; + long double y = truncl(x); + + if (fabsl(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("truncl(+0.0) != +0.0"); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, ceil_basic); + ATF_TP_ADD_TC(tp, ceil_nan); + ATF_TP_ADD_TC(tp, ceil_inf_neg); + ATF_TP_ADD_TC(tp, ceil_inf_pos); + ATF_TP_ADD_TC(tp, ceil_zero_neg); + ATF_TP_ADD_TC(tp, ceil_zero_pos); + + ATF_TP_ADD_TC(tp, ceilf_basic); + ATF_TP_ADD_TC(tp, ceilf_nan); + ATF_TP_ADD_TC(tp, ceilf_inf_neg); + ATF_TP_ADD_TC(tp, ceilf_inf_pos); + ATF_TP_ADD_TC(tp, ceilf_zero_neg); + ATF_TP_ADD_TC(tp, ceilf_zero_pos); + + ATF_TP_ADD_TC(tp, ceill_basic); + ATF_TP_ADD_TC(tp, ceill_nan); + ATF_TP_ADD_TC(tp, ceill_inf_neg); + ATF_TP_ADD_TC(tp, ceill_inf_pos); + ATF_TP_ADD_TC(tp, ceill_zero_neg); + ATF_TP_ADD_TC(tp, ceill_zero_pos); + + ATF_TP_ADD_TC(tp, floor_basic); + ATF_TP_ADD_TC(tp, floor_nan); + ATF_TP_ADD_TC(tp, floor_inf_neg); + ATF_TP_ADD_TC(tp, floor_inf_pos); + ATF_TP_ADD_TC(tp, floor_zero_neg); + ATF_TP_ADD_TC(tp, floor_zero_pos); + + ATF_TP_ADD_TC(tp, floorf_basic); + ATF_TP_ADD_TC(tp, floorf_nan); + ATF_TP_ADD_TC(tp, floorf_inf_neg); + ATF_TP_ADD_TC(tp, floorf_inf_pos); + ATF_TP_ADD_TC(tp, floorf_zero_neg); + ATF_TP_ADD_TC(tp, floorf_zero_pos); + + ATF_TP_ADD_TC(tp, floorl_basic); + ATF_TP_ADD_TC(tp, floorl_nan); + ATF_TP_ADD_TC(tp, floorl_inf_neg); + ATF_TP_ADD_TC(tp, floorl_inf_pos); + ATF_TP_ADD_TC(tp, floorl_zero_neg); + ATF_TP_ADD_TC(tp, floorl_zero_pos); + + ATF_TP_ADD_TC(tp, trunc_basic); + ATF_TP_ADD_TC(tp, trunc_nan); + ATF_TP_ADD_TC(tp, trunc_inf_neg); + ATF_TP_ADD_TC(tp, trunc_inf_pos); + ATF_TP_ADD_TC(tp, trunc_zero_neg); + ATF_TP_ADD_TC(tp, trunc_zero_pos); + + ATF_TP_ADD_TC(tp, truncf_basic); + ATF_TP_ADD_TC(tp, truncf_nan); + ATF_TP_ADD_TC(tp, truncf_inf_neg); + ATF_TP_ADD_TC(tp, truncf_inf_pos); + ATF_TP_ADD_TC(tp, truncf_zero_neg); + ATF_TP_ADD_TC(tp, truncf_zero_pos); + + ATF_TP_ADD_TC(tp, truncl_basic); + ATF_TP_ADD_TC(tp, truncl_nan); + ATF_TP_ADD_TC(tp, truncl_inf_neg); + ATF_TP_ADD_TC(tp, truncl_inf_pos); + ATF_TP_ADD_TC(tp, truncl_zero_neg); + ATF_TP_ADD_TC(tp, truncl_zero_pos); + + return atf_no_error(); +} diff --git a/lib/libm/t_cos.c b/lib/libm/t_cos.c new file mode 100644 index 000000000000..d99d60810eeb --- /dev/null +++ b/lib/libm/t_cos.c @@ -0,0 +1,263 @@ +/* $NetBSD: t_cos.c,v 1.4 2014/03/03 10:39:08 martin Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <atf-c.h> +#include <math.h> + +static const struct { + int angle; + double x; + double y; +} angles[] = { + { -180, -3.141592653589793, -1.0000000000000000 }, + { -135, -2.356194490192345, -0.7071067811865476 }, + { -90, -1.570796326794897, 0.0000000000000000 }, + { -45, -0.785398163397448, 0.7071067811865476 }, + { 0, 0.000000000000000, 1.0000000000000000 }, + { 30, 0.523598775598299, 0.8660254037844386 }, + { 45, 0.785398163397448, 0.7071067811865476 }, + { 60, 1.047197551196598, 0.5000000000000000 }, + { 90, 1.570796326794897, 0.0000000000000000 }, + { 120, 2.094395102393195, -0.5000000000000000 }, + { 135, 2.356194490192345, -0.7071067811865476 }, + { 150, 2.617993877991494, -0.8660254037844386 }, + { 180, 3.141592653589793, -1.0000000000000000 }, + { 270, 4.712388980384690, 0.0000000000000000 }, + { 360, 6.283185307179586, 1.0000000000000000 } +}; + +/* + * cos(3) + */ +ATF_TC(cos_angles); +ATF_TC_HEAD(cos_angles, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test some selected angles"); +} + +ATF_TC_BODY(cos_angles, tc) +{ + const double eps = 1.0e-15; + size_t i; + + for (i = 0; i < __arraycount(angles); i++) { + + if (fabs(cos(angles[i].x) - angles[i].y) > eps) + atf_tc_fail_nonfatal("cos(%d deg) != %0.01f", + angles[i].angle, angles[i].y); + } +} + +ATF_TC(cos_nan); +ATF_TC_HEAD(cos_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cos(NaN) == NaN"); +} + +ATF_TC_BODY(cos_nan, tc) +{ + const double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(cos(x)) != 0); +} + +ATF_TC(cos_inf_neg); +ATF_TC_HEAD(cos_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cos(-Inf) == NaN"); +} + +ATF_TC_BODY(cos_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + + ATF_CHECK(isnan(cos(x)) != 0); +} + +ATF_TC(cos_inf_pos); +ATF_TC_HEAD(cos_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cos(+Inf) == NaN"); +} + +ATF_TC_BODY(cos_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + + ATF_CHECK(isnan(cos(x)) != 0); +} + + +ATF_TC(cos_zero_neg); +ATF_TC_HEAD(cos_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cos(-0.0) == 1.0"); +} + +ATF_TC_BODY(cos_zero_neg, tc) +{ + const double x = -0.0L; + + ATF_CHECK(cos(x) == 1.0); +} + +ATF_TC(cos_zero_pos); +ATF_TC_HEAD(cos_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cos(+0.0) == 1.0"); +} + +ATF_TC_BODY(cos_zero_pos, tc) +{ + const double x = 0.0L; + + ATF_CHECK(cos(x) == 1.0); +} + +/* + * cosf(3) + */ +ATF_TC(cosf_angles); +ATF_TC_HEAD(cosf_angles, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test some selected angles"); +} + +ATF_TC_BODY(cosf_angles, tc) +{ + const float eps = 1.0e-7; + float x, y; + size_t i; + + for (i = 0; i < __arraycount(angles); i++) { + + x = angles[i].x; + y = angles[i].y; + + if (fabsf(cosf(x) - y) > eps) + atf_tc_fail_nonfatal("cosf(%d deg) != %0.01f", + angles[i].angle, angles[i].y); + } +} + +ATF_TC(cosf_nan); +ATF_TC_HEAD(cosf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cosf(NaN) == NaN"); +} + +ATF_TC_BODY(cosf_nan, tc) +{ + const float x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(cosf(x)) != 0); +} + +ATF_TC(cosf_inf_neg); +ATF_TC_HEAD(cosf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cosf(-Inf) == NaN"); +} + +ATF_TC_BODY(cosf_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + + if (isnan(cosf(x)) == 0) { + atf_tc_expect_fail("PR lib/45362"); + atf_tc_fail("cosf(-Inf) != NaN"); + } +} + +ATF_TC(cosf_inf_pos); +ATF_TC_HEAD(cosf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cosf(+Inf) == NaN"); +} + +ATF_TC_BODY(cosf_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + + if (isnan(cosf(x)) == 0) { + atf_tc_expect_fail("PR lib/45362"); + atf_tc_fail("cosf(+Inf) != NaN"); + } +} + + +ATF_TC(cosf_zero_neg); +ATF_TC_HEAD(cosf_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cosf(-0.0) == 1.0"); +} + +ATF_TC_BODY(cosf_zero_neg, tc) +{ + const float x = -0.0L; + + ATF_CHECK(cosf(x) == 1.0); +} + +ATF_TC(cosf_zero_pos); +ATF_TC_HEAD(cosf_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cosf(+0.0) == 1.0"); +} + +ATF_TC_BODY(cosf_zero_pos, tc) +{ + const float x = 0.0L; + + ATF_CHECK(cosf(x) == 1.0); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, cos_angles); + ATF_TP_ADD_TC(tp, cos_nan); + ATF_TP_ADD_TC(tp, cos_inf_neg); + ATF_TP_ADD_TC(tp, cos_inf_pos); + ATF_TP_ADD_TC(tp, cos_zero_neg); + ATF_TP_ADD_TC(tp, cos_zero_pos); + + ATF_TP_ADD_TC(tp, cosf_angles); + ATF_TP_ADD_TC(tp, cosf_nan); + ATF_TP_ADD_TC(tp, cosf_inf_neg); + ATF_TP_ADD_TC(tp, cosf_inf_pos); + ATF_TP_ADD_TC(tp, cosf_zero_neg); + ATF_TP_ADD_TC(tp, cosf_zero_pos); + + return atf_no_error(); +} diff --git a/lib/libm/t_cosh.c b/lib/libm/t_cosh.c new file mode 100644 index 000000000000..3f998de761bb --- /dev/null +++ b/lib/libm/t_cosh.c @@ -0,0 +1,270 @@ +/* $NetBSD: t_cosh.c,v 1.6 2014/03/03 10:39:08 martin Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__RCSID("$NetBSD: t_cosh.c,v 1.6 2014/03/03 10:39:08 martin Exp $"); + +#include <atf-c.h> +#include <math.h> +#include <stdio.h> + +static const struct { + double x; + double y; + double e; +} values[] = { + { -10, 11013.23292010332, 1e4, }, + { -2, 3.762195691083631, 1, }, + { -1, 1.543080634815244, 1, }, + { -0.05, 1.001250260438369, 1, }, + { -0.001, 1.000000500000042, 1, }, + { 0, 1, 1, }, + { 0.001, 1.000000500000042, 1, }, + { 0.05, 1.001250260438369, 1, }, + { 1, 1.543080634815244, 1, }, + { 2, 3.762195691083631, 1, }, + { 10, 11013.23292010332, 1e4, }, +}; + +/* + * cosh(3) + */ +ATF_TC(cosh_inrange); +ATF_TC_HEAD(cosh_inrange, tc) +{ + atf_tc_set_md_var(tc, "descr", "cosh(x) for some values"); +} + +ATF_TC_BODY(cosh_inrange, tc) +{ + double eps; + double x; + double y; + size_t i; + + for (i = 0; i < __arraycount(values); i++) { + x = values[i].x; + y = values[i].y; + eps = 1e-15 * values[i].e; + + if (fabs(cosh(x) - y) > eps) + atf_tc_fail_nonfatal("cosh(%g) != %g\n", x, y); + } +} + +ATF_TC(cosh_nan); +ATF_TC_HEAD(cosh_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cosh(NaN) == NaN"); +} + +ATF_TC_BODY(cosh_nan, tc) +{ + const double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(cosh(x)) != 0); +} + +ATF_TC(cosh_inf_neg); +ATF_TC_HEAD(cosh_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cosh(-Inf) == +Inf"); +} + +ATF_TC_BODY(cosh_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + double y = cosh(x); + + ATF_CHECK(isinf(y) != 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TC(cosh_inf_pos); +ATF_TC_HEAD(cosh_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cosh(+Inf) == +Inf"); +} + +ATF_TC_BODY(cosh_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + double y = cosh(x); + + ATF_CHECK(isinf(y) != 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TC(cosh_zero_neg); +ATF_TC_HEAD(cosh_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cosh(-0.0) == 1.0"); +} + +ATF_TC_BODY(cosh_zero_neg, tc) +{ + const double x = -0.0L; + + if (cosh(x) != 1.0) + atf_tc_fail_nonfatal("cosh(-0.0) != 1.0"); +} + +ATF_TC(cosh_zero_pos); +ATF_TC_HEAD(cosh_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test cosh(+0.0) == 1.0"); +} + +ATF_TC_BODY(cosh_zero_pos, tc) +{ + const double x = 0.0L; + + if (cosh(x) != 1.0) + atf_tc_fail_nonfatal("cosh(+0.0) != 1.0"); +} + +/* + * coshf(3) + */ +ATF_TC(coshf_inrange); +ATF_TC_HEAD(coshf_inrange, tc) +{ + atf_tc_set_md_var(tc, "descr", "coshf(x) for some values"); +} + +ATF_TC_BODY(coshf_inrange, tc) +{ + float eps; + float x; + float y; + size_t i; + + for (i = 0; i < __arraycount(values); i++) { + x = values[i].x; + y = values[i].y; + eps = 1e-6 * values[i].e; + + if (fabsf(coshf(x) - y) > eps) + atf_tc_fail_nonfatal("coshf(%g) != %g\n", x, y); + } +} + +ATF_TC(coshf_nan); +ATF_TC_HEAD(coshf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test coshf(NaN) == NaN"); +} + +ATF_TC_BODY(coshf_nan, tc) +{ + const float x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(coshf(x)) != 0); +} + +ATF_TC(coshf_inf_neg); +ATF_TC_HEAD(coshf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test coshf(-Inf) == +Inf"); +} + +ATF_TC_BODY(coshf_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + float y = coshf(x); + + ATF_CHECK(isinf(y) != 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TC(coshf_inf_pos); +ATF_TC_HEAD(coshf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test coshf(+Inf) == +Inf"); +} + +ATF_TC_BODY(coshf_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + float y = coshf(x); + + ATF_CHECK(isinf(y) != 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TC(coshf_zero_neg); +ATF_TC_HEAD(coshf_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test coshf(-0.0) == 1.0"); +} + +ATF_TC_BODY(coshf_zero_neg, tc) +{ + const float x = -0.0L; + + if (coshf(x) != 1.0) + atf_tc_fail_nonfatal("coshf(-0.0) != 1.0"); +} + +ATF_TC(coshf_zero_pos); +ATF_TC_HEAD(coshf_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test coshf(+0.0) == 1.0"); +} + +ATF_TC_BODY(coshf_zero_pos, tc) +{ + const float x = 0.0L; + + if (coshf(x) != 1.0) + atf_tc_fail_nonfatal("coshf(+0.0) != 1.0"); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, cosh_inrange); + ATF_TP_ADD_TC(tp, cosh_nan); + ATF_TP_ADD_TC(tp, cosh_inf_neg); + ATF_TP_ADD_TC(tp, cosh_inf_pos); + ATF_TP_ADD_TC(tp, cosh_zero_neg); + ATF_TP_ADD_TC(tp, cosh_zero_pos); + + ATF_TP_ADD_TC(tp, coshf_inrange); + ATF_TP_ADD_TC(tp, coshf_nan); + ATF_TP_ADD_TC(tp, coshf_inf_neg); + ATF_TP_ADD_TC(tp, coshf_inf_pos); + ATF_TP_ADD_TC(tp, coshf_zero_neg); + ATF_TP_ADD_TC(tp, coshf_zero_pos); + + return atf_no_error(); +} diff --git a/lib/libm/t_erf.c b/lib/libm/t_erf.c new file mode 100644 index 000000000000..25bbae7834a8 --- /dev/null +++ b/lib/libm/t_erf.c @@ -0,0 +1,299 @@ +/* $NetBSD: t_erf.c,v 1.2 2014/03/03 10:39:08 martin Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__RCSID("$NetBSD: t_erf.c,v 1.2 2014/03/03 10:39:08 martin Exp $"); + +#include <atf-c.h> +#include <math.h> + +/* + * erf(3) + */ +ATF_TC(erf_nan); +ATF_TC_HEAD(erf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test erf(NaN) == NaN"); +} + +ATF_TC_BODY(erf_nan, tc) +{ + const double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(erf(x)) != 0); +} + +ATF_TC(erf_inf_neg); +ATF_TC_HEAD(erf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test erf(-Inf) == -1.0"); +} + +ATF_TC_BODY(erf_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + + if (erf(x) != -1.0) + atf_tc_fail_nonfatal("erf(-Inf) != -1.0"); +} + +ATF_TC(erf_inf_pos); +ATF_TC_HEAD(erf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test erf(+Inf) == 1.0"); +} + +ATF_TC_BODY(erf_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + + if (erf(x) != 1.0) + atf_tc_fail_nonfatal("erf(+Inf) != 1.0"); +} + +ATF_TC(erf_zero_neg); +ATF_TC_HEAD(erf_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test erf(-0.0) == -0.0"); +} + +ATF_TC_BODY(erf_zero_neg, tc) +{ + const double x = -0.0L; + double y = erf(x); + + if (fabs(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("erf(-0.0) != -0.0"); +} + +ATF_TC(erf_zero_pos); +ATF_TC_HEAD(erf_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test erf(+0.0) == +0.0"); +} + +ATF_TC_BODY(erf_zero_pos, tc) +{ + const double x = 0.0L; + double y = erf(x); + + if (fabs(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("erf(+0.0) != +0.0"); +} + +/* + * erff(3) + */ +ATF_TC(erff_nan); +ATF_TC_HEAD(erff_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test erff(NaN) == NaN"); +} + +ATF_TC_BODY(erff_nan, tc) +{ + const float x = 0.0L / 0.0L; + + ATF_CHECK(isnan(erff(x)) != 0); +} + +ATF_TC(erff_inf_neg); +ATF_TC_HEAD(erff_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test erff(-Inf) == -1.0"); +} + +ATF_TC_BODY(erff_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + + if (erff(x) != -1.0) + atf_tc_fail_nonfatal("erff(-Inf) != -1.0"); +} + +ATF_TC(erff_inf_pos); +ATF_TC_HEAD(erff_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test erff(+Inf) == 1.0"); +} + +ATF_TC_BODY(erff_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + + if (erff(x) != 1.0) + atf_tc_fail_nonfatal("erff(+Inf) != 1.0"); +} + +ATF_TC(erff_zero_neg); +ATF_TC_HEAD(erff_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test erff(-0.0) == -0.0"); +} + +ATF_TC_BODY(erff_zero_neg, tc) +{ + const float x = -0.0L; + float y = erff(x); + + if (fabsf(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("erff(-0.0) != -0.0"); +} + +ATF_TC(erff_zero_pos); +ATF_TC_HEAD(erff_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test erff(+0.0) == +0.0"); +} + +ATF_TC_BODY(erff_zero_pos, tc) +{ + const float x = 0.0L; + float y = erff(x); + + if (fabsf(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("erff(+0.0) != +0.0"); +} + +/* + * erfc(3) + */ +ATF_TC(erfc_nan); +ATF_TC_HEAD(erfc_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test erfc(NaN) == NaN"); +} + +ATF_TC_BODY(erfc_nan, tc) +{ + const double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(erfc(x)) != 0); +} + +ATF_TC(erfc_inf_neg); +ATF_TC_HEAD(erfc_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test erfc(-Inf) == 2.0"); +} + +ATF_TC_BODY(erfc_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + + if (erfc(x) != 2.0) + atf_tc_fail_nonfatal("erfc(-Inf) != 2.0"); +} + +ATF_TC(erfc_inf_pos); +ATF_TC_HEAD(erfc_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test erfc(+Inf) == +0.0"); +} + +ATF_TC_BODY(erfc_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + double y = erfc(x); + + if (fabs(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("erfc(+Inf) != +0.0"); +} + +/* + * erfcf(3) + */ +ATF_TC(erfcf_nan); +ATF_TC_HEAD(erfcf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test erfcf(NaN) == NaN"); +} + +ATF_TC_BODY(erfcf_nan, tc) +{ + const float x = 0.0L / 0.0L; + + ATF_CHECK(isnan(erfcf(x)) != 0); +} + +ATF_TC(erfcf_inf_neg); +ATF_TC_HEAD(erfcf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test erfcf(-Inf) == 2.0"); +} + +ATF_TC_BODY(erfcf_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + + if (erfcf(x) != 2.0) + atf_tc_fail_nonfatal("erfcf(-Inf) != 2.0"); +} + +ATF_TC(erfcf_inf_pos); +ATF_TC_HEAD(erfcf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test erfcf(+Inf) == +0.0"); +} + +ATF_TC_BODY(erfcf_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + float y = erfcf(x); + + if (fabsf(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("erfcf(+Inf) != +0.0"); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, erf_nan); + ATF_TP_ADD_TC(tp, erf_inf_neg); + ATF_TP_ADD_TC(tp, erf_inf_pos); + ATF_TP_ADD_TC(tp, erf_zero_neg); + ATF_TP_ADD_TC(tp, erf_zero_pos); + + ATF_TP_ADD_TC(tp, erff_nan); + ATF_TP_ADD_TC(tp, erff_inf_neg); + ATF_TP_ADD_TC(tp, erff_inf_pos); + ATF_TP_ADD_TC(tp, erff_zero_neg); + ATF_TP_ADD_TC(tp, erff_zero_pos); + + ATF_TP_ADD_TC(tp, erfc_nan); + ATF_TP_ADD_TC(tp, erfc_inf_neg); + ATF_TP_ADD_TC(tp, erfc_inf_pos); + + ATF_TP_ADD_TC(tp, erfcf_nan); + ATF_TP_ADD_TC(tp, erfcf_inf_neg); + ATF_TP_ADD_TC(tp, erfcf_inf_pos); + + return atf_no_error(); +} diff --git a/lib/libm/t_exp.c b/lib/libm/t_exp.c new file mode 100644 index 000000000000..6d410972d77c --- /dev/null +++ b/lib/libm/t_exp.c @@ -0,0 +1,567 @@ +/* $NetBSD: t_exp.c,v 1.7 2014/03/17 11:08:11 martin Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <atf-c.h> +#include <math.h> +#include "t_libm.h" + +/* y = exp(x) */ +static const struct { + double x; + double y; + double e; +} exp_values[] = { + { -10, 0.4539992976248485e-4, 1e-4, }, + { -5, 0.6737946999085467e-2, 1e-2, }, + { -1, 0.3678794411714423, 1e-1, }, + { -0.1, 0.9048374180359595, 1e-1, }, + { 0, 1.0000000000000000, 1, }, + { 0.1, 1.1051709180756477, 1, }, + { 1, 2.7182818284590452, 1, }, + { 5, 148.41315910257660, 1e2, }, + { 10, 22026.465794806718, 1e4, }, +}; + +/* + * exp2/exp2f(3) + */ +ATF_LIBM_TEST(exp2_is_nan, "Test exp2(x) == NaN") +{ +#ifdef T_LIBM_NAN + T_LIBM_CHECK_NAN(0, exp2, T_LIBM_NAN); + T_LIBM_CHECK_NAN(0, exp2f, T_LIBM_NAN); +#else + atf_tc_skip("no NaN on this machine"); +#endif +} + +ATF_LIBM_TEST(exp2_is_plus_zero, "Test exp2(x) == +0.0") +{ +#ifdef T_LIBM_MINUS_INF + T_LIBM_CHECK_PLUS_ZERO(0, exp2, T_LIBM_MINUS_INF); + T_LIBM_CHECK_PLUS_ZERO(0, exp2f, T_LIBM_MINUS_INF); +#else + atf_tc_skip("no +/-Inf on this machine"); +#endif +} + +ATF_LIBM_TEST(exp2_powers, "Test exp2(x) is correct for some integer x") +{ + static const struct { + double x; + double d_y; + double f_y; + } v[] = { + { +0.0, 1.0, 1.0 }, + { -0.0, 1.0, 1.0 }, + { 1, 0x1p1, 0x1p1 }, + { 2, 0x1p2, 0x1p2 }, + { 100, 0x1p100, 0x1p100 }, + { 125, 0x1p125, 0x1p125 }, + { 126, 0x1p126, 0x1p126 }, +#if __DBL_MAX_EXP__ > 129 + { 127, 0x1p127, 0x1p127 }, +#endif +#ifdef T_LIBM_PLUS_INF + { 128, 0x1p128, T_LIBM_PLUS_INF }, + { 129, 0x1p129, T_LIBM_PLUS_INF }, + { 1000, 0x1p1000, T_LIBM_PLUS_INF }, + { 1020, 0x1p1020, T_LIBM_PLUS_INF }, + { 1023, 0x1p1023, T_LIBM_PLUS_INF }, + { 1024, T_LIBM_PLUS_INF, T_LIBM_PLUS_INF }, + { 1030, T_LIBM_PLUS_INF, T_LIBM_PLUS_INF }, + { 1050, T_LIBM_PLUS_INF, T_LIBM_PLUS_INF }, + { 2000, T_LIBM_PLUS_INF, T_LIBM_PLUS_INF }, + { 16383, T_LIBM_PLUS_INF, T_LIBM_PLUS_INF }, + { 16384, T_LIBM_PLUS_INF, T_LIBM_PLUS_INF }, + { 16385, T_LIBM_PLUS_INF, T_LIBM_PLUS_INF }, +#endif + { -1, 0x1p-1, 0x1p-1 }, + { -2, 0x1p-2, 0x1p-2 }, + { -100, 0x1p-100, 0x1p-100 }, + { -127, 0x1p-127, 0x1p-127 }, + { -128, 0x1p-128, 0x1p-128 }, +#if __LDBL_MIN_EXP__ < -129 + { -300, 0x1p-300, 0.0}, + { -400, 0x1p-400, 0.0}, + {-1000, 0x1p-1000, 0.0}, + {-1022, 0x1p-1022, 0.0}, + /* These should be denormal numbers */ + {-1023, 0x1p-1023, 0.0}, + {-1024, 0x1p-1024, 0.0}, + {-1040, 0x1p-1040, 0.0}, + {-1060, 0x1p-1060, 0.0}, + /* This is the smallest result gcc will allow */ + {-1074, 0x1p-1074, 0.0}, +#endif + {-1075, 0x0, 0.0}, + {-1080, 0x0, 0.0}, + {-2000, 0x0, 0.0}, + {-16382, 0x0, 0.0}, + {-16383, 0x0, 0.0}, + {-16384, 0x0, 0.0}, + }; + unsigned int i; + + for (i = 0; i < __arraycount(v); i++) { + T_LIBM_CHECK(i, exp2, v[i].x, v[i].d_y, 0.0); + T_LIBM_CHECK(i, exp2f, v[i].x, v[i].f_y, 0.0); + } +} + +ATF_LIBM_TEST(exp2_values, "Test exp2(x) is correct for some x") +{ + static const struct { + double x; + double y; + double d_eps; + double f_eps; + } v[] = { +#if __DBL_MAX_EXP__ > 128 + /* The largest double constant */ + { 0x1.fffffffffffffp9, 0x1.ffffffffffd3ap1023, + 0x1p969, 0.0 }, + /* The largest float constant */ + { 0x1.fffffep6, 0x1.ffff4ep+127, 6e30, 0.0 }, +#endif +#ifdef T_LIBM_PLUS_INF + { T_LIBM_PLUS_INF, T_LIBM_PLUS_INF, 0.0, 0.0 }, +#endif + + /* The few values from the old tests */ + /* Results from i386/amd64, d_eps needed on i386 */ + { 1.1, 0x1.125fbee250664p+1, 0x1p-52, 0x1.8p-22 }, + { 2.2, 0x1.2611186bae675p+2, 0x1p-51, 0x1.8p-21 }, + { 3.3, 0x1.3b2c47bff8328p+3, 0x1p-50, 0x1.8p-20 }, + { 4.4, 0x1.51cb453b9536ep+4, 0x1p-49, 0x1.8p-19 }, + { 5.5, 0x1.6a09e667f3bcdp+5, 0x1p-48, 0x1.8p-18 }, + { 6.6, 0x1.8406003b2ae5bp+6, 0x1p-47, 0x1.8p-17 }, + /* + * These two currently fail for 'float'. + * 8.8 is definitely out by more than it should be. + */ + { 7.7, 0x1.9fdf8bcce533ep+7, 0x1p-46, 0x1.8p-16 }, + { 8.8, 0x1.bdb8cdadbe124p+8, 0x1p-45, 0x1.8p-15 }, + }; + unsigned int i; + + for (i = 0; i < __arraycount(v); i++) { + T_LIBM_CHECK(i, exp2, v[i].x, v[i].y, v[i].d_eps); + if (i > 1) + T_LIBM_CHECK(i, exp2f, v[i].x, v[i].y, v[i].f_eps); + } +} + + +/* + * exp(3) + */ +ATF_TC(exp_nan); +ATF_TC_HEAD(exp_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test exp(NaN) == NaN"); +} + +ATF_TC_BODY(exp_nan, tc) +{ + const double x = 0.0L / 0.0L; + + if (isnan(exp(x)) == 0) + atf_tc_fail_nonfatal("exp(NaN) != NaN"); +} + +ATF_TC(exp_inf_neg); +ATF_TC_HEAD(exp_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test exp(-Inf) == +0.0"); +} + +ATF_TC_BODY(exp_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + double y = exp(x); + + if (fabs(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("exp(-Inf) != +0.0"); +} + +ATF_TC(exp_inf_pos); +ATF_TC_HEAD(exp_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test exp(+Inf) == +Inf"); +} + +ATF_TC_BODY(exp_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + double y = exp(x); + + if (isinf(y) == 0 || signbit(y) != 0) + atf_tc_fail_nonfatal("exp(+Inf) != +Inf"); +} + +ATF_TC(exp_product); +ATF_TC_HEAD(exp_product, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test some selected exp(x)"); +} + +ATF_TC_BODY(exp_product, tc) +{ + double eps; + double x; + double y; + size_t i; + + for (i = 0; i < __arraycount(exp_values); i++) { + x = exp_values[i].x; + y = exp_values[i].y; + eps = 1e-15 * exp_values[i].e; + + if (fabs(exp(x) - y) > eps) + atf_tc_fail_nonfatal("exp(%0.01f) != %18.18e", x, y); + } +} + +ATF_TC(exp_zero_neg); +ATF_TC_HEAD(exp_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test exp(-0.0) == 1.0"); +} + +ATF_TC_BODY(exp_zero_neg, tc) +{ + const double x = -0.0L; + + if (fabs(exp(x) - 1.0) > 0.0) + atf_tc_fail_nonfatal("exp(-0.0) != 1.0"); +} + +ATF_TC(exp_zero_pos); +ATF_TC_HEAD(exp_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test exp(+0.0) == 1.0"); +} + +ATF_TC_BODY(exp_zero_pos, tc) +{ + const double x = 0.0L; + + if (fabs(exp(x) - 1.0) > 0.0) + atf_tc_fail_nonfatal("exp(+0.0) != 1.0"); +} + +/* + * expf(3) + */ +ATF_TC(expf_nan); +ATF_TC_HEAD(expf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test expf(NaN) == NaN"); +} + +ATF_TC_BODY(expf_nan, tc) +{ + const float x = 0.0L / 0.0L; + + if (isnan(expf(x)) == 0) + atf_tc_fail_nonfatal("expf(NaN) != NaN"); +} + +ATF_TC(expf_inf_neg); +ATF_TC_HEAD(expf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test expf(-Inf) == +0.0"); +} + +ATF_TC_BODY(expf_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + float y = expf(x); + + if (fabsf(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("expf(-Inf) != +0.0"); +} + +ATF_TC(expf_inf_pos); +ATF_TC_HEAD(expf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test expf(+Inf) == +Inf"); +} + +ATF_TC_BODY(expf_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + float y = expf(x); + + if (isinf(y) == 0 || signbit(y) != 0) + atf_tc_fail_nonfatal("expf(+Inf) != +Inf"); +} + +ATF_TC(expf_product); +ATF_TC_HEAD(expf_product, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test some selected expf(x)"); +} + +ATF_TC_BODY(expf_product, tc) +{ + float eps; + float x; + float y; + size_t i; + + for (i = 0; i < __arraycount(exp_values); i++) { + x = exp_values[i].x; + y = exp_values[i].y; + eps = 1e-6 * exp_values[i].e; + + if (fabsf(expf(x) - y) > eps) + atf_tc_fail_nonfatal("expf(%0.01f) != %18.18e", x, y); + } +} + +ATF_TC(expf_zero_neg); +ATF_TC_HEAD(expf_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test expf(-0.0) == 1.0"); +} + +ATF_TC_BODY(expf_zero_neg, tc) +{ + const float x = -0.0L; + + if (fabsf(expf(x) - 1.0f) > 0.0) + atf_tc_fail_nonfatal("expf(-0.0) != 1.0"); +} + +ATF_TC(expf_zero_pos); +ATF_TC_HEAD(expf_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test expf(+0.0) == 1.0"); +} + +ATF_TC_BODY(expf_zero_pos, tc) +{ + const float x = 0.0L; + + if (fabsf(expf(x) - 1.0f) > 0.0) + atf_tc_fail_nonfatal("expf(+0.0) != 1.0"); +} + +/* + * expm1(3) + */ +ATF_TC(expm1_nan); +ATF_TC_HEAD(expm1_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test expm1(NaN) == NaN"); +} + +ATF_TC_BODY(expm1_nan, tc) +{ + const double x = 0.0L / 0.0L; + + if (isnan(expm1(x)) == 0) + atf_tc_fail_nonfatal("expm1(NaN) != NaN"); +} + +ATF_TC(expm1_inf_neg); +ATF_TC_HEAD(expm1_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test expm1(-Inf) == -1"); +} + +ATF_TC_BODY(expm1_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + + if (expm1(x) != -1.0) + atf_tc_fail_nonfatal("expm1(-Inf) != -1.0"); +} + +ATF_TC(expm1_inf_pos); +ATF_TC_HEAD(expm1_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test expm1(+Inf) == +Inf"); +} + +ATF_TC_BODY(expm1_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + double y = expm1(x); + + if (isinf(y) == 0 || signbit(y) != 0) + atf_tc_fail_nonfatal("expm1(+Inf) != +Inf"); +} + +ATF_TC(expm1_zero_neg); +ATF_TC_HEAD(expm1_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test expm1(-0.0) == -0.0"); +} + +ATF_TC_BODY(expm1_zero_neg, tc) +{ + const double x = -0.0L; + double y = expm1(x); + + if (fabs(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("expm1(-0.0) != -0.0"); +} + +ATF_TC(expm1_zero_pos); +ATF_TC_HEAD(expm1_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test expm1(+0.0) == 1.0"); +} + +ATF_TC_BODY(expm1_zero_pos, tc) +{ + const double x = 0.0L; + double y = expm1(x); + + if (fabs(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("expm1(+0.0) != +0.0"); +} + +/* + * expm1f(3) + */ +ATF_TC(expm1f_nan); +ATF_TC_HEAD(expm1f_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test expm1f(NaN) == NaN"); +} + +ATF_TC_BODY(expm1f_nan, tc) +{ + const float x = 0.0L / 0.0L; + + if (isnan(expm1f(x)) == 0) + atf_tc_fail_nonfatal("expm1f(NaN) != NaN"); +} + +ATF_TC(expm1f_inf_neg); +ATF_TC_HEAD(expm1f_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test expm1f(-Inf) == -1"); +} + +ATF_TC_BODY(expm1f_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + + if (expm1f(x) != -1.0) + atf_tc_fail_nonfatal("expm1f(-Inf) != -1.0"); +} + +ATF_TC(expm1f_inf_pos); +ATF_TC_HEAD(expm1f_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test expm1f(+Inf) == +Inf"); +} + +ATF_TC_BODY(expm1f_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + float y = expm1f(x); + + if (isinf(y) == 0 || signbit(y) != 0) + atf_tc_fail_nonfatal("expm1f(+Inf) != +Inf"); +} + +ATF_TC(expm1f_zero_neg); +ATF_TC_HEAD(expm1f_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test expm1f(-0.0) == -0.0"); +} + +ATF_TC_BODY(expm1f_zero_neg, tc) +{ + const float x = -0.0L; + float y = expm1f(x); + + if (fabsf(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("expm1f(-0.0) != -0.0"); +} + +ATF_TC(expm1f_zero_pos); +ATF_TC_HEAD(expm1f_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test expm1f(+0.0) == 1.0"); +} + +ATF_TC_BODY(expm1f_zero_pos, tc) +{ + const float x = 0.0L; + float y = expm1f(x); + + if (fabsf(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("expm1f(+0.0) != +0.0"); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, exp2_is_nan); + ATF_TP_ADD_TC(tp, exp2_is_plus_zero); + ATF_TP_ADD_TC(tp, exp2_values); + ATF_TP_ADD_TC(tp, exp2_powers); + + ATF_TP_ADD_TC(tp, exp_nan); + ATF_TP_ADD_TC(tp, exp_inf_neg); + ATF_TP_ADD_TC(tp, exp_inf_pos); + ATF_TP_ADD_TC(tp, exp_product); + ATF_TP_ADD_TC(tp, exp_zero_neg); + ATF_TP_ADD_TC(tp, exp_zero_pos); + + ATF_TP_ADD_TC(tp, expf_nan); + ATF_TP_ADD_TC(tp, expf_inf_neg); + ATF_TP_ADD_TC(tp, expf_inf_pos); + ATF_TP_ADD_TC(tp, expf_product); + ATF_TP_ADD_TC(tp, expf_zero_neg); + ATF_TP_ADD_TC(tp, expf_zero_pos); + + ATF_TP_ADD_TC(tp, expm1_nan); + ATF_TP_ADD_TC(tp, expm1_inf_neg); + ATF_TP_ADD_TC(tp, expm1_inf_pos); + ATF_TP_ADD_TC(tp, expm1_zero_neg); + ATF_TP_ADD_TC(tp, expm1_zero_pos); + + ATF_TP_ADD_TC(tp, expm1f_nan); + ATF_TP_ADD_TC(tp, expm1f_inf_neg); + ATF_TP_ADD_TC(tp, expm1f_inf_pos); + ATF_TP_ADD_TC(tp, expm1f_zero_neg); + ATF_TP_ADD_TC(tp, expm1f_zero_pos); + + return atf_no_error(); +} diff --git a/lib/libm/t_fmod.c b/lib/libm/t_fmod.c new file mode 100644 index 000000000000..7dac93deae52 --- /dev/null +++ b/lib/libm/t_fmod.c @@ -0,0 +1,63 @@ +/* $NetBSD: t_fmod.c,v 1.2 2014/02/27 17:26:02 joerg Exp $ */ + +/*- + * Copyright (c) 2013 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Joerg Sonnenberger. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <atf-c.h> +#include <float.h> +#include <math.h> + +ATF_TC(fmod); +ATF_TC_HEAD(fmod, tc) +{ + atf_tc_set_md_var(tc, "descr","Check fmod family"); +} + +ATF_TC_BODY(fmod, tc) +{ + ATF_CHECK(fmodf(2.0, 1.0) == 0); + ATF_CHECK(fmod(2.0, 1.0) == 0); + ATF_CHECK(fmodl(2.0, 1.0) == 0); + + ATF_CHECK(fmodf(2.0, 0.5) == 0); + ATF_CHECK(fmod(2.0, 0.5) == 0); + ATF_CHECK(fmodl(2.0, 0.5) == 0); + + ATF_CHECK(fabsf(fmodf(1.0, 0.1) - 0.1f) <= 55 * FLT_EPSILON); + ATF_CHECK(fabs(fmod(1.0, 0.1) - 0.1) <= 55 * DBL_EPSILON); + ATF_CHECK(fabsl(fmodl(1.0, 0.1L) - 0.1L) <= 55 * LDBL_EPSILON); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, fmod); + + return atf_no_error(); +} diff --git a/lib/libm/t_infinity.c b/lib/libm/t_infinity.c new file mode 100644 index 000000000000..7ac17370799c --- /dev/null +++ b/lib/libm/t_infinity.c @@ -0,0 +1,119 @@ +/* $NetBSD: t_infinity.c,v 1.6 2012/09/26 07:24:38 jruoho Exp $ */ + +/*- + * Copyright (c) 2002, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann <martin@NetBSD.org>. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__RCSID("$NetBSD: t_infinity.c,v 1.6 2012/09/26 07:24:38 jruoho Exp $"); + +#include <atf-c.h> +#include <math.h> +#include <float.h> +#include <stdlib.h> + +ATF_TC(infinity_float); +ATF_TC_HEAD(infinity_float, tc) +{ + atf_tc_set_md_var(tc, "descr", + "check FPU generated infinite float values"); +} + +ATF_TC_BODY(infinity_float, tc) +{ + float v; + + v = FLT_MAX; + v *= v; + ATF_REQUIRE(isinf(v)); + ATF_REQUIRE(fpclassify(v) == FP_INFINITE); + + v = -FLT_MAX; + v *= v; + ATF_REQUIRE(isinf(v)); + ATF_REQUIRE(fpclassify(v) == FP_INFINITE); +} + +ATF_TC(infinity_double); +ATF_TC_HEAD(infinity_double, tc) +{ + atf_tc_set_md_var(tc, "descr", + "check FPU generated infinite double values"); +} + +ATF_TC_BODY(infinity_double, tc) +{ + double v; + + v = DBL_MAX; + v *= v; + ATF_REQUIRE(isinf(v)); + ATF_REQUIRE(fpclassify(v) == FP_INFINITE); + + v = -DBL_MAX; + v *= v; + ATF_REQUIRE(isinf(v)); + ATF_REQUIRE(fpclassify(v) == FP_INFINITE); +} + +ATF_TC(infinity_long_double); +ATF_TC_HEAD(infinity_long_double, tc) +{ + atf_tc_set_md_var(tc, "descr", + "check FPU generated infinite long double values"); +} + +ATF_TC_BODY(infinity_long_double, tc) +{ + +#ifndef LDBL_MAX + atf_tc_skip("no long double support on this architecture"); + return; +#else + long double v; + + v = LDBL_MAX; + v *= v; + ATF_REQUIRE(isinf(v)); + ATF_REQUIRE(fpclassify(v) == FP_INFINITE); + + v = -LDBL_MAX; + v *= v; + ATF_REQUIRE(isinf(v)); + ATF_REQUIRE(fpclassify(v) == FP_INFINITE); +#endif +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, infinity_float); + ATF_TP_ADD_TC(tp, infinity_double); + ATF_TP_ADD_TC(tp, infinity_long_double); + + return atf_no_error(); +} diff --git a/lib/libm/t_ldexp.c b/lib/libm/t_ldexp.c new file mode 100644 index 000000000000..9dd001d413fe --- /dev/null +++ b/lib/libm/t_ldexp.c @@ -0,0 +1,481 @@ +/* $NetBSD: t_ldexp.c,v 1.13 2014/03/12 21:40:07 martin Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__RCSID("$NetBSD: t_ldexp.c,v 1.13 2014/03/12 21:40:07 martin Exp $"); + +#include <sys/param.h> + +#include <atf-c.h> +#include <atf-c/config.h> + +#include <math.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> + +#define SKIP 9999 +#define FORMAT "%23.23lg" + +static const int exps[] = { 0, 1, -1, 100, -100 }; + +struct ldexp_test { + double x; + int exp1; + int exp2; + const char *result; +}; + +struct ldexp_test ldexp_basic[] = { + { 1.0, 5, SKIP, " 32" }, + { 1.0, 1022, SKIP, "4.4942328371557897693233e+307" }, + { 1.0, 1023, -1, "4.4942328371557897693233e+307" }, + { 1.0, 1023, SKIP, "8.9884656743115795386465e+307" }, + { 1.0, 1022, 1, "8.9884656743115795386465e+307" }, + { 1.0, -1022, 2045, "8.9884656743115795386465e+307" }, + { 1.0, -5, SKIP, " 0.03125" }, + { 1.0, -1021, SKIP, "4.4501477170144027661805e-308" }, + { 1.0, -1022, 1, "4.4501477170144027661805e-308" }, + { 1.0, -1022, SKIP, "2.2250738585072013830902e-308" }, + { 1.0, -1021, -1, "2.2250738585072013830902e-308" }, + { 1.0, 1023, -2045, "2.2250738585072013830902e-308" }, + { 1.0, 1023, -1023, " 1" }, + { 1.0, -1022, 1022, " 1" }, + { 0, 0, 0, NULL } +}; + +struct ldexp_test ldexp_zero[] = { + { 0.0, -1, SKIP, " 0" }, + { 0.0, 0, SKIP, " 0" }, + { 0.0, 1, SKIP, " 0" }, + { 0.0, 1024, SKIP, " 0" }, + { 0.0, 1025, SKIP, " 0" }, + { 0.0, -1023, SKIP, " 0" }, + { 0.0, -1024, SKIP, " 0" }, + { 0, 0, 0, NULL } +}; + +struct ldexp_test ldexp_infinity[] = { + { 1.0, 1024, -1, " inf" }, + { 1.0, 1024, 0, " inf" }, + { 1.0, 1024, 1, " inf" }, + { -1.0, 1024, -1, " -inf" }, + { -1.0, 1024, 0, " -inf" }, + { -1.0, 1024, 1, " -inf" }, + { 0, 0, 0, NULL } +}; + +struct ldexp_test ldexp_overflow[] = { + { 1.0, 1024, SKIP, " inf" }, + { 1.0, 1023, 1, " inf" }, + { 1.0, -1022, 2046, " inf" }, + { 1.0, 1025, SKIP, " inf" }, + { -1.0, 1024, SKIP, " -inf" }, + { -1.0, 1023, 1, " -inf" }, + { -1.0, -1022, 2046, " -inf" }, + { -1.0, 1025, SKIP, " -inf" }, + { 0, 0, 0, NULL } +}; + +struct ldexp_test ldexp_denormal[] = { + { 1.0, -1023, SKIP, "1.1125369292536006915451e-308" }, + { 1.0, -1022, -1, "1.1125369292536006915451e-308" }, + { 1.0, 1023, -2046, "1.1125369292536006915451e-308" }, + { 1.0, -1024, SKIP, "5.5626846462680034577256e-309" }, + { 1.0, -1074, SKIP, "4.9406564584124654417657e-324" }, + { -1.0, -1023, SKIP, "-1.1125369292536006915451e-308" }, + { -1.0, -1022, -1, "-1.1125369292536006915451e-308" }, + { -1.0, 1023, -2046, "-1.1125369292536006915451e-308" }, + { -1.0, -1024, SKIP, "-5.5626846462680034577256e-309" }, + { -1.0, -1074, SKIP, "-4.9406564584124654417657e-324" }, + { 0, 0, 0, NULL } +}; + +struct ldexp_test ldexp_underflow[] = { + { 1.0, -1075, SKIP, " 0" }, + { 1.0, -1074, -1, " 0" }, + { 1.0, 1023, -2098, " 0" }, + { 1.0, -1076, SKIP, " 0" }, + { -1.0, -1075, SKIP, " -0" }, + { -1.0, -1074, -1, " -0" }, + { -1.0, 1023, -2098, " -0" }, + { -1.0, -1076, SKIP, " -0" }, + { 0, 0, 0, NULL } +}; + +struct ldexp_test ldexp_denormal_large[] = { + { 1.0, -1028, 1024, " 0.0625" }, + { 1.0, -1028, 1025, " 0.125" }, + { 1.0, -1028, 1026, " 0.25" }, + { 1.0, -1028, 1027, " 0.5" }, + { 1.0, -1028, 1028, " 1" }, + { 1.0, -1028, 1029, " 2" }, + { 1.0, -1028, 1030, " 4" }, + { 1.0, -1028, 1040, " 4096" }, + { 1.0, -1028, 1050, " 4194304" }, + { 1.0, -1028, 1060, " 4294967296" }, + { 1.0, -1028, 1100, " 4722366482869645213696" }, + { 1.0, -1028, 1200, "5.9863107065073783529623e+51" }, + { 1.0, -1028, 1300, "7.5885503602567541832791e+81" }, + { 1.0, -1028, 1400, "9.6196304190416209014353e+111" }, + { 1.0, -1028, 1500, "1.2194330274671844653834e+142" }, + { 1.0, -1028, 1600, "1.5458150092069033378781e+172" }, + { 1.0, -1028, 1700, "1.9595533242629369747791e+202" }, + { 1.0, -1028, 1800, "2.4840289476811342962384e+232" }, + { 1.0, -1028, 1900, "3.1488807865122869393369e+262" }, + { 1.0, -1028, 2000, "3.9916806190694396233127e+292" }, + { 1.0, -1028, 2046, "2.808895523222368605827e+306" }, + { 1.0, -1028, 2047, "5.6177910464447372116541e+306" }, + { 1.0, -1028, 2048, "1.1235582092889474423308e+307" }, + { 1.0, -1028, 2049, "2.2471164185778948846616e+307" }, + { 1.0, -1028, 2050, "4.4942328371557897693233e+307" }, + { 1.0, -1028, 2051, "8.9884656743115795386465e+307" }, + { 0, 0, 0, NULL } +}; + +static void +run_test(struct ldexp_test *table) +{ + char outbuf[64]; + size_t i; + double v; + + for (i = 0; table->result != NULL; table++, i++) { + + v = ldexp(table->x, table->exp1); + + if (table->exp2 == SKIP) + continue; + + v = ldexp(v, table->exp2); + + (void)snprintf(outbuf, sizeof(outbuf), FORMAT, v); + + ATF_CHECK_STREQ_MSG(table->result, outbuf, + "Entry %zu:\n\tExp: \"%s\"\n\tAct: \"%s\"", + i, table->result, outbuf); + } +} + +/* + * ldexp(3) + */ +ATF_TC(ldexp_exp2); +ATF_TC_HEAD(ldexp_exp2, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ldexp(x, n) == x * exp2(n)"); +} + +ATF_TC_BODY(ldexp_exp2, tc) +{ + const double n[] = { 1, 2, 3, 10, 50, 100 }; +#if __DBL_MIN_10_EXP__ <= -40 + const double eps = 1.0e-40; +#else + const double eps = __DBL_MIN__*4.0; +#endif + const double x = 12.0; + double y; + size_t i; + + for (i = 0; i < __arraycount(n); i++) { + + y = ldexp(x, n[i]); + + if (fabs(y - (x * exp2(n[i]))) > eps) { + atf_tc_fail_nonfatal("ldexp(%0.01f, %0.01f) " + "!= %0.01f * exp2(%0.01f)", x, n[i], x, n[i]); + } + } +} + +ATF_TC(ldexp_nan); +ATF_TC_HEAD(ldexp_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ldexp(NaN) == NaN"); +} + +ATF_TC_BODY(ldexp_nan, tc) +{ + const double x = 0.0L / 0.0L; + double y; + size_t i; + + ATF_REQUIRE(isnan(x) != 0); + + for (i = 0; i < __arraycount(exps); i++) { + y = ldexp(x, exps[i]); + ATF_CHECK(isnan(y) != 0); + } +} + +ATF_TC(ldexp_inf_neg); +ATF_TC_HEAD(ldexp_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ldexp(-Inf) == -Inf"); +} + +ATF_TC_BODY(ldexp_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + size_t i; + + for (i = 0; i < __arraycount(exps); i++) + ATF_CHECK(ldexp(x, exps[i]) == x); +} + +ATF_TC(ldexp_inf_pos); +ATF_TC_HEAD(ldexp_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ldexp(+Inf) == +Inf"); +} + +ATF_TC_BODY(ldexp_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + size_t i; + + for (i = 0; i < __arraycount(exps); i++) + ATF_CHECK(ldexp(x, exps[i]) == x); +} + +ATF_TC(ldexp_zero_neg); +ATF_TC_HEAD(ldexp_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ldexp(-0.0) == -0.0"); +} + +ATF_TC_BODY(ldexp_zero_neg, tc) +{ + const double x = -0.0L; + double y; + size_t i; + + ATF_REQUIRE(signbit(x) != 0); + + for (i = 0; i < __arraycount(exps); i++) { + y = ldexp(x, exps[i]); + ATF_CHECK(x == y); + ATF_CHECK(signbit(y) != 0); + } +} + +ATF_TC(ldexp_zero_pos); +ATF_TC_HEAD(ldexp_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ldexp(+0.0) == +0.0"); +} + +ATF_TC_BODY(ldexp_zero_pos, tc) +{ + const double x = 0.0L; + double y; + size_t i; + + ATF_REQUIRE(signbit(x) == 0); + + for (i = 0; i < __arraycount(exps); i++) { + y = ldexp(x, exps[i]); + ATF_CHECK(x == y); + ATF_CHECK(signbit(y) == 0); + } +} + +/* + * ldexpf(3) + */ + +ATF_TC(ldexpf_exp2f); +ATF_TC_HEAD(ldexpf_exp2f, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ldexpf(x, n) == x * exp2f(n)"); +} + +ATF_TC_BODY(ldexpf_exp2f, tc) +{ + const float n[] = { 1, 2, 3, 10, 50, 100 }; + const float eps = 1.0e-9; + const float x = 12.0; + float y; + size_t i; + + for (i = 0; i < __arraycount(n); i++) { + + y = ldexpf(x, n[i]); + + if (fabsf(y - (x * exp2f(n[i]))) > eps) { + atf_tc_fail_nonfatal("ldexpf(%0.01f, %0.01f) " + "!= %0.01f * exp2f(%0.01f)", x, n[i], x, n[i]); + } + } +} + +ATF_TC(ldexpf_nan); +ATF_TC_HEAD(ldexpf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ldexpf(NaN) == NaN"); +} + +ATF_TC_BODY(ldexpf_nan, tc) +{ + const float x = 0.0L / 0.0L; + float y; + size_t i; + + ATF_REQUIRE(isnan(x) != 0); + + for (i = 0; i < __arraycount(exps); i++) { + y = ldexpf(x, exps[i]); + ATF_CHECK(isnan(y) != 0); + } +} + +ATF_TC(ldexpf_inf_neg); +ATF_TC_HEAD(ldexpf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ldexpf(-Inf) == -Inf"); +} + +ATF_TC_BODY(ldexpf_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + size_t i; + + for (i = 0; i < __arraycount(exps); i++) + ATF_CHECK(ldexpf(x, exps[i]) == x); +} + +ATF_TC(ldexpf_inf_pos); +ATF_TC_HEAD(ldexpf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ldexpf(+Inf) == +Inf"); +} + +ATF_TC_BODY(ldexpf_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + size_t i; + + for (i = 0; i < __arraycount(exps); i++) + ATF_CHECK(ldexpf(x, exps[i]) == x); +} + +ATF_TC(ldexpf_zero_neg); +ATF_TC_HEAD(ldexpf_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ldexpf(-0.0) == -0.0"); +} + +ATF_TC_BODY(ldexpf_zero_neg, tc) +{ + const float x = -0.0L; + float y; + size_t i; + + ATF_REQUIRE(signbit(x) != 0); + + for (i = 0; i < __arraycount(exps); i++) { + y = ldexpf(x, exps[i]); + ATF_CHECK(x == y); + ATF_CHECK(signbit(y) != 0); + } +} + +ATF_TC(ldexpf_zero_pos); +ATF_TC_HEAD(ldexpf_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test ldexpf(+0.0) == +0.0"); +} + +ATF_TC_BODY(ldexpf_zero_pos, tc) +{ + const float x = 0.0L; + float y; + size_t i; + + ATF_REQUIRE(signbit(x) == 0); + + for (i = 0; i < __arraycount(exps); i++) { + y = ldexpf(x, exps[i]); + ATF_CHECK(x == y); + ATF_CHECK(signbit(y) == 0); + } +} + +#define TEST(name, desc) \ + ATF_TC(name); \ + ATF_TC_HEAD(name, tc) \ + { \ + \ + atf_tc_set_md_var(tc, "descr", \ + "Test ldexp(3) for " ___STRING(desc)); \ + } \ + ATF_TC_BODY(name, tc) \ + { \ + if (strcmp("vax", MACHINE_ARCH) == 0) \ + atf_tc_skip("Test not valid for " MACHINE_ARCH); \ + run_test(name); \ + } + +TEST(ldexp_basic, basics) +TEST(ldexp_zero, zero) +TEST(ldexp_infinity, infinity) +TEST(ldexp_overflow, overflow) +TEST(ldexp_denormal, denormal) +TEST(ldexp_denormal_large, large) +TEST(ldexp_underflow, underflow) + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, ldexp_basic); + ATF_TP_ADD_TC(tp, ldexp_zero); + ATF_TP_ADD_TC(tp, ldexp_infinity); + ATF_TP_ADD_TC(tp, ldexp_overflow); + ATF_TP_ADD_TC(tp, ldexp_denormal); + ATF_TP_ADD_TC(tp, ldexp_underflow); + ATF_TP_ADD_TC(tp, ldexp_denormal_large); + + ATF_TP_ADD_TC(tp, ldexp_exp2); + ATF_TP_ADD_TC(tp, ldexp_nan); + ATF_TP_ADD_TC(tp, ldexp_inf_neg); + ATF_TP_ADD_TC(tp, ldexp_inf_pos); + ATF_TP_ADD_TC(tp, ldexp_zero_neg); + ATF_TP_ADD_TC(tp, ldexp_zero_pos); + + ATF_TP_ADD_TC(tp, ldexpf_exp2f); + ATF_TP_ADD_TC(tp, ldexpf_nan); + ATF_TP_ADD_TC(tp, ldexpf_inf_neg); + ATF_TP_ADD_TC(tp, ldexpf_inf_pos); + ATF_TP_ADD_TC(tp, ldexpf_zero_neg); + ATF_TP_ADD_TC(tp, ldexpf_zero_pos); + + return atf_no_error(); +} diff --git a/lib/libm/t_libm.h b/lib/libm/t_libm.h new file mode 100644 index 000000000000..34e3cb28abf5 --- /dev/null +++ b/lib/libm/t_libm.h @@ -0,0 +1,62 @@ +/* $NetBSD: t_libm.h,v 1.6 2014/03/25 17:30:14 joerg Exp $ */ + +/* + * Check result of fn(arg) is correct within the bounds. + * Should be ok to do the checks using 'double' for 'float' functions. + * On i386 float and double values are returned on the x87 stack and might + * be out of range for the function - so save and print as 'long double'. + * (otherwise you can get 'inf != inf' reported!) + */ +#define T_LIBM_CHECK(subtest, fn, arg, expect_, epsilon_) do { \ + long double epsilon = epsilon_; \ + long double expect = expect_; \ + long double r = fn(arg); \ + long double e = fabsl(r - expect); \ + if (r != expect && e > epsilon) \ + atf_tc_fail_nonfatal( \ + "subtest %u: " #fn "(%g) is %Lg (%.14La) " \ + "not %Lg (%.13La), error %Lg (%.6La) > %Lg", \ + subtest, arg, r, r, expect, expect, e, e, epsilon); \ + } while (0) + +/* Check that the result of fn(arg) is NaN */ +#ifndef __vax__ +#define T_LIBM_CHECK_NAN(subtest, fn, arg) do { \ + double r = fn(arg); \ + if (!isnan(r)) \ + atf_tc_fail_nonfatal("subtest %u: " #fn "(%g) is %g not NaN", \ + subtest, arg, r); \ + } while (0) +#else +/* vax doesn't support NaN */ +#define T_LIBM_CHECK_NAN(subtest, fn, arg) (void)(arg) +#endif + +/* Check that the result of fn(arg) is +0.0 */ +#define T_LIBM_CHECK_PLUS_ZERO(subtest, fn, arg) do { \ + double r = fn(arg); \ + if (fabs(r) > 0.0 || signbit(r) != 0) \ + atf_tc_fail_nonfatal("subtest %u: " #fn "(%g) is %g not +0.0", \ + subtest, arg, r); \ + } while (0) + +/* Check that the result of fn(arg) is -0.0 */ +#define T_LIBM_CHECK_MINUS_ZERO(subtest, fn, arg) do { \ + double r = fn(arg); \ + if (fabs(r) > 0.0 || signbit(r) == 0) \ + atf_tc_fail_nonfatal("subtest %u: " #fn "(%g) is %g not -0.0", \ + subtest, arg, r); \ + } while (0) + +/* Some useful constants (for test vectors) */ +#ifndef __vax__ /* no NAN nor +/- INF on vax */ +#define T_LIBM_NAN (0.0 / 0.0) +#define T_LIBM_PLUS_INF (+1.0 / 0.0) +#define T_LIBM_MINUS_INF (-1.0 / 0.0) +#endif + +/* One line definition of a simple test */ +#define ATF_LIBM_TEST(name, description) \ +ATF_TC(name); \ +ATF_TC_HEAD(name, tc) { atf_tc_set_md_var(tc, "descr", description); } \ +ATF_TC_BODY(name, tc) diff --git a/lib/libm/t_log.c b/lib/libm/t_log.c new file mode 100644 index 000000000000..de5a1c649451 --- /dev/null +++ b/lib/libm/t_log.c @@ -0,0 +1,885 @@ +/* $NetBSD: t_log.c,v 1.11 2014/03/03 10:39:08 martin Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__RCSID("$NetBSD: t_log.c,v 1.11 2014/03/03 10:39:08 martin Exp $"); + +#include <atf-c.h> +#include <atf-c/config.h> + +#include <math.h> +#include <stdio.h> +#include <string.h> + +/* + * log10(3) + */ +ATF_TC(log10_base); +ATF_TC_HEAD(log10_base, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log10(10) == 1"); +} + +ATF_TC_BODY(log10_base, tc) +{ + ATF_CHECK(log10(10.0) == 1.0); +} + +ATF_TC(log10_nan); +ATF_TC_HEAD(log10_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log10(NaN) == NaN"); +} + +ATF_TC_BODY(log10_nan, tc) +{ + const double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(log10(x)) != 0); +} + +ATF_TC(log10_inf_neg); +ATF_TC_HEAD(log10_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log10(-Inf) == NaN"); +} + +ATF_TC_BODY(log10_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + const double y = log10(x); + + ATF_CHECK(isnan(y) != 0); +} + +ATF_TC(log10_inf_pos); +ATF_TC_HEAD(log10_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log10(+Inf) == +Inf"); +} + +ATF_TC_BODY(log10_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + + ATF_CHECK(log10(x) == x); +} + +ATF_TC(log10_one_pos); +ATF_TC_HEAD(log10_one_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log10(1.0) == +0.0"); +} + +ATF_TC_BODY(log10_one_pos, tc) +{ + const double x = log10(1.0); + const double y = 0.0L; + + ATF_CHECK(x == y); + ATF_CHECK(signbit(x) == 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TC(log10_zero_neg); +ATF_TC_HEAD(log10_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log10(-0.0) == -HUGE_VAL"); +} + +ATF_TC_BODY(log10_zero_neg, tc) +{ + const double x = -0.0L; + + ATF_CHECK(log10(x) == -HUGE_VAL); +} + +ATF_TC(log10_zero_pos); +ATF_TC_HEAD(log10_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log10(+0.0) == -HUGE_VAL"); +} + +ATF_TC_BODY(log10_zero_pos, tc) +{ + const double x = 0.0L; + + ATF_CHECK(log10(x) == -HUGE_VAL); +} + +/* + * log10f(3) + */ +ATF_TC(log10f_base); +ATF_TC_HEAD(log10f_base, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log10f(10) == 1"); +} + +ATF_TC_BODY(log10f_base, tc) +{ + ATF_CHECK(log10f(10.0) == 1.0); +} + +ATF_TC(log10f_nan); +ATF_TC_HEAD(log10f_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log10f(NaN) == NaN"); +} + +ATF_TC_BODY(log10f_nan, tc) +{ + const float x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(log10f(x)) != 0); +} + +ATF_TC(log10f_inf_neg); +ATF_TC_HEAD(log10f_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log10f(-Inf) == NaN"); +} + +ATF_TC_BODY(log10f_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + const float y = log10f(x); + + ATF_CHECK(isnan(y) != 0); +} + +ATF_TC(log10f_inf_pos); +ATF_TC_HEAD(log10f_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log10f(+Inf) == +Inf"); +} + +ATF_TC_BODY(log10f_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + +#if defined(__alpha__) + atf_tc_expect_fail("PR port-alpha/46301"); +#endif + + ATF_CHECK(log10f(x) == x); +} + +ATF_TC(log10f_one_pos); +ATF_TC_HEAD(log10f_one_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log10f(1.0) == +0.0"); +} + +ATF_TC_BODY(log10f_one_pos, tc) +{ + const float x = log10f(1.0); + const float y = 0.0L; + + ATF_CHECK(x == y); + ATF_CHECK(signbit(x) == 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TC(log10f_zero_neg); +ATF_TC_HEAD(log10f_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log10f(-0.0) == -HUGE_VALF"); +} + +ATF_TC_BODY(log10f_zero_neg, tc) +{ + const float x = -0.0L; + + ATF_CHECK(log10f(x) == -HUGE_VALF); +} + +ATF_TC(log10f_zero_pos); +ATF_TC_HEAD(log10f_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log10f(+0.0) == -HUGE_VALF"); +} + +ATF_TC_BODY(log10f_zero_pos, tc) +{ + const float x = 0.0L; + + ATF_CHECK(log10f(x) == -HUGE_VALF); +} + +/* + * log1p(3) + */ +ATF_TC(log1p_nan); +ATF_TC_HEAD(log1p_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log1p(NaN) == NaN"); +} + +ATF_TC_BODY(log1p_nan, tc) +{ + const double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(log1p(x)) != 0); +} + +ATF_TC(log1p_inf_neg); +ATF_TC_HEAD(log1p_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log1p(-Inf) == NaN"); +} + +ATF_TC_BODY(log1p_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + const double y = log1p(x); + + if (isnan(y) == 0) { + atf_tc_expect_fail("PR lib/45362"); + atf_tc_fail("log1p(-Inf) != NaN"); + } +} + +ATF_TC(log1p_inf_pos); +ATF_TC_HEAD(log1p_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log1p(+Inf) == +Inf"); +} + +ATF_TC_BODY(log1p_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + + ATF_CHECK(log1p(x) == x); +} + +ATF_TC(log1p_one_neg); +ATF_TC_HEAD(log1p_one_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log1p(-1.0) == -HUGE_VAL"); +} + +ATF_TC_BODY(log1p_one_neg, tc) +{ + const double x = log1p(-1.0); + + if (x != -HUGE_VAL) { + atf_tc_expect_fail("PR lib/45362"); + atf_tc_fail("log1p(-1.0) != -HUGE_VAL"); + } +} + +ATF_TC(log1p_zero_neg); +ATF_TC_HEAD(log1p_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log1p(-0.0) == -0.0"); +} + +ATF_TC_BODY(log1p_zero_neg, tc) +{ + const double x = -0.0L; + + ATF_CHECK(log1p(x) == x); +} + +ATF_TC(log1p_zero_pos); +ATF_TC_HEAD(log1p_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log1p(+0.0) == +0.0"); +} + +ATF_TC_BODY(log1p_zero_pos, tc) +{ + const double x = 0.0L; + + ATF_CHECK(log1p(x) == x); +} + +/* + * log1pf(3) + */ +ATF_TC(log1pf_nan); +ATF_TC_HEAD(log1pf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log1pf(NaN) == NaN"); +} + +ATF_TC_BODY(log1pf_nan, tc) +{ + const float x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(log1pf(x)) != 0); +} + +ATF_TC(log1pf_inf_neg); +ATF_TC_HEAD(log1pf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log1pf(-Inf) == NaN"); +} + +ATF_TC_BODY(log1pf_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + const float y = log1pf(x); + + if (isnan(y) == 0) { + atf_tc_expect_fail("PR lib/45362"); + atf_tc_fail("log1pf(-Inf) != NaN"); + } +} + +ATF_TC(log1pf_inf_pos); +ATF_TC_HEAD(log1pf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log1pf(+Inf) == +Inf"); +} + +ATF_TC_BODY(log1pf_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + + ATF_CHECK(log1pf(x) == x); +} + +ATF_TC(log1pf_one_neg); +ATF_TC_HEAD(log1pf_one_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log1pf(-1.0) == -HUGE_VALF"); +} + +ATF_TC_BODY(log1pf_one_neg, tc) +{ + const float x = log1pf(-1.0); + + if (x != -HUGE_VALF) { + atf_tc_expect_fail("PR lib/45362"); + atf_tc_fail("log1pf(-1.0) != -HUGE_VALF"); + } +} + +ATF_TC(log1pf_zero_neg); +ATF_TC_HEAD(log1pf_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log1pf(-0.0) == -0.0"); +} + +ATF_TC_BODY(log1pf_zero_neg, tc) +{ + const float x = -0.0L; + + ATF_CHECK(log1pf(x) == x); +} + +ATF_TC(log1pf_zero_pos); +ATF_TC_HEAD(log1pf_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log1pf(+0.0) == +0.0"); +} + +ATF_TC_BODY(log1pf_zero_pos, tc) +{ + const float x = 0.0L; + + ATF_CHECK(log1pf(x) == x); +} + +/* + * log2(3) + */ +ATF_TC(log2_base); +ATF_TC_HEAD(log2_base, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log2(2) == 1"); +} + +ATF_TC_BODY(log2_base, tc) +{ + ATF_CHECK(log2(2.0) == 1.0); +} + +ATF_TC(log2_nan); +ATF_TC_HEAD(log2_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log2(NaN) == NaN"); +} + +ATF_TC_BODY(log2_nan, tc) +{ + const double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(log2(x)) != 0); +} + +ATF_TC(log2_inf_neg); +ATF_TC_HEAD(log2_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log2(-Inf) == NaN"); +} + +ATF_TC_BODY(log2_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + const double y = log2(x); + + ATF_CHECK(isnan(y) != 0); +} + +ATF_TC(log2_inf_pos); +ATF_TC_HEAD(log2_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log2(+Inf) == +Inf"); +} + +ATF_TC_BODY(log2_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + + ATF_CHECK(log2(x) == x); +} + +ATF_TC(log2_one_pos); +ATF_TC_HEAD(log2_one_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log2(1.0) == +0.0"); +} + +ATF_TC_BODY(log2_one_pos, tc) +{ + const double x = log2(1.0); + const double y = 0.0L; + + ATF_CHECK(x == y); + ATF_CHECK(signbit(x) == 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TC(log2_zero_neg); +ATF_TC_HEAD(log2_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log2(-0.0) == -HUGE_VAL"); +} + +ATF_TC_BODY(log2_zero_neg, tc) +{ + const double x = -0.0L; + + ATF_CHECK(log2(x) == -HUGE_VAL); +} + +ATF_TC(log2_zero_pos); +ATF_TC_HEAD(log2_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log2(+0.0) == -HUGE_VAL"); +} + +ATF_TC_BODY(log2_zero_pos, tc) +{ + const double x = 0.0L; + + ATF_CHECK(log2(x) == -HUGE_VAL); +} + +/* + * log2f(3) + */ +ATF_TC(log2f_base); +ATF_TC_HEAD(log2f_base, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log2f(2) == 1"); +} + +ATF_TC_BODY(log2f_base, tc) +{ + ATF_CHECK(log2f(2.0) == 1.0); +} + +ATF_TC(log2f_nan); +ATF_TC_HEAD(log2f_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log2f(NaN) == NaN"); +} + +ATF_TC_BODY(log2f_nan, tc) +{ + const float x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(log2f(x)) != 0); +} + +ATF_TC(log2f_inf_neg); +ATF_TC_HEAD(log2f_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log2f(-Inf) == NaN"); +} + +ATF_TC_BODY(log2f_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + const float y = log2f(x); + + ATF_CHECK(isnan(y) != 0); +} + +ATF_TC(log2f_inf_pos); +ATF_TC_HEAD(log2f_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log2f(+Inf) == +Inf"); +} + +ATF_TC_BODY(log2f_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + +#if defined(__alpha__) + atf_tc_expect_fail("PR port-alpha/46301"); +#endif + + ATF_CHECK(log2f(x) == x); +} + +ATF_TC(log2f_one_pos); +ATF_TC_HEAD(log2f_one_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log2f(1.0) == +0.0"); +} + +ATF_TC_BODY(log2f_one_pos, tc) +{ + const float x = log2f(1.0); + const float y = 0.0L; + + ATF_CHECK(x == y); + ATF_CHECK(signbit(x) == 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TC(log2f_zero_neg); +ATF_TC_HEAD(log2f_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log2f(-0.0) == -HUGE_VALF"); +} + +ATF_TC_BODY(log2f_zero_neg, tc) +{ + const float x = -0.0L; + + ATF_CHECK(log2f(x) == -HUGE_VALF); +} + +ATF_TC(log2f_zero_pos); +ATF_TC_HEAD(log2f_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log2f(+0.0) == -HUGE_VALF"); +} + +ATF_TC_BODY(log2f_zero_pos, tc) +{ + const float x = 0.0L; + + ATF_CHECK(log2f(x) == -HUGE_VALF); +} + +/* + * log(3) + */ +ATF_TC(log_base); +ATF_TC_HEAD(log_base, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log(e) == 1"); +} + +ATF_TC_BODY(log_base, tc) +{ + const double eps = 1.0e-38; + + if (fabs(log(M_E) - 1.0) > eps) + atf_tc_fail_nonfatal("log(e) != 1"); +} + +ATF_TC(log_nan); +ATF_TC_HEAD(log_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log(NaN) == NaN"); +} + +ATF_TC_BODY(log_nan, tc) +{ + const double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(log(x)) != 0); +} + +ATF_TC(log_inf_neg); +ATF_TC_HEAD(log_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log(-Inf) == NaN"); +} + +ATF_TC_BODY(log_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + const double y = log(x); + + ATF_CHECK(isnan(y) != 0); +} + +ATF_TC(log_inf_pos); +ATF_TC_HEAD(log_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log(+Inf) == +Inf"); +} + +ATF_TC_BODY(log_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + + ATF_CHECK(log(x) == x); +} + +ATF_TC(log_one_pos); +ATF_TC_HEAD(log_one_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log(1.0) == +0.0"); +} + +ATF_TC_BODY(log_one_pos, tc) +{ + const double x = log(1.0); + const double y = 0.0L; + + ATF_CHECK(x == y); + ATF_CHECK(signbit(x) == 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TC(log_zero_neg); +ATF_TC_HEAD(log_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log(-0.0) == -HUGE_VAL"); +} + +ATF_TC_BODY(log_zero_neg, tc) +{ + const double x = -0.0L; + + ATF_CHECK(log(x) == -HUGE_VAL); +} + +ATF_TC(log_zero_pos); +ATF_TC_HEAD(log_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test log(+0.0) == -HUGE_VAL"); +} + +ATF_TC_BODY(log_zero_pos, tc) +{ + const double x = 0.0L; + + ATF_CHECK(log(x) == -HUGE_VAL); +} + +/* + * logf(3) + */ +ATF_TC(logf_base); +ATF_TC_HEAD(logf_base, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test logf(e) == 1"); +} + +ATF_TC_BODY(logf_base, tc) +{ + const float eps = 1.0e-7; + + if (fabsf(logf(M_E) - 1.0f) > eps) + atf_tc_fail_nonfatal("logf(e) != 1"); +} + +ATF_TC(logf_nan); +ATF_TC_HEAD(logf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test logf(NaN) == NaN"); +} + +ATF_TC_BODY(logf_nan, tc) +{ + const float x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(logf(x)) != 0); +} + +ATF_TC(logf_inf_neg); +ATF_TC_HEAD(logf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test logf(-Inf) == NaN"); +} + +ATF_TC_BODY(logf_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + const float y = logf(x); + + ATF_CHECK(isnan(y) != 0); +} + +ATF_TC(logf_inf_pos); +ATF_TC_HEAD(logf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test logf(+Inf) == +Inf"); +} + +ATF_TC_BODY(logf_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + +#if defined(__alpha__) + atf_tc_expect_fail("PR port-alpha/46301"); +#endif + + ATF_CHECK(logf(x) == x); +} + +ATF_TC(logf_one_pos); +ATF_TC_HEAD(logf_one_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test logf(1.0) == +0.0"); +} + +ATF_TC_BODY(logf_one_pos, tc) +{ + const float x = logf(1.0); + const float y = 0.0L; + + ATF_CHECK(x == y); + ATF_CHECK(signbit(x) == 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TC(logf_zero_neg); +ATF_TC_HEAD(logf_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test logf(-0.0) == -HUGE_VALF"); +} + +ATF_TC_BODY(logf_zero_neg, tc) +{ + const float x = -0.0L; + + ATF_CHECK(logf(x) == -HUGE_VALF); +} + +ATF_TC(logf_zero_pos); +ATF_TC_HEAD(logf_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test logf(+0.0) == -HUGE_VALF"); +} + +ATF_TC_BODY(logf_zero_pos, tc) +{ + const float x = 0.0L; + + ATF_CHECK(logf(x) == -HUGE_VALF); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, log10_base); + ATF_TP_ADD_TC(tp, log10_nan); + ATF_TP_ADD_TC(tp, log10_inf_neg); + ATF_TP_ADD_TC(tp, log10_inf_pos); + ATF_TP_ADD_TC(tp, log10_one_pos); + ATF_TP_ADD_TC(tp, log10_zero_neg); + ATF_TP_ADD_TC(tp, log10_zero_pos); + + ATF_TP_ADD_TC(tp, log10f_base); + ATF_TP_ADD_TC(tp, log10f_nan); + ATF_TP_ADD_TC(tp, log10f_inf_neg); + ATF_TP_ADD_TC(tp, log10f_inf_pos); + ATF_TP_ADD_TC(tp, log10f_one_pos); + ATF_TP_ADD_TC(tp, log10f_zero_neg); + ATF_TP_ADD_TC(tp, log10f_zero_pos); + + ATF_TP_ADD_TC(tp, log1p_nan); + ATF_TP_ADD_TC(tp, log1p_inf_neg); + ATF_TP_ADD_TC(tp, log1p_inf_pos); + ATF_TP_ADD_TC(tp, log1p_one_neg); + ATF_TP_ADD_TC(tp, log1p_zero_neg); + ATF_TP_ADD_TC(tp, log1p_zero_pos); + + ATF_TP_ADD_TC(tp, log1pf_nan); + ATF_TP_ADD_TC(tp, log1pf_inf_neg); + ATF_TP_ADD_TC(tp, log1pf_inf_pos); + ATF_TP_ADD_TC(tp, log1pf_one_neg); + ATF_TP_ADD_TC(tp, log1pf_zero_neg); + ATF_TP_ADD_TC(tp, log1pf_zero_pos); + + ATF_TP_ADD_TC(tp, log2_base); + ATF_TP_ADD_TC(tp, log2_nan); + ATF_TP_ADD_TC(tp, log2_inf_neg); + ATF_TP_ADD_TC(tp, log2_inf_pos); + ATF_TP_ADD_TC(tp, log2_one_pos); + ATF_TP_ADD_TC(tp, log2_zero_neg); + ATF_TP_ADD_TC(tp, log2_zero_pos); + + ATF_TP_ADD_TC(tp, log2f_base); + ATF_TP_ADD_TC(tp, log2f_nan); + ATF_TP_ADD_TC(tp, log2f_inf_neg); + ATF_TP_ADD_TC(tp, log2f_inf_pos); + ATF_TP_ADD_TC(tp, log2f_one_pos); + ATF_TP_ADD_TC(tp, log2f_zero_neg); + ATF_TP_ADD_TC(tp, log2f_zero_pos); + + ATF_TP_ADD_TC(tp, log_base); + ATF_TP_ADD_TC(tp, log_nan); + ATF_TP_ADD_TC(tp, log_inf_neg); + ATF_TP_ADD_TC(tp, log_inf_pos); + ATF_TP_ADD_TC(tp, log_one_pos); + ATF_TP_ADD_TC(tp, log_zero_neg); + ATF_TP_ADD_TC(tp, log_zero_pos); + + ATF_TP_ADD_TC(tp, logf_base); + ATF_TP_ADD_TC(tp, logf_nan); + ATF_TP_ADD_TC(tp, logf_inf_neg); + ATF_TP_ADD_TC(tp, logf_inf_pos); + ATF_TP_ADD_TC(tp, logf_one_pos); + ATF_TP_ADD_TC(tp, logf_zero_neg); + ATF_TP_ADD_TC(tp, logf_zero_pos); + + return atf_no_error(); +} diff --git a/lib/libm/t_modf.c b/lib/libm/t_modf.c new file mode 100644 index 000000000000..a856b15d1aab --- /dev/null +++ b/lib/libm/t_modf.c @@ -0,0 +1,68 @@ +/* $NetBSD: t_modf.c,v 1.1 2014/06/16 12:54:43 joerg Exp $ */ + +/*- + * Copyright (c) 2014 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Joerg Sonnenberger. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <atf-c.h> +#include <float.h> +#include <math.h> + +ATF_TC(modf); +ATF_TC_HEAD(modf, tc) +{ + atf_tc_set_md_var(tc, "descr","Check modf family"); +} + +ATF_TC_BODY(modf, tc) +{ + float basef; + double base; + long double basel; + ATF_CHECK(modff(1.0, &basef) == 0.0); + ATF_CHECK(basef == 1.0); + ATF_CHECK(modf(1.0, &base) == 0.0); + ATF_CHECK(base == 1.0); + ATF_CHECK(modfl(1.0, &basel) == 0.0); + ATF_CHECK(basel == 1.0); + + ATF_CHECK(modff(-1 - FLT_EPSILON, &basef) == -FLT_EPSILON); + ATF_CHECK(basef == -1.0); + ATF_CHECK(modf(-1 - DBL_EPSILON, &base) == -DBL_EPSILON); + ATF_CHECK(base == -1.0); + ATF_CHECK(modfl(-1 - LDBL_EPSILON, &basel) == -LDBL_EPSILON); + ATF_CHECK(basel == -1.0); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, modf); + + return atf_no_error(); +} diff --git a/lib/libm/t_pow.c b/lib/libm/t_pow.c new file mode 100644 index 000000000000..62b7235e7640 --- /dev/null +++ b/lib/libm/t_pow.c @@ -0,0 +1,669 @@ +/* $NetBSD: t_pow.c,v 1.3 2014/03/03 10:39:08 martin Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__RCSID("$NetBSD: t_pow.c,v 1.3 2014/03/03 10:39:08 martin Exp $"); + +#include <atf-c.h> +#include <math.h> + +/* + * pow(3) + */ +ATF_TC(pow_nan_x); +ATF_TC_HEAD(pow_nan_x, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test pow(NaN, y) == NaN"); +} + +ATF_TC_BODY(pow_nan_x, tc) +{ + const double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(pow(x, 2.0)) != 0); +} + +ATF_TC(pow_nan_y); +ATF_TC_HEAD(pow_nan_y, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test pow(x, NaN) == NaN"); +} + +ATF_TC_BODY(pow_nan_y, tc) +{ + const double y = 0.0L / 0.0L; + + ATF_CHECK(isnan(pow(2.0, y)) != 0); +} + +ATF_TC(pow_inf_neg_x); +ATF_TC_HEAD(pow_inf_neg_x, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test pow(-Inf, y) == +-Inf || +-0.0"); +} + +ATF_TC_BODY(pow_inf_neg_x, tc) +{ + const double x = -1.0L / 0.0L; + double z; + + /* + * If y is odd, y > 0, and x is -Inf, -Inf is returned. + * If y is even, y > 0, and x is -Inf, +Inf is returned. + */ + z = pow(x, 3.0); + + if (isinf(z) == 0 || signbit(z) == 0) + atf_tc_fail_nonfatal("pow(-Inf, 3.0) != -Inf"); + + z = pow(x, 4.0); + + if (isinf(z) == 0 || signbit(z) != 0) + atf_tc_fail_nonfatal("pow(-Inf, 4.0) != +Inf"); + + /* + * If y is odd, y < 0, and x is -Inf, -0.0 is returned. + * If y is even, y < 0, and x is -Inf, +0.0 is returned. + */ + z = pow(x, -3.0); + + if (fabs(z) > 0.0 || signbit(z) == 0) + atf_tc_fail_nonfatal("pow(-Inf, -3.0) != -0.0"); + + z = pow(x, -4.0); + + if (fabs(z) > 0.0 || signbit(z) != 0) + atf_tc_fail_nonfatal("pow(-Inf -4.0) != +0.0"); +} + +ATF_TC(pow_inf_neg_y); +ATF_TC_HEAD(pow_inf_neg_y, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test pow(x, -Inf) == +Inf || +0.0"); +} + +ATF_TC_BODY(pow_inf_neg_y, tc) +{ + const double y = -1.0L / 0.0L; + double z; + + /* + * If |x| < 1 and y is -Inf, +Inf is returned. + * If |x| > 1 and y is -Inf, +0.0 is returned. + */ + z = pow(0.1, y); + + if (isinf(z) == 0 || signbit(z) != 0) + atf_tc_fail_nonfatal("pow(0.1, -Inf) != +Inf"); + + z = pow(1.1, y); + + if (fabs(z) > 0.0 || signbit(z) != 0) + atf_tc_fail_nonfatal("pow(1.1, -Inf) != +0.0"); +} + +ATF_TC(pow_inf_pos_x); +ATF_TC_HEAD(pow_inf_pos_x, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test pow(+Inf, y) == +Inf || +0.0"); +} + +ATF_TC_BODY(pow_inf_pos_x, tc) +{ + const double x = 1.0L / 0.0L; + double z; + + /* + * For y < 0, if x is +Inf, +0.0 is returned. + * For y > 0, if x is +Inf, +Inf is returned. + */ + z = pow(x, -2.0); + + if (fabs(z) > 0.0 || signbit(z) != 0) + atf_tc_fail_nonfatal("pow(+Inf, -2.0) != +0.0"); + + z = pow(x, 2.0); + + if (isinf(z) == 0 || signbit(z) != 0) + atf_tc_fail_nonfatal("pow(+Inf, 2.0) != +Inf"); +} + +ATF_TC(pow_inf_pos_y); +ATF_TC_HEAD(pow_inf_pos_y, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test pow(x, +Inf) == +Inf || +0.0"); +} + +ATF_TC_BODY(pow_inf_pos_y, tc) +{ + const double y = 1.0L / 0.0L; + double z; + + /* + * If |x| < 1 and y is +Inf, +0.0 is returned. + * If |x| > 1 and y is +Inf, +Inf is returned. + */ + z = pow(0.1, y); + + if (fabs(z) > 0.0 || signbit(z) != 0) + atf_tc_fail_nonfatal("pow(0.1, +Inf) != +0.0"); + + z = pow(1.1, y); + + if (isinf(z) == 0 || signbit(z) != 0) + atf_tc_fail_nonfatal("pow(1.1, +Inf) != +Inf"); +} + +ATF_TC(pow_one_neg_x); +ATF_TC_HEAD(pow_one_neg_x, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test pow(-1.0, +-Inf) == 1.0"); +} + +ATF_TC_BODY(pow_one_neg_x, tc) +{ + const double infp = 1.0L / 0.0L; + const double infn = -1.0L / 0.0L; + + /* + * If x is -1.0, and y is +-Inf, 1.0 shall be returned. + */ + ATF_REQUIRE(isinf(infp) != 0); + ATF_REQUIRE(isinf(infn) != 0); + + if (pow(-1.0, infp) != 1.0) { + atf_tc_expect_fail("PR lib/45372"); + atf_tc_fail_nonfatal("pow(-1.0, +Inf) != 1.0"); + } + + if (pow(-1.0, infn) != 1.0) { + atf_tc_expect_fail("PR lib/45372"); + atf_tc_fail_nonfatal("pow(-1.0, -Inf) != 1.0"); + } +} + +ATF_TC(pow_one_pos_x); +ATF_TC_HEAD(pow_one_pos_x, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test pow(1.0, y) == 1.0"); +} + +ATF_TC_BODY(pow_one_pos_x, tc) +{ + const double y[] = { 0.0, 0.1, 2.0, -3.0, 99.0, 99.99, 9999999.9 }; + const double z = 0.0L / 0.0L; + size_t i; + + /* + * For any value of y (including NaN), + * if x is 1.0, 1.0 shall be returned. + */ + if (pow(1.0, z) != 1.0) + atf_tc_fail_nonfatal("pow(1.0, NaN) != 1.0"); + + for (i = 0; i < __arraycount(y); i++) { + + if (pow(1.0, y[i]) != 1.0) + atf_tc_fail_nonfatal("pow(1.0, %0.01f) != 1.0", y[i]); + } +} + +ATF_TC(pow_zero_x); +ATF_TC_HEAD(pow_zero_x, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test pow(+-0.0, y) == +-0.0 || HUGE"); +} + +ATF_TC_BODY(pow_zero_x, tc) +{ + double z; + + /* + * If x is +0.0 or -0.0, y > 0, and y + * is an odd integer, x is returned. + */ + z = pow(+0.0, 3.0); + + if (fabs(z) > 0.0 || signbit(z) != 0) + atf_tc_fail_nonfatal("pow(+0.0, 3.0) != +0.0"); + + z = pow(-0.0, 3.0); + + if (fabs(z) > 0.0 || signbit(z) == 0) + atf_tc_fail_nonfatal("pow(-0.0, 3.0) != -0.0"); + + /* + * If y > 0 and not an odd integer, + * if x is +0.0 or -0.0, +0.0 is returned. + */ + z = pow(+0.0, 4.0); + + if (fabs(z) > 0.0 || signbit(z) != 0) + atf_tc_fail_nonfatal("pow(+0.0, 4.0) != +0.0"); + + z = pow(-0.0, 4.0); + + if (fabs(z) > 0.0 || signbit(z) != 0) + atf_tc_fail_nonfatal("pow(-0.0, 4.0) != +0.0"); + + /* + * If y < 0 and x is +0.0 or -0.0, either +-HUGE_VAL, + * +-HUGE_VALF, or +-HUGE_VALL shall be returned. + */ + z = pow(+0.0, -4.0); + + if (z != HUGE_VAL) { + atf_tc_expect_fail("PR port-amd64/45391"); + atf_tc_fail_nonfatal("pow(+0.0, -4.0) != HUGE_VAL"); + } + + z = pow(-0.0, -4.0); + + if (z != HUGE_VAL) { + atf_tc_expect_fail("PR port-amd64/45391"); + atf_tc_fail_nonfatal("pow(-0.0, -4.0) != HUGE_VAL"); + } + + z = pow(+0.0, -5.0); + + if (z != HUGE_VAL) { + atf_tc_expect_fail("PR port-amd64/45391"); + atf_tc_fail_nonfatal("pow(+0.0, -5.0) != HUGE_VAL"); + } + + z = pow(-0.0, -5.0); + + if (z != -HUGE_VAL) + atf_tc_fail_nonfatal("pow(-0.0, -5.0) != -HUGE_VAL"); +} + +ATF_TC(pow_zero_y); +ATF_TC_HEAD(pow_zero_y, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test pow(x, +-0.0) == 1.0"); +} + +ATF_TC_BODY(pow_zero_y, tc) +{ + const double x[] = { 0.1, -3.0, 77.0, 99.99, 101.0000001 }; + const double z = 0.0L / 0.0L; + size_t i; + + /* + * For any value of x (including NaN), + * if y is +0.0 or -0.0, 1.0 is returned. + */ + if (pow(z, +0.0) != 1.0) + atf_tc_fail_nonfatal("pow(NaN, +0.0) != 1.0"); + + if (pow(z, -0.0) != 1.0) + atf_tc_fail_nonfatal("pow(NaN, -0.0) != 1.0"); + + for (i = 0; i < __arraycount(x); i++) { + + if (pow(x[i], +0.0) != 1.0) + atf_tc_fail_nonfatal("pow(%0.01f, +0.0) != 1.0", x[i]); + + if (pow(x[i], -0.0) != 1.0) + atf_tc_fail_nonfatal("pow(%0.01f, -0.0) != 1.0", x[i]); + } +} + +/* + * powf(3) + */ +ATF_TC(powf_nan_x); +ATF_TC_HEAD(powf_nan_x, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test powf(NaN, y) == NaN"); +} + +ATF_TC_BODY(powf_nan_x, tc) +{ + const float x = 0.0L / 0.0L; + + ATF_CHECK(isnanf(powf(x, 2.0)) != 0); +} + +ATF_TC(powf_nan_y); +ATF_TC_HEAD(powf_nan_y, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test powf(x, NaN) == NaN"); +} + +ATF_TC_BODY(powf_nan_y, tc) +{ + const float y = 0.0L / 0.0L; + + ATF_CHECK(isnanf(powf(2.0, y)) != 0); +} + +ATF_TC(powf_inf_neg_x); +ATF_TC_HEAD(powf_inf_neg_x, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test powf(-Inf, y) == +-Inf || +-0.0"); +} + +ATF_TC_BODY(powf_inf_neg_x, tc) +{ + const float x = -1.0L / 0.0L; + float z; + + /* + * If y is odd, y > 0, and x is -Inf, -Inf is returned. + * If y is even, y > 0, and x is -Inf, +Inf is returned. + */ + z = powf(x, 3.0); + + if (isinff(z) == 0 || signbit(z) == 0) + atf_tc_fail_nonfatal("powf(-Inf, 3.0) != -Inf"); + + z = powf(x, 4.0); + + if (isinff(z) == 0 || signbit(z) != 0) + atf_tc_fail_nonfatal("powf(-Inf, 4.0) != +Inf"); + + /* + * If y is odd, y < 0, and x is -Inf, -0.0 is returned. + * If y is even, y < 0, and x is -Inf, +0.0 is returned. + */ + z = powf(x, -3.0); + + if (fabsf(z) > 0.0 || signbit(z) == 0) { + atf_tc_expect_fail("PR lib/45372"); + atf_tc_fail_nonfatal("powf(-Inf, -3.0) != -0.0"); + } + + z = powf(x, -4.0); + + if (fabsf(z) > 0.0 || signbit(z) != 0) + atf_tc_fail_nonfatal("powf(-Inf -4.0) != +0.0"); +} + +ATF_TC(powf_inf_neg_y); +ATF_TC_HEAD(powf_inf_neg_y, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test powf(x, -Inf) == +Inf || +0.0"); +} + +ATF_TC_BODY(powf_inf_neg_y, tc) +{ + const float y = -1.0L / 0.0L; + float z; + + /* + * If |x| < 1 and y is -Inf, +Inf is returned. + * If |x| > 1 and y is -Inf, +0.0 is returned. + */ + z = powf(0.1, y); + + if (isinff(z) == 0 || signbit(z) != 0) + atf_tc_fail_nonfatal("powf(0.1, -Inf) != +Inf"); + + z = powf(1.1, y); + + if (fabsf(z) > 0.0 || signbit(z) != 0) + atf_tc_fail_nonfatal("powf(1.1, -Inf) != +0.0"); +} + +ATF_TC(powf_inf_pos_x); +ATF_TC_HEAD(powf_inf_pos_x, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test powf(+Inf, y) == +Inf || +0.0"); +} + +ATF_TC_BODY(powf_inf_pos_x, tc) +{ + const float x = 1.0L / 0.0L; + float z; + + /* + * For y < 0, if x is +Inf, +0.0 is returned. + * For y > 0, if x is +Inf, +Inf is returned. + */ + z = powf(x, -2.0); + + if (fabsf(z) > 0.0 || signbit(z) != 0) + atf_tc_fail_nonfatal("powf(+Inf, -2.0) != +0.0"); + + z = powf(x, 2.0); + + if (isinff(z) == 0 || signbit(z) != 0) + atf_tc_fail_nonfatal("powf(+Inf, 2.0) != +Inf"); +} + +ATF_TC(powf_inf_pos_y); +ATF_TC_HEAD(powf_inf_pos_y, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test powf(x, +Inf) == +Inf || +0.0"); +} + +ATF_TC_BODY(powf_inf_pos_y, tc) +{ + const float y = 1.0L / 0.0L; + float z; + + /* + * If |x| < 1 and y is +Inf, +0.0 is returned. + * If |x| > 1 and y is +Inf, +Inf is returned. + */ + z = powf(0.1, y); + + if (fabsf(z) > 0.0 || signbit(z) != 0) + atf_tc_fail_nonfatal("powf(0.1, +Inf) != +0.0"); + + z = powf(1.1, y); + + if (isinff(z) == 0 || signbit(z) != 0) + atf_tc_fail_nonfatal("powf(1.1, +Inf) != +Inf"); +} + +ATF_TC(powf_one_neg_x); +ATF_TC_HEAD(powf_one_neg_x, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test powf(-1.0, +-Inf) == 1.0"); +} + +ATF_TC_BODY(powf_one_neg_x, tc) +{ + const float infp = 1.0L / 0.0L; + const float infn = -1.0L / 0.0L; + + /* + * If x is -1.0, and y is +-Inf, 1.0 shall be returned. + */ + ATF_REQUIRE(isinff(infp) != 0); + ATF_REQUIRE(isinff(infn) != 0); + + if (powf(-1.0, infp) != 1.0) { + atf_tc_expect_fail("PR lib/45372"); + atf_tc_fail_nonfatal("powf(-1.0, +Inf) != 1.0"); + } + + if (powf(-1.0, infn) != 1.0) { + atf_tc_expect_fail("PR lib/45372"); + atf_tc_fail_nonfatal("powf(-1.0, -Inf) != 1.0"); + } +} + +ATF_TC(powf_one_pos_x); +ATF_TC_HEAD(powf_one_pos_x, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test powf(1.0, y) == 1.0"); +} + +ATF_TC_BODY(powf_one_pos_x, tc) +{ + const float y[] = { 0.0, 0.1, 2.0, -3.0, 99.0, 99.99, 9999999.9 }; + const float z = 0.0L / 0.0L; + size_t i; + + /* + * For any value of y (including NaN), + * if x is 1.0, 1.0 shall be returned. + */ + if (powf(1.0, z) != 1.0) + atf_tc_fail_nonfatal("powf(1.0, NaN) != 1.0"); + + for (i = 0; i < __arraycount(y); i++) { + + if (powf(1.0, y[i]) != 1.0) + atf_tc_fail_nonfatal("powf(1.0, %0.01f) != 1.0", y[i]); + } +} + +ATF_TC(powf_zero_x); +ATF_TC_HEAD(powf_zero_x, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test powf(+-0.0, y) == +-0.0 || HUGE"); +} + +ATF_TC_BODY(powf_zero_x, tc) +{ + float z; + + /* + * If x is +0.0 or -0.0, y > 0, and y + * is an odd integer, x is returned. + */ + z = powf(+0.0, 3.0); + + if (fabsf(z) > 0.0 || signbit(z) != 0) + atf_tc_fail_nonfatal("powf(+0.0, 3.0) != +0.0"); + + z = powf(-0.0, 3.0); + + if (fabsf(z) > 0.0 || signbit(z) == 0) + atf_tc_fail_nonfatal("powf(-0.0, 3.0) != -0.0"); + + /* + * If y > 0 and not an odd integer, + * if x is +0.0 or -0.0, +0.0 is returned. + */ + z = powf(+0.0, 4.0); + + if (fabsf(z) > 0.0 || signbit(z) != 0) + atf_tc_fail_nonfatal("powf(+0.0, 4.0) != +0.0"); + + z = powf(-0.0, 4.0); + + if (fabsf(z) > 0.0 || signbit(z) != 0) + atf_tc_fail_nonfatal("powf(-0.0, 4.0) != +0.0"); + + /* + * If y < 0 and x is +0.0 or -0.0, either +-HUGE_VAL, + * +-HUGE_VALF, or +-HUGE_VALL shall be returned. + */ + z = powf(+0.0, -4.0); + + if (z != HUGE_VALF) { + atf_tc_expect_fail("PR port-amd64/45391"); + atf_tc_fail_nonfatal("powf(+0.0, -4.0) != HUGE_VALF"); + } + + z = powf(-0.0, -4.0); + + if (z != HUGE_VALF) { + atf_tc_expect_fail("PR port-amd64/45391"); + atf_tc_fail_nonfatal("powf(-0.0, -4.0) != HUGE_VALF"); + } + + z = powf(+0.0, -5.0); + + if (z != HUGE_VALF) { + atf_tc_expect_fail("PR port-amd64/45391"); + atf_tc_fail_nonfatal("powf(+0.0, -5.0) != HUGE_VALF"); + } + + z = powf(-0.0, -5.0); + + if (z != -HUGE_VALF) + atf_tc_fail_nonfatal("powf(-0.0, -5.0) != -HUGE_VALF"); +} + +ATF_TC(powf_zero_y); +ATF_TC_HEAD(powf_zero_y, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test powf(x, +-0.0) == 1.0"); +} + +ATF_TC_BODY(powf_zero_y, tc) +{ + const float x[] = { 0.1, -3.0, 77.0, 99.99, 101.0000001 }; + const float z = 0.0L / 0.0L; + size_t i; + + /* + * For any value of x (including NaN), + * if y is +0.0 or -0.0, 1.0 is returned. + */ + if (powf(z, +0.0) != 1.0) + atf_tc_fail_nonfatal("powf(NaN, +0.0) != 1.0"); + + if (powf(z, -0.0) != 1.0) + atf_tc_fail_nonfatal("powf(NaN, -0.0) != 1.0"); + + for (i = 0; i < __arraycount(x); i++) { + + if (powf(x[i], +0.0) != 1.0) + atf_tc_fail_nonfatal("powf(%0.01f, +0.0) != 1.0",x[i]); + + if (powf(x[i], -0.0) != 1.0) + atf_tc_fail_nonfatal("powf(%0.01f, -0.0) != 1.0",x[i]); + } +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, pow_nan_x); + ATF_TP_ADD_TC(tp, pow_nan_y); + ATF_TP_ADD_TC(tp, pow_inf_neg_x); + ATF_TP_ADD_TC(tp, pow_inf_neg_y); + ATF_TP_ADD_TC(tp, pow_inf_pos_x); + ATF_TP_ADD_TC(tp, pow_inf_pos_y); + ATF_TP_ADD_TC(tp, pow_one_neg_x); + ATF_TP_ADD_TC(tp, pow_one_pos_x); + ATF_TP_ADD_TC(tp, pow_zero_x); + ATF_TP_ADD_TC(tp, pow_zero_y); + + ATF_TP_ADD_TC(tp, powf_nan_x); + ATF_TP_ADD_TC(tp, powf_nan_y); + ATF_TP_ADD_TC(tp, powf_inf_neg_x); + ATF_TP_ADD_TC(tp, powf_inf_neg_y); + ATF_TP_ADD_TC(tp, powf_inf_pos_x); + ATF_TP_ADD_TC(tp, powf_inf_pos_y); + ATF_TP_ADD_TC(tp, powf_one_neg_x); + ATF_TP_ADD_TC(tp, powf_one_pos_x); + ATF_TP_ADD_TC(tp, powf_zero_x); + ATF_TP_ADD_TC(tp, powf_zero_y); + + return atf_no_error(); +} diff --git a/lib/libm/t_precision.c b/lib/libm/t_precision.c new file mode 100644 index 000000000000..390be9dd18aa --- /dev/null +++ b/lib/libm/t_precision.c @@ -0,0 +1,76 @@ +/* $NetBSD: t_precision.c,v 1.1 2013/11/11 11:10:45 joerg Exp $ */ + +/*- + * Copyright (c) 2013 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Joerg Sonnenberger. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__RCSID("$NetBSD: t_precision.c,v 1.1 2013/11/11 11:10:45 joerg Exp $"); + +#include <atf-c.h> +#include <atf-c/config.h> + +#include <float.h> +#include <stdlib.h> + +ATF_TC(t_precision); + +ATF_TC_HEAD(t_precision, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Basic precision test for double and long double"); +} + +volatile double x = 1; +volatile long double y = 1; + +ATF_TC_BODY(t_precision, tc) +{ + x += DBL_EPSILON; + ATF_CHECK(x != 1.0); + x -= 1; + ATF_CHECK(x == DBL_EPSILON); + + x = 2; + x += DBL_EPSILON; + ATF_CHECK(x == 2.0); + + y += LDBL_EPSILON; + ATF_CHECK(y != 1.0L); + y -= 1; + ATF_CHECK(y == LDBL_EPSILON); + y = 2; + y += LDBL_EPSILON; + ATF_CHECK(y == 2.0L); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, t_precision); + + return atf_no_error(); +} diff --git a/lib/libm/t_round.c b/lib/libm/t_round.c new file mode 100644 index 000000000000..f47e1a0f8a13 --- /dev/null +++ b/lib/libm/t_round.c @@ -0,0 +1,85 @@ +/* $NetBSD: t_round.c,v 1.4 2013/11/11 23:57:34 joerg Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <atf-c.h> +#include <float.h> +#include <math.h> + +/* + * This tests for a bug in the initial implementation where + * precision was lost in an internal substraction, leading to + * rounding into the wrong direction. + */ + +/* 0.5 - EPSILON */ +#define VAL 0x0.7ffffffffffffcp0 +#define VALF 0x0.7fffff8p0 +#define VALL (0.5 - LDBL_EPSILON) + +#ifdef __vax__ +#define SMALL_NUM 1.0e-38 +#else +#define SMALL_NUM 1.0e-40 +#endif + +ATF_TC(round_dir); +ATF_TC_HEAD(round_dir, tc) +{ + atf_tc_set_md_var(tc, "descr","Check for rounding in wrong direction"); +} + +ATF_TC_BODY(round_dir, tc) +{ + double a = VAL, b, c; + float af = VALF, bf, cf; + long double al = VALL, bl, cl; + + b = round(a); + bf = roundf(af); + bl = roundl(al); + + ATF_CHECK(fabs(b) < SMALL_NUM); + ATF_CHECK(fabsf(bf) < SMALL_NUM); + ATF_CHECK(fabsl(bl) < SMALL_NUM); + + c = round(-a); + cf = roundf(-af); + cl = roundl(-al); + + ATF_CHECK(fabs(c) < SMALL_NUM); + ATF_CHECK(fabsf(cf) < SMALL_NUM); + ATF_CHECK(fabsl(cl) < SMALL_NUM); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, round_dir); + + return atf_no_error(); +} diff --git a/lib/libm/t_scalbn.c b/lib/libm/t_scalbn.c new file mode 100644 index 000000000000..586c2c3bc621 --- /dev/null +++ b/lib/libm/t_scalbn.c @@ -0,0 +1,523 @@ +/* $NetBSD: t_scalbn.c,v 1.11 2014/03/03 10:39:08 martin Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__RCSID("$NetBSD: t_scalbn.c,v 1.11 2014/03/03 10:39:08 martin Exp $"); + +#include <math.h> +#include <limits.h> +#include <float.h> +#include <errno.h> + +#include <atf-c.h> + +static const int exps[] = { 0, 1, -1, 100, -100 }; + +/* tests here do not require specific precision, so we just use double */ +struct testcase { + int exp; + double inval; + double result; + int error; +}; +struct testcase test_vals[] = { + { 0, 1.00085, 1.00085, 0 }, + { 0, 0.99755, 0.99755, 0 }, + { 0, -1.00085, -1.00085, 0 }, + { 0, -0.99755, -0.99755, 0 }, + { 1, 1.00085, 2.0* 1.00085, 0 }, + { 1, 0.99755, 2.0* 0.99755, 0 }, + { 1, -1.00085, 2.0* -1.00085, 0 }, + { 1, -0.99755, 2.0* -0.99755, 0 }, + + /* + * We could add more corner test cases here, but we would have to + * add some ifdefs for the exact format and use a reliable + * generator program - bail for now and only do trivial stuff above. + */ +}; + +/* + * scalbn(3) + */ +ATF_TC(scalbn_val); +ATF_TC_HEAD(scalbn_val, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbn() for a few values"); +} + +ATF_TC_BODY(scalbn_val, tc) +{ + const struct testcase *tests = test_vals; + const size_t tcnt = __arraycount(test_vals); + size_t i; + double rv; + + for (i = 0; i < tcnt; i++) { + rv = scalbn(tests[i].inval, tests[i].exp); + ATF_CHECK_EQ_MSG(errno, tests[i].error, + "test %zu: errno %d instead of %d", i, errno, + tests[i].error); + ATF_CHECK_MSG(fabs(rv-tests[i].result)<2.0*DBL_EPSILON, + "test %zu: return value %g instead of %g (difference %g)", + i, rv, tests[i].result, tests[i].result-rv); + } +} + +ATF_TC(scalbn_nan); +ATF_TC_HEAD(scalbn_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbn(NaN, n) == NaN"); +} + +ATF_TC_BODY(scalbn_nan, tc) +{ + const double x = 0.0L / 0.0L; + double y; + size_t i; + + ATF_REQUIRE(isnan(x) != 0); + + for (i = 0; i < __arraycount(exps); i++) { + y = scalbn(x, exps[i]); + ATF_CHECK(isnan(y) != 0); + } +} + +ATF_TC(scalbn_inf_neg); +ATF_TC_HEAD(scalbn_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbn(-Inf, n) == -Inf"); +} + +ATF_TC_BODY(scalbn_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + size_t i; + + for (i = 0; i < __arraycount(exps); i++) + ATF_CHECK(scalbn(x, exps[i]) == x); +} + +ATF_TC(scalbn_inf_pos); +ATF_TC_HEAD(scalbn_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbn(+Inf, n) == +Inf"); +} + +ATF_TC_BODY(scalbn_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + size_t i; + + for (i = 0; i < __arraycount(exps); i++) + ATF_CHECK(scalbn(x, exps[i]) == x); +} + +ATF_TC(scalbn_ldexp); +ATF_TC_HEAD(scalbn_ldexp, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbn(x, n) == ldexp(x, n)"); +} + +ATF_TC_BODY(scalbn_ldexp, tc) +{ +#if FLT_RADIX == 2 + const double x = 2.91288191221812821; + double y; + size_t i; + + for (i = 0; i < __arraycount(exps); i++) { + y = scalbn(x, exps[i]); + ATF_CHECK_MSG(y == ldexp(x, exps[i]), "test %zu: exponent=%d, " + "y=%g, expected %g (diff: %g)", i, exps[i], y, + ldexp(x, exps[i]), y - ldexp(x, exps[i])); + } +#endif +} + +ATF_TC(scalbn_zero_neg); +ATF_TC_HEAD(scalbn_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbn(-0.0, n) == -0.0"); +} + +ATF_TC_BODY(scalbn_zero_neg, tc) +{ + const double x = -0.0L; + double y; + size_t i; + + ATF_REQUIRE(signbit(x) != 0); + + for (i = 0; i < __arraycount(exps); i++) { + y = scalbn(x, exps[i]); + ATF_CHECK(x == y); + ATF_CHECK(signbit(y) != 0); + } +} + +ATF_TC(scalbn_zero_pos); +ATF_TC_HEAD(scalbn_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbn(+0.0, n) == +0.0"); +} + +ATF_TC_BODY(scalbn_zero_pos, tc) +{ + const double x = 0.0L; + double y; + size_t i; + + ATF_REQUIRE(signbit(x) == 0); + + for (i = 0; i < __arraycount(exps); i++) { + y = scalbn(x, exps[i]); + ATF_CHECK(x == y); + ATF_CHECK(signbit(y) == 0); + } +} + +/* + * scalbnf(3) + */ +ATF_TC(scalbnf_val); +ATF_TC_HEAD(scalbnf_val, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbnf() for a few values"); +} + +ATF_TC_BODY(scalbnf_val, tc) +{ + const struct testcase *tests = test_vals; + const size_t tcnt = __arraycount(test_vals); + size_t i; + double rv; + + for (i = 0; i < tcnt; i++) { + rv = scalbnf(tests[i].inval, tests[i].exp); + ATF_CHECK_EQ_MSG(errno, tests[i].error, + "test %zu: errno %d instead of %d", i, errno, + tests[i].error); + ATF_CHECK_MSG(fabs(rv-tests[i].result)<2.0*FLT_EPSILON, + "test %zu: return value %g instead of %g (difference %g)", + i, rv, tests[i].result, tests[i].result-rv); + } +} + +ATF_TC(scalbnf_nan); +ATF_TC_HEAD(scalbnf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbnf(NaN, n) == NaN"); +} + +ATF_TC_BODY(scalbnf_nan, tc) +{ + const float x = 0.0L / 0.0L; + float y; + size_t i; + + ATF_REQUIRE(isnan(x) != 0); + + for (i = 0; i < __arraycount(exps); i++) { + y = scalbnf(x, exps[i]); + ATF_CHECK(isnan(y) != 0); + } +} + +ATF_TC(scalbnf_inf_neg); +ATF_TC_HEAD(scalbnf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbnf(-Inf, n) == -Inf"); +} + +ATF_TC_BODY(scalbnf_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + size_t i; + + for (i = 0; i < __arraycount(exps); i++) + ATF_CHECK(scalbnf(x, exps[i]) == x); +} + +ATF_TC(scalbnf_inf_pos); +ATF_TC_HEAD(scalbnf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbnf(+Inf, n) == +Inf"); +} + +ATF_TC_BODY(scalbnf_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + size_t i; + + for (i = 0; i < __arraycount(exps); i++) + ATF_CHECK(scalbnf(x, exps[i]) == x); +} + +ATF_TC(scalbnf_ldexpf); +ATF_TC_HEAD(scalbnf_ldexpf, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbnf(x, n) == ldexpf(x, n)"); +} + +ATF_TC_BODY(scalbnf_ldexpf, tc) +{ +#if FLT_RADIX == 2 + const float x = 2.91288191221812821; + float y; + size_t i; + + for (i = 0; i < __arraycount(exps); i++) { + y = scalbnf(x, exps[i]); + ATF_CHECK_MSG(y == ldexpf(x, exps[i]), + "test %zu: exponent=%d, y=%g ldexpf returns %g (diff: %g)", + i, exps[i], y, ldexpf(x, exps[i]), y-ldexpf(x, exps[i])); + } +#endif +} + +ATF_TC(scalbnf_zero_neg); +ATF_TC_HEAD(scalbnf_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbnf(-0.0, n) == -0.0"); +} + +ATF_TC_BODY(scalbnf_zero_neg, tc) +{ + const float x = -0.0L; + float y; + size_t i; + + ATF_REQUIRE(signbit(x) != 0); + + for (i = 0; i < __arraycount(exps); i++) { + y = scalbnf(x, exps[i]); + ATF_CHECK(x == y); + ATF_CHECK(signbit(y) != 0); + } +} + +ATF_TC(scalbnf_zero_pos); +ATF_TC_HEAD(scalbnf_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbnf(+0.0, n) == +0.0"); +} + +ATF_TC_BODY(scalbnf_zero_pos, tc) +{ + const float x = 0.0L; + float y; + size_t i; + + ATF_REQUIRE(signbit(x) == 0); + + for (i = 0; i < __arraycount(exps); i++) { + y = scalbnf(x, exps[i]); + ATF_CHECK(x == y); + ATF_CHECK(signbit(y) == 0); + } +} + +/* + * scalbnl(3) + */ +ATF_TC(scalbnl_val); +ATF_TC_HEAD(scalbnl_val, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbnl() for a few values"); +} + +ATF_TC_BODY(scalbnl_val, tc) +{ +#ifndef __HAVE_LONG_DOUBLE + atf_tc_skip("Requires long double support"); +#else + const struct testcase *tests = test_vals; + const size_t tcnt = __arraycount(test_vals); + size_t i; + long double rv; + + for (i = 0; i < tcnt; i++) { + rv = scalbnl(tests[i].inval, tests[i].exp); + ATF_CHECK_EQ_MSG(errno, tests[i].error, + "test %zu: errno %d instead of %d", i, errno, + tests[i].error); + ATF_CHECK_MSG(fabsl(rv-(long double)tests[i].result)<2.0*LDBL_EPSILON, + "test %zu: return value %Lg instead of %Lg (difference %Lg)", + i, rv, (long double)tests[i].result, (long double)tests[i].result-rv); + } +#endif +} + +ATF_TC(scalbnl_nan); +ATF_TC_HEAD(scalbnl_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbnl(NaN, n) == NaN"); +} + +ATF_TC_BODY(scalbnl_nan, tc) +{ +#ifndef __HAVE_LONG_DOUBLE + atf_tc_skip("Requires long double support"); +#else + const long double x = 0.0L / 0.0L; + long double y; + size_t i; + + if (isnan(x) == 0) { + atf_tc_expect_fail("PR lib/45362"); + atf_tc_fail("(0.0L / 0.0L) != NaN"); + } + + for (i = 0; i < __arraycount(exps); i++) { + y = scalbnl(x, exps[i]); + ATF_CHECK(isnan(y) != 0); + } +#endif +} + +ATF_TC(scalbnl_inf_neg); +ATF_TC_HEAD(scalbnl_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbnl(-Inf, n) == -Inf"); +} + +ATF_TC_BODY(scalbnl_inf_neg, tc) +{ +#ifndef __HAVE_LONG_DOUBLE + atf_tc_skip("Requires long double support"); +#else + const long double x = -1.0L / 0.0L; + size_t i; + + for (i = 0; i < __arraycount(exps); i++) + ATF_CHECK(scalbnl(x, exps[i]) == x); +#endif +} + +ATF_TC(scalbnl_inf_pos); +ATF_TC_HEAD(scalbnl_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbnl(+Inf, n) == +Inf"); +} + +ATF_TC_BODY(scalbnl_inf_pos, tc) +{ +#ifndef __HAVE_LONG_DOUBLE + atf_tc_skip("Requires long double support"); +#else + const long double x = 1.0L / 0.0L; + size_t i; + + for (i = 0; i < __arraycount(exps); i++) + ATF_CHECK(scalbnl(x, exps[i]) == x); +#endif +} + +ATF_TC(scalbnl_zero_neg); +ATF_TC_HEAD(scalbnl_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbnl(-0.0, n) == -0.0"); +} + +ATF_TC_BODY(scalbnl_zero_neg, tc) +{ +#ifndef __HAVE_LONG_DOUBLE + atf_tc_skip("Requires long double support"); +#else + const long double x = -0.0L; + long double y; + size_t i; + + ATF_REQUIRE(signbit(x) != 0); + + for (i = 0; i < __arraycount(exps); i++) { + y = scalbnl(x, exps[i]); + ATF_CHECK(x == y); + ATF_CHECK(signbit(y) != 0); + } +#endif +} + +ATF_TC(scalbnl_zero_pos); +ATF_TC_HEAD(scalbnl_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scalbnl(+0.0, n) == +0.0"); +} + +ATF_TC_BODY(scalbnl_zero_pos, tc) +{ +#ifndef __HAVE_LONG_DOUBLE + atf_tc_skip("Requires long double support"); +#else + const long double x = 0.0L; + long double y; + size_t i; + + ATF_REQUIRE(signbit(x) == 0); + + for (i = 0; i < __arraycount(exps); i++) { + y = scalbnl(x, exps[i]); + ATF_CHECK(x == y); + ATF_CHECK(signbit(y) == 0); + } +#endif +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, scalbn_val); + ATF_TP_ADD_TC(tp, scalbn_nan); + ATF_TP_ADD_TC(tp, scalbn_inf_neg); + ATF_TP_ADD_TC(tp, scalbn_inf_pos); + ATF_TP_ADD_TC(tp, scalbn_ldexp); + ATF_TP_ADD_TC(tp, scalbn_zero_neg); + ATF_TP_ADD_TC(tp, scalbn_zero_pos); + + ATF_TP_ADD_TC(tp, scalbnf_val); + ATF_TP_ADD_TC(tp, scalbnf_nan); + ATF_TP_ADD_TC(tp, scalbnf_inf_neg); + ATF_TP_ADD_TC(tp, scalbnf_inf_pos); + ATF_TP_ADD_TC(tp, scalbnf_ldexpf); + ATF_TP_ADD_TC(tp, scalbnf_zero_neg); + ATF_TP_ADD_TC(tp, scalbnf_zero_pos); + + ATF_TP_ADD_TC(tp, scalbnl_val); + ATF_TP_ADD_TC(tp, scalbnl_nan); + ATF_TP_ADD_TC(tp, scalbnl_inf_neg); + ATF_TP_ADD_TC(tp, scalbnl_inf_pos); +/* ATF_TP_ADD_TC(tp, scalbnl_ldexp); */ + ATF_TP_ADD_TC(tp, scalbnl_zero_neg); + ATF_TP_ADD_TC(tp, scalbnl_zero_pos); + + return atf_no_error(); +} diff --git a/lib/libm/t_sin.c b/lib/libm/t_sin.c new file mode 100644 index 000000000000..a82f49dc65d6 --- /dev/null +++ b/lib/libm/t_sin.c @@ -0,0 +1,263 @@ +/* $NetBSD: t_sin.c,v 1.4 2014/03/03 10:39:08 martin Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <atf-c.h> +#include <math.h> + +static const struct { + int angle; + double x; + double y; +} angles[] = { + { -180, -3.141592653589793, 0.0000000000000000 }, + { -135, -2.356194490192345, -0.7071067811865476 }, + { -90, -1.570796326794897, -1.0000000000000000 }, + { -45, -0.785398163397448, -0.7071067811865476 }, + { 0, 0.000000000000000, 0.0000000000000000 }, + { 30, 0.523598775598299, 0.5000000000000000 }, + { 45, 0.785398163397448, 0.7071067811865476 }, + { 60, 1.047197551196598, 0.8660254037844386 }, + { 90, 1.570796326794897, 1.0000000000000000 }, + { 120, 2.094395102393195, 0.8660254037844386 }, + { 135, 2.356194490192345, 0.7071067811865476 }, + { 150, 2.617993877991494, 0.5000000000000000 }, + { 180, 3.141592653589793, 0.0000000000000000 }, + { 270, 4.712388980384690, -1.0000000000000000 }, + { 360, 6.283185307179586, 0.0000000000000000 } +}; + +/* + * sin(3) + */ +ATF_TC(sin_angles); +ATF_TC_HEAD(sin_angles, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test some selected angles"); +} + +ATF_TC_BODY(sin_angles, tc) +{ + const double eps = 1.0e-15; + size_t i; + + for (i = 0; i < __arraycount(angles); i++) { + + if (fabs(sin(angles[i].x) - angles[i].y) > eps) + atf_tc_fail_nonfatal("sin(%d deg) != %0.01f", + angles[i].angle, angles[i].y); + } +} + +ATF_TC(sin_nan); +ATF_TC_HEAD(sin_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sin(NaN) == NaN"); +} + +ATF_TC_BODY(sin_nan, tc) +{ + const double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(sin(x)) != 0); +} + +ATF_TC(sin_inf_neg); +ATF_TC_HEAD(sin_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sin(-Inf) == NaN"); +} + +ATF_TC_BODY(sin_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + + ATF_CHECK(isnan(sin(x)) != 0); +} + +ATF_TC(sin_inf_pos); +ATF_TC_HEAD(sin_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sin(+Inf) == NaN"); +} + +ATF_TC_BODY(sin_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + + ATF_CHECK(isnan(sin(x)) != 0); +} + + +ATF_TC(sin_zero_neg); +ATF_TC_HEAD(sin_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sin(-0.0) == -0.0"); +} + +ATF_TC_BODY(sin_zero_neg, tc) +{ + const double x = -0.0L; + + ATF_CHECK(sin(x) == x); +} + +ATF_TC(sin_zero_pos); +ATF_TC_HEAD(sin_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sin(+0.0) == +0.0"); +} + +ATF_TC_BODY(sin_zero_pos, tc) +{ + const double x = 0.0L; + + ATF_CHECK(sin(x) == x); +} + +/* + * sinf(3) + */ +ATF_TC(sinf_angles); +ATF_TC_HEAD(sinf_angles, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test some selected angles"); +} + +ATF_TC_BODY(sinf_angles, tc) +{ + const float eps = 1.0e-6; + float x, y; + size_t i; + + for (i = 0; i < __arraycount(angles); i++) { + + x = angles[i].x; + y = angles[i].y; + + if (fabsf(sinf(x) - y) > eps) + atf_tc_fail_nonfatal("sinf(%d deg) != %0.01f", + angles[i].angle, angles[i].y); + } +} + +ATF_TC(sinf_nan); +ATF_TC_HEAD(sinf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sinf(NaN) == NaN"); +} + +ATF_TC_BODY(sinf_nan, tc) +{ + const float x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(sinf(x)) != 0); +} + +ATF_TC(sinf_inf_neg); +ATF_TC_HEAD(sinf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sinf(-Inf) == NaN"); +} + +ATF_TC_BODY(sinf_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + + if (isnan(sinf(x)) == 0) { + atf_tc_expect_fail("PR lib/45362"); + atf_tc_fail("sinf(-Inf) != NaN"); + } +} + +ATF_TC(sinf_inf_pos); +ATF_TC_HEAD(sinf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sinf(+Inf) == NaN"); +} + +ATF_TC_BODY(sinf_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + + if (isnan(sinf(x)) == 0) { + atf_tc_expect_fail("PR lib/45362"); + atf_tc_fail("sinf(+Inf) != NaN"); + } +} + + +ATF_TC(sinf_zero_neg); +ATF_TC_HEAD(sinf_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sinf(-0.0) == -0.0"); +} + +ATF_TC_BODY(sinf_zero_neg, tc) +{ + const float x = -0.0L; + + ATF_CHECK(sinf(x) == x); +} + +ATF_TC(sinf_zero_pos); +ATF_TC_HEAD(sinf_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sinf(+0.0) == +0.0"); +} + +ATF_TC_BODY(sinf_zero_pos, tc) +{ + const float x = 0.0L; + + ATF_CHECK(sinf(x) == x); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, sin_angles); + ATF_TP_ADD_TC(tp, sin_nan); + ATF_TP_ADD_TC(tp, sin_inf_neg); + ATF_TP_ADD_TC(tp, sin_inf_pos); + ATF_TP_ADD_TC(tp, sin_zero_neg); + ATF_TP_ADD_TC(tp, sin_zero_pos); + + ATF_TP_ADD_TC(tp, sinf_angles); + ATF_TP_ADD_TC(tp, sinf_nan); + ATF_TP_ADD_TC(tp, sinf_inf_neg); + ATF_TP_ADD_TC(tp, sinf_inf_pos); + ATF_TP_ADD_TC(tp, sinf_zero_neg); + ATF_TP_ADD_TC(tp, sinf_zero_pos); + + return atf_no_error(); +} diff --git a/lib/libm/t_sinh.c b/lib/libm/t_sinh.c new file mode 100644 index 000000000000..d935f0ea7ffb --- /dev/null +++ b/lib/libm/t_sinh.c @@ -0,0 +1,273 @@ +/* $NetBSD: t_sinh.c,v 1.6 2014/03/03 10:39:08 martin Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__RCSID("$NetBSD: t_sinh.c,v 1.6 2014/03/03 10:39:08 martin Exp $"); + +#include <atf-c.h> +#include <math.h> +#include <stdio.h> + +static const struct { + double x; + double y; + double e; +} values[] = { + { -10, -11013.23287470339, 1e4, }, + { -2, -3.626860407847019, 1, }, + { -1, -1.175201193643801, 1, }, + { -0.05, -0.050020835937655, 1, }, + { -0.001,-0.001000000166667, 1, }, + { 0.001, 0.001000000166667, 1, }, + { 0.05, 0.050020835937655, 1, }, + { 1, 1.175201193643801, 1, }, + { 2, 3.626860407847019, 1, }, + { 10, 11013.23287470339, 1e4, }, +}; + +/* + * sinh(3) + */ +ATF_TC(sinh_inrange); +ATF_TC_HEAD(sinh_inrange, tc) +{ + atf_tc_set_md_var(tc, "descr", "sinh(x) for some values"); +} + +ATF_TC_BODY(sinh_inrange, tc) +{ + double eps; + double x; + double y; + size_t i; + + for (i = 0; i < __arraycount(values); i++) { + x = values[i].x; + y = values[i].y; + eps = 1e-15 * values[i].e; + + if (fabs(sinh(x) - y) > eps) + atf_tc_fail_nonfatal("sinh(%g) != %g\n", x, y); + } +} + +ATF_TC(sinh_nan); +ATF_TC_HEAD(sinh_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sinh(NaN) == NaN"); +} + +ATF_TC_BODY(sinh_nan, tc) +{ + const double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(sinh(x)) != 0); +} + +ATF_TC(sinh_inf_neg); +ATF_TC_HEAD(sinh_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sinh(-Inf) == -Inf"); +} + +ATF_TC_BODY(sinh_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + double y = sinh(x); + + ATF_CHECK(isinf(y) != 0); + ATF_CHECK(signbit(y) != 0); +} + +ATF_TC(sinh_inf_pos); +ATF_TC_HEAD(sinh_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sinh(+Inf) == +Inf"); +} + +ATF_TC_BODY(sinh_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + double y = sinh(x); + + ATF_CHECK(isinf(y) != 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TC(sinh_zero_neg); +ATF_TC_HEAD(sinh_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sinh(-0.0) == -0.0"); +} + +ATF_TC_BODY(sinh_zero_neg, tc) +{ + const double x = -0.0L; + double y = sinh(x); + + if (fabs(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("sinh(-0.0) != -0.0"); +} + +ATF_TC(sinh_zero_pos); +ATF_TC_HEAD(sinh_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sinh(+0.0) == +0.0"); +} + +ATF_TC_BODY(sinh_zero_pos, tc) +{ + const double x = 0.0L; + double y = sinh(x); + + if (fabs(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("sinh(+0.0) != +0.0"); +} + +/* + * sinhf(3) + */ +ATF_TC(sinhf_inrange); +ATF_TC_HEAD(sinhf_inrange, tc) +{ + atf_tc_set_md_var(tc, "descr", "sinhf(x) for some values"); +} + +ATF_TC_BODY(sinhf_inrange, tc) +{ + float eps; + float x; + float y; + size_t i; + + for (i = 0; i < __arraycount(values); i++) { + x = values[i].x; + y = values[i].y; + eps = 1e-6 * values[i].e; + + if (fabsf(sinhf(x) - y) > eps) + atf_tc_fail_nonfatal("sinhf(%g) != %g\n", x, y); + } +} + +ATF_TC(sinhf_nan); +ATF_TC_HEAD(sinhf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sinhf(NaN) == NaN"); +} + +ATF_TC_BODY(sinhf_nan, tc) +{ + const float x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(sinhf(x)) != 0); +} + +ATF_TC(sinhf_inf_neg); +ATF_TC_HEAD(sinhf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sinhf(-Inf) == -Inf"); +} + +ATF_TC_BODY(sinhf_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + float y = sinhf(x); + + ATF_CHECK(isinf(y) != 0); + ATF_CHECK(signbit(y) != 0); +} + +ATF_TC(sinhf_inf_pos); +ATF_TC_HEAD(sinhf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sinhf(+Inf) == +Inf"); +} + +ATF_TC_BODY(sinhf_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + float y = sinhf(x); + + ATF_CHECK(isinf(y) != 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TC(sinhf_zero_neg); +ATF_TC_HEAD(sinhf_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sinhf(-0.0) == -0.0"); +} + +ATF_TC_BODY(sinhf_zero_neg, tc) +{ + const float x = -0.0L; + float y = sinhf(x); + + if (fabsf(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("sinhf(-0.0) != -0.0"); +} + +ATF_TC(sinhf_zero_pos); +ATF_TC_HEAD(sinhf_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sinhf(+0.0) == +0.0"); +} + +ATF_TC_BODY(sinhf_zero_pos, tc) +{ + const float x = 0.0L; + float y = sinhf(x); + + if (fabsf(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("sinhf(+0.0) != +0.0"); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, sinh_inrange); + ATF_TP_ADD_TC(tp, sinh_nan); + ATF_TP_ADD_TC(tp, sinh_inf_neg); + ATF_TP_ADD_TC(tp, sinh_inf_pos); + ATF_TP_ADD_TC(tp, sinh_zero_neg); + ATF_TP_ADD_TC(tp, sinh_zero_pos); + + ATF_TP_ADD_TC(tp, sinhf_inrange); + ATF_TP_ADD_TC(tp, sinhf_nan); + ATF_TP_ADD_TC(tp, sinhf_inf_neg); + ATF_TP_ADD_TC(tp, sinhf_inf_pos); + ATF_TP_ADD_TC(tp, sinhf_zero_neg); + ATF_TP_ADD_TC(tp, sinhf_zero_pos); + + return atf_no_error(); +} diff --git a/lib/libm/t_sqrt.c b/lib/libm/t_sqrt.c new file mode 100644 index 000000000000..1d551ec3101d --- /dev/null +++ b/lib/libm/t_sqrt.c @@ -0,0 +1,368 @@ +/* $NetBSD: t_sqrt.c,v 1.7 2014/03/12 21:40:07 martin Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__RCSID("$NetBSD: t_sqrt.c,v 1.7 2014/03/12 21:40:07 martin Exp $"); + +#include <atf-c.h> +#include <math.h> +#include <float.h> +#include <stdio.h> + +/* + * sqrt(3) + */ +ATF_TC(sqrt_nan); +ATF_TC_HEAD(sqrt_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sqrt(NaN) == NaN"); +} + +ATF_TC_BODY(sqrt_nan, tc) +{ + const double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(sqrt(x)) != 0); +} + +ATF_TC(sqrt_pow); +ATF_TC_HEAD(sqrt_pow, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sqrt(3) vs. pow(3)"); +} + +ATF_TC_BODY(sqrt_pow, tc) +{ + const double x[] = { 0.0, 0.005, 1.0, 99.0, 123.123, 9999.9999 }; +#if __DBL_MIN_10_EXP__ <= -40 + const double eps = 1.0e-40; +#else + const double eps = __DBL_MIN__*4.0; +#endif + double y, z; + size_t i; + + for (i = 0; i < __arraycount(x); i++) { + + y = sqrt(x[i]); + z = pow(x[i], 1.0 / 2.0); + + if (fabs(y - z) > eps) + atf_tc_fail_nonfatal("sqrt(%0.03f) != " + "pow(%0.03f, 1/2)\n", x[i], x[i]); + } +} + +ATF_TC(sqrt_inf_neg); +ATF_TC_HEAD(sqrt_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sqrt(-Inf) == NaN"); +} + +ATF_TC_BODY(sqrt_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + double y = sqrt(x); + + ATF_CHECK(isnan(y) != 0); +} + +ATF_TC(sqrt_inf_pos); +ATF_TC_HEAD(sqrt_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sqrt(+Inf) == +Inf"); +} + +ATF_TC_BODY(sqrt_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + double y = sqrt(x); + + ATF_CHECK(isinf(y) != 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TC(sqrt_zero_neg); +ATF_TC_HEAD(sqrt_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sqrt(-0.0) == -0.0"); +} + +ATF_TC_BODY(sqrt_zero_neg, tc) +{ + const double x = -0.0L; + double y = sqrt(x); + + if (fabs(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("sqrt(-0.0) != -0.0"); +} + +ATF_TC(sqrt_zero_pos); +ATF_TC_HEAD(sqrt_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sqrt(+0.0) == +0.0"); +} + +ATF_TC_BODY(sqrt_zero_pos, tc) +{ + const double x = 0.0L; + double y = sqrt(x); + + if (fabs(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("sqrt(+0.0) != +0.0"); +} + +/* + * sqrtf(3) + */ +ATF_TC(sqrtf_nan); +ATF_TC_HEAD(sqrtf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sqrtf(NaN) == NaN"); +} + +ATF_TC_BODY(sqrtf_nan, tc) +{ + const float x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(sqrtf(x)) != 0); +} + +ATF_TC(sqrtf_powf); +ATF_TC_HEAD(sqrtf_powf, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sqrtf(3) vs. powf(3)"); +} + +ATF_TC_BODY(sqrtf_powf, tc) +{ + const float x[] = { 0.0, 0.005, 1.0, 99.0, 123.123, 9999.9999 }; + const float eps = 1.0e-30; + volatile float y, z; + size_t i; + + for (i = 0; i < __arraycount(x); i++) { + + y = sqrtf(x[i]); + z = powf(x[i], 1.0 / 2.0); + + if (fabsf(y - z) > eps) + atf_tc_fail_nonfatal("sqrtf(%0.03f) != " + "powf(%0.03f, 1/2)\n", x[i], x[i]); + } +} + +ATF_TC(sqrtf_inf_neg); +ATF_TC_HEAD(sqrtf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sqrtf(-Inf) == NaN"); +} + +ATF_TC_BODY(sqrtf_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + float y = sqrtf(x); + + ATF_CHECK(isnan(y) != 0); +} + +ATF_TC(sqrtf_inf_pos); +ATF_TC_HEAD(sqrtf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sqrtf(+Inf) == +Inf"); +} + +ATF_TC_BODY(sqrtf_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + float y = sqrtf(x); + + ATF_CHECK(isinf(y) != 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TC(sqrtf_zero_neg); +ATF_TC_HEAD(sqrtf_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sqrtf(-0.0) == -0.0"); +} + +ATF_TC_BODY(sqrtf_zero_neg, tc) +{ + const float x = -0.0L; + float y = sqrtf(x); + + if (fabsf(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("sqrtf(-0.0) != -0.0"); +} + +ATF_TC(sqrtf_zero_pos); +ATF_TC_HEAD(sqrtf_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sqrtf(+0.0) == +0.0"); +} + +ATF_TC_BODY(sqrtf_zero_pos, tc) +{ + const float x = 0.0L; + float y = sqrtf(x); + + if (fabsf(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("sqrtf(+0.0) != +0.0"); +} + +/* + * sqrtl(3) + */ +ATF_TC(sqrtl_nan); +ATF_TC_HEAD(sqrtl_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sqrtl(NaN) == NaN"); +} + +ATF_TC_BODY(sqrtl_nan, tc) +{ + const long double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(sqrtl(x)) != 0); +} + +ATF_TC(sqrtl_powl); +ATF_TC_HEAD(sqrtl_powl, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sqrtl(3) vs. powl(3)"); +} + +ATF_TC_BODY(sqrtl_powl, tc) +{ + const long double x[] = { 0.0, 0.005, 1.0, 99.0, 123.123, 9999.9999 }; + const long double eps = 5.0*DBL_EPSILON; /* XXX powl == pow for now */ + volatile long double y, z; + size_t i; + + for (i = 0; i < __arraycount(x); i++) { + + y = sqrtl(x[i]); + z = powl(x[i], 1.0 / 2.0); + + if (fabsl(y - z) > eps) + atf_tc_fail_nonfatal("sqrtl(%0.03Lf) != " + "powl(%0.03Lf, 1/2)\n", x[i], x[i]); + } +} + +ATF_TC(sqrtl_inf_neg); +ATF_TC_HEAD(sqrtl_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sqrtl(-Inf) == NaN"); +} + +ATF_TC_BODY(sqrtl_inf_neg, tc) +{ + const long double x = -1.0L / 0.0L; + long double y = sqrtl(x); + + ATF_CHECK(isnan(y) != 0); +} + +ATF_TC(sqrtl_inf_pos); +ATF_TC_HEAD(sqrtl_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sqrtl(+Inf) == +Inf"); +} + +ATF_TC_BODY(sqrtl_inf_pos, tc) +{ + const long double x = 1.0L / 0.0L; + long double y = sqrtl(x); + + ATF_CHECK(isinf(y) != 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TC(sqrtl_zero_neg); +ATF_TC_HEAD(sqrtl_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sqrtl(-0.0) == -0.0"); +} + +ATF_TC_BODY(sqrtl_zero_neg, tc) +{ + const long double x = -0.0L; + long double y = sqrtl(x); + + if (fabsl(y) > 0.0 || signbit(y) == 0) + atf_tc_fail_nonfatal("sqrtl(-0.0) != -0.0"); +} + +ATF_TC(sqrtl_zero_pos); +ATF_TC_HEAD(sqrtl_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test sqrtl(+0.0) == +0.0"); +} + +ATF_TC_BODY(sqrtl_zero_pos, tc) +{ + const long double x = 0.0L; + long double y = sqrtl(x); + + if (fabsl(y) > 0.0 || signbit(y) != 0) + atf_tc_fail_nonfatal("sqrtl(+0.0) != +0.0"); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, sqrt_nan); + ATF_TP_ADD_TC(tp, sqrt_pow); + ATF_TP_ADD_TC(tp, sqrt_inf_neg); + ATF_TP_ADD_TC(tp, sqrt_inf_pos); + ATF_TP_ADD_TC(tp, sqrt_zero_neg); + ATF_TP_ADD_TC(tp, sqrt_zero_pos); + + ATF_TP_ADD_TC(tp, sqrtf_nan); + ATF_TP_ADD_TC(tp, sqrtf_powf); + ATF_TP_ADD_TC(tp, sqrtf_inf_neg); + ATF_TP_ADD_TC(tp, sqrtf_inf_pos); + ATF_TP_ADD_TC(tp, sqrtf_zero_neg); + ATF_TP_ADD_TC(tp, sqrtf_zero_pos); + + ATF_TP_ADD_TC(tp, sqrtl_nan); + ATF_TP_ADD_TC(tp, sqrtl_powl); + ATF_TP_ADD_TC(tp, sqrtl_inf_neg); + ATF_TP_ADD_TC(tp, sqrtl_inf_pos); + ATF_TP_ADD_TC(tp, sqrtl_zero_neg); + ATF_TP_ADD_TC(tp, sqrtl_zero_pos); + + return atf_no_error(); +} diff --git a/lib/libm/t_tan.c b/lib/libm/t_tan.c new file mode 100644 index 000000000000..807e3d1f3364 --- /dev/null +++ b/lib/libm/t_tan.c @@ -0,0 +1,260 @@ +/* $NetBSD: t_tan.c,v 1.5 2014/03/03 10:39:08 martin Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <atf-c.h> +#include <math.h> + +static const struct { + int angle; + double x; + double y; +} angles[] = { + { -180, -3.141592653589793, 0.0000000000000000 }, + { -135, -2.356194490192345, 1.0000000000000000 }, + { -45, -0.785398163397448, -1.0000000000000000 }, + { 0, 0.000000000000000, 0.0000000000000000 }, + { 30, 0.523598775598299, 0.5773502691896258 }, + { 45, 0.785398163397448, 1.0000000000000000 }, + { 60, 1.047197551196598, 1.7320508075688773 }, + { 120, 2.094395102393195, -1.7320508075688773 }, + { 135, 2.356194490192345, -1.0000000000000000 }, + { 150, 2.617993877991494, -0.5773502691896258 }, + { 180, 3.141592653589793, 0.0000000000000000 }, + { 360, 6.283185307179586, 0.0000000000000000 } +}; + +/* + * tan(3) + */ +ATF_TC(tan_angles); +ATF_TC_HEAD(tan_angles, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test some selected angles"); +} + +ATF_TC_BODY(tan_angles, tc) +{ + const double eps = 1.0e-14; + size_t i; + + for (i = 0; i < __arraycount(angles); i++) { + + if (fabs(tan(angles[i].x) - angles[i].y) > eps) + atf_tc_fail_nonfatal("tan(%d deg) != %0.01f", + angles[i].angle, angles[i].y); + } +} + +ATF_TC(tan_nan); +ATF_TC_HEAD(tan_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tan(NaN) == NaN"); +} + +ATF_TC_BODY(tan_nan, tc) +{ + const double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(tan(x)) != 0); +} + +ATF_TC(tan_inf_neg); +ATF_TC_HEAD(tan_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tan(-Inf) == NaN"); +} + +ATF_TC_BODY(tan_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + + ATF_CHECK(isnan(tan(x)) != 0); +} + +ATF_TC(tan_inf_pos); +ATF_TC_HEAD(tan_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tan(+Inf) == NaN"); +} + +ATF_TC_BODY(tan_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + + ATF_CHECK(isnan(tan(x)) != 0); +} + + +ATF_TC(tan_zero_neg); +ATF_TC_HEAD(tan_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tan(-0.0) == -0.0"); +} + +ATF_TC_BODY(tan_zero_neg, tc) +{ + const double x = -0.0L; + + ATF_CHECK(tan(x) == x); +} + +ATF_TC(tan_zero_pos); +ATF_TC_HEAD(tan_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tan(+0.0) == +0.0"); +} + +ATF_TC_BODY(tan_zero_pos, tc) +{ + const double x = 0.0L; + + ATF_CHECK(tan(x) == x); +} + +/* + * tanf(3) + */ +ATF_TC(tanf_angles); +ATF_TC_HEAD(tanf_angles, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test some selected angles"); +} + +ATF_TC_BODY(tanf_angles, tc) +{ + const float eps = 1.0e-6; + float x, y; + size_t i; + + for (i = 0; i < __arraycount(angles); i++) { + + x = angles[i].x; + y = angles[i].y; + + if (fabsf(tanf(x) - y) > eps) + atf_tc_fail_nonfatal("tanf(%d deg) != %0.01f", + angles[i].angle, angles[i].y); + } +} + +ATF_TC(tanf_nan); +ATF_TC_HEAD(tanf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tanf(NaN) == NaN"); +} + +ATF_TC_BODY(tanf_nan, tc) +{ + const float x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(tanf(x)) != 0); +} + +ATF_TC(tanf_inf_neg); +ATF_TC_HEAD(tanf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tanf(-Inf) == NaN"); +} + +ATF_TC_BODY(tanf_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + + if (isnan(tanf(x)) == 0) { + atf_tc_expect_fail("PR lib/45362"); + atf_tc_fail("tanf(-Inf) != NaN"); + } +} + +ATF_TC(tanf_inf_pos); +ATF_TC_HEAD(tanf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tanf(+Inf) == NaN"); +} + +ATF_TC_BODY(tanf_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + + if (isnan(tanf(x)) == 0) { + atf_tc_expect_fail("PR lib/45362"); + atf_tc_fail("tanf(+Inf) != NaN"); + } +} + + +ATF_TC(tanf_zero_neg); +ATF_TC_HEAD(tanf_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tanf(-0.0) == -0.0"); +} + +ATF_TC_BODY(tanf_zero_neg, tc) +{ + const float x = -0.0L; + + ATF_CHECK(tanf(x) == x); +} + +ATF_TC(tanf_zero_pos); +ATF_TC_HEAD(tanf_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tanf(+0.0) == +0.0"); +} + +ATF_TC_BODY(tanf_zero_pos, tc) +{ + const float x = 0.0L; + + ATF_CHECK(tanf(x) == x); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, tan_angles); + ATF_TP_ADD_TC(tp, tan_nan); + ATF_TP_ADD_TC(tp, tan_inf_neg); + ATF_TP_ADD_TC(tp, tan_inf_pos); + ATF_TP_ADD_TC(tp, tan_zero_neg); + ATF_TP_ADD_TC(tp, tan_zero_pos); + + ATF_TP_ADD_TC(tp, tanf_angles); + ATF_TP_ADD_TC(tp, tanf_nan); + ATF_TP_ADD_TC(tp, tanf_inf_neg); + ATF_TP_ADD_TC(tp, tanf_inf_pos); + ATF_TP_ADD_TC(tp, tanf_zero_neg); + ATF_TP_ADD_TC(tp, tanf_zero_pos); + + return atf_no_error(); +} diff --git a/lib/libm/t_tanh.c b/lib/libm/t_tanh.c new file mode 100644 index 000000000000..4cc4551b842c --- /dev/null +++ b/lib/libm/t_tanh.c @@ -0,0 +1,207 @@ +/* $NetBSD: t_tanh.c,v 1.7 2014/03/03 10:39:08 martin Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jukka Ruohonen. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__RCSID("$NetBSD: t_tanh.c,v 1.7 2014/03/03 10:39:08 martin Exp $"); + +#include <atf-c.h> +#include <math.h> + +/* + * tanh(3) + */ +ATF_TC(tanh_nan); +ATF_TC_HEAD(tanh_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tanh(NaN) == NaN"); +} + +ATF_TC_BODY(tanh_nan, tc) +{ + const double x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(tanh(x)) != 0); +} + +ATF_TC(tanh_inf_neg); +ATF_TC_HEAD(tanh_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tanh(-Inf) == -1.0"); +} + +ATF_TC_BODY(tanh_inf_neg, tc) +{ + const double x = -1.0L / 0.0L; + + ATF_CHECK(tanh(x) == -1.0); +} + +ATF_TC(tanh_inf_pos); +ATF_TC_HEAD(tanh_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tanh(+Inf) == +1.0"); +} + +ATF_TC_BODY(tanh_inf_pos, tc) +{ + const double x = 1.0L / 0.0L; + + ATF_CHECK(tanh(x) == 1.0); +} + +ATF_TC(tanh_zero_neg); +ATF_TC_HEAD(tanh_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tanh(-0.0) == -0.0"); +} + +ATF_TC_BODY(tanh_zero_neg, tc) +{ + const double x = -0.0L; + double y = tanh(x); + + ATF_CHECK(x == y); + ATF_CHECK(signbit(x) != 0); + + ATF_REQUIRE_MSG(signbit(y) != 0, + "compiler bug, waiting for newer gcc import, see PR lib/44057"); +} + +ATF_TC(tanh_zero_pos); +ATF_TC_HEAD(tanh_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tanh(+0.0) == +0.0"); +} + +ATF_TC_BODY(tanh_zero_pos, tc) +{ + const double x = 0.0L; + double y = tanh(x); + + ATF_CHECK(x == y); + ATF_CHECK(signbit(x) == 0); + ATF_CHECK(signbit(y) == 0); +} + +/* + * tanhf(3) + */ +ATF_TC(tanhf_nan); +ATF_TC_HEAD(tanhf_nan, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tanhf(NaN) == NaN"); +} + +ATF_TC_BODY(tanhf_nan, tc) +{ + const float x = 0.0L / 0.0L; + + ATF_CHECK(isnan(x) != 0); + ATF_CHECK(isnan(tanhf(x)) != 0); +} + +ATF_TC(tanhf_inf_neg); +ATF_TC_HEAD(tanhf_inf_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tanhf(-Inf) == -1.0"); +} + +ATF_TC_BODY(tanhf_inf_neg, tc) +{ + const float x = -1.0L / 0.0L; + + ATF_CHECK(tanhf(x) == -1.0); +} + +ATF_TC(tanhf_inf_pos); +ATF_TC_HEAD(tanhf_inf_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tanhf(+Inf) == +1.0"); +} + +ATF_TC_BODY(tanhf_inf_pos, tc) +{ + const float x = 1.0L / 0.0L; + + ATF_CHECK(tanhf(x) == 1.0); +} + +ATF_TC(tanhf_zero_neg); +ATF_TC_HEAD(tanhf_zero_neg, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tanhf(-0.0) == -0.0"); +} + +ATF_TC_BODY(tanhf_zero_neg, tc) +{ + const float x = -0.0L; + float y = tanh(x); + + ATF_CHECK(x == y); + ATF_CHECK(signbit(x) != 0); + + ATF_REQUIRE_MSG(signbit(y) != 0, + "compiler bug, waiting for newer gcc import, see PR lib/44057"); +} + +ATF_TC(tanhf_zero_pos); +ATF_TC_HEAD(tanhf_zero_pos, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test tanhf(+0.0) == +0.0"); +} + +ATF_TC_BODY(tanhf_zero_pos, tc) +{ + const float x = 0.0L; + float y = tanhf(x); + + ATF_CHECK(x == y); + ATF_CHECK(signbit(x) == 0); + ATF_CHECK(signbit(y) == 0); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, tanh_nan); + ATF_TP_ADD_TC(tp, tanh_inf_neg); + ATF_TP_ADD_TC(tp, tanh_inf_pos); + ATF_TP_ADD_TC(tp, tanh_zero_neg); + ATF_TP_ADD_TC(tp, tanh_zero_pos); + + ATF_TP_ADD_TC(tp, tanhf_nan); + ATF_TP_ADD_TC(tp, tanhf_inf_neg); + ATF_TP_ADD_TC(tp, tanhf_inf_pos); + ATF_TP_ADD_TC(tp, tanhf_zero_neg); + ATF_TP_ADD_TC(tp, tanhf_zero_pos); + + return atf_no_error(); +} |