Skip to content

Commit 43a6a70

Browse files
authored
Merge pull request #1255 from primo-ppcg/sort
Special case common `sort` usages
2 parents cd36f1e + cdd7083 commit 43a6a70

File tree

1 file changed

+25
-12
lines changed

1 file changed

+25
-12
lines changed

src/boot/boot.janet

+25-12
Original file line numberDiff line numberDiff line change
@@ -805,38 +805,51 @@
805805
###
806806
###
807807

808-
(defn- median-of-three [a b c]
809-
(if (not= (> a b) (> a c))
810-
a
811-
(if (not= (> b a) (> b c)) b c)))
808+
(defmacro- median-of-three
809+
[x y z]
810+
~(if (<= ,x ,y)
811+
(if (<= ,y ,z) ,y (if (<= ,z ,x) ,x ,z))
812+
(if (<= ,z ,y) ,y (if (<= ,x ,z) ,x ,z))))
813+
814+
(defmacro- sort-partition-template
815+
[ind before? left right pivot]
816+
~(do
817+
(while (,before? (in ,ind ,left) ,pivot) (++ ,left))
818+
(while (,before? ,pivot (in ,ind ,right)) (-- ,right))))
812819

813820
(defn- sort-help [a lo hi before?]
814821
(when (< lo hi)
815-
(def pivot
816-
(median-of-three (in a hi) (in a lo)
817-
(in a (math/floor (/ (+ lo hi) 2)))))
822+
(def [x y z] [(in a lo)
823+
(in a (div (+ lo hi) 2))
824+
(in a hi)])
825+
(def pivot (median-of-three x y z))
818826
(var left lo)
819827
(var right hi)
820828
(while true
821-
(while (before? (in a left) pivot) (++ left))
822-
(while (before? pivot (in a right)) (-- right))
829+
(case before?
830+
< (sort-partition-template a < left right pivot)
831+
> (sort-partition-template a > left right pivot)
832+
(sort-partition-template a before? left right pivot))
823833
(when (<= left right)
824834
(def tmp (in a left))
825835
(set (a left) (in a right))
826836
(set (a right) tmp)
827837
(++ left)
828838
(-- right))
829839
(if (>= left right) (break)))
830-
(sort-help a lo right before?)
831-
(sort-help a left hi before?))
840+
(if (< lo right)
841+
(sort-help a lo right before?))
842+
(if (< left hi)
843+
(sort-help a left hi before?)))
832844
a)
833845

834846
(defn sort
835847
``Sorts `ind` in-place, and returns it. Uses quick-sort and is not a stable sort.
836848
If a `before?` comparator function is provided, sorts elements using that,
837849
otherwise uses `<`.``
838850
[ind &opt before?]
839-
(sort-help ind 0 (- (length ind) 1) (or before? <)))
851+
(default before? <)
852+
(sort-help ind 0 (- (length ind) 1) before?))
840853

841854
(defn sort-by
842855
``Sorts `ind` in-place by calling a function `f` on each element and

0 commit comments

Comments
 (0)