Floating Point Library

BESQUEUT

Senior Member
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
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:

BESQUEUT

Senior Member
Test program for Floating Point Library

Code:
'FL_JYB Test program
' 15/4/2015
' Only for simulation and result checking
' Not for speed measurements

#picaxe 40X2
#no_table
#simspeed 1


symbol bitTmp=bit0

symbol WL=b2
symbol WH=b3
symbol WW=w1
symbol E_2=b4
symbol E10=b5
symbol Nb =b6
symbol BT=b7
symbol Reste=b8
symbol EE=b9


symbol FL_ZM=w21
Symbol FL_TM=w22
symbol FL_ZE2=b46	' w23
symbol FL_TE2=b47

symbol WT=w24
symbol WTL=B48
symbol WTH=B49
symbol FL_XM=w25
symbol FL_XL=b50
symbol FL_XH=b51

symbol FL_YM=w26
symbol FL_YL=b52
symbol FL_YH=b53

symbol FL_XE2=b54	' w27
symbol FL_YE2=b55


#macro FL_Exp(Flott,E2,E)
	FL_XM=Flott
	FL_XE2=E2
	EE=E
	gosub FLexp
#endmacro

#macro FL_Enter(Flott)
	FL_XM=Flott
	FL_XE2=0
	gosub FL_Norm
#endmacro

#macro FL_EnterP10(Flott,Puiss)
	FL_XM=10
	FL_XE2=0
	EE=Puiss
	gosub FLexp
	FL_YM=Flott
	FL_YE2=0
	gosub FLmulti
#endmacro



#macro FL_Sqrt(Flott,E2,E)
	FL_XM=Flott
	FL_XE2=E2
	gosub FL_Norm
	EE=E
	gosub FLsqrt
#endmacro


#macro FL_Add(Flott,E2)
	FL_YM=FL_XM : FL_YE2=FL_XE2
	FL_XM=Flott
	FL_XE2=E2
	gosub FLadd
#endmacro

#macro FL_Div(Flott,E2)
	FL_YM=FL_XM : FL_YE2=FL_XE2
	FL_XM=Flott
	FL_XE2=E2
	gosub FL_Norm
	gosub FLdiv
#endmacro

#macro FL_Multi(Flott,E2)
	FL_YM=FL_XM : FL_YE2=FL_XE2
	FL_XM=Flott
	FL_XE2=E2
	gosub FLmulti
#endmacro



#rem
	for b10=1 to 16 step 3
		sertxd(13,10,"FL_Exp 3 ^",#b10," = ")
		FL_Exp(3,0,b10)
		gosub FLsertxd10
	next b10

#endrem

symbol PI_M=51472
symbol PI_E2=242	' =-14


	sertxd("60000+40000=")
	FL_Enter(60000)
	Fl_Add(40000,0)
	gosub FLsertxd10
	sertxd (" Expected=100000",13,10)	


	sertxd ("PI*50000=")
	FL_EnterP10(31415,-4)
	FL_Multi(50000,0)
	gosub FLsertxd10
	sertxd (" Expected=157075",13,10)
	
	sertxd ("Other way :",13,10,"PI*50000=")
	FL_XM=50000:FL_XE2=0
	FL_Multi(PI_M,PI_E2)
	gosub FLsertxd10
	sertxd (" Expected=157080",13,10)
	
	sertxd ("22/7=")
	FL_Enter(22) 
	FL_div(7,0)
	gosub FLsertxd10
	sertxd (" Expected=3,142857",13,10)

	for b10=0 to 4
		sertxd(13,10,"FL_Exp(7,",#b10,") = ")
		FL_Exp(7,0,b10)
		gosub FLsertxd10
	next b10

	for b10=1 to 4
		sertxd(13,10,"FL_Sqrt(10000,",#b10,") = ")
		FL_Sqrt(10000,0,b10)
		gosub FLsertxd10
	next b10

	for w20=1 to 10
		sertxd(13,10,"FL_Sqrt(",#w20,",2) = ")
		FL_Sqrt(w20,0,2)
		sertxd(13,10,"Result=")
		gosub FLsertxd10
	next w20
end


#INCLUDE "FL_JYB_U_sim001.bas"
FL_JYB is supposed to be stored in "FL_JYB_U_sim001.bas"
 

BESQUEUT

Senior Member
Code without the ** patch

Not for simulation !
Code:
' FL_JYB_U_002
'
' Floating Point Library Unsigned (not for simulation)
' V 002
' 15/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		
	FL_XM=FL_XM**FL_YM
'	gosub Multi			' contournement du BUG PE6
	

	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 ... 1000 sqrt en 33s

'	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
 

BESQUEUT

Senior Member
Code for speed testing

_7 ms for Exp(X,E) 0<X<100 0<E<11
32 ms for Sqrt(X,2)
Code:
'FL_JYB Test program
' 15/4/2015
' 
' For speed measuring

#picaxe 40X2
#no_table
#simspeed 1


symbol bitTmp=bit0

symbol WL=b2
symbol WH=b3
symbol WW=w1
symbol E_2=b4
symbol E10=b5
symbol Nb =b6
symbol BT=b7
symbol Reste=b8
symbol EE=b9


symbol FL_ZM=w21
Symbol FL_TM=w22
symbol FL_ZE2=b46	' w23
symbol FL_TE2=b47

symbol WT=w24
symbol WTL=B48
symbol WTH=B49
symbol FL_XM=w25
symbol FL_XL=b50
symbol FL_XH=b51

symbol FL_YM=w26
symbol FL_YL=b52
symbol FL_YH=b53

symbol FL_XE2=b54	' w27
symbol FL_YE2=b55


#macro FL_Exp(Flott,E2,E)
	FL_XM=Flott
	FL_XE2=E2
	EE=E
	gosub FLexp
#endmacro

#macro FL_Enter(Flott)
	FL_XM=Flott
	FL_XE2=0
	gosub FL_Norm
#endmacro

#macro FL_EnterP10(Flott,Puiss)
	FL_XM=10
	FL_XE2=0
	EE=Puiss
	gosub FLexp
	FL_YM=Flott
	FL_YE2=0
	gosub FLmulti
#endmacro



#macro FL_Sqrt(Flott,E2,E)
	FL_XM=Flott
	FL_XE2=E2
	gosub FL_Norm
	EE=E
	gosub FLsqrt
#endmacro


#macro FL_Add(Flott,E2)
	FL_YM=FL_XM : FL_YE2=FL_XE2
	FL_XM=Flott
	FL_XE2=E2
	gosub FLadd
#endmacro

#macro FL_Div(Flott,E2)
	FL_YM=FL_XM : FL_YE2=FL_XE2
	FL_XM=Flott
	FL_XE2=E2
	gosub FL_Norm
	gosub FLdiv
#endmacro

#macro FL_Multi(Flott,E2)
	FL_YM=FL_XM : FL_YE2=FL_XE2
	FL_XM=Flott
	FL_XE2=E2
	gosub FLmulti
#endmacro



#rem
	for b10=1 to 16 step 3
		sertxd(13,10,"FL_Exp 3 ^",#b10," = ")
		FL_Exp(3,0,b10)
		gosub FLsertxd10
	next b10

#endrem
setfreq em64

symbol PI_M=51472
symbol PI_E2=242	' =-14

#rem
	sertxd("60000+40000=")
	FL_Enter(60000)
	Fl_Add(40000,0)
	gosub FLsertxd10
	sertxd (" Expected=100000",13,10)	


	sertxd ("PI*50000=")
	FL_EnterP10(31415,-4)
	FL_Multi(50000,0)
	gosub FLsertxd10
	sertxd (" Expected=157075",13,10)
	
	sertxd ("Other way :",13,10,"PI*50000=")
	FL_XM=50000:FL_XE2=0
	FL_Multi(PI_M,PI_E2)
	gosub FLsertxd10
	sertxd (" Expected=157080",13,10)
	
	sertxd ("22/7=")
	FL_Enter(22) 
	FL_div(7,0)
	gosub FLsertxd10
	sertxd (" Expected=3,142857",13,10)

	for b10=0 to 4
		sertxd(13,10,"FL_Exp(7,",#b10,") = ")
		FL_Exp(7,0,b10)
		gosub FLsertxd10
	next b10

	for b10=1 to 4
		sertxd(13,10,"FL_Sqrt(10000,",#b10,") = ")
		FL_Sqrt(10000,0,b10)
		gosub FLsertxd10
	next b10
#endrem
	low D.3
	wait 5

	
	sertxd(13,10,"FL_Exp(x,2) ")

	high D.3
	for w20=1 to 100
		for b10=1 to 10
			FL_Exp(w20,0,b10)
		next b10
	next w20
	low d.3
	sertxd(13,10,"OK")
	
	
	low D.3
	wait 5

	
	sertxd(13,10,"FL_Sqrt(x,2) ")

	high D.3
	for w20=1 to 1000
		FL_Sqrt(w20,0,2)
	next w20
	low d.3
	sertxd(13,10,"OK")

end


#INCLUDE "FL_JYB_U_002.bas"
FL_JYB is supposed to be stored in "FL_JYB_U_002.bas"
 
Last edited:

geoff07

Senior Member
You seem a bit lonely here with four posts and no replies, so here is a reply!

The idea of having FP is very good. It is a major weakness that we don't have it, especially that my BBC Micro on a 2MHz 6502 with interpreted basic had FP in the 1980s. What isn't clear yet to me is what it takes to integrate this with an application, and whether the limitations are a problem or incidental. So I for one am interested but need to devote time to understanding what you have done and its implications, and that won't be happening in the immediate future.
 

BESQUEUT

Senior Member
You seem a bit lonely here with four posts and no replies, so here is a reply!

The idea of having FP is very good. It is a major weakness that we don't have it, especially that my BBC Micro on a 2MHz 6502 with interpreted basic had FP in the 1980s. What isn't clear yet to me is what it takes to integrate this with an application, and whether the limitations are a problem or incidental. So I for one am interested but need to devote time to understanding what you have done and its implications, and that won't be happening in the immediate future.
Thanks for your interest...
There are no real limitations, except you need a powerfull Picaxe (the library use some X2 specific math).
Negatives numbers are scheduled ASAP. Same thing for documentation : but you can start with the test program.
IEEE is for info. I use 3 bytes representation, whereas IEEE need 4 bytes.
You can expect 15 significative bits all the time, that is 4 to 5 decimal digits.
If you think of a simple Picaxe divide, that is far better !

To integrate, you need the symbols and the #include at the end of your program.
Macros are for convenience.
Then you can use FL_XM and FL_XE2 to do calculations.
Same for Y, Z et T variables, and more if needed.

In #2, there is an example to define PI constant :
symbol PI_M=51472
symbol PI_E2=242 ' =-14

PI is defined as 51472 * 2^-14 (IE 242 2s complement notation)

You can also use 31415*10^-4 and the ad hoc macro :
FL_EnterP10(31415,-4)
but you will lost some time and some digits...

For integers less than 65536, you can use :
FL_XM=12345 : FL_XE2=0
If the FPN need to be normalized, you can use :
gosub FL_Norm
(You can think that as transforming an integer to a FPN)
Then X will be represented as 49380*2^-2
IE FL_XM become 49380 and FL_XE2=-2

OK : I have to write a complete user manual as soon as possible...
 
Last edited:

binary1248

Senior Member
Great posting. I wrote a FP package in assy language for 8085 many many years ago. Thus I have a good appreciation for the difficulty, and all the testing required to debug it.
Thanks for the posting, I'll keep this link ready.
Paul
 

BESQUEUT

Senior Member
Great posting. I wrote a FP package in assy language for 8085 many many years ago. Thus I have a good appreciation for the difficulty, and all the testing required to debug it.
Thanks for the posting, I'll keep this link ready.
Paul
Thanks
This work is very different to a PIC or 8085 implementation as I use as far as possible Picaxe math, but I agree : it is a lot of work... (and the ** bug in PE6 simulator did not help...)
I hope there are not to much bugs remaining...
I also hope that some will help improving the lib.
For example, the FL_sertxd10 is very poor currently.
 
Last edited:

beb101

Senior Member
You could also use a $3 ESP8266 Wifi module with the latest Lua firmware as a Picaxe floating point
co-processor via the Picaxe serial port. For example, send (= is a shortcut for Lua print( ...) and get back (-->) :

=334553.775411*344997.33456 --> 115420160783.78

=115420160783.78/344997.33456 --> 334553.775411

=344566^7 --> 3.4028234663853e+38

=34886775.11341^(1/2) --> 5906.5027819692

=5663%4 --> 3

The full Lua math module is not implemented on the ESP, but sin, cos, tan, atan could easily be
implemented as Lua functions to be called from the Picaxe like this: =sin(1.1266).
 

oracacle

Senior Member
I have only had a brief look at the code so may have missed it, but is it going to be possible to split a number at the decimal? I have in the past to calculate the number of steps for a stepper motor to rotate a lead screw used (distance required*thread pitch)=total number of turns. split this number run sub procedure for full turns, and then run separate sub procedure for part of turn. this was done to stop overflow of variable with small step sizes (ie 1/64 step)

so with a thread pitch of 4mm and a step of 1/64 (giving 12800 steps per turn) and 95mm of movement

95/4=23.75 turns
23.75*12800=304000 steps to complete - this is way over the max size of a single variable
so:-
23 turns (so 23 loops of 12800 steps)
0.75*12800=9600 - this number can be used as a second loop counter.

not sure how well I described myself there so here is the code loops for the movement, numbers are calculated in FPU

Code:
      [color=Blue]if [/color][color=Black]rotation [/color][color=DarkCyan]> [/color][color=Navy]0 [/color][color=Blue]then                                  [/color][color=Green]'check for number of rotations
            [/color][color=Blue]for [/color][color=Purple]b18 [/color][color=DarkCyan]= [/color][color=Navy]1 [/color][color=Blue]to [/color][color=Black]rotation                         [/color][color=Green]'at least one rotation to the specified amount
                  [/color][color=Blue]for [/color][color=Black]tempword1 [/color][color=DarkCyan]= [/color][color=Navy]0 [/color][color=Blue]to [/color][color=Navy]12800                [/color][color=Green]'12800 steps per rototaion
                        [/color][color=Blue]pulsout [/color][color=Black]clk, [/color][color=Navy]5                      [/color][color=Green]'send clock signal
                  [/color][color=Blue]next [/color][color=Black]tempword1
            [/color][color=Blue]let [/color][color=Black]tempword1 [/color][color=DarkCyan]= [/color][color=Navy]0                               [/color][color=Green]'reset step counter
            [/color][color=Blue]next [/color][color=Purple]b18                                        [/color][color=Green]'next rotation
      [/color][color=Blue]end if
      let [/color][color=Black]tempword1 [/color][color=DarkCyan]= [/color][color=Navy]0
      
      [/color][color=Blue]if [/color][color=Black]stepps [/color][color=DarkCyan]> [/color][color=Navy]0 [/color][color=Blue]then                                    [/color][color=Green]'now loop for part rotation
            [/color][color=Blue]for [/color][color=Black]tempword1 [/color][color=DarkCyan]= [/color][color=Navy]0 [/color][color=Blue]to [/color][color=Black]stepps                     [/color][color=Green]'loop for steps in part rotation
                  [/color][color=Blue]pulsout [/color][color=Black]clk, [/color][color=Navy]5                            [/color][color=Green]'send clock signal
            [/color][color=Blue]next [/color][color=Black]tempword1
      [/color][color=Blue]end if[/color]
 

BESQUEUT

Senior Member
I have only had a brief look at the code so may have missed it, but is it going to be possible to split a number at the decimal? I have in the past to calculate the number of steps for a stepper motor to rotate a lead screw used (distance required*thread pitch)=total number of turns. split this number run sub procedure for full turns, and then run separate sub procedure for part of turn. this was done to stop overflow of variable with small step sizes (ie 1/64 step)

so with a thread pitch of 4mm and a step of 1/64 (giving 12800 steps per turn) and 95mm of movement

95/4=23.75 turns
23.75*12800=304000 steps to complete - this is way over the max size of a single variable
so:-
23 turns (so 23 loops of 12800 steps)
0.75*12800=9600 - this number can be used as a second loop counter.

not sure how well I described myself there so here is the code loops for the movement, numbers are calculated in FPU
Problem is how you get the distance to move ?
Are there fixed positions or are positions calculated from others sensors ?
Position accuracy is actually 0.000 3125 mm. Do you need that level of accuracy, and if not what is the accuracy level needed ?
 

oracacle

Senior Member
its an example taken from my macro rail project (http://www.picaxeforum.co.uk/showthread.php?25841-New-macro-Rail) which made use of the uM-FPU. the resolution was derived from the motor driver and pitch of the screw thread. the pitch is 4mm and there is 64 micro steps per step on a 200 step bipolar stepper motor. initial position is found using an end stop switch and current position is calculated from the known number of steps that have been taken.

the distance to move is a user input, the user increment either the whole or decimal. for the macro rail I allowed the user input of either 1mm or 0.5mm. each button press sent an i2c command to add or subtract either to the total depth and then print the new total onto a display. there was added complication due to the fact that the system checks for trying to use more depth the rail has length.

the macro rail takes other information to calculate the depth of field, image overlap and thus the amount time the camera has to be moved in any given distance.
as an example:
focal length of 40mm, object to be imaged is 95mm (as before) and a 30% overlap, f2.8, on a Nikon ASP-C camera
we get:
magnification of 2.1625
effective aperture: 8.855
DoF: 0.0755545
distance between shots: 0.052882
number of shots 1769

as I am looking at increasing magnification the distance between shot decreases resulting in the requirement of the extremely small number.

the only reason I mention the splitting of the number was I struggled to find a way of doing before I found the fsplit command, I just used an example I was familiar with. I have been looking at upgrading the old DVD drive based rail with similar functions but haven't gotten around to it yet, and splitting numbers was one thing that was putting me off. I haven't measured thread bitch or anything as yet so don't know what the outcome maybe if I do upgrade it. either way I am sure that splitting number may come in handy for someone in the future
 
Top