Home AMX User Forum Duet/Cafe Duet

Wrap your head around this Array!

Spire_JeffSpire_Jeff Formerly Caffeinated ProgrammerPosts: 1,917
I was just doing a little more reading in my Java book and this was an interesting concept to me. In Java, because of the object oriented nature of it all, a multi-dimensional array does not require the same number of dimensions throughout the array. Take for example an array that describes the contents of 4 different CD Changers. The details of the 4 changers are as follows:

Changer 1 holds 400 CDs
Changer 2 holds 200 CDs
Changer 3 holds 200 CDs
Changer 4 holds 5 CDs.

In NetLinx, you would have to either declare a minimum of 3 different arrays to effectively use memory, or declare a single multidimensional array that wastes a bunch of memory as such:

Char sCdInfo[4][400][25]

This results in the following lengths:
sCdInfo[1] length is 400 - 400 slots are used
sCdInfo[2] length is 400 - 200 slots are used, 200 are wasted
sCdInfo[3] length is 400 - 200 slots are used, 200 are wasted
sCdInfo[4] length is 400 - 5 slots are used, 395 are wasted


In Java, you can declare the variable in a way that uses only the necessary length for each dimension.

First you would declare the pointer and start the array:

CdRecord[][] sCdInfo = new CdRecord[4][];

Then you would declare the length for each dimension:
sCdInfo[0] = new CdRecord[400];
sCdInfo[1] = new CdRecord[200];
sCdInfo[2] = new CdRecord[200];
sCdInfo[3] = new CdRecord[5];

And voila, you have everything contained in one multidimensional array without all the wasted space!

You could even take it further and say that there are 3 racks in the project, Rack 1 has (3) 400 disc changers, Rack 2 has (2) 5 disc changers and (4) 200 disc changers, and Rack 3 has a single 5 disc changer.

CdRecord[][][] sCdInfo = new CdRecord[3][][];

Now declare the number of changers per rack:

sCdInfo[0] = new CdRecord[3][];
sCdInfo[1] = new CdRecord[6][];
sCdInfo[2] = new CdRecord[1][];


Then you would declare the capacity for each changer:
sCdInfo[0][0] = new CdRecord[400];
sCdInfo[0][1] = new CdRecord[400];
sCdInfo[0][2] = new CdRecord[400];
sCdInfo[1][0] = new CdRecord[5];
sCdInfo[1][1] = new CdRecord[5];
sCdInfo[1][2] = new CdRecord[200];
sCdInfo[1][3] = new CdRecord[200];
sCdInfo[1][4] = new CdRecord[200];
sCdInfo[1][5] = new CdRecord[200];
sCdInfo[2][0] = new CdRecord[5];


Now, you can get the CD info for anything being played by plugging in the CurrentRack-1, CurrentChanger-1 and CurrentCD-1 (Remember that Java starts at 0 for indexes).


Can this be done effectively with switch cases and multiple variables in NetLinx, sure. I have just become so accustomed to the way NetLinx deals with arrays that it took me a second to accept what the Java book was saying. My first thoughts were (in no particular order): 1) That's stupid, why would you need that. 2) That makes no logical sense. 3) That is either a misprint, or I read it wrong! :)
That just proved to me how my instincts to resist change work. I had probably originally tried to use an array in just the way Java implements it, but over the years, I have conditioned myself to "KNOW" that it works the way NetLinx does it. (I actually learned it that way LONG before I started using NetLinx :) )

I was so impressed with this, I just had to share it with people that can at least understand what I'm talking about.... even if nobody else is amazed by this, at least you can understand what I am saying :) If I tried to tell this to the boss or the people that live with me, I would most likely just get a glazed over looked followed by an object flying in my general direction at a high rate of speed.

Jeff

Comments

  • a_riot42a_riot42 AMX Wizard Posts: 1,619
    It's called a ragged array and if Netlinx had pointers you could do this. You don't even need a multidimensional array at all as the same thing can be achieved with one array and offsets. That way you don't waste all the memory that a multidimensional Netlinx array does.
    Paul
  • jweatherjweather Junior Member Posts: 320
    The downside of being able to support jagged arrays (to use the technical term) is increased use of memory for pointers and increased processor time to dereference a specific element.

    Rectangular arrays (again, the technical term) have the nice property of being able to store an array of NxM bytes in NxM bytes in memory. Dereferencing element n,m is as simple as looking in memory at the address base + n*M + m (or base + m*N + n, depending on layout). The downside, of course, is that they are rectangular, and the full NxM is allocated in memory whether you need all of the elements or not.

    Jagged arrays, as you can guess from the way you initialize them, use an array of N pointers for the first dimension, each of which points to an array with a variable number of elements. Extra memory is required, and dereferencing a two-dimensional array is a two-step process (look up the pointer in the first array, add the offset and look up the element in a second array) Each dimension adds another step. The benefit, of course, is that you can save the memory for elements that you don't need.

    I don't remember offhand how Java arrays work, but C# allows you to declare them as rectangular [i,j] or jagged [j] depending on what you need.

    NetLinx seems to be based on a simplified version of C. Without pointers, it's not possible to create jagged arrays, but you also gain some "safety" by removing some of the ways for things to go wrong. Java and C# are much more mature languages, and do indeed have some very cool features. If you really want to blow your mind (and expand your programming abilities), try teaching yourself LISP or Scheme.
  • jazzwyldjazzwyld Registered User Posts: 199
    Spire_Jeff wrote: »

    I was so impressed with this, I just had to share it with people that can at least understand what I'm talking about.... even if nobody else is amazed by this, at least you can understand what I am saying :) If I tried to tell this to the boss or the people that live with me, I would most likely just get a glazed over looked followed by an object flying in my general direction at a high rate of speed.

    Jeff

    Oh I completely understand. I have thought things in the past were rather interesting...and my finacee continues to call me names =)
  • annuelloannuello Junior Member Posts: 294
    jweather wrote: »
    If you really want to blow your mind (and expand your programming abilities), try teaching yourself LISP or Scheme.

    Ah, Scheme... I haven't looked at it for years. I agree that it really is mind-blowing. When I looked at it, it seemed too elegant to be true. Now if only there were some good RAD/GUI tools for Scheme... (Maybe there are - I haven't had the need to look.)

    Roger McLean
    Swinburne University
  • a_riot42a_riot42 AMX Wizard Posts: 1,619
    annuello wrote: »
    Ah, Scheme... I haven't looked at it for years. I agree that it really is mind-blowing. When I looked at it, it seemed too elegant to be true. Now if only there were some good RAD/GUI tools for Scheme... (Maybe there are - I haven't had the need to look.)

    Roger McLean
    Swinburne University

    If you like Scheme try Prolog. Its been many years since I have written a Prolog program but its pretty cool because all you do is write rules, and the program comes up with the intelligent answer to your query. Once the rules are written, the program figures things out on its own based on those rules. It is similar to the way chess games are written since there is no way a program could be written that could know what to do in any chess situation. I have often thought that control systems are perfectly suited to being written in Prolog.

    http://en.wikipedia.org/wiki/Prolog

    Paul
  • jason_the_adamsjason_the_adams Junior Member Posts: 108
    Would I be wrong in thinking that Netlinx does technically have pointers? Doesn't it technically simply assume the relationship between the pointer and the pointee without any freedom?

    For example, in Netlinx you would use the following to declare a pointer:
    volatile integer x;
    

    Where in Java you would use the following:
    intObj x;
    x = new intOb()j;
    

    Now in Java, you declare that x is a pointer of some type (intObj in the example), then you have the freedom to either assign it a pointee (the new intObj) or else another pointer and therefore take on that pointer's pointee - for example, the following:
    intObj x;
    intObj y;
    x = new intObj();
    y = x;
    

    Netlinx, as far as I can tell, simply assumes this connection; a pointee is simply simultaneously generated with the introduction of the pointer, and the link between the two is implicitly made. I guess the alternative is that Netlinx simply has literally no concept of a pointer or pointee, but if its function were translated to, say Java, then it would operate as I'm describing... Does this make any sense? :P
  • Chip MoodyChip Moody Junior Member Posts: 727
    I'm sure this just exposes how much of the AMX cool-aid I've consumed over the years, but for the given example I'd just be inclined to declare an 805 element array for CD info and keep track of which "sections" of the array "belong" to which changer. :)

    Sorry - I'm into more flexible data structures and memory handling and all that - just don't feel the need to dive into them for control system programming. At least not yet...

    - Chip
  • a_riot42a_riot42 AMX Wizard Posts: 1,619
    Would I be wrong in thinking that Netlinx does technically have pointers? Doesn't it technically simply assume the relationship between the pointer and the pointee without any freedom?

    For example, in Netlinx you would use the following to declare a pointer:
    volatile integer x;
    

    Where in Java you would use the following:
    intObj x;
    x = new intOb()j;
    

    Now in Java, you declare that x is a pointer of some type (intObj in the example), then you have the freedom to either assign it a pointee (the new intObj) or else another pointer and therefore take on that pointer's pointee - for example, the following:
    intObj x;
    intObj y;
    x = new intObj();
    y = x;
    

    Netlinx, as far as I can tell, simply assumes this connection; a pointee is simply simultaneously generated with the introduction of the pointer, and the link between the two is implicitly made. I guess the alternative is that Netlinx simply has literally no concept of a pointer or pointee, but if its function were translated to, say Java, then it would operate as I'm describing... Does this make any sense? :P

    There are no pointers in Netlinx or Java, only references. In your Java example above, you are just changing the reference from x to y. A pointer is a variable that contains a memory address of another variable. Once you have the address of a variable you can do arithmetic on it, pass it to a function and do other useful things. In C, you can declare a variable x and then declare a pointer to x called y. These are two different things as one is a variable that contains a value the other is a variable that contains the memory address of that value. I guess you could call Netlinx variables constant pointers, but then its just a reference so why not just call it that?
    Paul
  • mpullinmpullin Obvious Troll Account, Marked for Deletion Posts: 949
    a_riot42 wrote: »
    There are no pointers in Netlinx or Java, only references. In your Java example above, you are just changing the reference from x to y. A pointer is a variable that contains a memory address of another variable. Once you have the address of a variable you can do arithmetic on it, pass it to a function and do other useful things. In C, you can declare a variable x and then declare a pointer to x called y. These are two different things as one is a variable that contains a value the other is a variable that contains the memory address of that value. I guess you could call Netlinx variables constant pointers, but then its just a reference so why not just call it that?
    Paul
    Why not call a shirt a pair of shirts? It has two sleeves.
  • jason_the_adamsjason_the_adams Junior Member Posts: 108
    Hmm, I looked into what you were describing, and apparently you're right. I guess the idea that Java contains pointers is a common misconception; it, as you said, uses references which "function the very similarly" but follows a simpler syntax.

    I suppose, therefore my question is still conceptually valid, but terminologically incorrect. I realize, as well, that my question is practically pointless, but honestly I'm just trying to wrap my mind around it all.

    Thanks Paul.
  • ericmedleyericmedley Senior Member - 4000+ posts Posts: 4,177
    jagged vs. rectangular arrays is simply a matter of choice for the compiler. Obviously, there would have to be quite a few more steps in managing the error handling for a jagged array. If you stick to the rectangular, the error checking is rather simple. an array cell notation is in or out of the array on all occasions of that cell.

    given: array[2][3][4]

    rectanglular array model: array[x][y][5] is never legal.


    given
    array[1][2][4]
    array[2][2][5]

    jagged array model array[x][y][5] might sometimes be legan and others not.

    In most compilers I've seen that allow jagged they do kind of a modification of both methods to increase procesing speed: they basically assign the smallest contiguous block of memory needed to get the array done(rectangular) and then use pointer(s) to work the jagged part in a reserved part of dyncamic memory set asside for such silliness.

    so, when you're working in the main rectangle things move quite fast. Once you're accesing data outside the box, then the indexing/pointer(s) kick in.

    creepy...
Sign In or Register to comment.