move if statement that only needs to be checked once from helpBinSearch, which is recursive, to binSearch which is not recursive, for negligibly better performance (fewer branch predictions)

This commit is contained in:
2024-06-30 01:37:52 +01:00
parent 75aba5e8e1
commit ba7d3579b4

View File

@@ -2,34 +2,34 @@ structure LineGap =
struct struct
local local
fun helpCountLineBreaks (pos, acc, str) = fun helpCountLineBreaks (pos, acc, str) =
let let
val _ = print ("count pos: " ^ Int.toString pos ^ "\n") val _ = print ("count pos: " ^ Int.toString pos ^ "\n")
in in
if pos < 0 then if pos < 0 then
Vector.fromList acc Vector.fromList acc
else else
let let
val chr = String.sub (str, pos) val chr = String.sub (str, pos)
in in
if chr = #"\n" then if chr = #"\n" then
(* Is this a \r\n pair? Then the position of \r should be consed. *) (* Is this a \r\n pair? Then the position of \r should be consed. *)
if pos = 0 then if pos = 0 then
Vector.fromList (0 :: acc) Vector.fromList (0 :: acc)
else
let
val prevChar = String.sub (str, pos - 1)
in
if prevChar = #"\r" then
helpCountLineBreaks (pos - 2, (pos - 1) :: acc, str)
else
helpCountLineBreaks (pos - 2, pos :: acc, str)
end
else if chr = #"\r" then
helpCountLineBreaks (pos - 1, pos :: acc, str)
else else
let helpCountLineBreaks (pos - 1, acc, str)
val prevChar = String.sub (str, pos - 1) end
in end
if prevChar = #"\r" then
helpCountLineBreaks (pos - 2, (pos - 1) :: acc, str)
else
helpCountLineBreaks (pos - 2, pos :: acc, str)
end
else if chr = #"\r" then
helpCountLineBreaks (pos - 1, pos :: acc, str)
else
helpCountLineBreaks (pos - 1, acc, str)
end
end
in in
fun countLineBreaks str = fun countLineBreaks str =
helpCountLineBreaks (String.size str - 1, [], str) helpCountLineBreaks (String.size str - 1, [], str)
@@ -49,7 +49,13 @@ struct
val vecLimit = 32 val vecLimit = 32
val empty = val empty =
{idx = 0, leftStrings = [], rightStrings = [], line = 0, leftLines = [], rightLines = []} { idx = 0
, leftStrings = []
, rightStrings = []
, line = 0
, leftLines = []
, rightLines = []
}
local local
fun helpToString (acc, input) = fun helpToString (acc, input) =
@@ -71,29 +77,27 @@ struct
local local
fun helpBinSearch (findNum, lines, low, high) = fun helpBinSearch (findNum, lines, low, high) =
if Vector.length lines = 0 then let
0 val mid = low + ((high - low) div 2)
else in
let if high >= low then
val mid = low + ((high - low) div 2) let
in val midVal = Vector.sub (lines, mid)
if high >= low then in
let if midVal = findNum then
val midVal = Vector.sub (lines, mid) mid
in else if midVal < findNum then
if midVal = findNum then helpBinSearch (findNum, lines, mid + 1, high)
mid else
else if midVal < findNum then helpBinSearch (findNum, lines, low, mid - 1)
helpBinSearch (findNum, lines, mid + 1, high) end
else else
helpBinSearch (findNum, lines, low, mid - 1) Int.max (0, mid)
end end
else
Int.max (0, mid)
end
in in
fun binSearch (findNum, lines) = fun binSearch (findNum, lines) =
helpBinSearch (findNum, lines, 0, Vector.length lines) if Vector.length lines = 0 then 0
else helpBinSearch (findNum, lines, 0, Vector.length lines)
end end
fun insWhenIdxAndCurIdxAreEqual fun insWhenIdxAndCurIdxAreEqual
@@ -140,14 +144,14 @@ struct
let let
val _ = print "line 137\n" val _ = print "line 137\n"
in in
(* Does not fit in limit, so cons instead.*) (* Does not fit in limit, so cons instead.*)
{ idx = curIdx + String.size newString { idx = curIdx + String.size newString
, line = curLine + Vector.length newLines , line = curLine + Vector.length newLines
, leftStrings = newString :: leftStrings , leftStrings = newString :: leftStrings
, leftLines = newLines :: leftLines , leftLines = newLines :: leftLines
, rightStrings = rightStrings , rightStrings = rightStrings
, rightLines = rightLines , rightLines = rightLines
} }
end end
| (_, _) => | (_, _) =>
(* (*
@@ -156,17 +160,17 @@ struct
* also means that the other one is empty. * also means that the other one is empty.
* So we don't need to perform addition or consing. * So we don't need to perform addition or consing.
*) *)
let let
val _ = print "line 156\n" val _ = print "line 156\n"
in in
{ idx = String.size newString { idx = String.size newString
, line = Vector.length newLines , line = Vector.length newLines
, leftStrings = [newString] , leftStrings = [newString]
, leftLines = [newLines] , leftLines = [newLines]
, rightStrings = rightStrings , rightStrings = rightStrings
, rightLines = rightLines , rightLines = rightLines
} }
end end
fun insInLeftList fun insInLeftList
( idx ( idx
@@ -211,14 +215,17 @@ struct
end end
else else
(* Just cons everything; no way we can join while staying in limit. *) (* Just cons everything; no way we can join while staying in limit. *)
let val _ = print "line 210\n" in let
{ idx = curIdx + String.size newString val _ = print "line 210\n"
, line = curLine + Vector.length newLines in
, leftStrings = leftStringsHd :: newString :: leftStringsTl { idx = curIdx + String.size newString
, leftLines = leftLinesHd :: newLines :: leftLinesTl , line = curLine + Vector.length newLines
, rightStrings = rightStrings , leftStrings = leftStringsHd :: newString :: leftStringsTl
, rightLines = rightLines , leftLines = leftLinesHd :: newLines :: leftLinesTl
} end , rightStrings = rightStrings
, rightLines = rightLines
}
end
else else
(* Need to insert in the middle of the left list. *) (* Need to insert in the middle of the left list. *)
let let
@@ -228,7 +235,8 @@ struct
val strSub2 = String.substring val strSub2 = String.substring
(leftStringsHd, strLength, String.size leftStringsHd - strLength) (leftStringsHd, strLength, String.size leftStringsHd - strLength)
val midpoint = binSearch (String.size strSub1, leftLinesHd) val midpoint = binSearch (String.size strSub1, leftLinesHd)
val _ = print ("str size:" ^ Int.toString (Vector.length leftLinesHd) ^ "\n") val _ = print
("str size:" ^ Int.toString (Vector.length leftLinesHd) ^ "\n")
val _ = print ("midpoint:" ^ Int.toString (midpoint) ^ "\n") val _ = print ("midpoint:" ^ Int.toString (midpoint) ^ "\n")
in in
if if
@@ -236,7 +244,7 @@ struct
then then
(* Join three strings together. *) (* Join three strings together. *)
let let
val _ = print "line 233\n" val _ = print "line 233\n"
val joinedLines = val joinedLines =
Vector.tabulate Vector.tabulate
( Vector.length leftLinesHd + Vector.length newLines ( Vector.length leftLinesHd + Vector.length newLines
@@ -267,15 +275,15 @@ struct
(* If we can join newString/lines with sub1 while (* If we can join newString/lines with sub1 while
* staying in limit. *) * staying in limit. *)
let let
val _ = print "line 268\n" val _ = print "line 268\n"
val _ = print ("vector length: " ^ Int.toString (Vector.length newLines ) ^ "\n") val _ = print
val _ = print ("midpoint: " ^ Int.toString ( ("vector length: " ^ Int.toString (Vector.length newLines) ^ "\n")
midpoint) ^ "\n") val _ = print ("midpoint: " ^ Int.toString (midpoint) ^ "\n")
val newLeftLines = val newLeftLines =
Vector.tabulate (midpoint + Vector.length newLines, fn idx => Vector.tabulate (midpoint + Vector.length newLines, fn idx =>
if idx < midpoint then Vector.sub (leftLinesHd, idx) if idx < midpoint then Vector.sub (leftLinesHd, idx)
else Vector.sub (newLines, idx - midpoint) + String.size strSub1) else Vector.sub (newLines, idx - midpoint) + String.size strSub1)
val _ = print "line 275\n" val _ = print "line 275\n"
val newRightLines = VectorSlice.slice (leftLinesHd, midpoint, SOME val newRightLines = VectorSlice.slice (leftLinesHd, midpoint, SOME
(Vector.length leftLinesHd - midpoint)) (Vector.length leftLinesHd - midpoint))
val newRightLines = VectorSlice.vector newRightLines val newRightLines = VectorSlice.vector newRightLines
@@ -299,7 +307,7 @@ struct
(* If we can join newString/line with sub2 while staying (* If we can join newString/line with sub2 while staying
* in limit. *) * in limit. *)
let let
val _ = print "line 292\n" val _ = print "line 292\n"
val newLeftLines = VectorSlice.slice (leftLinesHd, 0, SOME midpoint) val newLeftLines = VectorSlice.slice (leftLinesHd, 0, SOME midpoint)
val newLeftLines = VectorSlice.vector newLeftLines val newLeftLines = VectorSlice.vector newLeftLines
@@ -326,7 +334,7 @@ struct
else else
(* Can't join on either side while staying in limit. *) (* Can't join on either side while staying in limit. *)
let let
val _ = print "line 319\n" val _ = print "line 319\n"
val lineSub1 = VectorSlice.slice (leftLinesHd, 0, SOME midpoint) val lineSub1 = VectorSlice.slice (leftLinesHd, 0, SOME midpoint)
val lineSub1 = VectorSlice.vector lineSub1 val lineSub1 = VectorSlice.vector lineSub1
@@ -481,7 +489,7 @@ struct
if isInLimit (newString, rightStringsHd, newLines, rightLinesHd) then if isInLimit (newString, rightStringsHd, newLines, rightLinesHd) then
(* Allocate new string because we can do so while staying in limit. *) (* Allocate new string because we can do so while staying in limit. *)
let let
val _ = print "line 474\n" val _ = print "line 474\n"
val newRightStringsHd = rightStringsHd ^ newString val newRightStringsHd = rightStringsHd ^ newString
val newRightLinesHd = val newRightLinesHd =
Vector.tabulate Vector.tabulate
@@ -505,14 +513,17 @@ struct
else else
(* Cons newString and newLines to after-the-head, (* Cons newString and newLines to after-the-head,
* because we can't join while staying in the limit.*) * because we can't join while staying in the limit.*)
let val _ = print "line 498\n" in let
{ idx = curIdx val _ = print "line 498\n"
, line = curLine in
, leftStrings = leftStrings { idx = curIdx
, leftLines = leftLines , line = curLine
, rightStrings = rightStringsHd :: newString :: rightStringsTl , leftStrings = leftStrings
, rightLines = rightLinesHd :: newLines :: rightLinesTl , leftLines = leftLines
} end , rightStrings = rightStringsHd :: newString :: rightStringsTl
, rightLines = rightLinesHd :: newLines :: rightLinesTl
}
end
else else
(* Have to split rightStringsHd and rightLinesHd in the middle. *) (* Have to split rightStringsHd and rightLinesHd in the middle. *)
let let
@@ -527,7 +538,7 @@ struct
then then
(* Join three strings together. *) (* Join three strings together. *)
let let
val _ = print "line 520\n" val _ = print "line 520\n"
val newRightStringsHd = String.concat [strSub1, newString, strSub2] val newRightStringsHd = String.concat [strSub1, newString, strSub2]
val newRightLinesHd = val newRightLinesHd =
Vector.tabulate Vector.tabulate
@@ -559,15 +570,12 @@ struct
* staying in limit. *) * staying in limit. *)
let let
(* strSub1 ^ newString is placed on the left list. *) (* strSub1 ^ newString is placed on the left list. *)
val _ = print "line 552\n" val _ = print "line 552\n"
val newLeftStringsHd = strSub1 ^ newString val newLeftStringsHd = strSub1 ^ newString
val newLeftLinesHd = val newLeftLinesHd =
Vector.tabulate (Vector.length newLines + midpoint, fn idx => Vector.tabulate (Vector.length newLines + midpoint, fn idx =>
if idx < midpoint then if idx < midpoint then Vector.sub (rightLinesHd, idx)
Vector.sub (rightLinesHd, idx) else Vector.sub (newLines, accessIdx) + String.size strSub1)
else
Vector.sub (newLines, accessIdx) + String.size strSub1
)
val _ = print "line 584\n" val _ = print "line 584\n"
val newRightLinesHd = val newRightLinesHd =
@@ -592,7 +600,7 @@ struct
(* If we can join newString/line with sub2 while staying (* If we can join newString/line with sub2 while staying
* in limit. *) * in limit. *)
let let
val _ = print "line 581\n" val _ = print "line 581\n"
val newRightStringsHd = newString ^ strSub2 val newRightStringsHd = newString ^ strSub2
val newRightLinesHd = val newRightLinesHd =
Vector.tabulate Vector.tabulate
@@ -619,7 +627,7 @@ struct
else else
(* Can't join on either side while staying in limit. *) (* Can't join on either side while staying in limit. *)
let let
val _ = print "line 608\n" val _ = print "line 608\n"
val lineSub1 = VectorSlice.slice (rightLinesHd, 0, SOME midpoint) val lineSub1 = VectorSlice.slice (rightLinesHd, 0, SOME midpoint)
val lineSub1 = VectorSlice.vector lineSub1 val lineSub1 = VectorSlice.vector lineSub1
val lineSub2 = VectorSlice.slice (rightLinesHd, midpoint, SOME val lineSub2 = VectorSlice.slice (rightLinesHd, midpoint, SOME
@@ -661,7 +669,7 @@ struct
(leftStringsHd, rightStringsHd, leftLinesHd, rightLinesHd) (leftStringsHd, rightStringsHd, leftLinesHd, rightLinesHd)
then then
let let
val _ = print "line 650\n" val _ = print "line 650\n"
val nextLine = curLine + Vector.length rightLinesHd val nextLine = curLine + Vector.length rightLinesHd
val newLeftStringsHd = leftStringsHd ^ rightStringsHd val newLeftStringsHd = leftStringsHd ^ rightStringsHd
val newLeftLinesHd = val newLeftLinesHd =
@@ -734,14 +742,17 @@ struct
end end
| (_, _) => | (_, _) =>
(* Right string/line is empty. *) (* Right string/line is empty. *)
let val _ = print "line 723\n" in let
{ idx = curIdx val _ = print "line 723\n"
, line = curLine in
, leftStrings = leftStrings { idx = curIdx
, leftLines = leftLines , line = curLine
, rightStrings = [newString] , leftStrings = leftStrings
, rightLines = [newLines] , leftLines = leftLines
} end , rightStrings = [newString]
, rightLines = [newLines]
}
end
fun ins fun ins
( idx ( idx