Home

Awesome

Intro

This document describes a partitioning stable adaptive comparison-based sort named gridsort.

Binary Cube

Gridsort sorts data by storing data in a simplified binary cube, a multidimentional sorted array. The binary cube offers excellent cache utilization. It's easiest to view a binary cube as a hash table, but instead of a hash function to find a bucket it uses a binary search on a lookup table.

Boundless Binary Search

The first step when sorting an element is a boundless binary search to pin point the bucket where the element should be stored. A boundless binary search is up to two times faster than the legacy binary search used by most applications. Once a bucket is found the element is added to the end of the bucket.

Gridsort switches to an adaptive binary search when it detects data that is already sorted.

Quadsort

Once a bucket overflows it is sorted using quadsort and a new bucket is created. The sorted data is split between the two buckets so each bucket is half full. The lowest element in each bucket is added to the lookup table.

Finish

Once all elements have been inserted into the binary cube every bucket receives a final sort and is copied back to the original array.

Memory

Gridsort allocates 2 * sqrt(n) blocks of memory of sqrt(n) size.

Data Types

The C implementation of gridsort supports long doubles and 8, 16, 32, and 64 bit data types. By using pointers it's possible to sort any other data type.

Interface

Gridsort uses the same interface as qsort, which is described in man qsort.

Big O

                 ┌───────────────────────┐┌───────────────────────┐
                 │comparisons            ││swap memory            │
┌───────────────┐├───────┬───────┬───────┤├───────┬───────┬───────┤┌──────┐┌─────────┐┌─────────┐
│name           ││min    │avg    │max    ││min    │avg    │max    ││stable││partition││adaptive │
├───────────────┤├───────┼───────┼───────┤├───────┼───────┼───────┤├──────┤├─────────┤├─────────┤
│gridsort       ││n      │n log n│n log n││n      │n      │n      ││yes   ││yes      ││yes      │
├───────────────┤├───────┼───────┼───────┤├───────┼───────┼───────┤├──────┤├─────────┤├─────────┤
│mergesort      ││n log n│n log n│n log n││n      │n      │n      ││yes   ││no       ││no       │
├───────────────┤├───────┼───────┼───────┤├───────┼───────┼───────┤├──────┤├─────────┤├─────────┤
│quadsort       ││n      │n log n│n log n││1      │n      │n      ││yes   ││no       ││yes      │
├───────────────┤├───────┼───────┼───────┤├───────┼───────┼───────┤├──────┤├─────────┤├─────────┤
│quicksort      ││n      │n log n│n²     ││1      │1      │1      ││no    ││yes      ││no       │
├───────────────┤├───────┼───────┼───────┤├───────┼───────┼───────┤├──────┤├─────────┤├─────────┤
│introsort      ││n log n│n log n│n log n││1      │1      │1      ││no    ││yes      ││no       │
└───────────────┘└───────┴───────┴───────┘└───────┴───────┴───────┘└──────┘└─────────┘└─────────┘

Gridsort makes n comparisons when the data is fully in order or in reverse order.

Porting

People wanting to port gridsort might want to have a look at twinsort, which is a simplified implementation of quadsort. Gridsort itself is a simplified implementation of cubesort. Another sort worth looking at is fluxsort which uses simpler top-down partitioning instead of gridsort's bottom-up partitioning.

Visualization

In the visualization below eight tests are performed. Random, Ascending, Ascending Saw, Generic, Descending, Descending Saw, Random Tail, and Wave order.

cubesort visualization

In the visualization below one test is performed on a random distribution. This visualization more accurately shows the use of pointer operations to partition memory.

Cyan numbers are unsorted, green numbers are sorted, white numbers are sorted and ready to be merged, yellow numbers are the index upon which a binary search is performed to find out where to insert the next number, magenta numbers are ready to be merged back to the main array.

gridsort visualization

Benchmarks

The following benchmark was on WSL gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) using the wolfsort benchmark. The source code was compiled using g++ -O3 -w -fpermissive bench.c. The bar graph shows the best run out of 10 on 32 bit integers. Comparisons for gridsort and std::stable_sort are inlined.

gridsort vs stdsort

<details><summary>data table</summary>
NameItemsTypeBestAverageLoopsSamplesDistribution
stablesort10000001280.1410870.142480110random order
gridsort10000001280.1017850.103576110random order
NameItemsTypeBestAverageLoopsSamplesDistribution
stablesort1000000640.0768950.077535110random order
gridsort1000000640.0513160.051824110random order
NameItemsTypeBestAverageLoopsSamplesDistribution
stablesort1000000320.0728910.073191110random order
gridsort1000000320.0508910.051147110random order
stablesort1000000320.0106080.010848110ascending order
gridsort1000000320.0032870.003543110ascending order
stablesort1000000320.0174880.017697110ascending saw
gridsort1000000320.0120150.012160110ascending saw
stablesort1000000320.0415840.041741110generic order
gridsort1000000320.0158090.016224110generic order
stablesort1000000320.0106410.010863110descending order
gridsort1000000320.0035770.003620110descending order
stablesort1000000320.0142600.014466110descending saw
gridsort1000000320.0098780.010047110descending saw
stablesort1000000320.0263430.026791110random tail
gridsort1000000320.0153110.015351110random tail
stablesort1000000320.0435290.043730110random half
gridsort1000000320.0282330.028463110random half
stablesort1000000320.0138240.013961110ascending tiles
gridsort1000000320.0122870.012459110ascending tiles
</details>

The following benchmark was on WSL gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1). The source code was compiled using gcc -O3 bench.c. The bar graph shows the best run out of 100 on 32 bit integers. Comparisons for gridsort and qsort are not inlined. The stdlib qsort() in the benchmark is a mergesort variant.

gridsort vs stdsort

<details><summary>data table</summary>
NameItemsTypeBestAverageComparesSamplesDistribution
qsort1000001280.0191170.0199961536181100random order
gridsort1000001280.0126860.0127301639247100random order
NameItemsTypeBestAverageComparesSamplesDistribution
qsort100000320.0084650.0085801536634100random order
gridsort100000320.0060450.0061351643169100random order
qsort100000320.0020190.002113815024100ascending order
gridsort100000320.0006560.000669202740100ascending order
qsort100000320.0028180.002827915019100ascending saw
gridsort100000320.0019760.001994582000100ascending saw
qsort100000320.0064020.0065451532339100generic order
gridsort100000320.0027930.0029481146648100generic order
qsort100000320.0024500.002566853904100descending order
gridsort100000320.0006610.000668200034100descending order
qsort100000320.0028270.0029411063907100descending saw
gridsort100000320.0016660.001737771299100descending saw
qsort100000320.0037340.0039431012028100random tail
gridsort100000320.0020570.002142625065100random tail
qsort100000320.0054420.0055951200835100random half
gridsort100000320.0035110.003573998798100random half
qsort100000320.0040800.0041791209200100ascending tiles
gridsort100000320.0031890.003343868332100ascending tiles
</details>