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