0

I know using vectors is much easier but it just crossed my mind if i wanted to use C-style arrays to do generic matrix multiplication, how would that work. I searched online and got some help by using templates but the array won't return from the function.

// Example program
#include <iostream>
#include <string>

using namespace std;

template <typename T, size_t row1, size_t col1, size_t row2, size_t col2>
typename multiply(T(&a)[row1][col1], T(&b)[row2][col2]) {
  if (row1 != col2) {
    cout << "Error! Rows of first matrix is not the same as Columns of second "
            "matrix, therefore Multiplication is NOT POSSIBLE!";
    return 0;
  } else {
    T c[row1][col2];
    for (size_t i = 0; i < row1; ++i) {
      for (size_t j = 0; j < col2; ++j) {
        c[i][j] = 0;
        for (size_t k = 0; k < col1; ++k) {
          c[i][j] += a[i][k] * b[k][j];
        }
      }
    }
    return c;
  }
}

int main() {
  // C-style array
  int my_array[2][5] = {{1, 2, 3, 4, 5}, {1, 2, 3, 4, 5}};
  int my_array2[5][2] = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
  int my_array3[2][2];

  int c[2][2] = multiply(my_array, my_array2);
  for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 2; ++j) {
      cout << c[i][j] << " ";
    }
    cout << endl;
  }
  return 0;
}

So any idea how I can make this code work?

Asad Nawaz
  • 355
  • 1
  • 3
  • 14
  • 5
    [`std::array`](http://en.cppreference.com/w/cpp/container/array) does that well already. –  Feb 10 '18 at 15:08
  • 2
    Possible duplicate of [How do I use arrays in C++?](https://stackoverflow.com/questions/4810664/how-do-i-use-arrays-in-c) – phuclv Feb 10 '18 at 15:15
  • 2
    You cannot return a C-style array from a function. – n. m. could be an AI Feb 10 '18 at 15:18
  • You should make incompatible matrix multiplication fail at compile time. – juanchopanza Feb 10 '18 at 15:21
  • Isn't the function declaration of `multiply` syntactically wrong because the return type is missing? (`multiply` is not a type name as your declaration suggests.) And if you declare it returning an array you'll find out that the compiler doesn't let you, as @n.m. correctly remarked already. Remedy: Define a struct holding nothing but an array (the old C method of effectively passing arrays by value). But that's kind of silly in C++. – Peter - Reinstate Monica Feb 10 '18 at 16:13

2 Answers2

1

You can't either return 0 either return c in your function as you do.

Instead, pass the output as a parameter c and put a and b as const.

The return of the function is the error code (0 for OK, -1 for KO)

Btw, your check condition is wrong, I corrected it also

// Example program
#include <iostream>
#include <string>

using namespace std;

template <typename T, size_t row1, size_t col1, size_t row2, size_t col2>
int multiply(const T(&a)[row1][col1], const T(&b)[row2][col2], T(&c)[row1][col2]  ) {
  if (col1 != row2) {
    cout << "Error! Columns of first matrix is not the same as Rows of second "
            "matrix, therefore Multiplication is NOT POSSIBLE!";
    return -1;
  } else {
    //T c[row1][col2];
    for (size_t i = 0; i < row1; ++i) {
      for (size_t j = 0; j < col2; ++j) {
        c[i][j] = 0;
        for (size_t k = 0; k < col1; ++k) {
          c[i][j] += a[i][k] * b[k][j];
        }
      }
    }
    return 0;
  }
}

int main() {
  // C-style array
  int my_array[2][5] = {{1, 2, 3, 4, 5}, {1, 2, 3, 4, 5}};
  int my_array2[5][2] = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
  int my_array3[2][2];

  int a = multiply(my_array, my_array2,my_array3);
  for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 2; ++j) {
      cout << my_array3[i][j] << " ";
    }
    cout << endl;
  }
  return 0;
}
Gabriel
  • 3,564
  • 1
  • 27
  • 49
  • So this works, but i don't understand how my_array3 is now changed when a is what holds the return value of the function. Can you explain? – Asad Nawaz Feb 10 '18 at 19:01
  • the return of the function is here to check if the function performed correctly. Don't use it to see the result; it is inside my_array3. my_array3 is being MODIFIED by the function. So this is what you need to look – Gabriel Feb 10 '18 at 23:31
0

You can pass the result as a parameter:

template<class T,int NLine1,int NC1L2,int NCol2>
void multiply(T (left&)[NLine1][NC1L2], T(right&)[NC1L2][NCol2], T(result&)[NLine1][NCol2]);
Oliv
  • 17,610
  • 1
  • 29
  • 72
  • I know i could do that, but i was just curious as to how it would work if i wanted to return it, if it was possible that is. – Asad Nawaz Feb 10 '18 at 18:57
  • Indeed thi is a right question... C arrays assimilation to pointer is a C++ heritage from C that makes C++ inconsistent. Most of the problematic linked to optimization and constrains on programmer are caused by this heritage. Looking at Gabriel comment, is not changing what he wants to recall us? – Oliv Feb 11 '18 at 09:49