`<cmath>`: add arithmetic overloads for `std::lerp` (#2113)

Co-authored-by: Casey Carter <Casey@Carter.net>
Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
This commit is contained in:
Igor Zhukov 2022-05-05 16:03:25 +07:00 коммит произвёл GitHub
Родитель 24b899e4ad
Коммит 39a0ea71be
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 25 добавлений и 4 удалений

Просмотреть файл

@ -693,7 +693,7 @@ _GENERIC_MATH2(fdim)
_GENERIC_MATH2(fmax) _GENERIC_MATH2(fmax)
_GENERIC_MATH2(fmin) _GENERIC_MATH2(fmin)
// fma() is hand-crafted // fma() is hand-crafted
// lerp() should be exempt, LWG-3223 // lerp() is hand-crafted
// The "classification/comparison functions" (fpclassify(), etc.) are exempt, LWG-1327 // The "classification/comparison functions" (fpclassify(), etc.) are exempt, LWG-1327
// TRANSITION, VSO-945789, Special Math shouldn't be exempt // TRANSITION, VSO-945789, Special Math shouldn't be exempt
@ -1308,9 +1308,6 @@ _NODISCARD constexpr _Ty _Common_lerp(const _Ty _ArgA, const _Ty _ArgB, const _T
} }
} }
// As of 2019-06-17 it is unclear whether the "sufficient additional overloads" clause is intended to target lerp;
// LWG-3223 is pending.
_NODISCARD constexpr inline float lerp(const float _ArgA, const float _ArgB, const float _ArgT) noexcept { _NODISCARD constexpr inline float lerp(const float _ArgA, const float _ArgB, const float _ArgT) noexcept {
return _Common_lerp(_ArgA, _ArgB, _ArgT); return _Common_lerp(_ArgA, _ArgB, _ArgT);
} }
@ -1323,6 +1320,13 @@ _NODISCARD constexpr inline long double lerp(
const long double _ArgA, const long double _ArgB, const long double _ArgT) noexcept { const long double _ArgA, const long double _ArgB, const long double _ArgT) noexcept {
return _Common_lerp(_ArgA, _ArgB, _ArgT); return _Common_lerp(_ArgA, _ArgB, _ArgT);
} }
template <class _Ty1, class _Ty2, class _Ty3,
enable_if_t<is_arithmetic_v<_Ty1> && is_arithmetic_v<_Ty2> && is_arithmetic_v<_Ty3>, int> = 0>
_NODISCARD constexpr auto lerp(const _Ty1 _ArgA, const _Ty2 _ArgB, const _Ty3 _ArgT) noexcept {
using _Tgt = conditional_t<_Is_any_of_v<long double, _Ty1, _Ty2, _Ty3>, long double, double>;
return _Common_lerp(static_cast<_Tgt>(_ArgA), static_cast<_Tgt>(_ArgB), static_cast<_Tgt>(_ArgT));
}
#endif // _HAS_CXX20 #endif // _HAS_CXX20
_STD_END _STD_END
#endif // _HAS_CXX17 #endif // _HAS_CXX17

Просмотреть файл

@ -1023,6 +1023,20 @@ bool test_lerp() {
return true; return true;
} }
constexpr bool test_gh_2112() {
// GH-2112 <cmath>: std::lerp is missing Arithmetic overloads
assert(lerp(0, 0, 0) == 0.0);
assert(lerp(0.0f, 0.0f, 0.0) == 0.0);
assert(lerp(0.0L, 0, 0) == 0.0L);
STATIC_ASSERT(is_same_v<double, decltype(lerp(0, 0, 0))>);
STATIC_ASSERT(is_same_v<long double, decltype(lerp(0.0L, 0, 0))>);
STATIC_ASSERT(is_same_v<long double, decltype(lerp(0, 0.0L, 0))>);
STATIC_ASSERT(is_same_v<long double, decltype(lerp(0, 0, 0.0L))>);
return true;
}
int main() { int main() {
test_constants<float>(); test_constants<float>();
test_constants<double>(); test_constants<double>();
@ -1093,4 +1107,7 @@ int main() {
test_lerp<float>(); test_lerp<float>();
test_lerp<double>(); test_lerp<double>();
test_lerp<long double>(); test_lerp<long double>();
test_gh_2112();
STATIC_ASSERT(test_gh_2112());
} }