#endif // _GLIBCXX_USE_C99_MATH_TR1
#endif // C++11
-#if __cplusplus > 201402L
+#if __cplusplus >= 201703L
// [c.math.hypot3], three-dimensional hypotenuse
#define __cpp_lib_hypot 201603
{ return std::__hypot3<long double>(__x, __y, __z); }
template<typename _Tp, typename _Up, typename _Vp>
- typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type
+ __gnu_cxx::__promoted_t<_Tp, _Up, _Vp>
hypot(_Tp __x, _Up __y, _Vp __z)
{
- using __type = typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type;
+ using __type = __gnu_cxx::__promoted_t<_Tp, _Up, _Vp>;
return std::__hypot3<__type>(__x, __y, __z);
}
#endif // C++17
-#if __cplusplus > 201703L
+#if __cplusplus >= 202002L
// linear interpolation
# define __cpp_lib_interpolate 201902L
constexpr long double
lerp(long double __a, long double __b, long double __t) noexcept
{ return std::__lerp(__a, __b, __t); }
+
+ template<typename _Tp, typename _Up, typename _Vp>
+ constexpr __gnu_cxx::__promoted_t<_Tp, _Up, _Vp>
+ lerp(_Tp __x, _Up __y, _Vp __z) noexcept
+ {
+ using __type = __gnu_cxx::__promoted_t<_Tp, _Up, _Vp>;
+ return std::__lerp<__type>(__x, __y, __z);
+ }
#endif // C++20
_GLIBCXX_END_NAMESPACE_VERSION
{ return true; }
#endif
- // For complex and cmath
+ // For arithmetic promotions in <complex> and <cmath>
+
template<typename _Tp, bool = std::__is_integer<_Tp>::__value>
struct __promote
{ typedef double __type; };
struct __promote<float>
{ typedef float __type; };
+#if __cpp_fold_expressions
+ template<typename... _Tp>
+ using __promoted_t = decltype((typename __promote<_Tp>::__type(0) + ...));
+#endif
+
template<typename _Tp, typename _Up,
typename _Tp2 = typename __promote<_Tp>::__type,
typename _Up2 = typename __promote<_Up>::__type>
--- /dev/null
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <cmath>
+
+// Fails template argument deduction unless both arguments are the same type.
+template<typename T>
+constexpr bool
+eq(T result, T expected) { return result == expected; }
+
+static_assert( eq( std::lerp(-10.0, 10.0, 0.25), -5.0 ) );
+static_assert( eq( std::lerp(2.0f, 2.0f, 200.0f), 2.0f ) );
+static_assert( eq( std::lerp(2.0L, 4.0L, 200.0L), 402.0L ) );
+// at least one type is long double, so result is long double
+static_assert( eq( std::lerp(2.0L, 4.0f, -20.0), -38.0L ) );
+// at least one type is double, so result is double:
+static_assert( eq( std::lerp(-8.0f, 10.0, 0.5f), 1.0 ) );
+// int promotes to double, so result is double
+static_assert( eq( std::lerp(0, 1, 0), 0.0 ) );
+// int promotes to double, so result is double
+static_assert( eq( std::lerp(2.0f, -10.0f, 1), -10.0 ) );
--- /dev/null
+// { dg-options "-std=gnu++2a" }
+// { dg-do preprocess { target c++2a } }
+
+#include <version>
+
+#ifndef __cpp_lib_interpolate
+# error "Feature-test macro for midpoint and lerp missing in <version>"
+#elif __cpp_lib_interpolate != 201902L
+# error "Feature-test macro for midpoint and lerp has wrong value in <version>"
+#endif