xref: /llvm-project/flang/include/flang/Evaluate/complex.h (revision fc97d2e68b03bc2979395e84b645e5b3ba35aecd)
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