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