Velocity Reviews > C++ > matrix mult with const in c++

# matrix mult with const in c++

eric
Guest
Posts: n/a

 08-01-2011
Dear c++/g++ programmers:
the run result on my system, ubuntuLinux10.04(kernel2.6.35-25),
gcc4.5.2 is not what book predict
source code
http://examples.oreilly.com/9780596007614/
11-28
11-29
11-24
----------------------------------
#include "matrix.hpp"

#include <iostream>

using namespace std;

int main( ) {
matrix<int> m(2,2);
m = 0;
m[0][0] = 1;
m[1][1] = 1;
m *= 2;
cout << "(" << m[0][0] << "," << m[0][1] << ")" << endl;
cout << "(" << m[1][0] << "," << m[1][1] << ")" << endl;
}
---------------------------------------------------------------
#ifndef MATRIX_HPP
#define MATRIX_HPP

#include <valarray>
#include <numeric>
#include <algorithm>

template<class Value_T>
class matrix
{
public:
// public typedefs
typedef Value_T value_type;
typedef matrix self;
typedef value_type* iterator;
typedef const value_type* const_iterator;
typedef Value_T* row_type;
typedef stride_iter<value_type*> col_type;
typedef const value_type* const_row_type;
typedef stride_iter<const value_type*> const_col_type;

// constructors
matrix( ) : nrows(0), ncols(0), m( ) { }
matrix(int r, int c) : nrows(r), ncols(c), m(r * c) { }
matrix(const self& x) : m(x.m), nrows(x.nrows), ncols(x.ncols) { }

template<typename T>
explicit matrix(const valarray<T>& x)
: m(x.size( ) + 1), nrows(x.size( )), ncols(1)
{
for (int i=0; i<x.size( ); ++i) m[i] = x[i];
}

// allow construction from matricies of other types
template<typename T>
explicit matrix(const matrix<T>& x)
: m(x.size( ) + 1), nrows(x.nrows), ncols(x.ncols)
{
copy(x.begin( ), x.end( ), m.begin( ));
}

// public functions
int rows( ) const { return nrows; }
int cols( ) const { return ncols; }
int size( ) const { return nrows * ncols; }

// element access
row_type row_begin(int n) { return &m[n * cols( )]; }
row_type row_end(int n) { return row_begin( ) + cols( ); }
col_type col_begin(int n) { return col_type(&m[n], cols( )); }
col_type col_end(int n) { return col_begin(n) + cols( ); }
const_row_type row_begin(int n) const { return &m[n * cols( )]; }
const_row_type row_end(int n) const { return row_begin( ) + cols( ); }
const_col_type col_begin(int n) const { return col_type(&m[n],
cols( )); }
const_col_type col_end(int n) const { return col_begin( ) + cols( ); }
iterator begin( ) { return &m[0]; }
iterator end( ) { return begin( ) + size( ); }
const_iterator begin( ) const { return &m[0]; }
const_iterator end( ) const { return begin( ) + size( ); }

// operators
self& operator=(const self& x) {
m = x.m; nrows = x.nrows; ncols = x.ncols; return *this;
}
self& operator=(value_type x) { m = x; return *this; }
row_type operator[](int n) { return row_begin(n); }
const_row_type operator[](int n) const { return row_begin(n); }
self& operator+=(const self& x) { m += x.m; return *this; }
self& operator-=(const self& x) { m -= x.m; return *this; }
self& operator+=(value_type x) { m += x; return *this; }
self& operator-=(value_type x) { m -= x; return *this; }
self& operator*=(value_type x) { m *= x; return *this; }
self& operator/=(value_type x) { m /= x; return *this; }
self& operator%=(value_type x) { m %= x; return *this; }
self operator-( ) { return -m; }
self operator+( ) { return +m; }
self operator!( ) { return !m; }
self operator~( ) { return ~m; }

// friend operators
friend self operator+(const self& x, const self& y) { return self(x)
+= y; }
friend self operator-(const self& x, const self& y) { return self(x) -
= y; }
friend self operator+(const self& x, value_type y) { return self(x) +=
y; }
friend self operator-(const self& x, value_type y) { return self(x) -=
y; }
friend self operator*(const self& x, value_type y) { return self(x) *=
y; }
friend self operator/(const self& x, value_type y) { return self(x) /=
y; }
friend self operator%(const self& x, value_type y) { return self(x) %=
y; }
private:
mutable valarray<Value_T> m;
int nrows;
int ncols;
};

#endif
---------------------------------------------------------------------------------
// example 11-24. stride_iter.hpp
#ifndef STRIDE_ITER_HPP
#define STRIDE_ITER_HPP

#include <iterator>
#include <cassert>

template<class Iter_T>
class stride_iter
{
public:
// public typdefs
typedef typename std::iterator_traits<Iter_T>::value_type value_type;
typedef typename std::iterator_traits<Iter_T>::reference reference;
typedef typename std::iterator_traits<Iter_T>::difference_type
difference_type;
typedef typename std::iterator_traits<Iter_T>inter pointer;
typedef std::random_access_iterator_tag iterator_category;
typedef stride_iter self;

// constructors
stride_iter() : m(NULL), step(0) { };
stride_iter(const self& x) : m(x.m), step(x.step) { }
stride_iter(Iter_T x, difference_type n) : m(x), step(n) { }

// operators
self& operator++() { m += step; return *this; }
self operator++(int) { self tmp = *this; m += step; return tmp; }
self& operator+=(difference_type x) { m += x * step; return *this; }
self& operator--() { m -= step; return *this; }
self operator--(int) { self tmp = *this; m -= step; return tmp; }
self& operator-=(difference_type x) { m -= x * step; return *this; }
reference operator[](difference_type n) { return m[n * step]; }
reference operator*() { return *m; }

// friend operators
friend bool operator==(const self& x, const self& y) {
assert(x.step == y.step);
return x.m == y.m;
}
friend bool operator!=(const self& x, const self& y) {
assert(x.step == y.step);
return x.m != y.m;
}
friend bool operator<(const self& x, const self& y) {
assert(x.step == y.step);
return x.m < y.m;
}
friend difference_type operator-(const self& x, const self& y) {
assert(x.step == y.step);
return (x.m - y.m) / x.step;
}
friend self operator+(const self& x, difference_type y) {
assert(x.step == y.step);
return x += y * x.step;
}
friend self operator+(difference_type x, const self& y) {
assert(x.step == y.step);
return y += x * x.step;
}
private:
Iter_T m;
difference_type step;
};

#endif

----------------------------------------------------------------
my result is
(1, 1)
(1, 1)
but book expect
(2 0)
(0 2)
plz help , Eric
linuxubuntu fsshl is online now Click to check your reputation for
this post Report This Post
------------------------------------------------------------------------------------------------------------------------------------------------------
an incorrect assumption in the example is that the underlying data in
std::valarray is a contiguous block of elements, i.e. an actual array.
This may or may not be true. It's obviously true for the writer's
compiler; however, it promotes poor coding technique. row_begin, etc.
should be using a std::slice created from the int provided.
Alternatively, using std::vector instead of std::valarray should work
with the type of access used because it's guaranteed by the C++
standard to store elements contiguously.

While I'm at it, take a look at this line:
Code:

const_row_type row_begin(int n) const { return &m[n * cols( )]; }

This is completely useless since m[n * cols( )] is an rvalue (i.e. it
doesn't have a location) because m is const in this case. This means
accessing elements from a const matrix should not work; I'd expect a
compiler warning and a segfault. That's not the problem here,
however.*

I find it entertaining that you're still using this book, given this
is the third example from it I've corrected. I'd like to see you
correct the next one on your own.
Kevin Barry

PS I actually don't know if this is the solution to the problem;
however, I wouldn't expect anything to work correctly in code written
like that.

PPS In these lines of main:
Code:

m[0][0] = 1;
m[1][1] = 1;

change = 1 to = 17 or something unique like that. If you get 17s
instead of 1s in your output, my guess is my first point above is the
problem, and that you're assigning to some random address that you're
accessing again when you print the elements.

*I see now that m is mutable, which means const_row_type row_begin(int
n) const should work like row_type row_begin(int n); that is,
"incorrectly". mutable is almost always a cheap hack, and I'm certain
it's used here so row_begin/col_begin don't have to be written
properly.
----------------------------------------------------------------------------------------------------------------------------------------
its result is
(17, 17)
(17, 17)
my g++ compiler at beginning remand me to compile matrix.hpp then get
a lot error, and generate matrix.hpp.gch, then g++ matrix.cpp, it
generate a.out. If I keep matrix.hpp.gch, then I just modify 1 to 17
in matrix.cpp, it can directly generate a.out. But if I remove
matrix.hpp.gch, I need to recompile from matrix.hpp. In the compile
error of matrix.hpp, I see something similar as what you mentioned.
root@eric-laptop:/home/eric/cppcookbook/ch11# g++ matrix.hpp
matrix.hpp:29:25: error: ‘valarray’ does not name a type
matrix.hpp:29:25: error: ISO C++ forbids declaration of ‘parameter’
with no type
matrix.hpp:29:33: error: expected ‘,’ or ‘...’ before ‘<’ token
matrix.hpp:89:13: error: ‘valarray’ does not name a type
matrix.hpp: In constructor ‘matrix<Value_T>::matrix()’:
matrix.hpp:24:34: error: class ‘matrix<Value_T>’ does not have any
field named ‘m’
matrix.hpp: In constructor ‘matrix<Value_T>::matrix(int, int)’:
matrix.hpp:25:46: error: class ‘matrix<Value_T>’ does not have any
field named ‘m’
matrix.hpp: In copy constructor ‘matrix<Value_T>::matrix(const
matrix<Value_T>::self&)’:
matrix.hpp:26:27: error: class ‘matrix<Value_T>’ does not have any
field named ‘m’
-----------------------------------
should I remove const on most of delcaration? Highly appreciate your
time/help to modify these example code but not deviate original
too much to achieve the goal of regular matrix op as book suggest.
Eric-----------
---------------------------------------------------------------------------------------------------------------------------------------------------------------
I tried to remove all const in declaration of my matrix.hpp, but ./
a.out still produce
(17, 17)
(17, 17)
is that possible? and how to fix it?
Eric