FLANG

complex.h
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(
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
80 constexpr Complex FlushSubnormalToZero() const {
81 return {re_.FlushSubnormalToZero(), im_.FlushSubnormalToZero()};
82 }
83
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_
Fortran::evaluate::Add
Definition: expression.h:278
Fortran::evaluate::Subtract
Definition: expression.h:285
Fortran::evaluate::Rounding
Definition: common.h:122
Fortran::evaluate::Divide
Definition: expression.h:299
Fortran::evaluate::Multiply
Definition: expression.h:292
Fortran::evaluate::Negate
Definition: expression.h:229
Fortran::evaluate::value::Complex
Definition: complex.h:22
Fortran::evaluate::ValueWithRealFlags
Definition: common.h:113