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

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@359211 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/cmath b/include/cmath
index 3af9f54..f618b1b 100644
--- a/include/cmath
+++ b/include/cmath
@@ -302,6 +302,7 @@
 
 #include <__config>
 #include <math.h>
+#include <algorithm>
 #include <version>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -606,6 +607,32 @@
     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/test/std/numerics/c.math/c.math.lerp/c.math.lerp.pass.cpp b/test/std/numerics/c.math/c.math.lerp/c.math.lerp.pass.cpp
new file mode 100644
index 0000000..2ab41c1
--- /dev/null
+++ b/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/www/cxx2a_status.html b/www/cxx2a_status.html
index e6f5444..d8b0342 100644
--- a/www/cxx2a_status.html
+++ b/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>