// Copyright (C) 2020-2024 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 // . // only: float|double|ldouble * * * // skip: ldouble * powerpc64* * // expensive: * [1-9] * * #include "bits/main.h" // 3-arg std::hypot needs to be fixed, this is a better reference: template [[gnu::optimize("-fno-unsafe-math-optimizations")]] T hypot3(T x, T y, T z) { x = std::abs(x); y = std::abs(y); z = std::abs(z); if (std::isinf(x) || std::isinf(y) || std::isinf(z)) return std::__infinity_v; else if (std::isnan(x) || std::isnan(y) || std::isnan(z)) return std::__quiet_NaN_v; else if (x == y && y == z) return x * std::sqrt(T(3)); else if (z == 0 && y == 0) return x; else if (x == 0 && z == 0) return y; else if (x == 0 && y == 0) return z; else { T hi = std::max(std::max(x, y), z); T lo0 = std::min(std::max(x, y), z); T lo1 = std::min(x, y); int e = 0; hi = std::frexp(hi, &e); lo0 = std::ldexp(lo0, -e); lo1 = std::ldexp(lo1, -e); T lo = lo0 * lo0 + lo1 * lo1; return std::ldexp(std::sqrt(hi * hi + lo), e); } } template void test() { vir::test::setFuzzyness(1); vir::test::setFuzzyness(1); vir::test::setFuzzyness(2); // because of the bad reference using T = typename V::value_type; test_values_3arg( { #ifdef __STDC_IEC_559__ std::__quiet_NaN_v, std::__infinity_v, -std::__infinity_v, std::__norm_min_v / 3, -0., std::__denorm_min_v, #endif 0., 1., -1., std::__norm_min_v, -std::__norm_min_v, 2., -2., std::__finite_max_v / 5, std::__finite_max_v / 3, std::__finite_max_v / 2, -std::__finite_max_v / 5, -std::__finite_max_v / 3, -std::__finite_max_v / 2, #ifdef __FAST_MATH__ // fast-math hypot is imprecise for the max exponent }, {100000, std::__finite_max_v / 2}, #else std::__finite_max_v, -std::__finite_max_v}, {100000}, #endif MAKE_TESTER_2(hypot, hypot3)); #if !__FINITE_MATH_ONLY__ COMPARE(hypot(V(std::__finite_max_v), V(std::__finite_max_v), V()), V(std::__infinity_v)); COMPARE(hypot(V(std::__finite_max_v), V(), V(std::__finite_max_v)), V(std::__infinity_v)); COMPARE(hypot(V(), V(std::__finite_max_v), V(std::__finite_max_v)), V(std::__infinity_v)); #endif COMPARE(hypot(V(std::__norm_min_v), V(std::__norm_min_v), V(std::__norm_min_v)), V(std::__norm_min_v * std::sqrt(T(3)))); auto&& hypot3_test = [](auto a, auto b, auto c) -> decltype(hypot(a, b, c)) { return {}; }; VERIFY((sfinae_is_callable(hypot3_test))); VERIFY((sfinae_is_callable(hypot3_test))); VERIFY((sfinae_is_callable(hypot3_test))); VERIFY((sfinae_is_callable(hypot3_test))); VERIFY((sfinae_is_callable(hypot3_test))); VERIFY((sfinae_is_callable(hypot3_test))); VERIFY((sfinae_is_callable(hypot3_test))); VERIFY((sfinae_is_callable(hypot3_test))); VERIFY((sfinae_is_callable(hypot3_test))); VERIFY((sfinae_is_callable(hypot3_test))); VERIFY(!(sfinae_is_callable(hypot3_test))); VERIFY(!(sfinae_is_callable(hypot3_test))); VERIFY(!(sfinae_is_callable(hypot3_test))); vir::test::setFuzzyness(0); vir::test::setFuzzyness(0); test_values_3arg( { #ifdef __STDC_IEC_559__ std::__quiet_NaN_v, std::__infinity_v, -std::__infinity_v, -0., std::__norm_min_v / 3, std::__denorm_min_v, #endif 0., std::__norm_min_v, std::__finite_max_v}, {10000, -std::__finite_max_v / 2, std::__finite_max_v / 2}, MAKE_TESTER(fma)); auto&& fma_test = [](auto a, auto b, auto c) -> decltype(fma(a, b, c)) { return {}; }; VERIFY((sfinae_is_callable(fma_test))); VERIFY((sfinae_is_callable(fma_test))); VERIFY((sfinae_is_callable(fma_test))); VERIFY((sfinae_is_callable(fma_test))); VERIFY((sfinae_is_callable(fma_test))); VERIFY((sfinae_is_callable(fma_test))); VERIFY((sfinae_is_callable(fma_test))); VERIFY((sfinae_is_callable(fma_test))); VERIFY((sfinae_is_callable(fma_test))); VERIFY((sfinae_is_callable(fma_test))); VERIFY((!sfinae_is_callable(fma_test))); VERIFY((!sfinae_is_callable(fma_test))); }