[subset] re-write compute distances to use an array lookup for the distance map.
This commit is contained in:
parent
5c4e0ffd97
commit
4c8dd41ed9
|
@ -43,7 +43,7 @@ struct hb_priority_queue_t
|
|||
~hb_priority_queue_t () { fini (); }
|
||||
|
||||
private:
|
||||
typedef hb_pair_t<unsigned, unsigned> item_t;
|
||||
typedef hb_pair_t<unsigned, int64_t> item_t;
|
||||
hb_vector_t<item_t> heap;
|
||||
|
||||
public:
|
||||
|
@ -55,7 +55,7 @@ struct hb_priority_queue_t
|
|||
|
||||
bool in_error () const { return heap.in_error (); }
|
||||
|
||||
void insert (unsigned value, unsigned priority)
|
||||
void insert (unsigned value, int64_t priority)
|
||||
{
|
||||
heap.push (item_t (value, priority));
|
||||
bubble_up (heap.length - 1);
|
||||
|
|
|
@ -161,7 +161,7 @@ struct graph_t
|
|||
return;
|
||||
}
|
||||
|
||||
hb_hashmap_t<unsigned, int64_t, -1, hb_int_max(int64_t)> distance_to;
|
||||
hb_vector_t<int64_t> distance_to;
|
||||
compute_distances (&distance_to);
|
||||
|
||||
hb_set_t queue;
|
||||
|
@ -242,15 +242,16 @@ struct graph_t
|
|||
private:
|
||||
|
||||
unsigned closest_object (const hb_set_t& queue,
|
||||
const hb_hashmap_t<unsigned, int64_t, -1, hb_int_max(int64_t)>& distance_to)
|
||||
const hb_vector_t<int64_t> distance_to)
|
||||
{
|
||||
// TODO(garretrieger): use a priority queue.
|
||||
int64_t closest_distance = hb_int_max (int64_t);
|
||||
unsigned closest_index = -1;
|
||||
for (unsigned i : queue)
|
||||
{
|
||||
if (distance_to.get (i) < closest_distance)
|
||||
if (distance_to[i] < closest_distance)
|
||||
{
|
||||
closest_distance = distance_to.get (i);
|
||||
closest_distance = distance_to[i];
|
||||
closest_index = i;
|
||||
}
|
||||
}
|
||||
|
@ -262,51 +263,41 @@ struct graph_t
|
|||
* Finds the distance too each object in the graph
|
||||
* from the initial node.
|
||||
*/
|
||||
void compute_distances (hb_hashmap_t<unsigned, int64_t, -1, hb_int_max(int64_t)>* distance_to)
|
||||
void compute_distances (hb_vector_t<int64_t>* distance_to)
|
||||
{
|
||||
// Uses Dijkstra's algorithm to find all of the shortest distances.
|
||||
// https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
|
||||
distance_to->clear ();
|
||||
distance_to->resize (0);
|
||||
distance_to->resize (objects_.length);
|
||||
for (unsigned i = 0; i < objects_.length; i++)
|
||||
(*distance_to)[i] = hb_int_max (int64_t);
|
||||
(*distance_to)[objects_.length - 1] = 0;
|
||||
|
||||
hb_set_t unvisited;
|
||||
unvisited.add_range (0, objects_.length - 1);
|
||||
|
||||
unsigned current_idx = objects_.length - 1;
|
||||
distance_to->set (current_idx, 0);
|
||||
|
||||
while (unvisited.get_population ())
|
||||
while (!unvisited.is_empty ())
|
||||
{
|
||||
const auto& current = objects_[current_idx];
|
||||
int current_distance = (*distance_to)[current_idx];
|
||||
unsigned next_idx = closest_object (unvisited, *distance_to);
|
||||
const auto& next = objects_[next_idx];
|
||||
int next_distance = (*distance_to)[next_idx];
|
||||
unvisited.del (next_idx);
|
||||
|
||||
for (const auto& link : current.links)
|
||||
for (const auto& link : next.links)
|
||||
{
|
||||
if (!unvisited.has (link.objidx)) continue;
|
||||
|
||||
const auto& child = objects_[link.objidx];
|
||||
int64_t child_weight = child.tail - child.head +
|
||||
(!link.is_wide ? (1 << 16) : ((int64_t) 1 << 32));
|
||||
int64_t child_distance = current_distance + child_weight;
|
||||
int64_t child_distance = next_distance + child_weight;
|
||||
|
||||
if (child_distance < distance_to->get (link.objidx))
|
||||
distance_to->set (link.objidx, child_distance);
|
||||
if (child_distance < (*distance_to)[link.objidx])
|
||||
(*distance_to)[link.objidx] = child_distance;
|
||||
}
|
||||
|
||||
unvisited.del (current_idx);
|
||||
|
||||
// TODO(garretrieger): change this to use a priority queue.
|
||||
int64_t smallest_distance = hb_int_max(int64_t);
|
||||
for (hb_codepoint_t idx : unvisited)
|
||||
{
|
||||
if (distance_to->get (idx) < smallest_distance)
|
||||
{
|
||||
smallest_distance = distance_to->get (idx);
|
||||
current_idx = idx;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(garretrieger): this will trigger if graph is disconnected. Handle this.
|
||||
assert (!unvisited.get_population () || smallest_distance != hb_int_max (int64_t));
|
||||
}
|
||||
// TODO(garretrieger): Handle this. If anything is left, part of the graph is disconnected.
|
||||
assert (unvisited.is_empty ());
|
||||
}
|
||||
|
||||
int64_t compute_offset (
|
||||
|
|
|
@ -271,6 +271,8 @@ static void test_will_overflow_2 ()
|
|||
assert (graph.will_overflow ());
|
||||
}
|
||||
|
||||
// TODO(garretrieger): add a test(s) using a real font.
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue