change API of BinVec

This commit is contained in:
2025-01-19 13:03:16 +00:00
parent 4459a676ac
commit e619fd1c05

View File

@@ -1,37 +1,32 @@
signature BIN_VEC = signature MAKE_BIN_VEC =
sig sig
(* char is just 8 bits, which is smaller than int's 32 bits type elem
* and smaller = faster here*)
type elem = char
type t = char vector
val singleton: elem -> t val l: elem * elem -> bool
val getIndex: t * elem -> int val eq: elem * elem -> bool
val insert: t * elem -> t val g: elem * elem -> bool
end 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 struct
type elem = char type elem = Fn.elem
type t = char vector
fun singleton x = Vector.fromList [x] val empty = Vector.fromList []
fun helpFind (findNum, vec, low, high) = val sub = Vector.sub
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)
fun reverseLinearSearch (pos, findNum, vec) = fun reverseLinearSearch (pos, findNum, vec) =
if pos < 0 then if pos < 0 then
@@ -40,7 +35,7 @@ struct
let let
val curNum = Vector.sub (vec, pos) val curNum = Vector.sub (vec, pos)
in in
if findNum > curNum then pos + 1 if Fn.g (findNum, curNum) then pos + 1
else reverseLinearSearch (pos - 1, findNum, vec) else reverseLinearSearch (pos - 1, findNum, vec)
end end
@@ -51,7 +46,7 @@ struct
let let
val curNum = Vector.sub (vec, pos) val curNum = Vector.sub (vec, pos)
in in
if findNum > curNum then pos if Fn.g (findNum, curNum) then pos
else forwardLinearSearch (pos + 1, findNum, vec) else forwardLinearSearch (pos + 1, findNum, vec)
end end
@@ -61,9 +56,9 @@ struct
val mid = low + ((high - low) div 2) val mid = low + ((high - low) div 2)
val curNum = Vector.sub (vec, mid) val curNum = Vector.sub (vec, mid)
in in
if curNum = findNum then if Fn.eq (curNum, findNum) then
mid mid
else if curNum < findNum then else if Fn.l (curNum, findNum) then
helpFindInsPos (findNum, vec, mid + 1, high, mid) helpFindInsPos (findNum, vec, mid + 1, high, mid)
else else
helpFindInsPos (findNum, vec, low, mid - 1, mid) helpFindInsPos (findNum, vec, low, mid - 1, mid)
@@ -72,36 +67,39 @@ struct
let let
val curNum = Vector.sub (vec, prevMid) val curNum = Vector.sub (vec, prevMid)
in in
if findNum < curNum then forwardLinearSearch (prevMid, findNum, vec) if Fn.l (findNum, curNum) then
else reverseLinearSearch (prevMid, findNum, vec) forwardLinearSearch (prevMid, findNum, vec)
else
reverseLinearSearch (prevMid, findNum, vec)
end end
fun findInsPos (findNum, vec) = fun findInsPos (findNum, vec) =
if Vector.length vec = 0 then ~1 if Vector.length vec = 0 then ~1
else helpFindInsPos (findNum, vec, 0, Vector.length vec - 1, 0) else helpFindInsPos (findNum, vec, 0, Vector.length vec - 1, 0)
fun insert (vec: t, elem: elem) = (* insPos parameter should be the unmodified result of calling findInsPos.
let * The reason the insert function does not call findInsPos directly is so,
val insPos = findInsPos (elem, vec) * if two BinVecs are used (one for keys and another for values like a map)
in * then the insert function can be used for both the key vector and value
if insPos < 0 then * vector *)
Vector.concat [Vector.fromList [elem], vec] fun insert (vec, elem, insPos) =
else if insPos = Vector.length vec then if insPos < 0 then
Vector.concat [vec, Vector.fromList [elem]] Vector.concat [Vector.fromList [elem], vec]
else else if insPos = Vector.length vec then
let Vector.concat [vec, Vector.fromList [elem]]
val elem = Vector.fromList [elem] else
val elem = VectorSlice.full elem let
val elem = Vector.fromList [elem]
val elem = VectorSlice.full elem
val s2len = Vector.length vec - insPos val s2len = Vector.length vec - insPos
val slice1 = VectorSlice.slice (vec, 0, SOME insPos) val slice1 = VectorSlice.slice (vec, 0, SOME insPos)
val slice2 = VectorSlice.slice (vec, insPos, SOME s2len) val slice2 = VectorSlice.slice (vec, insPos, SOME s2len)
in in
VectorSlice.concat [slice1, elem, slice2] VectorSlice.concat [slice1, elem, slice2]
end end
end
fun delete (vec, elem) = fun delete (vec, elem: elem) =
let let
val insPos = findInsPos (elem, vec) val insPos = findInsPos (elem, vec)
in in
@@ -118,3 +116,13 @@ struct
end end
end end
end end
structure IntBinVec =
MakeBinVec
(struct
type elem = int
val l = Int.<
fun eq (a, b) = a = b
val g = Int.>
end)