How to map the indexes of a matrix to a 1-dimensional array (C++)?
The way most languages store multi-dimensional arrays is by doing a conversion like the following:
If matrix
has size, n (rows) by m (columns), and we're using "row-major ordering" (where we count along the rows first) then:
matrix[ i ][ j ] = array[ i*m + j ]
.
Here i goes from 0 to (n-1) and j from 0 to (m-1).
So it's just like a number system of base 'm'. Note that the size of the last dimension (here the number of rows) doesn't matter.
For a conceptual understanding, think of a (3x5) matrix with 'i' as the row number, and 'j' as the column number. If you start numbering from i,j = (0,0) --> 0
. For 'row-major' ordering (like this), the layout looks like:
|-------- 5 ---------|
Row ______________________ _ _
0 |0 1 2 3 4 | |
1 |5 6 7 8 9 | 3
2 |10 11 12 13 14| _|_
|______________________|
Column 0 1 2 3 4
As you move along the row (i.e. increase the column number), you just start counting up, so the Array indices are 0,1,2...
. When you get to the second row, you already have 5
entries, so you start with indices 1*5 + 0,1,2...
. On the third row, you have 2*5
entries already, thus the indices are 2*5 + 0,1,2...
.
For higher dimension, this idea generalizes, i.e. for a 3D matrix
L by N by M:
matrix[ i ][ j ][ k ] = array[ i*(N*M) + j*M + k ]
and so on.
For a really good explanation, see: http://www.cplusplus.com/doc/tutorial/arrays/; or for some more technical aspects: http://en.wikipedia.org/wiki/Row-major_order
Map a 2D array onto a 1D array
You need to decide whether the array elements will be stored in row order or column order and then be consistent about it. http://en.wikipedia.org/wiki/Row-major_order
The C language uses row order for Multidimensional arrays
To simulate this with a single dimensional array, you multiply the row index by the width, and add the column index thus:
int array[width * height];
int SetElement(int row, int col, int value)
{
array[width * row + col] = value;
}
Map array index to matrix
If index
is an index into a single-dimensional array of 9 elements, the array can be viewed as a two-dimensional 3x3 array with this:
int row = index / 3;
int column = index % 3;
int foo = array[row][column];
How to map a 2D array in a 1D array in C++?
Let W be the width of the 2D array, and H its height. Then assuming row-major layout, the 1D index 'ix' relates to the 2D-index [x,y] as such:
ix = y*w + x;
y = ix / w; // implicit floor
x = ix % w;
e.g.:
const int W = 3, H=2;
int m[H][W] = {{1,2,3}, {4,5,6}};
int* oneD = &m[0][0];
assert(oneD[1*W + 2] == m[1][2]); // element 6, y=1, x=2
How do I map a position in a n dimensional matrix to 1D, in C++ at compile time?
If I understand correctly... your looking something as follows
template <auto ... as>
auto constexpr pos_nd_to_1d ()
{
std::size_t i { 0u };
((i *= DIM, i += as - 1u), ...);
return i;
}
Or maybe you can use std::common_type
, for i
,
std::common_type_t<decltype(as)...> i {};
but for indices I suggest the use of std::size_t
(also std::size_t ... as
).
The following is a full compiling example
#include <iostream>
constexpr auto DIM = 3u;
template <auto ... as>
auto constexpr pos_nd_to_1d ()
{
std::size_t i { 0u };
((i *= DIM, i += as - 1u), ...);
return i;
}
int main ()
{
std::cout << pos_nd_to_1d<1u, 1u, 1u>() << std::endl;
std::cout << pos_nd_to_1d<1u, 2u, 1u>() << std::endl;
std::cout << pos_nd_to_1d<1u, 3u, 1u>() << std::endl;
}
-- EDIT --
The OP ask
could you explain how this code works?I am a bit new to c++.
I'm better at coding that at explaining, anyway...
What I've used here
((i *= DIM, i += as - 1u), ...);
//...^^^^^^^^^^^^^^^^^^^^^^ repeated part
is called "fold expression" (or also "folding" or "template folding"), and is a new C++17 feature (you can obtain the same result also in C++14 (also C++11 but not constexpr
) but in a less simple and elegant way) that consist in expanding a variadic template pack with an operator.
By example, if you want to sum the indexes, you can simply write
(as + ...);
and the expression become
(a0 + (a1 + (a2 + (/* etc */))));
In this case I've used the fact that the comma is an operator, so the expression
((i *= DIM, i += as - 1u), ...);
become
((i *= DIM, i += a0 - 1u),
((i *= DIM, i += a1 - 1u),
((i *= DIM, i += a2 - 1u),
/* etc. */ )))))
Observe that, this way, the first i *= DIM
is unuseful (because i
is initialized with zero) but the following i *= DIM
multiply as - 1u
the right number of times
So, when as...
is 1, 2, 1
, by example, you get
(1 - 1)*DIM*DIM + (2 - 1)*DIM + (1 - 1)
Representing a 2D array as a 1D array
Take a look at Performance of 2-dimensional array vs 1-dimensional array
3D to 1D mapping function confusion
You computed the mapped index for out-of-bounds values of y
.
You said height * width * depth= 12
, and:
index = y * width * depth + x * depth + z
And we see in your table:
#.| Y | X | Z | index
--+---+---+---+------
1 | 0 | 1 | 0 | 2
2 | 1 | 0 | 0 | 6
This implies:
0 * width * depth + 1 * depth + 0 = 2
=>depth = 2
1 * width * depth + 0 * depth + 0 = 6
=>width * depth + 6
=>width = 3
height * width * depth= 12
=>height = 2
Thus:
- y is in [0, 1]
- x is in [0, 2]
- z is in [0, 1]
The maximum index is at {x, y, z} = {2, 1, 1}
and its value is 1 * 2 * 3 + 2 * 2 + 1 = 11
.
How to flatten or index 3D-array in 1D array?
The algorithm is mostly the same. If you have a 3D array Original[HEIGHT, WIDTH, DEPTH]
then you could turn it into Flat[HEIGHT * WIDTH * DEPTH]
by
Flat[x + WIDTH * (y + DEPTH * z)] = Original[x, y, z]
As an aside, you should prefer arrays of arrays over multi-dimensional arrays in .NET. The performance differences are significant
Navigating multidimensional array using one variable
I need to be able to navigate the array using a single int like:
int i = 4;
cout << arrayOne[4];
It it possible to do it like this
Yes, it is:
int arrayOne[3][3] {
{1,2,3},
{4,5,6},
{7,8,9},
};
int* array = arrayOne[0];
std::cout << array[4];
Map 2D matrix to 1D array
If you have a 2d
array and a 1d
array having same elements,then the following will be true
2d[i][j]=1d[i*number_of_columns+j]
I am assuming from your post that you already have created a 1d array out of a 2d one.
Note i
and j
are indices and rememeber indices begin from 0
EDIT:If you are accessing an element at [5][5]
(as last element)it means your array is of order 6 by 6
and not 5 by 5
.So your 1d array will have 6*6=36
elements and not 25
.
Related Topics
Why Is My Helloworld Function Not Declared in This Scope
Convert a String to a Date in C++
When and How to Use Gcc's Stack Protection Feature
How to Initialize C++ Object Member Variables in the Constructor
Behaviour of Malloc with Delete in C++
Winapi Sleep() Function Call Sleeps for Longer Than Expected
Is There a Formula to Determine Overall Color Given Bgr Values? (Opencv and C++)
This Regex Doesn't Work in C++
C/C++: Optimization of Pointers to String Constants
Isdigit(C) - a Char or Int Type
Receiving Chunked Http Data with Winsock
Boost C++ Serialization Overhead
How to Use Standard Library (Stl) Classes in My Dll Interface or Abi
How Can a C++ Header File Include Implementation
How to Handle Failure in Constructor in C++
Static and Extern Global Variables in C and C++