-
August 13th, 2011, 08:00 AM
#1
How to declare 4d vectors?
Can someone please show me how you declare a 4 dimensional vector?
-
August 13th, 2011, 10:16 AM
#2
Re: How to declare 4d vectors?
You can do the following:
Code:
typedef std::vector<int> vector_1d;
typedef std::vector<vector_1d> vector_2d;
typedef std::vector<vector_2d> vector_3d;
typedef std::vector<vector_3d> vector_4d;
However, if you know the size that you want the 4D vector to be, then from a performance point of view you would be better writing a small class that provides 4D modifiers and observers into a single allocation of data. e.g.:
Code:
#include <vector>
template <typename T>
class vector_4d
{
public:
typedef typename std::vector<T>::size_type size_type;
typedef typename std::vector<T>::iterator iterator;
typedef typename std::vector<T>::const_iterator const_iterator;
vector_4d(size_type x, size_type y, size_type z, size_type w)
:x_(x)
,y_(y)
,z_(z)
,w_(w)
,data_(x_*y_*z_*w_)
{}
const T& operator()(size_type x_pos, size_type y_pos, size_type z_pos, size_type w_pos) const
{
size_type pos_in_4d_plane = x_ * y_ * z_ * w_pos;
size_type pos_in_3d_plane = x_ * y_ * z_pos;
size_type pos_in_2d_plane = x_ * y_pos;
size_type pos_in_1d_plane = x_pos;
return data_[pos_in_4d_plane + pos_in_3d_plane + pos_in_2d_plane + pos_in_1d_plane];
}
T& operator()(size_type x_pos, size_type y_pos, size_type z_pos, size_type w_pos)
{
size_type pos_in_4d_plane = x_ * y_ * z_ * w_pos;
size_type pos_in_3d_plane = x_ * y_ * z_pos;
size_type pos_in_2d_plane = x_ * y_pos;
size_type pos_in_1d_plane = x_pos;
return data_[pos_in_4d_plane + pos_in_3d_plane + pos_in_2d_plane + pos_in_1d_plane];
}
iterator begin() { return data_.begin(); }
iterator end() { return data_.end(); }
const_iterator begin() const { return data_.begin(); }
const_iterator end() const { return data_.end(); }
private:
size_type x_;
size_type y_;
size_type z_;
size_type w_;
std::vector<T> data_;
};
Hopefully you should find the above maths for the mapping between 4D and 1D straight forward. Example use of the the above class is as follows:
Code:
int main()
{
vector_4d<int> vec4d(2,3,4,5);
//The following line will fill out the 4d vector so that the vector element value
//matches the element position in the memory allocation.
std::transform(vec4d.begin(), vec4d.end(), vec4d.begin(), incrementor<int>(0));
//To illustrate the above point, here is a print out of the vector contents
std::copy(vec4d.begin(), vec4d.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << "\n\n";
//access the last position in the vector_4d;
std::cout << vec4d(1,2,3,4) << std::endl;
//access the equivalent position at the bottom of the 4th plane
std::cout << vec4d(1,2,3,0) << std::endl;
//access the equivalent position at the bottom of the 3rd plane
std::cout << vec4d(1,2,0,0) << std::endl;
//access the equivalent position at the bottom of the 2nd plane
std::cout << vec4d(1,0,0,0) << std::endl;
std::cout << "\nJob done: press return to quit" << std::endl;
std::cin.get();
}
The incrementor is a function object that I defined as follows:
Code:
template <typename T>
struct incrementor : std::unary_function<T, T>
{
incrementor(const T& initial_value=T())
:value_(initial_value)
{}
T operator()(T)
{
return value_++;
}
private:
T value_;
};
The above classes and main, presented as a compilable peice of code looks like this:
Code:
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
template <typename T>
class vector_4d
{
public:
typedef typename std::vector<T>::size_type size_type;
typedef typename std::vector<T>::iterator iterator;
typedef typename std::vector<T>::const_iterator const_iterator;
vector_4d(size_type x, size_type y, size_type z, size_type w)
:x_(x)
,y_(y)
,z_(z)
,w_(w)
,data_(x_*y_*z_*w_)
{}
const T& operator()(size_type x_pos, size_type y_pos, size_type z_pos, size_type w_pos) const
{
size_type pos_in_4d_plane = x_ * y_ * z_ * w_pos;
size_type pos_in_3d_plane = x_ * y_ * z_pos;
size_type pos_in_2d_plane = x_ * y_pos;
size_type pos_in_1d_plane = x_pos;
return data_[pos_in_4d_plane + pos_in_3d_plane + pos_in_2d_plane + pos_in_1d_plane];
}
T& operator()(size_type x_pos, size_type y_pos, size_type z_pos, size_type w_pos)
{
size_type pos_in_4d_plane = x_ * y_ * z_ * w_pos;
size_type pos_in_3d_plane = x_ * y_ * z_pos;
size_type pos_in_2d_plane = x_ * y_pos;
size_type pos_in_1d_plane = x_pos;
return data_[pos_in_4d_plane + pos_in_3d_plane + pos_in_2d_plane + pos_in_1d_plane];
}
iterator begin() { return data_.begin(); }
iterator end() { return data_.end(); }
const_iterator begin() const { return data_.begin(); }
const_iterator end() const { return data_.end(); }
private:
size_type x_;
size_type y_;
size_type z_;
size_type w_;
std::vector<T> data_;
};
template <typename T>
struct incrementor : std::unary_function<T, T>
{
incrementor(const T& initial_value=T())
:value_(initial_value)
{}
T operator()(T)
{
return value_++;
}
private:
T value_;
};
int main()
{
vector_4d<int> vec4d(2,3,4,5);
//The following line will fill out the 4d vector so that the vector element value
//matches the element position in the memory allocation.
std::transform(vec4d.begin(), vec4d.end(), vec4d.begin(), incrementor<int>(0));
//To illustrate the above point, here is a print out of the vector contents
std::copy(vec4d.begin(), vec4d.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << "\n\n";
//access the last position in the vector_4d;
std::cout << vec4d(1,2,3,4) << std::endl;
//access the equivalent position at the bottom of the 4th plane
std::cout << vec4d(1,2,3,0) << std::endl;
//access the equivalent position at the bottom of the 3rd plane
std::cout << vec4d(1,2,0,0) << std::endl;
//access the equivalent position at the bottom of the 2nd plane
std::cout << vec4d(1,0,0,0) << std::endl;
std::cout << "\nJob done: press return to quit" << std::endl;
std::cin.get();
}
I hope that helps. Any questions about the code posted, please ask. If I'm not around to answer your questions, I'm sure others will help.
-
August 13th, 2011, 11:53 AM
#3
Re: How to declare 4d vectors?
Originally Posted by Bottledbread
Can someone please show me how you declare a 4 dimensional vector?
You can use MultiArray from Boost,
http://www.boost.org/doc/libs/1_47_0.../doc/user.html
Boost is high quality and has the status of an "almost" standard library for C++. And you usually don't have to compile anything just include the relevant header files.
Last edited by nuzzle; August 13th, 2011 at 04:07 PM.
-
August 17th, 2011, 02:41 AM
#4
Re: How to declare 4d vectors?
Originally Posted by PredicateNormative
The incrementor is a function object that I defined as follows:
...
Code:
//The following line will fill out the 4d vector so that the vector element value
//matches the element position in the memory allocation.
std::transform(vec4d.begin(), vec4d.end(), vec4d.begin(), incrementor<int>(0));
Hum... Shouldn't incrementor's operator take no argument, and be used with std::fill instead?
that incrementor looks an awful lot like boost's counting_iterator.
C++0x provides iota.
Is your question related to IO?
Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.
-
August 18th, 2011, 06:15 PM
#5
Re: How to declare 4d vectors?
Originally Posted by monarch_dodra
Hum... Shouldn't incrementor's operator take no argument, and be used with std::fill instead?
Yeah that would be a better solution, although I assume you meant std::generate rather than std::fill?
Originally Posted by monarch_dodra
Except... the boost one is more versatile/polished.
-
August 19th, 2011, 02:36 AM
#6
Re: How to declare 4d vectors?
Originally Posted by PredicateNormative
... the boost one is more versatile/polished.
I agree, but beware of counting_iterator, because I learned the hard way that the boost documentation is not fully correct;
basically, the problem is that counting_iterator is not a forward iterator, even when using an Incrementable that in theory enables random access semantics, the reason being that the iterator stores its referee.
As a consequence, for example, the code "const iter::value_type& f( iter it ) { return *it; }" that should give a valid reference whenever *it does, gives UB instead. This is exactly what happens in, say, reverse_iterator<> implementation that hence gives UB when used with counting_iterator even when it "is" random access.
-
August 19th, 2011, 06:59 AM
#7
Re: How to declare 4d vectors?
Originally Posted by superbonzo
I agree, but beware of counting_iterator, because I learned the hard way that the boost documentation is not fully correct;
basically, the problem is that counting_iterator is not a forward iterator, even when using an Incrementable that in theory enables random access semantics, the reason being that the iterator stores its referee.
As a consequence, for example, the code "const iter::value_type& f( iter it ) { return *it; }" that should give a valid reference whenever *it does, gives UB instead. This is exactly what happens in, say, reverse_iterator<> implementation that hence gives UB when used with counting_iterator even when it "is" random access.
That sounds worthy of a bug report!
I must admit, I have never used the counting_iterator before... and am probably unlikely to use it.
-
August 19th, 2011, 08:19 AM
#8
Re: How to declare 4d vectors?
Originally Posted by PredicateNormative
That sounds worthy of a bug report!
that's what I thought when I came across a crash in my program, caused by a reverse_iterator<counting_iterator<...>> ... and the "nice" thing is that if you use it with a small type, say, a signed integer, it will probably pass unnoticed with no crash ...
anyway, just before reporting this I found it was a known issue, that probably has no definitive solution because I can see no effective way of implementing such an iterator without storing the incrementable in the iterator instance.
that said, it would be nice if this behavior were at least properly documented ...
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|