[set] Compute is_subset by comparing pages.
Test subsets one page at a time instead of by codepoints. On my machine this is about 250x faster than the previous implementation.
This commit is contained in:
parent
1dffb55361
commit
2000f47ae5
@ -506,14 +506,44 @@ struct hb_set_t
|
||||
|
||||
bool is_subset (const hb_set_t *larger_set) const
|
||||
{
|
||||
if (get_population () > larger_set->get_population ())
|
||||
return false;
|
||||
if (unlikely(larger_set->is_empty ()))
|
||||
{
|
||||
return is_empty ();
|
||||
}
|
||||
|
||||
/* TODO Optimize to use pages. */
|
||||
hb_codepoint_t c = INVALID;
|
||||
while (next (&c))
|
||||
if (!larger_set->has (c))
|
||||
uint32_t spi = 0;
|
||||
for (uint32_t lpi = 0; spi < page_map.length && lpi < larger_set->page_map.length; lpi++)
|
||||
{
|
||||
uint32_t spm = page_map[spi].major;
|
||||
uint32_t lpm = larger_set->page_map[lpi].major;
|
||||
auto sp = page_at (spi);
|
||||
auto lp = larger_set->page_at (lpi);
|
||||
|
||||
if (spm < lpm && !sp.is_empty ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lpm < spm)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < ARRAY_LENGTH_CONST (sp.v); j++)
|
||||
{
|
||||
if ((~lp.v[j] & sp.v[j]) != 0) { return false; }
|
||||
}
|
||||
|
||||
spi++;
|
||||
}
|
||||
|
||||
while (spi < page_map.length)
|
||||
{
|
||||
if (!page_at (spi++).is_empty ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -215,6 +215,58 @@ static void test_set_union (void)
|
||||
hb_set_destroy (u);
|
||||
}
|
||||
|
||||
static void
|
||||
test_set_subsets (void)
|
||||
{
|
||||
hb_set_t *s = hb_set_create ();
|
||||
hb_set_t *l = hb_set_create ();
|
||||
|
||||
hb_set_add (l, 0x0FFFF);
|
||||
hb_set_add (s, 0x1FFFF);
|
||||
g_assert (!hb_set_is_subset (s, l));
|
||||
hb_set_clear (s);
|
||||
|
||||
hb_set_add (s, 0x0FFF0);
|
||||
g_assert (!hb_set_is_subset (s, l));
|
||||
hb_set_clear (s);
|
||||
|
||||
hb_set_add (s, 0x0AFFF);
|
||||
g_assert (!hb_set_is_subset (s, l));
|
||||
|
||||
hb_set_clear (s);
|
||||
g_assert (hb_set_is_subset (s, l));
|
||||
|
||||
hb_set_clear (l);
|
||||
g_assert (hb_set_is_subset (s, l));
|
||||
|
||||
hb_set_add (s, 0x1FFFF);
|
||||
g_assert (!hb_set_is_subset (s, l));
|
||||
hb_set_clear (s);
|
||||
|
||||
hb_set_add (s, 0xFF);
|
||||
hb_set_add (s, 0x1FFFF);
|
||||
hb_set_add (s, 0x2FFFF);
|
||||
|
||||
hb_set_add (l, 0xFF);
|
||||
hb_set_add (l, 0x1FFFF);
|
||||
hb_set_add (l, 0x2FFFF);
|
||||
|
||||
g_assert (hb_set_is_subset (s, l));
|
||||
hb_set_del (l, 0xFF);
|
||||
g_assert (!hb_set_is_subset (s, l));
|
||||
hb_set_add (l, 0xFF);
|
||||
|
||||
hb_set_del (l, 0x2FFFF);
|
||||
g_assert (!hb_set_is_subset (s, l));
|
||||
hb_set_add (l, 0x2FFFF);
|
||||
|
||||
hb_set_del (l, 0x1FFFF);
|
||||
g_assert (!hb_set_is_subset (s, l));
|
||||
|
||||
hb_set_destroy (s);
|
||||
hb_set_destroy (l);
|
||||
}
|
||||
|
||||
static void
|
||||
test_set_algebra (void)
|
||||
{
|
||||
@ -528,6 +580,7 @@ main (int argc, char **argv)
|
||||
hb_test_init (&argc, &argv);
|
||||
|
||||
hb_test_add (test_set_basic);
|
||||
hb_test_add (test_set_subsets);
|
||||
hb_test_add (test_set_algebra);
|
||||
hb_test_add (test_set_iter);
|
||||
hb_test_add (test_set_empty);
|
||||
|
Loading…
Reference in New Issue
Block a user