From ab6b08f3c97cb0f93380245b94bacb894438377f Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Tue, 21 May 2024 13:24:04 +0100 Subject: [PATCH] code insert function for rope (except for the leaf case) --- bench.mlb | 9 ------- examples.mlb | 1 + tiny_rope.sml | 7 +++-- tiny_rope23.sml | 65 ++++++++++++++++++++++++++++++++++++++++++++ utils.sml | 71 ++++++++++++++++++++++++++++++++----------------- 5 files changed, 115 insertions(+), 38 deletions(-) create mode 100644 tiny_rope23.sml diff --git a/bench.mlb b/bench.mlb index c6a7681..82b749b 100644 --- a/bench.mlb +++ b/bench.mlb @@ -1,14 +1,5 @@ $(SML_LIB)/basis/basis.mlb -ann - "allowVectorExps true" -in - svelte.sml - rust.sml - seph.sml - automerge.sml -end - tiny_rope.sml rope.sml utils.sml diff --git a/examples.mlb b/examples.mlb index 261e6f9..4e38127 100644 --- a/examples.mlb +++ b/examples.mlb @@ -1,5 +1,6 @@ $(SML_LIB)/basis/basis.mlb tiny_rope.sml +tiny_rope23.sml rope.sml examples.sml diff --git a/tiny_rope.sml b/tiny_rope.sml index c82cac3..64b08bd 100644 --- a/tiny_rope.sml +++ b/tiny_rope.sml @@ -7,7 +7,7 @@ sig val insert: int * string * t -> t val append: string * t -> t val delete: int * int * t -> t - val toString: t -> string + val toString: t -> string list val foldFromIdxTerm: (char * 'a -> 'a) * ('a -> bool) * int * t * 'a -> 'a val foldFromIdx: (char * 'a -> 'a) * int * t * 'a -> 'a end @@ -33,10 +33,9 @@ struct | N0 s => f (state, s) | _ => raise AuxConstructor + fun toStringFolder (acc, str) = str :: acc fun toString rope = - let val strList = foldr ((fn (acc, str) => str :: acc), [], rope) - in String.concat strList - end + foldr (toStringFolder, [], rope) datatype balance = AddedNode | DeletedNode | NoAction diff --git a/tiny_rope23.sml b/tiny_rope23.sml new file mode 100644 index 0000000..16272d2 --- /dev/null +++ b/tiny_rope23.sml @@ -0,0 +1,65 @@ +structure TinyRope23 = +struct + datatype t = + Leaf of string + | N2 of t * int * t * int + | N3 of t * int * t * int * t * int + + fun size rope = + case rope of + Leaf str => String.size str + | N2 (_, lm, _, rm) => rm + rm + | N3 (_, lm, _, mm, _, rm) => lm + mm + rm + + datatype treeI = TI of t * int | OF of t * int * t * int + + fun ins (curIdx, newStr, rope) = + case rope of + N2 (l, lm, r, rm) => + if curIdx < lm then + (case ins (curIdx, newStr, l) of + TI (l, lm) => TI (N2 (l, lm, r, rm), lm + rm) + | OF (l1, lm1, l2, lm2) => + TI (N3 (l1, lm1, l2, lm2, r, rm), lm1 + lm2 + rm)) + else + (case (ins (curIdx - lm, newStr, r)) of + TI (r, rm) => TI (N2 (l, lm, r, rm), lm + rm) + | OF (r1, rm1, r2, rm2) => + TI (N3 (l, lm, r1, rm1, r2, rm2), lm + rm1 + rm2)) + | N3 (l, lm, m, mm, r, rm) => + (* + * Ropes don't usually have N3 nodes so the way we accomodate this is: + * If current index is less than left metadata, use same strategy as + * recursing to the left as N2 nodes. + * Else if current index is less than middle metadata, + * recurse to middle node while subtracting left metadata. + * Else, recurse to right node while subtracting (left metadata + + * middle metadata). + * This simulates the mathematical operations that would take place + * for the following rope: + * (l, lm) + * / \ + * (..., ...) (m, mm, r, rm) + *) + if curIdx < lm then + (case ins (curIdx, newStr, l) of + TI (l, lm) => TI (N2 (l, lm, m, mm, r, rm)) + | OF (l1, lm1, l2, lm2) => + OF (N2 (l1, lm1, l2, lm2), lm1 + lm2, N2 (m, mm, r, rm), mm + rm)) + else if curIdx < mm then + (case ins (curIdx - lm, newStr, m) of + TI (m, mm) => TI (N3 (l, lm, m, mm, r, rm)) + | OF (m1, mm1, m2, mm2) => + OF (N2 (l, lm, m1, mm1), lm + mm1, N2 (m2, mm2, r, rm), mm2 + rm)) + else + (case ins (curIdx - (lm + mm), newStr, r) of + TI (r, rm) => TI (N3 (l, lm, m, mm, r, rm)) + | OF (r1, rm1, r2, rm2) => + OF (N2 (l, lm, m, mm), lm + mm, N2 (r1, rm1, r2, rm2))) + + fun insRoot (TI t) = t + | insRoot OF (l, lm, r, rm) = N2 (l, lm, r, rm) + + fun insert (idx, newStr, rope) = + insRoot (ins (idx, newStr, rope)) +end diff --git a/utils.sml b/utils.sml index 9bb4c9b..4fe1aa0 100644 --- a/utils.sml +++ b/utils.sml @@ -1,4 +1,4 @@ -fun timeFun title f = +fun timeFun (title, f) = let val title = String.concat ["Starting ", title, "..."] val _ = (print title) @@ -19,20 +19,20 @@ fun runTxns arr = Vector.foldl (fn ((pos, delNum, insStr), rope) => let - val rope = if delNum > 0 then Rope.delete (pos, delNum, rope) else rope + val rope = if delNum > 0 then TinyRope.delete (pos, delNum, rope) else rope val strSize = String.size insStr val rope = - if strSize > 0 then Rope.insert (pos, insStr, rope) else rope + if strSize > 0 then TinyRope.insert (pos, insStr, rope) else rope in rope - end) Rope.empty arr + end) TinyRope.empty arr fun runTxnsTime title arr = let val f = (fn () => runTxns arr) in timeFun title f end -fun runToString rope = Rope.toString rope +fun runToString rope = TinyRope.toString rope fun runToStringTime title rope = let val f = (fn () => runToString rope) @@ -74,29 +74,50 @@ fun writeFile filename acc = () end +fun timeFun (title, f) = + let + val title = String.concat ["Starting ", title, "..."] + val _ = (print title) + val startTime = Time.now () + val startTime = Time.toNanoseconds startTime + val x = f () + val endTime = Time.now () + val endTime = Time.toNanoseconds endTime + val timeDiff = endTime - startTime + val timeDiff = LargeInt.toString timeDiff + val timeTook = String.concat ["took ", timeDiff, " nanoseconds\n"] + val _ = (print timeTook) + in + x + end + +fun appendMany (ctr, limit, rope) = + if ctr = limit then rope + else + let + val rope = TinyRope.append ("hello, world!", rope) + in + appendMany (ctr + 1, limit, rope) + end + +val closure = fn () => + (appendMany (0, 2410, TinyRope.empty)) + +fun closure2 rope = fn () => + TinyRope.toString rope + +fun loop () = loop () + fun main () = let - (* Timing benchmarks. *) - val startTime = LargeInt.fromInt 0 - val _ = runTxns1000Times (999, svelte_arr, startTime) - val _ = runTxns1000Times (999, rust_arr, startTime) - val _ = runTxns1000Times (999, seph_arr, startTime) - val _ = runTxns1000Times (999, automerge_arr, startTime) - - (* Tests that line metadata is correct; will fail if incorrect. *) - val svelte = runTxns svelte_arr - val _ = Rope.verifyLines svelte - - val rust = runTxns rust_arr - val _ = Rope.verifyLines rust - - val seph = runTxns seph_arr - val _ = Rope.verifyLines seph - - val automerge = runTxns automerge_arr - val _ = Rope.verifyLines automerge + val rope = + timeFun("tiny_rope append : ", closure) + val str = timeFun ("tiny_rope toString: ", closure2 rope) + val str = String.concat str + val io = TextIO.openOut "hello.txt" + val _ = TextIO.output (io, str) in - () + () end val _ = main ()