diff options
-rw-r--r-- | libcxx/include/cmath | 27 | ||||
-rw-r--r-- | libcxx/test/std/numerics/c.math/c.math.lerp/c.math.lerp.pass.cpp | 75 | ||||
-rw-r--r-- | libcxx/www/cxx2a_status.html | 2 |
3 files changed, 103 insertions, 1 deletions
diff --git a/libcxx/include/cmath b/libcxx/include/cmath index 3af9f548190..f618b1bf467 100644 --- a/libcxx/include/cmath +++ b/libcxx/include/cmath @@ -302,6 +302,7 @@ long double truncl(long double x); #include <__config> #include <math.h> +#include <algorithm> #include <version> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -606,6 +607,32 @@ __libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT return isfinite(__lcpp_x); } +#if _LIBCPP_STD_VER > 17 +template <typename _Fp> +constexpr +_Fp __lerp(_Fp __a, _Fp __b, _Fp __t) noexcept { + if ((__a <= 0 && __b >= 0) || (__a >= 0 && __b <= 0)) + return __t * __b + (1 - __t) * __a; + + if (__t == 1) return __b; + const _Fp __x = __a + __t * (__b - __a); + if (__t > 1 == __b > __a) + return __b < __x ? __x : __b; + else + return __x < __b ? __x : __b; +} + +constexpr float +lerp(float __a, float __b, float __t) _NOEXCEPT { return __lerp(__a, __b, __t); } + +constexpr double +lerp(double __a, double __b, double __t) _NOEXCEPT { return __lerp(__a, __b, __t); } + +constexpr long double +lerp(long double __a, long double __b, long double __t) _NOEXCEPT { return __lerp(__a, __b, __t); } + +#endif // _LIBCPP_STD_VER > 17 + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_CMATH diff --git a/libcxx/test/std/numerics/c.math/c.math.lerp/c.math.lerp.pass.cpp b/libcxx/test/std/numerics/c.math/c.math.lerp/c.math.lerp.pass.cpp new file mode 100644 index 00000000000..2ab41c18225 --- /dev/null +++ b/libcxx/test/std/numerics/c.math/c.math.lerp/c.math.lerp.pass.cpp @@ -0,0 +1,75 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 +// <cmath> + +// constexpr float lerp(float a, float b, float t); +// constexpr double lerp(double a, double b, double t); +// constexpr long double lerp(long double a, long double b, long double t); + + +#include <cmath> +#include <limits> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "fp_compare.h" + +template <typename T> +constexpr bool constexpr_test() +{ + return std::lerp(T( 0), T(12), T(0)) == T(0) + && std::lerp(T(12), T( 0), T(0.5)) == T(6) + && std::lerp(T( 0), T(12), T(2)) == T(24); +} + + +template <typename T> +void test() +{ + ASSERT_SAME_TYPE(T, decltype(std::lerp(T(), T(), T()))); + LIBCPP_ASSERT_NOEXCEPT( std::lerp(T(), T(), T())); + +// constexpr T minV = std::numeric_limits<T>::min(); + constexpr T maxV = std::numeric_limits<T>::max(); + constexpr T inf = std::numeric_limits<T>::infinity(); + +// Things that can be compared exactly + assert((std::lerp(T( 0), T(12), T(0)) == T(0))); + assert((std::lerp(T( 0), T(12), T(1)) == T(12))); + assert((std::lerp(T(12), T( 0), T(0)) == T(12))); + assert((std::lerp(T(12), T( 0), T(1)) == T(0))); + + assert((std::lerp(T( 0), T(12), T(0.5)) == T(6))); + assert((std::lerp(T(12), T( 0), T(0.5)) == T(6))); + assert((std::lerp(T( 0), T(12), T(2)) == T(24))); + assert((std::lerp(T(12), T( 0), T(2)) == T(-12))); + + assert((std::lerp(maxV, maxV/10, T(0)) == maxV)); + assert((std::lerp(maxV/10, maxV, T(1)) == maxV)); + + assert((std::lerp(T(2.3), T(2.3), inf) == T(2.3))); + + assert(std::lerp(T( 0), T( 0), T(23)) == T(0)); + assert(std::isnan(std::lerp(T( 0), T( 0), inf))); +} + + +int main(int, char**) +{ + static_assert(constexpr_test<float>(), ""); + static_assert(constexpr_test<double>(), ""); + static_assert(constexpr_test<long double>(), ""); + + test<float>(); + test<double>(); + test<long double>(); + + return 0; +} diff --git a/libcxx/www/cxx2a_status.html b/libcxx/www/cxx2a_status.html index e6f5444977e..d8b03427c33 100644 --- a/libcxx/www/cxx2a_status.html +++ b/libcxx/www/cxx2a_status.html @@ -141,7 +141,7 @@ <tr><td><a href="https://wg21.link/P0339R6">P0339R6</a></td><td>LWG</td><td>polymorphic_allocator<> as a vocabulary type</td><td>Kona</td><td></td><td></td></tr> <tr><td><a href="https://wg21.link/P0340R3">P0340R3</a></td><td>LWG</td><td>Making std::underlying_type SFINAE-friendly</td><td>Kona</td><td></td><td></td></tr> <tr><td><a href="https://wg21.link/P0738R2">P0738R2</a></td><td>LWG</td><td>I Stream, You Stream, We All Stream for istream_iterator</td><td>Kona</td><td></td><td></td></tr> - <tr><td><a href="https://wg21.link/P0811R3">P0811R3</a></td><td>LWG</td><td>Well-behaved interpolation for numbers and pointers</td><td>Kona</td><td></td><td></td></tr> + <tr><td><a href="https://wg21.link/P0811R3">P0811R3</a></td><td>LWG</td><td>Well-behaved interpolation for numbers and pointers</td><td>Kona</td><td>Complete</td><td>9.0</td></tr> <tr><td><a href="https://wg21.link/P0920R2">P0920R2</a></td><td>LWG</td><td>Precalculated hash values in lookup</td><td>Kona</td><td></td><td></td></tr> <tr><td><a href="https://wg21.link/P1001R2">P1001R2</a></td><td>LWG</td><td>Target Vectorization Policies from Parallelism V2 TS to C++20</td><td>Kona</td><td></td><td></td></tr> <tr><td><a href="https://wg21.link/P1024R3">P1024R3</a></td><td>LWG</td><td>Usability Enhancements for std::span</td><td>Kona</td><td>Complete</td><td>9.0</td></tr> |