Posit numbers/decoding
Posit numbers/decoding is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Posit is a quantization of the real projective line proposed by John Gustafson in 2015. It is claimed to be an improvement over IEEE 754.
The purpose of this task is to write a program capable of decoding a posit number. You will use the example provided by Gustafson in his paper : 0b0000110111011101, representing a 16-bit long real number with three bits for the exponent. Once decoded, you should obtain either the fraction 477/134217728 or the floating point value 3.55393E−6.
raku
unit role Posit[UInt $nbits, UInt $es];
has Bool @.bits[$nbits];
method Str { sprintf('%0b' x $nbits, @!bits) }
sub useed { 2**(2**$es) }
sub two-complement(Str $n where /^<[01]>+$/) {
(
(
$n
.trans("01" => "10")
.parse-base(2)
+ 1
) +& (2**$n.chars - 1)
).polymod(2 xx $n.chars - 1)
.reverse
.join
}
method Real {
return 0 unless @!bits.any;
return Inf if self ~~ /^10*$/;
my $sign = @!bits.head ?? -1 !! +1;
$sign *
grammar {
token TOP { ^ <regime> <exponent>? <fraction>? $ }
token regime { [ 1+ 0? ] | [ 0+ 1? ] }
token exponent { <.bit> ** {1..$es} }
token fraction { <.bit>+ }
token bit { <[01]> }
}.parse(
($sign > 0 ?? {$_} !! &two-complement)(self.Str.substr(1)),
actions => class {
method TOP($/) {
make $<regime>.made *
($<exponent> ?? $<exponent>.made !! 1) *
($<fraction> ?? $<fraction>.made !! 1);
}
method regime($/) {
my $first-bit = $/.Str.substr(0,1);
my $m = $/.comb.Bag{$first-bit};
make useed**($first-bit eq '1' ?? $m - 1 !! -$m);
}
method exponent($/) { make 2**($/.Str.parse-base: 2); }
method fraction($/) {
make reduce { $^a + $^b / ($*=2.FatRat) }, 1, |$/.comb;
}
}
)
.made
}
CHECK {
use Test;
# example from L<http://www.johngustafson.net/pdfs/BeatingFloatingPoint.pdf>
is Posit[16, 3]
.new(bits => '0000110111011101'.comb.map({.Int.Bool})).Real.nude,
(477, 134217728);
}
- Output:
ok 1 -