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
16namespace llvm {
17class raw_ostream;
18}
19
20namespace Fortran::evaluate::value {
21
22template <typename REAL_TYPE> class Complex {
23public:
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) {
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 ValueWithRealFlags<Complex> KahanSummation(const Complex &,
81 Complex &correction,
82 Rounding rounding = TargetCharacteristics::defaultRounding) const;
83
84 // ABS/CABS = HYPOT(re_, imag_) = SQRT(re_**2 + im_**2)
86 Rounding rounding = TargetCharacteristics::defaultRounding) const {
87 return re_.HYPOT(im_, rounding);
88 }
89
90 constexpr Complex FlushSubnormalToZero() const {
91 return {re_.FlushSubnormalToZero(), im_.FlushSubnormalToZero()};
92 }
93
94 static constexpr Complex NotANumber() {
95 return {Part::NotANumber(), Part::NotANumber()};
96 }
97
98 std::string DumpHexadecimal() const;
99 llvm::raw_ostream &AsFortran(llvm::raw_ostream &, int kind) const;
100
103 constexpr static std::size_t bytesStored() { return 2 * Part::bytesStored(); }
104
107 static Complex FromRawBytes(
108 const void *raw, [[maybe_unused]] std::size_t expectedSize) {
109 CHECK(bytesStored() == expectedSize);
110 const char *data{static_cast<const char *>(raw)};
111 Part realPart{Part::FromRawBytes(data, Part::bytesStored())};
112 Part imagPart{
113 Part::FromRawBytes(data + Part::bytesStored(), Part::bytesStored())};
114 return {realPart, imagPart};
115 }
116
120 void StoreRawBytes(void *dst, [[maybe_unused]] size_t expectedSize,
121 bool *changed = nullptr) const {
122 CHECK(expectedSize == bytesStored());
123 re_.StoreRawBytes(dst, Part::bytesStored(), changed);
124 im_.StoreRawBytes(static_cast<char *>(dst) + Part::bytesStored(),
125 Part::bytesStored(), changed);
126 }
127
128 // TODO: unit testing
129
130private:
131 Part re_, im_;
132};
133
134extern template class Complex<Real<Integer<16>, 11>>;
135extern template class Complex<Real<Integer<16>, 8>>;
136extern template class Complex<Real<Integer<32>, 24>>;
137extern template class Complex<Real<Integer<64>, 53>>;
138extern template class Complex<Real<X87IntegerContainer, 64>>;
139extern template class Complex<Real<Integer<128>, 113>>;
140} // namespace Fortran::evaluate::value
141#endif // FORTRAN_EVALUATE_COMPLEX_H_
static constexpr std::size_t bytesStored()
Definition complex.h:103
void StoreRawBytes(void *dst, size_t expectedSize, bool *changed=nullptr) const
Definition complex.h:120
static Complex FromRawBytes(const void *raw, std::size_t expectedSize)
Definition complex.h:107
Definition target-rounding.h:18