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