Page 2 of 3
Re: [NXC] ArrayInit for 2D arrays
Posted: 04 Jun 2011, 09:42
by HaWe
2 arrays with both 122x122 is too big => file error -1!
Code: Select all
#define ArrayInit2D(bar, tmp, x, y) { \
ArrayInit(tmp, 0, y); \
ArrayInit(bar, tmp, x); \
}
task main(){
int ibar[][], itmp[];
float fbar[][], ftmp[];
int i, j, imax, jmax;
jmax=imax=122;
ArrayInit2D(ibar, itmp, imax, jmax);
for (i=0; i< imax; ++i) {
for (j=0; j< jmax; ++j) {
ibar[i][j]=(i+1)*(j+1);
TextOut(0,48, " ");
NumOut(0,48,ibar[i][j]);
}
}
ArrayInit2D(fbar, ftmp, imax, jmax);
for (i=0; i< imax; ++i) {
for (j=0; j< jmax; ++j) {
fbar[i][j]=(i+1)*(j+1);
TextOut(0,32, " ");
NumOut(0,32,fbar[i][j]);
}
}
while (true) {}
}
Re: [NXC] ArrayInit for 2D arrays
Posted: 04 Jun 2011, 09:44
by HaWe
now init array _1 by 122x122,
then downsizing array_1 to 5x5,
then try to init array_2 by 122x122 => program aborts (file error -1):
Code: Select all
#define ArrayInit2D(bar, tmp, x, y) { \
ArrayInit(tmp, 0, y); \
ArrayInit(bar, tmp, x); \
}
task main(){
int ibar[][], itmp[];
float fbar[][], ftmp[];
int i, j, imax, jmax;
jmax=imax=122;
ArrayInit2D(ibar, itmp, imax, jmax);
for (i=0; i< imax; ++i) { // test write
for (j=0; j< jmax; ++j) {
ibar[i][j]=(i+1)*(j+1);
TextOut(0,48, " ");
NumOut(0,48,ibar[i][j]); // test read
}
}
ArrayInit2D(ibar, itmp, 5, 5); // trying to downsize for free mem.....
ArrayInit2D(fbar, ftmp, imax, jmax); // file error !!
for (i=0; i< imax; ++i) { // not executed
for (j=0; j< jmax; ++j) {
fbar[i][j]=(i+1)*(j+1);
TextOut(0,32, " ");
NumOut(0,32,fbar[i][j]);
}
}
while (true) {}
}
the same issue it's for 1D arrays:
Code: Select all
task main(){
int ibar[];
float fbar[];
int i, imax;
imax=15000;
ArrayInit(ibar, 0, imax);
for (i=0; i< imax; ++i) { // test write
ibar[i]=i+1;
TextOut(0,48, " ");
NumOut(0,48,ibar[i]); // test read
}
ArrayInit(ibar, 0, 5); // trying to downsize for free-mem....
ArrayInit(fbar, 0, imax); // file error!
for (i=0; i< imax; ++i) { // not executed
fbar[i]=(i+1);
TextOut(0,32, " ");
NumOut(0,32,fbar[i]);
}
while (true) {}
}
so the memory allocated for array_1 seems NOT to be free-ed.
Can anyone confirm this?
Re: [NXC] ArrayInit for 2D arrays
Posted: 04 Jun 2011, 17:42
by afanofosc
A float is 4 bytes long so you can't ever allocate 15000 * 4 bytes worth of memory. You have 32k bytes to work with period. 15000 ints is okay as that is only 30k bytes.
John Hansen
Re: [NXC] ArrayInit for 2D arrays
Posted: 04 Jun 2011, 17:55
by HaWe
Heaven, how could I have missed that?
Now it's fine indeed:
no downsizing the 1st array before init the 2nd one => runtime error
Downsizing the 1st array => runs fine!
so the memory is indeed set free - amazing!
Code: Select all
task main(){
int ibar[];
float fbar[];
int i, imax;
imax=15000;
ArrayInit(ibar, 0, imax);
for (i=0; i< imax; ++i) {
ibar[i]=i+1;
TextOut(0,48, " ");
NumOut(0,48,ibar[i]);
}
ArrayInit(ibar, 0, 5); // now first downsize 1st array => variable memory is set free, no runtime error!
imax=7500;
ArrayInit(fbar, 0, imax);
for (i=0; i< imax; ++i) {
fbar[i]=(i+1);
TextOut(0,32, " ");
NumOut(0,32,fbar[i]);
}
while (true) {}
}
Re: [NXC] ArrayInit for 2D arrays
Posted: 04 Jun 2011, 18:30
by afanofosc
What actually happens is that the memory is not immediately freed. Rather, it is marked as not used and the next time you try to allocate memory with ArrayInit if it runs out of memory it tries to compact the dataspace, essentially running a garbage collector, and then it retries the allocation. If it fails the second time then you will get a file error abort.
Something to keep in mind is the amount of memory used by any temporary arrays that get used under the hood or explicitly when you work with 2d+ arrays and use temps to allocate the space for the N+1 dimension. Once you are done using the temp array you can ArrayInit it back to a zero length array to free up that memory. The compiler, if it creates one of these temporary arrays for you, may not be so clever about freeing up that memory (I don't recall off hand how that works).
John Hansen
Re: [NXC] ArrayInit for 2D arrays
Posted: 04 Jun 2011, 20:25
by HaWe
I think I don't quite understand what you mean about 2D+ arrays. Are they different in handling when resizing them up and down?
My intention was simply like the following:
Code: Select all
ArrayInit(bar, 0, 1); //"small declaration"
ArrayInit(foo, 0, 1); //"small declaration"
//upsizing array1 when mem space is needed (e.g., astar calculations)
ArrayInit(bar, 0, imax);
//... do something
// downsizing when intermediate calculations are done
ArrayInit(bar, 0, 1);
//upsizing array2 when mem space is needed (e.g., bug2 calculations)
ArrayInit(foo, 0, jmax);
//... do something
// downsizing when intermediate calculations are done to free all memory again
ArrayInit(foo, 0, 1);
with multi-dim arrays (2D, maybe 3D) I would do it similarily. Would that be right or wrong?
according to the TO question a 2D size changing macro could be the following (works with all (either) different array types):
Code: Select all
#define ArrayInit2D(bar, tmp, init_val, dimx, dimy) { \
ArrayInit(tmp, init_val, dimy); \
ArrayInit(bar, tmp, dimx); \
}
use:
declare the 2D-array variable type (int/long/char/float/double), ;)
declare a 1D-tmp array of same type
use ArrayInit2D with array, temp, init_value, and array (x,y) dimensions
Code: Select all
int myArray[][], tmpArray[];
ArrayInit2D(myArray, tmpArray, 111, 10, 20);
// creates a 10x20 array of integer and initializes it with 111
ArrayInit2D(myArray, tmpArray, 111, 1, 1); // resizes myArray and tempArray to the minimum dim [1]
ArrayInit2D(myArray, tmpArray, -1, 15, 30); // upsizes myArray to 15x30 initialized with -1
Re: [NXC] ArrayInit for 2D arrays
Posted: 04 Jun 2011, 21:13
by muntoo
More Array goodness:
Code: Select all
/* Program Name: "ArrayFunctions.nxc"
** Author: muntoo
** Programmed In: NXC
Description:
*/
/*
Copyright 2011 muntoo
This file is part of Memory Manager.
Memory Manager is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Memory Manager is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Memory Manager. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ARRAYFUNCTIONS_NXC__
#define __ARRAYFUNCTIONS_NXC__
#define ArrayInitD1(arr,val,arrlen1) ArrayInit(arr,val,arrlen1);
#define ArrayInitD2(type,arr,val,arrlen1,arrlen2) while(1) {type arrtemp[]; ArrayInit(arrtemp,val,arrlen2); ArrayInit(arr,arrtemp,arrlen1); break;}
#define ArrayInitD3(type,arr,val,arrlen1,arrlen2,arrlen3) while(1) {type arrtemp[]; type arrtemp2[][]; ArrayInit(arrtemp,val,arrlen3); ArrayInit(arrtemp2,arrtemp,arrlen2); ArrayInit(arr,arrtemp2,arrlen1); break;}
#define ArrayInitD4(type,arr,val,arrlen1,arrlen2,arrlen3,arrlen4) while(1) {type arrtemp[]; type arrtemp2[][]; type arrtemp3[][][]; ArrayInit(arrtemp,val,arrlen4); ArrayInit(arrtemp2,arrtemp,arrlen3); ArrayInit(arrtemp3,arrtemp2,arrlen2); ArrayInit(arr,arrtemp3,arrlen1); break;}
#define ArrayLenD1(arr) (ArrayLen(arr))
#define ArrayLenD2(arr,arridx1) (ArrayLen(arr[arridx1]))
#define ArrayLenD3(arr,arridx1,arridx2) (ArrayLen(arr[arridx1][arridx2]))
#define ArrayLenD4(arr,arridx1,arridx2,arridx3) (ArrayLen(arr[arridx1][arridx2][arridx3]))
#endif
Disclaimer: Code is untested. If your robot blows up, it's not my fault.
Re: [NXC] ArrayInit for 2D arrays
Posted: 04 Jun 2011, 21:22
by HaWe
smart :)
didn't know that you can pass a variable type to a macro like a variable or a string and that the macro can create a new variable out of this passed-through type :))
but what is the
while(1)... break
for?
Re: [NXC] ArrayInit for 2D arrays
Posted: 04 Jun 2011, 21:43
by muntoo
doc-helmut wrote:but what is the
while(1)... break
for?
Just so that:
Code: Select all
int foo[][], bar[][];
ArrayInitD2(int, foo, 0, 8, 16)
ArrayInitD2(int, bar, 0, 8, 16)
doesn't redeclare
int arrtemp[];
over and over in the same "scope".
Without the
while(1) break;
, the expanded code would be:
Code: Select all
int arrtemp[]; ArrayInit(arrtemp, 0, 16); ArrayInit(foo, arrtemp, 8);
int arrtemp[]; ArrayInit(arrtemp, 0, 16); ArrayInit(bar, arrtemp, 8);
I'm not sure whether just putting
{}
around the whole macro will work in NXC, so I'm playing it safe with
while(1) break;
.
Re: [NXC] ArrayInit for 2D arrays
Posted: 05 Jun 2011, 08:16
by HaWe
muntoo, don't quite understand what you're trying to explain,
but your code gives a compile error using different array types (the same it's when I'm trying to pass the "type" to the macro in my own code):
Code: Select all
#define ArrayInitD2(type,arr,val,arrlen1,arrlen2) while(1) {type arrtemp[]; ArrayInit(arrtemp,val,arrlen2); ArrayInit(arr,arrtemp,arrlen1); break;}
task main(){
int myBar[][];
float myFoo[][];
ArrayInitD2(int, myBar, 123, 10, 20);
ArrayInitD2(float, myFoo, 12.34, 8, 16);
// some random array readings
NumOut(0,56, myBar[0][0]);
NumOut(0,48, myBar[5][5]);
NumOut(0,40, myBar[9][19]);
NumOut(0,32, myFoo[3][0]);
NumOut(0,24, myFoo[7][15]);
while (true) {
}
}
# Error: Duplicate variable declaration (__main_7qG2_arrtemp_7qG2_001)
File "c:\Temp\temp.nxc" ; line 16
# __main_7qG2_arrtemp_7qG2_001 float[]
#----------------------------------------------------------
1 errors during compilation
so it seems to be better - and more safe - to pass the temp[] var additionally instead of a variable type.
me wrote:according to the TO question a 2D size changing macro could be the following (works with all (either) different array types):
Code: Select all
#define ArrayInit2D(array, tmp, init_val, dimx, dimy) { \
ArrayInit(tmp, init_val, dimy); \
ArrayInit(array, tmp, dimx); \
}
use:
declare the 2D-array variable type (int/long/char/float/double),
declare a 1D-tmp array of same type
use ArrayInit2D with array, temp, init_value, and array (x,y) dimensions
This however works fine:
Code: Select all
#define ArrayInit2D(array, tmp, init_val, dimx, dimy) { \
ArrayInit(tmp, init_val, dimy); \
ArrayInit(array, tmp, dimx); \
}
task main(){
int myBar[][], iTemp[];
float myFoo[][], fTemp[];
ArrayInit2D(myBar, iTemp, 123, 10, 20);
ArrayInit2D(myFoo, fTemp, 12.34, 8, 16);
// some random array readings
NumOut(0,56, myBar[0][0]);
NumOut(0,48, myBar[5][5]);
NumOut(0,40, myBar[9][19]);
NumOut(0,32, myFoo[3][0]);
NumOut(0,24, myFoo[7][15]);
while (true) {
}
}