[set] Speed up next_range()

next_range2
Behdad Esfahbod 1 year ago
parent 6a3ca37373
commit 2d7de7ce50
  1. 2
      src/hb-algs.hh
  2. 30
      src/hb-bit-page.hh
  3. 56
      src/hb-bit-set.hh

@ -1417,7 +1417,7 @@ struct
template <typename T> constexpr auto template <typename T> constexpr auto
operator () (const T &a) const HB_AUTO_RETURN (~a) operator () (const T &a) const HB_AUTO_RETURN (~a)
} }
HB_FUNCOBJ (hb_bitwise_neg); HB_FUNCOBJ (hb_bitwise_not);
struct struct
{ HB_PARTIALIZE(2); { HB_PARTIALIZE(2);

@ -76,7 +76,7 @@ struct hb_vector_size_t
hb_vector_size_t operator ^ (const hb_vector_size_t &o) const hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
{ return process (hb_bitwise_xor, o); } { return process (hb_bitwise_xor, o); }
hb_vector_size_t operator ~ () const hb_vector_size_t operator ~ () const
{ return process (hb_bitwise_neg); } { return process (hb_bitwise_not); }
hb_array_t<const elt_t> iter () const hb_array_t<const elt_t> iter () const
{ return hb_array (v); } { return hb_array (v); }
@ -106,6 +106,15 @@ struct hb_bit_page_t
| hb_none | hb_none
; ;
} }
bool is_full () const
{
if (has_population ()) return population == PAGE_BITS;
return
+ hb_iter (v)
| hb_filter (hb_bitwise_not)
| hb_none
;
}
uint32_t hash () const uint32_t hash () const
{ {
return hb_bytes_t ((const char *) &v, sizeof (v)).hash (); return hb_bytes_t ((const char *) &v, sizeof (v)).hash ();
@ -251,7 +260,7 @@ struct hb_bit_page_t
return population; return population;
} }
bool next (hb_codepoint_t *codepoint) const bool next (hb_codepoint_t *codepoint, unsigned bit = 1) const
{ {
unsigned int m = (*codepoint + 1) & MASK; unsigned int m = (*codepoint + 1) & MASK;
if (!m) if (!m)
@ -262,13 +271,28 @@ struct hb_bit_page_t
unsigned int i = m / ELT_BITS; unsigned int i = m / ELT_BITS;
unsigned int j = m & ELT_MASK; unsigned int j = m & ELT_MASK;
const elt_t vv = v[i] & ~((elt_t (1) << j) - 1); elt_t vv;
if (bit)
vv = v[i] & ~((elt_t (1) << j) - 1);
else
vv = v[i] | ((elt_t (1) << j) - 1);
for (const elt_t *p = &vv; i < len (); p = &v[++i]) for (const elt_t *p = &vv; i < len (); p = &v[++i])
if (bit)
{
if (*p) if (*p)
{ {
*codepoint = i * ELT_BITS + elt_get_min (*p); *codepoint = i * ELT_BITS + elt_get_min (*p);
return true; return true;
} }
}
else
{
if (~*p)
{
*codepoint = i * ELT_BITS + elt_get_min (~*p);
return true;
}
}
*codepoint = INVALID; *codepoint = INVALID;
return false; return false;

@ -699,19 +699,59 @@ struct hb_bit_set_t
} }
bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
{ {
hb_codepoint_t i; *first = *last;
if (!next (first))
i = *last;
if (!next (&i))
{ {
*last = *first = INVALID; *last = *first = INVALID;
return false; return false;
} }
/* TODO Speed up. */ const auto* page_map_array = page_map.arrayZ;
*last = *first = i; unsigned int major = get_major (*first);
while (next (&i) && i == *last + 1) unsigned int i = last_page_lookup;
(*last)++; if (unlikely (i >= page_map.length || page_map_array[i].major != major))
{
page_map.bfind (major, &i, HB_NOT_FOUND_STORE_CLOSEST);
assert (i < page_map.length);
}
*last = *first;
if (pages.arrayZ[page_map_array[i].index].next (last, 0))
{
*last += major * page_t::PAGE_BITS - 1;
return true;
}
else
*last = (major + 1) * page_t::PAGE_BITS - 1;
for (i++, major++; i < page_map.length; i++, major++)
{
const page_map_t &current = page_map_array[i];
if (current.major != major)
break;
auto &page = pages.arrayZ[current.index];
if (page.is_full ())
{
*last += page_t::PAGE_BITS;
continue;
}
if (page.get (0))
{
hb_codepoint_t x = 0;
if (page.next (&x, 0))
{
*last += x;
break;
}
else
*last += page_t::PAGE_BITS;
}
else
break;
}
return true; return true;
} }

Loading…
Cancel
Save