|
2 | 2 | -- | A list diff. |
3 | 3 | module Data.TreeDiff.List (diffBy, Edit (..)) where |
4 | 4 |
|
5 | | -import Control.DeepSeq (NFData (..)) |
6 | | -import Data.List.Compat (sortOn) |
| 5 | +import Control.DeepSeq (NFData (..)) |
7 | 6 |
|
8 | | -import qualified Data.Vector as V |
| 7 | +import qualified Data.Primitive as P |
9 | 8 |
|
10 | 9 | -- | List edit operations |
11 | 10 | -- |
@@ -39,43 +38,55 @@ instance NFData a => NFData (Edit a) where |
39 | 38 | -- of more obviously correct implementation. |
40 | 39 | -- |
41 | 40 | diffBy :: forall a. (a -> a -> Bool) -> [a] -> [a] -> [Edit a] |
42 | | -diffBy eq xs' ys' = reverse (snd (lcs xn yn)) |
| 41 | +diffBy eq xs' ys' = reverse (getCell (lcs xn yn)) |
43 | 42 | where |
44 | | - xn = V.length xs |
45 | | - yn = V.length ys |
| 43 | + xn = length xs' |
| 44 | + yn = length ys' |
46 | 45 |
|
47 | | - xs = V.fromList xs' |
48 | | - ys = V.fromList ys' |
| 46 | + xs = P.arrayFromListN xn xs' |
| 47 | + ys = P.arrayFromListN yn ys' |
49 | 48 |
|
50 | | - memo :: V.Vector (Int, [Edit a]) |
51 | | - memo = V.fromList |
| 49 | + memo :: P.Array (Cell [Edit a]) |
| 50 | + memo = P.arrayFromListN ((xn + 1) * (yn + 1)) |
52 | 51 | [ impl xi yi |
53 | 52 | | xi <- [0 .. xn] |
54 | 53 | , yi <- [0 .. yn] |
55 | 54 | ] |
56 | 55 |
|
57 | | - lcs :: Int -> Int -> (Int, [Edit a]) |
58 | | - lcs xi yi = memo V.! (yi + xi * (yn + 1)) |
| 56 | + lcs :: Int -> Int -> Cell [Edit a] |
| 57 | + lcs xi yi = P.indexArray memo (yi + xi * (yn + 1)) |
59 | 58 |
|
60 | | - impl :: Int -> Int -> (Int, [Edit a]) |
61 | | - impl 0 0 = (0, []) |
62 | | - impl 0 m = case lcs 0 (m-1) of |
63 | | - (w, edit) -> (w + 1, Ins (ys V.! (m - 1)) : edit) |
64 | | - impl n 0 = case lcs (n -1) 0 of |
65 | | - (w, edit) -> (w + 1, Del (xs V.! (n - 1)) : edit) |
| 59 | + impl :: Int -> Int -> Cell [Edit a] |
| 60 | + impl 0 0 = Cell 0 [] |
| 61 | + impl 0 m = case lcs 0 (m - 1) of |
| 62 | + Cell w edit -> Cell (w + 1) (Ins (P.indexArray ys (m - 1)) : edit) |
| 63 | + impl n 0 = case lcs (n - 1) 0 of |
| 64 | + Cell w edit -> Cell (w + 1) (Del (P.indexArray xs (n - 1)) : edit) |
66 | 65 |
|
67 | | - impl n m = head $ sortOn fst |
68 | | - [ edit |
69 | | - , bimap (+1) (Ins y :) (lcs n (m - 1)) |
70 | | - , bimap (+1) (Del x :) (lcs (n - 1) m) |
71 | | - ] |
| 66 | + impl n m = bestOfThree |
| 67 | + edit |
| 68 | + (bimap (+1) (Ins y :) (lcs n (m - 1))) |
| 69 | + (bimap (+1) (Del x :) (lcs (n - 1) m)) |
72 | 70 | where |
73 | | - x = xs V.! (n - 1) |
74 | | - y = ys V.! (m - 1) |
| 71 | + x = P.indexArray xs (n - 1) |
| 72 | + y = P.indexArray ys (m - 1) |
75 | 73 |
|
76 | 74 | edit |
77 | 75 | | eq x y = bimap id (Cpy x :) (lcs (n - 1) (m - 1)) |
78 | | - | otherwise = bimap (+1) (Swp x y :) (lcs (n -1 ) (m - 1)) |
| 76 | + | otherwise = bimap (+1) (Swp x y :) (lcs (n - 1) (m - 1)) |
| 77 | + |
| 78 | +data Cell a = Cell !Int !a |
| 79 | + |
| 80 | +getCell :: Cell a -> a |
| 81 | +getCell (Cell _ x) = x |
| 82 | + |
| 83 | +bestOfThree :: Cell a -> Cell a -> Cell a -> Cell a |
| 84 | +bestOfThree a@(Cell i _x) b@(Cell j _y) c@(Cell k _z) |
| 85 | + | i <= j |
| 86 | + = if i <= k then a else c |
| 87 | + |
| 88 | + | otherwise |
| 89 | + = if j <= k then b else c |
79 | 90 |
|
80 | | -bimap :: (a -> c) -> (b -> d) -> (a, b) -> (c, d) |
81 | | -bimap f g (x, y) = (f x, g y) |
| 91 | +bimap :: (Int -> Int) -> (a -> b) -> Cell a -> Cell b |
| 92 | +bimap f g (Cell i x) = Cell (f i) (g x) |
0 commit comments