PDA

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