Matrix class in C++ - c++

I need a Matrix class for a project I'm doing in C++ but I don't know how to declare the constructor.
I know I need a height and a width. But how do I go about the part where I store the values? What's the best practice?
I thought about having my constructor be:
Matrix::Matrix(int height, int width, int[] values)
and so the private attributes of my class would be height, width and? How can I say that I want to store a number of values that I don't have yet?
I hope this makes sense... I'm finding it very hard to explain and that's probably because I'm very confuse. I'm very new with C++, so any extra help will be appreciated.

Just for an illustration list of constructors for OpenCV's cv::Mat class:
// constructors
Mat();
// constructs matrix of the specified size and type
// (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.)
Mat(int _rows, int _cols, int _type);
Mat(Size _size, int _type);
// constucts matrix and fills it with the specified value _s.
Mat(int _rows, int _cols, int _type, const Scalar& _s);
Mat(Size _size, int _type, const Scalar& _s);
// copy constructor
Mat(const Mat& m);
// constructor for matrix headers pointing to user-allocated data
Mat(int _rows, int _cols, int _type, void* _data, size_t _step=AUTO_STEP);
Mat(Size _size, int _type, void* _data, size_t _step=AUTO_STEP);
// creates a matrix header for a part of the bigger matrix
Mat(const Mat& m, const Range& rowRange, const Range& colRange);
Mat(const Mat& m, const Rect& roi);
// converts old-style CvMat to the new matrix; the data is not copied by default
Mat(const CvMat* m, bool copyData=false);
// converts old-style IplImage to the new matrix; the data is not copied by default
Mat(const IplImage* img, bool copyData=false);
// builds matrix from std::vector with or without copying the data
template<typename _Tp> explicit Mat(const vector<_Tp>& vec, bool copyData=false);
// helper constructor to compile matrix expressions
Mat(const MatExpr_Base& expr);
// assignment operators
Mat& operator = (const Mat& m);
Mat& operator = (const MatExpr_Base& expr);
I think this is good place to get inspiration or use it for your project, hover I'd recommend following constructors:
// Will declare whether to fill allocated data with zeros, ones or leave it be
enum MatrixFill { NO_INITIALIZATION, ZERO_FILL, ONES_FILL};
Matrix( const int width, const int height, const MatrixFill fill = NO_INITIALIZATION);
// To initialize from T data[] = {1,2,3,1,2,3,1,2,3};
Matrix( const int width, const int height, const T *data);
// To initialize from T data[][3] = {{1,2,3},{1,2,3},{1,2,3}};
Matrix( const int width, const int height, const T **data);
// To initialize from other matrix
Matrix( const Matrix &orig);
// Don't forget assign operator
Matrix &operator=(const Matrix &orig);
I'd also create type SubMatrix which wouldn't contain any data just link to parent data and range which would allow you to do this:
Matrix my( old.getSubMatrix( row, col, rowsCount, colsCount));
// And of course it'd have constructor like this:
Matrix( const SubMatrix &orig);
You may add many more constructors but I'd start with those five. Ask questions if you have any.

I'd learn from the pros: http://www.boost.org/doc/libs/1_48_0/libs/numeric/ublas/doc/matrix.htm#matrix

You should probably have a number of constructors, based on how you expect to use the class.
Assuming you plan to use Matrix for some kind of linear algebra, you should have a constructor which initializes the elements to zero:
Matrix(int height, int width); // initializes elements to 0
You should have constructors that initialize the elements from whatever data source you expect to find convenient (below, the type T is the element type of your Matrix):
Matrix(int height, int width, const std::vector<T> &data); // init from vector
Matrix(int height, int width, const T *data); // init from array
If you want to be able to declare an array of matrices, you need a default constructor:
Matrix(); // uninitialized or default array (to be initialized later)
You should also either define or disable copy constructors and assignment operators (or C++ will define them for you, badly):
Matrix(const Matrix &orig); // copy constructor
Matrix& operator=(const Matrix &orig); // assignment operator

I would really try to look for a book about OO design and their application in C++. As this question (besides hard to understand) shows a general misunderstanding of how object oriented languages work. I could explain it here in this topic; but that would be redundant and book authors can do it much better than me.
Basically what I understood from this question is that you know the sizes of your matrix, yet don't know the values they will get when you create them?
In that case simply make a constructor with only the sizes. And initialize the matrix to some "NULL" value. (Possibly even set a private member to false, indicating it isn't completely usable yet). The class and constructor would look like:
class Matrix() {
public:
Matrix(int nRows, int nColumns);
private:
int numRows;
int numColums;
std::vector<VALUE_TYPE> val;
};
Matrix::Matrix(int nRows, int nColums) {
int numRows = nRows;
int numColumns = nColums;
std::vector<VALUE_TYPE> val(nRows * nColums);
}
Simply said: the constructor only makes sure the memory is "allocated". Then you use other functions to fill in the actual values.
If you wish to provide "something", where you don't know exactly what "something" is. But you do know it is a container of data - you should use standard iterators (or templates). This is the manner how c++ handles inserting of data to standard containers. The function would be like this:
template <typename InIt>
Matrix::Matrix(int nRows, int nColums, InIt begin, InIt end) {
int numRows = nRows;
int numColumns = nColums;
//[begin, end) now holds the data - manipulate it at will.
std::vector<VALUE_TYPE> val(begin, end);
val.resize(nColums * nRows);
}
But once again: I'd take a book as the question to me seems unclear and answered by books.

Not strictly related to cpstructors but ... are you matrix expected to be resized during their life? If not, consider the idea not to have numRows and numCols as "variables" (they will never vary) but as template parameters.
Your matrix can be so declared as
Matrix<int,3,3> a; //a 3x3 integers
Matrix<double,3,2> a; //a 3x2 doubles
This will let impossible operations (like adding matrix with different sizes) impossible to compile.

Related

Const Double Indexing with [][] in Matrix Class

The following code contains a simple example of a Matrix class, with double indexing [][] enabled using a 'proxy' Row class.
#include <valarray>
#include <iostream>
template <typename T>
class Matrix {
private:
// Data members
int nRows_;
int nColumns_;
std::valarray<T> data_;
public:
// Constructor
Matrix(const int nRows,
const int nColumns)
: nRows_{nRows},
nColumns_{nColumns},
data_{std::valarray<T>(nRows*nColumns)} {}
// Row friend class to enable double indexing
class Row {
friend class Matrix;
private:
// Constructor
Row(Matrix& parent,
int row)
: parent_{parent},
row_{row} {}
// Data members
Matrix& parent_;
int row_;
public:
// Index columns
T& operator[](int column) {
int nColumns{parent_.nColumns_};
int element{row_*nColumns + column};
return parent_.data_[element];
}
};
// Index rows
Row operator[](int row) {
return Row(*this, row);
}
};
However, this doesn't allow double indexing of a const Matrix. For example, the below code fails to compile when the last line is included.
int main() {
Matrix<int> a{3,3};
const Matrix<int> b{3,3};
std::cout << a[1][2];
std::cout << b[1][2];
}
So the question is, how can I modify my Matrix class to allow for double indexing of const Matrix objects?
Since b is a const Matrix, you need to add const versions of your indexing operator.
Row operator[](int row) const { ... }
This will require additional changes to the Row class (or a second proxy class) to handle the const Matrix & and const overload of operator[].
I think I'm lacking a logical understanding of why things need/need not be const
It depends if you can modify argument or not. in general operator[] should not change object (unless it does, but then...ugh), it should return reference to object's resource. Tada! Your implementation doesn't allow that, because valarray is const then. You cant assign const matrix reference to
Matrix& parent_;
And as result
Row(const Matrix& parent, int row)
Why store Matrix itself... I'd stored reference of valarray.
Actually I would ditch container and create own transparent array in heap. that way Row would have a reference to part of array and length of row, nearly zero of overhead.

This is from my assignment. Can't figure out T**?

template <class T>
class Matrix
{
private:
T** data; // matrix elements stored here
int rows; // number of rows
int cols; // number of columns
public:
Matrix(int numRows = 0, int numCols = 0); // makes storage allocation but leaves it uninitialized, for 0,0 dont allocate memory
Matrix(T const* const* inputData, int numRows, int numCols);
Matrix(const Matrix& rhs);
~Matrix();
I have to do implementation and normally I can. But this time I can't figure out what to do with T**
I am pretty newbie as you can see. At the first i thought as a double pointer but clearly it isn't. I can only use the ”iostream” header file and the Matrix class’ interface header file that which is given to me.
Look in the following link, its pretty self-explanatory, and will guide your implementation (supposing you know how to do it without templates):
http://www.cplusplus.com/doc/tutorial/templates/#class_templates
You will end initializing your class as:
Matrix<int> *myMatrix = new Matrix<int>(data, 10,10);
or
Matrix<int> myMatrix(10,10);
Matrix::Matrix(int numRows = 0, int numCols = 0)
:data(new T[numRows][numCols]){}
Matrix::~Matrix(){delete [] data;}
I'd let yourself figure out the rest.

Efficient way to access submatrices with single index

I'm trying to perform a strided access to a submatrix with a single index. I need this for a library I'm working on which uses expression templates. I have worked out the following class, where the access is performed by the overloaded operator[], see below:
template <class A, class Type>
class SubMatrixExpr
{
private:
int Rows_; // Rows of the SubMatrix
int Columns_; // Columns of the SubMatrix
int Rows_up_; // Rows of the original Matrix
int Columns_up_; // Columns of the original Matrix
int a_, c_; // Starting indices of the SubMatrix as evaluated in the original Matrix
int rowstep_, columnstep_; // Stride along rows and columns for the original matrix
A M_;
public:
SubMatrixExpr(A &M, int Rows_up, int Columns_up, int Rows, int Columns, int a, int rowstep, int c, int columnstep) :
a_(a), c_(c), M_(M),
Rows_(Rows),
Columns_(Columns),
Rows_up_(Rows_up), Columns_up_(Columns_up),
rowstep_(rowstep), columnstep_(columnstep) { }
inline const Type& operator[](const int i) const
{
const int LocalRow = i/Columns_;
const int LocalColumn = i%Columns_;
const int GlobalRow = a_+rowstep_*LocalRow;
const int GlobalColumn = c_+columnstep_*LocalColumn;
return M_[IDX2R(GlobalRow,GlobalColumn,Columns_up_)];
}
inline Type& operator[](const int i)
{
// Similar to above
}
};
where
#define IDX2R(i,j,N) (((i)*(N))+(j))
The overloaded operator[] works correctly, but is computationally very expensive.
Is there any way to better implement the overloaded operator[]?
Thanks a lot in advance.
The only way you may got speedup is if you now the size of the matrices and sub-matrices at compile time. Then using template / constexpr may speedup things. For example if the size is known to be a power of 2 at compile time, the compiler will be able to replace division by shift.

Where are cv::Mat constructors explicitly defined?

[1] Where are the cv::Mat data structure constructors explicitly (in C/C++) defined in the OpenCV source code?
I assume a cv::Mat data structure is dynamically allocated to the heap when something like
cv::Mat mat(rows, cols, type);
is called, but could neither find the ANSI C or C++ implementation in
opencv / modules / core / src / matrix.cpp nor in
opencv / modules / core / src / datastructs.cpp.
SOLVED: cv::Mat is allocated with a fastMalloc() in matrix.cpp. this is performed within the cv::Mat:create() function.
[2] Further, I'm curious to know where in hardware the cv::Mat will be located when image processing operations are performed:
. always in 'main memory' (SDRAM),
. always in on-chip caches (SRAM),
. or some combination of the two?
cv::Mat mat(rows, cols, type);
This is inline constructor and it's implemented in core/mat.hpp:
inline Mat::Mat(int _rows, int _cols, int _type) : size(&rows)
{
initEmpty();
create(_rows, _cols, _type);
}
The actual constructors are in
... / core / core.hpp
class CV_EXPORTS Mat
{
public:
//! default constructor
Mat();
//! constructs 2D matrix of the specified size and type
// (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.)
Mat(int rows, int cols, int type);
Mat(Size size, int type);
//! constucts 2D matrix and fills it with the specified value _s.
Mat(int rows, int cols, int type, const Scalar& s);
Mat(Size size, int type, const Scalar& s);
//! constructs n-dimensional matrix
Mat(int ndims, const int* sizes, int type);
Mat(int ndims, const int* sizes, int type, const Scalar& s);
//! copy constructor
Mat(const Mat& m);
//! constructor for matrix headers pointing to user-allocated data
Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP);
Mat(Size size, int type, void* data, size_t step=AUTO_STEP);
Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps=0);
.....
};

c++ template class's operators

I'm teaching myself c++ by creating my own data structure class (a matrix, to be exact) and I've changed it to a template class of type <T> from only using doubles. The overloaded matrix operators were pretty standard
// A snippet of code from when this matrix wasn't a template class
// Assignment
Matrix& operator=( const Matrix& other );
// Compound assignment
Matrix& operator+=( const Matrix& other ); // matrix addition
Matrix& operator-=( const Matrix& other ); // matrix subtracton
Matrix& operator&=( const Matrix& other ); // elem by elem product
Matrix& operator*=( const Matrix& other ); // matrix product
// Binary, defined in terms of compound
Matrix& operator+( const Matrix& other ) const; // matrix addition
Matrix& operator-( const Matrix& other ) const; // matrix subtracton
Matrix& operator&( const Matrix& other ) const; // elem by elem product
Matrix& operator*( const Matrix& other ) const; // matrix product
// examples of += and +, others similar
Matrix& Matrix::operator+=( const Matrix& rhs )
{
for( unsigned int i = 0; i < getCols()*getRows(); i++ )
{
this->elements.at(i) += rhs.elements.at(i);
}
return *this;
}
Matrix& Matrix::operator+( const Matrix& rhs ) const
{
return Matrix(*this) += rhs;
}
But now that Matrix can have a type, I'm having trouble determining which of the matrix references should be type <T> and what the consequences would be. Should I allow dissimilar types operate on each other (eg., Matrix<foo> a + Matrix<bar> b is valid)? I'm also a little fuzzy on how
One reason I'm interested in dissimilar types is to facilitate the use of complex numbers in the future. I'm a newbie at c++ but am happy to dive in over my head to learn. If you're familiar with any free online resources that deal with this problem I would find that most helpful.
Edit: no wonder no one thought this made sense all of my angle brackets in the body were treated as tags! I can't figure out how to escape them, so I'll inline code them.
I figure that I should illustrate my comment about parameterizing matrix dimensions, since you might not have seen this technique before.
template<class T, size_t NRows, size_t NCols>
class Matrix
{public:
Matrix() {} // `data` gets its default constructor, which for simple types
// like `float` means uninitialized, just like C.
Matrix(const T& initialValue)
{ // extra braces omitted for brevity.
for(size_t i = 0; i < NRows; ++i)
for(size_t j = 0; j < NCols; ++j)
data[i][j] = initialValue;
}
template<class U>
Matrix(const Matrix<U, NRows, NCols>& original)
{
for(size_t i = 0; i < NRows; ++i)
for(size_t j = 0; j < NCols; ++j)
data[i][j] = T(original.data[i][j]);
}
private:
T data[NRows][NCols];
public:
// Matrix copy -- ONLY valid if dimensions match, else compile error.
template<class U>
const Matrix<T, NRows, NCols>& (const Matrix<U, NRows, NCols>& original)
{
for(size_t i = 0; i < NRows; ++i)
for(size_t j = 0; j < NCols; ++j)
data[i][j] = T(original.data[i][j]);
return *this;
}
// Feel the magic: Matrix multiply only compiles if all dimensions
// are correct.
template<class U, size_t NOutCols>
Matrix<T, NRows, NOutCols> Matrix::operator*(
const Matrix<T, NCols, NOutCols>& rhs ) const
{
Matrix<T, NRows, NOutCols> result;
for(size_t i = 0; i < NRows; ++i)
for(size_t j = 0; j < NOutCols; ++j)
{
T x = data[i][0] * T(original.data[0][j]);
for(size_t k = 1; k < NCols; ++k)
x += data[i][k] * T(original.data[k][j]);
result[i][j] = x;
}
return result;
}
};
So you'd declare a 2x4 matrix of floats, initialized to 1.0, as:
Matrix<float, 2, 4> testArray(1.0);
Note that there is no requirement for the storage to be on the heap (i.e. using operator new) since the size is fixed. You could allocate this on the stack.
You can create another couple matrices of ints:
Matrix<int, 2, 4> testArrayIntA(2);
Matrix<int, 4, 2> testArrayIntB(100);
For copying, dimensions must match though types do not:
Matrix<float, 2, 4> testArray2(testArrayIntA); // works
Matrix<float, 2, 4> testArray3(testArrayIntB); // compile error
// No implementation for mismatched dimensions.
testArray = testArrayIntA; // works
testArray = testArrayIntB; // compile error, same reason
Multiplication must have the right dimensions:
Matrix<float, 2, 2> testArrayMult(testArray * testArrayIntB); // works
Matrix<float, 4, 4> testArrayMult2(testArray * testArrayIntB); // compile error
Matrix<float, 4, 4> testArrayMult2(testArrayIntB * testArray); // works
Note that, if there's a botch, it is caught at compile time. This is only possible if the matrix dimensions are fixed at compile time, though. Also note that this bounds checking results in no additional runtime code. It's the same code that you'd get if you just made the dimensions constant.
Resizing
If you don't know your matrix dimensions at compile time, but must wait until runtime, this code may not be of much use. You'll have to write a class that internally stores the dimensions and a pointer to the actual data, and it will need to do everything at runtime. Hint: write your operator [] to treat the matrix as a reshaped 1xN or Nx1 vector, and use operator () to perform multiple-index accesses. This is because operator [] can only take one parameter, but operator () has no such limit. It's easy to shoot yourself in the foot (force the optimizer to give up, at least) by trying to support a M[x][y] syntax.
That said, if there's some kind of standard matrix resizing that you do to resize one Matrix into another, given that all dimensions are known at compile time, then you could write a function to do the resize. For example, this template function will reshape any Matrix into a column vector:
template<class T, size_t NRows, size_t NCols>
Matrix<T, NRows * NCols, 1> column_vector(const Matrix<T, NRows, NCols>& original)
{ Matrix<T, NRows * NCols, 1> result;
for(size_t i = 0; i < NRows; ++i)
for(size_t j = 0; j < NCols; ++j)
result.data[i * NCols + j][0] = original.data[i][j];
// Or use the following if you want to be sure things are really optimized.
/*for(size_t i = 0; i < NRows * NCols; ++i)
static_cast<T*>(result.data)[i] = static_cast<T*>(original.data)[i];
*/
// (It could be reinterpret_cast instead of static_cast. I haven't tested
// this. Note that the optimizer may be smart enough to generate the same
// code for both versions. Test yours to be sure; if they generate the
// same code, prefer the more legible earlier version.)
return result;
}
... well, I think that's a column vector, anyway. Hope it's obvious how to fix it if not. Anyway, the optimizer will see that you're returning result and remove the extra copy operations, basically constructing the result right where the caller wants to see it.
Compile-Time Dimension Sanity Check
Say we want the compiler to stop if a dimension is 0 (normally resulting in an empty Matrix). There's a trick I've heard called "Compile-Time Assertion" which uses template specialization and is declared as:
template<bool Test> struct compiler_assert;
template<> struct compiler_assert<true> {};
What this does is let you write code such as:
private:
static const compiler_assert<(NRows > 0)> test_row_count;
static const compiler_assert<(NCols > 0)> test_col_count;
The basic idea is that, if the condition is true, the template turns into an empty struct that nobody uses and gets silently discarded. But if it's false, the compiler can't find a definition for struct compiler_assert<false> (just a declaration, which isn't enough) and errors out.
Better is Andrei Alexandrescu's version (from his book), which lets you use the declared name of the assertion object as an impromptu error message:
template<bool> struct CompileTimeChecker
{ CompileTimeChecker(...); };
template<> struct CompileTimeChecker<false> {};
#define STATIC_CHECK(expr, msg) { class ERROR_##msg {}; \
(void)sizeof(CompileTimeChecker<(expr)>(ERROR_##msg())); }
What you fill in for msg has to be a valid identifier (letters, numbers, and underscores only), but that's no big deal. Then we just replace the default constructor with:
Matrix()
{ // `data` gets its default constructor, which for simple types
// like `float` means uninitialized, just like C.
STATIC_CHECK(NRows > 0, NRows_Is_Zero);
STATIC_CHECK(NCols > 0, NCols_Is_Zero);
}
And voila, the compiler stops if we mistakenly set one of the dimensions to 0. For how it works, see page 25 of Andrei's book. Note that in the true case, the generated code gets discarded so long as the test has no side effects, so there's no bloat.
I'm not sure I understand what you're asking.
But I would point out that your operator declarations are incorrect and/or incomplete.
Firstly, the assignment operator should return the same type as its parameter; viz:
const Matrix& operator=(const Matrix& src);
Secondly, binary operators return a new object, so you can't return a reference. All binary operators should be declared thus:
Matrix operator+( const Matrix& other ) const; // matrix addition
Matrix operator-( const Matrix& other ) const; // matrix subtracton
Matrix operator&( const Matrix& other ) const; // elem by elem product
Matrix operator*( const Matrix& other ) const; // matrix product
Actually, it is considered better style to declare and implement binary operators as global friend functions instead:
class Matrix { ... };
inline Matrix operator+(const Matrix& lhs,const Matrix& rhs)
{ return Matrix(lhs)+=rhs; }
Hope this helps.
Now I understand what you're asking.
Presumably your implementation of various operators will in this case consist of operations on the composite types. So really the question of whether Matrix op Matrix is meaningful depends on whether string op int is meaningful (and whether such a thing might be useful). You would also need to determine what the return type might be.
Assuming the return type is the same as the LHS operand, the declarations would look something like:
template <typename T>
class Matrix
{
template <typename U>
Matrix<T>& operator+=(const Matrix<U>& rhs);
};
template <typename T,typename U>
Matrix<T> operator+(const Matrix<T>& lhs,const Matrix<U>& rhs)
{ return Matrix<T>(lhs)+=rhs; }
Matrix<double> x = ...;
Matrix<int> y = ...;
cout << x + y << endl; // prints a Matrix<double>?
OK, that's doable, but the problem gets tricky quickly.
Matrix<double> x = ...
Matrix<complex<float>> y = ...
cout << x + y << endl; // Matrix<complex<double>>?
You will most likely be happiest if you require that your binary operators use like-type operands and force your application builders to explicitly type-cast their values. For the latter case:
cout << ((Matrix<complex<double>>) x) + ((Matrix<complex<double>>) y) << endl;
You can provide a member template constructor (or a type conversion operator) to support the conversions.
template <typename T>
class Matrix {
...
public:
template <typename U>
Matrix(const Matrix<U>& that) {
// initialize this by performing U->T conversions for each element in that
}
...
};
The alternative, having your binary operator template deduce the correct Matrix return type based on the element types of the two operands, requires some moderately complex template meta-programming, probably not what you're looking to get into.
First of all, the copy assignment operator should not have const Matrix& as its return type; your interface is correct.
Grant's suggestion of how binary operators are implemented is the generally accepted way of doing these things.
It's a nice exercise, but one quickly sees why doing linear algebra in C++ is a bad idea to begin with. Operations like A+B and A*B are valid only if the dimensions of the matrices match up.
You don't have to add much at all, because inside a template, the class name itself refers to the current template parameter. So the following are equivalent:
template <typename T> struct Foo
{
Foo<T> bar(const Foo<T> &);
Foo bar2(const Foo *); // same
};
So all your operations just go through without change. What you should add is a constructor that converts one matrix type into another:
temlate <typename T> class Matrix
{
template <typename U> Matrix(const Matrix<U> &); // construct from another matrix
/*...*/
};
Using that conversion constructor, you can mix matrices in your operators, as Matrix<T>::operator+(Matrix<U>) will use the conversion to create an argument of type Matrix<T>, and then you use your already implemented operator.
In C++11 you can add static_assert(std::is_convertible<U, T>::value, "Boo"); to your converting constructor to give you a useful compile-time diagnostic if you call it with an incompatible type.