Skip to content

Instantly share code, notes, and snippets.

@thehans
Last active January 6, 2021 05:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thehans/ac6770127291416425d74f771ed073b0 to your computer and use it in GitHub Desktop.
Save thehans/ac6770127291416425d74f771ed073b0 to your computer and use it in GitHub Desktop.
OpenSCAD radix sort implementation
// LSD Radix sort (stable)
// base: should be a power of two, otherwise exit condition (d==m) might not be reached.
// key: 3 possible types
// - number (vector index into each element)
// - function (takes element and returns the key value)
// - undef (elements are used directly as the key)
// key values need not be integers, but will be treated as integers via floor()
// e.g. [1.5, 1, 1.2] is considered sorted since they are all same key after floor
function radix_sort(v,base=4,key) = key==undef ?
_rs(v,1,pow(base,-floor(log(max(v))/log(base))),base) :
is_num(key) ?
_rski(v,1,pow(base,-floor(log(max([for(x=v) v[key]]))/log(base))),base,key) :
is_function(key) ?
_rskf(v,1,pow(base,-floor(log(max([for(x=v) key(x)]))/log(base))),base,key) :
assert(false, "\"key\" argument must be either undef, number (index), or function");
// v: vector to stable sort
// d: inverse of the current digit
// m: inverse of the max digit
// r: radix (base)
// k: key(index or function)
function _rs(v,d,m,r) = let( // element == key
kvps = [for(x=v) [floor(x*d)%r,x]],
v = [for(i=[0:1:r-1],x=kvps) if(x[0]==i) x[1]]
) d==m ? v : _rs(v,d/r,m,r);
function _rski(v,d,m,r,k) = let( // indexed key
kvps = [for(x=v) [floor(x[k]*d)%r,x]],
v = [for(i=[0:1:r-1],x=kvps) if(x[0]==i) x[1]]
) d==m ? v : _rski(v,d/r,m,r,k);
function _rskf(v,d,m,r,k) = let( // function returns key
kvps = [for(x=v) [floor(k(x)*d)%r,x]],
v = [for(i=[0:1:r-1],x=kvps) if(x[0]==i) x[1]]
) d==m ? v : _rskf(v,d/r,m,r,k);
seed = 0;
v = [for(x=rands(0,pow(2,32),1e5,seed)) floor(x)];
sorted = radix_sort(v,base=4);
// function-literal key can be used to scale float values for more accurate sorting
//v = rands(0,pow(2,16),1e5,seed);
//sorted = radix_sort(v, key=function(x)x*65536);
echo(len(v));
echo(len(sorted));
//echo(sorted);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment