Home | History | Annotate | Line # | Download | only in libm
t_sincos.c revision 1.1
      1 /* $NetBSD: t_sincos.c,v 1.1 2022/08/27 08:31:58 christos Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2011, 2022 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 and Christos Zoulas
      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 #include <stdio.h>
     37 
     38 static const struct {
     39 	int		angle;
     40 	double		x;
     41 	double		y;
     42 	float		fy;
     43 } sin_angles[] = {
     44 //	{ -360, -6.283185307179586,  2.4492935982947064e-16, -1.7484555e-07 },
     45 	{ -180, -3.141592653589793, -1.2246467991473532e-16, 8.7422777e-08 },
     46 	{ -135, -2.356194490192345, -0.7071067811865476, 999 },
     47 //	{  -90, -1.570796326794897, -1.0000000000000000, 999 },
     48 	{  -45, -0.785398163397448, -0.7071067811865472, 999 },
     49 	{    0,  0.000000000000000,  0.0000000000000000, 999 },
     50 	{   30,  0.5235987755982989, 0.5000000000000000, 999 },
     51 	{   45,  0.785398163397448,  0.7071067811865472, 999 },
     52 //	{   60,  1.047197551196598,  0.8660254037844388, 999 },
     53 	{   90,  1.570796326794897,  1.0000000000000000, 999 },
     54 //	{  120,  2.094395102393195,  0.8660254037844389, 999 },
     55 	{  135,  2.356194490192345,  0.7071067811865476, 999 },
     56 	{  150,  2.617993877991494,  0.5000000000000003, 999 },
     57 	{  180,  3.141592653589793,  1.2246467991473532e-16, -8.7422777e-08 },
     58 	{  270,  4.712388980384690, -1.0000000000000000, 999 },
     59 	{  360,  6.283185307179586, -2.4492935982947064e-16, 1.7484555e-07 },
     60 };
     61 
     62 static const struct {
     63 	int		angle;
     64 	double		x;
     65 	double		y;
     66 	float		fy;
     67 } cos_angles[] = {
     68 	{ -180, -3.141592653589793, -1.0000000000000000, 999 },
     69 	{ -135, -2.356194490192345, -0.7071067811865476, 999 },
     70 //	{  -90, -1.5707963267948966, 6.123233995736766e-17, -4.3711388e-08 },
     71 //	{  -90, -1.5707963267948968, -1.6081226496766366e-16, -4.3711388e-08 },
     72 	{  -45, -0.785398163397448,  0.7071067811865478, 999 },
     73 	{    0,  0.000000000000000,  1.0000000000000000, 999 },
     74 	{   30,  0.5235987755982989, 0.8660254037844386, 999 },
     75 	{   45,  0.785398163397448,  0.7071067811865478, 999 },
     76 //	{   60,  1.0471975511965976,  0.5000000000000001, 999 },
     77 //	{   60,  1.0471975511965979,  0.4999999999999999, 999 },
     78 	{   90,  1.570796326794897, -3.8285686989269494e-16, -4.3711388e-08 },
     79 //	{  120,  2.0943951023931953, -0.4999999999999998, 999 },
     80 //	{  120,  2.0943951023931957, -0.5000000000000002, 999 },
     81 	{  135,  2.356194490192345, -0.7071067811865476, 999 },
     82 	{  150,  2.617993877991494, -0.8660254037844386, 999 },
     83 	{  180,  3.141592653589793, -1.0000000000000000, 999 },
     84 	{  270,  4.712388980384690, -1.8369701987210297e-16, 1.1924881e-08 },
     85 	{  360,  6.283185307179586,  1.0000000000000000, 999 },
     86 };
     87 
     88 #ifdef __HAVE_LONG_DOUBLE
     89 /*
     90  * sincosl(3)
     91  */
     92 ATF_TC(sincosl_angles);
     93 ATF_TC_HEAD(sincosl_angles, tc)
     94 {
     95 	atf_tc_set_md_var(tc, "descr", "Test some selected angles");
     96 }
     97 
     98 ATF_TC_BODY(sincosl_angles, tc)
     99 {
    100 	/*
    101 	 * XXX The given data is for double, so take that
    102 	 * into account and expect less precise results..
    103 	 */
    104 	const long double eps = DBL_EPSILON;
    105 	size_t i;
    106 
    107 	ATF_CHECK(__arraycount(sin_angles) == __arraycount(cos_angles));
    108 
    109 	for (i = 0; i < __arraycount(sin_angles); i++) {
    110 		ATF_CHECK_MSG(sin_angles[i].angle == cos_angles[i].angle,
    111 		    "%zu %d %d", i, sin_angles[i].angle, cos_angles[i].angle);
    112 		int deg = sin_angles[i].angle;
    113 		ATF_CHECK_MSG(sin_angles[i].x == cos_angles[i].x,
    114 		    "%zu %g %g", i, sin_angles[i].x, cos_angles[i].x);
    115 		long double theta = sin_angles[i].x;
    116 		long double sin_theta = sin_angles[i].y;
    117 		long double cos_theta = cos_angles[i].y;
    118 		long double s, c;
    119 
    120 		sincosl(theta, &s, &c);
    121 
    122 		if (fabsl((s - sin_theta)/sin_theta) > eps) {
    123 			atf_tc_fail_nonfatal("sin(%d deg = %.17Lg) = %.17Lg"
    124 			    " != %.17Lg",
    125 			    deg, theta, s, sin_theta);
    126 		}
    127 		if (fabsl((c - cos_theta)/cos_theta) > eps) {
    128 			atf_tc_fail_nonfatal("cos(%d deg = %.17Lg) = %.17Lg"
    129 			    " != %.17Lg",
    130 			    deg, theta, c, cos_theta);
    131 		}
    132 	}
    133 }
    134 
    135 ATF_TC(sincosl_nan);
    136 ATF_TC_HEAD(sincosl_nan, tc)
    137 {
    138 	atf_tc_set_md_var(tc, "descr", "Test sincosl(NaN) == (NaN, NaN)");
    139 }
    140 
    141 ATF_TC_BODY(sincosl_nan, tc)
    142 {
    143 	const long double x = 0.0L / 0.0L;
    144 	long double s, c;
    145 
    146 	sincosl(x, &s, &c);
    147 	ATF_CHECK(isnan(x) && isnan(s) && isnan(c));
    148 }
    149 
    150 ATF_TC(sincosl_inf_neg);
    151 ATF_TC_HEAD(sincosl_inf_neg, tc)
    152 {
    153 	atf_tc_set_md_var(tc, "descr", "Test sincosl(-Inf) == (NaN, NaN)");
    154 }
    155 
    156 ATF_TC_BODY(sincosl_inf_neg, tc)
    157 {
    158 	const long double x = -1.0L / 0.0L;
    159 	long double s, c;
    160 
    161 	sincosl(x, &s, &c);
    162 	ATF_CHECK(isnan(s) && isnan(c));
    163 }
    164 
    165 ATF_TC(sincosl_inf_pos);
    166 ATF_TC_HEAD(sincosl_inf_pos, tc)
    167 {
    168 	atf_tc_set_md_var(tc, "descr", "Test sincosl(+Inf) == (NaN, NaN)");
    169 }
    170 
    171 ATF_TC_BODY(sincosl_inf_pos, tc)
    172 {
    173 	const long double x = 1.0L / 0.0L;
    174 	long double s, c;
    175 
    176 	sincosl(x, &s, &c);
    177 	ATF_CHECK(isnan(s) && isnan(c));
    178 }
    179 
    180 
    181 ATF_TC(sincosl_zero_neg);
    182 ATF_TC_HEAD(sincosl_zero_neg, tc)
    183 {
    184 	atf_tc_set_md_var(tc, "descr", "Test sincosl(-0.0) == (0.0, 1.0)");
    185 }
    186 
    187 ATF_TC_BODY(sincosl_zero_neg, tc)
    188 {
    189 	const long double x = -0.0L;
    190 	long double s, c;
    191 
    192 	sincosl(x, &s, &c);
    193 	ATF_CHECK(s == 0.0 && c == 1.0);
    194 }
    195 
    196 ATF_TC(sincosl_zero_pos);
    197 ATF_TC_HEAD(sincosl_zero_pos, tc)
    198 {
    199 	atf_tc_set_md_var(tc, "descr", "Test sincosl(+0.0) == (0.0, 1.0)");
    200 }
    201 
    202 ATF_TC_BODY(sincosl_zero_pos, tc)
    203 {
    204 	const long double x = 0.0L;
    205 	long double s, c;
    206 
    207 	sincosl(x, &s, &c);
    208 	ATF_CHECK(s == 0.0 && c == 1.0);
    209 }
    210 #endif
    211 
    212 /*
    213  * sincos(3)
    214  */
    215 ATF_TC(sincos_angles);
    216 ATF_TC_HEAD(sincos_angles, tc)
    217 {
    218 	atf_tc_set_md_var(tc, "descr", "Test some selected angles");
    219 }
    220 
    221 ATF_TC_BODY(sincos_angles, tc)
    222 {
    223 	const double eps = DBL_EPSILON;
    224 	size_t i;
    225 
    226 	for (i = 0; i < __arraycount(sin_angles); i++) {
    227 		ATF_CHECK_MSG(sin_angles[i].angle == cos_angles[i].angle,
    228 		    "%zu %d %d", i, sin_angles[i].angle, cos_angles[i].angle);
    229 		int deg = sin_angles[i].angle;
    230 		ATF_CHECK_MSG(sin_angles[i].x == cos_angles[i].x,
    231 		    "%zu %g %g", i, sin_angles[i].x, cos_angles[i].x);
    232 		double theta = sin_angles[i].x;
    233 		double sin_theta = sin_angles[i].y;
    234 		double cos_theta = cos_angles[i].y;
    235 		double s, c;
    236 
    237 		sincos(theta, &s, &c);
    238 
    239 		if (fabs((s - sin_theta)/sin_theta) > eps) {
    240 			atf_tc_fail_nonfatal("sin(%d deg = %.17g) = %.17g"
    241 			    " != %.17g",
    242 			    deg, theta, s, sin_theta);
    243 		}
    244 		if (fabs((c - cos_theta)/cos_theta) > eps) {
    245 			atf_tc_fail_nonfatal("cos(%d deg = %.17g) = %.17g"
    246 			    " != %.17g",
    247 			    deg, theta, c, cos_theta);
    248 		}
    249 	}
    250 }
    251 
    252 ATF_TC(sincos_nan);
    253 ATF_TC_HEAD(sincos_nan, tc)
    254 {
    255 	atf_tc_set_md_var(tc, "descr", "Test sincos(NaN) == (NaN, NaN)");
    256 }
    257 
    258 ATF_TC_BODY(sincos_nan, tc)
    259 {
    260 	const double x = 0.0L / 0.0L;
    261 	double s, c;
    262 
    263 	sincos(x, &s, &c);
    264 	ATF_CHECK(isnan(x) && isnan(s) && isnan(c));
    265 }
    266 
    267 ATF_TC(sincos_inf_neg);
    268 ATF_TC_HEAD(sincos_inf_neg, tc)
    269 {
    270 	atf_tc_set_md_var(tc, "descr", "Test sincos(-Inf) == (NaN, NaN)");
    271 }
    272 
    273 ATF_TC_BODY(sincos_inf_neg, tc)
    274 {
    275 	const double x = -1.0L / 0.0L;
    276 	double s, c;
    277 
    278 	sincos(x, &s, &c);
    279 	ATF_CHECK(isnan(s) && isnan(c));
    280 }
    281 
    282 ATF_TC(sincos_inf_pos);
    283 ATF_TC_HEAD(sincos_inf_pos, tc)
    284 {
    285 	atf_tc_set_md_var(tc, "descr", "Test sincos(+Inf) == (NaN, NaN)");
    286 }
    287 
    288 ATF_TC_BODY(sincos_inf_pos, tc)
    289 {
    290 	const double x = 1.0L / 0.0L;
    291 	double s, c;
    292 
    293 	sincos(x, &s, &c);
    294 	ATF_CHECK(isnan(s) && isnan(c));
    295 }
    296 
    297 
    298 ATF_TC(sincos_zero_neg);
    299 ATF_TC_HEAD(sincos_zero_neg, tc)
    300 {
    301 	atf_tc_set_md_var(tc, "descr", "Test sincos(-0.0) == (0.0, 1.0)");
    302 }
    303 
    304 ATF_TC_BODY(sincos_zero_neg, tc)
    305 {
    306 	const double x = -0.0L;
    307 	double s, c;
    308 
    309 	sincos(x, &s, &c);
    310 	ATF_CHECK(s == 0 && c == 1.0);
    311 }
    312 
    313 ATF_TC(sincos_zero_pos);
    314 ATF_TC_HEAD(sincos_zero_pos, tc)
    315 {
    316 	atf_tc_set_md_var(tc, "descr", "Test cos(+0.0) == (0.0, 1.0)");
    317 }
    318 
    319 ATF_TC_BODY(sincos_zero_pos, tc)
    320 {
    321 	const double x = 0.0L;
    322 	double s, c;
    323 
    324 	sincos(x, &s, &c);
    325 	ATF_CHECK(s == 0 && c == 1.0);
    326 }
    327 
    328 /*
    329  * sincosf(3)
    330  */
    331 ATF_TC(sincosf_angles);
    332 ATF_TC_HEAD(sincosf_angles, tc)
    333 {
    334 	atf_tc_set_md_var(tc, "descr", "Test some selected angles");
    335 }
    336 
    337 ATF_TC_BODY(sincosf_angles, tc)
    338 {
    339 	const float eps = FLT_EPSILON;
    340 	size_t i;
    341 
    342 	for (i = 0; i < __arraycount(sin_angles); i++) {
    343 		ATF_CHECK_MSG(sin_angles[i].angle == cos_angles[i].angle,
    344 		    "%zu %d %d", i, sin_angles[i].angle, cos_angles[i].angle);
    345 		int deg = sin_angles[i].angle;
    346 		ATF_CHECK_MSG(sin_angles[i].x == cos_angles[i].x,
    347 		    "%zu %g %g", i, sin_angles[i].x, cos_angles[i].x);
    348 		float theta = sin_angles[i].x;
    349 		float sin_theta = sin_angles[i].fy;
    350 		float cos_theta = cos_angles[i].fy;
    351 		float s, c;
    352 
    353 		sincosf(theta, &s, &c);
    354 		if (cos_theta == 999)
    355 			cos_theta = cos_angles[i].y;
    356 		if (sin_theta == 999)
    357 			sin_theta = sin_angles[i].y;
    358 
    359 		if (fabs((s - sin_theta)/sin_theta) > eps) {
    360 			atf_tc_fail_nonfatal("sin(%d deg = %.8g) = %.8g"
    361 			    " != %.8g",
    362 			    deg, theta, s, sin_theta);
    363 		}
    364 		if (fabs((c - cos_theta)/cos_theta) > eps) {
    365 			atf_tc_fail_nonfatal("cos(%d deg = %.8g) = %.8g"
    366 			    " != %.8g",
    367 			    deg, theta, c, cos_theta);
    368 		}
    369 	}
    370 }
    371 
    372 ATF_TC(sincosf_nan);
    373 ATF_TC_HEAD(sincosf_nan, tc)
    374 {
    375 	atf_tc_set_md_var(tc, "descr", "Test cosf(NaN) == (NaN, NaN)");
    376 }
    377 
    378 ATF_TC_BODY(sincosf_nan, tc)
    379 {
    380 	const float x = 0.0L / 0.0L;
    381 	float s, c;
    382 
    383 	sincosf(x, &s, &c);
    384 	ATF_CHECK(isnan(x) && isnan(s) && isnan(c));
    385 }
    386 
    387 ATF_TC(sincosf_inf_neg);
    388 ATF_TC_HEAD(sincosf_inf_neg, tc)
    389 {
    390 	atf_tc_set_md_var(tc, "descr", "Test cosf(-Inf) == (NaN, NaN)");
    391 }
    392 
    393 ATF_TC_BODY(sincosf_inf_neg, tc)
    394 {
    395 	const float x = -1.0L / 0.0L;
    396 	float s, c;
    397 
    398 	sincosf(x, &s, &c);
    399 	ATF_CHECK(isnan(s) && isnan(c));
    400 
    401 }
    402 
    403 ATF_TC(sincosf_inf_pos);
    404 ATF_TC_HEAD(sincosf_inf_pos, tc)
    405 {
    406 	atf_tc_set_md_var(tc, "descr", "Test sincosf(+Inf) == (NaN, NaN)");
    407 }
    408 
    409 ATF_TC_BODY(sincosf_inf_pos, tc)
    410 {
    411 	const float x = 1.0L / 0.0L;
    412 	float s, c;
    413 
    414 	sincosf(x, &s, &c);
    415 	ATF_CHECK(isnan(s) && isnan(c));
    416 }
    417 
    418 
    419 ATF_TC(sincosf_zero_neg);
    420 ATF_TC_HEAD(sincosf_zero_neg, tc)
    421 {
    422 	atf_tc_set_md_var(tc, "descr", "Test sincosf(-0.0) == (0.0, 1.0)");
    423 }
    424 
    425 ATF_TC_BODY(sincosf_zero_neg, tc)
    426 {
    427 	const float x = -0.0L;
    428 	float s, c;
    429 
    430 	sincosf(x, &s, &c);
    431 
    432 	ATF_CHECK(s == 0.0 && c == 1.0);
    433 }
    434 
    435 ATF_TC(sincosf_zero_pos);
    436 ATF_TC_HEAD(sincosf_zero_pos, tc)
    437 {
    438 	atf_tc_set_md_var(tc, "descr", "Test sincosf(+0.0) == (0.0, 1.0)");
    439 }
    440 
    441 ATF_TC_BODY(sincosf_zero_pos, tc)
    442 {
    443 	const float x = 0.0L;
    444 
    445 	float s, c;
    446 
    447 	sincosf(x, &s, &c);
    448 
    449 	ATF_CHECK(s == 0 && c == 1.0);
    450 }
    451 
    452 ATF_TP_ADD_TCS(tp)
    453 {
    454 #ifdef __HAVE_LONG_DOUBLE
    455 	ATF_TP_ADD_TC(tp, sincosl_angles);
    456 	ATF_TP_ADD_TC(tp, sincosl_nan);
    457 	ATF_TP_ADD_TC(tp, sincosl_inf_neg);
    458 	ATF_TP_ADD_TC(tp, sincosl_inf_pos);
    459 	ATF_TP_ADD_TC(tp, sincosl_zero_neg);
    460 	ATF_TP_ADD_TC(tp, sincosl_zero_pos);
    461 #endif
    462 
    463 	ATF_TP_ADD_TC(tp, sincos_angles);
    464 	ATF_TP_ADD_TC(tp, sincos_nan);
    465 	ATF_TP_ADD_TC(tp, sincos_inf_neg);
    466 	ATF_TP_ADD_TC(tp, sincos_inf_pos);
    467 	ATF_TP_ADD_TC(tp, sincos_zero_neg);
    468 	ATF_TP_ADD_TC(tp, sincos_zero_pos);
    469 
    470 	ATF_TP_ADD_TC(tp, sincosf_angles);
    471 	ATF_TP_ADD_TC(tp, sincosf_nan);
    472 	ATF_TP_ADD_TC(tp, sincosf_inf_neg);
    473 	ATF_TP_ADD_TC(tp, sincosf_inf_pos);
    474 	ATF_TP_ADD_TC(tp, sincosf_zero_neg);
    475 	ATF_TP_ADD_TC(tp, sincosf_zero_pos);
    476 
    477 	return atf_no_error();
    478 }
    479