// 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/fluid/platform/complex.h" #define GLOG_NO_ABBREVIATED_SEVERITIES // msvc conflict logging with windows.h #include #include #include #include #include #include "paddle/fluid/framework/lod_tensor.h" #include "paddle/fluid/framework/tensor_util.h" #include "paddle/fluid/platform/eigen_ext.h" #include "paddle/fluid/platform/enforce.h" #if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP) namespace paddle { namespace platform { TEST(complex, conversion_on_gpu) { // *********** complex ************* // thrust from and to complex complex a(1.0f, 2.0f); EXPECT_EQ(complex(thrust::complex(a)).real, 1.0); EXPECT_EQ(complex(thrust::complex(a)).imag, 2.0); complex a1(1.0, 2.0); EXPECT_EQ(complex(thrust::complex(a1)).real, 1.0); EXPECT_EQ(complex(thrust::complex(a1)).imag, 2.0); #if defined(PADDLE_WITH_HIP) EXPECT_EQ(hipFloatComplex(a).real(), 1.0); EXPECT_EQ(hipFloatComplex(a).imag(), 2.0); EXPECT_EQ(hipDoubleComplex(a).real(), 1.0); EXPECT_EQ(hipDoubleComplex(a).imag(), 2.0); EXPECT_EQ(hipFloatComplex(a1).real(), 1.0); EXPECT_EQ(hipFloatComplex(a1).imag(), 2.0); EXPECT_EQ(hipDoubleComplex(a1).real(), 1.0); EXPECT_EQ(hipDoubleComplex(a1).imag(), 2.0); #else EXPECT_EQ(cuCrealf(cuFloatComplex(a)), 1.0); EXPECT_EQ(cuCimagf(cuFloatComplex(a)), 2.0); EXPECT_EQ(cuCreal(cuDoubleComplex(a)), 1.0); EXPECT_EQ(cuCimag(cuDoubleComplex(a)), 2.0); EXPECT_EQ(cuCrealf(cuFloatComplex(a1)), 1.0); EXPECT_EQ(cuCimagf(cuFloatComplex(a1)), 2.0); EXPECT_EQ(cuCreal(cuDoubleComplex(a1)), 1.0); EXPECT_EQ(cuCimag(cuDoubleComplex(a1)), 2.0); #endif EXPECT_EQ(complex().real, 0.0f); EXPECT_EQ(complex().imag, 0.0f); EXPECT_EQ(complex(1.0f, 1.0f).real, 1.0f); EXPECT_EQ(complex(1.0f, 1.0f).imag, 1.0f); EXPECT_EQ(complex(0.0f, 1.0f).real, 0.0f); EXPECT_EQ(complex(0.0f, 1.0f).imag, 1.0f); EXPECT_EQ(complex(1.0f).real, 1.0f); EXPECT_EQ(complex(1.0f).imag, 0.0f); // int to complex EXPECT_EQ(complex(1).real, 1.0f); EXPECT_EQ(complex(0).real, 0.0f); EXPECT_EQ(complex(2).real, 2.0f); EXPECT_EQ(complex(-2).real, -2.0f); // bool to complex EXPECT_EQ(complex(true).real, 1.0f); EXPECT_EQ(complex(true).imag, 0.0f); // complex to complex EXPECT_EQ(complex(complex(1.0, 2.0)).real, 1.0f); EXPECT_EQ(complex(complex(1.0, 2.0)).imag, 2.0f); // std::complex to complex EXPECT_EQ(complex(std::complex(1.0f, 2.0f)).real, 1.0f); EXPECT_EQ(complex(std::complex(1.0f, 2.0f)).imag, 2.0f); EXPECT_EQ(complex(std::complex(1.0, 2.0)).real, 1.0f); EXPECT_EQ(complex(std::complex(1.0, 2.0)).imag, 2.0f); // Assignment operator complex c = 1.0f; EXPECT_EQ(c.real, 1.0f); EXPECT_EQ(c.imag, 0.0f); c = complex(2.0, 2.0); EXPECT_EQ(c.real, 2.0f); EXPECT_EQ(c.imag, 2.0f); // Conversion operator EXPECT_EQ(static_cast(complex(0.5f)), 0.5f); EXPECT_NEAR(static_cast(complex(0.33333)), 0.33333, 0.01); EXPECT_EQ(static_cast(complex(-1)), -1); EXPECT_EQ(static_cast(complex(true)), true); // *********** complex ************* // double to complex EXPECT_EQ(complex().real, 0.0); EXPECT_EQ(complex().imag, 0.0); EXPECT_EQ(complex(1.0, 1.0).real, 1.0); EXPECT_EQ(complex(1.0, 1.0).imag, 1.0); EXPECT_EQ(complex(0.0, 1.0).real, 0.0); EXPECT_EQ(complex(0.0, 1.0).imag, 1.0); EXPECT_EQ(complex(1.0).real, 1.0); EXPECT_EQ(complex(1.0).imag, 0.0); // int to complex EXPECT_EQ(complex(1).real, 1.0); EXPECT_EQ(complex(0).real, 0.0); EXPECT_EQ(complex(2).real, 2.0); EXPECT_EQ(complex(-2).real, -2.0); // bool to complex EXPECT_EQ(complex(true).real, 1.0); EXPECT_EQ(complex(true).imag, 0.0); // complex to complex EXPECT_EQ(complex(complex(1.0f, 2.0f)).real, 1.0); EXPECT_EQ(complex(complex(1.0f, 2.0f)).imag, 2.0); // std::complex to complex EXPECT_EQ(complex(std::complex(1.0, 2.0)).real, 1.0); EXPECT_EQ(complex(std::complex(1.0, 2.0)).imag, 2.0); EXPECT_EQ(complex(std::complex(1.0, 2.0)).real, 1.0); EXPECT_EQ(complex(std::complex(1.0, 2.0)).imag, 2.0); // Assignment operator complex c1 = 1.0; EXPECT_EQ(c1.real, 1.0); EXPECT_EQ(c1.imag, 0.0); c1 = complex(2.0, 2.0); EXPECT_EQ(c1.real, 2.0); EXPECT_EQ(c1.imag, 2.0); // Conversion operator EXPECT_EQ(static_cast(complex(0.5)), 0.5); EXPECT_NEAR(static_cast(complex(0.33333)), 0.33333, 0.01); EXPECT_EQ(static_cast(complex(-1)), -1); EXPECT_EQ(static_cast(complex(true)), true); } TEST(bfloat16, comparison_cpu) { // *********** complex ************* EXPECT_TRUE(complex(1.0f) == complex(1.0f)); EXPECT_TRUE(complex(1.0f, 2.0f) == complex(1.0f, 2.0f)); EXPECT_FALSE(complex(-1.0f) == complex(-0.5f)); EXPECT_TRUE(complex(1.0f) != complex(0.5f)); EXPECT_FALSE(complex(-1.0f) != complex(-1.0f)); EXPECT_TRUE(complex(1.0f) < complex(2.0f)); EXPECT_FALSE(complex(-1.0f) < complex(-1.0f)); EXPECT_TRUE(complex(1.0f) <= complex(1.0f)); EXPECT_TRUE(complex(2.0f) > complex(1.0f)); EXPECT_FALSE(complex(-2.0f) > complex(-2.0f)); EXPECT_TRUE(complex(2.0f) >= complex(2.0f)); // *********** complex ************* EXPECT_TRUE(complex(1.0) == complex(1.0)); EXPECT_TRUE(complex(1.0, 2.0) == complex(1.0, 2.0)); EXPECT_FALSE(complex(-1.0) == complex(-0.5f)); EXPECT_TRUE(complex(1.0) != complex(0.5f)); EXPECT_FALSE(complex(-1.0) != complex(-1.0)); EXPECT_TRUE(complex(1.0) < complex(2.0)); EXPECT_FALSE(complex(-1.0) < complex(-1.0)); EXPECT_TRUE(complex(1.0) <= complex(1.0)); EXPECT_TRUE(complex(2.0) > complex(1.0)); EXPECT_FALSE(complex(-2.0) > complex(-2.0)); EXPECT_TRUE(complex(2.0) >= complex(2.0)); } TEST(complex, arithmetic_cpu) { // *********** complex ************* complex a = complex(1, 1) + complex(1, 1); EXPECT_NEAR(a.real, 2, 0.001); EXPECT_NEAR(a.imag, 2, 0.001); complex b = complex(-5, -5) + complex(5, 5); EXPECT_EQ(b.real, 0); EXPECT_EQ(b.imag, 0); complex c = complex(0.33333f, 0.33333f) + complex(0.66667f, 0.66667f); EXPECT_NEAR(c.real, 1.0f, 0.01); EXPECT_NEAR(c.imag, 1.0f, 0.01); complex d = complex(3) - complex(5); EXPECT_EQ(d.real, -2); EXPECT_EQ(d.imag, 0); complex e = complex(0.66667f, 0.66667f) - complex(0.33333f, 0.33333f); EXPECT_NEAR(e.real, 0.33334f, 0.01); EXPECT_NEAR(e.imag, 0.33334f, 0.01); complex f = complex(0.33f, 0.33f) * complex(0.2f, 0.2f); EXPECT_NEAR(f.real, 0.0f, 0.01); EXPECT_NEAR(f.imag, 0.132f, 0.01); complex g = complex(0.33f, 0.33f) / complex(0.2f, 0.2f); EXPECT_NEAR(g.real, 1.65f, 0.01); EXPECT_NEAR(g.imag, 0.0f, 0.01); complex h = -complex(0.33f, 0.33f); EXPECT_NEAR(h.real, -0.33f, 0.01); EXPECT_NEAR(h.imag, -0.33f, 0.01); h = -complex(-0.33f, -0.33f); EXPECT_NEAR(h.real, 0.33f, 0.01); EXPECT_NEAR(h.imag, 0.33f, 0.01); complex i = complex(1.0, 1.0); i += complex(2.0, 2.0); EXPECT_NEAR(i.real, 3.0f, 0.01); EXPECT_NEAR(i.imag, 3.0f, 0.01); i -= complex(1.0, 1.0); EXPECT_NEAR(i.real, 2.0f, 0.01); EXPECT_NEAR(i.imag, 2.0f, 0.01); i *= complex(3, 2); EXPECT_NEAR(i.real, 2.0f, 0.01); EXPECT_NEAR(i.imag, 10.0f, 0.01); i /= complex(3, 2); EXPECT_NEAR(i.real, 2.0f, 0.01); EXPECT_NEAR(i.imag, 2.0f, 0.01); // *********** complex ************* complex a1 = complex(1, 1) + complex(1, 1); EXPECT_NEAR(a1.real, 2, 0.001); EXPECT_NEAR(a1.imag, 2, 0.001); complex b1 = complex(-5, -5) + complex(5, 5); EXPECT_EQ(b1.real, 0); EXPECT_EQ(b1.imag, 0); complex c1 = complex(0.33333f, 0.33333f) + complex(0.66667f, 0.66667f); EXPECT_NEAR(c1.real, 1.0f, 0.01); EXPECT_NEAR(c1.imag, 1.0f, 0.01); complex d1 = complex(3) - complex(5); EXPECT_EQ(d1.real, -2); EXPECT_EQ(d1.imag, 0); complex e1 = complex(0.66667f, 0.66667f) - complex(0.33333f, 0.33333f); EXPECT_NEAR(e1.real, 0.33334f, 0.01); EXPECT_NEAR(e1.imag, 0.33334f, 0.01); complex f1 = complex(0.33f, 0.33f) * complex(0.2f, 0.2f); EXPECT_NEAR(f1.real, 0.0f, 0.01); EXPECT_NEAR(f1.imag, 0.132f, 0.01); complex g1 = complex(0.33f, 0.33f) / complex(0.2f, 0.2f); EXPECT_NEAR(g1.real, 1.65f, 0.01); EXPECT_NEAR(g1.imag, 0.0f, 0.01); complex h1 = -complex(0.33f, 0.33f); EXPECT_NEAR(h1.real, -0.33f, 0.01); EXPECT_NEAR(h1.imag, -0.33f, 0.01); h1 = -complex(-0.33f, -0.33f); EXPECT_NEAR(h1.real, 0.33f, 0.01); EXPECT_NEAR(h1.imag, 0.33f, 0.01); complex i1 = complex(1.0, 1.0); i1 += complex(2.0, 2.0); EXPECT_NEAR(i1.real, 3.0f, 0.01); EXPECT_NEAR(i1.imag, 3.0f, 0.01); i1 -= complex(1.0, 1.0); EXPECT_NEAR(i1.real, 2.0f, 0.01); EXPECT_NEAR(i1.imag, 2.0f, 0.01); i1 *= complex(3, 2); EXPECT_NEAR(i1.real, 2.0f, 0.01); EXPECT_NEAR(i1.imag, 10.0f, 0.01); i1 /= complex(3, 2); EXPECT_NEAR(i1.real, 2.0f, 0.01); EXPECT_NEAR(i1.imag, 2.0f, 0.01); } TEST(complex, print) { complex a(1.0f); std::cout << a << std::endl; complex b(1.0); std::cout << b << std::endl; } TEST(complex, isinf) { // *********** complex ************* complex a; a.real = float(INFINITY); EXPECT_EQ(std::isinf(a), true); a.imag = float(INFINITY); EXPECT_EQ(std::isinf(a), true); complex b = float(INFINITY); EXPECT_EQ(std::isinf(b), true); complex c(float(INFINITY), 0); EXPECT_EQ(std::isinf(c), true); // *********** complex ************* complex a1; a1.real = double(INFINITY); EXPECT_EQ(std::isinf(a1), true); a1.imag = double(INFINITY); EXPECT_EQ(std::isinf(a1), true); complex b1 = double(INFINITY); EXPECT_EQ(std::isinf(b1), true); complex c1(double(INFINITY), 0); EXPECT_EQ(std::isinf(c1), true); } TEST(complex, isnan) { // *********** complex ************* complex a; a.real = float(NAN); EXPECT_EQ(std::isnan(a), true); a.imag = float(NAN); EXPECT_EQ(std::isnan(a), true); complex b = float(NAN); EXPECT_EQ(std::isnan(b), true); complex c(float(NAN), 0); EXPECT_EQ(std::isnan(c), true); // *********** complex ************* complex a1; a1.real = double(NAN); EXPECT_EQ(std::isnan(a1), true); a1.imag = double(NAN); EXPECT_EQ(std::isnan(a1), true); complex b1 = double(NAN); EXPECT_EQ(std::isnan(b1), true); complex c1(double(NAN), 0); EXPECT_EQ(std::isnan(c1), true); } } // namespace platform } // namespace paddle #endif