Skip to content

Instantly share code, notes, and snippets.

@grondilu
Last active September 20, 2023 13:39
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 grondilu/ae982d181e9fe86baac2fb61cd88d65c to your computer and use it in GitHub Desktop.
Save grondilu/ae982d181e9fe86baac2fb61cd88d65c to your computer and use it in GitHub Desktop.
Rice coding in raku
unit module Rice;
# L<https://en.wikipedia.org/wiki/Golomb_coding>
our sub encode(Int $n, UInt :$k = 2) {
my $d = 2**$k;
my $q = $n div $d;
my $b = sign(1 + sign($q));
my $m = abs($q) + $b;
flat
$b xx $m, 1 - $b,
($n mod $d).polymod(2 xx $k - 1).reverse
}
our proto decode(|) returns Int {*}
multi decode(Channel $c, UInt :$k = 2) {
my $d = 2**$k;
my $b = $c.receive;
my $m = 1;
$m++ while $c.receive == $b;
my $q = $b ?? $m - 1 !! -$m;
$q*$d + ($c.receive xx $k).reduce(2 * * + *);
}
multi decode(@bits, UInt :$k = 2) {
my Channel $c .= new;
start { $c.send: $_ for @bits }
samewith $c, :$k;
}
CHECK {
use Test;
constant N = 100;
plan 2*N + 1;
is $_, decode encode $_ for -N..N;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment