[subset] Change compute_distances() to use a priority queue.
This commit is contained in:
parent
59ac0a0d0a
commit
5d3511e5b1
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
#include "hb-open-type.hh"
|
#include "hb-open-type.hh"
|
||||||
#include "hb-map.hh"
|
#include "hb-map.hh"
|
||||||
|
#include "hb-priority-queue.hh"
|
||||||
#include "hb-serialize.hh"
|
#include "hb-serialize.hh"
|
||||||
#include "hb-vector.hh"
|
#include "hb-vector.hh"
|
||||||
|
|
||||||
|
@ -267,25 +268,39 @@ struct graph_t
|
||||||
{
|
{
|
||||||
// Uses Dijkstra's algorithm to find all of the shortest distances.
|
// Uses Dijkstra's algorithm to find all of the shortest distances.
|
||||||
// https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
|
// https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
|
||||||
|
//
|
||||||
|
// Implementation Note:
|
||||||
|
// Since our priority queue doesn't support fast priority decreases
|
||||||
|
// we instead just add new entries into the queue when a priority changes.
|
||||||
|
// Redundant ones are filtered out later on by the visited set.
|
||||||
|
// According to https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf
|
||||||
|
// for practical performance this is faster then using a more advanced queue
|
||||||
|
// (such as a fibonaacci queue) with a fast decrease priority.
|
||||||
|
hb_priority_queue_t queue;
|
||||||
distance_to->resize (0);
|
distance_to->resize (0);
|
||||||
distance_to->resize (objects_.length);
|
distance_to->resize (objects_.length);
|
||||||
for (unsigned i = 0; i < objects_.length; i++)
|
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);
|
|
||||||
|
|
||||||
while (!unvisited.is_empty ())
|
|
||||||
{
|
{
|
||||||
unsigned next_idx = closest_object (unvisited, *distance_to);
|
if (i == objects_.length - 1)
|
||||||
|
(*distance_to)[i] = 0;
|
||||||
|
else
|
||||||
|
(*distance_to)[i] = hb_int_max (int64_t);
|
||||||
|
queue.insert (i, (*distance_to)[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_set_t visited;
|
||||||
|
|
||||||
|
while (!queue.is_empty ())
|
||||||
|
{
|
||||||
|
unsigned next_idx = queue.extract_minimum ().first;
|
||||||
|
if (visited.has (next_idx)) continue;
|
||||||
const auto& next = objects_[next_idx];
|
const auto& next = objects_[next_idx];
|
||||||
int next_distance = (*distance_to)[next_idx];
|
int64_t next_distance = (*distance_to)[next_idx];
|
||||||
unvisited.del (next_idx);
|
visited.add (next_idx);
|
||||||
|
|
||||||
for (const auto& link : next.links)
|
for (const auto& link : next.links)
|
||||||
{
|
{
|
||||||
if (!unvisited.has (link.objidx)) continue;
|
if (visited.has (link.objidx)) continue;
|
||||||
|
|
||||||
const auto& child = objects_[link.objidx];
|
const auto& child = objects_[link.objidx];
|
||||||
int64_t child_weight = child.tail - child.head +
|
int64_t child_weight = child.tail - child.head +
|
||||||
|
@ -293,11 +308,14 @@ struct graph_t
|
||||||
int64_t child_distance = next_distance + child_weight;
|
int64_t child_distance = next_distance + child_weight;
|
||||||
|
|
||||||
if (child_distance < (*distance_to)[link.objidx])
|
if (child_distance < (*distance_to)[link.objidx])
|
||||||
|
{
|
||||||
(*distance_to)[link.objidx] = child_distance;
|
(*distance_to)[link.objidx] = child_distance;
|
||||||
|
queue.insert (link.objidx, child_distance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO(garretrieger): Handle this. If anything is left, part of the graph is disconnected.
|
// TODO(garretrieger): Handle this. If anything is left, part of the graph is disconnected.
|
||||||
assert (unvisited.is_empty ());
|
assert (queue.is_empty ());
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t compute_offset (
|
int64_t compute_offset (
|
||||||
|
|
|
@ -477,6 +477,7 @@ if get_option('tests').enabled()
|
||||||
compiled_tests = {
|
compiled_tests = {
|
||||||
'test-algs': ['test-algs.cc', 'hb-static.cc'],
|
'test-algs': ['test-algs.cc', 'hb-static.cc'],
|
||||||
'test-array': ['test-array.cc'],
|
'test-array': ['test-array.cc'],
|
||||||
|
'test-repacker': ['test-repacker.cc', 'hb-static.cc'],
|
||||||
'test-iter': ['test-iter.cc', 'hb-static.cc'],
|
'test-iter': ['test-iter.cc', 'hb-static.cc'],
|
||||||
'test-meta': ['test-meta.cc', 'hb-static.cc'],
|
'test-meta': ['test-meta.cc', 'hb-static.cc'],
|
||||||
'test-number': ['test-number.cc', 'hb-number.cc'],
|
'test-number': ['test-number.cc', 'hb-number.cc'],
|
||||||
|
|
Loading…
Reference in New Issue