327 lines
11 KiB
C++
327 lines
11 KiB
C++
// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "paddle/phi/common/complex.h"
|
|
|
|
#include <complex>
|
|
|
|
#include "paddle/phi/kernels/funcs/eigen/extensions.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
#include "paddle/fluid/framework/lod_tensor.h"
|
|
#include "paddle/fluid/platform/enforce.h"
|
|
|
|
namespace paddle::platform {
|
|
|
|
template <typename T>
|
|
using complex = phi::dtype::complex<T>;
|
|
|
|
TEST(complex, conversion_cpu) {
|
|
// *********** complex<float> *************
|
|
// float to complex<float>
|
|
EXPECT_EQ(complex<float>().real, 0.0f);
|
|
EXPECT_EQ(complex<float>().imag, 0.0f);
|
|
|
|
EXPECT_EQ(complex<float>(1.0f, 1.0f).real, 1.0f);
|
|
EXPECT_EQ(complex<float>(1.0f, 1.0f).imag, 1.0f);
|
|
EXPECT_EQ(complex<float>(0.0f, 1.0f).real, 0.0f);
|
|
EXPECT_EQ(complex<float>(0.0f, 1.0f).imag, 1.0f);
|
|
|
|
EXPECT_EQ(complex<float>(1.0f).real, 1.0f);
|
|
EXPECT_EQ(complex<float>(1.0f).imag, 0.0f);
|
|
|
|
// int to complex<float>
|
|
EXPECT_EQ(complex<float>(1).real, 1.0f);
|
|
EXPECT_EQ(complex<float>(0).real, 0.0f);
|
|
EXPECT_EQ(complex<float>(2).real, 2.0f);
|
|
EXPECT_EQ(complex<float>(-2).real, -2.0f);
|
|
|
|
// bool to complex
|
|
EXPECT_EQ(complex<float>(true).real, 1.0f);
|
|
EXPECT_EQ(complex<float>(true).imag, 0.0f);
|
|
|
|
// complex<double> to complex<float>
|
|
EXPECT_EQ(complex<float>(complex<double>(1.0, 2.0)).real, 1.0f);
|
|
EXPECT_EQ(complex<float>(complex<double>(1.0, 2.0)).imag, 2.0f);
|
|
|
|
// std::complex<float> to complex<float>
|
|
EXPECT_EQ(complex<float>(std::complex<float>(1.0f, 2.0f)).real, 1.0f);
|
|
EXPECT_EQ(complex<float>(std::complex<float>(1.0f, 2.0f)).imag, 2.0f);
|
|
EXPECT_EQ(complex<float>(std::complex<double>(1.0, 2.0)).real, 1.0f);
|
|
EXPECT_EQ(complex<float>(std::complex<double>(1.0, 2.0)).imag, 2.0f);
|
|
|
|
// Assignment operator
|
|
complex<float> c = 1.0f;
|
|
EXPECT_EQ(c.real, 1.0f);
|
|
EXPECT_EQ(c.imag, 0.0f);
|
|
c = complex<float>(2.0, 2.0);
|
|
EXPECT_EQ(c.real, 2.0f);
|
|
EXPECT_EQ(c.imag, 2.0f);
|
|
|
|
// Conversion operator
|
|
EXPECT_EQ(static_cast<float>(complex<float>(0.5f)), 0.5f);
|
|
EXPECT_NEAR(static_cast<double>(complex<float>(0.33333)), 0.33333, 0.01);
|
|
EXPECT_EQ(static_cast<int>(complex<float>(-1)), -1);
|
|
EXPECT_EQ(static_cast<bool>(complex<float>(true)), true);
|
|
|
|
// *********** complex<double> *************
|
|
// double to complex<double>
|
|
EXPECT_EQ(complex<double>().real, 0.0);
|
|
EXPECT_EQ(complex<double>().imag, 0.0);
|
|
|
|
EXPECT_EQ(complex<double>(1.0, 1.0).real, 1.0);
|
|
EXPECT_EQ(complex<double>(1.0, 1.0).imag, 1.0);
|
|
EXPECT_EQ(complex<double>(0.0, 1.0).real, 0.0);
|
|
EXPECT_EQ(complex<double>(0.0, 1.0).imag, 1.0);
|
|
|
|
EXPECT_EQ(complex<double>(1.0).real, 1.0);
|
|
EXPECT_EQ(complex<double>(1.0).imag, 0.0);
|
|
|
|
// int to complex<double>
|
|
EXPECT_EQ(complex<double>(1).real, 1.0);
|
|
EXPECT_EQ(complex<double>(0).real, 0.0);
|
|
EXPECT_EQ(complex<double>(2).real, 2.0);
|
|
EXPECT_EQ(complex<double>(-2).real, -2.0);
|
|
|
|
// bool to complex
|
|
EXPECT_EQ(complex<double>(true).real, 1.0);
|
|
EXPECT_EQ(complex<double>(true).imag, 0.0);
|
|
|
|
// complex<float> to complex<double>
|
|
EXPECT_EQ(complex<double>(complex<float>(1.0f, 2.0f)).real, 1.0);
|
|
EXPECT_EQ(complex<double>(complex<float>(1.0f, 2.0f)).imag, 2.0);
|
|
|
|
// std::complex<float> to complex<double>
|
|
EXPECT_EQ(complex<double>(std::complex<double>(1.0, 2.0)).real, 1.0);
|
|
EXPECT_EQ(complex<double>(std::complex<double>(1.0, 2.0)).imag, 2.0);
|
|
EXPECT_EQ(complex<double>(std::complex<double>(1.0, 2.0)).real, 1.0);
|
|
EXPECT_EQ(complex<double>(std::complex<double>(1.0, 2.0)).imag, 2.0);
|
|
|
|
// Assignment operator
|
|
complex<double> c1 = 1.0;
|
|
EXPECT_EQ(c1.real, 1.0);
|
|
EXPECT_EQ(c1.imag, 0.0);
|
|
c1 = complex<double>(2.0, 2.0);
|
|
EXPECT_EQ(c1.real, 2.0);
|
|
EXPECT_EQ(c1.imag, 2.0);
|
|
|
|
// Conversion operator
|
|
EXPECT_EQ(static_cast<double>(complex<double>(0.5)), 0.5);
|
|
EXPECT_NEAR(static_cast<double>(complex<double>(0.33333)), 0.33333, 0.01);
|
|
EXPECT_EQ(static_cast<int>(complex<double>(-1)), -1);
|
|
EXPECT_EQ(static_cast<bool>(complex<double>(true)), true);
|
|
}
|
|
|
|
TEST(bfloat16, comparison_cpu) {
|
|
// *********** complex<float> *************
|
|
EXPECT_TRUE(complex<float>(1.0f) == complex<float>(1.0f));
|
|
EXPECT_TRUE(complex<float>(1.0f, 2.0f) == complex<float>(1.0f, 2.0f));
|
|
EXPECT_FALSE(complex<float>(-1.0f) == complex<float>(-0.5f));
|
|
EXPECT_TRUE(complex<float>(1.0f) != complex<float>(0.5f));
|
|
EXPECT_FALSE(complex<float>(-1.0f) != complex<float>(-1.0f));
|
|
EXPECT_TRUE(complex<float>(1.0f) < complex<float>(2.0f));
|
|
EXPECT_FALSE(complex<float>(-1.0f) < complex<float>(-1.0f));
|
|
EXPECT_TRUE(complex<float>(1.0f) <= complex<float>(1.0f));
|
|
EXPECT_TRUE(complex<float>(2.0f) > complex<float>(1.0f));
|
|
EXPECT_FALSE(complex<float>(-2.0f) > complex<float>(-2.0f));
|
|
EXPECT_TRUE(complex<float>(2.0f) >= complex<float>(2.0f));
|
|
|
|
// *********** complex<double> *************
|
|
EXPECT_TRUE(complex<double>(1.0) == complex<double>(1.0));
|
|
EXPECT_TRUE(complex<double>(1.0, 2.0) == complex<double>(1.0, 2.0));
|
|
EXPECT_FALSE(complex<double>(-1.0) == complex<double>(-0.5f));
|
|
EXPECT_TRUE(complex<double>(1.0) != complex<double>(0.5f));
|
|
EXPECT_FALSE(complex<double>(-1.0) != complex<double>(-1.0));
|
|
EXPECT_TRUE(complex<double>(1.0) < complex<double>(2.0));
|
|
EXPECT_FALSE(complex<double>(-1.0) < complex<double>(-1.0));
|
|
EXPECT_TRUE(complex<double>(1.0) <= complex<double>(1.0));
|
|
EXPECT_TRUE(complex<double>(2.0) > complex<double>(1.0));
|
|
EXPECT_FALSE(complex<double>(-2.0) > complex<double>(-2.0));
|
|
EXPECT_TRUE(complex<double>(2.0) >= complex<double>(2.0));
|
|
}
|
|
|
|
TEST(complex, arithmetic_cpu) {
|
|
// *********** complex<float> *************
|
|
complex<float> a = complex<float>(1, 1) + complex<float>(1, 1);
|
|
EXPECT_NEAR(a.real, 2, 0.001);
|
|
EXPECT_NEAR(a.imag, 2, 0.001);
|
|
|
|
complex<float> b = complex<float>(-5, -5) + complex<float>(5, 5);
|
|
EXPECT_EQ(b.real, 0);
|
|
EXPECT_EQ(b.imag, 0);
|
|
|
|
complex<float> c =
|
|
complex<float>(0.33333f, 0.33333f) + complex<float>(0.66667f, 0.66667f);
|
|
EXPECT_NEAR(c.real, 1.0f, 0.01);
|
|
EXPECT_NEAR(c.imag, 1.0f, 0.01);
|
|
|
|
complex<float> d = complex<float>(3) - complex<float>(5);
|
|
EXPECT_EQ(d.real, -2);
|
|
EXPECT_EQ(d.imag, 0);
|
|
|
|
complex<float> e =
|
|
complex<float>(0.66667f, 0.66667f) - complex<float>(0.33333f, 0.33333f);
|
|
EXPECT_NEAR(e.real, 0.33334f, 0.01);
|
|
EXPECT_NEAR(e.imag, 0.33334f, 0.01);
|
|
|
|
complex<float> f = complex<float>(0.33f, 0.33f) * complex<float>(0.2f, 0.2f);
|
|
EXPECT_NEAR(f.real, 0.0f, 0.01);
|
|
EXPECT_NEAR(f.imag, 0.132f, 0.01);
|
|
|
|
complex<float> g = complex<float>(0.33f, 0.33f) / complex<float>(0.2f, 0.2f);
|
|
EXPECT_NEAR(g.real, 1.65f, 0.01);
|
|
EXPECT_NEAR(g.imag, 0.0f, 0.01);
|
|
|
|
complex<float> h = -complex<float>(0.33f, 0.33f);
|
|
EXPECT_NEAR(h.real, -0.33f, 0.01);
|
|
EXPECT_NEAR(h.imag, -0.33f, 0.01);
|
|
h = -complex<float>(-0.33f, -0.33f);
|
|
EXPECT_NEAR(h.real, 0.33f, 0.01);
|
|
EXPECT_NEAR(h.imag, 0.33f, 0.01);
|
|
|
|
complex<float> i = complex<float>(1.0, 1.0);
|
|
i += complex<float>(2.0, 2.0);
|
|
EXPECT_NEAR(i.real, 3.0f, 0.01);
|
|
EXPECT_NEAR(i.imag, 3.0f, 0.01);
|
|
i -= complex<float>(1.0, 1.0);
|
|
EXPECT_NEAR(i.real, 2.0f, 0.01);
|
|
EXPECT_NEAR(i.imag, 2.0f, 0.01);
|
|
i *= complex<float>(3, 2);
|
|
EXPECT_NEAR(i.real, 2.0f, 0.01);
|
|
EXPECT_NEAR(i.imag, 10.0f, 0.01);
|
|
i /= complex<float>(3, 2);
|
|
EXPECT_NEAR(i.real, 2.0f, 0.01);
|
|
EXPECT_NEAR(i.imag, 2.0f, 0.01);
|
|
|
|
// *********** complex<double> *************
|
|
complex<double> a1 = complex<double>(1, 1) + complex<double>(1, 1);
|
|
EXPECT_NEAR(a1.real, 2, 0.001);
|
|
EXPECT_NEAR(a1.imag, 2, 0.001);
|
|
|
|
complex<double> b1 = complex<double>(-5, -5) + complex<double>(5, 5);
|
|
EXPECT_EQ(b1.real, 0);
|
|
EXPECT_EQ(b1.imag, 0);
|
|
|
|
complex<double> c1 =
|
|
complex<double>(0.33333f, 0.33333f) + complex<double>(0.66667f, 0.66667f);
|
|
EXPECT_NEAR(c1.real, 1.0f, 0.01);
|
|
EXPECT_NEAR(c1.imag, 1.0f, 0.01);
|
|
|
|
complex<double> d1 = complex<double>(3) - complex<double>(5);
|
|
EXPECT_EQ(d1.real, -2);
|
|
EXPECT_EQ(d1.imag, 0);
|
|
|
|
complex<double> e1 =
|
|
complex<double>(0.66667f, 0.66667f) - complex<double>(0.33333f, 0.33333f);
|
|
EXPECT_NEAR(e1.real, 0.33334f, 0.01);
|
|
EXPECT_NEAR(e1.imag, 0.33334f, 0.01);
|
|
|
|
complex<double> f1 =
|
|
complex<double>(0.33f, 0.33f) * complex<double>(0.2f, 0.2f);
|
|
EXPECT_NEAR(f1.real, 0.0f, 0.01);
|
|
EXPECT_NEAR(f1.imag, 0.132f, 0.01);
|
|
|
|
complex<double> g1 =
|
|
complex<double>(0.33f, 0.33f) / complex<double>(0.2f, 0.2f);
|
|
EXPECT_NEAR(g1.real, 1.65f, 0.01);
|
|
EXPECT_NEAR(g1.imag, 0.0f, 0.01);
|
|
|
|
complex<double> h1 = -complex<double>(0.33f, 0.33f);
|
|
EXPECT_NEAR(h1.real, -0.33f, 0.01);
|
|
EXPECT_NEAR(h1.imag, -0.33f, 0.01);
|
|
h1 = -complex<double>(-0.33f, -0.33f);
|
|
EXPECT_NEAR(h1.real, 0.33f, 0.01);
|
|
EXPECT_NEAR(h1.imag, 0.33f, 0.01);
|
|
|
|
complex<double> i1 = complex<double>(1.0, 1.0);
|
|
i1 += complex<double>(2.0, 2.0);
|
|
EXPECT_NEAR(i1.real, 3.0f, 0.01);
|
|
EXPECT_NEAR(i1.imag, 3.0f, 0.01);
|
|
i1 -= complex<double>(1.0, 1.0);
|
|
EXPECT_NEAR(i1.real, 2.0f, 0.01);
|
|
EXPECT_NEAR(i1.imag, 2.0f, 0.01);
|
|
i1 *= complex<double>(3, 2);
|
|
EXPECT_NEAR(i1.real, 2.0f, 0.01);
|
|
EXPECT_NEAR(i1.imag, 10.0f, 0.01);
|
|
i1 /= complex<double>(3, 2);
|
|
EXPECT_NEAR(i1.real, 2.0f, 0.01);
|
|
EXPECT_NEAR(i1.imag, 2.0f, 0.01);
|
|
}
|
|
|
|
TEST(complex, print) {
|
|
complex<float> a(1.0f);
|
|
std::cout << a << std::endl;
|
|
|
|
complex<double> b(1.0);
|
|
std::cout << b << std::endl;
|
|
}
|
|
|
|
TEST(complex, isinf) {
|
|
// *********** complex<float> *************
|
|
complex<float> a;
|
|
a.real = static_cast<float>(INFINITY);
|
|
EXPECT_EQ(std::isinf(a), true);
|
|
a.imag = static_cast<float>(INFINITY);
|
|
EXPECT_EQ(std::isinf(a), true);
|
|
|
|
complex<float> b = static_cast<float>(INFINITY);
|
|
EXPECT_EQ(std::isinf(b), true);
|
|
|
|
complex<float> c(static_cast<float>(INFINITY), 0);
|
|
EXPECT_EQ(std::isinf(c), true);
|
|
|
|
// *********** complex<double> *************
|
|
complex<double> a1;
|
|
a1.real = static_cast<double>(INFINITY);
|
|
EXPECT_EQ(std::isinf(a1), true);
|
|
a1.imag = static_cast<double>(INFINITY);
|
|
EXPECT_EQ(std::isinf(a1), true);
|
|
|
|
complex<double> b1 = static_cast<double>(INFINITY);
|
|
EXPECT_EQ(std::isinf(b1), true);
|
|
|
|
complex<double> c1(static_cast<double>(INFINITY), 0);
|
|
EXPECT_EQ(std::isinf(c1), true);
|
|
}
|
|
|
|
TEST(complex, isnan) {
|
|
// *********** complex<float> *************
|
|
complex<float> a;
|
|
a.real = static_cast<float>(NAN);
|
|
EXPECT_EQ(std::isnan(a), true);
|
|
a.imag = static_cast<float>(NAN);
|
|
EXPECT_EQ(std::isnan(a), true);
|
|
|
|
complex<float> b = static_cast<float>(NAN);
|
|
EXPECT_EQ(std::isnan(b), true);
|
|
|
|
complex<float> c(static_cast<float>(NAN), 0);
|
|
EXPECT_EQ(std::isnan(c), true);
|
|
|
|
// *********** complex<double> *************
|
|
complex<double> a1;
|
|
a1.real = static_cast<double>(NAN);
|
|
EXPECT_EQ(std::isnan(a1), true);
|
|
a1.imag = static_cast<double>(NAN);
|
|
EXPECT_EQ(std::isnan(a1), true);
|
|
|
|
complex<double> b1 = static_cast<double>(NAN);
|
|
EXPECT_EQ(std::isnan(b1), true);
|
|
|
|
complex<double> c1(static_cast<double>(NAN), 0);
|
|
EXPECT_EQ(std::isnan(c1), true);
|
|
}
|
|
|
|
} // namespace paddle::platform
|