Hi guys,
Thanks a lot for testing the code and for the analasis!
I didn't write it with speed in mind but I certainly didn't expect it to run THAT FREAKIN slow, geeez 400ms.....can't have that.
It's clear that it's the owDays routine that is the culprit and the problem is not with the division (the DIV32 and div by 4) commands as these executes in about 600 instruction cycles. It varies a little depending on the actual numbers but around 600 instructions.
The big hog is the "subtraction loop" and to be honest I didn't see that one comming. It's a about 120 instructions which, at first doesn't seem like much but when it is being executed 4015 times (11 years) it does indeed add up.
So, here's a suggested workaround. What it does is subtracting the seconds in steps (if possible). First 250 days worth (for as many times as possible), then 25 days worth (for as many times as possible) untill it finally does day by day.
My test show the complete owDays routine for Test Case 5 now takes around 3400 cycles instead of 420 000, that's roughly 125 times faster. Yes, it comes at the cost of a little more code space but it might be worth it.
Here's the modified section, everything else is the same, run it through its paces.
Code:
if AB < $5460 then ' Result of DIV32 will return a quotient that is 16-bit
' and caps the total seconds to 31-bits.
R0 = AB ' High word of seconds into system var
R2 = CD ' Low word of seconds into system var
owDays = DIV32 21600 ' Divide by 86400
owDays = owDays / 4
' Now we need to subtract 86400 seconds from the running time
' one time for each day that has passed. Since we're working with
' 16-bit words we need to this sort of "manually".
' 65536 + 20864 = 86400.
' As it turns out, doing this incrementally takes A LOT of time
' so we do it in steps. First (if possible) subtract 250 days worth for
' for as many times as possible. Then 25 days worth for as long as possible
' and finally one days worth for as many times as needed.
if owDays > 0 then ' As per Henrik, Speeds up the computation instead of wrapping around
i = owDays
WHILE i > 250 ' 21600000 seconds = 250 days
Temp = CD
CD = CD - 38656
IF Temp < CD THEN
AB = AB - 1
ENDIF
AB = AB - 329
i = i - 250
WEND
WHILE i > 25 ' 2160000 seconds = 25 days
Temp = CD
CD = CD - 62848
IF Temp < CD THEN
AB = AB - 1
ENDIF
AB = AB - 32
i = i - 25
WEND
While i > 0
Temp = CD
CD = CD - 20864
IF Temp < CD THEN ' Did we underflow the low word?
AB = AB - 1 ' If so, decrement high word
ENDIF
AB = AB - 1 ' Subtract 65536
i = i - 1
WEND
endif
/Henrik.
Bookmarks