64 bool operator<(
const Point& other)
const {
65 return x < other.x && y < other.y;
70 struct EditGraphArea {
75 int size()
const {
return width() + height(); }
76 int delta()
const {
return width() - height(); }
85 void Add(
const Point& p) {
points.push_back(p); }
86 void Add(
const Path& p) {
87 points.insert(
points.end(), p.points.begin(), p.points.end());
109 class FurthestReaching {
111 explicit FurthestReaching(std::vector<int>::size_type size) :
v_(size) {}
113 int& operator[](
int index) {
114 const size_t idx = index >= 0 ?
index :
v_.size() +
index;
118 const int& operator[](
int index)
const {
119 const size_t idx = index >= 0 ?
index :
v_.size() +
index;
147 MyersDiffer(Comparator::Input* input, Comparator::Output* output)
150 fr_forward_(input->GetLength1() + input->GetLength2() + 1),
151 fr_reverse_(input->GetLength1() + input->GetLength2() + 1) {
157 std::optional<Path> FindEditPath() {
158 return FindEditPath(Point{0, 0},
163 std::optional<Path> FindEditPath(Point from, Point to) {
166 std::optional<Snake> snake = FindMiddleSnake(from, to);
168 if (!snake)
return std::nullopt;
171 std::optional<Path> head = FindEditPath(from, snake->from);
172 std::optional<Path> tail = FindEditPath(snake->to, to);
201 std::optional<Snake> FindMiddleSnake(Point from, Point to) {
202 EditGraphArea area{
from, to};
203 if (area.size() == 0)
return std::nullopt;
211 for (
int d = 0; d <= std::ceil(area.size() / 2.0f); ++d) {
212 if (
auto snake = ShortestEditForward(area, d))
return snake;
213 if (
auto snake = ShortestEditReverse(area, d))
return snake;
226 std::optional<Snake> ShortestEditForward(
const EditGraphArea& area,
int d) {
233 for (
int k = -d; k <= d; k += 2) {
248 to.y = area.top_left.y + (to.x - area.top_left.x) - k;
249 from.y = (d == 0 || from.x != to.x) ? to.y : to.
y - 1;
261 const bool odd = area.delta() % 2 != 0;
262 const int l = k - area.delta();
264 return Snake{
from, to};
274 std::optional<Snake> ShortestEditReverse(
const EditGraphArea& area,
int d) {
281 for (
int l = d; l >= -d; l -= 2) {
296 const int k = l + area.delta();
297 to.y = area.top_left.y + (to.x - area.top_left.x) - k;
298 from.y = (d == 0 || from.x != to.x) ? to.y : to.
y + 1;
301 while (area.top_left < to &&
input_->Equals(to.x - 1, to.y - 1)) {
310 const bool even = area.delta() % 2 == 0;
311 if (even && k >= -d && k <= d && to.x <=
fr_forward_[k]) {
313 return Snake{
to, from};
332 explicit ResultWriter(Comparator::Output* output) :
output_(output) {}
334 void RecordNoModification(
const Point& from) {
335 if (!change_is_ongoing_)
return;
338 CHECK(change_start_);
344 void RecordInsertionOrDeletion(
const Point& from) {
345 if (change_is_ongoing_)
return;
360 void WriteResult(
const Path& path) {
363 for (
size_t i = 1;
i < path.points.size(); ++
i) {
364 Point
p1 = path.points[
i - 1];
365 Point
p2 = path.points[
i];
367 p1 = WalkDiagonal(writer,
p1,
p2);
368 const int cmp = (
p2.x -
p1.x) - (
p2.y -
p1.y);
370 writer.RecordInsertionOrDeletion(
p1);
372 }
else if (cmp == 1) {
373 writer.RecordInsertionOrDeletion(
p1);
377 p1 = WalkDiagonal(writer,
p1,
p2);
382 writer.RecordNoModification(path.points.back());
385 Point WalkDiagonal(ResultWriter& writer, Point
p1, Point
p2) {
387 writer.RecordNoModification(
p1);
395 static void MyersDiff(Comparator::Input* input, Comparator::Output* output) {
396 MyersDiffer differ(input, output);
397 auto result = differ.FindEditPath();
400 differ.WriteResult(*
result);
408 MyersDiffer::MyersDiff(input, result_writer);
static void CalculateDifference(Input *input, Output *result_writer)
ZoneVector< RpoNumber > & result
FurthestReaching fr_forward_
std::optional< Point > change_start_
std::vector< Point > points
Comparator::Output * output_
FurthestReaching fr_reverse_
void Add(RWDigits Z, Digits X, Digits Y)
V8_INLINE constexpr bool operator<(Builtin a, Builtin b)
#define DCHECK(condition)