FLANG
complex-value.h
1//===-- include/flang/Evaluate/complex-value.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_VALUE_H_
10#define FORTRAN_EVALUATE_COMPLEX_VALUE_H_
11
12#include "real-value.h"
13#include "llvm/Support/Compiler.h"
14
15namespace llvm {
16class raw_ostream;
17}
18
19namespace Fortran::evaluate::value {
20
28class ComplexValue {
29public:
30 using Part = RealValue;
31
32 ComplexValue() = default;
33 ComplexValue(const ComplexValue &) = default;
34 ComplexValue(ComplexValue &&) = default;
35 ComplexValue &operator=(const ComplexValue &) = default;
36 ComplexValue &operator=(ComplexValue &&) = default;
37
38 ComplexValue(const RealValue &r, const RealValue &i) : re_{r}, im_{i} {
39 CHECK_MSG(r.IsNull() == i.IsNull(), "real and imag must be the same kind");
40 CHECK_MSG(r.IsNull() || i.IsNull() || r.kind() == i.kind(),
41 "real and imag must be the same kind");
42 }
43
44 explicit ComplexValue(const RealValue &r)
45 : ComplexValue{r, RealValue::Zero(r.kind())} {}
46
47 ComplexValue(int kind, const RealValue &r) : ComplexValue{r} {
48 CHECK(kind == r.kind());
49 }
50
51 ComplexValue(int kind, const ComplexValue &v) : ComplexValue{v} {
52 CHECK(kind == v.kind());
53 }
54
55 ComplexValue(int kind, ComplexValue &&v) : ComplexValue{std::move(v)} {
56 CHECK(kind == v.kind());
57 }
58
62 static ComplexValue Zero(int kind) {
64 return ComplexValue{zero, zero};
65 }
66
67 void print(llvm::raw_ostream &os) const;
68
69#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
70 LLVM_DUMP_METHOD void dump() const;
71#endif
72
75 bool IsNull() const {
76 CHECK(re_.IsNull() == im_.IsNull());
77 return re_.IsNull();
78 }
79
81 int kind() const {
82 CHECK(re_.kind() == im_.kind());
83 return re_.kind();
84 }
85
87 std::size_t bytesStored() const {
88 return re_.bytesStored() + im_.bytesStored();
89 }
90 static constexpr std::size_t bytesStored(int kind) {
91 return 2 * RealValue::bytesStored(kind);
92 }
93
94 RealValue REAL() const { return re_; }
95
96 RealValue AIMAG() const { return im_; }
97
98 ComplexValue CONJG() const { return ComplexValue{re_, im_.Negate()}; }
99
100 ComplexValue Negate() const {
101 return ComplexValue{re_.Negate(), im_.Negate()};
102 }
103
104 bool Equals(const ComplexValue &y) const {
105 return re_.Compare(y.re_) == Relation::Equal &&
106 im_.Compare(y.im_) == Relation::Equal;
107 }
108
109 bool operator==(const ComplexValue &y) const {
110 return re_ == y.re_ && im_ == y.im_;
111 }
112
113 bool operator!=(const ComplexValue &y) const { return !(*this == y); }
114
115 bool IsZero() const { return re_.IsZero() && im_.IsZero(); }
116
117 bool IsInfinite() const { return re_.IsInfinite() || im_.IsInfinite(); }
118
119 bool IsNotANumber() const { return re_.IsNotANumber() || im_.IsNotANumber(); }
120
121 bool IsSignalingNaN() const {
122 return re_.IsSignalingNaN() || im_.IsSignalingNaN();
123 }
124
125 static ValueWithRealFlags<ComplexValue> FromInteger(int kind,
126 const IntegerValue &n, bool isUnsigned = false,
127 Rounding rounding = TargetCharacteristics::defaultRounding);
128
129 ValueWithRealFlags<ComplexValue> Add(const ComplexValue &,
130 Rounding rounding = TargetCharacteristics::defaultRounding) const;
131
132 ValueWithRealFlags<ComplexValue> Subtract(const ComplexValue &,
133 Rounding rounding = TargetCharacteristics::defaultRounding) const;
134 ValueWithRealFlags<ComplexValue> Multiply(const ComplexValue &,
135 Rounding rounding = TargetCharacteristics::defaultRounding) const;
136 ValueWithRealFlags<ComplexValue> Divide(const ComplexValue &,
137 Rounding rounding = TargetCharacteristics::defaultRounding) const;
138
139 ValueWithRealFlags<ComplexValue> KahanSummation(const ComplexValue &y,
140 ComplexValue &correction,
141 Rounding rounding = TargetCharacteristics::defaultRounding) const;
142
145 Rounding rounding = TargetCharacteristics::defaultRounding) const {
146 return re_.HYPOT(im_, rounding);
147 }
148
149 ComplexValue FlushSubnormalToZero() const {
150 return ComplexValue{re_.FlushSubnormalToZero(), im_.FlushSubnormalToZero()};
151 }
152
153 static ComplexValue NotANumber(int kind) {
154 return {RealValue::NotANumber(kind), RealValue::NotANumber(kind)};
155 }
156
157 std::string DumpHexadecimal() const;
158
159 llvm::raw_ostream &AsFortran(llvm::raw_ostream &, int kind) const;
160
161 void StoreRawBytes(void *dst, size_t size, bool *changed = nullptr) const;
162
163 static ComplexValue FromRawBytes(
164 int kind, const void *raw, std::size_t expectedSize);
165
166private:
167 RealValue re_, im_;
168};
169
170} // namespace Fortran::evaluate::value
171
172namespace llvm {
174inline raw_ostream &operator<<(
175 raw_ostream &os, const Fortran::evaluate::value::ComplexValue &v) {
176 v.print(os);
177 return os;
178}
179} // namespace llvm
180
181#endif // FORTRAN_EVALUATE_COMPLEX_VALUE_H_
Definition complex-value.h:28
std::size_t bytesStored() const
Number of bytes accessed by FromRawBytes/StoreRawBytes.
Definition complex-value.h:87
bool IsNull() const
Definition complex-value.h:75
static ComplexValue Zero(int kind)
Definition complex-value.h:62
int kind() const
The kind of the value currently stored.
Definition complex-value.h:81
ValueWithRealFlags< RealValue > ABS(Rounding rounding=TargetCharacteristics::defaultRounding) const
ABS/CABS = HYPOT(re_, imag_) = SQRT(re_**2 + im_**2)
Definition complex-value.h:144
Definition real-value.h:31
int kind() const
The kind of the value currently stored.
Definition real-value.cpp:61
bool IsNull() const
Definition real-value.cpp:59
std::size_t bytesStored() const
Number of bytes accessed by FromRawBytes/StoreRawBytes.
Definition real-value.h:84
static RealValue Zero(int kind)
Definition real-value.cpp:47
Definition target-rounding.h:18