LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 07-31-2011, 09:52 PM   #1
fsshl
Member
 
Registered: Jan 2002
Distribution: Ubuntu10.04
Posts: 49

Rep: Reputation: 1
get different result of matrix op on my hw rtw book


Dear Linux/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[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>:ointer 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
 
Old 07-31-2011, 11:59 PM   #2
flamelord
Member
 
Registered: Jun 2011
Distribution: Arch Linux
Posts: 151

Rep: Reputation: 34
It looks like it should work to me
 
Old 08-01-2011, 08:42 AM   #3
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
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.

Last edited by ta0kira; 08-01-2011 at 10:40 AM.
 
Old 08-01-2011, 12:40 PM   #4
fsshl
Member
 
Registered: Jan 2002
Distribution: Ubuntu10.04
Posts: 49

Original Poster
Rep: Reputation: 1
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
 
Old 08-01-2011, 01:00 PM   #5
fsshl
Member
 
Registered: Jan 2002
Distribution: Ubuntu10.04
Posts: 49

Original Poster
Rep: Reputation: 1
I tried to remove all const in declaration of my matrix.hpp, but ./a.out still produce
(17, 17)
(17, 17)
is that possible?
Eric
 
Old 08-01-2011, 01:19 PM   #6
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
One thing that was obvious is that the STL objects in the header files are missing the std:: namespace preface. For example, you need:
Code:
std::valarray<Value_T> m;
Also, I'm not sure why you are attempting to directly compile matrix.hpp; just compile the module containing main(), and that should include matrix.hpp, which in turn includes stride_iter.hpp.

Btw, I tested the code, once corrected for the compiler errors, and it yields the correct results, whether I use [1,0][0,1], or [17,0][0,17]. I'm using an older RHEL system with GCC 3.4.6.

P.S. For [1,0][0,1], I got [2,0][0,2]. For [17,0][0,17], I got [34,0][0,34]

Last edited by dwhitney67; 08-01-2011 at 01:21 PM.
 
Old 08-01-2011, 01:26 PM   #7
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by fsshl View Post
I tried to remove all const in declaration of my matrix.hpp, but ./a.out still produce
(17, 17)
(17, 17)
is that possible?
Eric
Like I said in my last post, I believe the problem is a fundamental, erroneous assumption made in the example. In other words, matrix would have to be rewritten for it to work as it's supposed to. I'm not going to do that. If you want to it would be a good learning exercise. You'd have two alternatives:
  1. Replace std::valarray with std::vector and make a few minor changes. This might be easy; however, I haven't looked that closely at the rest of the code.
  2. Fix row_begin/col_begin so they use std::slice. This would also require you to change their return types and how operator [] works. That might be difficult if you're using this example to learn from.
The 17s in your output are exactly what I was looking for. The m *= 2; (in main) shouldn't ("probably doesn't") fail; I have no doubt it's updating the actual elements of the std::valarray. This means accessing the elements of the matrix actually leads you to "mysterious" memory locations. This is very bad! If I inherited code from someone and this was a part of it, I'd rewrite everything they did from scratch. I'm also slightly offended that this is instructional material.
Kevin Barry

Last edited by ta0kira; 08-01-2011 at 01:46 PM. Reason: added quote for clarity
 
Old 08-01-2011, 01:33 PM   #8
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by dwhitney67 View Post
One thing that was obvious is that the STL objects in the header files are missing the std:: namespace preface. For example, you need:
Code:
std::valarray<Value_T> m;
I hadn't looked for a using namespace std; until you mentioned that; I'd just assumed it was in there somewhere. In fact, it's only in the file with main, but since no templates are instantiated before that there are no namespace errors. This is the obvious reason why matrix.hpp won't compile on its own.
Kevin Barry
 
Old 08-01-2011, 01:45 PM   #9
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by dwhitney67 View Post
Btw, I tested the code, once corrected for the compiler errors, and it yields the correct results, whether I use [1,0][0,1], or [17,0][0,17]. I'm using an older RHEL system with GCC 3.4.6.
Please see my comments regarding the underlying representation of the data. It entirely depends on the STL implementation, whereas the example assumes one of the possible implementations. I'd go so far as to say that even differences in optimization could change the results of this code.

This is the kind of bug that can cost huge amounts of time an money to fix because most people only question it when it fails for them. This is partly a problem with how C++ is specified and partly a problem of people not knowing that in C++ some things are always wrong even if they work in the majority of cases.
Kevin Barry

Last edited by ta0kira; 08-01-2011 at 02:02 PM.
 
Old 08-01-2011, 02:56 PM   #10
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by ta0kira View Post
Please see my comments regarding the underlying representation of the data. It entirely depends on the STL implementation, whereas the example assumes one of the possible implementations. I'd go so far as to say that even differences in optimization could change the results of this code.
I read your comments earlier, but I did not have much time to analyse them with care. Now that I'm away from work, I've had a chance to peruse the STL documentation. It appears that when the operator*=(T val) method is called on the valarray, that all members of the object are operated on.

Within the matrix template, the operator*=(T val) method calls the appropriate method of valarray, thus performing the expected operation.

At home, I've managed to repeat the testing I did at work, with success; at home, I have Ubuntu 10.04 LTS with GCC 4.4.3, and Ubuntu 11.04 with GCC 4.5.2.

Personally, regardless of the underlying implementation of valarray, I'm going with the documentation I've read. And the fact that it works on three different systems, with different versions of the compiler, adds more weight to the notion that the code is working, albeit with a few syntax errors.

Here's the code I tested with...

Main.cpp:
Code:
#include "matrix.hpp"

#include <iostream>

using namespace std;

int main( ) {
matrix<int> m(2,2);
m = 0;
m[0][0] = 17;
m[1][1] = 17;
m *= 2;
cout << "(" << m[0][0] << "," << m[0][1] << ")" << endl;
cout << "(" << m[1][0] << "," << m[1][1] << ")" << endl;
}
matrix.hpp:
Code:
#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>

using namespace std;      // NEVER specify this in a header file; but for the sake of simplicity...

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:
int nrows;
int ncols;
mutable valarray<Value_T> m;   // moved so that it is in the proper order, as expected by the constructor.
};

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

#include <iterator>
#include <cassert>

using namespace std;      // NEVER specify this in a header file; but for the sake of simplicity...

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
To build:
Code:
g++ main.cpp -o varray

./varray
The documentation that I referenced: http://www.cplusplus.com/reference/s...ray/operators/

Last edited by dwhitney67; 08-01-2011 at 04:28 PM.
 
Old 08-02-2011, 01:41 AM   #11
fsshl
Member
 
Registered: Jan 2002
Distribution: Ubuntu10.04
Posts: 49

Original Poster
Rep: Reputation: 1
Thanks all your help
best regard, Eric
 
Old 08-02-2011, 07:07 AM   #12
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by dwhitney67 View Post
Personally, regardless of the underlying implementation of valarray, I'm going with the documentation I've read. And the fact that it works on three different systems, with different versions of the compiler, adds more weight to the notion that the code is working, albeit with a few syntax errors.
So you're fine taking a pointer to internal data and using it as if it were a C array because three STL implementations allow that to work? I'd like to hear your explanation for why it doesn't work for OP. I'd also like to be convinced that I should always expect two consecutive std::valarray elements to be stored sizeof(type) apart. It's certainly possible, and it's often practical, for that not to be the case when implementing an array class. I use an array of pointers in my own list class because it makes inserting and sorting large elements substantially faster, but that would cause severe problems if it was used like this. At the same time, I could add all the functions, typedefs, etc. of std::valarray and it would be standard-compliant. To put my comments into perspective, the example code posted by OP uses a C++ backdoor to access (what the writer hopes is) a private member of std::valarray.

Just to make sure we're talking about the same thing, I've been pointing out the flaws in operator [] and row_begin and I counted on *= working to exploit what I believe is the problem. In other words, if *= writes to the "right" place yet it doesn't change the values assigned to the data structure, that means the values are actually being assigned to someplace besides the data structure; hence 17 instead of 34 in OP's output.

The C++ standard specifically says that the internal representation of a std::vector is a contiguous block of memory that can be used as a C array, whereas it says nothing of the sort for std::valarray. I'm sure it's a lot easier to implement std::valarray to be similar std::vector, but there's absolutely nothing requiring that to be the case.
Kevin Barry
 
Old 08-02-2011, 08:35 AM   #13
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by ta0kira View Post
SI'm sure it's a lot easier to implement std::valarray to be similar std::vector, but there's absolutely nothing requiring that to be the case.
Kevin Barry
If you examine the implementation of valarray, you will note that when it is constructed (with a size_t param), that a contiguous block of memory is allocated from the heap using operator new. Refer to /usr/include/c++/<GCC version>/bits/valarray_array.h, specifically at the __valarray_get_memory() method.

I can understand your argument in the sense that one should not take advantage, or make assumptions, of how the underlying data of a valarray is implemented. However the operator[] of valarray, given a valid subscript, does return a reference to the appropriate location within the "array". Regardless of how valarray may be implemented in some future standard, I'm sure that operation would remain the same, so as to honor the public interface that has been in place for many years.
 
Old 08-02-2011, 03:40 PM   #14
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by dwhitney67 View Post
If you examine the implementation of valarray, you will note that when it is constructed (with a size_t param), that a contiguous block of memory is allocated from the heap using operator new. Refer to /usr/include/c++/<GCC version>/bits/valarray_array.h, specifically at the __valarray_get_memory() method.
The point of all of this is there is no the. There is no valarray_array.h released by the C++ standards committee, nor by ISO, nor by ANSI. There's only the standard. This is vastly different from languages like Java and PHP where what works for one person works for all people. The top of that header has the GPL; do you think MSVC and BCB headers have the GPL on them? SGI also has a version of the STL. Look here: <valarray>. It's all in the main header, and there's no __valarray_get_memory to be found. I haven't looked at how storage is implemented, but hopefully you're starting to realize that the standard orates requirements for the STL and all ambiguities are left to the implementer to decide. The fact that one implementation puts it all in the public header and another doesn't should be enough to convince you of that.

A more salient example of standard-vs-implementation is struct flock in glibc vs. FreeBSD libc; the members aren't declared in the same order between the two, so code with {} initialization won't port unless member names are specified. I found that out the hard way when porting a program from Linux to FreeBSD. There's less reason for deviation in internal storage for std::valarray, but deviation is still perfectly legitimate.

The point seemingly missed is that it's entirely possible for an STL implementer to write std::valarray in a standard-compliant way that breaks this code. It doesn't matter who it works for or when because there's a fundamental flaw in the code that wouldn't fly in any serious C++ community. If OP posted this to comp.lang.c++.moderated at least half the responses would be along the lines of mine, but less polite. Since it does fail for OP, if this was submitted as a bug to gcc they'd say the same thing I'm saying; the C++ standard doesn't mandate that hacks like that work -> bug unsubstantiated.

Lastly, it isn't about getting huffy and thumping the standard for the sake of the standard. Proof by "it works in N cases" can easily end a business, and C++ is one of those things that frequently provides the opportunity.
Kevin Barry
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] Parallel matrix - matrix multiplication seg-faults ejspeiro Programming 9 04-18-2011 09:41 PM
LXer: Book Review: The Official Ubuntu Server Book LXer Syndicated Linux News 0 08-31-2009 03:00 AM
is there a matrix screensaver, very exactly like in the Matrix movie? frenchn00b Linux - Desktop 2 08-20-2009 10:00 AM
awk convert column matrix to square matrix? johnpaulodonnell Programming 4 04-30-2008 01:45 PM
LXer: Atlas gets its RTW LXer Syndicated Linux News 0 01-24-2007 06:21 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 08:55 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration