Implement 'lerp'; which is the last bit of P0811. Mark that paper as complete.

llvm-svn: 359211
This commit is contained in:
Marshall Clow
2019-04-25 17:44:18 +00:00
parent 19376ebd1a
commit b0e2daf64b
3 changed files with 103 additions and 1 deletions

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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>