// Copyright (C) 2019-2022 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License along // with this library; see the file COPYING3. If not see // . // { dg-do run { target c++11 } } #include #include #include namespace test { #ifdef _GLIBCXX_USE_C99_MATH_TR1 using std::copysign; #else bool copysign(float x, float y) { return __builtin_copysignf(x, y); } bool copysign(double x, double y) { return __builtin_copysign(x, y); } bool copysign(long double x, long double y) { return __builtin_copysignl(x, y); } #endif } template bool eq(const std::complex& x, const std::complex& y) { bool nan_reals = std::isnan(x.real()) && std::isnan(y.real()); bool nan_imags = std::isnan(x.imag()) && std::isnan(y.imag()); bool sign_reals = test::copysign(T(1), x.real()) == test::copysign(T(1), y.real()); bool sign_imags = test::copysign(T(1), x.imag()) == test::copysign(T(1), y.imag()); return ((x.real() == y.real() && sign_reals) || nan_reals) && ((x.imag() == y.imag() && sign_imags) || nan_imags); } void test01() { const double qnan = std::numeric_limits::quiet_NaN(); const double pinf = std::numeric_limits::infinity(); const double ninf = -pinf; std::complex c00(0, 0); VERIFY( eq( std::proj(c00) , c00 ) ); VERIFY( eq( std::proj(-c00) , -c00 ) ); c00.real(-0.0); VERIFY( eq( std::proj(c00) , c00 ) ); VERIFY( eq( std::proj(-c00) , -c00 ) ); const std::complex c01(0, 1); VERIFY( eq( std::proj(c01) , c01 ) ); VERIFY( eq( std::proj(-c01) , -c01 ) ); c00.real(-0.0); VERIFY( eq( std::proj(c01) , c01 ) ); VERIFY( eq( std::proj(-c01) , -c01 ) ); const std::complex c10(1, 0); VERIFY( eq( std::proj(c10) , c10 ) ); VERIFY( eq( std::proj(-c10) , -c10 ) ); const std::complex c12(1, 2); VERIFY( eq( std::proj(c12) , c12 ) ); VERIFY( eq( std::proj(-c12) , -c12 ) ); const std::complex c0q(0, qnan); VERIFY( eq( std::proj(c0q) , c0q ) ); VERIFY( eq( std::proj(-c0q) , -c0q ) ); const std::complex c1q(1, qnan); VERIFY( eq( std::proj(c1q) , c1q ) ); VERIFY( eq( std::proj(-c1q) , -c1q ) ); const std::complex cq0(qnan, 0); VERIFY( eq( std::proj(cq0) , cq0 ) ); VERIFY( eq( std::proj(-cq0) , -cq0 ) ); const std::complex cq1(qnan, 1); VERIFY( eq( std::proj(cq1) , cq1 ) ); VERIFY( eq( std::proj(-cq1) , -cq1 ) ); const std::complex cqq(qnan, qnan); VERIFY( eq( std::proj(cqq) , cqq ) ); VERIFY( eq( std::proj(-cqq) , -cqq ) ); const std::complex c0p(0, pinf); VERIFY( eq( std::proj(c0p) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-c0p) , std::complex(pinf, -0.0) ) ); const std::complex c1p(1, pinf); VERIFY( eq( std::proj(c1p) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-c1p) , std::complex(pinf, -0.0) ) ); const std::complex cqp(qnan, pinf); VERIFY( eq( std::proj(cqp) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cqp) , std::complex(pinf, -0.0) ) ); const std::complex cpp(pinf, pinf); VERIFY( eq( std::proj(cpp) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cpp) , std::complex(pinf, -0.0) ) ); const std::complex c0n(0, ninf); VERIFY( eq( std::proj(c0n) , std::complex(pinf, -0.0) ) ); VERIFY( eq( std::proj(-c0n) , std::complex(pinf, +0.0) ) ); const std::complex c1n(1, ninf); VERIFY( eq( std::proj(c1n) , std::complex(pinf, -0.0) ) ); VERIFY( eq( std::proj(-c1n) , std::complex(pinf, +0.0) ) ); const std::complex cqn(qnan, ninf); VERIFY( eq( std::proj(cqn) , std::complex(pinf, -0.0) ) ); VERIFY( eq( std::proj(-cqn) , std::complex(pinf, +0.0) ) ); const std::complex cpn(pinf, ninf); VERIFY( eq( std::proj(cpn) , std::complex(pinf, -0.0) ) ); VERIFY( eq( std::proj(-cpn) , std::complex(pinf, +0.0) ) ); const std::complex cnn(ninf, ninf); VERIFY( eq( std::proj(cnn) , std::complex(pinf, -0.0) ) ); VERIFY( eq( std::proj(-cnn) , std::complex(pinf, +0.0) ) ); const std::complex cp0(pinf, 0); VERIFY( eq( std::proj(cp0) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cp0) , std::complex(pinf, -0.0) ) ); const std::complex cp1(pinf, 1); VERIFY( eq( std::proj(cp1) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cp1) , std::complex(pinf, -0.0) ) ); const std::complex cpq(pinf, qnan); VERIFY( eq( std::proj(cpq) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cpq) , std::complex(pinf, -0.0) ) ); const std::complex cn0(ninf, 0); VERIFY( eq( std::proj(cn0) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cn0) , std::complex(pinf, -0.0) ) ); const std::complex cn1(ninf, 1); VERIFY( eq( std::proj(cn1) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cn1) , std::complex(pinf, -0.0) ) ); const std::complex cnq(ninf, qnan); VERIFY( eq( std::proj(cnq) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cnq) , std::complex(pinf, -0.0) ) ); const std::complex cnp(ninf, pinf); VERIFY( eq( std::proj(cnp) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cnp) , std::complex(pinf, -0.0) ) ); } void test02() { const float qnan = std::numeric_limits::quiet_NaN(); const float pinf = std::numeric_limits::infinity(); const float ninf = -pinf; std::complex c00(0, 0); VERIFY( eq( std::proj(c00) , c00 ) ); VERIFY( eq( std::proj(-c00) , -c00 ) ); c00.real(-0.0); VERIFY( eq( std::proj(c00) , c00 ) ); VERIFY( eq( std::proj(-c00) , -c00 ) ); const std::complex c01(0, 1); VERIFY( eq( std::proj(c01) , c01 ) ); VERIFY( eq( std::proj(-c01) , -c01 ) ); c00.real(-0.0); VERIFY( eq( std::proj(c01) , c01 ) ); VERIFY( eq( std::proj(-c01) , -c01 ) ); const std::complex c10(1, 0); VERIFY( eq( std::proj(c10) , c10 ) ); VERIFY( eq( std::proj(-c10) , -c10 ) ); const std::complex c12(1, 2); VERIFY( eq( std::proj(c12) , c12 ) ); VERIFY( eq( std::proj(-c12) , -c12 ) ); const std::complex c0q(0, qnan); VERIFY( eq( std::proj(c0q) , c0q ) ); VERIFY( eq( std::proj(-c0q) , -c0q ) ); const std::complex c1q(1, qnan); VERIFY( eq( std::proj(c1q) , c1q ) ); VERIFY( eq( std::proj(-c1q) , -c1q ) ); const std::complex cq0(qnan, 0); VERIFY( eq( std::proj(cq0) , cq0 ) ); VERIFY( eq( std::proj(-cq0) , -cq0 ) ); const std::complex cq1(qnan, 1); VERIFY( eq( std::proj(cq1) , cq1 ) ); VERIFY( eq( std::proj(-cq1) , -cq1 ) ); const std::complex cqq(qnan, qnan); VERIFY( eq( std::proj(cqq) , cqq ) ); VERIFY( eq( std::proj(-cqq) , -cqq ) ); const std::complex c0p(0, pinf); VERIFY( eq( std::proj(c0p) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-c0p) , std::complex(pinf, -0.0) ) ); const std::complex c1p(1, pinf); VERIFY( eq( std::proj(c1p) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-c1p) , std::complex(pinf, -0.0) ) ); const std::complex cqp(qnan, pinf); VERIFY( eq( std::proj(cqp) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cqp) , std::complex(pinf, -0.0) ) ); const std::complex cpp(pinf, pinf); VERIFY( eq( std::proj(cpp) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cpp) , std::complex(pinf, -0.0) ) ); const std::complex c0n(0, ninf); VERIFY( eq( std::proj(c0n) , std::complex(pinf, -0.0) ) ); VERIFY( eq( std::proj(-c0n) , std::complex(pinf, +0.0) ) ); const std::complex c1n(1, ninf); VERIFY( eq( std::proj(c1n) , std::complex(pinf, -0.0) ) ); VERIFY( eq( std::proj(-c1n) , std::complex(pinf, +0.0) ) ); const std::complex cqn(qnan, ninf); VERIFY( eq( std::proj(cqn) , std::complex(pinf, -0.0) ) ); VERIFY( eq( std::proj(-cqn) , std::complex(pinf, +0.0) ) ); const std::complex cpn(pinf, ninf); VERIFY( eq( std::proj(cpn) , std::complex(pinf, -0.0) ) ); VERIFY( eq( std::proj(-cpn) , std::complex(pinf, +0.0) ) ); const std::complex cnn(ninf, ninf); VERIFY( eq( std::proj(cnn) , std::complex(pinf, -0.0) ) ); VERIFY( eq( std::proj(-cnn) , std::complex(pinf, +0.0) ) ); const std::complex cp0(pinf, 0); VERIFY( eq( std::proj(cp0) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cp0) , std::complex(pinf, -0.0) ) ); const std::complex cp1(pinf, 1); VERIFY( eq( std::proj(cp1) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cp1) , std::complex(pinf, -0.0) ) ); const std::complex cpq(pinf, qnan); VERIFY( eq( std::proj(cpq) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cpq) , std::complex(pinf, -0.0) ) ); const std::complex cn0(ninf, 0); VERIFY( eq( std::proj(cn0) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cn0) , std::complex(pinf, -0.0) ) ); const std::complex cn1(ninf, 1); VERIFY( eq( std::proj(cn1) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cn1) , std::complex(pinf, -0.0) ) ); const std::complex cnq(ninf, qnan); VERIFY( eq( std::proj(cnq) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cnq) , std::complex(pinf, -0.0) ) ); const std::complex cnp(ninf, pinf); VERIFY( eq( std::proj(cnp) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cnp) , std::complex(pinf, -0.0) ) ); } void test03() { const long double qnan = std::numeric_limits::quiet_NaN(); const long double pinf = std::numeric_limits::infinity(); const long double ninf = -pinf; std::complex c00(0, 0); VERIFY( eq( std::proj(c00) , c00 ) ); VERIFY( eq( std::proj(-c00) , -c00 ) ); c00.real(-0.0); VERIFY( eq( std::proj(c00) , c00 ) ); VERIFY( eq( std::proj(-c00) , -c00 ) ); const std::complex c01(0, 1); VERIFY( eq( std::proj(c01) , c01 ) ); VERIFY( eq( std::proj(-c01) , -c01 ) ); c00.real(-0.0); VERIFY( eq( std::proj(c01) , c01 ) ); VERIFY( eq( std::proj(-c01) , -c01 ) ); const std::complex c10(1, 0); VERIFY( eq( std::proj(c10) , c10 ) ); VERIFY( eq( std::proj(-c10) , -c10 ) ); const std::complex c12(1, 2); VERIFY( eq( std::proj(c12) , c12 ) ); VERIFY( eq( std::proj(-c12) , -c12 ) ); const std::complex c0q(0, qnan); VERIFY( eq( std::proj(c0q) , c0q ) ); VERIFY( eq( std::proj(-c0q) , -c0q ) ); const std::complex c1q(1, qnan); VERIFY( eq( std::proj(c1q) , c1q ) ); VERIFY( eq( std::proj(-c1q) , -c1q ) ); const std::complex cq0(qnan, 0); VERIFY( eq( std::proj(cq0) , cq0 ) ); VERIFY( eq( std::proj(-cq0) , -cq0 ) ); const std::complex cq1(qnan, 1); VERIFY( eq( std::proj(cq1) , cq1 ) ); VERIFY( eq( std::proj(-cq1) , -cq1 ) ); const std::complex cqq(qnan, qnan); VERIFY( eq( std::proj(cqq) , cqq ) ); VERIFY( eq( std::proj(-cqq) , -cqq ) ); const std::complex c0p(0, pinf); VERIFY( eq( std::proj(c0p) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-c0p) , std::complex(pinf, -0.0) ) ); const std::complex c1p(1, pinf); VERIFY( eq( std::proj(c1p) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-c1p) , std::complex(pinf, -0.0) ) ); const std::complex cqp(qnan, pinf); VERIFY( eq( std::proj(cqp) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cqp) , std::complex(pinf, -0.0) ) ); const std::complex cpp(pinf, pinf); VERIFY( eq( std::proj(cpp) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cpp) , std::complex(pinf, -0.0) ) ); const std::complex c0n(0, ninf); VERIFY( eq( std::proj(c0n) , std::complex(pinf, -0.0) ) ); VERIFY( eq( std::proj(-c0n) , std::complex(pinf, +0.0) ) ); const std::complex c1n(1, ninf); VERIFY( eq( std::proj(c1n) , std::complex(pinf, -0.0) ) ); VERIFY( eq( std::proj(-c1n) , std::complex(pinf, +0.0) ) ); const std::complex cqn(qnan, ninf); VERIFY( eq( std::proj(cqn) , std::complex(pinf, -0.0) ) ); VERIFY( eq( std::proj(-cqn) , std::complex(pinf, +0.0) ) ); const std::complex cpn(pinf, ninf); VERIFY( eq( std::proj(cpn) , std::complex(pinf, -0.0) ) ); VERIFY( eq( std::proj(-cpn) , std::complex(pinf, +0.0) ) ); const std::complex cnn(ninf, ninf); VERIFY( eq( std::proj(cnn) , std::complex(pinf, -0.0) ) ); VERIFY( eq( std::proj(-cnn) , std::complex(pinf, +0.0) ) ); const std::complex cp0(pinf, 0); VERIFY( eq( std::proj(cp0) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cp0) , std::complex(pinf, -0.0) ) ); const std::complex cp1(pinf, 1); VERIFY( eq( std::proj(cp1) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cp1) , std::complex(pinf, -0.0) ) ); const std::complex cpq(pinf, qnan); VERIFY( eq( std::proj(cpq) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cpq) , std::complex(pinf, -0.0) ) ); const std::complex cn0(ninf, 0); VERIFY( eq( std::proj(cn0) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cn0) , std::complex(pinf, -0.0) ) ); const std::complex cn1(ninf, 1); VERIFY( eq( std::proj(cn1) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cn1) , std::complex(pinf, -0.0) ) ); const std::complex cnq(ninf, qnan); VERIFY( eq( std::proj(cnq) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cnq) , std::complex(pinf, -0.0) ) ); const std::complex cnp(ninf, pinf); VERIFY( eq( std::proj(cnp) , std::complex(pinf, +0.0) ) ); VERIFY( eq( std::proj(-cnp) , std::complex(pinf, -0.0) ) ); } int main() { /* If neither of these macros is nonzero, proj calls a specialization of the __complex_proj template, that just returns its argument, without testing for infinities, rendering the whole test pointless, and failing (as intended/noted in the implementation) the cases that involve infinities. Alas, the normal ways to skip tests may not work: we don't have a test for C99_COMPLEX, and these macros may vary depending on -std=*, but macro tests wouldn't take them into account. */ #if ! (_GLIBCXX_USE_C99_COMPLEX || _GLIBCXX_USE_C99_MATH_TR1) if (true) return 0; #endif test01(); test02(); test03(); }