From: peter klausler Date: Fri, 1 Jun 2018 22:30:31 +0000 (-0700) Subject: [flang] begin real.h X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0fb4b25ac80ddbc9066e21c4b2dd5983f02b8062;p=platform%2Fupstream%2Fllvm.git [flang] begin real.h Original-commit: flang-compiler/f18@b0f0cd896161d769efc3f499cd3ae1359c82953a Reviewed-on: https://github.com/flang-compiler/f18/pull/101 Tree-same-pre-rewrite: false --- diff --git a/flang/lib/evaluate/common.h b/flang/lib/evaluate/common.h index 67c4f54..c62223e 100644 --- a/flang/lib/evaluate/common.h +++ b/flang/lib/evaluate/common.h @@ -33,6 +33,16 @@ static constexpr Ordering Reverse(Ordering ordering) { } } +static constexpr Relation RelationFromOrdering(Ordering ordering) { + if (ordering == Ordering::Less) { + return Relation::Less; + } else if (ordering == Ordering::Greater) { + return Relation::Greater; + } else { + return Relation::Equal; + } +} + static constexpr Relation Reverse(Relation relation) { if (relation == Relation::Less) { return Relation::Greater; diff --git a/flang/lib/evaluate/integer.h b/flang/lib/evaluate/integer.h index 63de0e2..a9e1932 100644 --- a/flang/lib/evaluate/integer.h +++ b/flang/lib/evaluate/integer.h @@ -191,6 +191,8 @@ public: return {result, overflow}; } + // TODO formatting + static constexpr Integer HUGE() { return MASKR(bits - 1); } // Returns the number of full decimal digits that can be represented. diff --git a/flang/lib/evaluate/real.h b/flang/lib/evaluate/real.h new file mode 100644 index 0000000..c0d68b1 --- /dev/null +++ b/flang/lib/evaluate/real.h @@ -0,0 +1,120 @@ +// 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. + +#ifndef FORTRAN_EVALUATE_REAL_H_ +#define FORTRAN_EVALUATE_REAL_H_ + +#include "common.h" +#include "integer.h" +#include + +namespace Fortran::evaluate { + +// The class template parameter specifies the total number of bits in the +// significand, including any bit that might be implicit in a machine +// representation. +template class Real { +public: + static constexpr int significandBits{SIGNIFICAND_BITS}; + static_assert(significandBits > 0); + + constexpr Real() {} // +0.0 + constexpr Real(std::int64_t n) + : significand_{n}, exponent_{64}, negative_{n < 0} { + if (negative_) { + significand_ = significand_.Negate().value; // overflow is safe to ignore + } + Normalize(); + } + + constexpr bool IsNegative() const { return negative_ && !notANumber_; } + constexpr bool IsFinite() const { return !infinite_ && !notANumber_; } + constexpr bool IsInfinite() const { return infinite_ && !notANumber_; } + constexpr bool IsANumber() const { return !notANumber_; } + constexpr bool IsNotANumber() const { return notANumber_; } + constexpr bool IsZero() const { return !notANumber_ && significand_.IsZero(); } + + constexpr Relation Compare(const Real &y) const { + if (notANumber_ || y.notANumber_) { + return Relation::Unordered; + } else if (infinite_) { + if (y.infinite_) { + if (negative_) { + return y.negative_ ? Relation::Equal : Relation::Less; + } else { + return y.negative_ ? Relation::Greater : Relation::Equal; + } + } else { + return negative_ ? Relation::Less : Relation::Greater; + } + } else if (y.infinite_) { + return y.negative_ ? Relation::Greater : Relation::Less; + } else { + // two finite numbers + if (exponent_ == y.exponent_) { + Ordering order{significand_.CompareUnsigned(y.significand_)}; + if (order == Ordering::Equal) { + if (negative_ == y.negative_ || + (exponent_ == 0 && significand_.IsZero())) { + // Ignore signs on zeros, +0.0 == -0.0 + return Relation::Equal; + } else { + // finite nonzero numbers, same exponent & significand + return negative_ ? Relation::Less : Relation::Greater; + } + } else { + // finite numbers, same exponent, distinct significands + if (negative_ != y.negative_) { + return negative_ ? Relation::Less : Relation::Greater; + } else { + return RelationFromOrdering(order); + } + } + } else { + // not same exponent + if (negative_ != y.negative_) { + return negative_ ? Relation::Less : Relation::Greater; + } else { + return exponent_ < y.exponent_ ? Relation::Less : Relation::Greater; + } + } + } + } + +private: + using Significand = Integer; + using DoubleSignificand = Integer<2 * significandBits>; + + // All values are normalized on output and assumed normal on input. + void Normalize() { + if (!notANumber_ && !infinite_) { + int shift{significand_.LEADZ()}; + if (shift >= significandBits) { + exponent_ = 0; // +/-0.0 + } else { + exponent_ -= shift; + significand_ = significand_.SHIFTL(shift); + } + } + } + + Significand significand_{}; + int exponent_{0}; // unbiased; 1.0 has exponent 1 + bool negative_{false}; + bool infinite_{false}; + bool notANumber_{false}; +}; + +} // namespace Fortran::evaluate +#endif // FORTRAN_EVALUATE_REAL_H_