Index: flang/include/flang/Optimizer/Builder/Runtime/Numeric.h =================================================================== --- flang/include/flang/Optimizer/Builder/Runtime/Numeric.h +++ flang/include/flang/Optimizer/Builder/Runtime/Numeric.h @@ -38,6 +38,11 @@ mlir::Value genScale(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value x, mlir::Value i); +/// Generate call to Selected_real_kind intrinsic runtime routine. +mlir::Value genSelectedRealKind(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value precision, mlir::Value range, + mlir::Value radix); + /// Generate call to Set_exponent intrinsic runtime routine. mlir::Value genSetExponent(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value x, mlir::Value i); Index: flang/include/flang/Runtime/numeric.h =================================================================== --- flang/include/flang/Runtime/numeric.h +++ flang/include/flang/Runtime/numeric.h @@ -439,6 +439,36 @@ CppTypeFor, std::int64_t); #endif +// SELECTED_REAL_KIND +CppTypeFor RTNAME(SelectedRealKind8_8_8)( + CppTypeFor, CppTypeFor, + CppTypeFor); +#ifdef __SIZEOF_INT128__ +CppTypeFor RTNAME(SelectedRealKind16_8_8)( + CppTypeFor, CppTypeFor, + CppTypeFor); +CppTypeFor RTNAME(SelectedRealKind8_16_8)( + CppTypeFor, CppTypeFor, + CppTypeFor); +CppTypeFor RTNAME(SelectedRealKind16_16_8)( + CppTypeFor, + CppTypeFor, + CppTypeFor); +CppTypeFor RTNAME(SelectedRealKind8_8_16)( + CppTypeFor, CppTypeFor, + CppTypeFor); +CppTypeFor RTNAME(SelectedRealKind16_8_16)( + CppTypeFor, CppTypeFor, + CppTypeFor); +CppTypeFor RTNAME(SelectedRealKind8_16_16)( + CppTypeFor, CppTypeFor, + CppTypeFor); +CppTypeFor RTNAME(SelectedRealKind16_16_16)( + CppTypeFor, + CppTypeFor, + CppTypeFor); +#endif + // SPACING CppTypeFor RTNAME(Spacing4)( CppTypeFor); Index: flang/lib/Lower/IntrinsicCall.cpp =================================================================== --- flang/lib/Lower/IntrinsicCall.cpp +++ flang/lib/Lower/IntrinsicCall.cpp @@ -531,6 +531,7 @@ llvm::ArrayRef args); mlir::Value genScale(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genScan(mlir::Type, llvm::ArrayRef); + mlir::Value genSelectedRealKind(mlir::Type, llvm::ArrayRef); mlir::Value genSetExponent(mlir::Type resultType, llvm::ArrayRef args); mlir::Value genSign(mlir::Type, llvm::ArrayRef); @@ -890,6 +891,12 @@ {"back", asValue, handleDynamicOptional}, {"kind", asValue}}}, /*isElemental=*/true}, + {"selected_real_kind", + &I::genSelectedRealKind, + {{{"precision", asValue, handleDynamicOptional}, + {"range", asValue, handleDynamicOptional}, + {"radix", asValue, handleDynamicOptional}}}, + /*isElemental=*/false}, {"set_exponent", &I::genSetExponent}, {"sign", &I::genSign}, {"size", @@ -3623,6 +3630,35 @@ return readAndAddCleanUp(resultMutableBox, resultType, "SCAN"); } +// SELECTED_INT_KIND +mlir::Value +IntrinsicLibrary::genSelectedRealKind(mlir::Type resultType, + llvm::ArrayRef args) { + assert(args.size() == 3); + + // Handle optional precision(P) argument + mlir::Value precision = + isStaticallyAbsent(args[0]) + ? builder.createIntegerConstant(loc, builder.getI1Type(), 0) + : fir::getBase(args[0]); + + // Handle optional range(R) argument + mlir::Value range = + isStaticallyAbsent(args[0]) + ? builder.createIntegerConstant(loc, builder.getI1Type(), 0) + : fir::getBase(args[0]); + + // Handle optional radix(RADIX) argument + mlir::Value radix = + isStaticallyAbsent(args[0]) + ? builder.createIntegerConstant(loc, builder.getI1Type(), 2) + : fir::getBase(args[0]); + + return builder.createConvert( + loc, resultType, + fir::runtime::genSelectedRealKind(builder, loc, precision, range, radix)); +} + // SET_EXPONENT mlir::Value IntrinsicLibrary::genSetExponent(mlir::Type resultType, llvm::ArrayRef args) { Index: flang/lib/Optimizer/Builder/Runtime/Numeric.cpp =================================================================== --- flang/lib/Optimizer/Builder/Runtime/Numeric.cpp +++ flang/lib/Optimizer/Builder/Runtime/Numeric.cpp @@ -160,6 +160,104 @@ } }; +/// Placeholder for integer*16 version of SelectedRealKind Intrinsic +struct ForcedSelectedRealKind16_8_8 { + static constexpr const char *name = + ExpandAndQuoteKey(RTNAME(SelectedRealKind16_8_8)); + static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { + return [](mlir::MLIRContext *ctx) { + auto int128Ty = mlir::IntegerType::get(ctx, 128); + auto int64Ty = mlir::IntegerType::get(ctx, 64); + auto int32Ty = mlir::IntegerType::get(ctx, 32); + return mlir::FunctionType::get(ctx, {int128Ty, int64Ty, int64Ty}, + {int32Ty}); + }; + } +}; + +struct ForcedSelectedRealKind8_16_8 { + static constexpr const char *name = + ExpandAndQuoteKey(RTNAME(SelectedRealKind8_16_8)); + static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { + return [](mlir::MLIRContext *ctx) { + auto int128Ty = mlir::IntegerType::get(ctx, 128); + auto int64Ty = mlir::IntegerType::get(ctx, 64); + auto int32Ty = mlir::IntegerType::get(ctx, 32); + return mlir::FunctionType::get(ctx, {int64Ty, int128Ty, int64Ty}, + {int32Ty}); + }; + } +}; + +struct ForcedSelectedRealKind16_16_8 { + static constexpr const char *name = + ExpandAndQuoteKey(RTNAME(SelectedRealKind16_16_8)); + static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { + return [](mlir::MLIRContext *ctx) { + auto int128Ty = mlir::IntegerType::get(ctx, 128); + auto int64Ty = mlir::IntegerType::get(ctx, 64); + auto int32Ty = mlir::IntegerType::get(ctx, 32); + return mlir::FunctionType::get(ctx, {int128Ty, int128Ty, int64Ty}, + {int32Ty}); + }; + } +}; + +struct ForcedSelectedRealKind8_8_16 { + static constexpr const char *name = + ExpandAndQuoteKey(RTNAME(SelectedRealKind8_8_16)); + static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { + return [](mlir::MLIRContext *ctx) { + auto int128Ty = mlir::IntegerType::get(ctx, 128); + auto int64Ty = mlir::IntegerType::get(ctx, 64); + auto int32Ty = mlir::IntegerType::get(ctx, 32); + return mlir::FunctionType::get(ctx, {int64Ty, int64Ty, int128Ty}, + {int32Ty}); + }; + } +}; + +struct ForcedSelectedRealKind16_8_16 { + static constexpr const char *name = + ExpandAndQuoteKey(RTNAME(SelectedRealKind16_8_16)); + static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { + return [](mlir::MLIRContext *ctx) { + auto int128Ty = mlir::IntegerType::get(ctx, 128); + auto int64Ty = mlir::IntegerType::get(ctx, 64); + auto int32Ty = mlir::IntegerType::get(ctx, 32); + return mlir::FunctionType::get(ctx, {int128Ty, int64Ty, int128Ty}, + {int32Ty}); + }; + } +}; + +struct ForcedSelectedRealKind8_16_16 { + static constexpr const char *name = + ExpandAndQuoteKey(RTNAME(SelectedRealKind8_16_16)); + static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { + return [](mlir::MLIRContext *ctx) { + auto int128Ty = mlir::IntegerType::get(ctx, 128); + auto int64Ty = mlir::IntegerType::get(ctx, 64); + auto int32Ty = mlir::IntegerType::get(ctx, 32); + return mlir::FunctionType::get(ctx, {int64Ty, int128Ty, int128Ty}, + {int32Ty}); + }; + } +}; + +struct ForcedSelectedRealKind16_16_16 { + static constexpr const char *name = + ExpandAndQuoteKey(RTNAME(SelectedRealKind16_16_16)); + static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { + return [](mlir::MLIRContext *ctx) { + auto int128Ty = mlir::IntegerType::get(ctx, 128); + auto int32Ty = mlir::IntegerType::get(ctx, 32); + return mlir::FunctionType::get(ctx, {int128Ty, int128Ty, int128Ty}, + {int32Ty}); + }; + } +}; + /// Placeholder for real*10 version of RRSpacing Intrinsic struct ForcedSetExponent10 { static constexpr const char *name = ExpandAndQuoteKey(RTNAME(SetExponent10)); @@ -360,6 +458,87 @@ return builder.create(loc, func, args).getResult(0); } +/// Generate call to Selected_real_kind intrinsic runtime routine. +mlir::Value fir::runtime::genSelectedRealKind(fir::FirOpBuilder &builder, + mlir::Location loc, + mlir::Value precision, + mlir::Value range, + mlir::Value radix) { + mlir::func::FuncOp func; + mlir::Type pTy = precision.getType(); + mlir::Type rTy = range.getType(); + mlir::Type dTy = radix.getType(); + int pKindLabel = (pTy.isInteger(8) || pTy.isInteger(16) || + pTy.isInteger(32) || pTy.isInteger(64)) + ? 0 + : (pTy.isInteger(128) ? 1 : -1); + int rKindLabel = (rTy.isInteger(8) || rTy.isInteger(16) || + rTy.isInteger(32) || rTy.isInteger(64)) + ? 0 + : (rTy.isInteger(128) ? 1 : -1); + int dKindLabel = (dTy.isInteger(8) || dTy.isInteger(16) || + dTy.isInteger(32) || dTy.isInteger(64)) + ? 0 + : (dTy.isInteger(128) ? 1 : -1); + if (pKindLabel == -1 || rKindLabel == -1 || dKindLabel == -1) + fir::emitFatalError(loc, "unsupported kind in SELECTED_REAL_KIND"); + + mlir::Value pVal = precision; + mlir::Value rVal = range; + mlir::Value dVal = radix; + mlir::Type i64Ty = mlir::IntegerType::get(builder.getContext(), 64); + if (pKindLabel == 1) + pVal = builder.createConvert(loc, i64Ty, precision); + if (rKindLabel == 1) + rVal = builder.createConvert(loc, i64Ty, range); + if (dKindLabel == 1) + dVal = builder.createConvert(loc, i64Ty, radix); + + int kindLabel = pKindLabel + rKindLabel * 2 + dKindLabel * 2 * 2; + switch (kindLabel) { + case 0: + func = fir::runtime::getRuntimeFunc( + loc, builder); + break; + case 1: + func = fir::runtime::getRuntimeFunc(loc, + builder); + break; + case 2: + func = fir::runtime::getRuntimeFunc(loc, + builder); + break; + case 3: + func = fir::runtime::getRuntimeFunc(loc, + builder); + break; + case 4: + func = fir::runtime::getRuntimeFunc(loc, + builder); + break; + case 5: + func = fir::runtime::getRuntimeFunc(loc, + builder); + break; + case 6: + func = fir::runtime::getRuntimeFunc(loc, + builder); + break; + case 7: + func = fir::runtime::getRuntimeFunc( + loc, builder); + break; + default: + fir::emitFatalError(loc, "unsupported kind in SELECTED_REAL_KIND"); + } + + auto funcTy = func.getFunctionType(); + auto args = + fir::runtime::createArguments(builder, loc, funcTy, pVal, rVal, dVal); + + return builder.create(loc, func, args).getResult(0); +} + /// Generate call to Set_exponent instrinsic runtime routine. mlir::Value fir::runtime::genSetExponent(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value x, Index: flang/runtime/numeric.cpp =================================================================== --- flang/runtime/numeric.cpp +++ flang/runtime/numeric.cpp @@ -115,6 +115,54 @@ return std::ldexp(x, p); // x*2**p } +// SELECTED_REAL_KIND (16.9.170) +template +inline CppTypeFor SelectedRealKind(P p, R r, D d) { + if (d != 2) { + return -5; + } + + int error{0}; + int kind{0}; + if (p <= 3) { + kind = 2; + } else if (p <= 6) { + kind = 4; + } else if (p <= 15) { + kind = 8; +#if LDBL_MANT_DIG == 64 + } else if (p <= 18) { + kind = 10; + } else if (p <= 33) { + kind = 16; +#elif LDBL_MANT_DIG == 113 + } else if (p <= 33) { + kind = 16; +#endif + } else { + error -= 1; + } + + if (r <= 4) { + kind = kind < 2 ? 2 : kind; + } else if (r <= 37) { + kind = kind < 3 ? 3 : kind; + } else if (r <= 307) { + kind = kind < 8 ? 8 : kind; +#if LDBL_MANT_DIG == 64 + } else if (r <= 4931) { + kind = kind < 10 ? 10 : kind; +#elif LDBL_MANT_DIG == 113 + } else if (r <= 4931) { + kind = kind < 16 ? 16 : kind; +#endif + } else { + error -= 2; + } + + return error ? error : kind; +} + // SET_EXPONENT (16.9.171) template inline T SetExponent(T x, std::int64_t p) { if (std::isnan(x)) { @@ -839,6 +887,58 @@ } #endif +// SELECTED_REAL_KIND +CppTypeFor RTNAME(SelectedRealKind8_8_8)( + CppTypeFor p, + CppTypeFor r, + CppTypeFor d) { + return SelectedRealKind(p, r, d); +} +#ifdef __SIZEOF_INT128__ +CppTypeFor RTNAME(SelectedRealKind16_8_8)( + CppTypeFor p, + CppTypeFor r, + CppTypeFor d) { + return SelectedRealKind(p, r, d); +} +CppTypeFor RTNAME(SelectedRealKind8_16_8)( + CppTypeFor p, + CppTypeFor r, + CppTypeFor d) { + return SelectedRealKind(p, r, d); +} +CppTypeFor RTNAME(SelectedRealKind16_16_8)( + CppTypeFor p, + CppTypeFor r, + CppTypeFor d) { + return SelectedRealKind(p, r, d); +} +CppTypeFor RTNAME(SelectedRealKind8_8_16)( + CppTypeFor p, + CppTypeFor r, + CppTypeFor d) { + return SelectedRealKind(p, r, d); +} +CppTypeFor RTNAME(SelectedRealKind16_8_16)( + CppTypeFor p, + CppTypeFor r, + CppTypeFor d) { + return SelectedRealKind(p, r, d); +} +CppTypeFor RTNAME(SelectedRealKind8_16_16)( + CppTypeFor p, + CppTypeFor r, + CppTypeFor d) { + return SelectedRealKind(p, r, d); +} +CppTypeFor RTNAME(SelectedRealKind16_16_16)( + CppTypeFor p, + CppTypeFor r, + CppTypeFor d) { + return SelectedRealKind(p, r, d); +} +#endif + CppTypeFor RTNAME(Spacing4)( CppTypeFor x) { return Spacing<24>(x); Index: flang/test/Lower/Intrinsics/selected_real_kind.f90 =================================================================== --- /dev/null +++ flang/test/Lower/Intrinsics/selected_real_kind.f90 @@ -0,0 +1,101 @@ +! REQUIRES: shell +! RUN: bbc -emit-fir %s -o - | FileCheck %s + +! CHECK-LABEL: func.func @_QPselected_real_kind_test1( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref {fir.bindc_name = "p"}, +! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref {fir.bindc_name = "r"}, +! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref {fir.bindc_name = "d"}) { +! CHECK: %[[VAL_3:.*]] = fir.alloca i8 {bindc_name = "res", uniq_name = "_QFselected_real_kind_test1Eres"} +! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i8) -> i64 +! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_4]] : (i8) -> i64 +! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_4]] : (i8) -> i64 +! CHECK: %[[VAL_8:.*]] = fir.call @_FortranASelectedRealKind8_8_8(%[[VAL_5]], %[[VAL_6]], %[[VAL_7]]) : (i64, i64, i64) -> i32 +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i32) -> i8 +! CHECK: fir.store %[[VAL_9]] to %[[VAL_3]] : !fir.ref +! CHECK: return +! CHECK: } + +subroutine selected_real_kind_test1(p, r, d) + integer(1) :: p, r, d, res + res = selected_real_kind(P=p, R=r, RADIX=d) +end + +! CHECK-LABEL: func.func @_QPselected_real_kind_test2( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref {fir.bindc_name = "p"}, +! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref {fir.bindc_name = "r"}, +! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref {fir.bindc_name = "d"}) { +! CHECK: %[[VAL_3:.*]] = fir.alloca i16 {bindc_name = "res", uniq_name = "_QFselected_real_kind_test2Eres"} +! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i16) -> i64 +! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_4]] : (i16) -> i64 +! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_4]] : (i16) -> i64 +! CHECK: %[[VAL_8:.*]] = fir.call @_FortranASelectedRealKind8_8_8(%[[VAL_5]], %[[VAL_6]], %[[VAL_7]]) : (i64, i64, i64) -> i32 +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i32) -> i16 +! CHECK: fir.store %[[VAL_9]] to %[[VAL_3]] : !fir.ref +! CHECK: return +! CHECK: } + +subroutine selected_real_kind_test2(p, r, d) + integer(2) :: p, r, d, res + res = selected_real_kind(P=p, R=r, RADIX=d) +end + +! CHECK-LABEL: func.func @_QPselected_real_kind_test4( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref {fir.bindc_name = "p"}, +! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref {fir.bindc_name = "r"}, +! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref {fir.bindc_name = "d"}) { +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "res", uniq_name = "_QFselected_real_kind_test4Eres"} +! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i32) -> i64 +! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_4]] : (i32) -> i64 +! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_4]] : (i32) -> i64 +! CHECK: %[[VAL_8:.*]] = fir.call @_FortranASelectedRealKind8_8_8(%[[VAL_5]], %[[VAL_6]], %[[VAL_7]]) : (i64, i64, i64) -> i32 +! CHECK: fir.store %[[VAL_8]] to %[[VAL_3]] : !fir.ref +! CHECK: return +! CHECK: } + +subroutine selected_real_kind_test4(p, r, d) + integer(4) :: p, r, d, res + res = selected_real_kind(P=p, R=r, RADIX=d) +end + +! CHECK-LABEL: func.func @_QPselected_real_kind_test8( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref {fir.bindc_name = "p"}, +! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref {fir.bindc_name = "r"}, +! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref {fir.bindc_name = "d"}) { +! CHECK: %[[VAL_3:.*]] = fir.alloca i64 {bindc_name = "res", uniq_name = "_QFselected_real_kind_test8Eres"} +! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_5:.*]] = fir.call @_FortranASelectedRealKind8_8_8(%[[VAL_4]], %[[VAL_4]], %[[VAL_4]]) : (i64, i64, i64) -> i32 +! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (i32) -> i64 +! CHECK: fir.store %[[VAL_6]] to %[[VAL_3]] : !fir.ref +! CHECK: return +! CHECK: } + +subroutine selected_real_kind_test8(p, r, d) + integer(8) :: p, r, d, res + res = selected_real_kind(P=p, R=r, RADIX=d) +end + +! CHECK-LABEL: func.func @_QPselected_real_kind_test16( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref {fir.bindc_name = "p"}, +! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref {fir.bindc_name = "r"}, +! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref {fir.bindc_name = "d"}) { +! CHECK: %[[VAL_3:.*]] = fir.alloca i128 {bindc_name = "res", uniq_name = "_QFselected_real_kind_test16Eres"} +! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i128) -> i64 +! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_4]] : (i128) -> i64 +! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_4]] : (i128) -> i64 +! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_5]] : (i64) -> i128 +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_6]] : (i64) -> i128 +! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_7]] : (i64) -> i128 +! CHECK: %[[VAL_11:.*]] = fir.call @_FortranASelectedRealKind16_16_16(%[[VAL_8]], %[[VAL_9]], %[[VAL_10]]) : (i128, i128, i128) -> i32 +! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_11]] : (i32) -> i128 +! CHECK: fir.store %[[VAL_12]] to %[[VAL_3]] : !fir.ref +! CHECK: return +! CHECK: } + +subroutine selected_real_kind_test16(p, r, d) + integer(16) :: p, r, d, res + res = selected_real_kind(P=p, R=r, RADIX=d) +end Index: flang/unittests/Runtime/Numeric.cpp =================================================================== --- flang/unittests/Runtime/Numeric.cpp +++ flang/unittests/Runtime/Numeric.cpp @@ -152,6 +152,25 @@ RTNAME(SetExponent8)(std::numeric_limits>::quiet_NaN(), 1))); } +TEST(Numeric, SelectedRealKind) { + EXPECT_EQ( + RTNAME(SelectedRealKind8_8_8)(Int<8>{-10}, Int<8>{-1}, Int<8>{2}), 2); + EXPECT_EQ(RTNAME(SelectedRealKind8_8_8)(Int<8>{1}, Int<8>{1}, Int<8>{1}), -5); + EXPECT_EQ(RTNAME(SelectedRealKind8_8_8)(Int<8>{1}, Int<8>{1}, Int<8>{2}), 2); + EXPECT_EQ(RTNAME(SelectedRealKind8_8_8)(Int<8>{4}, Int<8>{1}, Int<8>{2}), 4); + EXPECT_EQ( + RTNAME(SelectedRealKind8_8_8)(Int<8>{50}, Int<8>{1}, Int<8>{2}), -1); + EXPECT_EQ(RTNAME(SelectedRealKind8_8_8)(Int<8>{1}, Int<8>{1}, Int<8>{2}), 2); + EXPECT_EQ(RTNAME(SelectedRealKind8_8_8)(Int<8>{1}, Int<8>{20}, Int<8>{2}), 3); + EXPECT_EQ(RTNAME(SelectedRealKind8_8_8)(Int<8>{4}, Int<8>{20}, Int<8>{2}), 4); + EXPECT_EQ( + RTNAME(SelectedRealKind8_8_8)(Int<8>{1}, Int<8>{100}, Int<8>{2}), 8); + EXPECT_EQ( + RTNAME(SelectedRealKind8_8_8)(Int<8>{1}, Int<8>{5000}, Int<8>{2}), -2); + EXPECT_EQ( + RTNAME(SelectedRealKind8_8_8)(Int<8>{50}, Int<8>{5000}, Int<8>{2}), -3); +} + TEST(Numeric, Spacing) { EXPECT_EQ(RTNAME(Spacing8)(Real<8>{0}), std::numeric_limits>::min()); EXPECT_EQ(RTNAME(Spacing4)(Real<4>{3.0}), std::ldexp(Real<4>{1.0}, -22));