+TheBF Posted May 22, 2017 Share Posted May 22, 2017 (edited) While looking at how to implement sprites I studied the old TI-Forth code that Lee has published for some clues. I found this piece of code that seemed hard to understand. : DXY ( X2 Y2 X1 Y1 --- X^2 Y^2 ) ROT - ABS ROT ROT - ABS DUP * SWAP DUP * I am sure the author was very proud of this tight statement with all stack juggling working out just perfect. But I find it hard to understand the intentions of the code. So I took it apart by removing the code that repeats and giving it a name. This is how Forth code is commonly "re-factored". So the first this I see is DUP *. Take a number on the stack and make a copy then multiply them together. That is like saying X^2 in BASIC. So I made this word: : ^2 ( n -- n') DUP * ; Now at the Forth console I can type 2 ^2 . and it prints 4. Perfect. Also noticed the phrase " - ABS" is used twice... so if you subtract 2 numbers and take the absolute value you have a calculation for the Delta, between them. So how about this definition: : DELTA ( n n -- n') - ABS ; I also noticed the "ROT ROT". Rot takes 3 numbers on the stack and "rotates" the 3RD number to the TOP position. So 1 2 3 ROT will give you 2 3 1 on stack. Doing 1 2 3 ROT ROT will give you 3 1 2, so it is like a backwards rotate, There is a Forth word to do that called "-ROT" so I replaced those 2 words with 1 word. So with those factors removed the DXY word became. : DXY ( x2 y2 x1 y1 -- x^2 y^2 ) ROT DELTA -ROT DELTA ^2 SWAP ^2 ; It still has some stack juggling noise in it, but by choosing meaningful names I can see that it takes 2 sets of x/y coordinates, gets the delta between the x and y parts and computes the square of each delta. IMHO, that is how you make Forth easier to read for the next poor guy who has to read your code. Create small, well named definitions. Soon the code starts to read clearly. B Edited May 22, 2017 by TheBF 1 Quote Link to comment Share on other sites More sharing options...
Willsy Posted May 22, 2017 Share Posted May 22, 2017 (edited) Yes that's evil! I like the way you factored it. I think this would do the same, no? >r swap >r - abs dup * ( x^2 ) r> r> - abs dup * ( x^2 y^2 ) Again, not as neat as yours but easier than the first version. I always forget which way ROT rotates! Edited May 22, 2017 by Willsy Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted May 23, 2017 Share Posted May 23, 2017 Because DXY reports the squares of Δx and Δy, the two instances of ABS are superfluous. When I developed fbForth 2.0, I converted most of the graphics primitives from high-level Forth to Assembler code before hoisting them into cartridge space. I optimized words where I saw the need. DXY was one such word. Now, optimizing your DELTA in this manner would render it, perhaps, an unnecessarily expensive synonym for - . ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted May 23, 2017 Share Posted May 23, 2017 For the high level Forth, a combination of ROT and return stack use (below, “S:” represents the parameter stack and “R:”, the return stack): : DXY ( x2 y2 x1 y1 --- x^2 y^2 ) ROT - DUP * >R \ S:X2 X1 R:dy^2 - DUP * \ S:dx^2 R:dy^2 R> \ S:dx^2 dy^2 ; ...lee Quote Link to comment Share on other sites More sharing options...
+TheBF Posted May 23, 2017 Author Share Posted May 23, 2017 (edited) LOL. Very cool Lee. Of course the ABS is redundant. The master speaks again. So I thought since I was still up I would measure these beasts. I did a version of mine with DELTA removed as well. In my current kernel -ROT is : -ROT ROT ROT ; so no speed advantage there. But... there was no real penalty for factoring out ^2 on my system. Yes there was a penalty but it was masked by the very slow ROT and -ROT words written in Forth. This black screen version has code words. Here is the code. (apologies for the timer name. I ran out of space in 8K so I squeaked it in) :-) I fixed the copy and paste errors in the original version. This one seems correct now. \ factoring dxy tests HEX \ TMR! sets the 9901 timer to >3FFF \ TMR@ reads the 9901 timer : TIDXY ( X2 Y2 X1 Y1 --- X^2 Y^2 ) ROT - ABS ROT ROT - ABS DUP * SWAP DUP * ; : ^2 ( n -- n^2) DUP * ; : DELTA ( n -- n') - ABS ; : BFDXY ( x2 y2 x1 y1 -- x^2 y^2 ) ROT DELTA -ROT DELTA ^2 SWAP ^2 ; : BFDXY2 ( x2 y2 x1 y1 -- x^2 y^2 ) ROT - -ROT - ^2 SWAP ^2 ; : WILLXY >R SWAP >R - ABS DUP * ( x^2 ) R> R> - ABS DUP * ; ( x^2 y^2 ) : LEEXY ( x2 y2 x1 y1 --- x^2 y^2 ) ROT - DUP * >R \ S:X2 X1 R:dy^2 - DUP * \ S:dx^2 R:dy^2 R> \ S:dx^2 dy^2 ; : INPUTS 10 20 30 40 ; : .OUTPUT ( n n t -- ) >R . . 3FFF R> - . ; : TESTTI INPUTS TMR! TIDXY TMR@ .OUTPUT ; : TESTBF INPUTS TMR! BFDXY TMR@ .OUTPUT ; : TESTBF2 INPUTS TMR! BFDXY2 TMR@ .OUTPUT ; : TESTWILL INPUTS TMR! WILLXY TMR@ .OUTPUT ; : TESTLEE INPUTS TMR! LEEXY TMR@ .OUTPUT ; Edited May 23, 2017 by TheBF Quote Link to comment Share on other sites More sharing options...
+TheBF Posted May 23, 2017 Author Share Posted May 23, 2017 (edited) I corrected my earlier post. I should not do this so late at night clearly. Edited May 23, 2017 by TheBF Quote Link to comment Share on other sites More sharing options...
+TheBF Posted May 23, 2017 Author Share Posted May 23, 2017 (edited) I really need to get a life :-) But I had to see what coding the word would do and the results are amazing. CODE: DXY ( x2 y2 x1 y1 --- x^2 y^2 ) *SP+ R0 MOV, \ x1->R0 *SP+ TOS SUB, \ y1-y2->tos *SP R0 SUB, \ x1-x2->R0 TOS R3 MOV, \ dup tos TOS R3 MPY, \ tos^2, result->R4 (tos) ( edit: removed and instruction here) R0 R2 MOV, \ dup R0 R2 R0 MPY, \ RO^2 R1 *SP MOV, \ result to stack NEXT, \ 16 bytes END-CODE The code word is the 2 bytes smaller (after editing) than Lee's Forth version I believe, 18 bytes vs 16 But it is 3.375 times faster than Lee's version and 5.5 Times faster that my factored version. Just adding ROT to word slows it down a lot it seems. Makes me wish for register based locals for things like this. Edited May 23, 2017 by TheBF Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.