public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r9-10059] libstdc++: Add additional overload of std::lerp [PR101870]
@ 2022-05-09 16:40 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2022-05-09 16:40 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:5ed333b0762d847ffb0096ba97e924188c766d69

commit r9-10059-g5ed333b0762d847ffb0096ba97e924188c766d69
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Aug 12 17:35:25 2021 +0100

    libstdc++: Add additional overload of std::lerp [PR101870]
    
    The [cmath.syn] p1 wording about additional overloads sufficient to
    handle any arithmetic types also applies to std::lerp. This adds a new
    overload of std::lerp that does the required promotions to support
    arguments of arbitrary arithmetic types.
    
    A new __promoted_t alias template is added, which the C++17 function
    templates std::hypot and std::lerp can use to avoid instantiating the
    __promote_3 class template.
    
    Signed-off-by: Jonathan Wakely <jwakely@redhat.com>
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/101870
            * include/c_global/cmath (hypot): Use __promoted_t.
            (lerp): Add new overload accepting any arithmetic types.
            * include/ext/type_traits.h (__promoted_t): New alias template.
            * testsuite/26_numerics/lerp.cc: Moved to...
            * testsuite/26_numerics/lerp/1.cc: ...here.
            * testsuite/26_numerics/lerp/constexpr.cc: New test.
            * testsuite/26_numerics/lerp/version.cc: New test.
    
    (cherry picked from commit 9017326e19fe278d5f62898cca4682b17f8e8e07)

Diff:
---
 libstdc++-v3/include/c_global/cmath                 | 14 +++++++++++---
 libstdc++-v3/include/ext/type_traits.h              |  8 +++++++-
 .../testsuite/26_numerics/{lerp.cc => lerp/1.cc}    |  0
 .../testsuite/26_numerics/lerp/constexpr.cc         | 21 +++++++++++++++++++++
 libstdc++-v3/testsuite/26_numerics/lerp/version.cc  | 10 ++++++++++
 5 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/libstdc++-v3/include/c_global/cmath b/libstdc++-v3/include/c_global/cmath
index 01e56a559fe..11f0706e203 100644
--- a/libstdc++-v3/include/c_global/cmath
+++ b/libstdc++-v3/include/c_global/cmath
@@ -1844,7 +1844,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #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
@@ -1877,10 +1877,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   { 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
@@ -1918,6 +1918,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   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
diff --git a/libstdc++-v3/include/ext/type_traits.h b/libstdc++-v3/include/ext/type_traits.h
index 97163911c29..49af656a7e8 100644
--- a/libstdc++-v3/include/ext/type_traits.h
+++ b/libstdc++-v3/include/ext/type_traits.h
@@ -163,7 +163,8 @@ _GLIBCXX_BEGIN_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; };
@@ -187,6 +188,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     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>
diff --git a/libstdc++-v3/testsuite/26_numerics/lerp.cc b/libstdc++-v3/testsuite/26_numerics/lerp/1.cc
similarity index 100%
rename from libstdc++-v3/testsuite/26_numerics/lerp.cc
rename to libstdc++-v3/testsuite/26_numerics/lerp/1.cc
diff --git a/libstdc++-v3/testsuite/26_numerics/lerp/constexpr.cc b/libstdc++-v3/testsuite/26_numerics/lerp/constexpr.cc
new file mode 100644
index 00000000000..f1ab42b5a42
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/lerp/constexpr.cc
@@ -0,0 +1,21 @@
+// { 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 ) );
diff --git a/libstdc++-v3/testsuite/26_numerics/lerp/version.cc b/libstdc++-v3/testsuite/26_numerics/lerp/version.cc
new file mode 100644
index 00000000000..3ccb032bc67
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/lerp/version.cc
@@ -0,0 +1,10 @@
+// { 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


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-05-09 16:40 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-09 16:40 [gcc r9-10059] libstdc++: Add additional overload of std::lerp [PR101870] Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).