Posit numbers/decoding: Difference between revisions
Content added Content deleted
(→{{header|Wren}}: Rewritten to deal with posit numbers of any size.) |
m (→{{header|Julia}}: add 2's complement handling for negatives) |
||
Line 14: | Line 14: | ||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
<syntaxhighlight lang="julia"> |
<syntaxhighlight lang="julia">""" Posit number, a quotient of integers, variable size and exponent length """ |
||
struct PositType3{T<:Integer} |
|||
numbits::UInt16 |
numbits::UInt16 |
||
es::UInt16 |
es::UInt16 |
||
bits::T |
bits::T |
||
PositType3(nb, ne, i) = new{typeof(i)}(UInt16(nb), UInt16(ne), i) |
PositType3(nb, ne, i) = new{typeof(i)}(UInt16(nb), UInt16(ne), i) |
||
end |
|||
""" |
""" Convert PositType3 to Rational. See also posithub.org/docs/Posits4.pdf """ |
||
function Base.Rational(p::PositType3) |
function Base.Rational(p::PositType3) |
||
s = signbit(signed(p.bits)) # s for S signbit, is 1 if negative |
s = signbit(signed(p.bits)) # s for S signbit, is 1 if negative |
||
pabs = p.bits << 1 # |
pabs = p.bits << 1 # Shift off signbit (adds a 0 to F at LSB) |
||
pabs == 0 && return s ? 1 // 0 : 0 // 1 # |
pabs == 0 && return s ? 1 // 0 : 0 // 1 # If p is 0, return 0 or if s 1 error |
||
s && (pabs = (-p.bits) << 1) # If p is negative, flip to 2's complement |
|||
expsign = signbit(signed(pabs)) # Exponent sign from 2nd bit now MSB |
|||
r = expsign == 1 ? leading_ones(pabs) : leading_zeros(pabs) # r regime R size |
r = expsign == 1 ? leading_ones(pabs) : leading_zeros(pabs) # r regime R size |
||
k = expsign ? r - 1 : -r # k for the exponent calculation |
k = expsign ? r - 1 : -r # k for the exponent calculation |
||
pabs <<= (r + 1) # |
pabs <<= (r + 1) # Shift off unwanted R bits |
||
pabs >>= (r + 2) # |
pabs >>= (r + 2) # Shift back for E, F |
||
fsize = p.numbits - 1 - r - 1 - p.es # |
fsize = p.numbits - 1 - r - 1 - p.es # Check how many F bits explicit |
||
e = fsize < 1 ? pabs : pabs >> fsize # Get E value |
|||
1 + (pabs & (2^fsize-1)) // 2^fsize |
f = fsize < 1 ? 1 : 1 + (pabs & (2^fsize - 1)) // 2^fsize # Get F value (1 by default) |
||
e = fsize < 1 ? pabs : pabs >> fsize # Get E value. |
|||
pw = 2^p.es * k + e |
pw = 2^p.es * k + e |
||
return pw >= 0 ? (-1)^s * f * big"2"^pw // 1 : (-1)^s * f // big"2"^(-pw) |
return pw >= 0 ? (-1)^s * f * big"2"^pw // 1 : (-1)^s * f // big"2"^(-pw) |
||
end |
end |
||
@show Rational(PositType3(16, 3, 0b0000110111011101)) == 477 // 134217728 |
@show Rational(PositType3(16, 3, 0b0000110111011101)) == 477 // 134217728 |
||
const tests = [ |
const tests = [ |
||
(16,3,0b0000110111011101), |
(16, 3, 0b0000110111011101), |
||
(16,3,0b1000000000000000), |
(16, 3, 0b1000000000000000), |
||
(16,3,0b0000000000000000), |
(16, 3, 0b0000000000000000), |
||
(16,1,0b0110110010101000), |
(16, 1, 0b0110110010101000), |
||
(16,1,0b1001001101011000), |
(16, 1, 0b1001001101011000), |
||
(16,2,0b0000000000000001), |
(16, 2, 0b0000000000000001), |
||
(16,0,0b0111111111111111), |
(16, 0, 0b0111111111111111), |
||
(16,6,0b0111111111111110), |
(16, 6, 0b0111111111111110), |
||
(8,1,0b01000000), |
(8, 1, 0b01000000), |
||
(8,1,0b11000000), |
(8, 1, 0b11000000), |
||
(8,1,0b00110000), |
(8, 1, 0b00110000), |
||
(8,1,0b00100000), |
(8, 1, 0b00100000), |
||
(8,2,0b00000001), |
(8, 2, 0b00000001), |
||
(8,2,0b01111111), |
(8, 2, 0b01111111), |
||
(8,7,0b01111110), |
(8, 7, 0b01111110), |
||
(32,2,0b00000000000000000000000000000001), |
(32, 2, 0b00000000000000000000000000000001), |
||
(32,2,0b01111111111111111111111111111111), |
(32, 2, 0b01111111111111111111111111111111), |
||
(32,5,0b01111111111111111111111111111110), |
(32, 5, 0b01111111111111111111111111111110), |
||
] |
] |
||
for t in tests |
for t in tests |
||
r = Rational(PositType3(t...)) |
r = Rational(PositType3(t...)) |
||
println(string(t[3], base=2, pad = t[1]), " => $r = ", float(r)) |
println(string(t[3], base = 2, pad = t[1]), " => $r = ", float(r)) |
||
end |
end |
||
</syntaxhighlight>{{out}} |
</syntaxhighlight>{{out}} |
||
Line 72: | Line 73: | ||
0000000000000000 => 0//1 = 0.0 |
0000000000000000 => 0//1 = 0.0 |
||
0110110010101000 => 405//32 = 12.65625 |
0110110010101000 => 405//32 = 12.65625 |
||
1001001101011000 => - |
1001001101011000 => -405//32 = -12.65625 |
||
0000000000000001 => 1//72057594037927936 = 1.387778780781445675529539585113525390625e-17 |
0000000000000001 => 1//72057594037927936 = 1.387778780781445675529539585113525390625e-17 |
||
0111111111111111 => 16384//1 = 16384.0 |
0111111111111111 => 16384//1 = 16384.0 |
||
Line 83: | Line 84: | ||
01111111 => 16777216//1 = 1.6777216e+07 |
01111111 => 16777216//1 = 1.6777216e+07 |
||
01111110 => 4562440617622195218641171605700291324893228507248559930579192517899275167208677386505912811317371399778642309573594407310688704721375437998252661319722214188251994674360264950082874192246603776//1 = 4.562440617622195218641171605700291324893228507248559930579192517899275167208677e+192 |
01111110 => 4562440617622195218641171605700291324893228507248559930579192517899275167208677386505912811317371399778642309573594407310688704721375437998252661319722214188251994674360264950082874192246603776//1 = 4.562440617622195218641171605700291324893228507248559930579192517899275167208677e+192 |
||
00000000000000000000000000000001 => 1//1329227995784915872903807060280344576 = 7.523163845262640050999913838222372338039459563341360137656010920181870460510254e-37 |
00000000000000000000000000000001 => 1//1329227995784915872903807060280344576 = 7.523163845262640050999913838222372338039459563341360137656010920181870460510254e-37 |
||
01111111111111111111111111111111 => 1329227995784915872903807060280344576//1 = 1.329227995784915872903807060280344576e+36 |
01111111111111111111111111111111 => 1329227995784915872903807060280344576//1 = 1.329227995784915872903807060280344576e+36 |
||
01111111111111111111111111111110 => 2269007733883335972287082669296112915239349672942191252221331572442536403137824056312817862695551072066953619064625508194663368599769448406663254670871573830845597595897613333042429214224697474472410882236254024057110212260250671521235807709272244389361641091086035023229622419456//1 = 2.269007733883335972287082669296112915239349672942191252221331572442536403137824e+279 |
01111111111111111111111111111110 => 2269007733883335972287082669296112915239349672942191252221331572442536403137824056312817862695551072066953619064625508194663368599769448406663254670871573830845597595897613333042429214224697474472410882236254024057110212260250671521235807709272244389361641091086035023229622419456//1 = 2.269007733883335972287082669296112915239349672942191252221331572442536403137824e+279 |
||
</pre> |
</pre> |
||