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 
TEST(Numeric,Ceiling)21 TEST(Numeric, Ceiling) {
22   EXPECT_EQ(RTNAME(Ceiling4_4)(Real<4>{3.7}), 4);
23   EXPECT_EQ(RTNAME(Ceiling8_8)(Real<8>{-3.7}), -3);
24   EXPECT_EQ(RTNAME(Ceiling4_1)(Real<4>{0}), 0);
25 }
26 
TEST(Numeric,Floor)27 TEST(Numeric, Floor) {
28   EXPECT_EQ(RTNAME(Floor4_4)(Real<4>{3.7}), 3);
29   EXPECT_EQ(RTNAME(Floor8_8)(Real<8>{-3.7}), -4);
30   EXPECT_EQ(RTNAME(Floor4_1)(Real<4>{0}), 0);
31 }
32 
TEST(Numeric,Exponent)33 TEST(Numeric, Exponent) {
34   EXPECT_EQ(RTNAME(Exponent4_4)(Real<4>{0}), 0);
35   EXPECT_EQ(RTNAME(Exponent4_8)(Real<4>{1.0}), 1);
36   EXPECT_EQ(RTNAME(Exponent8_4)(Real<8>{4.1}), 3);
37   EXPECT_EQ(RTNAME(Exponent8_8)(std::numeric_limits<Real<8>>::infinity()),
38       std::numeric_limits<Int<8>>::max());
39   EXPECT_EQ(RTNAME(Exponent8_8)(std::numeric_limits<Real<8>>::quiet_NaN()),
40       std::numeric_limits<Int<8>>::max());
41 }
42 
TEST(Numeric,Fraction)43 TEST(Numeric, Fraction) {
44   EXPECT_EQ(RTNAME(Fraction4)(Real<4>{0}), 0);
45   EXPECT_EQ(RTNAME(Fraction8)(Real<8>{3.0}), 0.75);
46   EXPECT_TRUE(
47       std::isnan(RTNAME(Fraction4)(std::numeric_limits<Real<4>>::infinity())));
48   EXPECT_TRUE(
49       std::isnan(RTNAME(Fraction8)(std::numeric_limits<Real<8>>::quiet_NaN())));
50 }
51 
TEST(Numeric,IsNaN)52 TEST(Numeric, IsNaN) {
53   EXPECT_FALSE(RTNAME(IsNaN4)(Real<4>{0}));
54   EXPECT_FALSE(RTNAME(IsNaN8)(std::numeric_limits<Real<8>>::infinity()));
55   EXPECT_TRUE(RTNAME(IsNaN8)(std::numeric_limits<Real<8>>::quiet_NaN()));
56 }
57 
TEST(Numeric,Mod)58 TEST(Numeric, Mod) {
59   EXPECT_EQ(RTNAME(ModInteger1)(Int<1>{8}, Int<1>(5)), 3);
60   EXPECT_EQ(RTNAME(ModInteger4)(Int<4>{-8}, Int<4>(5)), -3);
61   EXPECT_EQ(RTNAME(ModInteger2)(Int<2>{8}, Int<2>(-5)), 3);
62   EXPECT_EQ(RTNAME(ModInteger8)(Int<8>{-8}, Int<8>(-5)), -3);
63   EXPECT_EQ(RTNAME(ModReal4)(Real<4>{8.0}, Real<4>(5.0)), 3.0);
64   EXPECT_EQ(RTNAME(ModReal4)(Real<4>{-8.0}, Real<4>(5.0)), -3.0);
65   EXPECT_EQ(RTNAME(ModReal8)(Real<8>{8.0}, Real<8>(-5.0)), 3.0);
66   EXPECT_EQ(RTNAME(ModReal8)(Real<8>{-8.0}, Real<8>(-5.0)), -3.0);
67 }
68 
TEST(Numeric,Modulo)69 TEST(Numeric, Modulo) {
70   EXPECT_EQ(RTNAME(ModuloInteger1)(Int<1>{8}, Int<1>(5)), 3);
71   EXPECT_EQ(RTNAME(ModuloInteger4)(Int<4>{-8}, Int<4>(5)), 2);
72   EXPECT_EQ(RTNAME(ModuloInteger2)(Int<2>{8}, Int<2>(-5)), -2);
73   EXPECT_EQ(RTNAME(ModuloInteger8)(Int<8>{-8}, Int<8>(-5)), -3);
74   EXPECT_EQ(RTNAME(ModuloReal4)(Real<4>{8.0}, Real<4>(5.0)), 3.0);
75   EXPECT_EQ(RTNAME(ModuloReal4)(Real<4>{-8.0}, Real<4>(5.0)), 2.0);
76   EXPECT_EQ(RTNAME(ModuloReal8)(Real<8>{8.0}, Real<8>(-5.0)), -2.0);
77   EXPECT_EQ(RTNAME(ModuloReal8)(Real<8>{-8.0}, Real<8>(-5.0)), -3.0);
78 }
79 
TEST(Numeric,Nearest)80 TEST(Numeric, Nearest) {
81   EXPECT_EQ(RTNAME(Nearest4)(Real<4>{0}, true),
82       std::numeric_limits<Real<4>>::denorm_min());
83   EXPECT_EQ(RTNAME(Nearest4)(Real<4>{3.0}, true),
84       Real<4>{3.0} + std::ldexp(Real<4>{1.0}, -22));
85   EXPECT_EQ(RTNAME(Nearest8)(Real<8>{1.0}, true),
86       Real<8>{1.0} + std::ldexp(Real<8>{1.0}, -52));
87   EXPECT_EQ(RTNAME(Nearest8)(Real<8>{1.0}, false),
88       Real<8>{1.0} - std::ldexp(Real<8>{1.0}, -52));
89 }
90 
TEST(Numeric,Nint)91 TEST(Numeric, Nint) {
92   EXPECT_EQ(RTNAME(Nint4_4)(Real<4>{2.783}), 3);
93   EXPECT_EQ(RTNAME(Nint8_4)(Real<8>{-2.783}), -3);
94   EXPECT_EQ(RTNAME(Nint4_4)(Real<4>{2.5}), 3);
95   EXPECT_EQ(RTNAME(Nint8_4)(Real<8>{-2.5}), -3);
96   EXPECT_EQ(RTNAME(Nint8_8)(Real<8>{0}), 0);
97 }
98 
TEST(Numeric,RRSpacing)99 TEST(Numeric, RRSpacing) {
100   EXPECT_EQ(RTNAME(RRSpacing8)(Real<8>{0}), 0);
101   EXPECT_EQ(RTNAME(RRSpacing4)(Real<4>{-3.0}), 0.75 * (1 << 24));
102   EXPECT_EQ(RTNAME(RRSpacing8)(Real<8>{-3.0}), 0.75 * (std::int64_t{1} << 53));
103   EXPECT_TRUE(
104       std::isnan(RTNAME(RRSpacing4)(std::numeric_limits<Real<4>>::infinity())));
105   EXPECT_TRUE(std::isnan(
106       RTNAME(RRSpacing8)(std::numeric_limits<Real<8>>::quiet_NaN())));
107 }
108 
TEST(Numeric,Scale)109 TEST(Numeric, Scale) {
110   EXPECT_EQ(RTNAME(Scale4)(Real<4>{0}, 0), 0);
111   EXPECT_EQ(RTNAME(Scale4)(Real<4>{1.0}, 0), 1.0);
112   EXPECT_EQ(RTNAME(Scale4)(Real<4>{1.0}, 1), 2.0);
113   EXPECT_EQ(RTNAME(Scale4)(Real<4>{1.0}, -1), 0.5);
114   EXPECT_TRUE(
115       std::isinf(RTNAME(Scale4)(std::numeric_limits<Real<4>>::infinity(), 1)));
116   EXPECT_TRUE(
117       std::isnan(RTNAME(Scale8)(std::numeric_limits<Real<8>>::quiet_NaN(), 1)));
118 }
119 
TEST(Numeric,SetExponent)120 TEST(Numeric, SetExponent) {
121   EXPECT_EQ(RTNAME(SetExponent4)(Real<4>{0}, 0), 0);
122   EXPECT_EQ(RTNAME(SetExponent8)(Real<8>{0}, 666), 0);
123   EXPECT_EQ(RTNAME(SetExponent8)(Real<8>{3.0}, 0), 0.75);
124   EXPECT_EQ(RTNAME(SetExponent4)(Real<4>{1.0}, 0), 0.5);
125   EXPECT_EQ(RTNAME(SetExponent4)(Real<4>{1.0}, 1), 1.0);
126   EXPECT_EQ(RTNAME(SetExponent4)(Real<4>{1.0}, -1), 0.25);
127   EXPECT_TRUE(std::isnan(
128       RTNAME(SetExponent4)(std::numeric_limits<Real<4>>::infinity(), 1)));
129   EXPECT_TRUE(std::isnan(
130       RTNAME(SetExponent8)(std::numeric_limits<Real<8>>::quiet_NaN(), 1)));
131 }
132 
TEST(Numeric,SelectedIntKind)133 TEST(Numeric, SelectedIntKind) {
134   std::int8_t r0 = 1;
135   std::int16_t r1 = 3;
136   std::int32_t r2 = 8;
137   std::int64_t r3 = 10;
138   std::int32_t r4 = -10;
139   std::int32_t r5 = 100;
140   EXPECT_EQ(RTNAME(SelectedIntKind)(__FILE__, __LINE__, &r0, 1), 1);
141   EXPECT_EQ(RTNAME(SelectedIntKind)(__FILE__, __LINE__, &r1, 2), 2);
142   EXPECT_EQ(RTNAME(SelectedIntKind)(__FILE__, __LINE__, &r2, 4), 4);
143   EXPECT_EQ(RTNAME(SelectedIntKind)(__FILE__, __LINE__, &r3, 8), 8);
144   EXPECT_EQ(RTNAME(SelectedIntKind)(__FILE__, __LINE__, &r4, 4), 1);
145   EXPECT_EQ(RTNAME(SelectedIntKind)(__FILE__, __LINE__, &r5, 4), -1);
146 }
147 
TEST(Numeric,SelectedRealKind)148 TEST(Numeric, SelectedRealKind) {
149   std::int8_t p_s = 1;
150   std::int16_t p[11] = {-10, 1, 1, 4, 50, 1, 1, 4, 1, 1, 50};
151   std::int32_t r[11] = {-1, 1, 1, 1, 2, 1, 20, 20, 100, 5000, 5000};
152   std::int64_t d[11] = {2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2};
153   EXPECT_EQ(RTNAME(SelectedRealKind)(
154                 __FILE__, __LINE__, &p[0], 2, &r[0], 4, &d[0], 8),
155       2);
156   EXPECT_EQ(RTNAME(SelectedRealKind)(
157                 __FILE__, __LINE__, &p[1], 2, &r[1], 4, &d[1], 8),
158       -5);
159   EXPECT_EQ(RTNAME(SelectedRealKind)(
160                 __FILE__, __LINE__, &p[2], 2, &r[2], 4, &d[2], 8),
161       2);
162   EXPECT_EQ(RTNAME(SelectedRealKind)(
163                 __FILE__, __LINE__, &p[3], 2, &r[3], 4, &d[3], 8),
164       4);
165   EXPECT_EQ(RTNAME(SelectedRealKind)(
166                 __FILE__, __LINE__, &p[4], 2, &r[4], 4, &d[4], 8),
167       -1);
168   EXPECT_EQ(RTNAME(SelectedRealKind)(
169                 __FILE__, __LINE__, &p[5], 2, &r[5], 4, &d[5], 8),
170       2);
171   EXPECT_EQ(RTNAME(SelectedRealKind)(
172                 __FILE__, __LINE__, &p[6], 2, &r[6], 4, &d[6], 8),
173       3);
174   EXPECT_EQ(RTNAME(SelectedRealKind)(
175                 __FILE__, __LINE__, &p[7], 2, &r[7], 4, &d[7], 8),
176       4);
177   EXPECT_EQ(RTNAME(SelectedRealKind)(
178                 __FILE__, __LINE__, &p[8], 2, &r[8], 4, &d[8], 8),
179       8);
180   EXPECT_EQ(RTNAME(SelectedRealKind)(
181                 __FILE__, __LINE__, &p[9], 2, &r[9], 4, &d[9], 8),
182       -2);
183   EXPECT_EQ(RTNAME(SelectedRealKind)(
184                 __FILE__, __LINE__, &p[10], 2, &r[10], 4, &d[10], 8),
185       -3);
186   EXPECT_EQ(
187       RTNAME(SelectedRealKind)(__FILE__, __LINE__, &p_s, 1, &r[0], 4, &d[0], 8),
188       2);
189   EXPECT_EQ(RTNAME(SelectedRealKind)(
190                 __FILE__, __LINE__, nullptr, 0, &r[0], 4, &d[0], 8),
191       2);
192   EXPECT_EQ(RTNAME(SelectedRealKind)(
193                 __FILE__, __LINE__, &p[0], 2, nullptr, 0, &d[0], 8),
194       2);
195   EXPECT_EQ(RTNAME(SelectedRealKind)(
196                 __FILE__, __LINE__, &p[0], 2, &r[0], 4, nullptr, 0),
197       2);
198 }
199 
TEST(Numeric,Spacing)200 TEST(Numeric, Spacing) {
201   EXPECT_EQ(RTNAME(Spacing8)(Real<8>{0}), std::numeric_limits<Real<8>>::min());
202   EXPECT_EQ(RTNAME(Spacing4)(Real<4>{3.0}), std::ldexp(Real<4>{1.0}, -22));
203   EXPECT_TRUE(
204       std::isnan(RTNAME(Spacing4)(std::numeric_limits<Real<4>>::infinity())));
205   EXPECT_TRUE(
206       std::isnan(RTNAME(Spacing8)(std::numeric_limits<Real<8>>::quiet_NaN())));
207 }
208