This is my Beta version for a Floating point Library.
Floating Point Numbers (FPN) are stored in
- a word variable for Mantissa
- a byte variable for exponent
A normalised positive FPN bit16 is always one (32767<FPN Mantissa<65536)
For the time, negative FPN are not supported.
Due to Picaxe optimisation, FL_JYB is NOT IEEE compliant.
Only for X2 parts.
Actually done :
- FL_Norm : to normalise a FPN
- FLAdd
- FLmulti
- FLdiv
- FLexp
- FLsqrt
- FL_SertxdE10 : to write a FPN
To be done :
- documentation, and speed measurements,
- negative numbers,
- variable usage reduction,
- NANs
- ln
- trigo via CORDIC
For usable code, please look at post #3
Floating Point Numbers (FPN) are stored in
- a word variable for Mantissa
- a byte variable for exponent
A normalised positive FPN bit16 is always one (32767<FPN Mantissa<65536)
For the time, negative FPN are not supported.
Due to Picaxe optimisation, FL_JYB is NOT IEEE compliant.
Only for X2 parts.
Actually done :
- FL_Norm : to normalise a FPN
- FLAdd
- FLmulti
- FLdiv
- FLexp
- FLsqrt
- FL_SertxdE10 : to write a FPN
To be done :
- documentation, and speed measurements,
- negative numbers,
- variable usage reduction,
- NANs
- ln
- trigo via CORDIC
For usable code, please look at post #3
Code:
' FL_JYB_U_sim001
'
' Floating Point Library Unsigned (for simulation)
' V 001
' 14/4/2015
FLsertxd10:
if FL_XE2 >9 and FL_XE2<247 then
FL_TM=FL_XM : FL_TE2=FL_XE2
if FL_XE2>127 then
BT=-FL_XE2
WT=BT*301/1000+1
' sertxd(13,10,"FL_Exp 5 ^",#WT,13,10)
E10=-WT
else
BT=-FL_XE2
WT=FL_XE2*301/1000+1
' sertxd(13,10,"FL_Exp 5 ^-",#WT,13,10)
E10=WT
endif
FL_XM=40960: FL_XE2=-13 ' 5 normalise !
EE=-E10
gosub FLexp
FL_YM=FL_TM : FL_YE2=FL_TE2-E10
gosub FLmulti
else
E10=0
endif
gosub FLdeNorm
return
FLdeNorm:
if FL_XE2=0 then
sertxd (#FL_XM)
gosub FL_SertxdE10
elseif FL_XE2>127 then
FL_XE2=-FL_XE2
BT=16-FL_XE2
WW=10000>>FL_XE2
WT=FL_XM<<BT>>BT
WT=WT*WW
FL_XM=FL_XM>>FL_XE2
sertxd (#FL_XM,".")
select WT
case 0
case <10 : sertxd("000",#WT)
case <100: sertxd("00",#WT)
case <1000:sertxd("0",#WT)
else : sertxd(#WT)
endselect
gosub FL_SertxdE10
FL_XE2=-FL_XE2
else
WT=FL_XM//100<<FL_XE2
WL=WT//100
WT=WT/100
FL_XM=FL_XM/100
WT=FL_XM//100<<FL_XE2+WT
WH=WT//100
WT=WT/100
FL_XM=FL_XM/100<<FL_XE2+WT
if WH<10 then
sertxd (#FL_XM,"0",#WH)
else
sertxd (#FL_XM,#WH)
endif
if WL<10 then
sertxd ("0",#WL)
else
sertxd (#WL)
endif
gosub FL_SertxdE10
endif
return
FL_SertxdE10:
if E10=0 then
elseif E10<128 then
sertxd("*10^",#E10)
else
BT=-E10
sertxd("*10^-",#BT)
endif
return
FL_sertXd:
if FL_XE2<128 then
sertxd (" X=",#FL_XM,"*2^",#FL_XE2)
else
BT=-FL_XE2
sertxd (" X=",#FL_XM,"*2^-",#BT)
endif
return
FL_sertYd:
if FL_YE2<128 then
sertxd (" Y=",#FL_YM,"*2^",#FL_YE2)
else
BT=-FL_YE2
sertxd (" Y=",#FL_YM,"*2^-",#BT)
endif
return
FLexp: 'Effectue X^EE
' X pas forcement norme
If EE = 0 Then
FL_XM=1 : return
ElseIf EE = 1 Then ' answer is X
return
ElseIf EE = 2 Then ' answer is X2
FL_YM=FL_XM : FL_YE2=FL_XE2
gosub FLmulti : return
ElseIf EE >127 Then
' Expon = Expon(1 / X, -Exp)
FL_YM=32768 : FL_YE2=-15 ' Un en decimal
gosub FL_Norm ' On normalise X
gosub FLdiv
BT=-EE
else
BT=EE
endif
NB=ncd BT-2
FL_ZM=FL_XM : FL_ZE2=FL_XE2
NB=1<<NB
do while NB>0
FL_YM=FL_XM : FL_YE2=FL_XE2
gosub FLmulti
BT=EE and NB
if BT<>0 then ' impair
FL_YM=FL_ZM : FL_YE2=FL_ZE2
gosub FLmulti
endif
NB=NB>>1
loop
return
' calculate X^(1/EE) X must be normalized
FLsqrt: ' effectue X^(1/EE) X doit etre norme
if EE=0 then
FL_XM=32768:FL_XE2=-15 ' =1 normalise
return
elseif EE=1 then
return
endif
FL_TM=FL_XM : FL_TE2=FL_XE2
FL_XE2=16+FL_XE2
if FL_XE2>127 then
FL_XE2=-FL_XE2
FL_XE2=FL_XE2/EE
FL_XE2=-FL_XE2
else
FL_XE2=FL_XE2/EE
endif
FL_XE2=FL_XE2-15
FL_XM=40000 ' racine approchee
EE=EE-1
' sertxd("R App=",13,10)
for b11 = 1 to 3
' sertxd(#b11," ")
' gosub FL_sertxd
' sertxd(13,10)
FL_YM=FL_XM:FL_YE2=FL_XE2
FL_XM=EE : FL_XE2=0
gosub FLmulti
' sertxd(#b11," X*(EE-1) ==>")
' gosub FL_sertxd
' sertxd(13,10)
push FL_XH,FL_XL,FL_XE2
FL_XM=FL_YM:FL_XE2=FL_YE2
gosub FLexp ' Calcule X=X^(EE-1)
FL_YM=FL_TM:FL_YE2=FL_TE2
gosub FLdiv
' sertxd(#b11," A/() ==>")
' gosub FL_sertxd
' sertxd(13,10)
pop FL_YE2,FL_YL,FL_YH
gosub FLadd
FL_YM=FL_XM:FL_YE2=FL_XE2
FL_XM=EE+1:FL_XE2=0
gosub FL_norm
gosub FLdiv
next b11
EE=EE+1
return
' Effectue X=Y/X (X et Y doivent etre normalises, Y est perdu dans l'operation)
FLdiv:
' sertxd (13,10,"FLdiv ")
' gosub FL_SertXd
' gosub Fl_SertYd
FL_XE2=FL_YE2-FL_XE2 ' on libere FL_YE2
WW=FL_XM ' On sauvegarde X
if FL_XL=0 or FL_XM=FL_YM then
WT=FL_YM/FL_XH
else
WT=FL_YM/FL_XH-1
endif
FL_XM=WT*/WW
do while FL_YM<FL_XM
WT=WT-1
FL_XM=WT*/WW
loop
FL_YM=FL_YM-FL_XM
BT=ncd WT-8 ' Combien de bits au dividande ?
FL_YM=FL_YM<<7/WH<<1>>BT
BT=8-BT
FL_XM=WT<<BT+FL_YM
FL_XE2=FL_XE2-BT-8
' sertxd(" Q=")
' gosub FL_SertXd
' sertxd(13,10)
return
FLmul:
FL_XM=FL_XM**FL_YM
FL_XE2=FL_XE2+FL_YE2
return
FLmulti: ' X=X*Y et Y inchange
' Accepte les flottants non normalises
' WT=FL_XM*FL_YM ' contournement du BUG PE6
' FL_XM=FL_XM**FL_YM
gosub Multi
BT=ncd FL_XM
FL_XE2=FL_XE2+FL_YE2
if BT=0 then
BT=ncd WT
BT=16-BT
FL_XM=WT<<BT
FL_XE2=FL_XE2-BT
else
bitTMP=WT rev 16 and 1
WT=WT>>BT
BT=16-BT
FL_XM=FL_XM<<BT+WT+bitTMP
FL_XE2=FL_XE2-BT+16
endif
return
Multi: ' Waiting for ** to be simulated ...
if FL_XM<$8000 or FL_YM<$8000 then
WT=FL_XM*FL_YM
FL_XM=FL_XM**FL_YM
else
FL_XM=FL_XM and $7FFF
FL_YM=FL_YM and $7FFF
WT=FL_XM*FL_YM
WW=FL_XM**FL_YM
FL_XM=FL_XM+FL_YM>>1+WW+$4000
FL_YM=FL_YM+$8000
endif
return
FLadd: ' X=X+Y et Y inchange
' DEBUG : on doit pouvoir eviter de perdre un bit !
BT=FL_XE2-FL_YE2
if BT<128 then ' positif donc XE2 > YE2
FL_XE2=FL_XE2+1
FL_XM=FL_XM>>1
FL_XM=FL_YM>>1>>BT+FL_XM
else
BT=-BT
FL_YM=FL_YM>>1
FL_XM=FL_XM>>1>>BT+FL_YM
FL_XE2=FL_YE2+1
endif
return
FL_Norm:
BT=ncd FL_XM
if BT<16 then
BT=16-BT
FL_XM=FL_XM<<BT
FL_XE2=FL_XE2-BT
endif
return
Last edited: