Difference between revisions of "cpp/numeric/lerp"
From cppreference.com
m (→Example: added +1 comparison with `naïve_lerp` and shortened the extrapolation demo case.) |
m (→Top: added wiki-links, +some elaborations.) |
||
Line 17: | Line 17: | ||
{{dcl end}} | {{dcl end}} | ||
− | @1-3@ Computes the linear interpolation | + | @1-3@ Computes the linear [[enwiki:Linear_interpolation|interpolation]] or [[enwiki:Extrapolation#Linear|extrapolation]] between {{tt|a}} and {{tt|b}}, depending on the parameter {{tt|t}} (interpolation, if {{tt|t}} is inside {{tt|[0, 1]}}, extrapolation otherwise), i.e. the result of {{mathjax-or|\(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 [[cpp/types/is_arithmetic|arithmetic type]] not covered by 1-3). If any argument has [[cpp/types/is_integral|integral type]], it is cast to {{c|double}}. If any other argument is {{c|long double}}, then the return type is {{c|long double}}, otherwise it is {{c|double}}. | @4@ A set of overloads or a function template for all combinations of arguments of [[cpp/types/is_arithmetic|arithmetic type]] not covered by 1-3). If any argument has [[cpp/types/is_integral|integral type]], it is cast to {{c|double}}. If any other argument is {{c|long double}}, then the return type is {{c|long double}}, otherwise it is {{c|double}}. | ||
Revision as of 19:12, 2 January 2022
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 double t ) noexcept; |
(3) | (since C++20) |
constexpr Promoted lerp( Arithmetic1 a, Arithmetic2 b, Arithmetic3 t ) noexcept; |
(4) | (since C++20) |
1-3) Computes the linear interpolation or extrapolation between
a
and b
, depending on the parameter t
(interpolation, if t
is inside [0, 1]
, extrapolation otherwise), i.e. the result of 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.
Contents |
Parameters
a, b, t | - | values of floating-point or integral types |
Return value
a+t(b−a)
When isfinite(a) and isfinite(b), the following properties are guaranteed:
- If
t == 0
, the result is equal toa
. - If
t == 1
, the result is equal tob
. - If
t >= 0 && t <= 1
, the result is finite. - If
isfinite(t) && a == b
, the result is equal toa
. - If
isfinite(t) || (a != b
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.)
Notes
lerp
is available in the global namespace when <math.h>
is included, even if it is not a part of C.
Feature testing macro: __cpp_lib_interpolate.
Example
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'; }
Possible output:
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
See also
(C++20) |
midpoint between two numbers or pointers (function template) |