[set] Cache hash value

This commit is contained in:
Behdad Esfahbod 2022-05-19 14:02:48 -06:00
parent 844ac328e4
commit 44952bcc25
1 changed files with 23 additions and 3 deletions

View File

@ -47,6 +47,7 @@ struct hb_bit_set_t
if (likely (!a.successful || !b.successful)) if (likely (!a.successful || !b.successful))
return; return;
hb_swap (a.population, b.population); hb_swap (a.population, b.population);
hb_swap (a.hash_, b.hash_);
hb_swap (a.last_page_lookup, b.last_page_lookup); hb_swap (a.last_page_lookup, b.last_page_lookup);
hb_swap (a.page_map, b.page_map); hb_swap (a.page_map, b.page_map);
hb_swap (a.pages, b.pages); hb_swap (a.pages, b.pages);
@ -56,6 +57,7 @@ struct hb_bit_set_t
{ {
successful = true; successful = true;
population = 0; population = 0;
hash_ = 0;
last_page_lookup = 0; last_page_lookup = 0;
page_map.init (); page_map.init ();
pages.init (); pages.init ();
@ -78,6 +80,7 @@ struct hb_bit_set_t
bool successful = true; /* Allocations successful */ bool successful = true; /* Allocations successful */
mutable unsigned int population = 0; mutable unsigned int population = 0;
mutable unsigned int hash_ = 0;
mutable unsigned int last_page_lookup = 0; mutable unsigned int last_page_lookup = 0;
hb_sorted_vector_t<page_map_t> page_map; hb_sorted_vector_t<page_map_t> page_map;
hb_vector_t<page_t> pages; hb_vector_t<page_t> pages;
@ -114,7 +117,10 @@ struct hb_bit_set_t
{ {
resize (0); resize (0);
if (likely (successful)) if (likely (successful))
{
population = 0; population = 0;
hash_ = 0;
}
} }
bool is_empty () const bool is_empty () const
{ {
@ -126,16 +132,26 @@ struct hb_bit_set_t
} }
explicit operator bool () const { return !is_empty (); } explicit operator bool () const { return !is_empty (); }
bool has_hash () const { return hash_ != UINT_MAX; }
unsigned hash () const unsigned hash () const
{ {
if (has_hash ()) return hash_;
unsigned h = 0; unsigned h = 0;
for (auto &map : page_map) for (auto &map : page_map)
h = h * 31 + hb_hash (map.major) + hb_hash (pages[map.index]); h = h * 31 + hb_hash (map.major) + hb_hash (pages[map.index]);
hash_ = h;
return h; return h;
} }
private: private:
void dirty () { population = UINT_MAX; } void dirty ()
{
population = UINT_MAX;
hash_ = UINT_MAX;
}
public: public:
void add (hb_codepoint_t g) void add (hb_codepoint_t g)
@ -355,6 +371,7 @@ struct hb_bit_set_t
if (unlikely (!resize (count))) if (unlikely (!resize (count)))
return; return;
population = other.population; population = other.population;
hash_ = other.hash_;
/* TODO switch to vector operator =. */ /* TODO switch to vector operator =. */
hb_memcpy ((void *) pages, (const void *) other.pages, count * pages.item_size); hb_memcpy ((void *) pages, (const void *) other.pages, count * pages.item_size);
@ -364,7 +381,10 @@ struct hb_bit_set_t
bool is_equal (const hb_bit_set_t &other) const bool is_equal (const hb_bit_set_t &other) const
{ {
if (has_population () && other.has_population () && if (has_population () && other.has_population () &&
get_population () != other.get_population ()) population != other.population)
return false;
if (has_hash () && other.has_hash () &&
hash_ != other.hash_)
return false; return false;
unsigned int na = pages.length; unsigned int na = pages.length;
@ -392,7 +412,7 @@ struct hb_bit_set_t
bool is_subset (const hb_bit_set_t &larger_set) const bool is_subset (const hb_bit_set_t &larger_set) const
{ {
if (has_population () && larger_set.has_population () && if (has_population () && larger_set.has_population () &&
get_population () != larger_set.get_population ()) population != larger_set.population)
return false; return false;
uint32_t spi = 0; uint32_t spi = 0;