名前空間
変種
操作

std::lerp

From cppreference.com
< cpp‎ | numeric
 
 
 
ヘッダー <cmath> で定義
(1)
constexpr float       lerp( float a, float b, float t ) noexcept;

constexpr double      lerp( double a, double b, double t ) noexcept;
constexpr long double lerp( long double a, long double b,

                            long double t ) noexcept;
(C++20以降)
(C++23まで)
constexpr /* floating-point-type */

    lerp( /* floating-point-type */ a,
          /* floating-point-type */ b,

          /* floating-point-type */ t ) noexcept;
(C++23から)
ヘッダー <cmath> で定義
template< class Arithmetic1, class Arithmetic2, class Arithmetic3 >

constexpr /* common-floating-point-type */

    lerp( Arithmetic1 a, Arithmetic2 b, Arithmetic3 t ) noexcept;
(A) (C++20以降)
1) パラメータ t[01) の範囲内にある場合、ab の間の線形補間を計算します(それ以外の場合は線形外挿)。すなわち、浮動小数点計算の不正確さを考慮した a+t(b−a) の結果を計算します。 ライブラリは、パラメータ ab、および t の型として、すべてのcv修飾なし浮動小数点型に対するオーバーロードを提供します。(C++23以降)
A) その他の算術型の組み合わせすべてに対して、追加のオーバーロードが提供されます。

目次

[編集] パラメータ

a, b, t - 浮動小数点または整数値

[編集] 戻り値

a + t(b − a)

std::isfinite(a) && std::isfinite(b)true の場合、以下の特性が保証されます。

  • もし t == 0 ならば、結果は a と等しい。
  • もし t == 1 ならば、結果は b と等しい。
  • もし t >= 0 && t <= 1 ならば、結果は有限である。
  • もし std::isfinite(t) && a == b ならば、結果は a と等しい。
  • もし std::isfinite(t) || (b - a != 0 && std::isinf(t)) ならば、結果は NaN ではない。

CMP(x, y) を、x > y の場合は 1x < y の場合は -1、それ以外の場合は 0 とします。任意の t1t2 に対して、以下の積は

  • CMP(std::lerp(a, b, t2), std::lerp(a, b, t1)),
  • CMP(t2, t1)、および
  • CMP(b, a)

は非負である。(すなわち、std::lerp は単調である。)

[編集] 備考

追加のオーバーロードは、(A) とまったく同じように提供される必要はありません。それらは、最初の引数 num1、2番目の引数 num2、3番目の引数 num3 に対して、以下のことを保証するのに十分であるだけでよいです。

  • もし num1num2 または num3 の型が long double である場合、std::lerp(num1, num2, num3)std::lerp(static_cast<long double>(num1),
              static_cast<long double>(num2),
              static_cast<long double>(num3))
    と同じ効果を持ちます。
  • そうでない場合、もし num1num2 および/または num3 の型が double または整数型である場合、std::lerp(num1, num2, num3)std::lerp(static_cast<double>(num1),
              static_cast<double>(num2),
              static_cast<double>(num3))
    と同じ効果を持ちます。
  • そうでない場合、もし num1num2 または num3 の型が float である場合、std::lerp(num1, num2, num3)std::lerp(static_cast<float>(num1),
              static_cast<float>(num2),
              static_cast<float>(num3))
    と同じ効果を持ちます。
(C++23まで)

もし num1num2num3 が算術型である場合、std::lerp(num1, num2, num3)std::lerp(static_cast</*common-floating-point-type*/>(num1),
          static_cast</*common-floating-point-type*/>(num2),
          static_cast</*common-floating-point-type*/>(num3))
と同じ効果を持ちます。ここで /*common-floating-point-type*/ は、num1num2num3 の型の中で、最も高い浮動小数点変換ランクと最も高い浮動小数点変換サブランクを持つ浮動小数点型です。整数型の引数は、double と同じ浮動小数点変換ランクを持つとみなされます。

そのような最高のランクとサブランクセを持つ浮動小数点型が存在しない場合、オーバーロード解決は提供されたオーバーロードから使用可能な候補を導出しません。

(C++23から)
機能テストマクロ 規格 機能
__cpp_lib_interpolate 201902L (C++20) std::lerpstd::midpoint

[編集]

#include <cassert>
#include <cmath>
#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

[編集] 関連項目

(C++20)
2つの数値またはポインタの中間点
(関数テンプレート) [編集]
English 日本語 中文(简体) 中文(繁體)