See discourse thread https://discourse.llvm.org/t/rfc-support-cmake-option-to-control-link-type-built-for-flang-runtime-libraries/71602/18 for full details. Flang-rt is the new library target for the flang runtime libraries. It builds the Flang-rt library (which contains the sources of FortranRuntime and FortranDecimal) and the Fortran_main library. See documentation in this patch for detailed description (flang-rt/docs/GettingStarted.md). This patch aims to: - integrate Flang's runtime into existing llvm infrasturcture so that Flang's runtime can be built similarly to other runtimes via the runtimes target or via the llvm target as an enabled runtime - decouple the FortranDecimal library sources that were used by both compiler and runtime so that different build configurations can be applied for compiler vs runtime - add support for running flang-rt testsuites, which were created by migrating relevant tests from `flang/test` and `flang/unittest` to `flang-rt/test` and `flang-rt/unittest`, using a new `check-flang-rt` target. - provide documentation on how to build and use the new FlangRT runtime Reviewed By: DanielCChen Differential Revision: https://reviews.llvm.org/D154869
171 lines
6.1 KiB
C++
171 lines
6.1 KiB
C++
//===-- flang/unittests/Runtime/Complex.cpp ---------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#include "gmock/gmock.h"
|
|
#include "gtest/gtest-matchers.h"
|
|
#include <limits>
|
|
|
|
#ifdef __clang__
|
|
#pragma clang diagnostic ignored "-Wc99-extensions"
|
|
#endif
|
|
|
|
#include "flang/Common/Fortran.h"
|
|
#include "flang/Runtime/cpp-type.h"
|
|
#include "flang/Runtime/entry-names.h"
|
|
|
|
#include <complex>
|
|
#include <cstdint>
|
|
|
|
#ifndef _MSC_VER
|
|
#include <complex.h>
|
|
typedef float _Complex float_Complex_t;
|
|
typedef double _Complex double_Complex_t;
|
|
#else
|
|
struct float_Complex_t {
|
|
float re;
|
|
float im;
|
|
};
|
|
struct double_Complex_t {
|
|
double re;
|
|
double im;
|
|
};
|
|
#endif
|
|
|
|
extern "C" float_Complex_t RTNAME(cpowi)(
|
|
float_Complex_t base, std::int32_t exp);
|
|
|
|
extern "C" double_Complex_t RTNAME(zpowi)(
|
|
double_Complex_t base, std::int32_t exp);
|
|
|
|
extern "C" float_Complex_t RTNAME(cpowk)(
|
|
float_Complex_t base, std::int64_t exp);
|
|
|
|
extern "C" double_Complex_t RTNAME(zpowk)(
|
|
double_Complex_t base, std::int64_t exp);
|
|
|
|
static std::complex<float> cpowi(std::complex<float> base, std::int32_t exp) {
|
|
float_Complex_t cbase{*(float_Complex_t *)(&base)};
|
|
float_Complex_t cres{RTNAME(cpowi)(cbase, exp)};
|
|
return *(std::complex<float> *)(&cres);
|
|
}
|
|
|
|
static std::complex<double> zpowi(std::complex<double> base, std::int32_t exp) {
|
|
double_Complex_t cbase{*(double_Complex_t *)(&base)};
|
|
double_Complex_t cres{RTNAME(zpowi)(cbase, exp)};
|
|
return *(std::complex<double> *)(&cres);
|
|
}
|
|
|
|
static std::complex<float> cpowk(std::complex<float> base, std::int64_t exp) {
|
|
float_Complex_t cbase{*(float_Complex_t *)(&base)};
|
|
float_Complex_t cres{RTNAME(cpowk)(cbase, exp)};
|
|
return *(std::complex<float> *)(&cres);
|
|
}
|
|
|
|
static std::complex<double> zpowk(std::complex<double> base, std::int64_t exp) {
|
|
double_Complex_t cbase{*(double_Complex_t *)(&base)};
|
|
double_Complex_t cres{RTNAME(zpowk)(cbase, exp)};
|
|
return *(std::complex<double> *)(&cres);
|
|
}
|
|
|
|
MATCHER_P(ExpectComplexFloatEq, c, "") {
|
|
using namespace testing;
|
|
return ExplainMatchResult(
|
|
AllOf(Property(&std::complex<float>::real, FloatEq(c.real())),
|
|
Property(&std::complex<float>::imag, FloatEq(c.imag()))),
|
|
arg, result_listener);
|
|
}
|
|
|
|
MATCHER_P(ExpectComplexDoubleEq, c, "") {
|
|
using namespace testing;
|
|
return ExplainMatchResult(AllOf(Property(&std::complex<double>::real,
|
|
DoubleNear(c.real(), 0.00000001)),
|
|
Property(&std::complex<double>::imag,
|
|
DoubleNear(c.imag(), 0.00000001))),
|
|
arg, result_listener);
|
|
}
|
|
|
|
#define EXPECT_COMPLEX_FLOAT_EQ(val1, val2) \
|
|
EXPECT_THAT(val1, ExpectComplexFloatEq(val2))
|
|
|
|
#define EXPECT_COMPLEX_DOUBLE_EQ(val1, val2) \
|
|
EXPECT_THAT(val1, ExpectComplexDoubleEq(val2))
|
|
|
|
using namespace std::literals::complex_literals;
|
|
|
|
TEST(Complex, cpowi) {
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowi(3.f + 4if, 0), 1.f + 0if);
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowi(3.f + 4if, 1), 3.f + 4if);
|
|
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowi(3.f + 4if, 2), -7.f + 24if);
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowi(3.f + 4if, 3), -117.f + 44if);
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowi(3.f + 4if, 4), -527.f - 336if);
|
|
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowi(3.f + 4if, -2), -0.0112f - 0.0384if);
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowi(2.f + 1if, 10), -237.f - 3116if);
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowi(0.5f + 0.6if, -10), -9.322937f - 7.2984829if);
|
|
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowi(2.f + 1if, 5), -38.f + 41if);
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowi(0.5f + 0.6if, -5), -1.121837f + 3.252915if);
|
|
|
|
EXPECT_COMPLEX_FLOAT_EQ(
|
|
cpowi(0.f + 1if, std::numeric_limits<std::int32_t>::min()), 1.f + 0if);
|
|
}
|
|
|
|
TEST(Complex, cpowk) {
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowk(3.f + 4if, 0), 1.f + 0if);
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowk(3.f + 4if, 1), 3.f + 4if);
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowk(3.f + 4if, 2), -7.f + 24if);
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowk(3.f + 4if, 3), -117.f + 44if);
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowk(3.f + 4if, 4), -527.f - 336if);
|
|
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowk(3.f + 4if, -2), -0.0112f - 0.0384if);
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowk(2.f + 1if, 10), -237.f - 3116if);
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowk(0.5f + 0.6if, -10), -9.322937f - 7.2984829if);
|
|
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowk(2.f + 1if, 5), -38.f + 41if);
|
|
EXPECT_COMPLEX_FLOAT_EQ(cpowk(0.5f + 0.6if, -5), -1.121837f + 3.252915if);
|
|
|
|
EXPECT_COMPLEX_FLOAT_EQ(
|
|
cpowk(0.f + 1if, std::numeric_limits<std::int64_t>::min()), 1.f + 0if);
|
|
}
|
|
|
|
TEST(Complex, zpowi) {
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowi(3. + 4i, 0), 1. + 0i);
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowi(3. + 4i, 1), 3. + 4i);
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowi(3. + 4i, 2), -7. + 24i);
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowi(3. + 4i, 3), -117. + 44i);
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowi(3. + 4i, 4), -527. - 336i);
|
|
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowi(3. + 4i, -2), -0.0112 - 0.0384i);
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowi(2. + 1i, 10), -237. - 3116i);
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowi(0.5 + 0.6i, -10), -9.32293628 - 7.29848564i);
|
|
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowi(2. + 1i, 5), -38. + 41i);
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowi(0.5 + 0.6i, -5), -1.12183773 + 3.25291503i);
|
|
|
|
EXPECT_COMPLEX_DOUBLE_EQ(
|
|
zpowi(0. + 1i, std::numeric_limits<std::int32_t>::min()), 1. + 0i);
|
|
}
|
|
|
|
TEST(Complex, zpowk) {
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowk(3. + 4i, 0), 1. + 0i);
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowk(3. + 4i, 1), 3. + 4i);
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowk(3. + 4i, 2), -7. + 24i);
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowk(3. + 4i, 3), -117. + 44i);
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowk(3. + 4i, 4), -527. - 336i);
|
|
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowk(3. + 4i, -2), -0.0112 - 0.0384i);
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowk(2. + 1i, 10), -237. - 3116i);
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowk(0.5 + 0.6i, -10), -9.32293628 - 7.29848564i);
|
|
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowk(2. + 1i, 5l), -38. + 41i);
|
|
EXPECT_COMPLEX_DOUBLE_EQ(zpowk(0.5 + 0.6i, -5), -1.12183773 + 3.25291503i);
|
|
|
|
EXPECT_COMPLEX_DOUBLE_EQ(
|
|
zpowk(0. + 1i, std::numeric_limits<std::int64_t>::min()), 1. + 0i);
|
|
}
|