Streamlining Jeremy Leach's Q16.16 Arithmetic Module

wapo54001

Senior Member
I am to the point in a project when it is time to get serious about using Jeremy Leach’s Q16.16 Arithmetic Module. I’ve had a quick play with the decimal addition and am pretty excited about what it will do. If the rest of it works that well it will be invaluable.

The program as written includes demo code and other symbols and comments that seem unnecessary for the core signed math modules to run, and I would like to remove everything that doesn’t need to be there to do the math plus a few comments to visually divide the code into functional modules, etc.

In short, I would like to get rid of all code that isn’t necessary for the modules to work, but I don’t have the full understanding of what everything does to have the confidence to strip out things like the “User Macro Definitions” although I believe that they are unnecessary.

Would anyone be interested in taking a swipe at removing all coding that isn’t required for the four math functions to work? Most especially, I’d like to remove any SYMBOLS and VARIABLE definitions that are not needed for the modules to work.

Attached is Jeremy's code.
 

wapo54001

Senior Member
Interesting bug - ERROR in line 512 - then cannot stop simulation in latest V6.0.6.2 editor :confused:
I did not try to run a simulation -- I just entered some code in the program to add two numbers with large decimals and output the result via SERTXD. it worked perfectly. Line 512 looks like it's down in some of the code that I believe is unnecessary for function.

Also, I'm still using Editor 5. (No blasts, please!)
 

Goeytex

Senior Member
Line 511 is a #endrem with no corresponding #rem. This is tolerated in PE5, but not in PE6.

The simulator would not stop for me as well. Had to click reset first and then stop. Then the sim kept hanging at line 314 (BLSW = DLSW ** CLSW) After the hang, the rt mouse button no longer worked. Had to close PE6 with task manager.
 

Buzby

Senior Member
Same for me, stopped around line 315, but I just clicked stop or break a few times and it recovered. Still not very good though.

I then tried again, but first put a break on line 314 ( BMSW = 0 ). Single stepping from there then caused a lock on (BLSW = DLSW ** CLSW) for a good few seconds, and when it returned my right clicks and menu buttons had gone !.

RevEd have indicated that my venerable old PC is most likely the cause of issues like this, and I probably need something like http://www.pcpro.co.uk/reviews/desktops/385555/chillblast-photo-oc-v to run PE6 properly.

EDIT : The side windows ( code explorer etc. ) were still working. I clicked around a few of those and the whole simulation started to run again !. ( Until it got to the breakpoint, and now single step caused another lock up. )
 
Last edited:

JimPerry

Senior Member
Venerable old Pc not in my case - 16GB Win7 Pro 64-bit - twin dual core 3GHz Xeon processors :confused:
 

wapo54001

Senior Member
How about trying to run this *after* editing out the demo mode and macro code and anything else that is not needed for the four math functions to work properly?
 

wapo54001

Senior Member
I've tried running the multiplication routine and either I'm doing it wrong or the code isn't working right -- the answer should be 2400-something and I'm getting 2040-something. This set of codes could be very useful in a variety of applications but it may need some housekeeping to get it slimmed down and fully functional. Fresh start tomorrow.
 

wapo54001

Senior Member
This is Jeremy Leach's code with the macro code removed. The addition and subtraction work fine, the multiplication does not. The multiplication does work as long as the value after the decimal is zero, but if it is not zero the result is wrong. I'm wondering if there is a command in there that has been superceded or modified. Any thoughts?
 

hippy

Ex-Staff (retired)
The multiplication does work as long as the value after the decimal is zero, but if it is not zero the result is wrong.
Operator = op_Mul
AMSW = 6
ALSW = 5
BMSW = 2
BLSW = 0

'Result = 12.10 (wrong)
The result looks correct to me ( though the result is not actually 12.10, that's just how it has been visualised / reported ).

Were you expecting 6.5 x 2 = 13 ?

If so it is probably that ALSW=5 is incorrect for 0.5, and it should be ALSW=$8000 or ALSW=32768
 

wapo54001

Senior Member
The result looks correct to me ( though the result is not actually 12.10, that's just how it has been visualised / reported ).

Were you expecting 6.5 x 2 = 13 ?

If so it is probably that ALSW=5 is incorrect for 0.5, and it should be ALSW=$8000 or ALSW=32768
hippy, as you can see I am in over my depth, I just want to be able to use the module.

Yes, I was expecting 13. If everything else is in decimal, why is ALSW not in decimal? Or is nothing in decimal? What do I need to do to make it all in decimal?
 

wapo54001

Senior Member
The result looks correct to me ( though the result is not actually 12.10, that's just how it has been visualised / reported ).

Were you expecting 6.5 x 2 = 13 ?

If so it is probably that ALSW=5 is incorrect for 0.5, and it should be ALSW=$8000 or ALSW=32768
@hippy, I guess you're right -- found the attached in the PDF that describes this module. It seems like it could be made to work in all decimal values with just a few more lines of code . . .
 

hippy

Ex-Staff (retired)
Yes, I was expecting 13. If everything else is in decimal, why is ALSW not in decimal? Or is nothing in decimal?
Each bit does represent a decimal value.

For AMSW etc, bits have values, from msb down to lsb, left to right; 32768, 16384, 8192 ... 16, 8, 4, 2, 1. This is standard integer representation.

For ALSW etc, this continues but for fractional power-of-two values; the msb is 1/2, then 1/4, then 1/8, down to 1/65536. So ...

$8000 = 0.5
$4000 = 0.25
$2000 = 0.125 etc

$C000 = 0.75 ( 0.5 + 0.25 )
 

wapo54001

Senior Member
The result looks correct to me ( though the result is not actually 12.10, that's just how it has been visualised / reported ).

Were you expecting 6.5 x 2 = 13 ?

If so it is probably that ALSW=5 is incorrect for 0.5, and it should be ALSW=$8000 or ALSW=32768
It has been a long journey since hippy made me understand how little I know about computer math, and I have been working with Jeremy Leach's module ever since. I didn't need the signing or the macro capability so I stripped that out. I realized that I had no clue about decimal vs binary vs hex vs anything, so I've been learning. Also began to understand Jeremy's accompanying pdf after about the 15th reading of it.

This is the code that I wound up with. It takes any two integer values (say 233 and 100) and divides them and gives the result as a decimal number including two digits after the decimal point which is exactly what I want. I realize that this is not entirely accurate and I haven't entered any decmials in the starting values, but it's good enough for what I need. Provided here in case anyone else has a similar need (with the major caveat that I only claim it does what I want it to, nothing more!), and of course any improvements are very happily welcomed.


Code:
#picaxe 20X2
setfreq m32
#no_table
#no_data


'#############################################################################
'#   TITLE       	     : Q16.16 Arithmetic Module                           #
'#   Author             : Jeremy Leach (modified)                                       #
'#############################################################################


'#############################################################################
'#  DEFINITIONS                                                              #
'#############################################################################

'Constants

Symbol Op_Add 	= 0
Symbol Op_Sub 	= 1
Symbol Op_Mul 	= 2
Symbol Op_Div 	= 3

'Symbols for Arguments
Symbol AMSW 	= w0
Symbol BMSW 	= w1
Symbol ALSW 	= w2 
Symbol BLSW 	= w3

Symbol CMSW		= w4
Symbol CLSW		= w5
Symbol DMSW		= w6
Symbol DLSW		= w7

Symbol EMSW		= w8
Symbol ELSW		= w9
Symbol FMSW		= w10
Symbol FLSW		= w11

'Symbol for Result
Symbol RMSW 	= w1
Symbol RLSW		= w3

'Symbols for Statement
Symbol Operator	= b25

Symbol Integer = W25
Symbol Fractional = W24


'#############################################################################
'#  MAIN                                                                     #
'#############################################################################

'STEP1: Load up Operator with the type of calculation you wish to perform (Op_Add,Op_Sub,Op_Mul,Op_Div)
'STEP2: Load up [AMSW].[ALSW] and [BMSW].[BLSW]
'STEP3: Gosub Calculate
'The signed result is in [RMSW].[RLSW]

'Calculation parameters
'BMSW always 100 for 100 step per segment pot travel
Operator = Op_Div
AMSW = 7
ALSW = 0
BMSW = 100
BLSW = 00

SERTXD("Numbers to divide ",#AMSW,".",#ALSW," / ",#BMSW,".",#BLSW,cr,lf,cr,lf)

'do the calculation
GOSUB Calculate
'Store the integer and fractional values to variable
SERTXD("Raw result ",#RMSW,".",#RLSW,cr,lf,cr,lf)
'Store the integer value
Integer = RMSW

'change the fraction to decimal value
'AMSW=0, BMSW=0, ALSW=RLSW from previous calc, BLSW=10,000,
Operator = Op_Mul
AMSW = 0
ALSW = RLSW
BMSW = 0
BLSW = 10000
GOSUB Calculate

'Add 1 to compensate for typical error
Fractional = RLSW + 1
'make it based on 100
Fractional = Fractional / 100
'if equal to or bigger than 100/100, add an integer and remove fractional
IF Fractional > 99 THEN
Integer = Integer + 1
Fractional = Fractional - 100
ENDIF
SERTXD("Decimal Result ",#integer," & ",#fractional,"/100",cr,lf,cr,lf)

End


'#############################################################################
'#  Q16.16 USER ROUTINES                                                     #
'#############################################################################

Calculate:

	Select Case Operator
		Case Op_Add
			Gosub UnsignedAdd
		Case Op_Sub
			Gosub UnsignedAdd
		Case Op_Mul
			CMSW = AMSW
			CLSW = ALSW
			DMSW = BMSW
			DLSW = BLSW
			Gosub UnsignedMultiply
		Case Op_Div
			EMSW = AMSW
			ELSW = ALSW
			FMSW = BMSW
			FLSW = BLSW
			Gosub UnsignedDivide
		End Select
Return

'#############################################################################
'#  Q16.16 CORE ROUTINES                                                     #
'#############################################################################

UnsignedAdd:
	RLSW = ALSW + BLSW 'Add the least significant Words together.
	RMSW = AMSW + BMSW 'Add the most significant Words together.
	If RLSW < ALSW Then 'Account for Carry if necessary (using comparison trick to spot carry).
		Inc RMSW
	EndIf
Return
	
UnSignedMultiply:
	BMSW = 0
	BLSW = DLSW ** CLSW
	'A = [P2MSW].[P2LSW]
	AMSW = DLSW ** CMSW
	ALSW = DLSW *  CMSW
	Gosub UnsignedAdd 'Leaving the result in B

	AMSW = DMSW ** CLSW	
	ALSW = DMSW * CLSW
	Gosub UnsignedAdd 'Leaving the result in B
	
	AMSW = DMSW * CMSW
	ALSW = 0
	Gosub UnsignedAdd
Return
	
UnSignedDivide:
	Symbol EndThreshold = 65530
	
	If FMSW = 0 Then
		
		CMSW = 65535 / FLSW 'W
		CLSW = 65535 // FLSW * CMSW '~ R * W 
	Else
	
		CMSW=0 
		CLSW=65535/FMSW
	EndIf  
	
	Do
		'Fn+1 = Fn * Cn
		DMSW = FMSW
		DLSW = FLSW
		Gosub UnsignedMultiply
		FMSW = RMSW
		FLSW = RLSW
	
		'En+1 = En * Cn
		DMSW = EMSW
		DLSW = ELSW
		Gosub UnsignedMultiply
		EMSW = RMSW
		ELSW = RLSW
	
		If FLSW >= EndThreshold Then Exit 'Exit when Fn has converged to 1.
		
		CMSW = 2 - FMSW
		CLSW = 0 - FLSW
		If CLSW > 0 Then 
			Dec CMSW 
		Endif
	Loop
Return
 
Top