View Full Version : detect overflow of multiply/ div32 result
richard
- 15th September 2015, 08:45
I want to multiply two word vars and then do a div32 divide where a or b can be 0-$ffff
dummy = a * b
result = div32 100
is there a way to detect if the result is > $ffff so I could
try
result = div32 1000
etc etc.
till there is no overflow
or oh for a icd that works that could monitor r(x)
pedja089
- 15th September 2015, 09:13
You can using */ or **.
** will return byte 2 and byte 3 of result, ignoring byte 0 and byte 1.
So you can do something like this:
Dummy = a ** b
If dummy=0 then
dummy = a*b
result = div32 100
multiplicator=1
else
dummy = a * b
result = div32 1000
multiplicator=10
endif
richard
- 15th September 2015, 09:32
perfect thanks for that
pedja089
- 15th September 2015, 10:07
I don't know maximum value of that variables, but if it is $FFFF then maximum number is $FFFE0001, or 4,294,836,225.
So maybe you need to divide with more 10000,100000 etc.
Just use select case or ELSEIF to determine with what value you need to divide.
richard
- 15th September 2015, 10:48
I did this , not tested yet
mult=1
;remaining time in seconds = (left * LAPSE )/100
REMTIMEHOU = left ** lapse
while REMTIMEHOU
mult=mult*10
if lapse > left then
REMTIMESEC = lapse /mult
REMTIMEMIN = left
else
REMTIMESEC = left/mult
REMTIMEMIN = lapse
endif
REMTIMEHOU = REMTIMESEC ** REMTIMEMIN
wend
select case mult
case 1
REMTIMEHOU = left * lapse
REMTIMESEC = div32 100
REMTIMEHOU=REMTIMESEC//3600
REMTIMESEC=REMTIMESEC/3600
case 10
REMTIMEHOU = left * lapse
REMTIMESEC = div32 1000
REMTIMEHOU=REMTIMESEC//360
REMTIMESEC=REMTIMESEC/360
case 100
REMTIMEHOU = left * lapse
REMTIMESEC = div32 10000
REMTIMEHOU=REMTIMESEC//36
REMTIMESEC=REMTIMESEC/36
case else
; wtf error
end select
REMTIMEMIN=REMTIMESEC//60
REMTIMESEC=REMTIMESEC/60
ARRAYWRITE buff,["REMAINING ",DEC2 REMTIMEHOU,":",DEC2 REMTIMEMIN,":",DEC2 REMTIMESEC,0]
GLCDSTR 25,80 ,buff
pedja089
- 15th September 2015, 11:17
I just noticed, that you can easily overflow variable mult after just 5 iteration.
You can just store number of 0 in that variable, or something...
richard
- 15th September 2015, 11:30
was hoping 3 iterations will be enough, but your right
one day I'm going to write a python pbp calculator with
pbp math functions including ** , */ and div32
using unsigned bytes and words
trial and error is tedious and I hate surprise results
pedja089
- 15th September 2015, 17:00
It's not complicated...
C=A*/B is same as C=(A*B)/$FF
C=A**B same as C=(A*B)/$FFFF
ruijc
- 15th September 2015, 22:38
one day I'm going to write a python pbp calculator with
pbp math functions including ** , */ and div32
using unsigned bytes and words
Richard... I would pay for that :D
I have a lot of trouble with that kind of pbp math.
I always have to compile and test and that takes forever !
If there was a simulator for pbp math it would be a life saver for sure !
Regards
Rui
richard
- 16th September 2015, 00:48
It's not complicated...
C=A*/B is same as C=(A*B)/$FF
C=A**B same as C=(A*B)/$FFFF
true but if you go on to a div32 then the result needs to be <$8000000
and that the div32 divider needs to be < $8000
and my meat calculator can't do /256 very easily
here is a start for a pbp calculator
richard
- 16th September 2015, 06:57
with more bells and whistles
ruijc
- 17th September 2015, 20:24
Hi guys,
I hope i'm not hijacking this thread but...
It's not complicated...
C=A*/B is same as C=(A*B)/$FF
C=A**B same as C=(A*B)/$FFFF
Maybe my mind is set to work with decimal only and this might be a dumb question but i cant understand what we can get from these operations
If A=1234 and B=5678 then
A*B=7006652 ( which in bynary is 0110 1010 ... )
I know that this operation keeps the higher 2 bytes 0110 1010 so
A**B= 106
Having said that, i know how they work... so my question is, when and why are these operations used?
Thanks
richard
- 17th September 2015, 22:36
its mainly about speed of execution and code size.
eg miles to kilometre conversion k=m*1.609
pbp has no floats so the 1.609 needs to be scaled up and then the result scaled back
this will work :-
you could do 1.609*1000=1609
k=m*1609 /1000
(k=m*1609
div32 1000)
this is better :-
using 1.609 * 256 = 411
so k=m*411/256 (eq to k=m*/411)
and will give you smaller faster code
and has a larger input range before overflowing also
ruijc
- 21st September 2015, 07:58
Thanks for the explanation Richard,
It's crystal clear now :)
Regards
Rui
Powered by vBulletin® Version 4.1.7 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.