Description
The spec describes sort_asc and sort_desc as sorting "in place" for a comparable T, and is_sorted as true when each element is <= the next. They work for int, i64, u64, uint, float, byte, char and string. They do not work for the other sized numeric types.
The codegen dispatch for sort_asc/sort_desc (codegen.c, near the gray_arrays_sort_* emit) only has variants for float, string, byte, char, wide ints and enums. Every other element type falls through to the int64 variant, which calls qsort with cmp_i64_asc. That comparator reads 8 bytes at each element pointer, but the elements of these arrays are 1, 2 or 4 bytes wide (the runtime already has cmp_u8 and cmp_i32 comparators, and none for i8, i16, u16, u32 or f32). The comparison is made on 8 bytes of unrelated neighbouring elements, so the result is an arbitrary permutation. For the last elements it also reads up to 7 bytes past the end of the array. is_sorted gets the same wrong answer, so is_sorted reports false for an array that is already sorted.
The elements are moved as whole elements, so no values are lost or changed. They just end up in the wrong order.
Expected
The array is sorted ascending (sort_asc) or descending (sort_desc), and is_sorted returns true for an ascending array.
Actual
| Call |
Result |
mut a [i32] = {5, 3, 9, 1}; arrays.sort_asc(a) |
a is {9, 5, 1, 3} |
mut a [i8] = {94, 15, 26, -70, -66, -84, 45, 95, -35}; arrays.sort_desc(a) |
{-66, 26, 15, -70, 94, -84, 45, 95, -35} |
mut b [u8] = {5, 3, 9, 1}; arrays.sort_desc(b) |
unchanged: {5, 3, 9, 1} |
sort_asc / sort_desc on nine random values in [i16], [u16], [u32], [f32] |
not sorted in either direction |
arrays.is_sorted(a) where a is the ascending [i32] {-50000, 1, 2, 90000} |
false |
same for [i8], [i16], [u8], [u16], [u32], [f32] |
false |
same calls on [i64], [uint], [u64], [float], [byte], [char], [string] |
correct |
arrays.binary_search, min_index, max_index, index_of and count give the right answers on these sized arrays.
Minimal reproduction
import @arrays
do main() {
mut a [i32] = {5, 3, 9, 1}
arrays.sort_asc(a)
println(a)
println(arrays.is_sorted(a))
}
Prints {9, 5, 1, 3} and false. Expected: {1, 3, 5, 9} and true.
import @arrays
do main() {
mut a [u8] = {1, 2, 3, 200}
println(arrays.is_sorted(a))
}
Prints false. Expected: true.
Description
The spec describes
sort_ascandsort_descas sorting "in place" for a comparableT, andis_sortedas true when each element is<=the next. They work forint,i64,u64,uint,float,byte,charandstring. They do not work for the other sized numeric types.The codegen dispatch for
sort_asc/sort_desc(codegen.c, near thegray_arrays_sort_*emit) only has variants for float, string, byte, char, wide ints and enums. Every other element type falls through to theint64variant, which callsqsortwithcmp_i64_asc. That comparator reads 8 bytes at each element pointer, but the elements of these arrays are 1, 2 or 4 bytes wide (the runtime already hascmp_u8andcmp_i32comparators, and none for i8, i16, u16, u32 or f32). The comparison is made on 8 bytes of unrelated neighbouring elements, so the result is an arbitrary permutation. For the last elements it also reads up to 7 bytes past the end of the array.is_sortedgets the same wrong answer, sois_sortedreportsfalsefor an array that is already sorted.The elements are moved as whole elements, so no values are lost or changed. They just end up in the wrong order.
Expected
The array is sorted ascending (
sort_asc) or descending (sort_desc), andis_sortedreturnstruefor an ascending array.Actual
mut a [i32] = {5, 3, 9, 1};arrays.sort_asc(a)ais{9, 5, 1, 3}mut a [i8] = {94, 15, 26, -70, -66, -84, 45, 95, -35};arrays.sort_desc(a){-66, 26, 15, -70, 94, -84, 45, 95, -35}mut b [u8] = {5, 3, 9, 1};arrays.sort_desc(b){5, 3, 9, 1}sort_asc/sort_descon nine random values in[i16],[u16],[u32],[f32]arrays.is_sorted(a)whereais the ascending[i32]{-50000, 1, 2, 90000}false[i8],[i16],[u8],[u16],[u32],[f32]false[i64],[uint],[u64],[float],[byte],[char],[string]arrays.binary_search,min_index,max_index,index_ofandcountgive the right answers on these sized arrays.Minimal reproduction
Prints
{9, 5, 1, 3}andfalse. Expected:{1, 3, 5, 9}andtrue.Prints
false. Expected:true.