implement function to join when left has greater depth than right. (I need to implement a function to join when right is greater than left though.
This commit is contained in:
@@ -81,8 +81,7 @@ struct
|
|||||||
* offset for "lower" vector *)
|
* offset for "lower" vector *)
|
||||||
val finish =
|
val finish =
|
||||||
finish - Vector.sub (sizes, Vector.length sizes - 1)
|
finish - Vector.sub (sizes, Vector.length sizes - 1)
|
||||||
val newNode = BRANCH
|
val newNode = BRANCH (#[newVec], #[finish])
|
||||||
(#[newVec], #[finish])
|
|
||||||
in
|
in
|
||||||
APPEND newNode
|
APPEND newNode
|
||||||
end
|
end
|
||||||
@@ -607,7 +606,7 @@ struct
|
|||||||
let
|
let
|
||||||
val {start, finish} = Vector.sub (rightItems, i - Vector.length leftItems)
|
val {start, finish} = Vector.sub (rightItems, i - Vector.length leftItems)
|
||||||
in
|
in
|
||||||
{start + maxLeftSize, finish + maxLeftSize}
|
{start = start + maxLeftSize, finish = finish + maxLeftSize}
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
val sizes =
|
val sizes =
|
||||||
@@ -624,6 +623,121 @@ struct
|
|||||||
end
|
end
|
||||||
| _ => raise Fail "PersistentVector.joinSameDepth: one is BRANCH and other is LEAF"
|
| _ => raise Fail "PersistentVector.joinSameDepth: one is BRANCH and other is LEAF"
|
||||||
|
|
||||||
|
datatype join_result =
|
||||||
|
JOIN_APPEND of t
|
||||||
|
| JOIN_UPDATE of t
|
||||||
|
|
||||||
|
fun appendJoin (left, right, joinDepth, rightLength) =
|
||||||
|
case left of
|
||||||
|
BRANCH (nodes, sizes) =>
|
||||||
|
if joinDepth = 0 then
|
||||||
|
(* base case: should join at this depth *)
|
||||||
|
if Vector.length nodes + rightLength > maxSize then
|
||||||
|
JOIN_APPEND right
|
||||||
|
else
|
||||||
|
(case right of
|
||||||
|
BRANCH (rightNodes, rightSizes) =>
|
||||||
|
let
|
||||||
|
val nodes = Vector.concat [nodes, rightNodes]
|
||||||
|
|
||||||
|
val lastLeftSize = Vector.sub (sizes, Vector.length sizes - 1)
|
||||||
|
val sizes = Vector.tabulate (Vector.length nodes,
|
||||||
|
fn i =>
|
||||||
|
if i < Vector.length sizes then
|
||||||
|
Vector.sub (sizes, i)
|
||||||
|
else
|
||||||
|
Vector.sub (rightSizes, i - Vector.length sizes)
|
||||||
|
+ lastLeftSize
|
||||||
|
)
|
||||||
|
in
|
||||||
|
JOIN_UPDATE (BRANCH (nodes, sizes))
|
||||||
|
end
|
||||||
|
| LEAF _ =>
|
||||||
|
raise Fail
|
||||||
|
"persistent-vector.sml appendJoin: \
|
||||||
|
\expected to join when left and right are both BRANCH \
|
||||||
|
\but left is BRANCH and right is LEAF"
|
||||||
|
)
|
||||||
|
else
|
||||||
|
(* recursion case: join below *)
|
||||||
|
let
|
||||||
|
val lastIdx = Vector.length nodes - 1
|
||||||
|
val lastNode = Vector.sub (nodes, lastIdx)
|
||||||
|
in
|
||||||
|
case appendJoin (lastNode, right, joinDepth - 1, rightLength) of
|
||||||
|
JOIN_UPDATE newLast =>
|
||||||
|
let
|
||||||
|
val prevSize =
|
||||||
|
if lastIdx > 0 then Vector.sub (sizes, lastIdx - 1)
|
||||||
|
else 0
|
||||||
|
val newLastSize = getMaxSize newLast + prevSize
|
||||||
|
val sizes = Vector.update (sizes, lastIdx, newLastSize)
|
||||||
|
val nodes = Vector.update (nodes, lastIdx, newLast)
|
||||||
|
in
|
||||||
|
JOIN_UPDATE (BRANCH (nodes, sizes))
|
||||||
|
end
|
||||||
|
| JOIN_APPEND newNode =>
|
||||||
|
if Vector.length nodes + rightLength > maxSize then
|
||||||
|
(* parent has to append insead as this node
|
||||||
|
* would exceed capacity if appended here *)
|
||||||
|
|
||||||
|
(* todo: I would prefer to take some nodes from right,
|
||||||
|
* then append those nodes to this one to make it reach
|
||||||
|
* max capacity, then return update left * right. *)
|
||||||
|
JOIN_APPEND (BRANCH (#[newNode], #[getMaxSize newNode]))
|
||||||
|
else
|
||||||
|
let
|
||||||
|
val prevSize =
|
||||||
|
Vector.sub (sizes, Vector.length sizes - 1)
|
||||||
|
val newNodeSize = #[getMaxSize newNode + prevSize]
|
||||||
|
val sizes = Vector.concat [sizes, newNodeSize]
|
||||||
|
|
||||||
|
val newNode = #[newNode]
|
||||||
|
val nodes = Vector.concat [nodes, newNode]
|
||||||
|
in
|
||||||
|
JOIN_UPDATE (BRANCH (nodes, sizes))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
| LEAF (items, sizes) =>
|
||||||
|
(* joinDepth should = 0, and we assume it is *)
|
||||||
|
if Vector.length items + rightLength > maxSize then
|
||||||
|
JOIN_APPEND right
|
||||||
|
else
|
||||||
|
(case right of
|
||||||
|
LEAF (rightItems, rightSizes) =>
|
||||||
|
let
|
||||||
|
val leftMaxSize = Vector.sub (sizes, Vector.length sizes - 1)
|
||||||
|
|
||||||
|
val newLen = Vector.length items + Vector.length rightItems
|
||||||
|
val items = Vector.tabulate (newLen,
|
||||||
|
fn i =>
|
||||||
|
if i < Vector.length items then
|
||||||
|
Vector.sub (items, i)
|
||||||
|
else
|
||||||
|
let
|
||||||
|
val {start, finish} = Vector.sub (rightItems, i - Vector.length items)
|
||||||
|
in
|
||||||
|
{start = start + leftMaxSize, finish = finish + leftMaxSize}
|
||||||
|
end
|
||||||
|
)
|
||||||
|
val sizes = Vector.tabulate (newLen,
|
||||||
|
fn i =>
|
||||||
|
if i < Vector.length sizes then
|
||||||
|
Vector.sub (sizes, i)
|
||||||
|
else
|
||||||
|
Vector.sub (rightSizes, i - Vector.length sizes)
|
||||||
|
+ leftMaxSize
|
||||||
|
)
|
||||||
|
in
|
||||||
|
JOIN_UPDATE (LEAF (items, sizes))
|
||||||
|
end
|
||||||
|
| BRANCH _ =>
|
||||||
|
raise Fail
|
||||||
|
"persistent-vector.sml appendJoin: \
|
||||||
|
\left is LEAF and expected right to also be LEAF \
|
||||||
|
\but right is BRANCH"
|
||||||
|
)
|
||||||
|
|
||||||
fun join (left, right) =
|
fun join (left, right) =
|
||||||
if isEmpty left then
|
if isEmpty left then
|
||||||
right
|
right
|
||||||
@@ -631,8 +745,8 @@ struct
|
|||||||
left
|
left
|
||||||
else
|
else
|
||||||
let
|
let
|
||||||
val leftDepth = getDepth left
|
val leftDepth = getDepth (left, 0)
|
||||||
val rightDepth = getDepth right
|
val rightDepth = getDepth (right, 0)
|
||||||
in
|
in
|
||||||
if leftDepth = rightDepth then
|
if leftDepth = rightDepth then
|
||||||
if getRootVecLength left + getRootVecLength right <= maxSize then
|
if getRootVecLength left + getRootVecLength right <= maxSize then
|
||||||
@@ -646,4 +760,24 @@ struct
|
|||||||
in
|
in
|
||||||
BRANCH (nodes, sizes)
|
BRANCH (nodes, sizes)
|
||||||
end
|
end
|
||||||
|
else if leftDepth > rightDepth then
|
||||||
|
let
|
||||||
|
val joinDepth = leftDepth - rightDepth
|
||||||
|
val rightLength = getRootVecLength right
|
||||||
|
in
|
||||||
|
case appendJoin (left, right, joinDepth, rightLength) of
|
||||||
|
JOIN_UPDATE t => t
|
||||||
|
| JOIN_APPEND newRight =>
|
||||||
|
let
|
||||||
|
val ls = getMaxSize left
|
||||||
|
val rs = getMaxSize right + ls
|
||||||
|
val sizes = #[ls, rs]
|
||||||
|
val nodes = #[left, newRight]
|
||||||
|
in
|
||||||
|
BRANCH (nodes, sizes)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
raise Fail "unimplemented"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user