I defined the struct below in C++ to hold a C++ class array:
template <int nrow, int ncol>
struct Mat{
int row_size = nrow;
int col_size = ncol;
std::array<std::array<float, ncol>, nrow> mat;
};
Then I tried to define a function which prints this 2D array:
void show(Mat mat){
for(size_t row=0; row<mat.row_size; row++){
for(size_t col=0; col<mat.col_size; col++){
std::cout<<mat.mat[row][col]<<" ";
}
}
}
However, I get the error below:
Use of class template 'Mat' requires template arguments; argument deduction not allowed in function prototype
I am new to C++ and I cannot understand what the error means! I thought perhaps trying this might work:
void show(Mat<int, int> mat){
for(size_t row=0; row<mat.row_size; row++){
for(size_t col=0; col<mat.col_size; col++){
std::cout<<mat.mat[row][col]<<" ";
}
}
}
But then I get another error.
Make your function a template function (the same way you made your template struct) i.e.:
template<int nrow, int ncol>
void show(Mat<nrow, ncol> mat){
for(size_t row=0; row<mat.row_size; row++){
for(size_t col=0; col<mat.col_size; col++){
std::cout<<mat.mat[row][col]<<" ";
}
}
}
Now you can define your Mat struct as such:
Mat<10,10> matrix;
//insert elements into matrix;
//...
show(mat);
Hope it helps!
Related
i'm building a linear algebra library en c++ with learning purposes.
I want to make a constructor that takes the rows, columns and a 2D array for a matrix class without using templates or std::vector, but can't figure it out. I have this already done:
#include <iostream>
using namespace std;
class Matrix{
private:
int rows, columns;
float **matrix;
public:
Matrix(int rows, int columns){
this->rows = rows;
this->columns = columns;
this->matrix = new float*[rows]();
for(int row = 0; row < rows; row++){
this->matrix[row] = new float[columns]();
}
}
float operator()(int row, int col){
return this->matrix[row][col];
}
void print(void){
cout << "\n";
for(int row = 0; row < rows; row++){
cout << "\n";
for(int col = 0; col < columns; col++){
cout << matrix[row][col];
}
}
}
};
For initialize a matrix with, for example, Matrix A(3,3), printing it or using elements of it.
Now I would like to make one that takes a 2d array as an argument, something like Matrix A(2,2,a) where a is declared as float** a{{1,5},{7,8}}, but I can't figure out how to pass the array to the constructor. In C I would make a constructor like `Matrix (int rows, int cols, float matrix[rows][cols]), but in c++ that doesn't seems to work.
I don't want some crapy solution like input element by element, I want to make code readable, and declaration as simple as possible. Any advice?
I want to do something like:
int a[][]; // I know this code won't work, its to demonstrate what I want to do
void func(int n, int m){
a = int[n][m];
}
that is, initialise a global array whose size depends on function input. If this array was local, it would be a trivial case, but I don't know how to do this in the case shown above. Any help would be very useful!
You can create a matrix with std::vector:
std::vector<std::vector<int>> a;
void func(int n, int m) {
a.resize(n);
for(int i = 0; i < n; i++) {
a[i].resize(m);
}
}
Then you can access elements in the same way you do with int a[][]:
a[i][j] = number;
One way to achieve this is to encapsulate a flat std::vector in a Matrix class and use math to get an element with row and column as in this example:
template<typename T>
class Matrix {
private:
vector<T> vec;
//...
public:
T& get_value(size_t const row, size_t const col) {
return vec[row * col_count + col];
}
};
you can try this
int ** a; // is a pointer of two dimension
void func(int n, int m){
a = new int*[n]; //dynamic allocation global pointer a
for(int i = 0; i < n; i++)
a[i] = new int[m]();
}
I want to implement a Matrix class. I coded an array of arrays of pointers. When I set the values of each element of the array to 0 with a for loop, it works fine (apparently). But when I try to declare a function of my class (setvalues) to take the values of a 1D array and store them in the matrix, theres a problem with the arguments. I am not sure how to declare a function that takes a dynamic array as argument.
#include<iostream>
using namespace std;
class Matrix{
int rows, columns, numE;
double *mData=new double[numE];
public:
double** matrix;
Matrix(int,int);
setmatrix();
setvalues(double);
};
Matrix::Matrix(int x, int y){
rows=y;
columns=x;
matrix=new double*[columns];
for(int i = 0; i < columns; ++i){
matrix[i]=new double[rows];
}
}
Matrix::setmatrix(){
for(int i=0;i<rows;i++){
for(int j=0;j<columns;j++){
matrix[i][j]=0.0;
cout<<matrix[i][j]<<endl;
}
}
}
Matrix::setvalues(double mData[]){
for(int i=0;i<rows;i++){
for(int j=0;j<columns;j++){
matrix[i][j]=mData[i];
}
}
}
int main(){
Matrix AA(2,2);
AA.setmatrix();
//AA.setvalues();
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
cout<<AA.matrix[i][j] << endl;
}
}
cout<< AA.matrix << endl;
delete [] AA.matrix;
return 0;
}
PS: I don't want to use vector or smart pointers. Also if you have any feedback about my code regarding functionaity, readability and if you know a smarter way to do it please tell me.
I'm trying to use clear functions to do a matrix multiplication with random generated values. Therefore I'm hoping to use a function(mat_def) to generate the matrices and another function(mat_mul) to multiply them when the matrices are sent as parameters.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
double mat_def(int n) //how to return the matrix
{
double a[n][n];
double f;
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
f= rand();
cout<<f ;
a[i][j]=f;
}
}
return 0;
}
double mat_mul( int n, double a[n][n], double b[n][n]) //how to send matrix as parameter
{
return 0;
}
int main()
{
/* initialize random seed: */
srand (time(NULL));
mat_def(10);
}
Here's a nice, standard C++ Matrix template for you.
Matrix.h
#include <vector>
class Matrix
{
class InnerM
{
private:
int ydim;
double* values;
public:
InnerM(int y) : ydim(y)
{
values = new double[y];
}
double& operator[](int y)
{
return values[y];
}
};
private:
int xdim;
int ydim;
std::vector<InnerM> inner;
public:
Matrix(int x, int y) : xdim(x), ydim(y), inner(xdim, InnerM(ydim))
{
}
InnerM& operator[](int x)
{
return inner[x];
}
};
All the memory leaks are there for you but you get the idea. From here you can handle the multiplication by overiding ::operator*() in the Matrix class.
I assume your problem is to define 2-D array and then pass it to mat_mul function to multiply the matrices. And the rest will be quite simple.
Defining the 2-D array(considering memory needs are known at run time):
int rows,cols;
cin >> rows;
cin >> cols;
int **arr = new int*[rows]; // rows X cols 2D-array
for(int i = 0; i < rows; ++i) {
arr[i] = new int[cols];
}
You can define another 2-D array exactly the same way with required rows and column.
now, Passing the 2-D array to function:
void mat_mul(int **arr1, int **arr2, int m, int n, int p, int q){
//define a 2-D array to store the result
//do the multiplication operation
//you could store the result in one of the two arrays
//so that you don't have to return it
//or else the return type should be modified to return the 2-D array
}
example:
void display(int **arr, int row, int col){
for (int i=0; i<row; i++){
for(int j=0;j<col; j++){
cout << arr[i][j] << '\t';
}
cout << endl;
}
}
Delete the memory if not required anymore with the following syntax:
for(int i=0; i<rows; i++){
delete[] array[i];
}
delete[] array;
hope this will be sufficient to get your work done!
there is already an answer on how to return a 2-D array on SO. Check the link below.
https://stackoverflow.com/a/8618617/8038009
Returning the raw allocation is a sucker bet. You need to manage all of the memory allocated yourself and pass it around with the matrix size parameters.
Why suffer? Use a matrix class
template<class Type>
class Matrix{
int rows;
int cols;
std::vector<type> data;
public:
Matrix(int row, int col):rows(row), cols(col), data(rows*cols)
{
// does nothing. All of the heavy lifting was in the initializer
}
// std::vector eliminates the need for destructor, assignment operators, and copy
//and move constructors.
//add a convenience method for easy access to the vector
type & operator()(size_t row, size_t col)
{
return data[row*cols+col];
}
type operator()(size_t row, size_t col) const
{
return data[row*cols+col];
}
};
Usage would be
Matrix<double> mat_mul(const Matrix<double> &a, const Matrix<double> &b)
{
Matrix<double> result;
// do multiplication
return result;
}
int main()
{
/* initialize random seed: */
srand (time(NULL));
Matrix<double> matA(10, 10);
matA(0,0) = 3.14; // sample assignment
matA(9,9) = 2.78;
double x = matA(0,0) * matA(9,9)
Matrix<double> matB(10, 10);
Matrix<double> matC = mat_mul(matA, matB) ;
}
More functionality, such as construction from an initializer list, can be added to the class to make your life easier. You can also specify an operator * overload for Matrix and use that in place of mat_mul if you chose. Read Operator overloading for more on that option.
#include<iostream>
using namespace std;
void transpose(const int input[2][3], int (&output)[3][2]){
for(int i=0; i<2; ++i) {
for(int j=0; j<3 ; ++j) {
output [j][i] = input [i][j];
}
}
}
void printMultiArray(const int multi[2][3], const int len){
for (int row=0; row<2; row++){
for (int col=0; col<3; col++){
cout << multi[row][col] << " " ;
}
cout << endl;
}
}
int main(){
int multi[2][3] = {{1, 2, 3}, {7, 8, 9}};
int empty[3][2];
printMultiArray(multi, 6);
cout << "... space line ..." << endl;
transpose(multi, empty);
printMultiArray(empty, 6);
return 0;
}
I have the above code to tranpose a 2x3 array... but it does not compile and fails with:
6-3-transposeArray.cpp: In function ‘int main()’:
6-3-transposeArray.cpp:33: error: cannot convert ‘int (*)[2]’ to ‘const int (*)[3]’ for argument ‘1’ to ‘void printMultiArray(const int (*)[3], int)’
I am not sure what the problem is though. It seems to be complaining about the 1st arg to transpose() but printMultiArray() seems to have no problem with the array being passed in the same manner.
Secondly is there a more generic way to implement this? (e.g. a generic func that could take in 2x3, 2x4 and 2x5 arrays and return the transpose of each)
Bit of a basic question but Any help appreciated :)
It seems to be complaining about the 1st arg to transpose()
No, the error clearly says the problem is with the first argument to printMultiArray. You're passing a 3x2 array, and the function is hard-coded for a 2x3 array.
Secondly is there a more generic way to implement this?
Yes; you can use integer template parameters to specify the dimensions:
template <size_t N, size_t M>
void transpose(const int (&input)[N][M], int (&output)[M][N]) {
for (size_t i = 0; i < N; ++i) {
for (size_t j = 0; j < M; ++j) {
output[j][i] = input[i][j];
}
}
}
The correct template specialisation can be deduced from the function arguments:
transpose(multi, empty); // Automatically selects N=2, M=3.
Similarly, you can implement a generic printMultiArray to fix your error.
Create a class that contains a vector. In the constructor pass the x and y size of the matrix, and resize the vector to x * y. Create get/set functions (or operator []) which take the x, y coordinate the user wishes to access. Also have a "transposed" bool flag in the class. If the flag is true, swap x and y, and then return vec[x + y * sizex]. Now transposing the array does not need any copying. Just flip the flag.
You could implement these using std::vectors and it would be much more readable and manageable.
BUT if you want something that is generic I would use Eigen. If you insist on implementing yourself and you want something generic I would build a class that does this for you. I won't go too much into the design but it could be something like
newMat = oldMat.Transpose()
where newMat and oldMat are of a MyMatrix class that you implement