Pointer to Part of an Array
BlitzMax Forums/BlitzMax Beginners Area/Pointer to Part of an Array
| ||
I am trying to create a simulation of Conway's Game of Life. (http://en.wikipedia.org/wiki/Conway's_Game_of_Life) To do this I need two 2D arrays. One with the current state, and one to create the next generation state on. Then to create the subsequent generation, I must reverse the roles of the arrays so the second is the current generation, and the first is the next generation, and so on. (Similar to flipping in double-buffering). So far I have made an array[x, y, 2]. The most obvious thing to do is create a variable which is either 0 or 1 to keep track of which array is which. However I was thinking of creating two pointers to the [x, y] part of the array, and not the [2] part. Then swapping around the pointers. So I can just use firstarray[x, y]. But I'm not sure how to do this exactly, or if it's a good solution. Any advice will be appreciated. Thanks. |
| ||
you can't BM arrays are objects not continous int / float blocks. If you need that use Banks instead. |
| ||
In that case I think I'll stick with a chooser variable ;) |
| ||
BM arrays are objects not continous int / float blocks. Are you sure? That's not been my experience. Object Arrays are just an array of pointers, yes, but int and float arrays appear to be a block of contiguous memory. Granted you have to point inside the array ( Array[0] or Array[0,0] ) but the data does appear to be contiguous. Proof of Concept: Global IntArray:Int[,]=New Int[101,101] Local B:Byte Ptr=Varptr(IntArray[50,50]) Print IntArray[50,53] B[12]=2 Print IntArray[50,53] |
| ||
I'm with Gabriel on this one... from my experience, arrays of primitives (byte, short, int, float, double, long) appear to use contiguous memory. |
| ||
What about arrays of arrays...Local MyArray:Int[50][50][2] Then you just need a variable that is either 0 or 1 which you use to refer to the third aspect of the array. It's really an array of arrays of arrays. Otherwise I would just use two separate 2d arrays and an if-else to jump between them. |
| ||
They often will appear to use contiguous memory - but don't count on it. These days memory fragmentation isn't as much of an issue (pretty much a non-issue really, especially on OSes with buddy-heap type memory managers) but you could conceivably create an array larger than your largest block of free memory. From what I can tell, BlitzMAX arrays are more like ArrayLists than traditional arrays. |
| ||
I would recommend using banks as 2d arrays and accessing with pointers. |
| ||
If you look at the source of some BRL modules, arrays are treated as contiguous memory, such as CurrentTime and CurrentDate of the System.mod uses local byte arrays and passes them by pointers to C functions. |
| ||
Why couldn't you just swap the array references like this? |
| ||
Or you could put all the update and draw stuff in a function which takes two arrays as input. Then in the main loop you call this function with array1,array2 and then call it again with array2,array1. |
| ||
Thanks for your suggestions! I think I will try something like TomToad's solution. I'll have two arrays and swap these two around after each generation. Thanks again. |
| ||
They often will appear to use contiguous memory - but don't count on it. These days memory fragmentation isn't as much of an issue (pretty much a non-issue really, especially on OSes with buddy-heap type memory managers) but you could conceivably create an array larger than your largest block of free memory. So how is that different from C++? C++ programmers constantly rely on arrays being in blocks of contiguous memory, so why would BlitzMax be any more prone to creating an array larger than your largest block of free memory than C++ is? |
| ||
Isn't an exception thrown or something if an array can't be allocated in contigous memory in C++? |
| ||
long int array[999999999999999999999999999]; Anyone willing to try it? :) |
| ||
Isn't an exception thrown or something if an array can't be allocated in contigous memory in C++? Interesting thought. I've never experienced it, but then I've never experienced BlitzMax failing to allocate it in contiguous memory either. I'd like an official response from BRL if possible though, because my TrueVision modules is completely dependant on arrays using contiguous memory, and it's going to become bloody slow to do some things if I can't rely on it. |
| ||
I've always assumed its contiguous as well. I seem to recall looking in the blitzmax module code and seeing the array type, with only one pointer to a block of memory. I didn't see any sign of a linked list or anything like that. If they had a linked list they'd have to be checking within which link an array index lies before you can access it, which would be horrendous. |
| ||
Found this line under the Blitz.mod in array.c file:arr=(BBArray*)bbGCAlloc( BBARRAYSIZE(size,dims),(BBGCPool*)&bbArrayClass ); This is part of the `new array` code, and allocates apparently a single block of memory for each `dimension`, unless I'm not interpreting it right - so maybe each dimension is stored together as one block of memory, and for a 1 dimensional array there is just one single block? However, a look at blitz_memory.c is interesting, particularly in the bbGCMemAlloc subroutine. e.g. if( size>(MAXSIZE-SIZEALIGN) ){ p=bbMemAlloc( size ); MAXSIZE is 256, so likelyhood is that bbMemAlloc will be called..., which calls: b=malloc(size+4+SIZEALIGN); So now we're into malloc(). I'm guessing therefore that you get a solid block of memory that's contiguous, at least for each dimension. You'd think that it's supposed to be safe to get a pointer to the first element of the array and then access all the elements with the pointer, which would be seriously compromized if the contiguous indexes were split up into multiple memory sections. I would think Mark would've designed it so that where there are natural breaks, ie where you have an array of arrays or an array with more than one dimension, that the memory for those extra arrays or dimensions would be separate areas with their own `base pointers`. I don't think Mark would've overlooked the possibility that people would try to access array elements with pointers, which is a language feature, only to have it create creashes or array bounds exceptions for no reason that the user can find apparent. Anyone know different? |
| ||
Try this test program:Local OneD:Int[1024*1024] '4 megabytes of Int's Print "Testing 4MB memory one-dimensional array" 'Test continuity Local Last:Int=Int(Varptr(OneD[0])) Local Current:Int Local Cont:Int=True For Local Count:Int=1 To (1024*1024)-1 Current=Int(Varptr(OneD[Count])) If Current<>Last+4 Print "Last: "+Last+", Current: "+Current+", Discontinuous Memory!" Cont=False WaitKey EndIf Last=Current Next If Cont=True Then Print "Memory was continuous!" Else Print "Memory was not continuous!" Print "~nTesting two-dimensional array 1024x1024 (4 MB)" Local TwoD:Int[1024,1024] '4 megabytes of Int's 'Test continuity For Count=1 To 1024 If Varptr(TwoD[Count-1,1023])<>Varptr(TwoD[Count,0])-4 Then Print "Separate memory for everything in ["+Count+",x]" Next Local Diff:Int=False For Count=1 To 1024 If Varptr(TwoD[0,Count-1])<>Varptr(TwoD[0,Count])-4 Print "Separate memory within [0,"+Count+"]" Diff=True EndIf Next If Diff=True Then Print "Memory within dimension [0,x] is discontinuous" Else Print "Memory within dimension [0,x] is all continuous" If this is correct and I'm interpreting it right, it suggests that: a) For a one dimensional array, everything within that one dimension is in contiguous memory. b) In a two-dimensional array, each of the first dimension elements points to a whole separate block of contigous memory which holds all of its children. So array[0,0] array[0,1] array[0,2] array [0,3] are all contigous, but array[0,0] array[1,0] and array[2,0] are separate memory areas. If you have more dimensions than 2 the same still applies, for each level, if there is a level below it, all of the contents of the below level are in a contiguous block of memory refereced by the current element in the current level. The only thing this did not test is fragmented memory and whether this introduces a split. |