Quote:
Perhaps if you had started from scratch, you'd have come out with an even faster version. That was the first time I ever used GROB in a program, so I might have not used the best approach for the task.
If I were doing this from scratch, I'd probably pre-allocate the space for the final grob first, then move the pixel data to the appropriate place in the final file while looping. It's a little messier to do that, but I believe there would be a noticeable savings in execution time (especially for larger grobs). Doing it that way would mean there's much less movement of data each time a row is added. As it stands now, there's at least the potential for a new copy of the main grob to be made with each loop iteration. So as it stands now, each row addition slows down as the grob gets larger.
I realize now that I made another change, which is to output a 20-bit row instead of 16. It's a minor change, but didn't want that to confuse anyone.
The source code follows, exactly as it was compiled by Debug4x. If you want to try this with the built-in assembler (ala menu 256), you'll have to pull it apart into separate pieces. I've attempted to use enough comments to make it readable even if you're not familiar with SysRPL/ASM:
RPL
INCLUDE DirMacro.s
ASSEMBLE
Dir <Num2Grob>
RPL
::
CK1NOLASTWD ( must have 1 parameter )
CK&DISPATCH1 ( integer or real will be converted to real )
real ( any other type in stack level 1 will generate error )
::
%ABSCOERCE ( don't want negative, and convert to system binary )
NULLHXS BINT16 EXPAND ( create an object of the appropriate size in stack level 1 )
CODEM
SAVE % save RPL status registers
% obtain the address of hxs, move into D1
D0=(5) =DSKTOP
A=DAT0 A
D0=A
A=DAT0 A
D1=A
% change the ob type from HXS to GROB
LC(5) =DOGROB
DAT1=C A
% set row and column size (ob size is already set)
D1=D1+10
C=0 W
LC 1400001
DAT1=C 10
% put data to be reversed in C.A
D0=D0+5
C=DAT0 A
D0=C
D0=D0+5
C=DAT0 A
% reverse 5 nibbles of C.A into D.A
LA 04
B=A B
{
P=C 0
LA 84C2A6E195D3B7F0
P=0
DSL A
D=A P
CSR A
B=B-1 B
UPNC
}
C=D A
% write the reformatted bits into the GROB
D1=D1+10
DAT1=C A
% restore registers and return to RPL loop
LOADRPL
ENDCODE
( drop the number, leave the GROB )
SWAPDROP
;
;
ASSEMBLE
Dir <BPRM>
RPL
DEFINE GetRowCount 2GETLAM
DEFINE GetCurPrime 1GETLAM
DEFINE PutCurPrime 1PUTLAM
::
( check for 1 parameter )
CK1NOLASTWD
CK&DISPATCH1 ( zint will be converted to real )
real ( anything other than zint or real will generate error )
::
%ABSCOERCE ( no negative num, convert to system binary )
Z1_ ( place zint 1 on stack as the initial prime )
ZEROZEROTWO DOBIND ( bind local vars [unnamed] )
NULLPAINT_ ( start with a blank GROB )
( main loop )
GetRowCount #1+_ONE_DO (DO) ( do for each row )
( note that the first prime converted will actually be 2 instead of 1 )
( this is to make the output match that of Gerson's posting )
GetCurPrime FLASHPTR Prime+ DUP PutCurPrime ( get the next prime )
ID Num2Grob ( convert the current prime to a GROB )
FLASHPTR GROBADDext ( add the new GROB to the one on the stack )
LOOP
ABND ( "unbind" the local vars )
;
;
ASSEMBLE
Dir <TSTBPRM>
RPL
::
CK0NOLASTWD ( no args expected )
SysTime ( beginning timestamp )
% 128 ID BPRM ( make grob for 128 primes )
SysTime ( ending timestamp )
( leave GROB on stack, find difference in timestamps and convert to seconds )
ROT bit- HXS>% % 8192 %/
;