MULDIV64 appears to have 2% error
When the following program is run the convert degree 45 is changed to angle32bit then converted back to a degree resulting in the returned value 44 . (45-44)/45*100 which is 2.2% error , Must be doing something wrong in this program:
{{MULDIV64(mult1,mult2,divisor) : quotient
Divide the 64-bit product of 'mult1' and 'mult2' by 'divisor', return quotient (unsigned operation)
allows unsigned integer values to be multiplied then divided then returning qutient value }}
CON
_clkfreq = 200_000_000 'must be greater than 10MHZ for debug
PUB main()| var01,var02,var03,angle32bit,degree,rotation,unitDegree
unitDegree := 360
rotation := $FFFF_FFFF '2*pi = angle32bit maximum
var01 := $FFFF_FFFF
var02 := $FFFF_FFFF
var03 := $FFFF_FFFF
debug(udec(var01),uhex(var01))
debug(udec(var02))
debug(udec(var03))
debug("var03 = (var01*var02)/var03) = ",udec(var03))
var01 := 45
var02 := rotation
var03 := unitDegree
'var01 must be less than var03 the quotient
debug(udec(var01))
debug(udec(var02))
debug(udec(var03))
angle32bit := MULDIV64(var01,var02,var03)
debug("angle32bit = $FFFF_FFFF*45/360 = ",uhex(angle32bit),udec(angle32bit))
debug("angle32bit = (var01*var02)/var03) = ",udec(var03))
degree := MULDIV64(angle32bit,unitDegree,rotation)
debug(udec(angle32bit))
debug(udec(rotation))
debug(udec(unitDegree))
debug("(angle32bit*unitDegree)/rotation = ","degree = ",udec(degree))
repeat
Comment would be apreciated
Regards
Bob (WRD)
Comments
Off-by-one is classic case of simple binary arithmetic rounding error. Not unexpected. If the range was 0-1 then it would always round down to zero. Up to 100% error.
Because it always rounds down, even 0.9999 will still round down to zero. The fix, in hardware, is to always add a half-bit to the result. In software the workaround is to add half the divisor to the dividend before the division.
EDIT: The fix needs added internal to the muldiv64() method. Not hard. Something for Chip to sort out.
In the meantime, changing unitDegree from 360 to 360_000, and var01 to 45_000, might be helpful for you.
Thanks Evanh will try
Regards
Bob (WRD)
Here's what muldiv64 will be like:
And here's an example fix:
Thanks evanh I was trying :
angle32bit,rotation,unitDegree := 4_294_967_295/8,4_294_967_295,360
var01,var02,var03 := angle32bit,rotation,unitDegree
errorDegree := MULDIV64(angle32bit,360,1)
debug(udec(errorDegree))
errorDegree := errorDegree + (rotation/2)
degree := MULDIV64(errorDegree,1,rotation)
debug(udec(degree))
but this wouldn't work because values seem to error to 0
will go through your code (I am a littler slow) apreciate your reply
Bob (WRD)
evanh
That code seems to work should this sugests the spin code should change or is there other factors to consider?
Is there access to the assembly code spin commands are using?
again Thanks
Bob (WRD)
In most cases I think the compensating rounding to nearest is the right solution. Maybe in cases where the remainder is used then an uncompensated division would be needed instead.
Um, not completely sure of the question here. You can write pasm code inside spin methods like that yourself.
evanh
If MULDIV64(mul1,mul2,divisor) is a spin command it must call a program to run in the byte code interpeter is there someway to see what action this interperter takes, most likely as you sugest some
assembly program is called. If MULDIV64 is in the byte code interperter I would assume this can't be modified being in propeller rom?
Not exceedingly important I have lot to learn but it is interesting.
Regards
Bob (WRD)
Ooooh! Gotcha. Chip has long been refining Spin2 using the Pnut test bed, Spin2 has only just recently settled down. Spin2 is not in ROM with the Prop2. Different to the Prop1.
He hasn't yet but he may well publish the built-in method sources. Some will be direct mapped machine code instructions, some will be Pasm code like I did, whiles others will be plain Spin code or a mix.
EDIT: Completely wrong about the published sources. See below.
Thanks for reply. This was interesting.
Regards
Bob (WRD)
I never thought about this. I was writing code for the Si570 frequency synthesizer chip and got "discontinuities" at certain frequencies and never knew why. I will be sure to try the MULDIV65 assembly code snippet. Thanks for the insight.
My pleasure. It is satisfying to kill those glitches.
@"Bob Drury"
If you download the PNut archive ypu'll find inside the "Spin2_interpreter.spin2" which is the PASM source of the bytecode interpreter.
Unfortunately PNut dasn't compile this file but it have internally the binary blob that is appended to the generated bin that get then transferred into P2 ... so any change to the above file will not make any change in the interpreter ... it is there only for reference.
Propeller tool even doesn't include the Spin2 interpreter source in its distribution so I presume it behave as PNut
Oh, hehe, all pasm coded.
You're using signed division operators in that code -- does it work if you change to unsigned division? +/
Jon
Not sure how to make that change for MULDIV64 spin method. The debug statement is just showing what the MULDIV64 spin function is doing for descriptive purposes.
regards
Bob (WRD)