Skip to content

Commit ee4ded2

Browse files
committed
feat: myers diff
1 parent 752b407 commit ee4ded2

10 files changed

Lines changed: 2017 additions & 0 deletions

File tree

diff/myers/diag_wbtest.mbt

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// Copyright 2026 International Digital Economy Academy
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
///|
16+
fn run_diag_range(
17+
old : Array[Int],
18+
new : Array[Int],
19+
lhs_offset : Int,
20+
lhs_limit : Int,
21+
rhs_offset : Int,
22+
rhs_limit : Int,
23+
too_expensive : Int,
24+
find_minimal : Bool,
25+
) -> Partition {
26+
let forward_search_diagonal = FixedArray::make(
27+
old.length() + new.length() + 3,
28+
0,
29+
)
30+
let backward_search_diagonal = FixedArray::make(
31+
old.length() + new.length() + 3,
32+
0,
33+
)
34+
let diagonal_shift = new.length() + 1
35+
diag(
36+
forward_search_diagonal~,
37+
backward_search_diagonal~,
38+
diagonal_shift~,
39+
lhs_get=fn(i) { old[i] },
40+
rhs_get=fn(i) { new[i] },
41+
lhs_offset~,
42+
lhs_limit~,
43+
rhs_offset~,
44+
rhs_limit~,
45+
too_expensive~,
46+
find_minimal~,
47+
)
48+
}
49+
50+
///|
51+
fn run_diag(
52+
old : Array[Int],
53+
new : Array[Int],
54+
too_expensive : Int,
55+
find_minimal : Bool,
56+
) -> Partition {
57+
run_diag_range(
58+
old,
59+
new,
60+
0,
61+
old.length(),
62+
0,
63+
new.length(),
64+
too_expensive,
65+
find_minimal,
66+
)
67+
}
68+
69+
///|
70+
fn patterned_array(length : Int, shift : Int, modulo : Int) -> Array[Int] {
71+
let result = Array::make(length, 0)
72+
for i = 0; i < length; i = i + 1 {
73+
result[i] = (i + shift) % modulo
74+
}
75+
result
76+
}
77+
78+
///|
79+
test "diag reaches lower diagonal boundary when old is longer" {
80+
let partition = run_diag([1, 2, 3, 4, 5], [10], 1024, true)
81+
assert_true(partition.lo_minimal)
82+
assert_true(partition.hi_minimal)
83+
assert_true(partition.lhs_midpoint >= 0 && partition.lhs_midpoint <= 5)
84+
assert_true(partition.rhs_midpoint >= 0 && partition.rhs_midpoint <= 1)
85+
}
86+
87+
///|
88+
test "diag reaches upper diagonal boundary when new is longer" {
89+
let partition = run_diag([1], [10, 11, 12, 13, 14], 1024, true)
90+
assert_true(partition.lo_minimal)
91+
assert_true(partition.hi_minimal)
92+
assert_true(partition.lhs_midpoint >= 0 && partition.lhs_midpoint <= 1)
93+
assert_true(partition.rhs_midpoint >= 0 && partition.rhs_midpoint <= 5)
94+
}
95+
96+
///|
97+
test "diag odd parity can return from forward search" {
98+
let partition = run_diag([1, 2], [9], 1024, true)
99+
assert_true(partition.lo_minimal)
100+
assert_true(partition.hi_minimal)
101+
}
102+
103+
///|
104+
test "diag heuristic path can choose either side" {
105+
let saw_forward = @ref.Ref::new(false)
106+
let saw_backward = @ref.Ref::new(false)
107+
for n = 3; n <= 8; n = n + 1 {
108+
for m = 3; m <= 8; m = m + 1 {
109+
for old_shift = 0; old_shift < 5; old_shift = old_shift + 1 {
110+
for new_shift = 0; new_shift < 5; new_shift = new_shift + 1 {
111+
let old = patterned_array(n, old_shift, 5)
112+
let new = patterned_array(m, new_shift, 5)
113+
for xoff = 0; xoff <= 1; xoff = xoff + 1 {
114+
for yoff = 0; yoff <= 1; yoff = yoff + 1 {
115+
if xoff < n && yoff < m {
116+
let partition = run_diag_range(
117+
old, new, xoff, n, yoff, m, 0, false,
118+
)
119+
if partition.lo_minimal && not(partition.hi_minimal) {
120+
saw_forward.val = true
121+
}
122+
if not(partition.lo_minimal) && partition.hi_minimal {
123+
saw_backward.val = true
124+
}
125+
}
126+
}
127+
}
128+
}
129+
}
130+
}
131+
}
132+
assert_true(saw_forward.val)
133+
assert_true(saw_backward.val)
134+
}

0 commit comments

Comments
 (0)