Cleanup core/number.h with some c++20.
Remove the custom `kPi` and use the `std::numbers::pi_v`. Replace some
`std::enable_if` entries with `requires`.
Bug: 343500108
Change-Id: I9c4afba218c3034c5cdbd73ed3e20bfa87447018
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/242595
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
Auto-Submit: dan sinclair <dsinclair@chromium.org>
Commit-Queue: James Price <jrprice@google.com>
diff --git a/src/tint/lang/core/constant/eval.cc b/src/tint/lang/core/constant/eval.cc
index 7e60c2f..e93992a 100644
--- a/src/tint/lang/core/constant/eval.cc
+++ b/src/tint/lang/core/constant/eval.cc
@@ -29,6 +29,7 @@
#include <algorithm>
#include <limits>
+#include <numbers>
#include <string>
#include <type_traits>
#include <utility>
@@ -2456,8 +2457,7 @@
using NumberT = decltype(e);
using T = UnwrapNumber<NumberT>;
- auto pi = kPi<T>;
- auto scale = Div(source, NumberT(180), NumberT(pi));
+ auto scale = Div(source, NumberT(180), NumberT(std::numbers::pi_v<T>));
if (scale != Success) {
AddNote(source) << "when calculating degrees";
return error;
@@ -3389,8 +3389,7 @@
using NumberT = decltype(e);
using T = UnwrapNumber<NumberT>;
- auto pi = kPi<T>;
- auto scale = Div(source, NumberT(pi), NumberT(180));
+ auto scale = Div(source, NumberT(std::numbers::pi_v<T>), NumberT(180));
if (scale != Success) {
AddNote(source) << "when calculating radians";
return error;
diff --git a/src/tint/lang/core/number.h b/src/tint/lang/core/number.h
index 59f700f..f824a82 100644
--- a/src/tint/lang/core/number.h
+++ b/src/tint/lang/core/number.h
@@ -302,15 +302,13 @@
static_assert(std::numeric_limits<double>::has_infinity);
static_assert(std::numeric_limits<double>::has_quiet_NaN);
-template <typename T, std::enable_if_t<IsFloatingPoint<T>>* = nullptr>
-inline const auto kPi = T(UnwrapNumber<T>(3.14159265358979323846));
-
/// True iff T is an abstract number type
template <typename T>
constexpr bool IsAbstract = std::is_same_v<T, AInt> || std::is_same_v<T, AFloat>;
/// @returns the friendly name of Number type T
-template <typename T, std::enable_if_t<IsNumber<T>>* = nullptr>
+template <typename T>
+ requires(IsNumber<T>)
const char* FriendlyName() {
if constexpr (std::is_same_v<T, AInt>) {
return "abstract-int";
@@ -330,7 +328,8 @@
}
/// @returns the friendly name of T when T is bool
-template <typename T, std::enable_if_t<std::is_same_v<T, bool>>* = nullptr>
+template <typename T>
+ requires(std::is_same_v<T, bool>)
const char* FriendlyName() {
return "bool";
}
@@ -426,7 +425,8 @@
/// @param b the RHS number
/// @returns true if the numbers `a` and `b` are exactly equal.
template <typename A, typename B>
-std::enable_if_t<IsNumeric<B>, bool> operator==(Number<A> a, B b) {
+ requires(IsNumeric<B>)
+bool operator==(Number<A> a, B b) {
return a == Number<B>(b);
}
@@ -435,7 +435,8 @@
/// @param b the RHS number
/// @returns true if the numbers `a` and `b` are exactly unequal.
template <typename A, typename B>
-std::enable_if_t<IsNumeric<B>, bool> operator!=(Number<A> a, B b) {
+ requires(IsNumeric<B>)
+bool operator!=(Number<A> a, B b) {
return !(a == b);
}
@@ -444,7 +445,8 @@
/// @param b the RHS number
/// @returns true if the numbers `a` and `b` are exactly equal.
template <typename A, typename B>
-std::enable_if_t<IsNumeric<A>, bool> operator==(A a, Number<B> b) {
+ requires(IsNumeric<A>)
+bool operator==(A a, Number<B> b) {
return Number<A>(a) == b;
}
@@ -453,7 +455,8 @@
/// @param b the RHS number
/// @returns true if the numbers `a` and `b` are exactly unequal.
template <typename A, typename B>
-std::enable_if_t<IsNumeric<A>, bool> operator!=(A a, Number<B> b) {
+ requires(IsNumeric<A>)
+bool operator!=(A a, Number<B> b) {
return !(a == b);
}
@@ -496,7 +499,8 @@
/// @param a the LHS number
/// @param b the RHS number
/// @returns a + b, or an empty optional if the resulting value overflowed the float value
-template <typename FloatingPointT, typename = std::enable_if_t<IsFloatingPoint<FloatingPointT>>>
+template <typename FloatingPointT>
+ requires(IsFloatingPoint<FloatingPointT>)
inline std::optional<FloatingPointT> CheckedAdd(FloatingPointT a, FloatingPointT b) {
auto result = FloatingPointT{a.value + b.value};
if (!std::isfinite(result.value)) {
@@ -532,7 +536,8 @@
/// @param a the LHS number
/// @param b the RHS number
/// @returns a + b, or an empty optional if the resulting value overflowed the float value
-template <typename FloatingPointT, typename = std::enable_if_t<IsFloatingPoint<FloatingPointT>>>
+template <typename FloatingPointT>
+ requires(IsFloatingPoint<FloatingPointT>)
inline std::optional<FloatingPointT> CheckedSub(FloatingPointT a, FloatingPointT b) {
auto result = FloatingPointT{a.value - b.value};
if (!std::isfinite(result.value)) {
@@ -580,7 +585,8 @@
/// @param a the LHS number
/// @param b the RHS number
/// @returns a * b, or an empty optional if the resulting value overflowed the float value
-template <typename FloatingPointT, typename = std::enable_if_t<IsFloatingPoint<FloatingPointT>>>
+template <typename FloatingPointT>
+ requires(IsFloatingPoint<FloatingPointT>)
inline std::optional<FloatingPointT> CheckedMul(FloatingPointT a, FloatingPointT b) {
auto result = FloatingPointT{a.value * b.value};
if (!std::isfinite(result.value)) {
@@ -607,7 +613,8 @@
/// @param a the LHS number
/// @param b the RHS number
/// @returns a / b, or an empty optional if the resulting value overflowed the float value
-template <typename FloatingPointT, typename = std::enable_if_t<IsFloatingPoint<FloatingPointT>>>
+template <typename FloatingPointT>
+ requires(IsFloatingPoint<FloatingPointT>)
inline std::optional<FloatingPointT> CheckedDiv(FloatingPointT a, FloatingPointT b) {
if (b == FloatingPointT{0.0}) {
return {};
@@ -653,7 +660,8 @@
/// @param b the RHS number
/// @returns the remainder of a / b, or an empty optional if the resulting value overflowed the
/// float value
-template <typename FloatingPointT, typename = std::enable_if_t<IsFloatingPoint<FloatingPointT>>>
+template <typename FloatingPointT>
+ requires(IsFloatingPoint<FloatingPointT>)
inline std::optional<FloatingPointT> CheckedMod(FloatingPointT a, FloatingPointT b) {
if (b == FloatingPointT{0.0}) {
return {};
@@ -680,7 +688,8 @@
/// @param exp the exponent
/// @returns the value of `base` raised to the power `exp`, or an empty optional if the operation
/// cannot be performed.
-template <typename FloatingPointT, typename = std::enable_if_t<IsFloatingPoint<FloatingPointT>>>
+template <typename FloatingPointT>
+ requires(IsFloatingPoint<FloatingPointT>)
inline std::optional<FloatingPointT> CheckedPow(FloatingPointT base, FloatingPointT exp) {
static_assert(IsNumber<FloatingPointT>);
if ((base < 0) || (base == 0 && exp <= 0)) {
diff --git a/src/tint/lang/wgsl/resolver/eval_builtin_test.cc b/src/tint/lang/wgsl/resolver/eval_builtin_test.cc
index ed5e05c..f8582d4 100644
--- a/src/tint/lang/wgsl/resolver/eval_builtin_test.cc
+++ b/src/tint/lang/wgsl/resolver/eval_builtin_test.cc
@@ -27,6 +27,8 @@
#include "src/tint/lang/wgsl/resolver/eval_test.h"
+#include <numbers>
+
#include "src/tint/utils/result.h"
using namespace tint::core::number_suffixes; // NOLINT
@@ -412,15 +414,17 @@
template <typename T>
std::vector<Case> AcosCases() {
+ auto pi = std::numbers::pi_v<UnwrapNumber<T>>;
+
return {
// If i is +/-0, +/-0 is returned
C({T(0.87758256189)}, T(0.5)).FloatComp(),
C({T(1.0)}, T(0.0)),
- C({-T(1.0)}, kPi<T>).FloatComp(),
+ C({-T(1.0)}, T(pi)).FloatComp(),
// Vector tests
- C({Vec(T(1.0), -T(1.0))}, Vec(T(0), kPi<T>)).FloatComp(),
+ C({Vec(T(1.0), -T(1.0))}, Vec(T(0), T(pi))).FloatComp(),
E({T(1.1)},
"12:34 error: acos must be called with a value in the range [-1 .. 1] (inclusive)"),
@@ -438,12 +442,13 @@
template <typename T>
std::vector<Case> AcoshCases() {
+ auto pi = std::numbers::pi_v<UnwrapNumber<T>>;
return {
C({T(1.0)}, T(0.0)),
- C({T(11.5919532755)}, kPi<T>).FloatComp(),
+ C({T(11.5919532755)}, T(pi)).FloatComp(),
// Vector tests
- C({Vec(T(1.0), T(11.5919532755))}, Vec(T(0), kPi<T>)).FloatComp(),
+ C({Vec(T(1.0), T(11.5919532755))}, Vec(T(0), T(pi))).FloatComp(),
E({T::Smallest()}, "12:34 error: acosh must be called with a value >= 1.0"),
E({-T(1.1)}, "12:34 error: acosh must be called with a value >= 1.0"),
@@ -1017,7 +1022,7 @@
auto x = builder::As<T>(v.args[0]);
auto y = builder::As<T>(v.args[1]);
auto z = builder::As<T>(v.args[2]);
- auto rads = T(degs) * kPi<T> / T(180);
+ auto rads = T(degs) * std::numbers::pi_v<UnwrapNumber<T>> / T(180);
auto x2 = T(x * std::cos(rads) - y * std::sin(rads));
auto y2 = T(x * std::sin(rads) + y * std::cos(rads));
return Vec(x2, y2, z);
@@ -2284,8 +2289,8 @@
auto eta = [](auto angle1, auto angle2) {
// Snell's law: sin(angle1) / sin(angle2) == n2 / n1
// We want the ratio of n1 to n2, so sin(angle2) / sin(angle1)
- auto angle1_rads = T(angle1) * kPi<T> / T(180);
- auto angle2_rads = T(angle2) * kPi<T> / T(180);
+ auto angle1_rads = T(angle1) * std::numbers::pi_v<UnwrapNumber<T>> / T(180);
+ auto angle2_rads = T(angle2) * std::numbers::pi_v<UnwrapNumber<T>> / T(180);
return T(std::sin(angle2_rads) / std::sin(angle1_rads));
};