[set] Speed up next_range()

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

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

@ -76,7 +76,7 @@ struct hb_vector_size_t
hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
{ return process (hb_bitwise_xor, o); }
hb_vector_size_t operator ~ () const
{ return process (hb_bitwise_neg); }
{ return process (hb_bitwise_not); }
hb_array_t<const elt_t> iter () const
{ return hb_array (v); }
@ -106,6 +106,15 @@ struct hb_bit_page_t
| 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
{
return hb_bytes_t ((const char *) &v, sizeof (v)).hash ();
@ -251,7 +260,7 @@ struct hb_bit_page_t
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;
if (!m)
@ -262,12 +271,27 @@ struct hb_bit_page_t
unsigned int i = m / ELT_BITS;
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])
if (*p)
if (bit)
{
*codepoint = i * ELT_BITS + elt_get_min (*p);
return true;
if (*p)
{
*codepoint = i * ELT_BITS + elt_get_min (*p);
return true;
}
}
else
{
if (~*p)
{
*codepoint = i * ELT_BITS + elt_get_min (~*p);
return true;
}
}
*codepoint = INVALID;

@ -699,19 +699,59 @@ struct hb_bit_set_t
}
bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
{
hb_codepoint_t i;
i = *last;
if (!next (&i))
*first = *last;
if (!next (first))
{
*last = *first = INVALID;
return false;
}
/* TODO Speed up. */
*last = *first = i;
while (next (&i) && i == *last + 1)
(*last)++;
const auto* page_map_array = page_map.arrayZ;
unsigned int major = get_major (*first);
unsigned int i = last_page_lookup;
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;
}

Loading…
Cancel
Save