I have defined one matrix class, and overloaded the + operator to be able to add instances of this class together.
class Matrix{
public:
vector<vector<int>> a;
Matrix & operator+(const Matrix& b)
{
vector<vector<int>>::const_iterator it0=b.a.begin();
vector<vector<int>>::iterator it1=this->a.begin();
vector<int>::iterator it2=it1->begin();
vector<int>::iterator it3=it1->end();
vector<int>::const_iterator it01=it0->begin();
for(it1;it1!=this->a.end();it1++)
{
it2=it1->begin();
it3=it1->end();
it01=it0->begin();
it0++;
// a.begin(),a.end(),b.begin(),ret.begin()
std::transform(it2,it3,it01,it2,std::plus<int>());
}
return *this;
}
};
But then, there is also another way of doing this,
class Matrix{
public:
vector<vector<int> > a;
Matrix & operator + (const Matrix &y) {
for (int m=0; m<y.a.size(); ++m) {
for (int n=0; n<y.a[0].size(); ++n) {
this->a[m][n] = this->a[m][n] + y.a[m][n];
}
}
return *this;
}};
The second form is shorter, but uses arrays directly, while the first one uses iterators. Maybe it's possible to do this with iterators in a shorter way, I'm not sure. I've tested with simple cases and they seem to be equally efficient.
What's the proper way of doing this?
For non-trivial classes (such as classes including a std::vector), in-place operations are often cheaper than allocating a new object and then (presumably) destroying one or both of the arguments. However, aggressive use of rvalue reference overloads can somewhat mitigate this.
Note that regardless of which function implementation I used, I would not use nested std::vectors - I would either use a single std::vector or better a std::unique_ptr<T[]> and then calculate the index as y*w+x (remember to bounds-check first).
Related
I need to implement matrix as a class in C++.
This is my class:
class {
private:
int rows, columns;
int **mat;
};
In the main, I need to start the matrix in the regular way. For example : m[0][0]=1;
I thought to overloading the operator[][] but it is forbidden.
I would like to get some help. thanks.
Instead, you could overload the function call operator (operator()()), to get something like this:
int operator()(int p_row, int p_column);
which is legal and clean. I would allow you to write something like this:
// Create and fill in matrix called 'm'...
int matrixElement = m(0, 0); // get element m[0][0]
// ...
Here is an example of how to overload this operator.
Let's say we have vector<vector<int>> xThe operator [][] is really (ignoring out of bounds) vector<int> b = x[0] then int = b[0] combined into one line. I.e accessing the first array then the subscript operator of the second.
Hope this helps.
You can store the data in a continuous array using std::vector and then supply your own indexing operator which returns a pointer to the beginning of the row.
class Matrix
{
int rows, columns;
std::vector<int> data;
public:
/*...*/
// The overloaded operator[] returns a pointer to the beginning
// of the requested row, which can then be indexed for the column
// without checking the boundaries.
int* operator[](int r){
return &data[r*columns];
}
};
Using a vector of vectors is less efficient because the data gets spread to different memory locations. If you need bounds checking you can wrap the pointer in your own class and overload its operator[].
OK, I've been googling around for too long, I'm just not sure what to call this technique, so I figured it's better to just ask here on SO. Please point me in the right direction if this has an obvious name and/or solution I've overlooked.
For the laymen: a tensor is the logical extension of the matrix, in the same way a matrix is the logical extension of the vector. A vector is a rank-1 tensor (in programming terms, a 1D array of numbers), a matrix is a rank-2 tensor (a 2D array of numbers), and a rank-N tensor is then simply an N-D array of numbers.
Now, suppose I have something like this Tensor class:
template<typename T = double> // possibly also with size parameters
class Tensor
{
private:
T *M; // Tensor data (C-array)
// alternatively, std::vector<T> *M
// or std::array<T> *M
// etc., or possibly their constant-sized versions
// using Tensor<>'s template parameters
public:
... // insert trivial fluffy stuff here
// read elements
const T & operator() (size_t a, size_t b) const {
... // error checks etc.
return M[a + rows*b];
}
// write elements
T & operator() (size_t a, size_t b) {
... // error checks etc.
return M[a + rows*b];
}
...
};
With these definitions of operator()(...), indexing/assign individual elements then has the same call signature:
Tensor<> B(5,5);
double a = B(3,4); // operator() (size_t,size_t) used to both GET elements
B(3,4) = 5.5; // and SET elements
It is fairly trivial to extend this up to arbitrary tensor rank. But what I'd like to be able to implement is a more high-level way of indexing/assigning elements:
Tensor<> B(5,5);
Tensor<> C = B( Slice(0,4,2), 2 ); // operator() (Slice(),size_t) used to GET elements
B( Slice(0,4,2), 2 ) = C; // and SET elements
// (C is another tensor of the correct dimensions)
I am aware that std::valarray (and many others for that matter) does a very similar thing already, but it's not my objective to just accomplish the behavior; my objective here is to learn how to elegantly, efficiently and safely add the following functionality to my Tensor<> class:
// Indexing/assigning with Tensor<bool>
B( B>0 ) += 1.0;
// Indexing/assigning arbitrary amount of dimensions, each dimension indexed
// with either Tensor<bool>, size_t, Tensor<size_t>, or Slice()
B( Slice(0,2,FINAL), 3, Slice(0,3,FINAL), 4 ) = C;
// double indexing/assignment operation
B(3, Slice(0,4,FINAL))(mask) = C; // [mask] == Tensor<bool>
.. etc.
Note that it's my intention to use operator[] for non-checked versions of operator(). Alternatively, I'll stick more to the std::vector<> approach of using .at() methods for checked versions of operator[]. Anyway, this is a design choice and besides the issue right now.
I've conjured up the following incomplete "solution". This method is only really manageable for vectors/matrices (rank-1 or rank-2 tensors), and has many undesirable side-effects:
// define a simple slice class
Slice ()
{
private:
size_t
start, stride, end;
public:
Slice(size_t s, size_t e) : start(s), stride(1), end(e) {}
Slice(size_t s, size_t S, size_t e) : start(s), stride(S), end(e) {}
...
};
template<typename T = double>
class Tensor
{
... // same as before
public:
// define two operators() for use with slices:
// version for retrieving data
const Tensor<T> & operator() (Slice r, size_t c) const {
// use slicing logic to construct return tensor
...
return M;
{
// version for assigning data
Sass operator() (Slice r, size_t c) {
// returns Sass object, defined below
return Sass(*this, r,c);
}
protected:
class Sass
{
friend class Tensor<T>;
private:
Tensor<T>& M;
const Slice &R;
const size_t c;
public:
Sass(Tensor<T> &M, const Slice &R, const size_t c)
: M(M)
, R(R)
, c(c)
{}
operator Tensor<T>() const { return M; }
Tensor<T> & operator= (const Tensor<T> &M2) {
// use R/c to copy contents of M2 into M using the same
// Slice-logic as in "Tensor<T>::operator()(...) const" above
...
return M;
}
};
But this just feels wrong...
For each of the indexing/assignment methods outlined above, I'd have to define a separate Tensor<T>::Sass::Sass(...) constructor, a new Tensor<T>::Sass::operator=(...), and a new Tensor<T>::operator()(...) for each and every such operation. Moreover, the Tensor<T>::Sass::operators=(...) would need to contain much of the same stuff that's already in the corresponding Tensor<T>::operator()(...), and making everything suitable for a Tensor<> of arbitrary rank makes this approach quite ugly, way too verbose and more importantly, completely unmanageable.
So, I'm under the impression there is a much more effective approach to all this.
Any suggestions?
First of all I'd like to point out some design issues:
T & operator() (size_t a, size_t b) const;
suggests you can't alter the matrix through this method, because it's const. But you are giving back a nonconst reference to a matrix element, so in fact you can alter it. This only compiles because of the raw pointer you are using. I suggest to use std::vector instead, which does the memory management for you and will give you an error because vector's const version of operator[] gives a const reference like it should.
Regarding your actual question, I am not sure what the parameters of the Slice constructor should do, nor what a Sass object is meant to be (I am no native speaker, and "Sass" gives me only one translation in the dictionary, meaning sth. like "impudence", "impertinence").
However, I suppose with a slice you want to create an object that gives access to a subset of a matrix, defined by the slice's parameters.
I would advice against using operator() for every way to access the matrix. op() with two indices to access a given element seems natural. Using a similar operator to get a whole matrix to me seems less intuitive.
Here's an idea: make a Slice class that holds a reference to a Matrix and the necessary parameters that define which part of the Matrix is represented by the Slice. That way a Slice would be something like a proxy to the Matrix subset it defines, similar to a pair of iterators which can be seen as a proxy to a subrange of the container they are pointing to. Give your Matrix a pair of slice() methods (const and nonconst) that give back a Slice/ConstSlice, referencing the Matrix you call the method on. That way, you can even put checks into the method to see if the Slice's parameters make sense for the Matrix it refers to. If it makes sense and is necessary, you can also add a conversion operator, to convert a Slice into a Matrix of its own.
Overloading operator() again and again and using the parameters as a mask, as linear indices and other stuff is more confusing than helping imo. operator() is slick if it does something natural which everybody expects from it. It only obfuscates the code if it is used everywhere. Use named methods instead.
Not an answer, just a note to follow up my comment:
Tensor<bool> T(false);
// T (whatever its rank) contains all false
auto lazy = T(Slice(0,4,2));
// if I use lazy here, it will be all false
T = true;
// now T contains all true
// if I use lazy here, it will be all true
This may be what you want, or it might be unexpected.
In general, this can work cleanly with immutable tensors, but allowing mutation gives the same class of problem as COW strings.
If you allow for your Tensor to implicitly be a double you can return only Tensors from your operator() overload.
operator double() {
return M.size() == 1 ? M[0] : std::numeric_limits<double>::quiet_NaN();
};
That should allow for
double a = B(3,4);
Tensor<> a = B(Slice(1,2,3),4);
To get the operator() to work with multiple overloads with Slice and integer is another issue. I'd probably just use Slice and create another implicit conversion so integers can be Slice's, then maybe using the variable argument elipses.
const Tensor<T> & operator() (int numOfDimensions, ...)
Although the variable argument route is kind of a kludge best to just have 8 specializations for 1-8 parameters of Slice.
I have my own mathematical Vector class that I use in my code. I have a new need to generalize my vector class to n dimensions instead of just two.
My question is, what's the best way to implement the operator overloads, and is there a significant overhead to doing this?
I now store the values in an array
double *vals;
....
vals = new double[dimension];
With this, I implement the + operator like so:
Vector Vector::operator+(Vector v)
{
Vector ret = Vector(dimension);
for (int i = 0; i < dimension; i ++)
{
ret.vals[i] = vals[i] + v.vals[i];
}
}
This operation will be done a LOT and has to run fast. Is this significantly worse than the old version (as far as speed)?
Vector Vector::operator+(Vector v) {
return Vector(x + v.x, y + v.y);
}
Thanks for any input!
If you want a fast vector class then use templates for the size:
template<std::size_t size>
class Vector {
double data[size];
public:
double& operator[](std::size_t x) { return data[x]; }
};
template<std::size_t size>
Vector<size> operator+(Vector<size> lhs, const Vector<size>& rhs) {
for (std::size_t i = 0; i < size; ++i)
lhs[i] += rhs[i];
return lhs;
}
Having them be dynamic size is only unnecessary if you want to re-size them, or if they are incredibly large.
There are ways to get much faster than this, such as SSE. You should use a dedicated math library if you want something highly optimized.
First, I would suggest passing your operand by reference instead of by value to avoid an unnecessary object copy:
Vector Vector::operator+(const Vector &v) {
Second, most compilers implement Return Value Optimization which will help eliminate the local ret in your multidimensional implementation.
The best approach, of course, is to implement your code, benchmark it, and then apply optimisations where necessary. Scott Meyers' Effective C++ is an excellent reference for the sort of thing you're attempting to do here.
I have four std::vector containers that all might (or might not) contain elements. I want to determine which of them has the most elements and use it subsequently.
I tried to create a std::map with their respective sizes as keys and references to those containers as values. Then I applied std::max on the size() of each vector to figure out the maximum and accessed it through the std::map.
Obviously, this gets me into trouble once there is the same number of elements in at least two vectors.
Can anyone think of a elegant solution ?
You're severely overthinking this. You've only got four vectors. You can determine the largest vector using 3 comparisons. Just do that:
std::vector<blah>& max = vector1;
if (max.size() < vector2.size()) max = vector2;
if (max.size() < vector3.size()) max = vector3;
if (max.size() < vector4.size()) max = vector4;
EDIT:
Now with pointers!
EDIT (280Z28):
Now with references! :)
EDIT:
The version with references won't work. Pavel Minaev explains it nicely in the comments:
That's correct, the code use
references. The first line, which
declares max, doesn't cause a copy.
However, all following lines do cause
a copy, because when you write max =
vectorN, if max is a reference, it
doesn't cause the reference to refer
to a different vector (a reference
cannot be changed to refer to a
different object once initialized).
Instead, it is the same as
max.operator=(vectorN), which simply
causes vector1 to be cleared and
replaced by elements contained in
vectorN, copying them.
The pointer version is likely your best bet: it's quick, low-cost, and simple.
std::vector<blah> * max = &vector1;
if (max->size() < vector2.size()) max = &vector2;
if (max->size() < vector3.size()) max = &vector3;
if (max->size() < vector4.size()) max = &vector4;
Here's one solution (aside from Pesto's far-too-straightforward approach) - I've avoided bind and C++0x lambdas for explanatory purposes, but you could use them to remove the need for a separate function. I'm also assuming that with two vectors with an equal number of elements, which one is picked is irrelevant.
template <typename T> bool size_less (const T* lhs, const T* rhs) {
return lhs->size() < rhs ->size();
}
void foo () {
vector<T>* vecs[] = {&vec1, &vec2, &vec3, &vec4};
vector<T>& vec = std::min_element(vecs, vecs + 4, size_less<vector<T> >);
}
Here is my very simple method. Only interest is that you just need basic c++ to understand it.
vector<T>* v[] = {&v1, &v2, &v3, &v4}, *max=&v1;
for(int i=1; i < 4; ++i)
if (v[i]->size() > max->size()) max = v[i];
This is a modified version of coppro's answer using a std::vector to reference any number of vectors for comparison.
template <typename T> bool size_less (const T* lhs, const T* rhs) {
return lhs->size() < rhs ->size();
}
void foo () {
// Define vector holding pointers to the original vectors
typedef vector< vector<T>* > VectorPointers;
// Fill the list
VectorPointers vecs;
vecs.push_back(&vec1);
vecs.push_back(&vec2);
vecs.push_back(&vec3);
vecs.push_back(&vec4);
vector<T>& vec = std::min_element(
vecs.begin(),
vecs.end(),
size_less<vector<T> >
);
}
I'm all for over-thinking stuff :)
For the general problem of finding the highest/lowest element in a group, I would use a priority_queue with a comparator:
(copying shamelessly from coppro, and modifying...)
template <typename T> bool size_less (const T* lhs, const T* rhs)
{
return lhs->size() < rhs ->size();
}
vector* highest()
{
priority_queue<vector<T>, size_less<T> > myQueue;
...
...
return myQueue.top();
}
You could use a std::multimap. That allows multiple entries with the same key.
I want to create an adjacency matrix for a graph. Since I read it is not safe to use arrays of the form matrix[x][y] because they don't check for range, I decided to use the vector template class of the stl. All I need to store in the matrix are boolean values. So my question is, if using std::vector<std::vector<bool>* >* produces too much overhead or if there is a more simple way for a matrix and how I can properly initialize it.
EDIT: Thanks a lot for the quick answers. I just realized, that of course I don't need any pointers. The size of the matrix will be initialized right in the beginning and won't change until the end of the program. It is for a school project, so it would be good if I write "nice" code, although technically performance isn't too important. Using the STL is fine. Using something like boost, is probably not appreciated.
Note that also you can use boost.ublas for matrix creation and manipulation and also boost.graph to represent and manipulate graphs in a number of ways, as well as using algorithms on them, etc.
Edit: Anyway, doing a range-check version of a vector for your purposes is not a hard thing:
template <typename T>
class BoundsMatrix
{
std::vector<T> inner_;
unsigned int dimx_, dimy_;
public:
BoundsMatrix (unsigned int dimx, unsigned int dimy)
: dimx_ (dimx), dimy_ (dimy)
{
inner_.resize (dimx_*dimy_);
}
T& operator()(unsigned int x, unsigned int y)
{
if (x >= dimx_ || y>= dimy_)
throw std::out_of_range("matrix indices out of range"); // ouch
return inner_[dimx_*y + x];
}
};
Note that you would also need to add the const version of the operators, and/or iterators, and the strange use of exceptions, but you get the idea.
Best way:
Make your own matrix class, that way you control every last aspect of it, including range checking.
eg. If you like the "[x][y]" notation, do this:
class my_matrix {
std::vector<std::vector<bool> >m;
public:
my_matrix(unsigned int x, unsigned int y) {
m.resize(x, std::vector<bool>(y,false));
}
class matrix_row {
std::vector<bool>& row;
public:
matrix_row(std::vector<bool>& r) : row(r) {
}
bool& operator[](unsigned int y) {
return row.at(y);
}
};
matrix_row& operator[](unsigned int x) {
return matrix_row(m.at(x));
}
};
// Example usage
my_matrix mm(100,100);
mm[10][10] = true;
nb. If you program like this then C++ is just as safe as all those other "safe" languages.
The standard vector does NOT do range checking by default.
i.e. The operator[] does not do a range check.
The method at() is similar to [] but does do a range check.
It will throw an exception on out of range.
std::vector::at()
std::vector::operator[]()
Other notes:
Why a vector<Pointers> ?
You can quite easily have a vector<Object>. Now there is no need to worry about memory management (i.e. leaks).
std::vector<std::vector<bool> > m;
Note: vector<bool> is overloaded and not very efficient (i.e. this structure was optimized for size not speed) (It is something that is now recognized as probably a mistake by the standards committee).
If you know the size of the matrix at compile time you could use std::bitset?
std::vector<std::bitset<5> > m;
or if it is runtime defined use boost::dynamic_bitset
std::vector<boost::dynamic_bitset> m;
All of the above will allow you to do:
m[6][3] = true;
If you want 'C' array performance, but with added safety and STL-like semantics (iterators, begin() & end() etc), use boost::array.
Basically it's a templated wrapper for 'C'-arrays with some NDEBUG-disable-able range checking asserts (and also some std::range_error exception-throwing accessors).
I use stuff like
boost::array<boost::array<float,4>,4> m;
instead of
float m[4][4];
all the time and it works great (with appropriate typedefs to keep the verbosity down, anyway).
UPDATE: Following some discussion in the comments here of the relative performance of boost::array vs boost::multi_array, I'd point out that this code, compiled with g++ -O3 -DNDEBUG on Debian/Lenny amd64 on a Q9450 with 1333MHz DDR3 RAM takes 3.3s for boost::multi_array vs 0.6s for boost::array.
#include <iostream>
#include <time.h>
#include "boost/array.hpp"
#include "boost/multi_array.hpp"
using namespace boost;
enum {N=1024};
typedef multi_array<char,3> M;
typedef array<array<array<char,N>,N>,N> C;
// Forward declare to avoid being optimised away
static void clear(M& m);
static void clear(C& c);
int main(int,char**)
{
const clock_t t0=clock();
{
M m(extents[N][N][N]);
clear(m);
}
const clock_t t1=clock();
{
std::auto_ptr<C> c(new C);
clear(*c);
}
const clock_t t2=clock();
std::cout
<< "multi_array: " << (t1-t0)/static_cast<float>(CLOCKS_PER_SEC) << "s\n"
<< "array : " << (t2-t1)/static_cast<float>(CLOCKS_PER_SEC) << "s\n";
return 0;
}
void clear(M& m)
{
for (M::index i=0;i<N;i++)
for (M::index j=0;j<N;j++)
for (M::index k=0;k<N;k++)
m[i][j][k]=1;
}
void clear(C& c)
{
for (int i=0;i<N;i++)
for (int j=0;j<N;j++)
for (int k=0;k<N;k++)
c[i][j][k]=1;
}
What I would do is create my own class for dealing with matrices (probably as an array[x*y] because I'm more used to C (and I'd have my own bounds checking), but you could use vectors or any other sub-structure in that class).
Get your stuff functional first then worry about how fast it runs. If you design the class properly, you can pull out your array[x*y] implementation and replace it with vectors or bitmasks or whatever you want without changing the rest of the code.
I'm not totally sure, but I thing that's what classes were meant for, the ability to abstract the implementation well out of sight and provide only the interface :-)
In addition to all the answers that have been posted so far, you might do well to check out the C++ FAQ Lite. Questions 13.10 - 13.12 and 16.16 - 16.19 cover several topics related to rolling your own matrix class. You'll see a couple of different ways to store the data and suggestions on how to best write the subscript operators.
Also, if your graph is sufficiently sparse, you may not need a matrix at all. You could use std::multimap to map each vertex to those it connects.
my favourite way to store a graph is vector<set<int>>; n elements in vector (nodes 0..n-1), >=0 elements in each set (edges). Just do not forget adding a reverse copy of every bi-directional edge.
Consider also how big is your graph/matrix, does performance matter a lot? Is the graph static, or can it grow over time, e.g. by adding new edges?
Probably, not relevant as this is an old question, but you can use the Armadillo library, which provides many linear algebra oriented data types and functions.
Below is an example for your specific problem:
// In C++11
Mat<bool> matrix = {
{ true, true},
{ false, false},
};
// In C++98
Mat<bool> matrix;
matrix << true << true << endr
<< false << false << endr;
Mind you std::vector doesn't do range checking either.