//===-- runtime/numeric.cpp -----------------------------------------------===// // // 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 "flang/Runtime/numeric.h" #include "terminator.h" #include "flang/Common/float128.h" #include #include #include #include namespace Fortran::runtime { template inline RT_API_ATTRS RES getIntArgValue(const char *source, int line, void *arg, int kind, std::int64_t defaultValue, int resKind) { RES res; if (!arg) { res = static_cast(defaultValue); } else if (kind == 1) { res = static_cast( *static_cast *>(arg)); } else if (kind == 2) { res = static_cast( *static_cast *>(arg)); } else if (kind == 4) { res = static_cast( *static_cast *>(arg)); } else if (kind == 8) { res = static_cast( *static_cast *>(arg)); #ifdef __SIZEOF_INT128__ } else if (kind == 16) { if (resKind != 16) { Terminator{source, line}.Crash("Unexpected integer kind in runtime"); } res = static_cast( *static_cast *>(arg)); #endif } else { Terminator{source, line}.Crash("Unexpected integer kind in runtime"); } return res; } // NINT (16.9.141) template inline RT_API_ATTRS RESULT Nint(ARG x) { if (x >= 0) { return std::trunc(x + ARG{0.5}); } else { return std::trunc(x - ARG{0.5}); } } // CEILING & FLOOR (16.9.43, .79) template inline RT_API_ATTRS RESULT Ceiling(ARG x) { return std::ceil(x); } template inline RT_API_ATTRS RESULT Floor(ARG x) { return std::floor(x); } // EXPONENT (16.9.75) template inline RT_API_ATTRS RESULT Exponent(ARG x) { if (std::isinf(x) || std::isnan(x)) { return std::numeric_limits::max(); // +/-Inf, NaN -> HUGE(0) } else if (x == 0) { return 0; // 0 -> 0 } else { return std::ilogb(x) + 1; } } // Suppress the warnings about calling __host__-only std::frexp, // defined in C++ STD header files, from __device__ code. RT_DIAG_PUSH RT_DIAG_DISABLE_CALL_HOST_FROM_DEVICE_WARN // FRACTION (16.9.80) template inline RT_API_ATTRS T Fraction(T x) { if (std::isnan(x)) { return x; // NaN -> same NaN } else if (std::isinf(x)) { return std::numeric_limits::quiet_NaN(); // +/-Inf -> NaN } else if (x == 0) { return x; // 0 -> same 0 } else { int ignoredExp; return std::frexp(x, &ignoredExp); } } RT_DIAG_POP // SET_EXPONENT (16.9.171) template inline RT_API_ATTRS T SetExponent(T x, std::int64_t p) { if (std::isnan(x)) { return x; // NaN -> same NaN } else if (std::isinf(x)) { return std::numeric_limits::quiet_NaN(); // +/-Inf -> NaN } else if (x == 0) { return x; // return negative zero if x is negative zero } else { int expo{std::ilogb(x) + 1}; auto ip{static_cast(p - expo)}; if (ip != p - expo) { ip = p < 0 ? std::numeric_limits::min() : std::numeric_limits::max(); } return std::ldexp(x, ip); // x*2**(p-e) } } // MOD & MODULO (16.9.135, .136) template inline RT_API_ATTRS T IntMod(T x, T p, const char *sourceFile, int sourceLine) { if (p == 0) { Terminator{sourceFile, sourceLine}.Crash( IS_MODULO ? "MODULO with P==0" : "MOD with P==0"); } auto mod{x - (x / p) * p}; if (IS_MODULO && (x > 0) != (p > 0)) { mod += p; } return mod; } template inline RT_API_ATTRS T RealMod( T a, T p, const char *sourceFile, int sourceLine) { if (p == 0) { Terminator{sourceFile, sourceLine}.Crash( IS_MODULO ? "MODULO with P==0" : "MOD with P==0"); } if (std::isnan(a) || std::isnan(p) || std::isinf(a)) { return std::numeric_limits::quiet_NaN(); } else if (std::isinf(p)) { return a; } else { // The standard defines MOD(a,p)=a-AINT(a/p)*p and // MODULO(a,p)=a-FLOOR(a/p)*p, but those definitions lose // precision badly due to cancellation when ABS(a) is // much larger than ABS(p). // Insights: // - MOD(a,p)=MOD(a-n*p,p) when a>0, p>0, integer n>0, and a>=n*p // - when n is a power of two, n*p is exact // - as a>=n*p, a-n*p does not round. // So repeatedly reduce a by all n*p in decreasing order of n; // what's left is the desired remainder. This is basically // the same algorithm as arbitrary precision binary long division, // discarding the quotient. T tmp{std::abs(a)}; T pAbs{std::abs(p)}; for (T adj{SetExponent(pAbs, Exponent(tmp))}; tmp >= pAbs; adj /= 2) { if (tmp >= adj) { tmp -= adj; if (tmp == 0) { break; } } } if (a < 0) { tmp = -tmp; } if constexpr (IS_MODULO) { if ((a < 0) != (p < 0)) { tmp += p; } } return tmp; } } // RRSPACING (16.9.164) template inline RT_API_ATTRS T RRSpacing(T x) { if (std::isnan(x)) { return x; // NaN -> same NaN } else if (std::isinf(x)) { return std::numeric_limits::quiet_NaN(); // +/-Inf -> NaN } else if (x == 0) { return 0; // 0 -> 0 } else { return std::ldexp(std::abs(x), PREC - (std::ilogb(x) + 1)); } } // SCALE (16.9.166) template inline RT_API_ATTRS T Scale(T x, std::int64_t p) { auto ip{static_cast(p)}; if (ip != p) { ip = p < 0 ? std::numeric_limits::min() : std::numeric_limits::max(); } return std::ldexp(x, p); // x*2**p } // SELECTED_INT_KIND (16.9.169) template inline RT_API_ATTRS CppTypeFor SelectedIntKind(T x) { if (x <= 2) { return 1; } else if (x <= 4) { return 2; } else if (x <= 9) { return 4; } else if (x <= 18) { return 8; #ifdef __SIZEOF_INT128__ } else if (x <= 38) { return 16; #endif } return -1; } // SELECTED_REAL_KIND (16.9.170) template inline RT_API_ATTRS 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 ? (p == 3 ? 4 : 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; } // SPACING (16.9.180) template inline RT_API_ATTRS T Spacing(T x) { if (std::isnan(x)) { return x; // NaN -> same NaN } else if (std::isinf(x)) { return std::numeric_limits::quiet_NaN(); // +/-Inf -> NaN } else if (x == 0) { // The standard-mandated behavior seems broken, since TINY() can't be // subnormal. return std::numeric_limits::min(); // 0 -> TINY(x) } else { T result{ std::ldexp(static_cast(1.0), std::ilogb(x) + 1 - PREC)}; // 2**(e-p) return result == 0 ? /*TINY(x)*/ std::numeric_limits::min() : result; } } // NEAREST (16.9.139) template inline RT_API_ATTRS T Nearest(T x, bool positive) { if (positive) { return std::nextafter(x, std::numeric_limits::infinity()); } else { return std::nextafter(x, -std::numeric_limits::infinity()); } } // Exponentiation operator for (Real ** Integer) cases (10.1.5.2.1). template RT_API_ATTRS BTy FPowI(BTy base, ETy exp) { if (exp == ETy{0}) return BTy{1}; bool isNegativePower{exp < ETy{0}}; bool isMinPower{exp == std::numeric_limits::min()}; if (isMinPower) { exp = std::numeric_limits::max(); } else if (isNegativePower) { exp = -exp; } BTy result{1}; BTy origBase{base}; while (true) { if (exp & ETy{1}) { result *= base; } exp >>= 1; if (exp == ETy{0}) { break; } base *= base; } if (isMinPower) { result *= origBase; } if (isNegativePower) { result = BTy{1} / result; } return result; } extern "C" { RT_EXT_API_GROUP_BEGIN CppTypeFor RTDEF(Ceiling4_1)( CppTypeFor x) { return Ceiling>(x); } CppTypeFor RTDEF(Ceiling4_2)( CppTypeFor x) { return Ceiling>(x); } CppTypeFor RTDEF(Ceiling4_4)( CppTypeFor x) { return Ceiling>(x); } CppTypeFor RTDEF(Ceiling4_8)( CppTypeFor x) { return Ceiling>(x); } #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T CppTypeFor RTDEF(Ceiling4_16)( CppTypeFor x) { return Ceiling>(x); } #endif CppTypeFor RTDEF(Ceiling8_1)( CppTypeFor x) { return Ceiling>(x); } CppTypeFor RTDEF(Ceiling8_2)( CppTypeFor x) { return Ceiling>(x); } CppTypeFor RTDEF(Ceiling8_4)( CppTypeFor x) { return Ceiling>(x); } CppTypeFor RTDEF(Ceiling8_8)( CppTypeFor x) { return Ceiling>(x); } #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T CppTypeFor RTDEF(Ceiling8_16)( CppTypeFor x) { return Ceiling>(x); } #endif #if LDBL_MANT_DIG == 64 CppTypeFor RTDEF(Ceiling10_1)( CppTypeFor x) { return Ceiling>(x); } CppTypeFor RTDEF(Ceiling10_2)( CppTypeFor x) { return Ceiling>(x); } CppTypeFor RTDEF(Ceiling10_4)( CppTypeFor x) { return Ceiling>(x); } CppTypeFor RTDEF(Ceiling10_8)( CppTypeFor x) { return Ceiling>(x); } #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T CppTypeFor RTDEF(Ceiling10_16)( CppTypeFor x) { return Ceiling>(x); } #endif #elif LDBL_MANT_DIG == 113 CppTypeFor RTDEF(Ceiling16_1)( CppTypeFor x) { return Ceiling>(x); } CppTypeFor RTDEF(Ceiling16_2)( CppTypeFor x) { return Ceiling>(x); } CppTypeFor RTDEF(Ceiling16_4)( CppTypeFor x) { return Ceiling>(x); } CppTypeFor RTDEF(Ceiling16_8)( CppTypeFor x) { return Ceiling>(x); } #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T CppTypeFor RTDEF(Ceiling16_16)( CppTypeFor x) { return Ceiling>(x); } #endif #endif CppTypeFor RTDEF(Exponent4_4)( CppTypeFor x) { return Exponent>(x); } CppTypeFor RTDEF(Exponent4_8)( CppTypeFor x) { return Exponent>(x); } CppTypeFor RTDEF(Exponent8_4)( CppTypeFor x) { return Exponent>(x); } CppTypeFor RTDEF(Exponent8_8)( CppTypeFor x) { return Exponent>(x); } #if LDBL_MANT_DIG == 64 CppTypeFor RTDEF(Exponent10_4)( CppTypeFor x) { return Exponent>(x); } CppTypeFor RTDEF(Exponent10_8)( CppTypeFor x) { return Exponent>(x); } #elif LDBL_MANT_DIG == 113 CppTypeFor RTDEF(Exponent16_4)( CppTypeFor x) { return Exponent>(x); } CppTypeFor RTDEF(Exponent16_8)( CppTypeFor x) { return Exponent>(x); } #endif CppTypeFor RTDEF(Floor4_1)( CppTypeFor x) { return Floor>(x); } CppTypeFor RTDEF(Floor4_2)( CppTypeFor x) { return Floor>(x); } CppTypeFor RTDEF(Floor4_4)( CppTypeFor x) { return Floor>(x); } CppTypeFor RTDEF(Floor4_8)( CppTypeFor x) { return Floor>(x); } #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T CppTypeFor RTDEF(Floor4_16)( CppTypeFor x) { return Floor>(x); } #endif CppTypeFor RTDEF(Floor8_1)( CppTypeFor x) { return Floor>(x); } CppTypeFor RTDEF(Floor8_2)( CppTypeFor x) { return Floor>(x); } CppTypeFor RTDEF(Floor8_4)( CppTypeFor x) { return Floor>(x); } CppTypeFor RTDEF(Floor8_8)( CppTypeFor x) { return Floor>(x); } #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T CppTypeFor RTDEF(Floor8_16)( CppTypeFor x) { return Floor>(x); } #endif #if LDBL_MANT_DIG == 64 CppTypeFor RTDEF(Floor10_1)( CppTypeFor x) { return Floor>(x); } CppTypeFor RTDEF(Floor10_2)( CppTypeFor x) { return Floor>(x); } CppTypeFor RTDEF(Floor10_4)( CppTypeFor x) { return Floor>(x); } CppTypeFor RTDEF(Floor10_8)( CppTypeFor x) { return Floor>(x); } #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T CppTypeFor RTDEF(Floor10_16)( CppTypeFor x) { return Floor>(x); } #endif #elif LDBL_MANT_DIG == 113 CppTypeFor RTDEF(Floor16_1)( CppTypeFor x) { return Floor>(x); } CppTypeFor RTDEF(Floor16_2)( CppTypeFor x) { return Floor>(x); } CppTypeFor RTDEF(Floor16_4)( CppTypeFor x) { return Floor>(x); } CppTypeFor RTDEF(Floor16_8)( CppTypeFor x) { return Floor>(x); } #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T CppTypeFor RTDEF(Floor16_16)( CppTypeFor x) { return Floor>(x); } #endif #endif CppTypeFor RTDEF(Fraction4)( CppTypeFor x) { return Fraction(x); } CppTypeFor RTDEF(Fraction8)( CppTypeFor x) { return Fraction(x); } #if LDBL_MANT_DIG == 64 CppTypeFor RTDEF(Fraction10)( CppTypeFor x) { return Fraction(x); } #elif LDBL_MANT_DIG == 113 CppTypeFor RTDEF(Fraction16)( CppTypeFor x) { return Fraction(x); } #endif bool RTDEF(IsFinite4)(CppTypeFor x) { return std::isfinite(x); } bool RTDEF(IsFinite8)(CppTypeFor x) { return std::isfinite(x); } #if LDBL_MANT_DIG == 64 bool RTDEF(IsFinite10)(CppTypeFor x) { return std::isfinite(x); } #elif LDBL_MANT_DIG == 113 bool RTDEF(IsFinite16)(CppTypeFor x) { return std::isfinite(x); } #endif bool RTDEF(IsNaN4)(CppTypeFor x) { return std::isnan(x); } bool RTDEF(IsNaN8)(CppTypeFor x) { return std::isnan(x); } #if LDBL_MANT_DIG == 64 bool RTDEF(IsNaN10)(CppTypeFor x) { return std::isnan(x); } #elif LDBL_MANT_DIG == 113 bool RTDEF(IsNaN16)(CppTypeFor x) { return std::isnan(x); } #endif CppTypeFor RTDEF(ModInteger1)( CppTypeFor x, CppTypeFor p, const char *sourceFile, int sourceLine) { return IntMod(x, p, sourceFile, sourceLine); } CppTypeFor RTDEF(ModInteger2)( CppTypeFor x, CppTypeFor p, const char *sourceFile, int sourceLine) { return IntMod(x, p, sourceFile, sourceLine); } CppTypeFor RTDEF(ModInteger4)( CppTypeFor x, CppTypeFor p, const char *sourceFile, int sourceLine) { return IntMod(x, p, sourceFile, sourceLine); } CppTypeFor RTDEF(ModInteger8)( CppTypeFor x, CppTypeFor p, const char *sourceFile, int sourceLine) { return IntMod(x, p, sourceFile, sourceLine); } #ifdef __SIZEOF_INT128__ CppTypeFor RTDEF(ModInteger16)( CppTypeFor x, CppTypeFor p, const char *sourceFile, int sourceLine) { return IntMod(x, p, sourceFile, sourceLine); } #endif CppTypeFor RTDEF(ModReal4)( CppTypeFor x, CppTypeFor p, const char *sourceFile, int sourceLine) { return RealMod(x, p, sourceFile, sourceLine); } CppTypeFor RTDEF(ModReal8)( CppTypeFor x, CppTypeFor p, const char *sourceFile, int sourceLine) { return RealMod(x, p, sourceFile, sourceLine); } #if LDBL_MANT_DIG == 64 CppTypeFor RTDEF(ModReal10)( CppTypeFor x, CppTypeFor p, const char *sourceFile, int sourceLine) { return RealMod(x, p, sourceFile, sourceLine); } #elif LDBL_MANT_DIG == 113 CppTypeFor RTDEF(ModReal16)( CppTypeFor x, CppTypeFor p, const char *sourceFile, int sourceLine) { return RealMod(x, p, sourceFile, sourceLine); } #endif CppTypeFor RTDEF(ModuloInteger1)( CppTypeFor x, CppTypeFor p, const char *sourceFile, int sourceLine) { return IntMod(x, p, sourceFile, sourceLine); } CppTypeFor RTDEF(ModuloInteger2)( CppTypeFor x, CppTypeFor p, const char *sourceFile, int sourceLine) { return IntMod(x, p, sourceFile, sourceLine); } CppTypeFor RTDEF(ModuloInteger4)( CppTypeFor x, CppTypeFor p, const char *sourceFile, int sourceLine) { return IntMod(x, p, sourceFile, sourceLine); } CppTypeFor RTDEF(ModuloInteger8)( CppTypeFor x, CppTypeFor p, const char *sourceFile, int sourceLine) { return IntMod(x, p, sourceFile, sourceLine); } #ifdef __SIZEOF_INT128__ CppTypeFor RTDEF(ModuloInteger16)( CppTypeFor x, CppTypeFor p, const char *sourceFile, int sourceLine) { return IntMod(x, p, sourceFile, sourceLine); } #endif CppTypeFor RTDEF(ModuloReal4)( CppTypeFor x, CppTypeFor p, const char *sourceFile, int sourceLine) { return RealMod(x, p, sourceFile, sourceLine); } CppTypeFor RTDEF(ModuloReal8)( CppTypeFor x, CppTypeFor p, const char *sourceFile, int sourceLine) { return RealMod(x, p, sourceFile, sourceLine); } #if LDBL_MANT_DIG == 64 CppTypeFor RTDEF(ModuloReal10)( CppTypeFor x, CppTypeFor p, const char *sourceFile, int sourceLine) { return RealMod(x, p, sourceFile, sourceLine); } #elif LDBL_MANT_DIG == 113 CppTypeFor RTDEF(ModuloReal16)( CppTypeFor x, CppTypeFor p, const char *sourceFile, int sourceLine) { return RealMod(x, p, sourceFile, sourceLine); } #endif CppTypeFor RTDEF(Nearest4)( CppTypeFor x, bool positive) { return Nearest<24>(x, positive); } CppTypeFor RTDEF(Nearest8)( CppTypeFor x, bool positive) { return Nearest<53>(x, positive); } #if LDBL_MANT_DIG == 64 CppTypeFor RTDEF(Nearest10)( CppTypeFor x, bool positive) { return Nearest<64>(x, positive); } #elif LDBL_MANT_DIG == 113 CppTypeFor RTDEF(Nearest16)( CppTypeFor x, bool positive) { return Nearest<113>(x, positive); } #endif CppTypeFor RTDEF(Nint4_1)( CppTypeFor x) { return Nint>(x); } CppTypeFor RTDEF(Nint4_2)( CppTypeFor x) { return Nint>(x); } CppTypeFor RTDEF(Nint4_4)( CppTypeFor x) { return Nint>(x); } CppTypeFor RTDEF(Nint4_8)( CppTypeFor x) { return Nint>(x); } #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T CppTypeFor RTDEF(Nint4_16)( CppTypeFor x) { return Nint>(x); } #endif CppTypeFor RTDEF(Nint8_1)( CppTypeFor x) { return Nint>(x); } CppTypeFor RTDEF(Nint8_2)( CppTypeFor x) { return Nint>(x); } CppTypeFor RTDEF(Nint8_4)( CppTypeFor x) { return Nint>(x); } CppTypeFor RTDEF(Nint8_8)( CppTypeFor x) { return Nint>(x); } #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T CppTypeFor RTDEF(Nint8_16)( CppTypeFor x) { return Nint>(x); } #endif #if LDBL_MANT_DIG == 64 CppTypeFor RTDEF(Nint10_1)( CppTypeFor x) { return Nint>(x); } CppTypeFor RTDEF(Nint10_2)( CppTypeFor x) { return Nint>(x); } CppTypeFor RTDEF(Nint10_4)( CppTypeFor x) { return Nint>(x); } CppTypeFor RTDEF(Nint10_8)( CppTypeFor x) { return Nint>(x); } #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T CppTypeFor RTDEF(Nint10_16)( CppTypeFor x) { return Nint>(x); } #endif #elif LDBL_MANT_DIG == 113 CppTypeFor RTDEF(Nint16_1)( CppTypeFor x) { return Nint>(x); } CppTypeFor RTDEF(Nint16_2)( CppTypeFor x) { return Nint>(x); } CppTypeFor RTDEF(Nint16_4)( CppTypeFor x) { return Nint>(x); } CppTypeFor RTDEF(Nint16_8)( CppTypeFor x) { return Nint>(x); } #if defined __SIZEOF_INT128__ && !AVOID_NATIVE_UINT128_T CppTypeFor RTDEF(Nint16_16)( CppTypeFor x) { return Nint>(x); } #endif #endif CppTypeFor RTDEF(RRSpacing4)( CppTypeFor x) { return RRSpacing<24>(x); } CppTypeFor RTDEF(RRSpacing8)( CppTypeFor x) { return RRSpacing<53>(x); } #if LDBL_MANT_DIG == 64 CppTypeFor RTDEF(RRSpacing10)( CppTypeFor x) { return RRSpacing<64>(x); } #elif LDBL_MANT_DIG == 113 CppTypeFor RTDEF(RRSpacing16)( CppTypeFor x) { return RRSpacing<113>(x); } #endif CppTypeFor RTDEF(SetExponent4)( CppTypeFor x, std::int64_t p) { return SetExponent(x, p); } CppTypeFor RTDEF(SetExponent8)( CppTypeFor x, std::int64_t p) { return SetExponent(x, p); } #if LDBL_MANT_DIG == 64 CppTypeFor RTDEF(SetExponent10)( CppTypeFor x, std::int64_t p) { return SetExponent(x, p); } #elif LDBL_MANT_DIG == 113 CppTypeFor RTDEF(SetExponent16)( CppTypeFor x, std::int64_t p) { return SetExponent(x, p); } #endif CppTypeFor RTDEF(Scale4)( CppTypeFor x, std::int64_t p) { return Scale(x, p); } CppTypeFor RTDEF(Scale8)( CppTypeFor x, std::int64_t p) { return Scale(x, p); } #if LDBL_MANT_DIG == 64 CppTypeFor RTDEF(Scale10)( CppTypeFor x, std::int64_t p) { return Scale(x, p); } #elif LDBL_MANT_DIG == 113 CppTypeFor RTDEF(Scale16)( CppTypeFor x, std::int64_t p) { return Scale(x, p); } #endif // SELECTED_INT_KIND CppTypeFor RTDEF(SelectedIntKind)( const char *source, int line, void *x, int xKind) { #ifdef __SIZEOF_INT128__ CppTypeFor r = getIntArgValue>( source, line, x, xKind, /*defaultValue*/ 0, /*resKind*/ 16); #else std::int64_t r = getIntArgValue( source, line, x, xKind, /*defaultValue*/ 0, /*resKind*/ 8); #endif return SelectedIntKind(r); } // SELECTED_REAL_KIND CppTypeFor RTDEF(SelectedRealKind)(const char *source, int line, void *precision, int pKind, void *range, int rKind, void *radix, int dKind) { #ifdef __SIZEOF_INT128__ CppTypeFor p = getIntArgValue>( source, line, precision, pKind, /*defaultValue*/ 0, /*resKind*/ 16); CppTypeFor r = getIntArgValue>( source, line, range, rKind, /*defaultValue*/ 0, /*resKind*/ 16); CppTypeFor d = getIntArgValue>( source, line, radix, dKind, /*defaultValue*/ 2, /*resKind*/ 16); #else std::int64_t p = getIntArgValue( source, line, precision, pKind, /*defaultValue*/ 0, /*resKind*/ 8); std::int64_t r = getIntArgValue( source, line, range, rKind, /*defaultValue*/ 0, /*resKind*/ 8); std::int64_t d = getIntArgValue( source, line, radix, dKind, /*defaultValue*/ 2, /*resKind*/ 8); #endif return SelectedRealKind(p, r, d); } CppTypeFor RTDEF(Spacing4)( CppTypeFor x) { return Spacing<24>(x); } CppTypeFor RTDEF(Spacing8)( CppTypeFor x) { return Spacing<53>(x); } #if LDBL_MANT_DIG == 64 CppTypeFor RTDEF(Spacing10)( CppTypeFor x) { return Spacing<64>(x); } #elif LDBL_MANT_DIG == 113 CppTypeFor RTDEF(Spacing16)( CppTypeFor x) { return Spacing<113>(x); } #endif CppTypeFor RTDEF(FPow4i)( CppTypeFor b, CppTypeFor e) { return FPowI(b, e); } CppTypeFor RTDEF(FPow8i)( CppTypeFor b, CppTypeFor e) { return FPowI(b, e); } #if LDBL_MANT_DIG == 64 CppTypeFor RTDEF(FPow10i)( CppTypeFor b, CppTypeFor e) { return FPowI(b, e); } #endif #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(FPow16i)( CppTypeFor b, CppTypeFor e) { return FPowI(b, e); } #endif CppTypeFor RTDEF(FPow4k)( CppTypeFor b, CppTypeFor e) { return FPowI(b, e); } CppTypeFor RTDEF(FPow8k)( CppTypeFor b, CppTypeFor e) { return FPowI(b, e); } #if LDBL_MANT_DIG == 64 CppTypeFor RTDEF(FPow10k)( CppTypeFor b, CppTypeFor e) { return FPowI(b, e); } #endif #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(FPow16k)( CppTypeFor b, CppTypeFor e) { return FPowI(b, e); } #endif RT_EXT_API_GROUP_END } // extern "C" } // namespace Fortran::runtime