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