Skip to content

Commit b0e2daf

Browse files
committed
Implement 'lerp'; which is the last bit of P0811. Mark that paper as complete.
llvm-svn: 359211
1 parent 19376eb commit b0e2daf

File tree

3 files changed

+103
-1
lines changed

3 files changed

+103
-1
lines changed

libcxx/include/cmath

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ long double truncl(long double x);
302302

303303
#include <__config>
304304
#include <math.h>
305+
#include <algorithm>
305306
#include <version>
306307

307308
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -606,6 +607,32 @@ __libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT
606607
return isfinite(__lcpp_x);
607608
}
608609

610+
#if _LIBCPP_STD_VER > 17
611+
template <typename _Fp>
612+
constexpr
613+
_Fp __lerp(_Fp __a, _Fp __b, _Fp __t) noexcept {
614+
if ((__a <= 0 && __b >= 0) || (__a >= 0 && __b <= 0))
615+
return __t * __b + (1 - __t) * __a;
616+
617+
if (__t == 1) return __b;
618+
const _Fp __x = __a + __t * (__b - __a);
619+
if (__t > 1 == __b > __a)
620+
return __b < __x ? __x : __b;
621+
else
622+
return __x < __b ? __x : __b;
623+
}
624+
625+
constexpr float
626+
lerp(float __a, float __b, float __t) _NOEXCEPT { return __lerp(__a, __b, __t); }
627+
628+
constexpr double
629+
lerp(double __a, double __b, double __t) _NOEXCEPT { return __lerp(__a, __b, __t); }
630+
631+
constexpr long double
632+
lerp(long double __a, long double __b, long double __t) _NOEXCEPT { return __lerp(__a, __b, __t); }
633+
634+
#endif // _LIBCPP_STD_VER > 17
635+
609636
_LIBCPP_END_NAMESPACE_STD
610637

611638
#endif // _LIBCPP_CMATH
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
9+
// <cmath>
10+
11+
// constexpr float lerp(float a, float b, float t);
12+
// constexpr double lerp(double a, double b, double t);
13+
// constexpr long double lerp(long double a, long double b, long double t);
14+
15+
16+
#include <cmath>
17+
#include <limits>
18+
#include <type_traits>
19+
#include <cassert>
20+
21+
#include "test_macros.h"
22+
#include "fp_compare.h"
23+
24+
template <typename T>
25+
constexpr bool constexpr_test()
26+
{
27+
return std::lerp(T( 0), T(12), T(0)) == T(0)
28+
&& std::lerp(T(12), T( 0), T(0.5)) == T(6)
29+
&& std::lerp(T( 0), T(12), T(2)) == T(24);
30+
}
31+
32+
33+
template <typename T>
34+
void test()
35+
{
36+
ASSERT_SAME_TYPE(T, decltype(std::lerp(T(), T(), T())));
37+
LIBCPP_ASSERT_NOEXCEPT( std::lerp(T(), T(), T()));
38+
39+
// constexpr T minV = std::numeric_limits<T>::min();
40+
constexpr T maxV = std::numeric_limits<T>::max();
41+
constexpr T inf = std::numeric_limits<T>::infinity();
42+
43+
// Things that can be compared exactly
44+
assert((std::lerp(T( 0), T(12), T(0)) == T(0)));
45+
assert((std::lerp(T( 0), T(12), T(1)) == T(12)));
46+
assert((std::lerp(T(12), T( 0), T(0)) == T(12)));
47+
assert((std::lerp(T(12), T( 0), T(1)) == T(0)));
48+
49+
assert((std::lerp(T( 0), T(12), T(0.5)) == T(6)));
50+
assert((std::lerp(T(12), T( 0), T(0.5)) == T(6)));
51+
assert((std::lerp(T( 0), T(12), T(2)) == T(24)));
52+
assert((std::lerp(T(12), T( 0), T(2)) == T(-12)));
53+
54+
assert((std::lerp(maxV, maxV/10, T(0)) == maxV));
55+
assert((std::lerp(maxV/10, maxV, T(1)) == maxV));
56+
57+
assert((std::lerp(T(2.3), T(2.3), inf) == T(2.3)));
58+
59+
assert(std::lerp(T( 0), T( 0), T(23)) == T(0));
60+
assert(std::isnan(std::lerp(T( 0), T( 0), inf)));
61+
}
62+
63+
64+
int main(int, char**)
65+
{
66+
static_assert(constexpr_test<float>(), "");
67+
static_assert(constexpr_test<double>(), "");
68+
static_assert(constexpr_test<long double>(), "");
69+
70+
test<float>();
71+
test<double>();
72+
test<long double>();
73+
74+
return 0;
75+
}

libcxx/www/cxx2a_status.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ <h3>Paper Status</h3>
141141
<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>
142142
<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>
143143
<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>
144-
<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>
144+
<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>
145145
<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>
146146
<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>
147147
<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>

0 commit comments

Comments
 (0)