add_test(NAME Leadz COMMAND leading-zero-bit-count-test)
add_test(NAME PopPar COMMAND bit-population-count-test)
add_test(NAME Integer COMMAND integer-test)
+add_test(NAME Logical COMMAND logical-test)
add_test(NAME Real COMMAND real-test)
// For static expression evaluation, all the bits will have the same value.
constexpr bool IsTrue() const { return word_.BTEST(0); }
- constexpr Logical NOT() const {
- return {word_.NOT()};
- }
+ constexpr Logical NOT() const { return {word_.NOT()}; }
constexpr Logical AND(const Logical &that) const {
return {word_.IAND(that.word_)};
return {word_.IOR(that.word_)};
}
- constexpr Logical EQV(const Logical &that) const {
- return NEQV(that).NOT();
- }
+ constexpr Logical EQV(const Logical &that) const { return NEQV(that).NOT(); }
constexpr Logical NEQV(const Logical &that) const {
return {word_.IEOR(that.word_)};
return result;
}
- template<typename INT>
- constexpr INT EXPONENT() const {
+ template<typename INT> constexpr INT EXPONENT() const {
std::uint64_t exponent{Exponent()};
if (exponent == maxExponent) {
return INT::HUGE();
if (lshift + precision >= result.value.bits) {
result.flags.set(RealFlag::Overflow);
} else {
- result.value = result.value.ConvertUnsigned(fraction).value.SHIFTL(lshift);
+ result.value =
+ result.value.ConvertUnsigned(fraction).value.SHIFTL(lshift);
}
}
if (result.flags.test(RealFlag::Overflow)) {
Word word_{}; // an Integer<>
};
-using RealKind2 = Real<Integer<16>, 11>;
extern template class Real<Integer<16>, 11>;
-
-using RealKind4 = Real<Integer<32>, 24>;
extern template class Real<Integer<32>, 24>;
-
-using RealKind8 = Real<Integer<64>, 53>;
extern template class Real<Integer<64>, 53>;
-
-using RealKind10 = Real<Integer<80>, 64, false>; // 80387 extended precision
-extern template class Real<Integer<80>, 64, false>;
-
-using RealKind16 = Real<Integer<128>, 112>;
+extern template class Real<Integer<80>, 64, false>; // 80387 extended precision
extern template class Real<Integer<128>, 112>;
-
// N.B. No "double-double" support.
} // namespace Fortran::evaluate::value
using ValueType = value::Integer<8 * kind>;
};
-template<int KIND> struct Real {
+template<int KIND> struct Real;
+template<> struct Real<2> {
static constexpr Classification classification{Classification::Real};
- static constexpr int kind{KIND};
+ static constexpr int kind{2};
+ static constexpr bool hasLen{false};
+ using ValueType = value::Real<value::Integer<16>, 11>;
+};
+template<> struct Real<4> {
+ static constexpr Classification classification{Classification::Real};
+ static constexpr int kind{4};
static constexpr bool hasLen{false};
- using ValueType = value::Real<8 * K>;
+ using ValueType = value::Real<value::Integer<32>, 24>;
+};
+template<> struct Real<8> {
+ static constexpr Classification classification{Classification::Real};
+ static constexpr int kind{8};
+ static constexpr bool hasLen{false};
+ using ValueType = value::Real<value::Integer<64>, 53>;
+};
+template<> struct Real<10> {
+ static constexpr Classification classification{Classification::Real};
+ static constexpr int kind{10};
+ static constexpr bool hasLen{false};
+ using ValueType = value::Real<value::Integer<80>, 64, false>;
+};
+template<> struct Real<16> {
+ static constexpr Classification classification{Classification::Real};
+ static constexpr int kind{16};
+ static constexpr bool hasLen{false};
+ using ValueType = value::Real<value::Integer<128>, 112>;
};
#if 0 // TODO
static constexpr Classification classification{Classification::Complex};
static constexpr int kind{KIND};
static constexpr bool hasLen{false};
- using ValueType = value::Complex<8 * K>;
+ using ValueType = value::Complex<8 * kind>;
};
#endif
static constexpr Classification classification{Classification::Logical};
static constexpr int kind{KIND};
static constexpr bool hasLen{false};
- using ValueType = value::Logical<8 * K>;
+ using ValueType = value::Logical<8 * kind>;
};
#if 0 // TODO
static constexpr Classification classification{Classification::Character};
static constexpr int kind{KIND};
static constexpr bool hasLen{true};
- using ValueType = value::Character<8 * K>;
+ using ValueType = value::Character<8 * kind>;
};
#endif
using DefaultReal = Real<4>;
using DefaultInteger = Integer<DefaultReal::kind>;
using IntrinsicTypeParameterType = DefaultInteger;
-#if 0 // TODO
+#if 0 // TODO
using DefaultComplex = Complex<2 * DefaultReal::kind>;
#endif
using DefaultLogical = Logical<DefaultReal::kind>;
-#if 0 // TODO
+#if 0 // TODO
using DefaultCharacter = Character<1>;
#endif
-} // namespace Fortran::evaluate
+} // namespace Fortran::evaluate::type
#endif // FORTRAN_EVALUATE_TYPE_H_
FortranEvaluateTesting
)
+add_executable(logical-test
+ logical.cc
+)
+
+target_link_libraries(logical-test
+ FortranEvaluate
+ FortranEvaluateTesting
+)
+
add_executable(real-test
real.cc
)
#include "testing.h"
#include <cstdio>
-using Fortran::evaluate::value::Integer;
using Fortran::evaluate::Ordering;
+using Fortran::evaluate::value::Integer;
template<int BITS, typename INT = Integer<BITS>> void exhaustiveTesting() {
std::uint64_t maxUnsignedValue{(std::uint64_t{1} << BITS) - 1};
--- /dev/null
+// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "testing.h"
+#include "../../lib/evaluate/type.h"
+#include <cstdio>
+
+using namespace Fortran::evaluate::type;
+
+template<int KIND> void testKind() {
+ using Type = Logical<KIND>;
+ TEST(Type::classification == Classification::Logical);
+ TEST(Type::kind == KIND);
+ TEST(!Type::hasLen);
+ using Value = typename Type::ValueType;
+ MATCH(8 * KIND, Value::bits);
+ TEST(!Value{}.IsTrue());
+ TEST(!Value{false}.IsTrue());
+ TEST(Value{true}.IsTrue());
+ TEST(Value{false}.NOT().IsTrue());
+ TEST(!Value{true}.NOT().IsTrue());
+ TEST(!Value{false}.AND(Value{false}).IsTrue());
+ TEST(!Value{false}.AND(Value{true}).IsTrue());
+ TEST(!Value{true}.AND(Value{false}).IsTrue());
+ TEST(Value{true}.AND(Value{true}).IsTrue());
+ TEST(!Value{false}.OR(Value{false}).IsTrue());
+ TEST(Value{false}.OR(Value{true}).IsTrue());
+ TEST(Value{true}.OR(Value{false}).IsTrue());
+ TEST(Value{true}.OR(Value{true}).IsTrue());
+ TEST(Value{false}.EQV(Value{false}).IsTrue());
+ TEST(!Value{false}.EQV(Value{true}).IsTrue());
+ TEST(!Value{true}.EQV(Value{false}).IsTrue());
+ TEST(Value{true}.EQV(Value{true}).IsTrue());
+ TEST(!Value{false}.NEQV(Value{false}).IsTrue());
+ TEST(Value{false}.NEQV(Value{true}).IsTrue());
+ TEST(Value{true}.NEQV(Value{false}).IsTrue());
+ TEST(!Value{true}.NEQV(Value{true}).IsTrue());
+}
+
+int main() {
+ testKind<1>();
+ testKind<2>();
+ testKind<4>();
+ testKind<8>();
+ testKind<16>();
+ return testing::Complete();
+}