diff options
author | 2021-02-23 23:16:31 +0000 | |
---|---|---|
committer | 2021-02-23 23:16:31 +0000 | |
commit | 47fa868e419a0f50008c17151477493bafec192b (patch) | |
tree | 02cf1faaae9fd51c046ce013672d97fe6f580d9c | |
parent | ee577e1b3691af74612929ca00743f2230180f15 (diff) | |
parent | ce58d5b19aac30ab10f08ad16a1e437bffe43e11 (diff) |
Merge changes from topic "libui_hashcombine" into sc-dev
* changes:
libui: Add std::hash support for Rects/Region
libmath: Add HashCombine
-rw-r--r-- | libs/math/Android.bp | 20 | ||||
-rw-r--r-- | libs/math/include/math/HashCombine.h | 38 | ||||
-rw-r--r-- | libs/math/include/math/TVecHelpers.h | 26 | ||||
-rw-r--r-- | libs/math/include/math/half.h | 7 | ||||
-rw-r--r-- | libs/math/tests/Android.bp | 7 | ||||
-rw-r--r-- | libs/math/tests/half_test.cpp | 9 | ||||
-rw-r--r-- | libs/math/tests/hashcombine_test.cpp | 43 | ||||
-rw-r--r-- | libs/ui/Android.bp | 2 | ||||
-rw-r--r-- | libs/ui/include/ui/FloatRect.h | 11 | ||||
-rw-r--r-- | libs/ui/include/ui/Rect.h | 10 | ||||
-rw-r--r-- | libs/ui/include/ui/Region.h | 14 | ||||
-rw-r--r-- | libs/ui/tests/Rect_test.cpp | 29 | ||||
-rw-r--r-- | libs/ui/tests/Region_test.cpp | 12 |
13 files changed, 228 insertions, 0 deletions
diff --git a/libs/math/Android.bp b/libs/math/Android.bp index 3cf9f3f97b..907eb67e9a 100644 --- a/libs/math/Android.bp +++ b/libs/math/Android.bp @@ -39,6 +39,7 @@ cc_library_static { "com.android.media.swcodec", "com.android.neuralnetworks", ], + min_sdk_version: "29", export_include_dirs: ["include"], @@ -49,4 +50,23 @@ cc_library_static { } } +cc_library_headers { + name: "libmath_headers", + export_include_dirs: ["include"], + host_supported: true, + vendor_available: true, + + apex_available: [ + "//apex_available:anyapex", + "//apex_available:platform", + ], + min_sdk_version: "apex_inherit", + + target: { + windows: { + enabled: true, + } + } +} + subdirs = ["tests"] diff --git a/libs/math/include/math/HashCombine.h b/libs/math/include/math/HashCombine.h new file mode 100644 index 0000000000..e91b52ba98 --- /dev/null +++ b/libs/math/include/math/HashCombine.h @@ -0,0 +1,38 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * 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. + */ + +#pragma once + +#include <functional> + +namespace android { +static inline void hashCombineSingleHashed(size_t& combinedHash, size_t hash) { + combinedHash = 31 * combinedHash + hash; +} + +template<typename T> +static inline void hashCombineSingle(size_t& combinedHash, const T& val) { + hashCombineSingleHashed(combinedHash, std::hash<T>{}(val)); +} + +template<typename... Types> +static inline size_t hashCombine(const Types& ... args) { + size_t hash = 0; + ( hashCombineSingle(hash, args), ... ); + return hash; +} + +} // namespace android
\ No newline at end of file diff --git a/libs/math/include/math/TVecHelpers.h b/libs/math/include/math/TVecHelpers.h index 20f852fd9f..0dac662e97 100644 --- a/libs/math/include/math/TVecHelpers.h +++ b/libs/math/include/math/TVecHelpers.h @@ -19,9 +19,11 @@ #include <math.h> #include <stdint.h> +#include <math/HashCombine.h> #include <sys/types.h> #include <cmath> +#include <functional> #include <limits> #include <iostream> @@ -250,6 +252,17 @@ public: } return r; } + + // This isn't strictly a unary operator, but it is a common place shared between both + // matrix and vector classes + size_t hash() const { + VECTOR<T> const& rv(static_cast<VECTOR<T> const&>(*this)); + size_t hashed = 0; + for (size_t i = 0; i < rv.size(); i++) { + android::hashCombineSingle(hashed, rv[i]); + } + return hashed; + } }; /* @@ -606,3 +619,16 @@ public: // ------------------------------------------------------------------------------------- } // namespace details } // namespace android + +namespace std { + template<template<typename T> class VECTOR, typename T> + struct hash<VECTOR<T>> { + static constexpr bool IS_VECTOR = + std::is_base_of<android::details::TVecUnaryOperators<VECTOR, T>, VECTOR<T>>::value; + + typename std::enable_if<IS_VECTOR, size_t>::type + operator()(const VECTOR<T>& v) const { + return v.hash(); + } + }; +} diff --git a/libs/math/include/math/half.h b/libs/math/include/math/half.h index 617a0ab5d2..5ec9bf7b40 100644 --- a/libs/math/include/math/half.h +++ b/libs/math/include/math/half.h @@ -17,6 +17,7 @@ #pragma once #include <stdint.h> +#include <functional> #include <iosfwd> #include <limits> #include <type_traits> @@ -202,6 +203,12 @@ public: inline static constexpr type signaling_NaN() noexcept { return android::half(android::half::binary, 0x7dff); } }; +template<> struct hash<android::half> { + size_t operator()(const android::half& half) { + return std::hash<float>{}(half); + } +}; + } // namespace std #ifdef LIKELY_DEFINED_LOCAL diff --git a/libs/math/tests/Android.bp b/libs/math/tests/Android.bp index 4a7c4dd8a4..14fb72af78 100644 --- a/libs/math/tests/Android.bp +++ b/libs/math/tests/Android.bp @@ -50,3 +50,10 @@ cc_test { static_libs: ["libmath"], cflags: ["-Wall", "-Werror"], } + +cc_test { + name: "hashcombine_test", + srcs: ["hashcombine_test.cpp"], + static_libs: ["libmath"], + cflags: ["-Wall", "-Werror"], +} diff --git a/libs/math/tests/half_test.cpp b/libs/math/tests/half_test.cpp index 604072e557..a514d986e4 100644 --- a/libs/math/tests/half_test.cpp +++ b/libs/math/tests/half_test.cpp @@ -94,4 +94,13 @@ TEST_F(HalfTest, Vec) { EXPECT_EQ(f4.xy, h2); } + +TEST_F(HalfTest, Hash) { + float4 f4a(1,2,3,4); + float4 f4b(2,2,3,4); + half4 h4a(f4a), h4b(f4b); + + EXPECT_NE(std::hash<half4>{}(h4a), std::hash<half4>{}(h4b)); +} + }; // namespace android diff --git a/libs/math/tests/hashcombine_test.cpp b/libs/math/tests/hashcombine_test.cpp new file mode 100644 index 0000000000..96c6e81588 --- /dev/null +++ b/libs/math/tests/hashcombine_test.cpp @@ -0,0 +1,43 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * 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. + */ + +#define LOG_TAG "HashCombineTest" + +#include <math.h> +#include <stdlib.h> + +#include <math/half.h> +#include <math/vec4.h> + +#include <gtest/gtest.h> + +namespace android { + +class HashCombineTest : public testing::Test { +protected: +}; + +TEST_F(HashCombineTest, Basics) { + char a = 40; + int b = 32; + int c = 55; + float d = 42.f; + float d_ = 42.1f; + + EXPECT_NE(hashCombine(a, b, c, d), hashCombine(a, b, c, d_)); +} + +}; // namespace android diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp index ac0ae72f29..de2b9a406b 100644 --- a/libs/ui/Android.bp +++ b/libs/ui/Android.bp @@ -238,9 +238,11 @@ cc_library_headers { }, header_libs: [ "libnativewindow_headers", + "libmath_headers", ], export_header_lib_headers: [ "libnativewindow_headers", + "libmath_headers", ], min_sdk_version: "29", } diff --git a/libs/ui/include/ui/FloatRect.h b/libs/ui/include/ui/FloatRect.h index 5d329ea6a9..4c9c7b7ef1 100644 --- a/libs/ui/include/ui/FloatRect.h +++ b/libs/ui/include/ui/FloatRect.h @@ -16,6 +16,7 @@ #pragma once +#include <math/HashCombine.h> #include <ostream> namespace android { @@ -62,3 +63,13 @@ static inline void PrintTo(const FloatRect& rect, ::std::ostream* os) { } } // namespace android + +namespace std { + +template <> +struct hash<android::FloatRect> { + size_t operator()(const android::FloatRect& rect) const { + return android::hashCombine(rect.left, rect.top, rect.right, rect.bottom); + } +}; +} // namespace std diff --git a/libs/ui/include/ui/Rect.h b/libs/ui/include/ui/Rect.h index 58323e553e..9e24a077ff 100644 --- a/libs/ui/include/ui/Rect.h +++ b/libs/ui/include/ui/Rect.h @@ -24,6 +24,7 @@ #include <utils/Log.h> #include <utils/TypeHelpers.h> +#include <math/HashCombine.h> #include <ui/FloatRect.h> #include <ui/Point.h> #include <ui/Size.h> @@ -234,4 +235,13 @@ ANDROID_BASIC_TYPES_TRAITS(Rect) }; // namespace android +namespace std { +template <> +struct hash<android::Rect> { + size_t operator()(const android::Rect& rect) const { + return android::hashCombine(rect.left, rect.top, rect.right, rect.bottom); + } +}; +} // namespace std + #endif // ANDROID_UI_RECT diff --git a/libs/ui/include/ui/Region.h b/libs/ui/include/ui/Region.h index 6bb7b8d21c..927c334c85 100644 --- a/libs/ui/include/ui/Region.h +++ b/libs/ui/include/ui/Region.h @@ -21,6 +21,7 @@ #include <sys/types.h> #include <ostream> +#include <math/HashCombine.h> #include <ui/Rect.h> #include <utils/Flattenable.h> @@ -234,4 +235,17 @@ static inline void PrintTo(const Region& region, ::std::ostream* os) { // --------------------------------------------------------------------------- }; // namespace android +namespace std { +template <> +struct hash<android::Region> { + size_t operator()(const android::Region& region) const { + size_t hash = 0; + for (const android::Rect& rect : region) { + android::hashCombineSingle(hash, rect); + } + return hash; + } +}; +} // namespace std + #endif // ANDROID_UI_REGION_H diff --git a/libs/ui/tests/Rect_test.cpp b/libs/ui/tests/Rect_test.cpp index 5499a5b507..9cc36bb15b 100644 --- a/libs/ui/tests/Rect_test.cpp +++ b/libs/ui/tests/Rect_test.cpp @@ -259,4 +259,33 @@ TEST(RectTest, toFloatRect) { EXPECT_EQ(FloatRect(10.f, 20.f, 50.f, 60.f), floatRect); } +TEST(RectTest, RectHash) { + const std::vector<Rect> rects = { + Rect(10, 20, 50, 60), Rect(11, 20, 50, 60), Rect(11, 21, 50, 60), + Rect(11, 21, 51, 60), Rect(11, 21, 51, 61), + }; + + for (const auto& a : rects) { + for (const auto& b : rects) { + const bool hashEq = std::hash<Rect>{}(a) == std::hash<Rect>{}(b); + EXPECT_EQ(a == b, hashEq); + } + } +} + +TEST(RectTest, FloatRectHash) { + const std::vector<FloatRect> floatRects = { + Rect(10, 20, 50, 60).toFloatRect(), Rect(11, 20, 50, 60).toFloatRect(), + Rect(11, 21, 50, 60).toFloatRect(), Rect(11, 21, 51, 60).toFloatRect(), + Rect(11, 21, 51, 61).toFloatRect(), + }; + + for (const auto& a : floatRects) { + for (const auto& b : floatRects) { + const bool hashEq = std::hash<FloatRect>{}(a) == std::hash<FloatRect>{}(b); + EXPECT_EQ(a == b, hashEq); + } + } +} + } // namespace android::ui diff --git a/libs/ui/tests/Region_test.cpp b/libs/ui/tests/Region_test.cpp index c6b826d66e..74924bdce8 100644 --- a/libs/ui/tests/Region_test.cpp +++ b/libs/ui/tests/Region_test.cpp @@ -167,5 +167,17 @@ TEST_F(RegionTest, EqualsToSelf) { ASSERT_TRUE(touchableRegion.contains(50, 50)); } +TEST_F(RegionTest, RegionHash) { + Region region1; + region1.addRectUnchecked(10, 20, 30, 40); + region1.addRectUnchecked(40, 30, 20, 10); + + Region region2; + region2.addRectUnchecked(11, 20, 30, 40); + region2.addRectUnchecked(40, 31, 20, 10); + + EXPECT_NE(std::hash<Region>{}(region1), std::hash<Region>{}(region2)); +} + }; // namespace android |