1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
//===-- flang/unittests/RuntimeGTest/Numeric.cpp ----------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "../../runtime/numeric.h"
#include "gtest/gtest.h"
#include <cmath>
#include <limits>
using namespace Fortran::runtime;
using Fortran::common::TypeCategory;
template <int KIND> using Int = CppTypeFor<TypeCategory::Integer, KIND>;
template <int KIND> using Real = CppTypeFor<TypeCategory::Real, KIND>;
// Simple tests of numeric intrinsic functions using examples from Fortran 2018
TEST(Numeric, Aint) {
EXPECT_EQ(RTNAME(Aint4_4)(Real<4>{3.7}), 3.0);
EXPECT_EQ(RTNAME(Aint8_4)(Real<8>{-3.7}), -3.0);
EXPECT_EQ(RTNAME(Aint8_8)(Real<8>{0}), 0.0);
EXPECT_EQ(RTNAME(Aint4_4)(std::numeric_limits<Real<4>>::infinity()),
std::numeric_limits<Real<4>>::infinity());
EXPECT_TRUE(
std::isnan(RTNAME(Aint8_8)(std::numeric_limits<Real<8>>::quiet_NaN())));
}
TEST(Numeric, Anint) {
EXPECT_EQ(RTNAME(Anint4_4)(Real<4>{2.783}), 3.0);
EXPECT_EQ(RTNAME(Anint8_4)(Real<8>{-2.783}), -3.0);
EXPECT_EQ(RTNAME(Anint4_4)(Real<4>{2.5}), 3.0);
EXPECT_EQ(RTNAME(Anint8_4)(Real<8>{-2.5}), -3.0);
EXPECT_EQ(RTNAME(Anint8_8)(Real<8>{0}), 0.0);
EXPECT_EQ(RTNAME(Anint4_4)(std::numeric_limits<Real<4>>::infinity()),
std::numeric_limits<Real<4>>::infinity());
EXPECT_TRUE(
std::isnan(RTNAME(Aint8_8)(std::numeric_limits<Real<8>>::quiet_NaN())));
}
TEST(Numeric, Ceiling) {
EXPECT_EQ(RTNAME(Ceiling4_4)(Real<4>{3.7}), 4);
EXPECT_EQ(RTNAME(Ceiling8_8)(Real<8>{-3.7}), -3);
EXPECT_EQ(RTNAME(Ceiling4_1)(Real<4>{0}), 0);
EXPECT_EQ(RTNAME(Ceiling4_4)(std::numeric_limits<Real<4>>::infinity()),
std::numeric_limits<Int<4>>::min());
EXPECT_EQ(RTNAME(Ceiling4_4)(std::numeric_limits<Real<4>>::quiet_NaN()),
std::numeric_limits<Int<4>>::min());
}
TEST(Numeric, Floor) {
EXPECT_EQ(RTNAME(Floor4_4)(Real<4>{3.7}), 3);
EXPECT_EQ(RTNAME(Floor8_8)(Real<8>{-3.7}), -4);
EXPECT_EQ(RTNAME(Floor4_1)(Real<4>{0}), 0);
EXPECT_EQ(RTNAME(Floor4_4)(std::numeric_limits<Real<4>>::infinity()),
std::numeric_limits<Int<4>>::min());
EXPECT_EQ(RTNAME(Floor4_4)(std::numeric_limits<Real<4>>::quiet_NaN()),
std::numeric_limits<Int<4>>::min());
}
TEST(Numeric, Exponent) {
EXPECT_EQ(RTNAME(Exponent4_4)(Real<4>{0}), 0);
EXPECT_EQ(RTNAME(Exponent4_8)(Real<4>{1.0}), 1);
EXPECT_EQ(RTNAME(Exponent8_4)(Real<8>{4.1}), 3);
EXPECT_EQ(RTNAME(Exponent8_8)(std::numeric_limits<Real<8>>::infinity()),
std::numeric_limits<Int<8>>::max());
EXPECT_EQ(RTNAME(Exponent8_8)(std::numeric_limits<Real<8>>::quiet_NaN()),
std::numeric_limits<Int<8>>::max());
}
TEST(Numeric, Fraction) {
EXPECT_EQ(RTNAME(Fraction4)(Real<4>{0}), 0);
EXPECT_EQ(RTNAME(Fraction8)(Real<8>{3.0}), 0.75);
EXPECT_TRUE(
std::isnan(RTNAME(Fraction4)(std::numeric_limits<Real<4>>::infinity())));
EXPECT_TRUE(
std::isnan(RTNAME(Fraction8)(std::numeric_limits<Real<8>>::quiet_NaN())));
}
TEST(Numeric, Mod) {
EXPECT_EQ(RTNAME(ModInteger1)(Int<1>{8}, Int<1>(5)), 3);
EXPECT_EQ(RTNAME(ModInteger4)(Int<4>{-8}, Int<4>(5)), -3);
EXPECT_EQ(RTNAME(ModInteger2)(Int<2>{8}, Int<2>(-5)), 3);
EXPECT_EQ(RTNAME(ModInteger8)(Int<8>{-8}, Int<8>(-5)), -3);
EXPECT_EQ(RTNAME(ModReal4)(Real<4>{8.0}, Real<4>(5.0)), 3.0);
EXPECT_EQ(RTNAME(ModReal4)(Real<4>{-8.0}, Real<4>(5.0)), -3.0);
EXPECT_EQ(RTNAME(ModReal8)(Real<8>{8.0}, Real<8>(-5.0)), 3.0);
EXPECT_EQ(RTNAME(ModReal8)(Real<8>{-8.0}, Real<8>(-5.0)), -3.0);
}
TEST(Numeric, Modulo) {
EXPECT_EQ(RTNAME(ModuloInteger1)(Int<1>{8}, Int<1>(5)), 3);
EXPECT_EQ(RTNAME(ModuloInteger4)(Int<4>{-8}, Int<4>(5)), 2);
EXPECT_EQ(RTNAME(ModuloInteger2)(Int<2>{8}, Int<2>(-5)), -2);
EXPECT_EQ(RTNAME(ModuloInteger8)(Int<8>{-8}, Int<8>(-5)), -3);
EXPECT_EQ(RTNAME(ModuloReal4)(Real<4>{8.0}, Real<4>(5.0)), 3.0);
EXPECT_EQ(RTNAME(ModuloReal4)(Real<4>{-8.0}, Real<4>(5.0)), 2.0);
EXPECT_EQ(RTNAME(ModuloReal8)(Real<8>{8.0}, Real<8>(-5.0)), -2.0);
EXPECT_EQ(RTNAME(ModuloReal8)(Real<8>{-8.0}, Real<8>(-5.0)), -3.0);
}
TEST(Numeric, Nearest) {
EXPECT_EQ(RTNAME(Nearest4)(Real<4>{0}, true),
std::numeric_limits<Real<4>>::denorm_min());
EXPECT_EQ(RTNAME(Nearest4)(Real<4>{3.0}, true),
Real<4>{3.0} + std::ldexp(Real<4>{1.0}, -22));
EXPECT_EQ(RTNAME(Nearest8)(Real<8>{1.0}, true),
Real<8>{1.0} + std::ldexp(Real<8>{1.0}, -52));
EXPECT_EQ(RTNAME(Nearest8)(Real<8>{1.0}, false),
Real<8>{1.0} - std::ldexp(Real<8>{1.0}, -52));
}
TEST(Numeric, Nint) {
EXPECT_EQ(RTNAME(Nint4_4)(Real<4>{2.783}), 3);
EXPECT_EQ(RTNAME(Nint8_4)(Real<8>{-2.783}), -3);
EXPECT_EQ(RTNAME(Nint4_4)(Real<4>{2.5}), 3);
EXPECT_EQ(RTNAME(Nint8_4)(Real<8>{-2.5}), -3);
EXPECT_EQ(RTNAME(Nint8_8)(Real<8>{0}), 0);
auto nintInf{RTNAME(Nint4_4)(std::numeric_limits<Real<4>>::infinity())};
EXPECT_TRUE(nintInf == std::numeric_limits<Int<4>>::min() ||
nintInf == std::numeric_limits<Int<4>>::max());
auto nintNaN{RTNAME(Nint4_4)(std::numeric_limits<Real<4>>::quiet_NaN())};
EXPECT_TRUE(nintNaN == std::numeric_limits<Int<4>>::min() ||
nintNaN == std::numeric_limits<Int<4>>::max());
}
TEST(Numeric, RRSpacing) {
EXPECT_EQ(RTNAME(RRSpacing8)(Real<8>{0}), 0);
EXPECT_EQ(RTNAME(RRSpacing4)(Real<4>{-3.0}), 0.75 * (1 << 24));
EXPECT_EQ(RTNAME(RRSpacing8)(Real<8>{-3.0}), 0.75 * (std::int64_t{1} << 53));
EXPECT_TRUE(
std::isnan(RTNAME(RRSpacing4)(std::numeric_limits<Real<4>>::infinity())));
EXPECT_TRUE(std::isnan(
RTNAME(RRSpacing8)(std::numeric_limits<Real<8>>::quiet_NaN())));
}
TEST(Numeric, Scale) {
EXPECT_EQ(RTNAME(Scale4)(Real<4>{0}, 0), 0);
EXPECT_EQ(RTNAME(Scale4)(Real<4>{1.0}, 0), 1.0);
EXPECT_EQ(RTNAME(Scale4)(Real<4>{1.0}, 1), 2.0);
EXPECT_EQ(RTNAME(Scale4)(Real<4>{1.0}, -1), 0.5);
EXPECT_TRUE(
std::isinf(RTNAME(Scale4)(std::numeric_limits<Real<4>>::infinity(), 1)));
EXPECT_TRUE(
std::isnan(RTNAME(Scale8)(std::numeric_limits<Real<8>>::quiet_NaN(), 1)));
}
TEST(Numeric, SetExponent) {
EXPECT_EQ(RTNAME(SetExponent4)(Real<4>{0}, 0), 0);
EXPECT_EQ(RTNAME(SetExponent8)(Real<8>{0}, 666), 0);
EXPECT_EQ(RTNAME(SetExponent8)(Real<8>{3.0}, 0), 1.5);
EXPECT_EQ(RTNAME(SetExponent4)(Real<4>{1.0}, 0), 1.0);
EXPECT_EQ(RTNAME(SetExponent4)(Real<4>{1.0}, 1), 2.0);
EXPECT_EQ(RTNAME(SetExponent4)(Real<4>{1.0}, -1), 0.5);
EXPECT_TRUE(std::isnan(
RTNAME(SetExponent4)(std::numeric_limits<Real<4>>::infinity(), 1)));
EXPECT_TRUE(std::isnan(
RTNAME(SetExponent8)(std::numeric_limits<Real<8>>::quiet_NaN(), 1)));
}
TEST(Numeric, Spacing) {
EXPECT_EQ(RTNAME(Spacing8)(Real<8>{0}), std::numeric_limits<Real<8>>::min());
EXPECT_EQ(RTNAME(Spacing4)(Real<4>{3.0}), std::ldexp(Real<4>{1.0}, -22));
EXPECT_TRUE(
std::isnan(RTNAME(Spacing4)(std::numeric_limits<Real<4>>::infinity())));
EXPECT_TRUE(
std::isnan(RTNAME(Spacing8)(std::numeric_limits<Real<8>>::quiet_NaN())));
}
|