| //===-- lib/runtime/extrema-value.cpp ---------------------------*- C++ -*-===// | |
| // | |
| // 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 | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // MAXVAL, MINVAL, and NORM2 entry points. | |
| #include "extrema.h" | |
| namespace Fortran::runtime { | |
| extern "C" { | |
| RT_EXT_API_GROUP_BEGIN | |
| CppTypeFor<TypeCategory::Integer, 1> RTDEF(MaxvalInteger1)(const Descriptor &x, | |
| const char *source, int line, int dim, const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Integer, 1, true>( | |
| x, source, line, dim, mask, "MAXVAL"); | |
| } | |
| CppTypeFor<TypeCategory::Integer, 2> RTDEF(MaxvalInteger2)(const Descriptor &x, | |
| const char *source, int line, int dim, const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Integer, 2, true>( | |
| x, source, line, dim, mask, "MAXVAL"); | |
| } | |
| CppTypeFor<TypeCategory::Integer, 4> RTDEF(MaxvalInteger4)(const Descriptor &x, | |
| const char *source, int line, int dim, const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Integer, 4, true>( | |
| x, source, line, dim, mask, "MAXVAL"); | |
| } | |
| CppTypeFor<TypeCategory::Integer, 8> RTDEF(MaxvalInteger8)(const Descriptor &x, | |
| const char *source, int line, int dim, const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Integer, 8, true>( | |
| x, source, line, dim, mask, "MAXVAL"); | |
| } | |
| #ifdef __SIZEOF_INT128__ | |
| CppTypeFor<TypeCategory::Integer, 16> RTDEF(MaxvalInteger16)( | |
| const Descriptor &x, const char *source, int line, int dim, | |
| const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Integer, 16, true>( | |
| x, source, line, dim, mask, "MAXVAL"); | |
| } | |
| #endif | |
| CppTypeFor<TypeCategory::Unsigned, 1> RTDEF(MaxvalUnsigned1)( | |
| const Descriptor &x, const char *source, int line, int dim, | |
| const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Unsigned, 1, true>( | |
| x, source, line, dim, mask, "MAXVAL"); | |
| } | |
| CppTypeFor<TypeCategory::Unsigned, 2> RTDEF(MaxvalUnsigned2)( | |
| const Descriptor &x, const char *source, int line, int dim, | |
| const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Unsigned, 2, true>( | |
| x, source, line, dim, mask, "MAXVAL"); | |
| } | |
| CppTypeFor<TypeCategory::Unsigned, 4> RTDEF(MaxvalUnsigned4)( | |
| const Descriptor &x, const char *source, int line, int dim, | |
| const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Unsigned, 4, true>( | |
| x, source, line, dim, mask, "MAXVAL"); | |
| } | |
| CppTypeFor<TypeCategory::Unsigned, 8> RTDEF(MaxvalUnsigned8)( | |
| const Descriptor &x, const char *source, int line, int dim, | |
| const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Unsigned, 8, true>( | |
| x, source, line, dim, mask, "MAXVAL"); | |
| } | |
| #ifdef __SIZEOF_INT128__ | |
| CppTypeFor<TypeCategory::Unsigned, 16> RTDEF(MaxvalUnsigned16)( | |
| const Descriptor &x, const char *source, int line, int dim, | |
| const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Unsigned, 16, true>( | |
| x, source, line, dim, mask, "MAXVAL"); | |
| } | |
| #endif | |
| // TODO: REAL(2 & 3) | |
| CppTypeFor<TypeCategory::Real, 4> RTDEF(MaxvalReal4)(const Descriptor &x, | |
| const char *source, int line, int dim, const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Real, 4, true>( | |
| x, source, line, dim, mask, "MAXVAL"); | |
| } | |
| CppTypeFor<TypeCategory::Real, 8> RTDEF(MaxvalReal8)(const Descriptor &x, | |
| const char *source, int line, int dim, const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Real, 8, true>( | |
| x, source, line, dim, mask, "MAXVAL"); | |
| } | |
| #if HAS_FLOAT80 | |
| CppTypeFor<TypeCategory::Real, 10> RTDEF(MaxvalReal10)(const Descriptor &x, | |
| const char *source, int line, int dim, const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Real, 10, true>( | |
| x, source, line, dim, mask, "MAXVAL"); | |
| } | |
| #endif | |
| #if HAS_LDBL128 || HAS_FLOAT128 | |
| CppTypeFor<TypeCategory::Real, 16> RTDEF(MaxvalReal16)(const Descriptor &x, | |
| const char *source, int line, int dim, const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Real, 16, true>( | |
| x, source, line, dim, mask, "MAXVAL"); | |
| } | |
| #endif | |
| void RTDEF(MaxvalCharacter)(Descriptor &result, const Descriptor &x, | |
| const char *source, int line, const Descriptor *mask) { | |
| CharacterMaxOrMin<true>(result, x, 0, source, line, mask, "MAXVAL"); | |
| } | |
| CppTypeFor<TypeCategory::Integer, 1> RTDEF(MinvalInteger1)(const Descriptor &x, | |
| const char *source, int line, int dim, const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Integer, 1, false>( | |
| x, source, line, dim, mask, "MINVAL"); | |
| } | |
| CppTypeFor<TypeCategory::Integer, 2> RTDEF(MinvalInteger2)(const Descriptor &x, | |
| const char *source, int line, int dim, const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Integer, 2, false>( | |
| x, source, line, dim, mask, "MINVAL"); | |
| } | |
| CppTypeFor<TypeCategory::Integer, 4> RTDEF(MinvalInteger4)(const Descriptor &x, | |
| const char *source, int line, int dim, const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Integer, 4, false>( | |
| x, source, line, dim, mask, "MINVAL"); | |
| } | |
| CppTypeFor<TypeCategory::Integer, 8> RTDEF(MinvalInteger8)(const Descriptor &x, | |
| const char *source, int line, int dim, const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Integer, 8, false>( | |
| x, source, line, dim, mask, "MINVAL"); | |
| } | |
| #ifdef __SIZEOF_INT128__ | |
| CppTypeFor<TypeCategory::Integer, 16> RTDEF(MinvalInteger16)( | |
| const Descriptor &x, const char *source, int line, int dim, | |
| const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Integer, 16, false>( | |
| x, source, line, dim, mask, "MINVAL"); | |
| } | |
| #endif | |
| CppTypeFor<TypeCategory::Unsigned, 1> RTDEF(MinvalUnsigned1)( | |
| const Descriptor &x, const char *source, int line, int dim, | |
| const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Unsigned, 1, false>( | |
| x, source, line, dim, mask, "MINVAL"); | |
| } | |
| CppTypeFor<TypeCategory::Unsigned, 2> RTDEF(MinvalUnsigned2)( | |
| const Descriptor &x, const char *source, int line, int dim, | |
| const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Unsigned, 2, false>( | |
| x, source, line, dim, mask, "MINVAL"); | |
| } | |
| CppTypeFor<TypeCategory::Unsigned, 4> RTDEF(MinvalUnsigned4)( | |
| const Descriptor &x, const char *source, int line, int dim, | |
| const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Unsigned, 4, false>( | |
| x, source, line, dim, mask, "MINVAL"); | |
| } | |
| CppTypeFor<TypeCategory::Unsigned, 8> RTDEF(MinvalUnsigned8)( | |
| const Descriptor &x, const char *source, int line, int dim, | |
| const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Unsigned, 8, false>( | |
| x, source, line, dim, mask, "MINVAL"); | |
| } | |
| #ifdef __SIZEOF_INT128__ | |
| CppTypeFor<TypeCategory::Unsigned, 16> RTDEF(MinvalUnsigned16)( | |
| const Descriptor &x, const char *source, int line, int dim, | |
| const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Unsigned, 16, false>( | |
| x, source, line, dim, mask, "MINVAL"); | |
| } | |
| #endif | |
| // TODO: REAL(2 & 3) | |
| CppTypeFor<TypeCategory::Real, 4> RTDEF(MinvalReal4)(const Descriptor &x, | |
| const char *source, int line, int dim, const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Real, 4, false>( | |
| x, source, line, dim, mask, "MINVAL"); | |
| } | |
| CppTypeFor<TypeCategory::Real, 8> RTDEF(MinvalReal8)(const Descriptor &x, | |
| const char *source, int line, int dim, const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Real, 8, false>( | |
| x, source, line, dim, mask, "MINVAL"); | |
| } | |
| #if HAS_FLOAT80 | |
| CppTypeFor<TypeCategory::Real, 10> RTDEF(MinvalReal10)(const Descriptor &x, | |
| const char *source, int line, int dim, const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Real, 10, false>( | |
| x, source, line, dim, mask, "MINVAL"); | |
| } | |
| #endif | |
| #if HAS_LDBL128 || HAS_FLOAT128 | |
| CppTypeFor<TypeCategory::Real, 16> RTDEF(MinvalReal16)(const Descriptor &x, | |
| const char *source, int line, int dim, const Descriptor *mask) { | |
| return TotalNumericMaxOrMin<TypeCategory::Real, 16, false>( | |
| x, source, line, dim, mask, "MINVAL"); | |
| } | |
| #endif | |
| void RTDEF(MinvalCharacter)(Descriptor &result, const Descriptor &x, | |
| const char *source, int line, const Descriptor *mask) { | |
| CharacterMaxOrMin<false>(result, x, 0, source, line, mask, "MINVAL"); | |
| } | |
| void RTDEF(MaxvalDim)(Descriptor &result, const Descriptor &x, int dim, | |
| const char *source, int line, const Descriptor *mask) { | |
| if (x.type().IsCharacter()) { | |
| CharacterMaxOrMin<true>(result, x, dim, source, line, mask, "MAXVAL"); | |
| } else { | |
| NumericMaxOrMin<true>(result, x, dim, source, line, mask, "MAXVAL"); | |
| } | |
| } | |
| void RTDEF(MinvalDim)(Descriptor &result, const Descriptor &x, int dim, | |
| const char *source, int line, const Descriptor *mask) { | |
| if (x.type().IsCharacter()) { | |
| CharacterMaxOrMin<false>(result, x, dim, source, line, mask, "MINVAL"); | |
| } else { | |
| NumericMaxOrMin<false>(result, x, dim, source, line, mask, "MINVAL"); | |
| } | |
| } | |
| RT_EXT_API_GROUP_END | |
| } // extern "C" | |
| // NORM2 | |
| extern "C" { | |
| RT_EXT_API_GROUP_BEGIN | |
| // TODO: REAL(2 & 3) | |
| CppTypeFor<TypeCategory::Real, 4> RTDEF(Norm2_4)( | |
| const Descriptor &x, const char *source, int line, int dim) { | |
| return GetTotalReduction<TypeCategory::Real, 4>( | |
| x, source, line, dim, nullptr, Norm2Accumulator<4>{x}, "NORM2"); | |
| } | |
| CppTypeFor<TypeCategory::Real, 8> RTDEF(Norm2_8)( | |
| const Descriptor &x, const char *source, int line, int dim) { | |
| return GetTotalReduction<TypeCategory::Real, 8>( | |
| x, source, line, dim, nullptr, Norm2Accumulator<8>{x}, "NORM2"); | |
| } | |
| #if HAS_FLOAT80 | |
| CppTypeFor<TypeCategory::Real, 10> RTDEF(Norm2_10)( | |
| const Descriptor &x, const char *source, int line, int dim) { | |
| return GetTotalReduction<TypeCategory::Real, 10>( | |
| x, source, line, dim, nullptr, Norm2Accumulator<10>{x}, "NORM2"); | |
| } | |
| #endif | |
| void RTDEF(Norm2Dim)(Descriptor &result, const Descriptor &x, int dim, | |
| const char *source, int line) { | |
| Terminator terminator{source, line}; | |
| auto type{x.type().GetCategoryAndKind()}; | |
| RUNTIME_CHECK(terminator, type); | |
| if (type->first == TypeCategory::Real) { | |
| ApplyFloatingPointKind<Norm2Helper, void, true>( | |
| type->second, terminator, result, x, dim, nullptr, terminator); | |
| } else { | |
| terminator.Crash("NORM2: bad type code %d", x.type().raw()); | |
| } | |
| } | |
| RT_EXT_API_GROUP_END | |
| } // extern "C" | |
| } // namespace Fortran::runtime |