From 567a53e87cef93a2f4086765920b2c401c7ff0a7 Mon Sep 17 00:00:00 2001 From: Ben Clayton Date: Tue, 9 May 2023 15:10:05 +0000 Subject: [PATCH] tint/utils: Add Vector::Any(), Vector::All() and predicates Can be used to write simple whole-vector comparision checks. Change-Id: I441a7e8d6b626a5a32ef3db9043e771f792900d3 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/131746 Reviewed-by: Antonio Maiorano Commit-Queue: Ben Clayton Kokoro: Ben Clayton Kokoro: Kokoro --- src/tint/BUILD.gn | 2 + src/tint/CMakeLists.txt | 2 + src/tint/utils/predicates.h | 78 +++++++++++++++++++++++++++++ src/tint/utils/predicates_test.cc | 83 +++++++++++++++++++++++++++++++ src/tint/utils/vector.h | 14 ++++++ src/tint/utils/vector_test.cc | 40 ++++++++++++--- 6 files changed, 213 insertions(+), 6 deletions(-) create mode 100644 src/tint/utils/predicates.h create mode 100644 src/tint/utils/predicates_test.cc diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn index 8cf3daa93c..f106fb96cf 100644 --- a/src/tint/BUILD.gn +++ b/src/tint/BUILD.gn @@ -251,6 +251,7 @@ libtint_source_set("libtint_utils_src") { "utils/hashset.h", "utils/map.h", "utils/math.h", + "utils/predicates.h", "utils/scoped_assignment.h", "utils/slice.h", "utils/string.cc", @@ -1725,6 +1726,7 @@ if (tint_build_unittests) { "utils/io/tmpfile_test.cc", "utils/map_test.cc", "utils/math_test.cc", + "utils/predicates_test.cc", "utils/result_test.cc", "utils/reverse_test.cc", "utils/scoped_assignment_test.cc", diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt index f47d2cea2c..c4a8724147 100644 --- a/src/tint/CMakeLists.txt +++ b/src/tint/CMakeLists.txt @@ -532,6 +532,7 @@ list(APPEND TINT_LIB_SRCS utils/hashset.h utils/map.h utils/math.h + utils/predicates.h utils/scoped_assignment.h utils/slice.h utils/string.cc @@ -1030,6 +1031,7 @@ if(TINT_BUILD_TESTS) utils/hashset_test.cc utils/map_test.cc utils/math_test.cc + utils/predicates_test.cc utils/result_test.cc utils/reverse_test.cc utils/scoped_assignment_test.cc diff --git a/src/tint/utils/predicates.h b/src/tint/utils/predicates.h new file mode 100644 index 0000000000..0769b30d0d --- /dev/null +++ b/src/tint/utils/predicates.h @@ -0,0 +1,78 @@ +// Copyright 2023 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_TINT_UTILS_PREDICATES_H_ +#define SRC_TINT_UTILS_PREDICATES_H_ + +namespace tint::utils { + +/// @param value the value to compare against +/// @return a function with the signature `bool(const T&)` which returns true if the argument is +/// equal to +/// @p value +template +auto Eq(const T& value) { + return [value](const T& v) { return v == value; }; +} + +/// @param value the value to compare against +/// @return a function with the signature `bool(const T&)` which returns true if the argument is not +/// equal to @p value +template +auto Ne(const T& value) { + return [value](const T& v) { return v != value; }; +} + +/// @param value the value to compare against +/// @return a function with the signature `bool(const T&)` which returns true if the argument is +/// greater than @p value +template +auto Gt(const T& value) { + return [value](const T& v) { return v > value; }; +} + +/// @param value the value to compare against +/// @return a function with the signature `bool(const T&)` which returns true if the argument is +/// less than +/// @p value +template +auto Lt(const T& value) { + return [value](const T& v) { return v < value; }; +} + +/// @param value the value to compare against +/// @return a function with the signature `bool(const T&)` which returns true if the argument is +/// greater or equal to @p value +template +auto Ge(const T& value) { + return [value](const T& v) { return v >= value; }; +} + +/// @param value the value to compare against +/// @return a function with the signature `bool(const T&)` which returns true if the argument is +/// less than or equal to @p value +template +auto Le(const T& value) { + return [value](const T& v) { return v <= value; }; +} + +/// @param ptr the pointer +/// @return true if the pointer argument is null. +static inline bool IsNull(const void* ptr) { + return ptr == nullptr; +} + +} // namespace tint::utils + +#endif // SRC_TINT_UTILS_PREDICATES_H_ diff --git a/src/tint/utils/predicates_test.cc b/src/tint/utils/predicates_test.cc new file mode 100644 index 0000000000..7733cf771d --- /dev/null +++ b/src/tint/utils/predicates_test.cc @@ -0,0 +1,83 @@ +// Copyright 2021 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/tint/utils/predicates.h" + +#include "gtest/gtest.h" + +namespace tint::utils { +namespace { + +TEST(PredicatesTest, Eq) { + auto pred = Eq(3); + EXPECT_FALSE(pred(1)); + EXPECT_FALSE(pred(2)); + EXPECT_TRUE(pred(3)); + EXPECT_FALSE(pred(4)); + EXPECT_FALSE(pred(5)); +} + +TEST(PredicatesTest, Ne) { + auto pred = Ne(3); + EXPECT_TRUE(pred(1)); + EXPECT_TRUE(pred(2)); + EXPECT_FALSE(pred(3)); + EXPECT_TRUE(pred(4)); + EXPECT_TRUE(pred(5)); +} + +TEST(PredicatesTest, Gt) { + auto pred = Gt(3); + EXPECT_FALSE(pred(1)); + EXPECT_FALSE(pred(2)); + EXPECT_FALSE(pred(3)); + EXPECT_TRUE(pred(4)); + EXPECT_TRUE(pred(5)); +} + +TEST(PredicatesTest, Lt) { + auto pred = Lt(3); + EXPECT_TRUE(pred(1)); + EXPECT_TRUE(pred(2)); + EXPECT_FALSE(pred(3)); + EXPECT_FALSE(pred(4)); + EXPECT_FALSE(pred(5)); +} + +TEST(PredicatesTest, Ge) { + auto pred = Ge(3); + EXPECT_FALSE(pred(1)); + EXPECT_FALSE(pred(2)); + EXPECT_TRUE(pred(3)); + EXPECT_TRUE(pred(4)); + EXPECT_TRUE(pred(5)); +} + +TEST(PredicatesTest, Le) { + auto pred = Le(3); + EXPECT_TRUE(pred(1)); + EXPECT_TRUE(pred(2)); + EXPECT_TRUE(pred(3)); + EXPECT_FALSE(pred(4)); + EXPECT_FALSE(pred(5)); +} + +TEST(PredicatesTest, IsNull) { + int i = 1; + EXPECT_TRUE(IsNull(nullptr)); + EXPECT_FALSE(IsNull(&i)); +} + +} // namespace +} // namespace tint::utils diff --git a/src/tint/utils/vector.h b/src/tint/utils/vector.h index ed4fcf162b..65595e7920 100644 --- a/src/tint/utils/vector.h +++ b/src/tint/utils/vector.h @@ -322,6 +322,20 @@ class Vector { Sort([](auto& a, auto& b) { return a < b; }); } + /// @returns true if the predicate function returns true for any of the elements of the vector + /// @param pred a function-like with the signature `bool(T)` + template + bool Any(PREDICATE&& pred) const { + return std::any_of(begin(), end(), std::forward(pred)); + } + + /// @returns false if the predicate function returns false for any of the elements of the vector + /// @param pred a function-like with the signature `bool(T)` + template + bool All(PREDICATE&& pred) const { + return std::all_of(begin(), end(), std::forward(pred)); + } + /// @returns true if the vector is empty. bool IsEmpty() const { return impl_.slice.len == 0; } diff --git a/src/tint/utils/vector_test.cc b/src/tint/utils/vector_test.cc index 06047326f4..bb70e08f53 100644 --- a/src/tint/utils/vector_test.cc +++ b/src/tint/utils/vector_test.cc @@ -20,6 +20,7 @@ #include "gmock/gmock.h" #include "src/tint/utils/bitcast.h" +#include "src/tint/utils/predicates.h" #include "src/tint/utils/string_stream.h" namespace tint::utils { @@ -1788,6 +1789,38 @@ TEST(TintVectorTest, Equality) { EXPECT_NE((Vector{2, 1}), (Vector{1, 2})); } +TEST(TintVectorTest, Sort) { + Vector vec{1, 5, 3, 4, 2}; + vec.Sort(); + EXPECT_THAT(vec, testing::ElementsAre(1, 2, 3, 4, 5)); +} + +TEST(TintVectorTest, Any) { + Vector vec{1, 7, 5, 9}; + EXPECT_TRUE(vec.Any(Eq(1))); + EXPECT_FALSE(vec.Any(Eq(2))); + EXPECT_FALSE(vec.Any(Eq(3))); + EXPECT_FALSE(vec.Any(Eq(4))); + EXPECT_TRUE(vec.Any(Eq(5))); + EXPECT_FALSE(vec.Any(Eq(6))); + EXPECT_TRUE(vec.Any(Eq(7))); + EXPECT_FALSE(vec.Any(Eq(8))); + EXPECT_TRUE(vec.Any(Eq(9))); +} + +TEST(TintVectorTest, All) { + Vector vec{1, 7, 5, 9}; + EXPECT_FALSE(vec.All(Ne(1))); + EXPECT_TRUE(vec.All(Ne(2))); + EXPECT_TRUE(vec.All(Ne(3))); + EXPECT_TRUE(vec.All(Ne(4))); + EXPECT_FALSE(vec.All(Ne(5))); + EXPECT_TRUE(vec.All(Ne(6))); + EXPECT_FALSE(vec.All(Ne(7))); + EXPECT_TRUE(vec.All(Ne(8))); + EXPECT_FALSE(vec.All(Ne(9))); +} + TEST(TintVectorTest, ostream) { utils::StringStream ss; ss << Vector{1, 2, 3}; @@ -2005,12 +2038,6 @@ TEST(TintVectorRefTest, Index) { EXPECT_EQ(vec_ref[1], "two"); } -TEST(TintVectorRefTest, Sort) { - Vector vec{1, 5, 3, 4, 2}; - vec.Sort(); - EXPECT_THAT(vec, testing::ElementsAre(1, 2, 3, 4, 5)); -} - TEST(TintVectorRefTest, SortPredicate) { Vector vec{1, 5, 3, 4, 2}; vec.Sort([](int a, int b) { return b < a; }); @@ -2072,6 +2099,7 @@ TEST(TintVectorRefTest, ostream) { ss << vec_ref; EXPECT_EQ(ss.str(), "[1, 2, 3]"); } + } // namespace } // namespace tint::utils