CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Aug 2011
    Posts
    5

    How to declare 4d vectors?

    Can someone please show me how you declare a 4 dimensional vector?

  2. #2
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    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.

  3. #3
    Join Date
    May 2009
    Posts
    2,413

    Re: How to declare 4d vectors?

    Quote Originally Posted by Bottledbread View Post
    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.

  4. #4
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: How to declare 4d vectors?

    Quote Originally Posted by PredicateNormative View Post
    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.

  5. #5
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: How to declare 4d vectors?

    Quote Originally Posted by monarch_dodra View Post
    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?
    Quote Originally Posted by monarch_dodra View Post
    that incrementor looks an awful lot like boost's counting_iterator.

    C++0x provides iota.
    Except... the boost one is more versatile/polished.

  6. #6
    Join Date
    Oct 2008
    Posts
    1,456

    Re: How to declare 4d vectors?

    Quote Originally Posted by PredicateNormative View Post
    ... 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.

  7. #7
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: How to declare 4d vectors?

    Quote Originally Posted by superbonzo View Post
    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.

  8. #8
    Join Date
    Oct 2008
    Posts
    1,456

    Re: How to declare 4d vectors?

    Quote Originally Posted by PredicateNormative View Post
    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
  •  





Click Here to Expand Forum to Full Width

Featured