[NXC] ArrayInit for 2D arrays

Discussion specific to NXT-G, NXC, NBC, RobotC, Lejos, and more.
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: [NXC] ArrayInit for 2D arrays

Post 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) {}

}
Last edited by HaWe on 04 Jun 2011, 09:55, edited 2 times in total.
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: [NXC] ArrayInit for 2D arrays

Post 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?
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: [NXC] ArrayInit for 2D arrays

Post 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
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: [NXC] ArrayInit for 2D arrays

Post 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) {}

}
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: [NXC] ArrayInit for 2D arrays

Post 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
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: [NXC] ArrayInit for 2D arrays

Post 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
muntoo
Posts: 834
Joined: 01 Oct 2010, 02:54
Location: Your Worst Nightmare
Contact:

Re: [NXC] ArrayInit for 2D arrays

Post 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.
Last edited by muntoo on 04 Jun 2011, 21:45, edited 2 times in total.
Image

Commit to LEGO Mindstorms Robotics Stack Exchange:
bit.ly/MindstormsSE


Commit to LEGO Stack Exchange: bit.ly/Area51LEGOcommit
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: [NXC] ArrayInit for 2D arrays

Post 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?
Last edited by HaWe on 05 Jun 2011, 08:18, edited 1 time in total.
muntoo
Posts: 834
Joined: 01 Oct 2010, 02:54
Location: Your Worst Nightmare
Contact:

Re: [NXC] ArrayInit for 2D arrays

Post 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;.
Image

Commit to LEGO Mindstorms Robotics Stack Exchange:
bit.ly/MindstormsSE


Commit to LEGO Stack Exchange: bit.ly/Area51LEGOcommit
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: [NXC] ArrayInit for 2D arrays

Post 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) {
  }
}
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest