arithmetic operations: multiplication and division
There are two different multiplication subroutines. Both of them are fairly accurate. FMLT is about twice as fast as MULT, but it is slightly less accurate and it changes the values in X and Y. MULT isn't 100% accurate but all results are within $01 of the correct value, and MULT preserves the values in X and Y.
function name FMLT
address BFAE
time (mean) 47 cycles
description multiply X by Y, faster version
inputs X, Y
registers used A, X, Y
outputs A
tables used HALF, ML3F
notes error standard deviation = 0.6757
function name MULT
address BFB1
time (mean) (87) cycles
description multiply X by Y, more accurate version
inputs X, Y
registers used A
tables used FABS,HALF, MLT5, MLT4, MLT3, MLT2, MLT1, MLT0
outputs A
notes error standard deviation = 0.4301
The code for FMLT is displayed below. It uses inline versions of FAVG and FHDF, taking advantage of the identity
(x/2 + y/2)^2 - (x/2 - y/2)^2
= x^2/4 + 2xy/4 + y^2/4 - x^2/4 + 2xy/4 - y^2/4
= 4xy/4
= xy
![arith2b.png.5cdb15459927fc2a28d89f190ea540a3.png](<___base_url___>/applications/core/interface/js/spacer.png)
Here's the code for MULT:
![arith3.png.2b2ce99fe209b60008e6606d74c5869a.png](<___base_url___>/applications/core/interface/js/spacer.png)
MULT just adds fractions if the corresponding bit in the absolute value of X is equal to 1. The BBR commands just skip that addition if the bit in absolute value of X is zero. That absolute value is taken at the beginning if X is negative, and then bit 7 in the temporary zero page variable is set. At the end of the calculation, if bit 7 is set the result is negated. The only command not shown on this image is the RTS.
There are two entries to the division subroutine. FDIV is the first, and does the error checking on the inputs. FDV2 is a little farther down and skips that error checking step.
function name FDIV
address BFB4
time (mean) (108) cycles
description divide X by Y
inputs X, Y
registers used A
tables used FABS, DIV6, DIV5, DIV4, DIV3, DIV2, DIV1, DIV0
outputs A
notes error standard deviation = 0.4726, returns carry set if Y=$00 or Y=$80 or X=$80 or abs(X)>abs(Y)
function name FDV2
address BFB7
time (mean) (88) cycles
description divide X by Y, no error checking
inputs X, Y
registers used A
tables used FABS, DIV6, DIV5, DIV4, DIV3, DIV2, DIV1, DIV0
outputs A
notes error standard deviation = 0.4726
Here's the code for FDIV in the META/L editor:
![arith5a.png.dfeac48db8357ae6588940675d3d5c98.png](<___base_url___>/applications/core/interface/js/spacer.png)
The multiplication and division functions are pretty important to the rest of the subroutines, so I wanted to make certain that they were actually close to correct. A nice thing about having two-parameter functions that can each only take 256 possible values is that it's easy to calculate all possible results for all possible combinations of inputs on a spreadsheet, and compare the results to an ideal target. The targets were all done in floating point, and only converted into single byte format at the last step. I was then able to compare the calculations of these subroutines against the target, and make histograms of the differences between calculation and target.
![FDIVerror.png.e1e4afb6ab0f351291279c08cd657991.png](<___base_url___>/applications/core/interface/js/spacer.png)
There is another division method using logarithms, but it's only about 20 cycles faster than FDIV and the accuracy is pretty bad, so I didn't include the log/antilog tables in the file:
![DIvLOGerror.png.4e28650b18bcc3cfbf24d018e35aa888.png](<___base_url___>/applications/core/interface/js/spacer.png)