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-consts.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