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
(* 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)