I agree but a recent spat proved how fruitless it is... if the man don't want to implement it... it won't get implemented. Case in point: I never envisaged myself having to code IEEE number schemes but one miserable afternoon a few weeks ago I needed *two* doubles for an opengl call. Could have waited until today but now glad I didn't
Here's the code, done in such a way that I could check the results. Sad considering the IEEE spec has to be maybe 40 or 50 years old and there exists many free maths libs that could be plugged in to PB with little effort.
Code: Select all
; ====================================================================
;
;The format for single precision numbers uses 32 bits divided in the following way,
;
; seeeeeeeefffffffffffffffffffffff
;
; s = sign bit, 1 bit
; e = exponent, 8 bits (E_min=-126, E_max=127, bias=127)
; f = fraction, 23 bits
;
;The format for double precision numbers uses 64 bits divided in the following way,
;
; seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
;
; s = sign bit, 1 bit
; e = exponent, 11 bits (E_min=-1022, E_max=1023, bias=1023)
; f = fraction, 52 bits
;
Structure d
l.l
h.f
EndStructure
Procedure.s f2bs(f.f, n.l)
bs_i.s ; Binary String - Integer Part
bs_f.s ; Binary String - Fraction
bs_s.s ; Binary String - Sign
bs_e.s ; Binary String - Exponent
bs_m.s ; Binary String - Mantissa
Select n
Case 8
fbce = 3
fbcm = 4
Case 32
fbce = 8
fbcm = 23
Case 64
fbce = 11
fbcm = 52
Default
Debug "Unsupported FP: "+Str(n)
EndSelect
bias = Pow(2,fbce-1)-1
; Sign
;
If f<0
bs_s = "1"
Else
bs_s = "0"
EndIf
f2.f = Abs(f)
; Integral Part
;
ip.l = Int(f2)
; Fractional Part
;
fp.f = f2-ip
bs_f = ""
For n=1 To fbcm+2
tf.f = fp * 2
ti = Int(tf)
fp = tf-ti
bs_f = bs_f + Str(ti)
Next
e = 0
If ip=0
If bs_f <> Left("000000000000", fbcm)
While Left(bs_f,1)="0"
bs_f = Right(bs_f, Len(bs_f)-1)+"0"
e-1
Wend
bs_f = Right(bs_f, Len(bs_f)-1)+"0"
e-1
EndIf
Else
bs_i = Bin(ip)
bs_f = Right(bs_i, Len(bs_i)-1) + bs_f
e = Len(bs_i)-1
EndIf
bs_m = Left(bs_f, fbcm)
If Len(bs_m)<fbcm: bs_m = bs_m + Left("000000000000", fbcm-Len(bs_m)): EndIf
eb = e + bias ; add bias for 8 bit float
bs_e = Right(Bin(eb), fbce)
If Len(bs_e)<fbce: bs_e = Left("000000000000", fbce-Len(bs_e)) + bs_e: EndIf
; Debug StrF(f) + " = " + bs_s + ":" + bs_e + "." + bs_m; + " eb:" + Str(eb)
ProcedureReturn bs_s + bs_e + bs_m
EndProcedure
Procedure.s bs2d(bs.s, da.l) ; Length must be 64 bits = 8 bytes = 2 longs
bn=0
For bn=7 To 0 Step -1
n.s = Left(bs,8)
bs = Right(bs, Len(bs)-8)
t.b = 0
If Mid(n,1,1)="1": t=t+128: EndIf
If Mid(n,2,1)="1": t=t+ 64: EndIf
If Mid(n,3,1)="1": t=t+ 32: EndIf
If Mid(n,4,1)="1": t=t+ 16: EndIf
If Mid(n,5,1)="1": t=t+ 8: EndIf
If Mid(n,6,1)="1": t=t+ 4: EndIf
If Mid(n,7,1)="1": t=t+ 2: EndIf
If Mid(n,8,1)="1": t=t+ 1: EndIf
;Debug t & $FF
PokeB(da+bn, t & $FF)
;Debug StrU(PeekB(da+bn),#byte)
Next
EndProcedure
Procedure f2d(f.f, da.l)
bs2d(f2bs(f, 64), da)
EndProcedure
;==========================================================================
Procedure.s bs2h(bs.s) ; Length must be multiple of 4
h.s = ""
While bs<>""
n.s = Left(bs,4)
bs = Right(bs, Len(bs)-4)
t = 0
If Mid(n,1,1)="1": t=t+8: EndIf
If Mid(n,2,1)="1": t=t+4: EndIf
If Mid(n,3,1)="1": t=t+2: EndIf
If Mid(n,4,1)="1": t=t+1: EndIf
h = h + Hex(t)
Wend
ProcedureReturn h
EndProcedure
Procedure.s HexBU(ba)
hb.s = Hex(Val(StrU(PeekB(ba),#byte)))
If Len(hb)=1: hb="0"+hb: EndIf
ProcedureReturn hb
EndProcedure
;==========================================================================
;d2f(2.625, 8)
;d2f(-4.75, 8)
;d2f(0.40625, 8)
;d2f(-12, 8)
;d2f(1.7, 8)
;d2f(-113.3125, 32)
;bs1.s = f2bs( 0.25, 64)
;bs2.s = f2bs(256.0, 64)
;Debug bs2h(bs1)
;Debug bs2h(bs2)
;bs2d(bs1, @d.d)
f2d(0.25, @d.d)
Debug HexBU(@d+7)+HexBU(@d+6)+HexBU(@d+5)+HexBU(@d+4)+HexBU(@d+3)+HexBU(@d+2)+HexBU(@d+1)+HexBU(@d)