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