/zermelo

A radix sorting library for Go (golang)

Primary LanguageGoMIT LicenseMIT

zermelo v2

go.dev reference license Go Report Card

A radix sorting library for Go. Trade memory for speed! Now with more generics!

import "github.com/shawnsmithdev/zermelo/v2"

func foo(large []uint64)
    zermelo.Sort(large)
}

About

Zermelo is a sorting library featuring implementations of radix sort. I am especially influenced here by these two articles that describe various optimizations and how to work around the typical limitations of radix sort.

You will generally only want to use zermelo if you won't mind the extra memory used for buffers and your application frequently sorts slices of supported types with at least 256 elements (128 for 32-bit types, 386 for []float64). The larger the slices you are sorting, the more benefit you will gain by using zermelo instead of the standard library's in-place comparison sort slices.Sort().

Etymology

Zermelo is named after Ernst Zermelo, who developed the proof for the well-ordering theorem.

Supported Types

Sort and NewSorter support integer slices, that is []int, []uint64, []byte, etc, and derived types.

Sorter

A Sorter returned by NewSorter will reuse buffers created during Sort() calls. This is not thread safe. Buffers are grown as needed at a 25% exponential growth rate. This means if you sort a slice of size n, subsequent calls with slices up to n * 1.25 in length will not cause another buffer allocation. This does not apply to the first allocation, which will make a buffer of the same size as the requested slice. This way, if the slices being sorted do not grow in size, there is no unused buffer space.

import "github.com/shawnsmithdev/zermelo/v2"

func foo(bar [][]uint64) {
    sorter := zermelo.NewSorter[uint64]()
    for _, x := range bar {
        sorter.Sort(x)
    }
}

Float Subpackage

SortFloats and FloatSorter provided in the floats subpackage support float slices, specifically []float32 and []float64 and derived types. This uses the unsafe package to treat floats as though they were unsigned integers.

import "github.com/shawnsmithdev/zermelo/v2/floats"

func foo(bar [][]floats64) {
    sorter := floats.NewFloatSorter[float64]()
    for _, x := range bar {
        sorter.Sort(x)
    }
}