MCPcopy Create free account
hub / github.com/apache/arrow / QuadraticSpaceMyersDiff

Class QuadraticSpaceMyersDiff

cpp/src/arrow/array/diff.cc:377–560  ·  view source on GitHub ↗

A generic sequence difference algorithm, based on E. W. Myers, "An O(ND) difference algorithm and its variations," Algorithmica, vol. 1, no. 1-4, pp. 251–266, 1986. To summarize, an edit script is computed by maintaining the furthest set of EditPoints which are reachable in a given number of edits D. This is used to compute the furthest set reachable with D+1 edits, and the process continues ind

Source from the content-addressed store, hash-verified

375/// since most of the elements are shared between base and target and are represented
376/// implicitly.
377class QuadraticSpaceMyersDiff {
378 public:
379 QuadraticSpaceMyersDiff(const Array& base, const Array& target, MemoryPool* pool)
380 : base_(base), target_(target), pool_(pool) {}
381
382 private:
383 // increment the position within base (the element pointed to was deleted)
384 // then extend maximally
385 EditPoint DeleteOne(EditPoint p) const {
386 if (p.base != base_end_) {
387 ++p.base;
388 }
389 return ExtendFrom(p);
390 }
391
392 // increment the position within target (the element pointed to was inserted)
393 // then extend maximally
394 EditPoint InsertOne(EditPoint p) const {
395 if (p.target != target_end_) {
396 ++p.target;
397 }
398 return ExtendFrom(p);
399 }
400
401 // increment the position within base and target (the elements skipped in this way were
402 // present in both sequences)
403 EditPoint ExtendFrom(EditPoint p) const {
404 const int64_t run_length_of_equals =
405 _comparator->RunLengthOfEqualsFrom(p.base, base_end_, p.target, target_end_);
406 p.base += run_length_of_equals;
407 p.target += run_length_of_equals;
408 return p;
409 }
410
411 // beginning of a range for storing per-edit state in endpoint_base_ and insert_
412 int64_t StorageOffset(int64_t edit_count) const {
413 return edit_count * (edit_count + 1) / 2;
414 }
415
416 // given edit_count and index, augment endpoint_base_[index] with the corresponding
417 // position in target (which is only implicitly represented in edit_count, index)
418 EditPoint GetEditPoint(int64_t edit_count, int64_t index) const {
419 DCHECK_GE(index, StorageOffset(edit_count));
420 DCHECK_LT(index, StorageOffset(edit_count + 1));
421 auto insertions_minus_deletions =
422 2 * (index - StorageOffset(edit_count)) - edit_count;
423 auto maximal_base = endpoint_base_[index];
424 auto maximal_target = std::min(
425 target_begin_ + ((maximal_base - base_begin_) + insertions_minus_deletions),
426 target_end_);
427 return {maximal_base, maximal_target};
428 }
429
430 void Next() {
431 ++edit_count_;
432 // base_begin_ is used as a dummy value here since Iterator may not be default
433 // constructible. The newly allocated range is completely overwritten below.
434 endpoint_base_.resize(StorageOffset(edit_count_ + 1), base_begin_);

Callers 1

DiffFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected