Defined in header <cmath>
constexpr float lerp( float a, float b, float t ) noexcept; (1)
(since C++20)
constexpr double lerp( double a, double b, double t ) noexcept; (2)
(since C++20)
constexpr long double lerp( long double a, long double b, long (3)
(since C++20)
double t ) noexcept;
constexpr Promoted lerp( Arithmetic1 a, Arithmetic2 b, Arithmetic3 (4)
(since C++20)
t ) noexcept;
1-3) Computes the linear interpolation between a and b, if the parameter t is
inside
[0, 1] (the linear extrapolation otherwise), i.e. the result of
\(a+t(b−a)\)a+t(b−a) with accounting for floating-point
calculation imprecision.
4) A set of overloads or a function template for all combinations of
arguments of
arithmetic type not covered by 1-3). If any argument has integral type, it is
cast
to double. If any other argument is long double, then the return type is long
double, otherwise it is double.
a, b, t - values of floating-point or integral types
\(a+t(b−a)\)a+t(b−a)
When isfinite(a) and isfinite(b), the following properties are
guaranteed:
* If t == 0, the result is equal to a.
* If t == 1, the result is equal to b.
* If t >= 0 && t <= 1, the result is finite.
* If isfinite(t) && a == b, the result is equal to a.
* If isfinite(t) || (b - a != 0 and isinf(t)), the result is not NaN.
Let CMP(x,y) be 1 if x > y, -1 if x < y, and 0 otherwise. For any t1
and t2, the
product of CMP(lerp(a, b, t2), lerp(a, b, t1)), CMP(t2, t1), and CMP(b, a) is
non-negative. (That is, lerp is monotonic.)
lerp is available in the global namespace when <math.h> is
included, even if it is
not a part of C.
Feature-test macro: __cpp_lib_interpolate
// Run this code
#include <cmath>
#include <cassert>
#include <iostream>
float naive_lerp(float a, float b, float t)
{
return a + t * (b - a);
}
int main()
{
std::cout << std::boolalpha;
const float a = 1e8f, b = 1.0f;
const float midpoint = std::lerp(a, b, 0.5f);
std::cout << "a = " << a << ", "
<< "b = " << b << '\n'
<< "midpoint = " << midpoint << '\n';
std::cout << "std::lerp is exact: "
<< (a == std::lerp(a, b, 0.0f)) << ' '
<< (b == std::lerp(a, b, 1.0f)) << '\n';
std::cout << "naive_lerp is exact: "
<< (a == naive_lerp(a, b, 0.0f)) << ' '
<< (b == naive_lerp(a, b, 1.0f)) << '\n';
std::cout << "std::lerp(a, b, 1.0f) = " << std::lerp(a,
b, 1.0f) << '\n'
<< "naive_lerp(a, b, 1.0f) = " << naive_lerp(a, b,
1.0f) << '\n';
assert(not std::isnan(std::lerp(a, b, INFINITY))); // lerp here can be
-inf
std::cout << "Extrapolation demo, given std::lerp(5, 10,
t):\n";
for (auto t{-2.0}; t <= 2.0; t += 0.5)
std::cout << std::lerp(5.0, 10.0, t) << ' ';
std::cout << '\n';
}
a = 1e+08, b = 1
midpoint = 5e+07
std::lerp is exact?: true true
naive_lerp is exact?: true false
std::lerp(a, b, 1.0f) = 1
naive_lerp(a, b, 1.0f) = 0
Extrapolation demo, given std::lerp(5, 10, t):
-5 -2.5 0 2.5 5 7.5 10 12.5 15
midpoint midpoint between two numbers or pointers
(C++20) (function template)