I am writing this c++ code to multiply two 2d matrices and return the resultant 2d matrix.
The error is cannot convert ll (*)[2] to ll**
ll** multiply(ll a[2][2],ll b[2][2])
{
ll ans[2][2];
ans[0][0]=((a[0][0]*b[0][0])%mod+(a[0][1]*b[1][0])%mod)%mod;
ans[0][1]=((a[0][0]*b[0][1])%mod+(a[0][1]*b[1][1])%mod)%mod;
ans[1][0]=((a[1][0]*b[0][0])%mod+(a[1][1]*b[1][0])%mod)%mod;
ans[1][1]=((a[1][0]*b[0][1])%mod+(a[1][1]*b[1][1])%mod)%mod;
return ans;
}
You have a fallen into a trap that seems to get a lot of newcomers to the language.
Passing 2D arrays to a function and returning 2D arrays to a function leads to error prone code. Using a strut/class removes those errors.
In your case, since the size of the arrays is fixed, you can easily use a struct
struct MyMatrix
{
ll data[2][2];
};
then, update multiply to use MyMatrix instead of 2D arrays.
MyMatrix multiply(MyMatrix const& a, MyMatrix const& b)
{
MyMatrix ans;
...
return ans;
}
You can change the function to an overloaded operator too.
MyMatrix operator*(MyMatrix const& a, MyMatrix const& b)
{
MyMatrix ans;
...
return ans;
}
and simplify usage to:
MyMatrix a{ fill in the data for a};
MyMatrix b{ fill in the data for b};
MyMatrix c = a*b;
Related
I'm learning C++, so please be patient with me.
I have a std::valarray in which there are double elements and I consider it as a 2D matrix.
class Matrix {
valarray<double> elems;
int r, c;
public:
/* type? operator[](int r) { return ? } */
//...
}
I want to overload the operator[], so that I can get a row of the matrix, and after that, I want have the m[r][c] access operator.
Is there any way to get a row, as a sequence of double using std::slice in the valarray, so that if I change a value, it is changed also in the matrix?
I've read this definition in valarray:
std::slice_array<T> operator[]( std::slice slicearr );
My operator[] must have std::slice_array<double>& as returned type?
Thanks.
I don't think std::slice and std::slice_array is what you're looking for, especially the latter is nothing but a helper type with a very limited public interface. You can instead return an proxy object. Here's a possible example of how to implement that.
class Matrix {
/* ... */
class RowProxy {
public:
RowProxy(std::valarray<double>& elems, int c, int row) :
elems(elems), c(c), row(row) {}
double& operator[](int j)
{
return elems[row*c + j];
}
private:
std::valarray<double>& elems;
int row;
int c;
};
RowProxy operator[](int i)
{
return RowProxy(elems, c, i);
}
};
This way, you can access the data with two operator[].
Matrix m(2, 4); // Assuming the ctor initializes elemens with row*column
m[0][0] = 1.234;
m[1][0] = 2.234;
m[1][3] = -52.023;
Note that both Matrix and RowProxy are missing overloads and proper handling for const-ness, and variable names are poor. Also, you might want to think about an out-of-bounds error handling strategy. But it may serve as a starting point for your implementation.
Suppose I have a Matrix class and I'd like to initialize my Matrix objects in two ways:
Matrix a = {1,2,3} // for a row vector
and
Matrix b = {{1,2,3},{4,5,6},{7,8,9}} // for a matrix
As a result, I implemented two copy constructors as below
class Matrix {
private:
size_t rows, cols;
double* mat;
public:
Matrix() {}
Matrix(initializer_list<double> row_vector) { ... }
Matrix(initializer_list< initializer_list<double> > matrix) { ... }
...
}
No matter how I change my interface, such as adding an explicit keyword or change the nested version to Matrix(initializer_list< vector<double> > matrix). It will always cause ambiguities between these two cases:
Matrix a = {1,2,3};n
Matrix b = {{1}, {2}, {3}};
I'm not quite familiar with the stuff like direct/copy initialization or implicit type conversion. Are there any solutions for this problem?
There is no solution which will unambiguously work in every case. However, you can create ways to disambiguate cases:
template<typename T>
auto il(std::initializer_list<T> the_il) -> std::initializer_list<T> { return the_il; }
Matrix b = {il({1}), {2}, {3}};
However, I would personally suggest that you be explicit about it. If a user wants a matrix containing one row, then it should look like a matrix containing one row, not like a vector:
Matrix a = {{1,2,3}};
So I would suggest ditching the first overload altogether.
Well, here's a very dirty trick:
#include <iostream>
#include <initializer_list>
struct Matrix
{
template<class = void> Matrix(std::initializer_list<double>) { std::cout << "vector\n"; }
Matrix(std::initializer_list<std::initializer_list<double>>) { std::cout << "matrix\n"; }
};
int main()
{
Matrix a = {1, 2, 3};
Matrix b = {{1}, {2}, {3}};
(void)a; (void)b;
}
The two overloads cannot be distinguished based on conversions, so we rely on a subsequent step in the overload resolution process: a non-template function is preferred over a template specialization.
Why not just create one constructor that takes a matrix, create a private function copy and inside copy you check for a row_vector.
private void Matrix::copy(const Matrix &matrix)
{
if (matrix.rows == 1)
{
//row vector stuff here
}
else if (matrix.cols == 1)
{
//col vector stuff here
}
else
{
//matrix stuff here
}
}
I am new to C++ and I have a question (sorry if it is something too basic but I want to know). So I have this code which is supposed to multiply every element of a vector with a number:
#include<iostream>
#include "IntCell.h"
#include<vector>
using namespace std;
vector<float> MatMult(int a, vector<float> & b)
{
vector<float> c;
int i;
for(i=0;i<=b.size();i++){
c[i]=b[i]*a;
}
return c;
}
int main()
{int a=3;
vector<float> b{1,2,3,4,5};
vector<float> c = MatMult(a,b);
cout<<c[2];
}
It compiles fine, but I get Segmentation fault: 11. What is wrong about it?
Thank you!
If you have a reasonably current compiler this is simpler. Take the vector by value and multiply using a range-based for loop to avoid out-of-range bugs.
vector<float> MatMult(int a, vector<float> b)
{
for (float& value : b) {
value *= a;
}
return b;
}
This can be made more generic as a template function. Note the code below almost certainly can be improved.
template <typename T>
vector<T> MatMult(int a, vector<T> b)
{
for (auto& value : b) {
value *= a;
}
return b;
}
vector<float> c; creates an empty vector. You then uses it in c[i]=b[i]*a; which is undefined behavior as c[anything] does not exist.
You need to make c the same size as b if you want to use c[i]=b[i]*a;. That would look like:
vector<float> MatMult(int a, vector<float> & b)
{
vector<float> c(b.size());
for(int i = 0; i < b.size(); i++){
// ^ use < here since b[b.size()] is out of bounds
c[i]=b[i]*a;
}
return c;
}
You can't just do c[i] since there's no such index yet. You'd better write c.push_back(b[i] * a) or preallocate memory with c.reserve(b.size()).
What's more, b.size() returns the number of elements in a vector, not the biggest index, so you should use i < b.size() instead of i <= b.size().
In addition to the other answers given, one way to discover right away if you are accessing vectors out of bounds is to first develop using vector::at() and not use [].
vector<float> MatMult(int a, vector<float> & b)
{
vector<float> c;
int i;
for(i=0;i<=b.size();i++){
c.at(i) = b.at(i) * a;
}
return c;
Instead of a segmentation fault, you would have been given an out_of_range exception, thus giving you much more information on what the issue is. Once you rid yourself of all of the out_of_range errors, you can then switch to using [].
Live Example using vector::at
I have a Matrix class that looks something like this:
template<int R, int C>
class Matrix{
public:
double matrix[R][C];
Matrix(double n = 0)...{}
...
};
Matrix<2,3> m;
How do I initialize the array when creating a new matrix with the n in the c'tor, without iterating over the whole array cell by cell?
I've read here some answers about something called memset, but I can't use it at the moment (it's a part of homework assignment).
My advice is to use std algorithms wherever possible:
std::for_each(std::begin(matrix), std::end(matrix),
[n](double* row) { std::fill_n(row, C, n); } );
Full example:
template<int R, int C>
class Matrix{
public:
double matrix[R][C];
Matrix(double n = 0) {
std::for_each(std::begin(matrix), std::end(matrix),
[n](double* row) { std::fill_n(row, C, n); } );
}
};
Iterate over the whole array cell be cell using clear, simple, obvious code. If your compiler is sensible (and why use it if it's not) it will understand precisely what you are doing and substitute in the optimal initialization mechanism for your platform.
I am doing an addition of matrices using classes.I have declared a class 'Matrix'.now i need to pass an object of Matrix to a function.how do i do that?
Actually, the best way (IMHO) is to overload operator+(). Thus in your code, you'll need to use only +:
class Matrix {
private:
// Your code
public:
// Your code
friend Matrix operator+(const Matrix &c1, const Matrix &c2);
}
friend Matrix operator+(const Matrix &c1, const Matrix &c2) { <--- passing by reference
// Your code to add matrices
}
int main() {
Matrix A, B;
Matrix C = A + B;
}
In the case of the passing by value Matrix sum(Matrix a, Matrix b), you will need to write a copy constructor if memory for matrix is allocated dynamically.
Passing by pointer Matrix sum(Matrix *a, Matrix *b) is a C style coding, so it is still correct, but not preferable for C++.
Matrix object;
// ...
f(object);
You have quite a few ways to do it.
By Value:
void func (Matrix m);
By Reference:
void func (Matrix& m);
Or By Pointer:
void func (Matrix* m);
Which one you use depends on your needs and semantics of the operation.