BASIC arrays
Julie Stamp (8365) 474 posts |
I’m writing a BASIC program that uses lots of floating-point arrays, such as
which I then pass into a procedure DEFPROCprocess(x()). I’d like to be able to read even more arrays from a file. I could have something like
and then later
but this is long winded (I don’t think ON PROC would work here, as you’d be limited by line length), and puts a limit on the number of arrays loadable. Another way could be to use one big array
but that means you have to have a very big DIM if even just one array has N% large, and to pass a single array through to PROCprocess I’d have to copy it into a temp(N%,4). So, is there a way to do this, or is it time to give up and rewrite it all in C? |
Clive Semmens (2335) 3276 posts |
I’m not quite sure what you’re doing here, but you can have
to import arrays of different sizes into PROCblahblah (OR FNblahblah) – the local array is killed (no memory leak) at the end of the PROC or FN. Don’t try to reDIM a() inside the PROC or FN though – whatever its dimensions are in the outside world are what they must be within the procedure or function. You might be using b and c to tell the function or procedure what its dimensions are – possibly even how many dimensions it has. You could even do the loading of the arrays within the procedure or function, and only determine the sizes of the arrays when you do the loading. (sorry about some edits! trying to make more points, more clearly.) |
Julie Stamp (8365) 474 posts |
I’d like to have a ‘load’ button on the screen, so that extra arrays may be brought in from files, and then referred to afterwards. So I’d effectively be able to have more arrays user11(56,6) … appear as required, and then pass all of those through PROCprocess later on. |
Rick Murray (539) 13850 posts |
I think the only sensible way to do that is to manage your own array heap above HIMEM (fiddle WimpSlot and don’t tell BASIC so you’ll get the extra memory for your own use), and then use the indirection operators to access the data. I think it might be block%|offset% for floating point? I don’t know, I’ve never used an FP array in that manner. |
Clive Semmens (2335) 3276 posts |
Ah, I see. Yup, it’s possible – the way I’d do it is to put whatever you want to import into the program into a file that you’d drag and drop onto the icon of the app on the icon bar. The program would then load your file, and extract the details of the arrays it needed to create, then create those arrays within a function or procedure, so it could recover the memory afterwards. |
Clive Semmens (2335) 3276 posts |
Rick – I’ve never used indirection operators for FP…and creating and destroying normal arrays with LOCAL in procedures and functions works perfectly well… |
Graeme (8815) 106 posts |
It is | but you can’t use it like block%|offset%, you must use: Also, different versions of BASIC can store different lengths for floating point numbers. Early versions store into 5 bytes of memory, later versions use 8 bytes. |
Rick Murray (539) 13850 posts |
Ah, it only works in that form. Fair enough.
Just assume eight bytes used, and let BASIC sort itself out. The most you’ll risk is wasting three bytes per value on standard BASIC. Better than messing up completely with the more numerically capable versions (BASIC64 or BASICVFP).
I think this depends upon the expected lifespan of the data, and how much it might be expected to change during runtime. I would still build and manage my own array structure if I had to do it in BASIC… |
Steve Drain (222) 1620 posts |
Not without some ‘magic’. ;-) I think the answer requires named arrays, or perhaps an array of arrays. There are some well-known ‘tricks’ to deal with named variables and named functions using only BASIC, but not named arrays. It can be done, but is a bit convoluted and not very robust. If it were important, it would not take very much assembler, I think. The other problem is importing the array values from a file, which is long-winded, and for floats has to use the PRINT/INPUT interface. It takes a bit more to do this as a block load, but my Basalt would do it, so the assembler code exists.
If you can, I think it is. ;-) The alternative is to use indirection, as suggested, but it is a bit fiddly. |
Steve Drain (222) 1620 posts |
A thought. Do the arrays have to be held and used simultaneously or are they dealt with sequentially. If the latter, only one array reference is required and this can be manipulated to use different data of different dimension sizes with very little ‘magic’. |
Clive Semmens (2335) 3276 posts |
Well – as long as you don’t want more data in memory simultaneously than the available memory, all is well: you create the space for the current set as you enter a proc or fn, and recover it as you exit the proc or fn, ready to load the next lot. Nothing terribly fiddly about it – far simpler than handling the WIMP, for example, which really is quite fiddly… You do have to be careful if you DIM blocks of memory, rather than proper arrays: it’s awfully easy to lose track of those and end up with memory leaks. |
Julie Stamp (8365) 474 posts |
Sequentially. Magic it is then :-) Here’s what I’ve put together. Once loaded (see below) I have an array of pointers user_ptr%() to the underlying array structures, which sit in the heap. To process the arrays I set a global variable user() to point to each array structure in turn, and call PROCprocess(user()). I have to dimension user() to create the variable. I didn’t want to put user() as local in PROCprocess_arrays as I’m unsure what would happen at the end of the procedure after I’ve fiddled with it!
To actually load the arrays, I use a temporary local array temp(), into which I read the data using INPUT#. I then use routines from !Routines to copy the underlying structure for temp() to the heap (above HIMEM).
FNptr(“temp()”) is like PTR in Basalt, returning the address of the underlying structure. (I believe. I used Steve’s SH manuals to figure out how to do this anyway). !FNlvalue_ptr(“user()”) is effectively the hidden pointer variable that gets automatically derefenced whenever you use user(), so I am pleased, I’ve now got several arrays loaded from a file at the same time in my application, and with, as Steve says, only a very small bit of assembler. |
Steve Drain (222) 1620 posts |
Excellent. That is very similar to what I had in mind. ;-) |
Steve Drain (222) 1620 posts |
You do not show FNptr, so I may be stepping on toes, but it is quite a handy thing to have, so here is how I do it. The assembly is really trivial to get the l-value of any variable with: CALL_LVAL,<variable>,lval% .
This is one of my codelets. ;-) ._LVAL LDR r0,[r9],#8 LDR r1,[r9] STR r1,[r0] MOV pc,lr As it stands, that has no input checks, so it is a bit fragile. With an array, |