1 | //===-- flang/unittests/Runtime/Complex.cpp ---------------------*- 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 | #include "gmock/gmock.h" |
9 | #include "gtest/gtest-matchers.h" |
10 | #include <limits> |
11 | |
12 | #ifdef __clang__ |
13 | #pragma clang diagnostic ignored "-Wc99-extensions" |
14 | #endif |
15 | |
16 | #include "flang/Common/Fortran.h" |
17 | #include "flang/Runtime/cpp-type.h" |
18 | #include "flang/Runtime/entry-names.h" |
19 | |
20 | #include <complex> |
21 | #include <cstdint> |
22 | |
23 | #ifndef _MSC_VER |
24 | #include <complex.h> |
25 | typedef float _Complex float_Complex_t; |
26 | typedef double _Complex double_Complex_t; |
27 | #else |
28 | struct float_Complex_t { |
29 | float re; |
30 | float im; |
31 | }; |
32 | struct double_Complex_t { |
33 | double re; |
34 | double im; |
35 | }; |
36 | #endif |
37 | |
38 | extern "C" float_Complex_t RTNAME(cpowi)( |
39 | float_Complex_t base, std::int32_t exp); |
40 | |
41 | extern "C" double_Complex_t RTNAME(zpowi)( |
42 | double_Complex_t base, std::int32_t exp); |
43 | |
44 | extern "C" float_Complex_t RTNAME(cpowk)( |
45 | float_Complex_t base, std::int64_t exp); |
46 | |
47 | extern "C" double_Complex_t RTNAME(zpowk)( |
48 | double_Complex_t base, std::int64_t exp); |
49 | |
50 | static std::complex<float> cpowi(std::complex<float> base, std::int32_t exp) { |
51 | float_Complex_t cbase{*(float_Complex_t *)(&base)}; |
52 | float_Complex_t cres{RTNAME(cpowi)(cbase, exp)}; |
53 | return *(std::complex<float> *)(&cres); |
54 | } |
55 | |
56 | static std::complex<double> zpowi(std::complex<double> base, std::int32_t exp) { |
57 | double_Complex_t cbase{*(double_Complex_t *)(&base)}; |
58 | double_Complex_t cres{RTNAME(zpowi)(cbase, exp)}; |
59 | return *(std::complex<double> *)(&cres); |
60 | } |
61 | |
62 | static std::complex<float> cpowk(std::complex<float> base, std::int64_t exp) { |
63 | float_Complex_t cbase{*(float_Complex_t *)(&base)}; |
64 | float_Complex_t cres{RTNAME(cpowk)(cbase, exp)}; |
65 | return *(std::complex<float> *)(&cres); |
66 | } |
67 | |
68 | static std::complex<double> zpowk(std::complex<double> base, std::int64_t exp) { |
69 | double_Complex_t cbase{*(double_Complex_t *)(&base)}; |
70 | double_Complex_t cres{RTNAME(zpowk)(cbase, exp)}; |
71 | return *(std::complex<double> *)(&cres); |
72 | } |
73 | |
74 | MATCHER_P(ExpectComplexFloatEq, c, "" ) { |
75 | using namespace testing; |
76 | return ExplainMatchResult( |
77 | AllOf(Property(&std::complex<float>::real, FloatEq(c.real())), |
78 | Property(&std::complex<float>::imag, FloatEq(c.imag()))), |
79 | arg, result_listener); |
80 | } |
81 | |
82 | MATCHER_P(ExpectComplexDoubleEq, c, "" ) { |
83 | using namespace testing; |
84 | return ExplainMatchResult(AllOf(Property(&std::complex<double>::real, |
85 | DoubleNear(c.real(), 0.00000001)), |
86 | Property(&std::complex<double>::imag, |
87 | DoubleNear(c.imag(), 0.00000001))), |
88 | arg, result_listener); |
89 | } |
90 | |
91 | #define EXPECT_COMPLEX_FLOAT_EQ(val1, val2) \ |
92 | EXPECT_THAT(val1, ExpectComplexFloatEq(val2)) |
93 | |
94 | #define EXPECT_COMPLEX_DOUBLE_EQ(val1, val2) \ |
95 | EXPECT_THAT(val1, ExpectComplexDoubleEq(val2)) |
96 | |
97 | using namespace std::literals::complex_literals; |
98 | |
99 | TEST(Complex, cpowi) { |
100 | EXPECT_COMPLEX_FLOAT_EQ(cpowi(3.f + 4if, 0), 1.f + 0if); |
101 | EXPECT_COMPLEX_FLOAT_EQ(cpowi(3.f + 4if, 1), 3.f + 4if); |
102 | |
103 | EXPECT_COMPLEX_FLOAT_EQ(cpowi(3.f + 4if, 2), -7.f + 24if); |
104 | EXPECT_COMPLEX_FLOAT_EQ(cpowi(3.f + 4if, 3), -117.f + 44if); |
105 | EXPECT_COMPLEX_FLOAT_EQ(cpowi(3.f + 4if, 4), -527.f - 336if); |
106 | |
107 | EXPECT_COMPLEX_FLOAT_EQ(cpowi(3.f + 4if, -2), -0.0112f - 0.0384if); |
108 | EXPECT_COMPLEX_FLOAT_EQ(cpowi(2.f + 1if, 10), -237.f - 3116if); |
109 | EXPECT_COMPLEX_FLOAT_EQ(cpowi(0.5f + 0.6if, -10), -9.322937f - 7.2984829if); |
110 | |
111 | EXPECT_COMPLEX_FLOAT_EQ(cpowi(2.f + 1if, 5), -38.f + 41if); |
112 | EXPECT_COMPLEX_FLOAT_EQ(cpowi(0.5f + 0.6if, -5), -1.121837f + 3.252915if); |
113 | |
114 | EXPECT_COMPLEX_FLOAT_EQ( |
115 | cpowi(0.f + 1if, std::numeric_limits<std::int32_t>::min()), 1.f + 0if); |
116 | } |
117 | |
118 | TEST(Complex, cpowk) { |
119 | EXPECT_COMPLEX_FLOAT_EQ(cpowk(3.f + 4if, 0), 1.f + 0if); |
120 | EXPECT_COMPLEX_FLOAT_EQ(cpowk(3.f + 4if, 1), 3.f + 4if); |
121 | EXPECT_COMPLEX_FLOAT_EQ(cpowk(3.f + 4if, 2), -7.f + 24if); |
122 | EXPECT_COMPLEX_FLOAT_EQ(cpowk(3.f + 4if, 3), -117.f + 44if); |
123 | EXPECT_COMPLEX_FLOAT_EQ(cpowk(3.f + 4if, 4), -527.f - 336if); |
124 | |
125 | EXPECT_COMPLEX_FLOAT_EQ(cpowk(3.f + 4if, -2), -0.0112f - 0.0384if); |
126 | EXPECT_COMPLEX_FLOAT_EQ(cpowk(2.f + 1if, 10), -237.f - 3116if); |
127 | EXPECT_COMPLEX_FLOAT_EQ(cpowk(0.5f + 0.6if, -10), -9.322937f - 7.2984829if); |
128 | |
129 | EXPECT_COMPLEX_FLOAT_EQ(cpowk(2.f + 1if, 5), -38.f + 41if); |
130 | EXPECT_COMPLEX_FLOAT_EQ(cpowk(0.5f + 0.6if, -5), -1.121837f + 3.252915if); |
131 | |
132 | EXPECT_COMPLEX_FLOAT_EQ( |
133 | cpowk(0.f + 1if, std::numeric_limits<std::int64_t>::min()), 1.f + 0if); |
134 | } |
135 | |
136 | TEST(Complex, zpowi) { |
137 | EXPECT_COMPLEX_DOUBLE_EQ(zpowi(3. + 4i, 0), 1. + 0i); |
138 | EXPECT_COMPLEX_DOUBLE_EQ(zpowi(3. + 4i, 1), 3. + 4i); |
139 | EXPECT_COMPLEX_DOUBLE_EQ(zpowi(3. + 4i, 2), -7. + 24i); |
140 | EXPECT_COMPLEX_DOUBLE_EQ(zpowi(3. + 4i, 3), -117. + 44i); |
141 | EXPECT_COMPLEX_DOUBLE_EQ(zpowi(3. + 4i, 4), -527. - 336i); |
142 | |
143 | EXPECT_COMPLEX_DOUBLE_EQ(zpowi(3. + 4i, -2), -0.0112 - 0.0384i); |
144 | EXPECT_COMPLEX_DOUBLE_EQ(zpowi(2. + 1i, 10), -237. - 3116i); |
145 | EXPECT_COMPLEX_DOUBLE_EQ(zpowi(0.5 + 0.6i, -10), -9.32293628 - 7.29848564i); |
146 | |
147 | EXPECT_COMPLEX_DOUBLE_EQ(zpowi(2. + 1i, 5), -38. + 41i); |
148 | EXPECT_COMPLEX_DOUBLE_EQ(zpowi(0.5 + 0.6i, -5), -1.12183773 + 3.25291503i); |
149 | |
150 | EXPECT_COMPLEX_DOUBLE_EQ( |
151 | zpowi(0. + 1i, std::numeric_limits<std::int32_t>::min()), 1. + 0i); |
152 | } |
153 | |
154 | TEST(Complex, zpowk) { |
155 | EXPECT_COMPLEX_DOUBLE_EQ(zpowk(3. + 4i, 0), 1. + 0i); |
156 | EXPECT_COMPLEX_DOUBLE_EQ(zpowk(3. + 4i, 1), 3. + 4i); |
157 | EXPECT_COMPLEX_DOUBLE_EQ(zpowk(3. + 4i, 2), -7. + 24i); |
158 | EXPECT_COMPLEX_DOUBLE_EQ(zpowk(3. + 4i, 3), -117. + 44i); |
159 | EXPECT_COMPLEX_DOUBLE_EQ(zpowk(3. + 4i, 4), -527. - 336i); |
160 | |
161 | EXPECT_COMPLEX_DOUBLE_EQ(zpowk(3. + 4i, -2), -0.0112 - 0.0384i); |
162 | EXPECT_COMPLEX_DOUBLE_EQ(zpowk(2. + 1i, 10), -237. - 3116i); |
163 | EXPECT_COMPLEX_DOUBLE_EQ(zpowk(0.5 + 0.6i, -10), -9.32293628 - 7.29848564i); |
164 | |
165 | EXPECT_COMPLEX_DOUBLE_EQ(zpowk(2. + 1i, 5l), -38. + 41i); |
166 | EXPECT_COMPLEX_DOUBLE_EQ(zpowk(0.5 + 0.6i, -5), -1.12183773 + 3.25291503i); |
167 | |
168 | EXPECT_COMPLEX_DOUBLE_EQ( |
169 | zpowk(0. + 1i, std::numeric_limits<std::int64_t>::min()), 1. + 0i); |
170 | } |
171 | |