190075Sobrien/*-
290075Sobrien * Copyright (c) 2005-2008 David Schultz <das@FreeBSD.org>
3169689Skan * All rights reserved.
490075Sobrien *
590075Sobrien * Redistribution and use in source and binary forms, with or without
690075Sobrien * modification, are permitted provided that the following conditions
7132718Skan * are met:
890075Sobrien * 1. Redistributions of source code must retain the above copyright
9132718Skan *    notice, this list of conditions and the following disclaimer.
10132718Skan * 2. Redistributions in binary form must reproduce the above copyright
11132718Skan *    notice, this list of conditions and the following disclaimer in the
12132718Skan *    documentation and/or other materials provided with the distribution.
1390075Sobrien *
14132718Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15132718Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16132718Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17132718Skan * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1890075Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19132718Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20132718Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2390075Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24132718Skan * SUCH DAMAGE.
2590075Sobrien */
2690075Sobrien
2790075Sobrien/*
2890075Sobrien * Test for lrint(), lrintf(), llrint(), and llrintf().
2990075Sobrien */
3090075Sobrien
3190075Sobrien#include <sys/cdefs.h>
3290075Sobrien#include <fenv.h>
33169689Skan#include <limits.h>
34169689Skan#include <math.h>
35169689Skan#include <stdio.h>
3690075Sobrien
37169689Skan#ifdef	__i386__
3890075Sobrien#include <ieeefp.h>
3990075Sobrien#endif
4090075Sobrien
41169689Skan#include "test-utils.h"
4290075Sobrien
4390075Sobrien#define	test(func, x, result, excepts)	do {					\
4490075Sobrien	ATF_CHECK(feclearexcept(FE_ALL_EXCEPT) == 0);				\
45117395Skan	long long _r = (func)(x);						\
4690075Sobrien	ATF_CHECK_MSG(_r == (result) || fetestexcept(FE_INVALID),		\
4790075Sobrien	    #func "(%Lg) returned %lld, expected %lld", (long double)x, _r,	\
4890075Sobrien	    (long long)(result));						\
4990075Sobrien	CHECK_FP_EXCEPTIONS_MSG(excepts, FE_ALL_EXCEPT & ALL_STD_EXCEPT,	\
50132718Skan	    "for %s(%s)", #func, #x);						\
5190075Sobrien} while (0)
5290075Sobrien
5390075Sobrien#define	testall(x, result, excepts)	do {				\
5490075Sobrien	test(lrint, x, result, excepts);				\
5590075Sobrien	test(lrintf, x, result, excepts);				\
5690075Sobrien	test(lrintl, x, result, excepts);				\
5790075Sobrien	test(llrint, x, result, excepts);				\
5890075Sobrien	test(llrintf, x, result, excepts);				\
5990075Sobrien	test(llrintl, x, result, excepts);				\
6090075Sobrien} while (0)
6190075Sobrien
6296263Sobrien#define	IGNORE	0
6396263Sobrien
6496263Sobrien#pragma STDC FENV_ACCESS ON
6590075Sobrien
66117395Skanstatic void
67117395Skanrun_tests(void)
6890075Sobrien{
6990075Sobrien	ATF_REQUIRE_EQ(0, fesetround(FE_DOWNWARD));
7090075Sobrien	testall(0.75, 0, FE_INEXACT);
7190075Sobrien	testall(-0.5, -1, FE_INEXACT);
7290075Sobrien
7390075Sobrien	ATF_REQUIRE_EQ(0, fesetround(FE_TONEAREST));
7490075Sobrien	testall(0.0, 0, 0);
7590075Sobrien	testall(0.25, 0, FE_INEXACT);
7690075Sobrien	testall(0.5, 0, FE_INEXACT);
7790075Sobrien	testall(-2.5, -2, FE_INEXACT);
7890075Sobrien	testall(1.0, 1, 0);
7990075Sobrien	testall(0x12345000p0, 0x12345000, 0);
8090075Sobrien	testall(0x1234.fp0, 0x1235, FE_INEXACT);
8190075Sobrien	testall(INFINITY, IGNORE, FE_INVALID);
8290075Sobrien	testall(NAN, IGNORE, FE_INVALID);
8390075Sobrien
8490075Sobrien#if (LONG_MAX == 0x7fffffffl)
8590075Sobrien	ATF_REQUIRE_EQ(0, fesetround(FE_UPWARD));
86	test(lrint, 0x7fffffff.8p0, IGNORE, FE_INVALID);
87	test(lrint, -0x80000000.4p0, (long)-0x80000000l, FE_INEXACT);
88
89	ATF_REQUIRE_EQ(0, fesetround(FE_DOWNWARD));
90	test(lrint, -0x80000000.8p0, IGNORE, FE_INVALID);
91	test(lrint, 0x80000000.0p0, IGNORE, FE_INVALID);
92	test(lrint, 0x7fffffff.4p0, 0x7fffffffl, FE_INEXACT);
93	test(lrintf, 0x80000000.0p0f, IGNORE, FE_INVALID);
94	test(lrintf, 0x7fffff80.0p0f, 0x7fffff80l, 0);
95
96	ATF_REQUIRE_EQ(0, fesetround(FE_TOWARDZERO));
97	test(lrint, 0x7fffffff.8p0,  0x7fffffffl, FE_INEXACT);
98	test(lrint, -0x80000000.8p0, -0x80000000l, FE_INEXACT);
99	test(lrint, 0x80000000.0p0, IGNORE, FE_INVALID);
100	test(lrintf, 0x80000000.0p0f, IGNORE, FE_INVALID);
101	test(lrintf, 0x7fffff80.0p0f, 0x7fffff80l, 0);
102#elif (LONG_MAX == 0x7fffffffffffffffll)
103	ATF_REQUIRE_EQ(0, fesetround(FE_TONEAREST));
104	test(lrint, 0x8000000000000000.0p0, IGNORE, FE_INVALID);
105	test(lrintf, 0x8000000000000000.0p0f, IGNORE, FE_INVALID);
106	test(lrint, 0x7ffffffffffffc00.0p0, 0x7ffffffffffffc00l, 0);
107	test(lrintf, 0x7fffff8000000000.0p0f, 0x7fffff8000000000l, 0);
108	test(lrint, -0x8000000000000800.0p0, IGNORE, FE_INVALID);
109	test(lrintf, -0x8000010000000000.0p0f, IGNORE, FE_INVALID);
110	test(lrint, -0x8000000000000000.0p0, (long long)-0x8000000000000000ul, 0);
111	test(lrintf, -0x8000000000000000.0p0f, (long long)-0x8000000000000000ul, 0);
112#else
113#error "Unsupported long size"
114#endif
115
116#if (LLONG_MAX == 0x7fffffffffffffffLL)
117	ATF_REQUIRE_EQ(0, fesetround(FE_TONEAREST));
118	test(llrint, 0x8000000000000000.0p0, IGNORE, FE_INVALID);
119	test(llrintf, 0x8000000000000000.0p0f, IGNORE, FE_INVALID);
120	test(llrint, 0x7ffffffffffffc00.0p0, 0x7ffffffffffffc00ll, 0);
121	test(llrintf, 0x7fffff8000000000.0p0f, 0x7fffff8000000000ll, 0);
122	test(llrint, -0x8000000000000800.0p0, IGNORE, FE_INVALID);
123	test(llrintf, -0x8000010000000000.0p0f, IGNORE, FE_INVALID);
124	test(llrint, -0x8000000000000000.0p0, (long long)-0x8000000000000000ull, 0);
125	test(llrintf, -0x8000000000000000.0p0f, (long long)-0x8000000000000000ull, 0);
126#else
127#error "Unsupported long long size"
128#endif
129}
130
131ATF_TC_WITHOUT_HEAD(lrint);
132ATF_TC_BODY(lrint, tc)
133{
134	run_tests();
135#ifdef	__i386__
136	fpsetprec(FP_PE);
137	run_tests();
138#endif
139}
140
141ATF_TP_ADD_TCS(tp)
142{
143    ATF_TP_ADD_TC(tp, lrint);
144    return (atf_no_error());
145}
146