Set Function Parameters for a Variable, row/col, Matrix - c++

So, what isn't the problem? Anyway, in attempts to solve the N Queens problem using stacks library, we were met with issues trying to set function parameters to take our matrix and manipulate it.
int main(){
const int n = 8;
bool board[n][n];
Here we're trying to take in the board.
bool isValid(int n, bool board[][], int row, int col)
How else could we input our matrix?
We tried using Vectors and it screwed with our calculations, ruining our progress.
We are currently trying to use dynamic arrays and pointers, but we don't understand the concept to be implemented in our scope.

One problem is the argument declaration bool board[][], which is equal to bool (*board)[]. And C++ doesn't allow arrays without a size, the size needs to be specified by a compile-time constant.
It might be possible to use std::array and templates, perhaps as
template<std::size_t M, std::size_t N>
bool isValid(std::array<std::array<bool, N>, M> board, int row, int col);
where std::array<std::array<bool, N>, M> board corresponds to bool board[M][N].
Note that n is no longer needed as the size is built into the arrays themselves.
Or use a global constexpr variable initialized to the actual size, and use that for the array sizes instead of template values.

Related

Error initializing matrix with nembers of the same struct

I'm learning C++.
I only need a matrix and SPECIALLY how many rows and columns are in the matrix. I've though that I can use the following structure:
struct map {
int rows;
int columns;
int matrix[rows][columns];
}
But, it doesn't compile. There is an error on line: int matrix[rows][columns];
I have also tried:
struct map {
int rows;
int columns;
int matrix[map.rows][this.columns];
}
But, it doesn't compile.
The map.matrix will have map.rows and map.columns. I have declared this way because I don't know if I can declared without specifying its dimensions.
If it is correct to do: int matrix[][];.
What do I have to do to make the map.matrix have map.rows rows and map.columns columns?
In order to create an array on the stack (i.e. not allocating it on the heap with new), the size of the arrays need to be known at compile time (your rows and columns are not known at compiletime).
Alternative 1: allocate on the heap (for big arrays which don't fit on the stack) or simply use vectors (vectors use heap memory).
Alternative 2: if you really need it to be on the stack, you could use a template class:
template <size_t ROWS, size_t COLUMNS>
class MyMatrix
{
int _matrix[ROWS][COLUMNS];
};

How to generalize plain 2D arrays?

For C++, I have seen several recommendations to use a 2D arrays as follows:
int* theArray = new int[d1 * d2];
An element (i, j) can then be accessed as follows:
int myInt = theArray[i + d2 * j];
I have two questions: First, how to access a 3D array? Is there a general formula? Second and more important, will there be a performance penalty if I use functions
int getNumber(int i, int j, int k)
void setNumber(int i, int j, int k, int theValue)
to retrieve and set number? I don't want to screw it up somewhere in the code and then spend forever finding where that screw up is.
Generalization to three dimension is not difficult:
int* theArray = new int[d1*d2*d3];
and accessing it using
int myInt = theArray[i+d1*(j+d2*k)];
Just like decimal system for example. When you write 123 as 3+10*2+100*3 = 3 + 10*(2+10*3). Where 10 is the size of each dimension. Note that I have changed your d2 to d1, as what is indented is the size of the dimension associated to the index i.
Regarding your second question, the function called can reduce the performances. But you can avoid this issue by inlining the function, or defining a macro, which is then equivalent to no function call at all, regarding performance.
I'd say for 2D array, assuming i is the first index and j is the second, it's better to do indexing like
int myInt = theArray[i*d2 + j];
so changing the last index gives you contiguous range. This is how C and C++ multi-dimensional arrays are implemented.
So if your 3D array is
int* theArray = new int[d1*d2*d3];
Then you access it this way:
int myInt = theArray[(i*d2 + j)*d3 + k];
Regarding accessor functions - if they are inline, the overhead will be zero. You may want also to wrap this all into your custom array class (but that's probably what you are already intending to do)
To see how this is solved in a more general way, you can have a look at boost multi_array.
I would go with std::array instead and not do any manual index calculations. Just make sure that the last index is the one you will most likely loop over. std::array is as fast as [].
#include <iostream>
#include <array>
int main() {
constexpr size_t a=5;
constexpr size_t b=4;
constexpr size_t c=3;
std::array<std::array<std::array<float,a>, b>, c> arr3d;
for(auto& outer : arr3d){
for(auto& row : outer){
for(auto& place : row){
place=3.5;
}
}
}
for(size_t i=0;i<a; ++i){
for(size_t j=0;j<b; ++j){
for(size_t k=0;k<c; ++k){
arr3d[i][j][k]=k; // or whatever
}
}
}
std::cout << arr3d[0][1][2] << std::endl;
}
If you need run-time flexibility for the sizes, use std::vector.
template<typename T> using Vec = std::vector<T>;
Vec<Vec<Vec<float>>> arr3d(a,Vec<Vec<float>>(b,Vec<float>(c,0)));
but it is going to be significantly slower to initialize and depending on how you use it (and the values of a,b,c) access will be slower also. (note comments).
For other ways to initialize the array: Other ways to initialize the array

What is better practise in high-performance computing: passing a struct of data into a function or a set of variables?

Imagine that I have a struct that contains a set of variables that describe an object, which is a grid in my case. I was wondering, if I have a function that only uses a subset of the grid, whether there are any performance differences in the two variants of the computational_kernel functions below. The kernels are the same, except that the one in which the struct is passed has to extract the itot, jtot and ktot from the struct before heavy computations are done.
struct Grid
{
int itot;
int jtot;
int ktot;
int not_used_in_kernel1;
int not_used_in_kernel2;
int not_used_in_kernel3;
int not_used_in_kernel4;
}
Grid grid;
// Code that initializes the grid values...
// Variant 1
computational_kernel(double* array1, double* array2,
const int itot, const int jtot, const int ktot);
// Variant 2
computational_kernel(double* array1, double* array2,
const Grid& grid);
I think passing a struct is better for the code maintenence. if you add new fields to your grid, you will only have to change the function. But passing a set of variables you will have to change the function and every call to the function.
If computational_kernel is a function that does a lot of work internally and is invoked few times the difference between the two versions is infinitesimal. The second version has just the extra cost of dereferencing 3 values, than the rest is identical, and you presumably have to do such dereferencing anyway before invoking the first version.
I would definitely use the second form for compactness reasons: if you are defining object-oriented data structures then use them in such a fashion (better encapsulation).
I would say that passing a reference to a struct as in the 2nd variant would probably be more efficient performance-wise. On the 1st variant the caller will need to push the 3 int variables on the stack while on the 2nd variant all it has to push is a reference (a pointer) to the struct and do the stuff there. The performance impact is of course bigger if you had more than 3 variables to pass.

const array of fixed size const array as argument of a method in C++

Following my question about passing array as const argument, I am trying to figure out how to write a method where the argument is a const array of fixed size const array. The only writable thing would be the content of these arrays.
I am thinking about something like this:
template <size_t N>
void myMethod(int* const (&inTab)[N])
{
inTab = 0; // this won't compile
inTab[0] = 0; // this won't compile
inTab[0][0] = 0; // this will compile
}
The only problem in this solution is that we don't know the first dimension.
Does anyone have a solution for this?
Thanks in advance,
Kevin
[Edit]
I don't want to use std::vector or such dynamically allocated arrays.
If both dimensions are known at compile time, then you could use a 2-dimensional array (in other words, an array of arrays) rather than an array of pointers to arrays:
template <size_t N, size_t M>
void myMethod(int (&inTab)[N][M])
{
inTab = 0; // this won't compile
inTab[0] = 0; // this won't compile
inTab[0][0] = 0; // this will compile
}
int stuff[3][42];
myMethod(stuff); // infers N=3, M=42
If either dimension is not known at runtime, then the arrays presumably need to be dynamically allocated. In that case, consider using std::vector both to manage the allocated memory and to keep track of the size.
The reference prevents line 4 (inTab = 0;), because you've made inTab a reference. The const prevents line 5 (inTab[0] = 0;) because an inTab pointer is const.

How can I pass a dynamic multidimensional array to a function?

How can I pass a multidimensional array to a function in C/C++ ?
The dimensions of array are not known at compile time
A pointer to the start of the array along with the dimensions - then do the array arithmetic in the function is the most common solution.
Or use boost
Passing the array is easy, the hard part is accessing the array inside your function. As noted by some of the other answers, you can declare the parameter to the function as a pointer and also pass the number of elements for each dim of the array.
#define xsize 20
#define ysize 30
int array[xsize][ysize];
void fun(int* arr, int x, int y)
{
// to access element 5,20
int x = arr[y*5+20];
}
fun(array, xsize, ysize);
Of course, I've left out the whole business of allocating the array (since it isn't known what its size will be, you can't really use #defines (and some say they're bad anyhow)
Use a vector of vectors, you can pass a vector.
You could pass a pointer and sizes, or use a std::vector. But the "real" solution is with a template:
template <size_t N, size_t M>
void foo(int (&pArray)[N][M]);
This function template accepts a N by M array of ints, by reference. Note this is a function template, not a function, so you do get a different instantiated function per array type.
I think this is a GCC extension (or a quite modern C feature), but it can be quite convenient:
void foo(int bar[n][m], int n, int m) {...}
You can pass the pointer to initial memory location of your multi dimension array. you should also pass the size of array i.e. limit of each dimension.
i.e
int var [x][y][z];
func (var, x, y, z);
function definintion:
void func (int*, int, int, int);
I'm just summarizing the options from other posts.
If the number of dimensions (the N as in N-dimensional array) is unknown, the only way is to use a C++ multidimensional array class. There are several publicly available implementations, from Boost or other libraries. See Martin Beckett's post.
If the number of dimensions is known but the array size is dynamic, see Tom's answer for accessing an array element (converting multi index into element pointer). The array itself will have to be allocated with malloc or new.
If you are writing the multidimensional array class yourself, you'll need to know about Row-major-order, Column-major-order, etc.
Namely, if the array dimensios is (Size1, Size2, Size3, ..., SizeN), then:
The number of elements in the array is (Size1 * Size2 * Size3 * ... * SizeN)
The memory needed is sizeof(value_type) * numOfElements
To access the element (index1, index2, index3, ..., indexN), use
ptr[ index1 + (Size1 * index2) + (Size1 * Size2 * index3) + ... ] assuming the first array index is the fastest-moving dimension
Section 3.4 on this page addresses your question:
http://www.programmersheaven.com/2/Pointers-and-Arrays-page-2
Of course variable-length arrays were not present in C until C99 and as far as I know they are not present in C++. Also, MSVC does not implement/support C99.
A simple method is to flatten the array and iterate using dimensions.
#include <stdio.h>
void print_array(int *arr,int row,int col)
{
int i,j;
for(i=0;i<row;i++){
for(j=0;j<col;j++){
printf("%d ",*(arr+i*col+j));
}
printf("\n");
}
}
int main()
{
int a[2][3] = {{1,0,2},{-1,3,1}};
int b[4] = {1,2,3,34};
print_array(a,2,3);
return 0;
}
This technique works but flattening array might prevent compiler optimizations which in turn might result in slow execution.