Home | History | Annotate | Line # | Download | only in libm
t_cos.c revision 1.9
      1 /* $NetBSD: t_cos.c,v 1.9 2019/05/27 00:10:36 maya Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2011 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jukka Ruohonen.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <assert.h>
     33 #include <atf-c.h>
     34 #include <float.h>
     35 #include <math.h>
     36 
     37 static const struct {
     38 	int		angle;
     39 	double		x;
     40 	double		y;
     41 	float		fy;
     42 } angles[] = {
     43 	{ -180, -3.141592653589793, -1.0000000000000000, 999 },
     44 	{ -135, -2.356194490192345, -0.7071067811865476, 999 },
     45 	{  -90, -1.5707963267948966, 6.123233995736766e-17, -4.3711388e-08 },
     46 	{  -90, -1.5707963267948968, -1.6081226496766366e-16, -4.3711388e-08 },
     47 	{  -45, -0.785398163397448,  0.7071067811865478, 999 },
     48 	{    0,  0.000000000000000,  1.0000000000000000, 999 },
     49 	{   30,  0.523598775598299,  0.8660254037844386, 999 },
     50 	{   45,  0.785398163397448,  0.7071067811865478, 999 },
     51 	{   60,  1.0471975511965976,  0.5000000000000001, 999 },
     52 	{   60,  1.0471975511965979,  0.4999999999999999, 999 },
     53 	{   90,  1.570796326794897, -3.8285686989269494e-16, -4.3711388e-08 },
     54 	{  120,  2.0943951023931953, -0.4999999999999998, 999 },
     55 	{  120,  2.0943951023931957, -0.5000000000000002, 999 },
     56 	{  135,  2.356194490192345, -0.7071067811865476, 999 },
     57 	{  150,  2.617993877991494, -0.8660254037844386, 999 },
     58 	{  180,  3.141592653589793, -1.0000000000000000, 999 },
     59 	{  270,  4.712388980384690, -1.8369701987210297e-16, 1.1924881e-08 },
     60 	{  360,  6.283185307179586,  1.0000000000000000, 999 },
     61 };
     62 
     63 #ifdef __HAVE_LONG_DOUBLE
     64 /*
     65  * cosl(3)
     66  */
     67 ATF_TC(cosl_angles);
     68 ATF_TC_HEAD(cosl_angles, tc)
     69 {
     70 	atf_tc_set_md_var(tc, "descr", "Test some selected angles");
     71 }
     72 
     73 ATF_TC_BODY(cosl_angles, tc)
     74 {
     75 	/*
     76 	 * XXX The given data is for double, so take that
     77 	 * into account and expect less precise results..
     78 	 */
     79 	const long double eps = DBL_EPSILON;
     80 	size_t i;
     81 
     82 	for (i = 0; i < __arraycount(angles); i++) {
     83 		int deg = angles[i].angle;
     84 		long double theta = angles[i].x;
     85 		long double cos_theta = angles[i].y;
     86 
     87 		assert(cos_theta != 0);
     88 		if (!(fabsl((cosl(theta) - cos_theta)/cos_theta) <= eps)) {
     89 			atf_tc_fail_nonfatal("cos(%d deg = %.17Lg) = %.17Lg"
     90 			    " != %.17Lg",
     91 			    deg, theta, cosl(theta), cos_theta);
     92 		}
     93 	}
     94 }
     95 
     96 ATF_TC(cosl_nan);
     97 ATF_TC_HEAD(cosl_nan, tc)
     98 {
     99 	atf_tc_set_md_var(tc, "descr", "Test cosl(NaN) == NaN");
    100 }
    101 
    102 ATF_TC_BODY(cosl_nan, tc)
    103 {
    104 	const long double x = 0.0L / 0.0L;
    105 
    106 	ATF_CHECK(isnan(x) != 0);
    107 	ATF_CHECK(isnan(cosl(x)) != 0);
    108 }
    109 
    110 ATF_TC(cosl_inf_neg);
    111 ATF_TC_HEAD(cosl_inf_neg, tc)
    112 {
    113 	atf_tc_set_md_var(tc, "descr", "Test cosl(-Inf) == NaN");
    114 }
    115 
    116 ATF_TC_BODY(cosl_inf_neg, tc)
    117 {
    118 	const long double x = -1.0L / 0.0L;
    119 
    120 	ATF_CHECK(isnan(cosl(x)) != 0);
    121 }
    122 
    123 ATF_TC(cosl_inf_pos);
    124 ATF_TC_HEAD(cosl_inf_pos, tc)
    125 {
    126 	atf_tc_set_md_var(tc, "descr", "Test cosl(+Inf) == NaN");
    127 }
    128 
    129 ATF_TC_BODY(cosl_inf_pos, tc)
    130 {
    131 	const long double x = 1.0L / 0.0L;
    132 
    133 	ATF_CHECK(isnan(cosl(x)) != 0);
    134 }
    135 
    136 
    137 ATF_TC(cosl_zero_neg);
    138 ATF_TC_HEAD(cosl_zero_neg, tc)
    139 {
    140 	atf_tc_set_md_var(tc, "descr", "Test cosl(-0.0) == 1.0");
    141 }
    142 
    143 ATF_TC_BODY(cosl_zero_neg, tc)
    144 {
    145 	const long double x = -0.0L;
    146 
    147 	ATF_CHECK(cosl(x) == 1.0);
    148 }
    149 
    150 ATF_TC(cosl_zero_pos);
    151 ATF_TC_HEAD(cosl_zero_pos, tc)
    152 {
    153 	atf_tc_set_md_var(tc, "descr", "Test cosl(+0.0) == 1.0");
    154 }
    155 
    156 ATF_TC_BODY(cosl_zero_pos, tc)
    157 {
    158 	const long double x = 0.0L;
    159 
    160 	ATF_CHECK(cosl(x) == 1.0);
    161 }
    162 #endif
    163 
    164 /*
    165  * cos(3)
    166  */
    167 ATF_TC(cos_angles);
    168 ATF_TC_HEAD(cos_angles, tc)
    169 {
    170 	atf_tc_set_md_var(tc, "descr", "Test some selected angles");
    171 }
    172 
    173 ATF_TC_BODY(cos_angles, tc)
    174 {
    175 	const double eps = DBL_EPSILON;
    176 	size_t i;
    177 
    178 	for (i = 0; i < __arraycount(angles); i++) {
    179 		int deg = angles[i].angle;
    180 		double theta = angles[i].x;
    181 		double cos_theta = angles[i].y;
    182 
    183 		assert(cos_theta != 0);
    184 		if (!(fabs((cos(theta) - cos_theta)/cos_theta) <= eps)) {
    185 			atf_tc_fail_nonfatal("cos(%d deg = %.17g) = %.17g"
    186 			    " != %.17g",
    187 			    deg, theta, cos(theta), cos_theta);
    188 		}
    189 	}
    190 }
    191 
    192 ATF_TC(cos_nan);
    193 ATF_TC_HEAD(cos_nan, tc)
    194 {
    195 	atf_tc_set_md_var(tc, "descr", "Test cos(NaN) == NaN");
    196 }
    197 
    198 ATF_TC_BODY(cos_nan, tc)
    199 {
    200 	const double x = 0.0L / 0.0L;
    201 
    202 	ATF_CHECK(isnan(x) != 0);
    203 	ATF_CHECK(isnan(cos(x)) != 0);
    204 }
    205 
    206 ATF_TC(cos_inf_neg);
    207 ATF_TC_HEAD(cos_inf_neg, tc)
    208 {
    209 	atf_tc_set_md_var(tc, "descr", "Test cos(-Inf) == NaN");
    210 }
    211 
    212 ATF_TC_BODY(cos_inf_neg, tc)
    213 {
    214 	const double x = -1.0L / 0.0L;
    215 
    216 	ATF_CHECK(isnan(cos(x)) != 0);
    217 }
    218 
    219 ATF_TC(cos_inf_pos);
    220 ATF_TC_HEAD(cos_inf_pos, tc)
    221 {
    222 	atf_tc_set_md_var(tc, "descr", "Test cos(+Inf) == NaN");
    223 }
    224 
    225 ATF_TC_BODY(cos_inf_pos, tc)
    226 {
    227 	const double x = 1.0L / 0.0L;
    228 
    229 	ATF_CHECK(isnan(cos(x)) != 0);
    230 }
    231 
    232 
    233 ATF_TC(cos_zero_neg);
    234 ATF_TC_HEAD(cos_zero_neg, tc)
    235 {
    236 	atf_tc_set_md_var(tc, "descr", "Test cos(-0.0) == 1.0");
    237 }
    238 
    239 ATF_TC_BODY(cos_zero_neg, tc)
    240 {
    241 	const double x = -0.0L;
    242 
    243 	ATF_CHECK(cos(x) == 1.0);
    244 }
    245 
    246 ATF_TC(cos_zero_pos);
    247 ATF_TC_HEAD(cos_zero_pos, tc)
    248 {
    249 	atf_tc_set_md_var(tc, "descr", "Test cos(+0.0) == 1.0");
    250 }
    251 
    252 ATF_TC_BODY(cos_zero_pos, tc)
    253 {
    254 	const double x = 0.0L;
    255 
    256 	ATF_CHECK(cos(x) == 1.0);
    257 }
    258 
    259 /*
    260  * cosf(3)
    261  */
    262 ATF_TC(cosf_angles);
    263 ATF_TC_HEAD(cosf_angles, tc)
    264 {
    265 	atf_tc_set_md_var(tc, "descr", "Test some selected angles");
    266 }
    267 
    268 ATF_TC_BODY(cosf_angles, tc)
    269 {
    270 	const float eps = FLT_EPSILON;
    271 	size_t i;
    272 
    273 	for (i = 0; i < __arraycount(angles); i++) {
    274 		int deg = angles[i].angle;
    275 		float theta = angles[i].x;
    276 		float cos_theta = angles[i].fy;
    277 
    278 		/*
    279 		 * Force rounding to float even if FLT_EVAL_METHOD=2,
    280 		 * as is the case on i386.
    281 		 *
    282 		 * The volatile should not be necessary, by C99 Sec.
    283 		 * 5.2.4.2.2. para. 8 on p. 24 which specifies that
    284 		 * assignment and cast remove all extra range and precision,
    285 		 * but seems to be needed to work around a compiler bug.
    286 		 */
    287 		volatile float result = cosf(theta);
    288 
    289 		if (cos_theta == 999)
    290 			cos_theta = angles[i].y;
    291 
    292 		assert(cos_theta != 0);
    293 		if (!(fabsf((result - cos_theta)/cos_theta) <= eps)) {
    294 			atf_tc_fail_nonfatal("cosf(%d deg = %.8g) = %.8g"
    295 			    " != %.8g", deg, theta, result, cos_theta);
    296 		}
    297 	}
    298 }
    299 
    300 ATF_TC(cosf_nan);
    301 ATF_TC_HEAD(cosf_nan, tc)
    302 {
    303 	atf_tc_set_md_var(tc, "descr", "Test cosf(NaN) == NaN");
    304 }
    305 
    306 ATF_TC_BODY(cosf_nan, tc)
    307 {
    308 	const float x = 0.0L / 0.0L;
    309 
    310 	ATF_CHECK(isnan(x) != 0);
    311 	ATF_CHECK(isnan(cosf(x)) != 0);
    312 }
    313 
    314 ATF_TC(cosf_inf_neg);
    315 ATF_TC_HEAD(cosf_inf_neg, tc)
    316 {
    317 	atf_tc_set_md_var(tc, "descr", "Test cosf(-Inf) == NaN");
    318 }
    319 
    320 ATF_TC_BODY(cosf_inf_neg, tc)
    321 {
    322 	const float x = -1.0L / 0.0L;
    323 
    324 	if (isnan(cosf(x)) == 0) {
    325 		atf_tc_expect_fail("PR lib/45362");
    326 		atf_tc_fail("cosf(-Inf) != NaN");
    327 	}
    328 }
    329 
    330 ATF_TC(cosf_inf_pos);
    331 ATF_TC_HEAD(cosf_inf_pos, tc)
    332 {
    333 	atf_tc_set_md_var(tc, "descr", "Test cosf(+Inf) == NaN");
    334 }
    335 
    336 ATF_TC_BODY(cosf_inf_pos, tc)
    337 {
    338 	const float x = 1.0L / 0.0L;
    339 
    340 	if (isnan(cosf(x)) == 0) {
    341 		atf_tc_expect_fail("PR lib/45362");
    342 		atf_tc_fail("cosf(+Inf) != NaN");
    343 	}
    344 }
    345 
    346 
    347 ATF_TC(cosf_zero_neg);
    348 ATF_TC_HEAD(cosf_zero_neg, tc)
    349 {
    350 	atf_tc_set_md_var(tc, "descr", "Test cosf(-0.0) == 1.0");
    351 }
    352 
    353 ATF_TC_BODY(cosf_zero_neg, tc)
    354 {
    355 	const float x = -0.0L;
    356 
    357 	ATF_CHECK(cosf(x) == 1.0);
    358 }
    359 
    360 ATF_TC(cosf_zero_pos);
    361 ATF_TC_HEAD(cosf_zero_pos, tc)
    362 {
    363 	atf_tc_set_md_var(tc, "descr", "Test cosf(+0.0) == 1.0");
    364 }
    365 
    366 ATF_TC_BODY(cosf_zero_pos, tc)
    367 {
    368 	const float x = 0.0L;
    369 
    370 	ATF_CHECK(cosf(x) == 1.0);
    371 }
    372 
    373 ATF_TP_ADD_TCS(tp)
    374 {
    375 #ifdef __HAVE_LONG_DOUBLE
    376 	ATF_TP_ADD_TC(tp, cosl_angles);
    377 	ATF_TP_ADD_TC(tp, cosl_nan);
    378 	ATF_TP_ADD_TC(tp, cosl_inf_neg);
    379 	ATF_TP_ADD_TC(tp, cosl_inf_pos);
    380 	ATF_TP_ADD_TC(tp, cosl_zero_neg);
    381 	ATF_TP_ADD_TC(tp, cosl_zero_pos);
    382 #endif
    383 
    384 	ATF_TP_ADD_TC(tp, cos_angles);
    385 	ATF_TP_ADD_TC(tp, cos_nan);
    386 	ATF_TP_ADD_TC(tp, cos_inf_neg);
    387 	ATF_TP_ADD_TC(tp, cos_inf_pos);
    388 	ATF_TP_ADD_TC(tp, cos_zero_neg);
    389 	ATF_TP_ADD_TC(tp, cos_zero_pos);
    390 
    391 	ATF_TP_ADD_TC(tp, cosf_angles);
    392 	ATF_TP_ADD_TC(tp, cosf_nan);
    393 	ATF_TP_ADD_TC(tp, cosf_inf_neg);
    394 	ATF_TP_ADD_TC(tp, cosf_inf_pos);
    395 	ATF_TP_ADD_TC(tp, cosf_zero_neg);
    396 	ATF_TP_ADD_TC(tp, cosf_zero_pos);
    397 
    398 	return atf_no_error();
    399 }
    400