From 6fba536f6f3f6d0d31415ecb7a4cbca19012a3b6 Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Mon, 1 Dec 2025 14:24:41 +0000 Subject: [PATCH] when insert forces persistent-vector.sml to split, distribute half of nodes to left side and half of nodes to right side. (We avoid repeated tiny vectors this way, which reduces tree height and maintains balance.) --- fcore/persistent-vector.sml | 54 ++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/fcore/persistent-vector.sml b/fcore/persistent-vector.sml index 4c780b2..345f817 100644 --- a/fcore/persistent-vector.sml +++ b/fcore/persistent-vector.sml @@ -363,7 +363,7 @@ struct val rightSize = VectorSlice.full #[getMaxSize right] val leftLen = SOME idx - val rightLen = SOME (idx - Vector.length nodes - 1) + val rightLen = SOME (Vector.length nodes - idx - 1) val leftSizeSlice = VectorSlice.slice (sizes, 0, leftLen) val rightSizeSlice = VectorSlice.slice (sizes, idx + 1, rightLen) @@ -426,11 +426,28 @@ struct if Vector.length sizes = maxSize then (* have to split *) let - val rightItems = #[{start = start, finish = finish}] - val rightSize = #[finish] - val right = LEAF (rightItems, rightSize) + val startLen = SOME halfSize + val midLen = SOME (Vector.length items - halfSize) + + val leftSizes = VectorSlice.slice (sizes, 0, startLen) + val leftItems = VectorSlice.slice (items, 0, startLen) + + val midSizes = VectorSlice.slice (sizes, halfSize, midLen) + val midItems = VectorSlice.slice (items, halfSize, midLen) + + val rightSizes = VectorSlice.full #[finish] + val rightItems = VectorSlice.full #[{start = start, finish = finish}] + + val rightItems = VectorSlice.concat [midItems, rightItems] + val leftItems = VectorSlice.vector leftItems + + val rightSizes = VectorSlice.concat [midSizes, rightSizes] + val leftSizes = VectorSlice.vector leftSizes + + val left = LEAF (leftItems, leftSizes) + val right = LEAF (rightItems, rightSizes) in - INSERT_SPLIT (tree, right) + INSERT_SPLIT (left, right) end else (* can just append *) @@ -446,11 +463,28 @@ struct if Vector.length sizes = maxSize then (* have to split *) let - val leftItems = #[{start = start, finish = finish}] - val leftSize = #[finish] - val left = LEAF (leftItems, leftSize) + val leftSizes = VectorSlice.full #[finish] + val leftItems = VectorSlice.full #[{start = start, finish = finish}] + + val midLen = SOME halfSize + val rightLen = SOME (Vector.length items - halfSize) + + val midSizes = VectorSlice.slice (sizes, 0, midLen) + val midItems = VectorSlice.slice (items, 0, midLen) + + val rightSizes = VectorSlice.slice (sizes, halfSize, rightLen) + val rightItems = VectorSlice.slice (items, halfSize, rightLen) + + val leftSizes = VectorSlice.concat [leftSizes, midSizes] + val rightSizes = VectorSlice.vector rightSizes + + val leftItems = VectorSlice.concat [leftItems, midItems] + val rightItems = VectorSlice.vector rightItems + + val left = LEAF (leftItems, leftSizes) + val right = LEAF (rightItems, rightSizes) in - INSERT_SPLIT (left, tree) + INSERT_SPLIT (left, right) end else (* just prepend *) @@ -466,7 +500,7 @@ struct let val idx = BinSearch.equalOrMore (finish, sizes) val leftLen = SOME idx - val rightLen = SOME (idx - Vector.length sizes) + val rightLen = SOME (Vector.length sizes - idx) val leftSizes = VectorSlice.slice (sizes, 0, leftLen) val rightSizes = VectorSlice.slice (sizes, idx, rightLen)