1 //===-- include/flang/Evaluate/complex.h ------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef FORTRAN_EVALUATE_COMPLEX_H_ 10 #define FORTRAN_EVALUATE_COMPLEX_H_ 11 12 #include "formatting.h" 13 #include "real.h" 14 #include <string> 15 16 namespace llvm { 17 class raw_ostream; 18 } 19 20 namespace Fortran::evaluate::value { 21 22 template <typename REAL_TYPE> class Complex { 23 public: 24 using Part = REAL_TYPE; 25 static constexpr int bits{2 * Part::bits}; 26 27 constexpr Complex() {} // (+0.0, +0.0) 28 constexpr Complex(const Complex &) = default; 29 constexpr Complex(const Part &r, const Part &i) : re_{r}, im_{i} {} 30 explicit constexpr Complex(const Part &r) : re_{r} {} 31 constexpr Complex &operator=(const Complex &) = default; 32 constexpr Complex &operator=(Complex &&) = default; 33 34 constexpr bool operator==(const Complex &that) const { 35 return re_ == that.re_ && im_ == that.im_; 36 } 37 38 constexpr const Part &REAL() const { return re_; } 39 constexpr const Part &AIMAG() const { return im_; } 40 constexpr Complex CONJG() const { return {re_, im_.Negate()}; } 41 constexpr Complex Negate() const { return {re_.Negate(), im_.Negate()}; } 42 43 constexpr bool Equals(const Complex &that) const { 44 return re_.Compare(that.re_) == Relation::Equal && 45 im_.Compare(that.im_) == Relation::Equal; 46 } 47 48 constexpr bool IsZero() const { return re_.IsZero() || im_.IsZero(); } 49 50 constexpr bool IsInfinite() const { 51 return re_.IsInfinite() || im_.IsInfinite(); 52 } 53 54 constexpr bool IsNotANumber() const { 55 return re_.IsNotANumber() || im_.IsNotANumber(); 56 } 57 58 constexpr bool IsSignalingNaN() const { 59 return re_.IsSignalingNaN() || im_.IsSignalingNaN(); 60 } 61 62 template <typename INT> 63 static ValueWithRealFlags<Complex> FromInteger(const INT &n, 64 bool isUnsigned = false, 65 Rounding rounding = TargetCharacteristics::defaultRounding) { 66 ValueWithRealFlags<Complex> result; 67 result.value.re_ = Part::FromInteger(n, isUnsigned, rounding) 68 .AccumulateFlags(result.flags); 69 return result; 70 } 71 72 ValueWithRealFlags<Complex> Add(const Complex &, 73 Rounding rounding = TargetCharacteristics::defaultRounding) const; 74 ValueWithRealFlags<Complex> Subtract(const Complex &, 75 Rounding rounding = TargetCharacteristics::defaultRounding) const; 76 ValueWithRealFlags<Complex> Multiply(const Complex &, 77 Rounding rounding = TargetCharacteristics::defaultRounding) const; 78 ValueWithRealFlags<Complex> Divide(const Complex &, 79 Rounding rounding = TargetCharacteristics::defaultRounding) const; 80 81 // ABS/CABS = HYPOT(re_, imag_) = SQRT(re_**2 + im_**2) 82 ValueWithRealFlags<Part> ABS( 83 Rounding rounding = TargetCharacteristics::defaultRounding) const { 84 return re_.HYPOT(im_, rounding); 85 } 86 87 constexpr Complex FlushSubnormalToZero() const { 88 return {re_.FlushSubnormalToZero(), im_.FlushSubnormalToZero()}; 89 } 90 91 static constexpr Complex NotANumber() { 92 return {Part::NotANumber(), Part::NotANumber()}; 93 } 94 95 std::string DumpHexadecimal() const; 96 llvm::raw_ostream &AsFortran(llvm::raw_ostream &, int kind) const; 97 98 // TODO: unit testing 99 100 private: 101 Part re_, im_; 102 }; 103 104 extern template class Complex<Real<Integer<16>, 11>>; 105 extern template class Complex<Real<Integer<16>, 8>>; 106 extern template class Complex<Real<Integer<32>, 24>>; 107 extern template class Complex<Real<Integer<64>, 53>>; 108 extern template class Complex<Real<X87IntegerContainer, 64>>; 109 extern template class Complex<Real<Integer<128>, 113>>; 110 } // namespace Fortran::evaluate::value 111 #endif // FORTRAN_EVALUATE_COMPLEX_H_ 112