An array slices question

BlitzMax Forums/BlitzMax Beginners Area/An array slices question

ImaginaryHuman(Posted 2005) [#1]
I quote the documentation:

BlitzMax also does not support a 'Redim' operation. Instead, you can use slices. For example:
Global my_array$[100] 'create a 100 element string array
my_array=my_array[..200] 'now a 200 element array!

My question:

Does resizing the array, where my_array=my_arrays[..oldsize+extra], keep the original contents of the array, or does it just give you a bigger empty array that forgets what was stored in it?

If I store 100 numbers in the array and use [..200] to make it bigger, will those 100 numbers still be there?

Does doing this involve some kind of a memory copy - ie does it make a new 200 element array and copy the content from the old one? If it makes a new array but *doesn't* copy the content, do I have to do that myself?

Also, on the topic of arrays.... I notice you can't use EachIn as a loop counter where the array is an array of function pointers? ie

where myfunctions[] is an array of function pointers...
	For counter=EachIn myfunctions
		myfunctions[counter](param)
	Next

doesn't compile. ???


ImaginaryHuman(Posted 2005) [#2]
Oh, I figured out the EachIn part ... should be:

Local tempfunc(param:Int)
For tempfunc=EachIn myfunctions
   tempfunc(param)
Next

Hey, that's a nice little speedup. 72 millisecs for 1 million calls, compared to 80 millisecs for a regular for-next numerical loop. The only drawback is that since the `loopcounter` is tied into the EachIn thing, there can only be one value for the tempfunc per iteration. It'd be nice to be able to do a procedural EachIn such as:

For counter=0 to 9
    NextIn(myfunctions)(param)
Next

ie to keep track of where I am in reading the myfunctions array rather than recomputing the offset for every call. Or maybe an EachIn loop should also let you define a To amount, to stop somewhere? And maybe a From ... ie

Local tempfunc(param:int)
For tempfunct=EachIn myfunctions[18] To 49
   tempfunct(param)
Next

would be nice :-D

But anyway, I still need someone to explain the array resize thing. :-)


PowerPC603(Posted 2005) [#3]
When you resize an array using slices, the contents of the array are copied also.

I do this in my game too.
I'm trying to create a spacesim (like Freelancer), which needs info about each object in space (location, price, name, description, cargospace needed = for commodities to trade, ...).
I'm loading a textfile, which holds all this data, into arrays.
In this file, there are datablocks (parts of the file which identify each object).
Every time a datablock has been found, the appropriate array is resized (size increased by 1).
Contents are not lost.

If you want to take a look at the source-code:
http://users.pandora.be/vge/SG/SG.zip


ImaginaryHuman(Posted 2005) [#4]
Hmm ok. Just out of curiosity, why don't you make your array a whole lot bigger like add on an extra 20 entries, and then just resize it when you reach the limit by adding 20 more? hardly any memory loss and much less resizing needed?


PowerPC603(Posted 2005) [#5]
If a sector has only 3 stations, then it would be too big.
I can imagine that four bytes (an Int to hold the memory-pointer to a type-instance) per index isn't much for computers these days, but if you have about 100 sectors, then it really can eat some memory that would be usefull for something else.

And also, each time a new station is found in the datafile, a field is increased by 1.
The resizing uses this field to resize the array to it's new size, and in other functions (when the 3D module is out and I can really fly in space), those functions will use that field for a for-next loop, to process all stations inside a sector.
If the size is too big (and no type-instances are linked to each index), then I would get errors, stating that there is no object present at that index (the ones that aren't used).

Okay, I could use some extra checks to detect if an instance is linked, but that's extra work for the computer.

Now it's just looping from index 1 to the number of stations inside that sector, and I'm sure that each station exists.
No need to check references and much less errors.
Little more time for the processor to do other things.


John Pickford(Posted 2005) [#6]
I'd be tempted to start the array off very large and shrink it once you've loaded all the data. Only one resize compared to resizing it for each element.


PowerPC603(Posted 2005) [#7]
I'll see to that, that's a better option, thanks.

That way my loading loading would be a bit faster.
It's fast now, because the datafile holds just a small bit of data, but will be bigger eventually, much bigger.

So, ...

When a new sector has been created, just set the size of the stations-array to 20 (default setting), and increase the field "NumStat" (variable to hold the number of stations inside current sector) by 1 if a station has been found, add it's data to the array at index "NumStat" and move on to the next one.

Once the datafile reached EOF, close the file and resize all arrays at once.

I kinda like it.

When I find the time, I'll rewrite the entire loading-routine.

It took me about 7 rewrites in B3D to get the most efficient (to me anyways) loading-routines.
But each time, adding more functionality and flexibility.
Now each field in the datafile can be in any order inside a datablock, non-recognised fields and statements in the file are ignored and unknown datablocks are also ignored.
Spacing and indentation is also processed automatically now.

I've converted those loading routines to BMax as soon as I got BMax Beta, so this was my first project in BMax.
No bad job if I may say so myself.

But thanks again John.


teamonkey(Posted 2005) [#8]
@PowerPC603
Have you found any advantage of using this method over TList?


PowerPC603(Posted 2005) [#9]
Direct access to a station.
That way I only have to let the game remember some numbers, which are stored automatically inside the player-type (which isn't present yet).

The player-type will hold the fields:
- SectorNumber (number of the sector where the player is located)
- StationNumber (number of the station where the player is docked)
- CommodityNumber (number of the commodity the player just bought or sold or whatever)

The I can do this for example:
Universe.ASectors[SectorNumber].AStations[StationNumber].AComm[CommodityNumber].Name$

to access a specific commodity inside a specific station, in the sector where the player is located.

But it will take another rewrite to get everything going, when the 3D module is published.

I'll consider the use of TLists when I'm rewriting the game.
This was just some first exercise for getting to know BMax.
In B3D I didn't have TLists (ones you could define separately anyways), so I just converted to routines from B3D to BMax, using the same approach (arrays of types).

I've never used linked lists before, so I avoided it.
In B3D I always used arrays of types and no For...Each loop, to loop through all type instances.

But I can already see the benefit of using TLists, now that they can be defined separately, and inside types.