[RESOLVED] 2D Array

Hi,
I am experimenting with compressing a Boolean array into a byte array so it uses all the bits (so each byte holds 8 Boolean values).
So a 128128 matrix would become 16128, yes? And the second index can stay the same for accessing the values, correct? So 64,18 would be the same as ?,18 on a compressed array.
There's my problem, I need to find the ?. And if I'm correct, to find ? one would need to find the byte that contains the ? bit. Because then to access ?,18 one could use:
myArray[which_byte][18] << ?
So how can I find which byte refers to any specific index?
Thanks

The modulo operator ('%') is useful here.

Yes I was thinking it'll probably have a modulo in it, just not sure how to implement it in this case. Maybe to simplify it:
I have a "line" of bytes each containing 8 bits:
00000000 00000000
Each byte can only be accessed individually, and I need to find the nth bit (from the right). But I'm not sure how I can do it, especially since each byte can only be accessed by itself, otherwise just a bitshift would do the trick...

From a mathamatical point of view you have a function that maps from a boolean array to a byte array. Let's assume that the second dimension is one (that makes it easier for the moment).

The first eight entries (0..7) in the boolean array map to the first byte in the byte array.
The second eight entries (8..15) in the boolean array map to the second byte in the byte array.

See something?
Let's display it in a table:
Boolean Array (b) | Byte Array (x) / position in byte (y)
0 | 0 / 0
1 | 0 / 1
...
7 | 0 / 7
8 | 1 / 0
9 | 1 / 1
...
15 | 1 / 7
... and so on.

So the question is how to get to values with drawing such a table for every possible value?
You can compute x simply as

x = (int) (b / 8);

Example: 15 / 8 = 1.875, which will be cut off to 1 because of the integer cast.
OK, let's go to the position (y). As you can see the positions always counts up to seven and starts than from zero again. This looks very much like the result from a modolo operation:

y = b % 8

Example: 15 % 8 = 7.

With this in mind you can get your values out of the byte array. But keep in mind that you might need a bit mask together with the >>-operator.

Example: 0b11001100 is stored in myByteArray[1][1]. To retrieve position no. 3 you need a bitmask like 0b00000100.
(myByteArray[1][1] & 0b00000100) >> 3; => returns 1; Can you see why? You have to fileter the other values out before left shifting, or do it after, but if xou don't do it the result would be 0b00011001, which is not the flag that you want.

A useful set of Arduino-provided functions are bitRead, bitWrite etc.

So to find ?,18 should I use
(myArray[? % 8][18] & (1 << ?)) >> ?
?
Or have I not understood what you were saying?

I think you have not understood when to use '/' and when to use '%'.
Think about it - '/' gives you the byte and '%' gives you the bit.

Well I have implemented this in my code:

byte arrayRead(byte array, byte first, byte second) {
  if(array == 1) {
    return (values[(int)first / 8][second] & (1 << (first % 8))) >> first;
  }
  else if(array == 2) {
    return (nextValues[(int)first / 8][second] & (1 << (first % 8))) >> first;
  }
}

void arrayWrite(byte array, byte first, byte second, byte data) {
  if(array == 1) {
    values[(int)first / 8][second] |= (data << (first % 8));
  }
  else if(array == 2) {
    nextValues[(int)first / 8][second] |= (data << (first % 8));
  }
}

And is that what I should be doing? Because it is not working...

I can't see what the parameters mean. Can you explain it?
array is the array where you want to store/read data from, right? But what is first and second?

Sorry, I just copied that straight from my code and I should have explained it.
There are two arrays I will be writing and reading from, hence the array variable and the if statements. First is the "width" coordinate of the array and second is the "height" coordinate. So in C when you would usually do myArray{first}{second} (I can't use square brackets because this forum will think its a tag).
So basically all that's important is:
I want to write and read data to the array with the two indexes "first" and "second". "data" is the data I want to write to the array at the point {first}{second}.
Hope that cleared it up

values[(int)first / 8][second] |= (data << (first % 8));

What if "data" is zero, and the bit already there is one?

If you're not comfortable with bit operations, use bitRead and bitWrite, or look at their source to see how to do it properly.

If it makes it clearer, you can do it step by step (I'm usually a friend of this. Once you understood you can wrap it up to more compact code):

byte arrayRead(byte array, byte first, byte second) {
  if(array == 1) {
    int x = first / 8; // the position of the byte
    int y = first % 8; // the position within the byte

    byte flags = values[x][second]; // get the byte you want
    byte flag = flags >> y; // move the flag you want to position 1
    flag = flag & 1; // use a bit mask to hide other bits

    return flag;
  }
 ...
}

Thanks Kai, that should work.
AWOL should I use &= then? Or would neither of the compound bitwise operators do it?

indeed:
AWOL should I use &= then? Or would neither of the compound bitwise operators do it?

AWOL's answer is for storing. There you need the bitwise-OR. Otherwise you would delete the other bits in the array.

But isn't AWOL saying it wouldn't work, because if data is 0 then it won't override it?

The code is working now sort of, if I use |= it works but can't overwrite data with a zero, but if I use &= nothing happens at all...
So what should I do?

Does this help you? c++ - How to set, clear, and toggle a single bit? - Stack Overflow

Otherwise try to do it step by step. I'm sure this can be done. Just keep on trying :wink:

Thank you! :slight_smile:
Finally it's working! Thanks to the both of you for the help!