Add ieee_is_normal/ieee_is_negative to ieee_arithmetic module.

This commit is contained in:
Yury Gribov 2022-01-21 17:24:32 +09:00 committed by Yuri Gribov
parent 267711e38b
commit d3f5ef241a
5 changed files with 57 additions and 1 deletions

View file

@ -88,6 +88,9 @@ public:
constexpr bool IsSubnormal() const { constexpr bool IsSubnormal() const {
return Exponent() == 0 && !GetSignificand().IsZero(); return Exponent() == 0 && !GetSignificand().IsZero();
} }
constexpr bool IsNormal() const {
return !(IsInfinite() || IsNotANumber() || IsSubnormal());
}
constexpr Real ABS() const { // non-arithmetic, no flags returned constexpr Real ABS() const { // non-arithmetic, no flags returned
return {word_.IBCLR(bits - 1)}; return {word_.IBCLR(bits - 1)};

View file

@ -118,6 +118,20 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
ScalarFunc<T, DefaultReal>([](const Scalar<DefaultReal> &x) { ScalarFunc<T, DefaultReal>([](const Scalar<DefaultReal> &x) {
return Scalar<T>{x.IsNotANumber()}; return Scalar<T>{x.IsNotANumber()};
})); }));
} else if (name == "__builtin_ieee_is_negative") {
auto restorer{context.messages().DiscardMessages()};
using DefaultReal = Type<TypeCategory::Real, 4>;
return FoldElementalIntrinsic<T, DefaultReal>(context, std::move(funcRef),
ScalarFunc<T, DefaultReal>([](const Scalar<DefaultReal> &x) {
return Scalar<T>{x.IsNegative()};
}));
} else if (name == "__builtin_ieee_is_normal") {
auto restorer{context.messages().DiscardMessages()};
using DefaultReal = Type<TypeCategory::Real, 4>;
return FoldElementalIntrinsic<T, DefaultReal>(context, std::move(funcRef),
ScalarFunc<T, DefaultReal>([](const Scalar<DefaultReal> &x) {
return Scalar<T>{x.IsNormal()};
}));
} else if (name == "is_contiguous") { } else if (name == "is_contiguous") {
if (args.at(0)) { if (args.at(0)) {
if (auto *expr{args[0]->UnwrapExpr()}) { if (auto *expr{args[0]->UnwrapExpr()}) {

View file

@ -793,6 +793,8 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
DefaultingKIND}, DefaultingKIND},
KINDInt}, KINDInt},
{"__builtin_ieee_is_nan", {{"a", AnyFloating}}, DefaultLogical}, {"__builtin_ieee_is_nan", {{"a", AnyFloating}}, DefaultLogical},
{"__builtin_ieee_is_normal", {{"a", AnyFloating}}, DefaultLogical},
{"__builtin_ieee_is_negative", {{"a", AnyFloating}}, DefaultLogical},
{"__builtin_ieee_next_after", {{"x", SameReal}, {"y", AnyReal}}, SameReal}, {"__builtin_ieee_next_after", {{"x", SameReal}, {"y", AnyReal}}, SameReal},
{"__builtin_ieee_next_down", {{"x", SameReal}}, SameReal}, {"__builtin_ieee_next_down", {{"x", SameReal}}, SameReal},
{"__builtin_ieee_next_up", {{"x", SameReal}}, SameReal}, {"__builtin_ieee_next_up", {{"x", SameReal}}, SameReal},

View file

@ -41,7 +41,8 @@ module __Fortran_builtins
procedure(type(__builtin_c_ptr)) :: __builtin_c_loc procedure(type(__builtin_c_ptr)) :: __builtin_c_loc
intrinsic :: __builtin_ieee_is_nan intrinsic :: __builtin_ieee_is_nan, __builtin_ieee_is_normal, &
__builtin_ieee_is_negative
intrinsic :: __builtin_ieee_next_after, __builtin_ieee_next_down, & intrinsic :: __builtin_ieee_next_after, __builtin_ieee_next_down, &
__builtin_ieee_next_up __builtin_ieee_next_up
intrinsic :: scale ! for ieee_scalb intrinsic :: scale ! for ieee_scalb

View file

@ -11,6 +11,8 @@ module ieee_arithmetic
use __Fortran_builtins, only: & use __Fortran_builtins, only: &
ieee_is_nan => __builtin_ieee_is_nan, & ieee_is_nan => __builtin_ieee_is_nan, &
ieee_is_normal => __builtin_ieee_is_normal, &
ieee_is_negative => __builtin_ieee_is_negative, &
ieee_next_after => __builtin_ieee_next_after, & ieee_next_after => __builtin_ieee_next_after, &
ieee_next_down => __builtin_ieee_next_down, & ieee_next_down => __builtin_ieee_next_down, &
ieee_next_up => __builtin_ieee_next_up, & ieee_next_up => __builtin_ieee_next_up, &
@ -235,6 +237,40 @@ module ieee_arithmetic
_IS_FINITE(16) _IS_FINITE(16)
#undef _IS_FINITE #undef _IS_FINITE
#define _IS_NEGATIVE(KIND) \
elemental function ieee_is_negative_a##KIND(x) result(res); \
real(kind=KIND), intent(in) :: x; \
logical :: res; \
type(ieee_class_type) :: classification; \
classification = ieee_class(x); \
res = classification == ieee_negative_zero .or. classification == ieee_negative_denormal \
.or. classification == ieee_negative_normal .or. classification == ieee_negative_inf; \
end function
_IS_NEGATIVE(2)
_IS_NEGATIVE(3)
_IS_NEGATIVE(4)
_IS_NEGATIVE(8)
_IS_NEGATIVE(10)
_IS_NEGATIVE(16)
#undef _IS_NEGATIVE
#define _IS_NORMAL(KIND) \
elemental function ieee_is_normal_a##KIND(x) result(res); \
real(kind=KIND), intent(in) :: x; \
logical :: res; \
type(ieee_class_type) :: classification; \
classification = ieee_class(x); \
res = classification == ieee_negative_normal .or. classification == ieee_positive_normal \
.or. classification == ieee_negative_zero .or. classification == ieee_positive_zero; \
end function
_IS_NORMAL(2)
_IS_NORMAL(3)
_IS_NORMAL(4)
_IS_NORMAL(8)
_IS_NORMAL(10)
_IS_NORMAL(16)
#undef _IS_NORMAL
! TODO: handle edge cases from 17.11.31 ! TODO: handle edge cases from 17.11.31
#define _REM(XKIND,YKIND) \ #define _REM(XKIND,YKIND) \
elemental function ieee_rem_a##XKIND##_a##YKIND(x, y) result(res); \ elemental function ieee_rem_a##XKIND##_a##YKIND(x, y) result(res); \