0

I have been looking for code on how to create a matrix determinant calculator, and I found code from ( Matrix determinant algorithm C++ ).

I adopted the code to try it, but i realized that i did not know how to pass in a multidimensional array into the function, without defining its dimensions first (i got errors).

So, can you please show me how to pass a multidimensional array into a function without defining its dimensions first (i.e how int a[MAX][MAX] is an argument, what is 'MAX').

I hope my question is clear, thank you for your help.

This is the (edited) code: -sample input would be a square matrix and its size.

int determinant(int oMat[][], int n){

    int sMat[n][n]; //Temporary matrix
    int det = 0; //Initializing 'det'.

    if(n==1){
        det = oMat[0][0]; //Calculating.
        return det;
    }else if(n==2){
        det = oMat[0][0]*oMat[1][1] - oMat[1][0]*oMat[0][1]; //Formula for 2x2.
        return det;
    }else{

        for(int p=0; p<n; p++){ //Selecting 'oMat' row one.
            int k=0; //'sMat' rows.
            int m=0; //'sMat' columns.

            //Creating the temporary matrix 'sMat'.
            for(int i=1; i<n; i++){ //for 'oMat' rows.
                for(int j=0; j<n; j++){

                    if(j==p){
                        continue;
                    }

                    sMat[k][m] = oMat[i][j]; m++;


                    if(m==n-1){
                        k++; //Go to the next row.
                        m = 0; //Start at column one (index 0).
                    }
                }
            }

            det = det + oMat[0][p] * pow(-1,p) * determinant(sMat, n-1);

        }
        return det;
    }
}
Community
  • 1
  • 1
ATM
  • 3
  • 2

4 Answers4

2

You can pass an array by reference and have the function figure out the size of the matrix. To do this use a template as follows

template <int R>
int determ(int (&a)[R][R]) {
//now R is the number of rows
std::cout << R << std::endl;
// rest of code here
}
linuxfever
  • 3,763
  • 2
  • 19
  • 43
1

If you're passing a 2-D array to function determ() as

int a[MAX][MAX];
determ(a, int n);

the function declaration should be:

determ(int a[][MAX], int n) { .. }

In the above declaration number of rows need not be specified as we are not allocating the memory for the array hence can be ignored. Number of columns is required for the dimension of the array.

Sunil Bojanapally
  • 12,528
  • 4
  • 33
  • 46
0

There is two ways:

1) Declare your function as is:

int determ(int** a, int size, int n) {...} // 'size' aka 'MAX'

2) Use dynamic container such as std::vector:

int determ(const vector<vector<int>>& a, int n) {...}
Alexey Andronov
  • 582
  • 6
  • 28
  • Note that a vector of vectors is quite different to 2D array. It is more like an array of pointers to arrays. – juanchopanza Jan 31 '15 at 09:12
  • @Alexey: I will try that, but if I may ask, what does int** a mean. – ATM Jan 31 '15 at 09:15
  • @ATM, it called "pointer to pointer" and essentially is a hint to compiler. The thing is, that with pointer 'int* a' you can write 'a[2] = 2' and similarly, with "int **a" - 'a[2][2] = 2' – Alexey Andronov Jan 31 '15 at 09:30
  • What I did: `int determinant(int** oMat, int n)` But then I got an error at this line `det = det + oMat[0][p] * pow(-1,p) * determinant(sMat, n-1)` – ATM Jan 31 '15 at 09:32
  • @juanchopanza, yep, I was suggesting a better design solution, but you absolutely right: on the low-level they are quite different – Alexey Andronov Jan 31 '15 at 09:32
  • @ATM, have a look here on your error: [http://stackoverflow.com/questions/1584100/converting-multidimensional-arrays-to-pointers-in-c](http://stackoverflow.com/questions/1584100/converting-multidimensional-arrays-to-pointers-in-c) – Alexey Andronov Jan 31 '15 at 09:46
0

You have a number of options:

  1. Use a compile time size like MAX, and declare your array parameter in terms of that:

    int determinant(int (*oMat)[MAX], int n) {
    

    With that you are passing a pointer to the first element (= row) of your 2D array. The same can be done with the std::array<> template:

    int determinant(array<array<int, MAX>, MAX> *oMat, int n) {
    

    However, in both cases MAX must be a compile time constant. You may pass MAX in as a template parameter, allowing different code to work on matrices of different size, but the problem remains that MAX needs to be a compile time constant.

  2. If you want to work with a dynamic size in C++, you have two choices: First you can use a vector of vector

    int determinant(vector<vector<int> > *oMat, int n) {
    

    This allows maximum flexibility, however, it does not enforce that the lines have the same size. oMat could be a ragged 2D array. The other way is to use a 1D array and calculate the indexes yourself:

    int determinant(int size, int *oMat, int n) {
        for(int i = 0; i < size; i++)
            for(int j = 0; j < size; j++)
                //Access the individual elements with
                oMat[size*i + j];
    
  3. The third approach is to drop back to C, because in contrast to C++, C allows for true dynamic 2D arrays:

    int determinant(int size, int (*oMat)[size], int n) {
        for(int i = 0; i < size; i++)
            for(int j = 0; j < size; j++)
                //Access the individual elements with
                oMat[i][j];
    

    You would create the array and call the function like this:

    int n = /*whatever*/;
    int (*matrix)[n] = malloc(n*sizeof(*matrix));
    fillMatrix(n, matrix);
    determinant(n, matrix, n);
    free(matrix);    //Don't forget the cleanup.
    
cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106
  • I would like to try option one, BUT what is a compile time size? How do use it... do I define `MAX`...? – ATM Jan 31 '15 at 10:20
  • Compile time constants mean that the value must be known by the compiler when it compiles the program, it cannot depend on anything that is only known when the program is run. Usually, these compile time constants are either `const` variables with global, namespace, or static class scope, plain literals like `7`, or passed to a template as a template argument. `array<7>` passes `7` as such a template argument to the `array<>` template. However, the value that's passed to a template argument must be a compile time constant itself, ie. `array` won't do. – cmaster - reinstate monica Jan 31 '15 at 11:58