From e619fd1c05ed15203b23a69309d4c94ff83abf46 Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Sun, 19 Jan 2025 13:03:16 +0000 Subject: [PATCH] change API of BinVec --- fcore/bin-vec.sml | 114 +++++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 53 deletions(-) diff --git a/fcore/bin-vec.sml b/fcore/bin-vec.sml index ec0f2bd..d6be46b 100644 --- a/fcore/bin-vec.sml +++ b/fcore/bin-vec.sml @@ -1,37 +1,32 @@ -signature BIN_VEC = +signature MAKE_BIN_VEC = sig - (* char is just 8 bits, which is smaller than int's 32 bits - * and smaller = faster here*) - type elem = char - type t = char vector + type elem - val singleton: elem -> t - val getIndex: t * elem -> int - val insert: t * elem -> t + val l: elem * elem -> bool + val eq: elem * elem -> bool + val g: elem * elem -> bool end -structure BinVec: BIN_VEC = +signature BIN_VEC = +sig + type elem + + val empty: elem vector + + val sub: elem vector * int -> elem + + val findInsPos: elem * elem vector -> int + val insert: elem vector * elem * int -> elem vector + val delete: elem vector * elem -> elem vector +end + +functor MakeBinVec(Fn: MAKE_BIN_VEC): BIN_VEC = struct - type elem = char - type t = char vector + type elem = Fn.elem - fun singleton x = Vector.fromList [x] + val empty = Vector.fromList [] - fun helpFind (findNum, vec, low, high) = - if high >= low then - let - val mid = low + ((high - low) div 2) - val curNum = Vector.sub (vec, mid) - in - if curNum = findNum then mid - else if curNum < findNum then helpFind (findNum, vec, mid + 1, high) - else helpFind (findNum, vec, low, mid - 1) - end - else - ~1 - - fun getIndex (vec: t, findNum: elem) = - helpFind (findNum, vec, 0, Vector.length vec - 1) + val sub = Vector.sub fun reverseLinearSearch (pos, findNum, vec) = if pos < 0 then @@ -40,7 +35,7 @@ struct let val curNum = Vector.sub (vec, pos) in - if findNum > curNum then pos + 1 + if Fn.g (findNum, curNum) then pos + 1 else reverseLinearSearch (pos - 1, findNum, vec) end @@ -51,7 +46,7 @@ struct let val curNum = Vector.sub (vec, pos) in - if findNum > curNum then pos + if Fn.g (findNum, curNum) then pos else forwardLinearSearch (pos + 1, findNum, vec) end @@ -61,9 +56,9 @@ struct val mid = low + ((high - low) div 2) val curNum = Vector.sub (vec, mid) in - if curNum = findNum then + if Fn.eq (curNum, findNum) then mid - else if curNum < findNum then + else if Fn.l (curNum, findNum) then helpFindInsPos (findNum, vec, mid + 1, high, mid) else helpFindInsPos (findNum, vec, low, mid - 1, mid) @@ -72,36 +67,39 @@ struct let val curNum = Vector.sub (vec, prevMid) in - if findNum < curNum then forwardLinearSearch (prevMid, findNum, vec) - else reverseLinearSearch (prevMid, findNum, vec) + if Fn.l (findNum, curNum) then + forwardLinearSearch (prevMid, findNum, vec) + else + reverseLinearSearch (prevMid, findNum, vec) end fun findInsPos (findNum, vec) = if Vector.length vec = 0 then ~1 else helpFindInsPos (findNum, vec, 0, Vector.length vec - 1, 0) - fun insert (vec: t, elem: elem) = - let - val insPos = findInsPos (elem, vec) - in - if insPos < 0 then - Vector.concat [Vector.fromList [elem], vec] - else if insPos = Vector.length vec then - Vector.concat [vec, Vector.fromList [elem]] - else - let - val elem = Vector.fromList [elem] - val elem = VectorSlice.full elem + (* insPos parameter should be the unmodified result of calling findInsPos. + * The reason the insert function does not call findInsPos directly is so, + * if two BinVecs are used (one for keys and another for values like a map) + * then the insert function can be used for both the key vector and value + * vector *) + fun insert (vec, elem, insPos) = + if insPos < 0 then + Vector.concat [Vector.fromList [elem], vec] + else if insPos = Vector.length vec then + Vector.concat [vec, Vector.fromList [elem]] + else + let + val elem = Vector.fromList [elem] + val elem = VectorSlice.full elem - val s2len = Vector.length vec - insPos - val slice1 = VectorSlice.slice (vec, 0, SOME insPos) - val slice2 = VectorSlice.slice (vec, insPos, SOME s2len) - in - VectorSlice.concat [slice1, elem, slice2] - end - end + val s2len = Vector.length vec - insPos + val slice1 = VectorSlice.slice (vec, 0, SOME insPos) + val slice2 = VectorSlice.slice (vec, insPos, SOME s2len) + in + VectorSlice.concat [slice1, elem, slice2] + end - fun delete (vec, elem) = + fun delete (vec, elem: elem) = let val insPos = findInsPos (elem, vec) in @@ -118,3 +116,13 @@ struct end end end + +structure IntBinVec = + MakeBinVec + (struct + type elem = int + + val l = Int.< + fun eq (a, b) = a = b + val g = Int.> + end)