-6

Let us assume the following C (edit only C, not C++) function that performs a matrix-matrix multiplication from two matrices A,B and stores the result in new allocated memory (C):

double **MatrixMult(double **A, int rowA, int colA, double **B, int rowB, int colB)
{
    double **C = createEmptyMatrix(rowA, colB);
    int i; int j; int k;
    for (i=0;i<rowA;i++)
    {
        for (j=0;j<colB;j++)
        {
            C[i][j] = 0;
            for (k=0;k<rowB;k++)
                C[i][j] += (A[i][k]*B[k][j]);
        }
    }
    return C;
}

Matrices A and B are created as follows:

    double **A = createEmptyMatrix(10,10);
    double **B = createEmptyMatrix(10,10);

with the function

double **createEmptyMatrix(int rows,int cols)
{
    int i;
    double **L;
    L = (double **) malloc(rows*sizeof(double *));
    for (i = 0; i < rows; i++){
        L[i] = (double *) malloc(cols*sizeof(double));
    }
    return L;
}

Now, I try to use the SAME function to multiply a constant array (matrix) like

const double A_const[7][9] =  {
                                  {1.1,2.1,3.1,4.1,5.1,6.1,7.1,8.1,9.1},
                                  {1.2,2.2,3.2,4.2,5.2,6.2,7.2,8.2,9.2},
                                  {1.3,2.3,3.3,4.3,5.3,6.3,7.3,8.3,9.3},
                                  {1.4,2.4,3.4,4.4,5.4,6.4,7.4,8.4,9.4},
                                  {1.1,2.1,3.1,4.1,5.1,6.1,7.1,8.1,9.1},
                                  {1.2,2.2,3.2,4.2,5.2,6.2,7.2,8.2,9.2},
                                  {1.3,2.3,3.3,4.3,5.3,6.3,7.3,8.3,9.3}
                              };

with a non constant matrix B (dimension and content of A_const are chosen by random).

Basically, I try to pass a const array of doubles to a function that assumes double** as an argument.

I would like to avoid changing the definition of the function "MatrixMult". So, is it possible to define a ** (double pointer) to a constant array?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
boschika
  • 7
  • 2
  • 6
    There is no such thing as C/C++ - they are two separate languages. Pick one (this is most likely C) – UnholySheep May 01 '17 at 16:00
  • 1
    Can you explain what C/C++ is? – deW1 May 01 '17 at 16:01
  • 1
    Also since you aren't modifying the passed in parameters in the function they should be declared as `const` anyway (e.g.: `const double **A` and `const double **B`) which may fix your problem (not sure, since you haven't described it in enough detail) – UnholySheep May 01 '17 at 16:02
  • 4
    You absolutely cannot use the same function with an array. A double pointer is not the same thing as a 2-dimensional array. – Antti Haapala -- Слава Україні May 01 '17 at 16:04
  • 1
    Even though this code may compile in C and C++ the best answers differ. Choose 1 language as the dual language tags attracts down-votes. – chux - Reinstate Monica May 01 '17 at 16:13
  • 1
    `double **` is not an array or a matrix. It can also not point to a matrix (aka 2D array). Why not use a 2D array, but the more complicated and problematic `double **`? – too honest for this site May 01 '17 at 16:16
  • The C answer: Distinguish pointer and array. The C++ answer: We use classes. The "C/C++" answer: STOP pretending there is something called "C/C++"! –  May 01 '17 at 16:17
  • "I would like to avoid changing the definition of the function "MatrixMult"" - Your parameters demands a pointers to pointers to `double`. You currently have native arrays of arrays on the caller side, not pointers to pointers. We don't know what you're *trying* to pass because the *caller* side of the actual invoke was never provided in your posted code. – WhozCraig May 01 '17 at 16:40
  • Since the matrices (2D arrays) become very large i'd like to avoid doubling the memory requirements when calling the function – boschika May 01 '17 at 17:31
  • You should probably assert that `colA == rowB`, or otherwise detect shape mismatches. You might do better with a function signature `void MatrixMultiply(int rowA, int colArowB, int colB, double A[rowA][colArowB], double B[colArowB][colB], double C[rowA][colB])` where the calling code takes care of allocating the space. However, this is using true matrices, not the `double **` variant that you start with, so it requires major changes. Yes, this is using C99 and 'variable length array' (VLA) notation. Yes, you can dynamically allocate those arrays. – Jonathan Leffler May 01 '17 at 17:37
  • What about the memory footprint of your suggested change? Does the function create a copy of the matrices A and B when called? – boschika May 01 '17 at 17:44

1 Answers1

1

You can create an array of pointers to each row of your 2D array:

double *A_const_p[] = { A_const[0], A_const[1], 
                        A_const[2], A_const[3], 
                        A_const[4], A_const[5], A_const[6]};

Then you can pass this array to MatrixMult.

Note however that you'll need to remove the const qualifier from A_const if you don't want to change the function definition.

You also can't change the function to accept a const double ** because a double ** cannot be passed in for this parameter. See this question for details.

Community
  • 1
  • 1
dbush
  • 205,898
  • 23
  • 218
  • 273
  • I thought of this way before. But i assume that the memory requirements (for the pointer array) are added to those of the constant matrix?! – boschika May 01 '17 at 17:34
  • @boschika: yes, but that is unavoidable since your function requires an array of pointers, and that means you have to store the pointers somewhere in an array, separate from the array(s) of values. – Jonathan Leffler May 01 '17 at 23:47