matrix mult with const in c++

Discussion in 'C++' started by eric, Aug 1, 2011.

  1. eric

    eric Guest

    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 "stride_iter.hpp" // see <link linkend="cplusplusckbk-CHP-11-
    SECT-12">Recipe 11.12</link>

    #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 = x;
    }

    // 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>:eek: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
    eric, Aug 1, 2011
    #1
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. David W

    Gridview and mult-select boxes

    David W, Dec 29, 2006, in forum: ASP .Net
    Replies:
    2
    Views:
    512
    gpicazo
    Oct 19, 2007
  2. Replies:
    44
    Views:
    1,956
    Chris Torek
    Sep 24, 2006
  3. Adrian Hawryluk

    Mult-thread macro

    Adrian Hawryluk, Mar 22, 2007, in forum: C++
    Replies:
    2
    Views:
    335
    Adrian Hawryluk
    Mar 22, 2007
  4. Javier
    Replies:
    2
    Views:
    548
    James Kanze
    Sep 4, 2007
  5. GaryDean

    Membership Provider for Mult apps

    GaryDean, Oct 11, 2007, in forum: ASP .Net
    Replies:
    3
    Views:
    363
    Steven Cheng[MSFT]
    Oct 15, 2007
Loading...

Share This Page