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 Complex()27 constexpr Complex() {} // (+0.0, +0.0) 28 constexpr Complex(const Complex &) = default; Complex(const Part & r,const Part & i)29 constexpr Complex(const Part &r, const Part &i) : re_{r}, im_{i} {} Complex(const Part & r)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 REAL()38 constexpr const Part &REAL() const { return re_; } AIMAG()39 constexpr const Part &AIMAG() const { return im_; } CONJG()40 constexpr Complex CONJG() const { return {re_, im_.Negate()}; } Negate()41 constexpr Complex Negate() const { return {re_.Negate(), im_.Negate()}; } 42 Equals(const Complex & that)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 IsZero()48 constexpr bool IsZero() const { return re_.IsZero() || im_.IsZero(); } 49 IsInfinite()50 constexpr bool IsInfinite() const { 51 return re_.IsInfinite() || im_.IsInfinite(); 52 } 53 IsNotANumber()54 constexpr bool IsNotANumber() const { 55 return re_.IsNotANumber() || im_.IsNotANumber(); 56 } 57 IsSignalingNaN()58 constexpr bool IsSignalingNaN() const { 59 return re_.IsSignalingNaN() || im_.IsSignalingNaN(); 60 } 61 62 template <typename INT> 63 static ValueWithRealFlags<Complex> FromInteger( 64 const INT &n, Rounding rounding = defaultRounding) { 65 ValueWithRealFlags<Complex> result; 66 result.value.re_ = 67 Part::FromInteger(n, rounding).AccumulateFlags(result.flags); 68 return result; 69 } 70 71 ValueWithRealFlags<Complex> Add( 72 const Complex &, Rounding rounding = defaultRounding) const; 73 ValueWithRealFlags<Complex> Subtract( 74 const Complex &, Rounding rounding = defaultRounding) const; 75 ValueWithRealFlags<Complex> Multiply( 76 const Complex &, Rounding rounding = defaultRounding) const; 77 ValueWithRealFlags<Complex> Divide( 78 const Complex &, Rounding rounding = defaultRounding) const; 79 FlushSubnormalToZero()80 constexpr Complex FlushSubnormalToZero() const { 81 return {re_.FlushSubnormalToZero(), im_.FlushSubnormalToZero()}; 82 } 83 NotANumber()84 static constexpr Complex NotANumber() { 85 return {Part::NotANumber(), Part::NotANumber()}; 86 } 87 88 std::string DumpHexadecimal() const; 89 llvm::raw_ostream &AsFortran(llvm::raw_ostream &, int kind) const; 90 91 // TODO: (C)ABS once Real::HYPOT is done 92 // TODO: unit testing 93 94 private: 95 Part re_, im_; 96 }; 97 98 extern template class Complex<Real<Integer<16>, 11>>; 99 extern template class Complex<Real<Integer<16>, 8>>; 100 extern template class Complex<Real<Integer<32>, 24>>; 101 extern template class Complex<Real<Integer<64>, 53>>; 102 extern template class Complex<Real<Integer<80>, 64>>; 103 extern template class Complex<Real<Integer<128>, 113>>; 104 } // namespace Fortran::evaluate::value 105 #endif // FORTRAN_EVALUATE_COMPLEX_H_ 106