diff --git a/code/__HELPERS/hallucinations.dm b/code/__HELPERS/hallucinations.dm
index 809ff475fc96..1bb54a917cbc 100644
--- a/code/__HELPERS/hallucinations.dm
+++ b/code/__HELPERS/hallucinations.dm
@@ -149,7 +149,7 @@ GLOBAL_LIST_INIT(random_hallucination_weighted_list, generate_hallucination_weig
last_type_weight = this_weight
// Sort by weight descending, where weight is the values (not the keys). We assoc_to_keys later to get JUST the text
- all_weights = sortTim(all_weights, GLOBAL_PROC_REF(cmp_numeric_dsc), associative = TRUE)
+ sortTim(all_weights, GLOBAL_PROC_REF(cmp_numeric_dsc), associative = TRUE)
var/page_style = ""
var/page_contents = "[page_style]
[header][jointext(assoc_to_keys(all_weights), "")]
"
diff --git a/code/__HELPERS/sorts/InsertSort.dm b/code/__HELPERS/sorts/InsertSort.dm
deleted file mode 100644
index 2d5ca408ce3b..000000000000
--- a/code/__HELPERS/sorts/InsertSort.dm
+++ /dev/null
@@ -1,19 +0,0 @@
-//simple insertion sort - generally faster than merge for runs of 7 or smaller
-/proc/sortInsert(list/L, cmp=/proc/cmp_numeric_asc, associative, fromIndex=1, toIndex=0)
- if(L && L.len >= 2)
- fromIndex = fromIndex % L.len
- toIndex = toIndex % (L.len+1)
- if(fromIndex <= 0)
- fromIndex += L.len
- if(toIndex <= 0)
- toIndex += L.len + 1
-
- var/datum/sort_instance/SI = GLOB.sortInstance
- if(!SI)
- SI = new
- SI.L = L
- SI.cmp = cmp
- SI.associative = associative
-
- SI.binarySort(fromIndex, toIndex, fromIndex)
- return L
diff --git a/code/__HELPERS/sorts/MergeSort.dm b/code/__HELPERS/sorts/MergeSort.dm
deleted file mode 100644
index 4692534edffd..000000000000
--- a/code/__HELPERS/sorts/MergeSort.dm
+++ /dev/null
@@ -1,19 +0,0 @@
-//merge-sort - gernerally faster than insert sort, for runs of 7 or larger
-/proc/sortMerge(list/L, cmp=/proc/cmp_numeric_asc, associative, fromIndex=1, toIndex)
- if(L && L.len >= 2)
- fromIndex = fromIndex % L.len
- toIndex = toIndex % (L.len+1)
- if(fromIndex <= 0)
- fromIndex += L.len
- if(toIndex <= 0)
- toIndex += L.len + 1
-
- var/datum/sort_instance/SI = GLOB.sortInstance
- if(!SI)
- SI = new
- SI.L = L
- SI.cmp = cmp
- SI.associative = associative
-
- SI.mergeSort(fromIndex, toIndex)
- return L
diff --git a/code/__HELPERS/sorts/TimSort.dm b/code/__HELPERS/sorts/TimSort.dm
deleted file mode 100644
index 44f6d170df40..000000000000
--- a/code/__HELPERS/sorts/TimSort.dm
+++ /dev/null
@@ -1,20 +0,0 @@
-//TimSort interface
-/proc/sortTim(list/L, cmp=/proc/cmp_numeric_asc, associative, fromIndex=1, toIndex=0)
- if(L && L.len >= 2)
- fromIndex = fromIndex % L.len
- toIndex = toIndex % (L.len+1)
- if(fromIndex <= 0)
- fromIndex += L.len
- if(toIndex <= 0)
- toIndex += L.len + 1
-
- var/datum/sort_instance/SI = GLOB.sortInstance
- if(!SI)
- SI = new
-
- SI.L = L
- SI.cmp = cmp
- SI.associative = associative
-
- SI.timSort(fromIndex, toIndex)
- return L
diff --git a/code/__HELPERS/sorts/helpers.dm b/code/__HELPERS/sorts/helpers.dm
new file mode 100644
index 000000000000..7198286f29fe
--- /dev/null
+++ b/code/__HELPERS/sorts/helpers.dm
@@ -0,0 +1,95 @@
+/// Sorts the list in place with timSort, default settings.
+#define SORT_TIM(to_sort, associative) if(length(to_sort) >= 2) { \
+ var/datum/sort_instance/sorter = GLOB.sortInstance; \
+ if (isnull(sorter)) { \
+ sorter = new; \
+ } \
+ sorter.L = to_sort; \
+ sorter.cmp = GLOBAL_PROC_REF(cmp_numeric_asc); \
+ sorter.associative = associative; \
+ sorter.timSort(1, 0); \
+}
+
+
+/// Helper for the sorting procs. Prevents some code duplication. Creates /datum/sort_instance/sorter
+#define CREATE_SORT_INSTANCE(to_sort, cmp, associative, fromIndex, toIndex) \
+ if(length(to_sort) < 2) { \
+ return to_sort; \
+ } \
+ fromIndex = fromIndex % length(to_sort); \
+ toIndex = toIndex % (length(to_sort) + 1); \
+ if (fromIndex <= 0) { \
+ fromIndex += length(to_sort); \
+ } \
+ if (toIndex <= 0) { \
+ toIndex += length(to_sort) + 1; \
+ } \
+ var/datum/sort_instance/sorter = GLOB.sortInstance; \
+ if (isnull(sorter)) { \
+ sorter = new; \
+ } \
+ sorter.L = to_sort; \
+ sorter.cmp = cmp; \
+ sorter.associative = associative;
+
+
+/**
+ * ## Tim Sort
+ * Hybrid sorting algorithm derived from merge sort and insertion sort.
+ *
+ * **Sorts in place**.
+ * You might not need to get the return value.
+ *
+ * @see
+ * https://en.wikipedia.org/wiki/Timsort
+ *
+ * @param {list} to_sort - The list to sort.
+ *
+ * @param {proc} cmp - The comparison proc to use. Default: Numeric ascending.
+ *
+ * @param {boolean} associative - Whether the list is associative. Default: FALSE.
+ *
+ * @param {int} fromIndex - The index to start sorting from. Default: 1.
+ *
+ * @param {int} toIndex - The index to stop sorting at. Default: 0.
+ */
+/proc/sortTim(list/to_sort, cmp = GLOBAL_PROC_REF(cmp_numeric_asc), associative = FALSE, fromIndex = 1, toIndex = 0) as /list
+ CREATE_SORT_INSTANCE(to_sort, cmp, associative, fromIndex, toIndex)
+
+ sorter.timSort(fromIndex, toIndex)
+
+ return to_sort
+
+
+/**
+ * ## Merge Sort
+ * Divide and conquer sorting algorithm.
+ *
+ * @see
+ * - https://en.wikipedia.org/wiki/Merge_sort
+ */
+/proc/sortMerge(list/to_sort, cmp = GLOBAL_PROC_REF(cmp_numeric_asc), associative = FALSE, fromIndex = 1, toIndex = 0) as /list
+ CREATE_SORT_INSTANCE(to_sort, cmp, associative, fromIndex, toIndex)
+
+ sorter.mergeSort(fromIndex, toIndex)
+
+ return to_sort
+
+
+/**
+ * ## Insertion Sort
+ * Simple sorting algorithm that builds the final sorted list one item at a time.
+ *
+
+ * @see
+ * - https://en.wikipedia.org/wiki/Insertion_sort
+ */
+/proc/sortInsert(list/to_sort, cmp = GLOBAL_PROC_REF(cmp_numeric_asc), associative = FALSE, fromIndex = 1, toIndex = 0) as /list
+ CREATE_SORT_INSTANCE(to_sort, cmp, associative, fromIndex, toIndex)
+
+ sorter.binarySort(fromIndex, toIndex)
+
+ return to_sort
+
+
+#undef CREATE_SORT_INSTANCE
diff --git a/code/__HELPERS/sorts/__main.dm b/code/__HELPERS/sorts/sort_instance.dm
similarity index 99%
rename from code/__HELPERS/sorts/__main.dm
rename to code/__HELPERS/sorts/sort_instance.dm
index 8a34a26de6d0..bd1bbe0582a2 100644
--- a/code/__HELPERS/sorts/__main.dm
+++ b/code/__HELPERS/sorts/sort_instance.dm
@@ -101,7 +101,8 @@ GLOBAL_DATUM_INIT(sortInstance, /datum/sort_instance, new())
if(start <= lo)
start = lo + 1
- for(,start < hi, ++start)
+ var/list/L = src.L
+ for(start in start to hi - 1)
var/pivot = fetchElement(L,start)
//set left and right to the index where pivot belongs
@@ -140,6 +141,7 @@ GLOBAL_DATUM_INIT(sortInstance, /datum/sort_instance, new())
if(runHi >= hi)
return 1
+ var/list/L = src.L
var/last = fetchElement(L,lo)
var/current = fetchElement(L,runHi++)
@@ -221,7 +223,6 @@ GLOBAL_DATUM_INIT(sortInstance, /datum/sort_instance, new())
runLens.Cut(i+1, i+2)
runBases.Cut(i+1, i+2)
-
//Find where the first element of run2 goes in run1.
//Prior elements in run1 can be ignored (because they're already in place)
var/k = gallopRight(fetchElement(L,base2), base1, len1, 0)
@@ -259,6 +260,7 @@ GLOBAL_DATUM_INIT(sortInstance, /datum/sort_instance, new())
/datum/sort_instance/proc/gallopLeft(key, base, len, hint)
//ASSERT(len > 0 && hint >= 0 && hint < len)
+ var/list/L = src.L
var/lastOffset = 0
var/offset = 1
if(call(cmp)(key, fetchElement(L,base+hint)) > 0)
@@ -318,6 +320,7 @@ GLOBAL_DATUM_INIT(sortInstance, /datum/sort_instance, new())
/datum/sort_instance/proc/gallopRight(key, base, len, hint)
//ASSERT(len > 0 && hint >= 0 && hint < len)
+ var/list/L = src.L
var/offset = 1
var/lastOffset = 0
if(call(cmp)(key, fetchElement(L,base+hint)) < 0) //key <= L[base+hint]
@@ -366,6 +369,7 @@ GLOBAL_DATUM_INIT(sortInstance, /datum/sort_instance, new())
/datum/sort_instance/proc/mergeLo(base1, len1, base2, len2)
//ASSERT(len1 > 0 && len2 > 0 && base1 + len1 == base2)
+ var/list/L = src.L
var/cursor1 = base1
var/cursor2 = base2
@@ -468,6 +472,7 @@ GLOBAL_DATUM_INIT(sortInstance, /datum/sort_instance, new())
/datum/sort_instance/proc/mergeHi(base1, len1, base2, len2)
//ASSERT(len1 > 0 && len2 > 0 && base1 + len1 == base2)
+ var/list/L = src.L
var/cursor1 = base1 + len1 - 1 //start at end of sublists
var/cursor2 = base2 + len2 - 1
@@ -610,6 +615,7 @@ GLOBAL_DATUM_INIT(sortInstance, /datum/sort_instance, new())
return L
/datum/sort_instance/proc/mergeAt2(i)
+ var/list/L = src.L
var/cursor1 = runBases[i]
var/cursor2 = runBases[i+1]
diff --git a/code/controllers/subsystem/dcs.dm b/code/controllers/subsystem/dcs.dm
index 8dbd88e6231a..a5deea383a69 100644
--- a/code/controllers/subsystem/dcs.dm
+++ b/code/controllers/subsystem/dcs.dm
@@ -53,8 +53,8 @@ PROCESSING_SUBSYSTEM_DEF(dcs)
else
fullid += REF(key)
- if(length(named_arguments))
- named_arguments = sortTim(named_arguments, GLOBAL_PROC_REF(cmp_text_asc))
+ if(named_arguments)
+ sortTim(named_arguments, GLOBAL_PROC_REF(cmp_text_asc))
fullid += named_arguments
return list2params(fullid)
diff --git a/code/datums/datum.dm b/code/datums/datum.dm
index 8e02f9c19181..320a814601d9 100644
--- a/code/datums/datum.dm
+++ b/code/datums/datum.dm
@@ -329,7 +329,7 @@
ASSERT(isatom(src) || isimage(src))
var/atom/atom_cast = src // filters only work with images or atoms.
atom_cast.filters = null
- filter_data = sortTim(filter_data, GLOBAL_PROC_REF(cmp_filter_data_priority), TRUE)
+ sortTim(filter_data, GLOBAL_PROC_REF(cmp_filter_data_priority), TRUE)
for(var/filter_raw in filter_data)
var/list/data = filter_data[filter_raw]
var/list/arguments = data.Copy()
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index f9e7202ba37c..e4c0431ea003 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -910,7 +910,7 @@
var/list/sorted = list()
for (var/source in per_source)
sorted += list(list("source" = source, "count" = per_source[source]))
- sorted = sortTim(sorted, GLOBAL_PROC_REF(cmp_timer_data))
+ sortTim(sorted, GLOBAL_PROC_REF(cmp_timer_data))
// Now that everything is sorted, compile them into an HTML output
var/output = ""
diff --git a/code/modules/antagonists/malf_ai/malf_ai_module_picker.dm b/code/modules/antagonists/malf_ai/malf_ai_module_picker.dm
index 51058f82ac02..0ac27c14c97b 100644
--- a/code/modules/antagonists/malf_ai/malf_ai_module_picker.dm
+++ b/code/modules/antagonists/malf_ai/malf_ai_module_picker.dm
@@ -24,7 +24,7 @@
filtered_modules[AM.category][AM] = AM
for(var/category in filtered_modules)
- filtered_modules[category] = sortTim(filtered_modules[category], GLOBAL_PROC_REF(cmp_malfmodules_priority))
+ sortTim(filtered_modules[category], GLOBAL_PROC_REF(cmp_malfmodules_priority))
return filtered_modules
diff --git a/code/modules/antagonists/pirate/pirate.dm b/code/modules/antagonists/pirate/pirate.dm
index 8812de960ddd..5894b881f05d 100644
--- a/code/modules/antagonists/pirate/pirate.dm
+++ b/code/modules/antagonists/pirate/pirate.dm
@@ -86,7 +86,7 @@
//Lists notable loot.
if(!cargo_hold || !cargo_hold.total_report)
return "Nothing"
- cargo_hold.total_report.total_value = sortTim(cargo_hold.total_report.total_value, cmp = GLOBAL_PROC_REF(cmp_numeric_dsc), associative = TRUE)
+ sortTim(cargo_hold.total_report.total_value, cmp = GLOBAL_PROC_REF(cmp_numeric_dsc), associative = TRUE)
var/count = 0
var/list/loot_texts = list()
for(var/datum/export/E in cargo_hold.total_report.total_value)
diff --git a/code/modules/asset_cache/assets/uplink.dm b/code/modules/asset_cache/assets/uplink.dm
index e283b86c0429..e85ee1b35b5c 100644
--- a/code/modules/asset_cache/assets/uplink.dm
+++ b/code/modules/asset_cache/assets/uplink.dm
@@ -9,7 +9,7 @@
var/list/items = list()
for(var/datum/uplink_category/category as anything in subtypesof(/datum/uplink_category))
categories += category
- categories = sortTim(categories, GLOBAL_PROC_REF(cmp_uplink_category_desc))
+ sortTim(categories, GLOBAL_PROC_REF(cmp_uplink_category_desc))
var/list/new_categories = list()
for(var/datum/uplink_category/category as anything in categories)
diff --git a/code/modules/modular_computers/file_system/programs/emojipedia.dm b/code/modules/modular_computers/file_system/programs/emojipedia.dm
index 93c59aef7ca4..e50a9c931cee 100644
--- a/code/modules/modular_computers/file_system/programs/emojipedia.dm
+++ b/code/modules/modular_computers/file_system/programs/emojipedia.dm
@@ -14,7 +14,7 @@
/datum/computer_file/program/emojipedia/New()
. = ..()
// Sort the emoji list so it's easier to find things and we don't have to keep sorting on ui_data since the number of emojis can not change in-game.
- emoji_list = sortTim(emoji_list, /proc/cmp_text_asc)
+ sortTim(emoji_list, /proc/cmp_text_asc)
/datum/computer_file/program/emojipedia/ui_static_data(mob_user)
var/list/data = list()
diff --git a/code/modules/research/stock_parts.dm b/code/modules/research/stock_parts.dm
index 7f14aa37ec00..ac5c2eb3f79d 100644
--- a/code/modules/research/stock_parts.dm
+++ b/code/modules/research/stock_parts.dm
@@ -228,7 +228,7 @@ If you create T5+ please take a pass at mech_fabricator.dm. The parts being good
continue
part_list += component_part
//Sort the parts. This ensures that higher tier items are applied first.
- part_list = sortTim(part_list, GLOBAL_PROC_REF(cmp_rped_sort))
+ sortTim(part_list, GLOBAL_PROC_REF(cmp_rped_sort))
return part_list
/proc/cmp_rped_sort(obj/item/first_item, obj/item/second_item)
diff --git a/code/modules/unit_tests/unit_test.dm b/code/modules/unit_tests/unit_test.dm
index e3446e24618a..992a5b8d0c3e 100644
--- a/code/modules/unit_tests/unit_test.dm
+++ b/code/modules/unit_tests/unit_test.dm
@@ -348,7 +348,7 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests())
if(length(focused_tests))
tests_to_run = focused_tests
- tests_to_run = sortTim(tests_to_run, GLOBAL_PROC_REF(cmp_unit_test_priority))
+ sortTim(tests_to_run, GLOBAL_PROC_REF(cmp_unit_test_priority))
var/list/test_results = list()
diff --git a/tgstation.dme b/tgstation.dme
index 9f12f9af55c1..faa01b3f1cdf 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -593,10 +593,8 @@
#include "code\__HELPERS\paths\jps.dm"
#include "code\__HELPERS\paths\path.dm"
#include "code\__HELPERS\paths\sssp.dm"
-#include "code\__HELPERS\sorts\__main.dm"
-#include "code\__HELPERS\sorts\InsertSort.dm"
-#include "code\__HELPERS\sorts\MergeSort.dm"
-#include "code\__HELPERS\sorts\TimSort.dm"
+#include "code\__HELPERS\sorts\helpers.dm"
+#include "code\__HELPERS\sorts\sort_instance.dm"
#include "code\__HELPERS\~monkestation-helpers\announcements.dm"
#include "code\__HELPERS\~monkestation-helpers\antags.dm"
#include "code\__HELPERS\~monkestation-helpers\atoms.dm"