Author Topic: Axe Q&A  (Read 600002 times)

0 Members and 3 Guests are viewing this topic.

Offline Deep Toaster

  • So much to do, so much time, so little motivation
  • Administrator
  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 8217
  • Rating: +758/-15
    • View Profile
    • ClrHome
Re: Axe Q&A
« Reply #1440 on: April 02, 2012, 06:32:57 pm »
It will almost definitely overflow the stack in a very short amount of time (and that's probably why the routine you linked to crashes).

A better alternative (that works) is a queue algorithm. It uses a queue (like an array) to hold the list of points to test, instead of recursively calling a function that can quickly fill up the hardware stack.




Offline MGOS

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 336
  • Rating: +95/-0
    • View Profile
Re: Axe Q&A
« Reply #1441 on: April 03, 2012, 03:43:33 am »
That's what I did... first I gave the program the 714 bytes L1 which sucked, then a 5kB Buffer which kinda works, but not 100%.

(A,B) are the coordinates of the "Paint bucket"
(P,Q) are the coordinates the stack returns (given is a 5000B large Buffer, so 2500 coordinates should fit in)
Code: [Select]
0->S
PUS(A,B)
While S
POP()
Pxl-On(P,Q)
If P-95
PUS(P+1,Q)
End
If P
PUS(P-1,Q)
End
If Q-63
PUS(P,Q+1)
End
If Q
PUS(P,Q+1)
End
End
Return

Lbl PUS
ReturnIf pxl-Test(r1,r2)
If S<2500
r1->{S*2+GBD1}
r2->{S*2+GBD1+1}
S++
End
Return
Lbl POP
S--
{S*2+GBD1}->P
{S*2+GBD1+1}->Q
Return

File is attached

The number displayd at the end tells how often there was a stack overflow.
« Last Edit: April 03, 2012, 04:37:29 am by MGOS »

Offline Builderboy

  • Physics Guru
  • CoT Emeritus
  • LV13 Extreme Addict (Next: 9001)
  • *
  • Posts: 5673
  • Rating: +613/-9
  • Would you kindly?
    • View Profile
Re: Axe Q&A
« Reply #1442 on: April 03, 2012, 03:47:32 am »
There was a floodfill routine posted earlier that used no extra memory and so can never cause a crash, but I can't find the link anymore D:

Offline MGOS

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 336
  • Rating: +95/-0
    • View Profile
Re: Axe Q&A
« Reply #1443 on: April 03, 2012, 04:38:46 am »
There was a floodfill routine posted earlier that used no extra memory and so can never cause a crash, but I can't find the link anymore D:

That's a bummer.

Offline chattahippie

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 358
  • Rating: +27/-0
  • Super Member! :D
    • View Profile
Re: Axe Q&A
« Reply #1444 on: April 03, 2012, 06:42:52 am »
Here's one jacobly made

http://ourl.ca/151805

Offline MGOS

  • LV6 Super Member (Next: 500)
  • ******
  • Posts: 336
  • Rating: +95/-0
    • View Profile
Re: Axe Q&A
« Reply #1445 on: April 03, 2012, 08:03:58 am »
Here's one jacobly made

http://ourl.ca/151805

Wow... that one's cool. now I'm wondering if I should stick with the tough work of converting it to axe or think of another solution by myself.

Edit: I rewrote my algorithm that it needs only a second 768 B buffer like Xeda wrote, but it is d*mn slow (because of the search algorithm I used)

Screeny at 4x speed:
« Last Edit: April 03, 2012, 08:37:47 am by MGOS »

Offline Yeong

  • Not a bridge
  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 3739
  • Rating: +278/-12
  • Survivor of Apocalypse
    • View Profile
Re: Axe Q&A
« Reply #1446 on: April 05, 2012, 01:31:45 pm »
Why won't this code work?

Code: [Select]
"Pic0Pic1Pic2Pic3Pic4Pic5Pic6Pic7Pic8Pic9"→Z
"Pic1"→I
GetCalc("varP")→Q
float{Q}→P
{Z+P}→{I}

For some reason, it seems like string I doesn't change. Why is that?
Sig wipe!

Offline jacobly

  • LV5 Advanced (Next: 300)
  • *****
  • Posts: 205
  • Rating: +161/-1
    • View Profile
Re: Axe Q&A
« Reply #1447 on: April 05, 2012, 03:47:53 pm »
"Pic0" is actually 3 bytes long (not including the terminating 0).

Since the first two bytes are always the same, you could do:
Code: [Select]
"Pic0Pic1Pic2Pic3Pic4Pic5Pic6Pic7Pic8Pic9"→Z
"Pic1"→I
GetCalc("varP")→Q
float{Q}→P
{P*3+Z+2}→{I+2}

But an even better method would be:
Code: [Select]
"Pic1"→I
GetCalc("varP")→Q
float{Q}→P
(P?-1,9)→{I+2} .Pic1-Pic9 is 0-8, and Pic0 is 9.

Edit: Not enough parentheses. Also, that's subtract 1, not negative 1.
« Last Edit: April 05, 2012, 04:18:17 pm by jacobly »

Offline Yeong

  • Not a bridge
  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 3739
  • Rating: +278/-12
  • Survivor of Apocalypse
    • View Profile
Re: Axe Q&A
« Reply #1448 on: April 05, 2012, 03:49:29 pm »
Ah. I never knew that Pic1 was 3 bytes O.o
Thanks a bunch.
EDIT: also, will I be able to use 0 as pic0? because that seems more reasonable to me.
« Last Edit: April 05, 2012, 03:51:03 pm by TBO_Yeong »
Sig wipe!

Offline jacobly

  • LV5 Advanced (Next: 300)
  • *****
  • Posts: 205
  • Rating: +161/-1
    • View Profile
Re: Axe Q&A
« Reply #1449 on: April 05, 2012, 04:09:35 pm »
That's what the code does: it converts an input from 0-9 to the internal representation of that Pic. So if you type in a 0 it will give you the pointer to Pic0 (represented internally as a 9).

Offline Runer112

  • Project Author
  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2289
  • Rating: +639/-31
    • View Profile
Re: Axe Q&A
« Reply #1450 on: April 05, 2012, 05:17:25 pm »
I know you didn't ask for this, but I'm just going to provide a few tips about how to improve the code:

Code: [Select]
"Pic1"→Str1                 .Use static instead of varaible data pointers
                            . whenever possible, they are more optimized
!If GetCalc("varP")         .Error handling is important!
 .Handle error
 .Return or Goto somewhere
End
(float{}??10)-1→{2+Str1}    .Omits storing and reloading the value returned by GetCalc()
                            . and restructures the conditional to omit the else branch
« Last Edit: April 05, 2012, 05:39:49 pm by Runer112 »

Offline Yeong

  • Not a bridge
  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 3739
  • Rating: +278/-12
  • Survivor of Apocalypse
    • View Profile
Re: Axe Q&A
« Reply #1451 on: April 05, 2012, 07:55:49 pm »
So, here's my code. :D

Code: [Select]
:.AATEST
:"Pic1"→I
:GetCalc("uP")→J
:fPart(J}→K
:K?-1,9→{I+2}
:UnArchiveI
:GetCalc(I)→Q
:conj(Q,{L6},768
:DispGraph
:ArchiveI
:GetCalc("Str1")→V
:GetCalc("uA")→M
:GetCalc("uB")→N
:GetCalc("uH")→O
:GetCalc("uW")→P
:fPart(M}→A
:fPart(N}→B
:fPart(O}→H
:fPart(P}→W
:
:"0123456789ABCDEF"→T
:0→θ
:For(D,0,H/8-1
:For(C,0,W/8-1
:For(F,0,7
:8*pxl-Test(8*C+A→Z,8*D+B+F→Y)
:+(4*pxl-Test(Z+1,Y))
:+(2*pxl-Test(Z+2,Y))
:+pxl-Test(Z+3,Y)
:→U
:{T+U}→{V+θ}
:8*pxl-Test(Z+4,Y)
:+(4*pxl-Test(Z+5,Y))
:+(2*pxl-Test(Z+6,Y))
:+pxl-Test(Z+7,Y)
:→U
:{T+U}→{V+θ+1}
:θ+2→θ
:End
:End:End

Yeah, I know I takes a lot of var from OS :P
But that aside, the problem is that no matter the OSVar P is, it still shows Pic1. What did I do wrong? (problem probably comes from the first few lines of the code)
Sig wipe!

Offline Runer112

  • Project Author
  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2289
  • Rating: +639/-31
    • View Profile
Re: Axe Q&A
« Reply #1452 on: April 05, 2012, 08:25:15 pm »
The issue is the line with the inline conditional. It's not treated as TI-BASIC experience may suggest, like this:
(K?-1,9)→{I+2}

It's treated like this:
K?(-1),(9→{I+2})

So with your current code, P=0 will select Pic0, but no other values of P have any effect because the store statement is not executed. To fix this, add the parentheses as shown in the first line of code. Alternatively, use the code I suggested in my previous post since it's more optimized anyway. ;)
« Last Edit: April 05, 2012, 08:26:08 pm by Runer112 »

Offline Yeong

  • Not a bridge
  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 3739
  • Rating: +278/-12
  • Survivor of Apocalypse
    • View Profile
Re: Axe Q&A
« Reply #1453 on: April 05, 2012, 08:28:16 pm »
oh. O.O
Thanks for the solution. :D
also, what's the difference of using Str1 and A? (Static and variable)
Sig wipe!

Offline Runer112

  • Project Author
  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2289
  • Rating: +639/-31
    • View Profile
Re: Axe Q&A
« Reply #1454 on: April 05, 2012, 08:37:15 pm »
Depending upon usage, there are quite a few differences between using static pointers (constants) and variables. Most can simply be summarized with the fact that constants are more optimized. To cite the two examples from your code:
"Pic1"→I = 3 bytes (not counting the size of the string data)
→{I+2} = 8 bytes

Whereas with a constant:
"Pic1"→Str1 = 0 bytes (not counting the size of the string data)
→{Str1+2} = 4 bytes

I also just realized that the second code statement can be further optimized by making the store a full 2-byte store. It may sound counter-intuitive that saving 2 bytes instead of 1 byte is actually smaller, but it works out this way because Axe works with 2-byte values and the conversion to a 1-byte value costs a byte when storing to a constant address.
Note: You shouldn't always convert 1-byte stores to a constant address into 2-byte stores to save size, as many times, overwriting the second byte at the store address is undesired. However, in this case you'll end up overwriting a 0 with another 0, so it doesn't matter
« Last Edit: April 05, 2012, 08:40:22 pm by Runer112 »