llvm-project/flang/runtime/numeric.cpp
Peixin Qiao f532c07211 [flang] Support intrinsic selected_int_kind for variables
As Fortran 2018 16.9.169, the argument of selected_int_kind is integer
scalar, and result is default integer scalar. The constant expression in
this intrinsic has been supported by folding the constant expression.
This supports lowering and runtime for variables in this intrinsic.

Reviewed By: Jean Perier

Differential Revision: https://reviews.llvm.org/D129959
2022-07-26 00:33:27 +08:00

876 lines
28 KiB
C++

//===-- 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/Runtime/float128.h"
#include <cfloat>
#include <climits>
#include <cmath>
#include <limits>
namespace Fortran::runtime {
template <typename RES>
inline RES getIntArgValue(const char *source, int line, void *arg, int kind,
std::int64_t defaultValue, int resKind) {
RES res;
if (!arg) {
res = static_cast<RES>(defaultValue);
} else if (kind == 1) {
res = static_cast<RES>(
*static_cast<CppTypeFor<TypeCategory::Integer, 1> *>(arg));
} else if (kind == 2) {
res = static_cast<RES>(
*static_cast<CppTypeFor<TypeCategory::Integer, 2> *>(arg));
} else if (kind == 4) {
res = static_cast<RES>(
*static_cast<CppTypeFor<TypeCategory::Integer, 4> *>(arg));
} else if (kind == 8) {
res = static_cast<RES>(
*static_cast<CppTypeFor<TypeCategory::Integer, 8> *>(arg));
#ifdef __SIZEOF_INT128__
} else if (kind == 16) {
if (resKind != 16) {
Terminator{source, line}.Crash("Unexpected integer kind in runtime");
}
res = static_cast<RES>(
*static_cast<CppTypeFor<TypeCategory::Integer, 16> *>(arg));
#endif
} else {
Terminator{source, line}.Crash("Unexpected integer kind in runtime");
}
return res;
}
// NINT (16.9.141)
template <typename RESULT, typename ARG> inline 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 <typename RESULT, typename ARG> inline RESULT Ceiling(ARG x) {
return std::ceil(x);
}
template <typename RESULT, typename ARG> inline RESULT Floor(ARG x) {
return std::floor(x);
}
// EXPONENT (16.9.75)
template <typename RESULT, typename ARG> inline RESULT Exponent(ARG x) {
if (std::isinf(x) || std::isnan(x)) {
return std::numeric_limits<RESULT>::max(); // +/-Inf, NaN -> HUGE(0)
} else if (x == 0) {
return 0; // 0 -> 0
} else {
return std::ilogb(x) + 1;
}
}
// FRACTION (16.9.80)
template <typename T> inline T Fraction(T x) {
if (std::isnan(x)) {
return x; // NaN -> same NaN
} else if (std::isinf(x)) {
return std::numeric_limits<T>::quiet_NaN(); // +/-Inf -> NaN
} else if (x == 0) {
return 0; // 0 -> 0
} else {
int ignoredExp;
return std::frexp(x, &ignoredExp);
}
}
// MOD & MODULO (16.9.135, .136)
template <bool IS_MODULO, typename T>
inline 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 <bool IS_MODULO, typename T>
inline 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");
}
T quotient{a / p};
if (std::isinf(quotient) && std::isfinite(a) && std::isfinite(p)) {
// a/p overflowed -- so it must be an integer, and the result
// must be a zero of the same sign as one of the operands.
return std::copysign(T{}, IS_MODULO ? p : a);
}
T toInt{IS_MODULO ? std::floor(quotient) : std::trunc(quotient)};
return a - toInt * p;
}
// RRSPACING (16.9.164)
template <int PREC, typename T> inline T RRSpacing(T x) {
if (std::isnan(x)) {
return x; // NaN -> same NaN
} else if (std::isinf(x)) {
return std::numeric_limits<T>::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 <typename T> inline T Scale(T x, std::int64_t p) {
auto ip{static_cast<int>(p)};
if (ip != p) {
ip = p < 0 ? std::numeric_limits<int>::min()
: std::numeric_limits<int>::max();
}
return std::ldexp(x, p); // x*2**p
}
// SELECTED_INT_KIND (16.9.169)
template <typename T>
inline CppTypeFor<TypeCategory::Integer, 4> 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 <typename P, typename R, typename D>
inline CppTypeFor<TypeCategory::Integer, 4> 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;
}
// SET_EXPONENT (16.9.171)
template <typename T> inline 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<T>::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<int>(p - expo)};
if (ip != p - expo) {
ip = p < 0 ? std::numeric_limits<int>::min()
: std::numeric_limits<int>::max();
}
return std::ldexp(x, ip); // x*2**(p-e)
}
}
// SPACING (16.9.180)
template <int PREC, typename T> inline T Spacing(T x) {
if (std::isnan(x)) {
return x; // NaN -> same NaN
} else if (std::isinf(x)) {
return std::numeric_limits<T>::quiet_NaN(); // +/-Inf -> NaN
} else if (x == 0) {
// The standard-mandated behavior seems broken, since TINY() can't be
// subnormal.
return std::numeric_limits<T>::min(); // 0 -> TINY(x)
} else {
return std::ldexp(
static_cast<T>(1.0), std::ilogb(x) + 1 - PREC); // 2**(e-p)
}
}
// NEAREST (16.9.139)
template <int PREC, typename T> inline T Nearest(T x, bool positive) {
auto spacing{Spacing<PREC>(x)};
if (x == 0) {
auto least{std::numeric_limits<T>::denorm_min()};
return positive ? least : -least;
} else {
return positive ? x + spacing : x - spacing;
}
}
extern "C" {
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling4_1)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x);
}
CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling4_2)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling4_4)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling4_8)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling4_16)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x);
}
#endif
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling8_1)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x);
}
CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling8_2)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling8_4)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling8_8)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling8_16)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x);
}
#endif
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling10_1)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x);
}
CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling10_2)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling10_4)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling10_8)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling10_16)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x);
}
#endif
#elif LDBL_MANT_DIG == 113
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Ceiling16_1)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 1>>(x);
}
CppTypeFor<TypeCategory::Integer, 2> RTNAME(Ceiling16_2)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 2>>(x);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Ceiling16_4)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Ceiling16_8)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> RTNAME(Ceiling16_16)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Ceiling<CppTypeFor<TypeCategory::Integer, 16>>(x);
}
#endif
#endif
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent4_4)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent4_8)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent8_4)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent8_8)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent10_4)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent10_8)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#elif LDBL_MANT_DIG == 113
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Exponent16_4)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Exponent<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Exponent16_8)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Exponent<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#endif
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor4_1)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x);
}
CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor4_2)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor4_4)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor4_8)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor4_16)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x);
}
#endif
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor8_1)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x);
}
CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor8_2)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor8_4)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor8_8)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor8_16)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x);
}
#endif
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor10_1)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x);
}
CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor10_2)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor10_4)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor10_8)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor10_16)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x);
}
#endif
#elif LDBL_MANT_DIG == 113
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Floor16_1)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 1>>(x);
}
CppTypeFor<TypeCategory::Integer, 2> RTNAME(Floor16_2)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 2>>(x);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Floor16_4)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Floor16_8)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> RTNAME(Floor16_16)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Floor<CppTypeFor<TypeCategory::Integer, 16>>(x);
}
#endif
#endif
CppTypeFor<TypeCategory::Real, 4> RTNAME(Fraction4)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Fraction(x);
}
CppTypeFor<TypeCategory::Real, 8> RTNAME(Fraction8)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Fraction(x);
}
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Real, 10> RTNAME(Fraction10)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Fraction(x);
}
#elif LDBL_MANT_DIG == 113
CppTypeFor<TypeCategory::Real, 16> RTNAME(Fraction16)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Fraction(x);
}
#endif
bool RTNAME(IsFinite4)(CppTypeFor<TypeCategory::Real, 4> x) {
return std::isfinite(x);
}
bool RTNAME(IsFinite8)(CppTypeFor<TypeCategory::Real, 8> x) {
return std::isfinite(x);
}
#if LDBL_MANT_DIG == 64
bool RTNAME(IsFinite10)(CppTypeFor<TypeCategory::Real, 10> x) {
return std::isfinite(x);
}
#elif LDBL_MANT_DIG == 113
bool RTNAME(IsFinite16)(CppTypeFor<TypeCategory::Real, 16> x) {
return std::isfinite(x);
}
#endif
bool RTNAME(IsNaN4)(CppTypeFor<TypeCategory::Real, 4> x) {
return std::isnan(x);
}
bool RTNAME(IsNaN8)(CppTypeFor<TypeCategory::Real, 8> x) {
return std::isnan(x);
}
#if LDBL_MANT_DIG == 64
bool RTNAME(IsNaN10)(CppTypeFor<TypeCategory::Real, 10> x) {
return std::isnan(x);
}
#elif LDBL_MANT_DIG == 113
bool RTNAME(IsNaN16)(CppTypeFor<TypeCategory::Real, 16> x) {
return std::isnan(x);
}
#endif
CppTypeFor<TypeCategory::Integer, 1> RTNAME(ModInteger1)(
CppTypeFor<TypeCategory::Integer, 1> x,
CppTypeFor<TypeCategory::Integer, 1> p, const char *sourceFile,
int sourceLine) {
return IntMod<false>(x, p, sourceFile, sourceLine);
}
CppTypeFor<TypeCategory::Integer, 2> RTNAME(ModInteger2)(
CppTypeFor<TypeCategory::Integer, 2> x,
CppTypeFor<TypeCategory::Integer, 2> p, const char *sourceFile,
int sourceLine) {
return IntMod<false>(x, p, sourceFile, sourceLine);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(ModInteger4)(
CppTypeFor<TypeCategory::Integer, 4> x,
CppTypeFor<TypeCategory::Integer, 4> p, const char *sourceFile,
int sourceLine) {
return IntMod<false>(x, p, sourceFile, sourceLine);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(ModInteger8)(
CppTypeFor<TypeCategory::Integer, 8> x,
CppTypeFor<TypeCategory::Integer, 8> p, const char *sourceFile,
int sourceLine) {
return IntMod<false>(x, p, sourceFile, sourceLine);
}
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> RTNAME(ModInteger16)(
CppTypeFor<TypeCategory::Integer, 16> x,
CppTypeFor<TypeCategory::Integer, 16> p, const char *sourceFile,
int sourceLine) {
return IntMod<false>(x, p, sourceFile, sourceLine);
}
#endif
CppTypeFor<TypeCategory::Real, 4> RTNAME(ModReal4)(
CppTypeFor<TypeCategory::Real, 4> x, CppTypeFor<TypeCategory::Real, 4> p,
const char *sourceFile, int sourceLine) {
return RealMod<false>(x, p, sourceFile, sourceLine);
}
CppTypeFor<TypeCategory::Real, 8> RTNAME(ModReal8)(
CppTypeFor<TypeCategory::Real, 8> x, CppTypeFor<TypeCategory::Real, 8> p,
const char *sourceFile, int sourceLine) {
return RealMod<false>(x, p, sourceFile, sourceLine);
}
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Real, 10> RTNAME(ModReal10)(
CppTypeFor<TypeCategory::Real, 10> x, CppTypeFor<TypeCategory::Real, 10> p,
const char *sourceFile, int sourceLine) {
return RealMod<false>(x, p, sourceFile, sourceLine);
}
#elif LDBL_MANT_DIG == 113
CppTypeFor<TypeCategory::Real, 16> RTNAME(ModReal16)(
CppTypeFor<TypeCategory::Real, 16> x, CppTypeFor<TypeCategory::Real, 16> p,
const char *sourceFile, int sourceLine) {
return RealMod<false>(x, p, sourceFile, sourceLine);
}
#endif
CppTypeFor<TypeCategory::Integer, 1> RTNAME(ModuloInteger1)(
CppTypeFor<TypeCategory::Integer, 1> x,
CppTypeFor<TypeCategory::Integer, 1> p, const char *sourceFile,
int sourceLine) {
return IntMod<true>(x, p, sourceFile, sourceLine);
}
CppTypeFor<TypeCategory::Integer, 2> RTNAME(ModuloInteger2)(
CppTypeFor<TypeCategory::Integer, 2> x,
CppTypeFor<TypeCategory::Integer, 2> p, const char *sourceFile,
int sourceLine) {
return IntMod<true>(x, p, sourceFile, sourceLine);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(ModuloInteger4)(
CppTypeFor<TypeCategory::Integer, 4> x,
CppTypeFor<TypeCategory::Integer, 4> p, const char *sourceFile,
int sourceLine) {
return IntMod<true>(x, p, sourceFile, sourceLine);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(ModuloInteger8)(
CppTypeFor<TypeCategory::Integer, 8> x,
CppTypeFor<TypeCategory::Integer, 8> p, const char *sourceFile,
int sourceLine) {
return IntMod<true>(x, p, sourceFile, sourceLine);
}
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> RTNAME(ModuloInteger16)(
CppTypeFor<TypeCategory::Integer, 16> x,
CppTypeFor<TypeCategory::Integer, 16> p, const char *sourceFile,
int sourceLine) {
return IntMod<true>(x, p, sourceFile, sourceLine);
}
#endif
CppTypeFor<TypeCategory::Real, 4> RTNAME(ModuloReal4)(
CppTypeFor<TypeCategory::Real, 4> x, CppTypeFor<TypeCategory::Real, 4> p,
const char *sourceFile, int sourceLine) {
return RealMod<true>(x, p, sourceFile, sourceLine);
}
CppTypeFor<TypeCategory::Real, 8> RTNAME(ModuloReal8)(
CppTypeFor<TypeCategory::Real, 8> x, CppTypeFor<TypeCategory::Real, 8> p,
const char *sourceFile, int sourceLine) {
return RealMod<true>(x, p, sourceFile, sourceLine);
}
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Real, 10> RTNAME(ModuloReal10)(
CppTypeFor<TypeCategory::Real, 10> x, CppTypeFor<TypeCategory::Real, 10> p,
const char *sourceFile, int sourceLine) {
return RealMod<true>(x, p, sourceFile, sourceLine);
}
#elif LDBL_MANT_DIG == 113
CppTypeFor<TypeCategory::Real, 16> RTNAME(ModuloReal16)(
CppTypeFor<TypeCategory::Real, 16> x, CppTypeFor<TypeCategory::Real, 16> p,
const char *sourceFile, int sourceLine) {
return RealMod<true>(x, p, sourceFile, sourceLine);
}
#endif
CppTypeFor<TypeCategory::Real, 4> RTNAME(Nearest4)(
CppTypeFor<TypeCategory::Real, 4> x, bool positive) {
return Nearest<24>(x, positive);
}
CppTypeFor<TypeCategory::Real, 8> RTNAME(Nearest8)(
CppTypeFor<TypeCategory::Real, 8> x, bool positive) {
return Nearest<53>(x, positive);
}
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Real, 10> RTNAME(Nearest10)(
CppTypeFor<TypeCategory::Real, 10> x, bool positive) {
return Nearest<64>(x, positive);
}
#elif LDBL_MANT_DIG == 113
CppTypeFor<TypeCategory::Real, 16> RTNAME(Nearest16)(
CppTypeFor<TypeCategory::Real, 16> x, bool positive) {
return Nearest<113>(x, positive);
}
#endif
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint4_1)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x);
}
CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint4_2)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint4_4)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint4_8)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint4_16)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x);
}
#endif
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint8_1)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x);
}
CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint8_2)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint8_4)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint8_8)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint8_16)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x);
}
#endif
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint10_1)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x);
}
CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint10_2)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint10_4)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint10_8)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint10_16)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x);
}
#endif
#elif LDBL_MANT_DIG == 113
CppTypeFor<TypeCategory::Integer, 1> RTNAME(Nint16_1)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 1>>(x);
}
CppTypeFor<TypeCategory::Integer, 2> RTNAME(Nint16_2)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 2>>(x);
}
CppTypeFor<TypeCategory::Integer, 4> RTNAME(Nint16_4)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 4>>(x);
}
CppTypeFor<TypeCategory::Integer, 8> RTNAME(Nint16_8)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 8>>(x);
}
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> RTNAME(Nint16_16)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Nint<CppTypeFor<TypeCategory::Integer, 16>>(x);
}
#endif
#endif
CppTypeFor<TypeCategory::Real, 4> RTNAME(RRSpacing4)(
CppTypeFor<TypeCategory::Real, 4> x) {
return RRSpacing<24>(x);
}
CppTypeFor<TypeCategory::Real, 8> RTNAME(RRSpacing8)(
CppTypeFor<TypeCategory::Real, 8> x) {
return RRSpacing<53>(x);
}
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Real, 10> RTNAME(RRSpacing10)(
CppTypeFor<TypeCategory::Real, 10> x) {
return RRSpacing<64>(x);
}
#elif LDBL_MANT_DIG == 113
CppTypeFor<TypeCategory::Real, 16> RTNAME(RRSpacing16)(
CppTypeFor<TypeCategory::Real, 16> x) {
return RRSpacing<113>(x);
}
#endif
CppTypeFor<TypeCategory::Real, 4> RTNAME(SetExponent4)(
CppTypeFor<TypeCategory::Real, 4> x, std::int64_t p) {
return SetExponent(x, p);
}
CppTypeFor<TypeCategory::Real, 8> RTNAME(SetExponent8)(
CppTypeFor<TypeCategory::Real, 8> x, std::int64_t p) {
return SetExponent(x, p);
}
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Real, 10> RTNAME(SetExponent10)(
CppTypeFor<TypeCategory::Real, 10> x, std::int64_t p) {
return SetExponent(x, p);
}
#elif LDBL_MANT_DIG == 113
CppTypeFor<TypeCategory::Real, 16> RTNAME(SetExponent16)(
CppTypeFor<TypeCategory::Real, 16> x, std::int64_t p) {
return SetExponent(x, p);
}
#endif
CppTypeFor<TypeCategory::Real, 4> RTNAME(Scale4)(
CppTypeFor<TypeCategory::Real, 4> x, std::int64_t p) {
return Scale(x, p);
}
CppTypeFor<TypeCategory::Real, 8> RTNAME(Scale8)(
CppTypeFor<TypeCategory::Real, 8> x, std::int64_t p) {
return Scale(x, p);
}
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Real, 10> RTNAME(Scale10)(
CppTypeFor<TypeCategory::Real, 10> x, std::int64_t p) {
return Scale(x, p);
}
#elif LDBL_MANT_DIG == 113
CppTypeFor<TypeCategory::Real, 16> RTNAME(Scale16)(
CppTypeFor<TypeCategory::Real, 16> x, std::int64_t p) {
return Scale(x, p);
}
#endif
// SELECTED_INT_KIND
CppTypeFor<TypeCategory::Integer, 4> RTNAME(SelectedIntKind)(
const char *source, int line, void *x, int xKind) {
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> r =
getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>(
source, line, x, xKind, /*defaultValue*/ 0, /*resKind*/ 16);
#else
std::int64_t r = getIntArgValue<std::int64_t>(
source, line, x, xKind, /*defaultValue*/ 0, /*resKind*/ 8);
#endif
return SelectedIntKind(r);
}
// SELECTED_REAL_KIND
CppTypeFor<TypeCategory::Integer, 4> RTNAME(SelectedRealKind)(
const char *source, int line, void *precision, int pKind, void *range,
int rKind, void *radix, int dKind) {
#ifdef __SIZEOF_INT128__
CppTypeFor<TypeCategory::Integer, 16> p =
getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>(
source, line, precision, pKind, /*defaultValue*/ 0, /*resKind*/ 16);
CppTypeFor<TypeCategory::Integer, 16> r =
getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>(
source, line, range, rKind, /*defaultValue*/ 0, /*resKind*/ 16);
CppTypeFor<TypeCategory::Integer, 16> d =
getIntArgValue<CppTypeFor<TypeCategory::Integer, 16>>(
source, line, radix, dKind, /*defaultValue*/ 2, /*resKind*/ 16);
#else
std::int64_t p = getIntArgValue<std::int64_t>(
source, line, precision, pKind, /*defaultValue*/ 0, /*resKind*/ 8);
std::int64_t r = getIntArgValue<std::int64_t>(
source, line, range, rKind, /*defaultValue*/ 0, /*resKind*/ 8);
std::int64_t d = getIntArgValue<std::int64_t>(
source, line, radix, dKind, /*defaultValue*/ 2, /*resKind*/ 8);
#endif
return SelectedRealKind(p, r, d);
}
CppTypeFor<TypeCategory::Real, 4> RTNAME(Spacing4)(
CppTypeFor<TypeCategory::Real, 4> x) {
return Spacing<24>(x);
}
CppTypeFor<TypeCategory::Real, 8> RTNAME(Spacing8)(
CppTypeFor<TypeCategory::Real, 8> x) {
return Spacing<53>(x);
}
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Real, 10> RTNAME(Spacing10)(
CppTypeFor<TypeCategory::Real, 10> x) {
return Spacing<64>(x);
}
#elif LDBL_MANT_DIG == 113
CppTypeFor<TypeCategory::Real, 16> RTNAME(Spacing16)(
CppTypeFor<TypeCategory::Real, 16> x) {
return Spacing<113>(x);
}
#endif
} // extern "C"
} // namespace Fortran::runtime