xref: /netbsd-src/tests/lib/libm/t_round.c (revision 34908c4889d4750464a0e4f157f4388273124901)
1*34908c48Sandvar /* $NetBSD: t_round.c,v 1.10 2024/02/02 22:39:09 andvar Exp $ */
22cae26a1Sjruoho 
32cae26a1Sjruoho /*-
42cae26a1Sjruoho  * Copyright (c) 2011 The NetBSD Foundation, Inc.
52cae26a1Sjruoho  * All rights reserved.
62cae26a1Sjruoho  *
72cae26a1Sjruoho  * Redistribution and use in source and binary forms, with or without
82cae26a1Sjruoho  * modification, are permitted provided that the following conditions
92cae26a1Sjruoho  * are met:
102cae26a1Sjruoho  * 1. Redistributions of source code must retain the above copyright
112cae26a1Sjruoho  *    notice, this list of conditions and the following disclaimer.
122cae26a1Sjruoho  * 2. Redistributions in binary form must reproduce the above copyright
132cae26a1Sjruoho  *    notice, this list of conditions and the following disclaimer in the
142cae26a1Sjruoho  *    documentation and/or other materials provided with the distribution.
152cae26a1Sjruoho  *
162cae26a1Sjruoho  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
172cae26a1Sjruoho  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
182cae26a1Sjruoho  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
192cae26a1Sjruoho  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
202cae26a1Sjruoho  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
212cae26a1Sjruoho  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
222cae26a1Sjruoho  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
232cae26a1Sjruoho  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
242cae26a1Sjruoho  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
252cae26a1Sjruoho  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
262cae26a1Sjruoho  * POSSIBILITY OF SUCH DAMAGE.
272cae26a1Sjruoho  */
28a2963f40Sjruoho 
29ba15b3ffSmaya #include <sys/param.h>
30ba15b3ffSmaya 
31a2963f40Sjruoho #include <atf-c.h>
322e412cf6Sjoerg #include <float.h>
33a2963f40Sjruoho #include <math.h>
34ba15b3ffSmaya #include <stdio.h>
35cab44f07Smaya #include <stdint.h>
36a2963f40Sjruoho 
37a2963f40Sjruoho /*
38a2963f40Sjruoho  * This tests for a bug in the initial implementation where
39*34908c48Sandvar  * precision was lost in an internal subtraction, leading to
40a2963f40Sjruoho  * rounding into the wrong direction.
41a2963f40Sjruoho  */
42a2963f40Sjruoho 
43a2963f40Sjruoho /* 0.5 - EPSILON */
44a2963f40Sjruoho #define VAL	0x0.7ffffffffffffcp0
45a2963f40Sjruoho #define VALF	0x0.7fffff8p0
462e412cf6Sjoerg #define VALL	(0.5 - LDBL_EPSILON)
47a2963f40Sjruoho 
488aa49555Smrg #ifdef __vax__
498aa49555Smrg #define SMALL_NUM	1.0e-38
508aa49555Smrg #else
518aa49555Smrg #define SMALL_NUM	1.0e-40
528aa49555Smrg #endif
538aa49555Smrg 
54a2963f40Sjruoho ATF_TC(round_dir);
ATF_TC_HEAD(round_dir,tc)55a2963f40Sjruoho ATF_TC_HEAD(round_dir, tc)
56a2963f40Sjruoho {
57a2963f40Sjruoho 	atf_tc_set_md_var(tc, "descr","Check for rounding in wrong direction");
58a2963f40Sjruoho }
59a2963f40Sjruoho 
ATF_TC_BODY(round_dir,tc)60a2963f40Sjruoho ATF_TC_BODY(round_dir, tc)
61a2963f40Sjruoho {
62a2963f40Sjruoho 	double a = VAL, b, c;
63a2963f40Sjruoho 	float af = VALF, bf, cf;
642e412cf6Sjoerg 	long double al = VALL, bl, cl;
65a2963f40Sjruoho 
66a2963f40Sjruoho 	b = round(a);
67a2963f40Sjruoho 	bf = roundf(af);
682e412cf6Sjoerg 	bl = roundl(al);
69a2963f40Sjruoho 
702cae26a1Sjruoho 	ATF_CHECK(fabs(b) < SMALL_NUM);
712cae26a1Sjruoho 	ATF_CHECK(fabsf(bf) < SMALL_NUM);
722e412cf6Sjoerg 	ATF_CHECK(fabsl(bl) < SMALL_NUM);
73a2963f40Sjruoho 
74a2963f40Sjruoho 	c = round(-a);
75a2963f40Sjruoho 	cf = roundf(-af);
762e412cf6Sjoerg 	cl = roundl(-al);
77a2963f40Sjruoho 
782cae26a1Sjruoho 	ATF_CHECK(fabs(c) < SMALL_NUM);
792cae26a1Sjruoho 	ATF_CHECK(fabsf(cf) < SMALL_NUM);
802e412cf6Sjoerg 	ATF_CHECK(fabsl(cl) < SMALL_NUM);
81a2963f40Sjruoho }
82a2963f40Sjruoho 
83ba15b3ffSmaya ATF_TC(rounding_alpha);
ATF_TC_HEAD(rounding_alpha,tc)84ba15b3ffSmaya ATF_TC_HEAD(rounding_alpha, tc)
85ba15b3ffSmaya {
86ba15b3ffSmaya 	atf_tc_set_md_var(tc, "descr","Checking MPFR's config failure with -mieee on Alpha");
87ba15b3ffSmaya }
88ba15b3ffSmaya 
89ba15b3ffSmaya typedef uint64_t gimpy_limb_t;
90ba15b3ffSmaya #define GIMPY_NUMB_BITS 64
91ba15b3ffSmaya 
ATF_TC_BODY(rounding_alpha,tc)92ba15b3ffSmaya ATF_TC_BODY(rounding_alpha, tc)
93ba15b3ffSmaya {
94ba15b3ffSmaya         double d;
95ba15b3ffSmaya         gimpy_limb_t u;
96ba15b3ffSmaya         int i;
97ba15b3ffSmaya 
98ba15b3ffSmaya         d = 1.0;
99ba15b3ffSmaya         for (i = 0; i < GIMPY_NUMB_BITS - 1; i++)
100ba15b3ffSmaya                 d = d + d;
101ba15b3ffSmaya 
102ba15b3ffSmaya         printf("d = %g\n", d);
103ba15b3ffSmaya         u = (gimpy_limb_t) d;
104ba15b3ffSmaya 
105ba15b3ffSmaya         for (; i > 0; i--) {
106d498d301Smaya                 ATF_CHECK_MSG((u % 2 == 0),
107d498d301Smaya 		    "%"PRIu64" is not an even number! (iteration %d)", u , i);
108ba15b3ffSmaya                 u = u >> 1;
109ba15b3ffSmaya         }
110ba15b3ffSmaya }
111ba15b3ffSmaya 
112cab44f07Smaya ATF_TC(rounding_alpha_simple);
ATF_TC_HEAD(rounding_alpha_simple,tc)113cab44f07Smaya ATF_TC_HEAD(rounding_alpha_simple, tc)
114cab44f07Smaya {
115cab44f07Smaya 	atf_tc_set_md_var(tc, "descr","Checking double to uint64_t edge case");
116cab44f07Smaya }
117cab44f07Smaya 
118d498d301Smaya 
119d498d301Smaya double rounding_alpha_simple_even = 9223372036854775808.000000; /* 2^63 */
120d498d301Smaya 
ATF_TC_BODY(rounding_alpha_simple,tc)121cab44f07Smaya ATF_TC_BODY(rounding_alpha_simple, tc)
122cab44f07Smaya {
123d498d301Smaya 	uint64_t unsigned_even = rounding_alpha_simple_even;
124cab44f07Smaya 
125cab44f07Smaya 	ATF_CHECK_MSG(unsigned_even % 2 == 0,
12621689810Swiz 	    "2^63 cast to uint64_t is odd (got %"PRIu64")", unsigned_even);
127cab44f07Smaya 
128cab44f07Smaya }
ATF_TP_ADD_TCS(tp)129a2963f40Sjruoho ATF_TP_ADD_TCS(tp)
130a2963f40Sjruoho {
131a2963f40Sjruoho 
132a2963f40Sjruoho 	ATF_TP_ADD_TC(tp, round_dir);
133ba15b3ffSmaya 	ATF_TP_ADD_TC(tp, rounding_alpha);
134cab44f07Smaya 	ATF_TP_ADD_TC(tp, rounding_alpha_simple);
135a2963f40Sjruoho 
136a2963f40Sjruoho 	return atf_no_error();
137a2963f40Sjruoho }
138