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">struct PositType3{T<:Integer}
<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
end

""" From posithub.org/docs/Posits4.pdf """
""" 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 # shift off signbit (adds a 0 to F at LSB)
pabs = p.bits << 1 # Shift off signbit (adds a 0 to F at LSB)
pabs == 0 && return s ? 1 // 0 : 0 // 1 # if p is 0, return 0 or if s 1 error
pabs == 0 && return s ? 1 // 0 : 0 // 1 # If p is 0, return 0 or if s 1 error
expsign = signbit(signed(pabs)) # exponent sign from 2nd bit now MSB
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) # shift off unwanted R bits
pabs <<= (r + 1) # Shift off unwanted R bits
pabs >>= (r + 2) # shift back for E, F
pabs >>= (r + 2) # Shift back for E, F
fsize = p.numbits - 1 - r - 1 - p.es # check how many F bits explicit
fsize = p.numbits - 1 - r - 1 - p.es # Check how many F bits explicit
f = fsize < 1 ? 1 :
e = fsize < 1 ? pabs : pabs >> fsize # Get E value
1 + (pabs & (2^fsize-1)) // 2^fsize # Get F value. Can be missing -> 1
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 => -363//4096 = -0.088623046875
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>