1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9// __clamp_to_integral<IntT>(RealT)
10
11// Test the conversion function that truncates floating point types to the
12// closest representable value for the specified integer type, or
13// numeric_limits<IntT>::max()/min() if the value isn't representable.
14
15#include <cassert>
16#include <cmath>
17#include <limits>
18#include <random> // for __clamp_to_integral
19
20template <class IntT>
21void test() {
22 typedef std::numeric_limits<IntT> Lim;
23 const bool MaxIsRepresentable = sizeof(IntT) < 8;
24 const bool IsSigned = std::is_signed<IntT>::value;
25 struct TestCase {
26 double Input;
27 IntT Expect;
28 bool IsRepresentable;
29 } TestCases[] = {
30 {0, 0, true},
31 {1, 1, true},
32 {IsSigned ? static_cast<IntT>(-1) : 0,
33 IsSigned ? static_cast<IntT>(-1) : 0, true},
34 {Lim::lowest(), Lim::lowest(), true},
35 {static_cast<double>(Lim::max()), Lim::max(), MaxIsRepresentable},
36 {static_cast<double>(Lim::max()) + 1, Lim::max(), false},
37 {static_cast<double>(Lim::max()) + 1024, Lim::max(), false},
38 {nextafter(x: static_cast<double>(Lim::max()), INFINITY), Lim::max(), false},
39 };
40 for (TestCase TC : TestCases) {
41 auto res = std::__clamp_to_integral<IntT>(TC.Input);
42 assert(res == TC.Expect);
43 if (TC.IsRepresentable) {
44 auto other = static_cast<IntT>(std::trunc(TC.Input));
45 assert(res == other);
46 } else
47 assert(res == Lim::min() || res == Lim::max());
48 }
49}
50
51template <class IntT>
52void test_float() {
53 typedef std::numeric_limits<IntT> Lim;
54 const bool MaxIsRepresentable = sizeof(IntT) < 4;
55 ((void)MaxIsRepresentable);
56 const bool IsSigned = std::is_signed<IntT>::value;
57 struct TestCase {
58 float Input;
59 IntT Expect;
60 bool IsRepresentable;
61 } TestCases[] = {
62 {0, 0, true},
63 {1, 1, true},
64 {IsSigned ? static_cast<IntT>(-1) : 0,
65 IsSigned ? static_cast<IntT>(-1) : 0, true},
66 {Lim::lowest(), Lim::lowest(), true},
67 {static_cast<float>(Lim::max()), Lim::max(), MaxIsRepresentable },
68 {nextafter(x: static_cast<float>(Lim::max()), INFINITY), Lim::max(), false},
69 };
70 for (TestCase TC : TestCases) {
71 auto res = std::__clamp_to_integral<IntT>(TC.Input);
72 assert(res == TC.Expect);
73 if (TC.IsRepresentable) {
74 auto other = static_cast<IntT>(std::trunc(TC.Input));
75 assert(res == other);
76 } else
77 assert(res == Lim::min() || res == Lim::max());
78 }
79}
80
81int main(int, char**) {
82 test<short>();
83 test<unsigned short>();
84 test<int>();
85 test<unsigned>();
86 test<long long>();
87 test<unsigned long long>();
88 test_float<short>();
89 test_float<int>();
90 test_float<long long>();
91 return 0;
92}
93

source code of libcxx/test/libcxx/numerics/clamp_to_integral.pass.cpp