mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 12:26:52 +08:00
Implement 'lerp'; which is the last bit of P0811. Mark that paper as complete.
llvm-svn: 359211
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user