2

I'm trying to change the constructor behaviour of a BOOST uBLAS vector and was wondering what the best way to do this is. I want to initialise the components (co-ordinates) of a 2D vector using the constructor, for example:

Instead of:

typedef boost::ublas::vector BoostVector;

double x=1;
double y=0.7;

BoostVector<double> v(2);
v(1) = x; v(2) = y; //x and y are vector components/co-ordinates

I want to be able to specify x and y in the constructor.

BoostVector<double> v(x,y);

I'm thinking I could create a new class that provides an interface for doing this, either by containing or inheriting from the boost vector class, but I'm fairly new to C++ and I'm not sure of the best way to retain the functionality of the boost vector. Especially as I don't want to interfere with the template expression optimisation used by the uBLAS vector class. Any advice on this would be very appreciated. Thanks, Kieran

kieranhood
  • 21
  • 1
  • 3

3 Answers3

0

If you are dealing much with 2D vectors and want to use uBLAS then it might be reasonable to introduce some convenience functions. BTW, when you are working with fixed size vectors it's more efficient to use the bounded_array storage (on stack)

I thought of the following solutions (none is ideal, it would be nice to have uBlas compatible with std::initialization_list):

// Assignment:
#include <boost/numeric/ublas/assignment.hpp>
ublas::bounded_vector<double,2> v1;
v1 <<= 1.1, 2.1; // syntactic sugar over plain assignment

// Use a helper
template<typename T>
ublas::vector<T> makeVector2(T x1, T x2) 
{
    ublas::bounded_vector<T,2> res; // I
    res <<= x1, x2; // or plain res(0)=x1; res(1)=x2;
    return res;
}
ublas::vector<double> v1 = makeVector2<double>(1,2.2);

// Use an `evil' conversion-helper (or it's templatized variant)
class Foo {
public:
    Foo(double x1, double x2) : m_x1(x1), m_x2(x2) {}
    operator ublas::vector<double>() { return makeVector2(m_x1, m_x2); };
private:
    double m_x1, m_x2;
};
ublas::vector<double> v3(Foo(1.3,2.3));

Finally have a look at Example 3.

Anonymous
  • 18,162
  • 2
  • 41
  • 64
0

2D as in multi-dimensional array or two coordinates? If multi-dimensional, use a vector of vectors:

vector<vector<type>> v;

In this case I'm not sure what you mean by x and y though. And use the [] operator rather than the () operator: v[1] = x, etc

If two coordinates (x axis, y axis), I would do something like this:

template <class T>
class Vector2
{
public:
    Vector2(const T& x, const T& y) : mX(x), mY(y) {}

private:
    T x;
    T y;
};

The reason I would tend to create your own Vector2 class rather than use the existing std::vector is because you're getting rid of a ton of overhead that you wouldn't use if all you're storing is two values. This includes dynamic memory allocation, storing the length of the array, etc. You don't need all that stuff if all you're doing is storing two values.

Andrew Rasmussen
  • 14,912
  • 10
  • 45
  • 81
  • Thanks for the reply. I meant 2D as in with two co-ordinates. I've already created a Vector2 class similar to yours, with a load of methods for mathematical operations (dot products etc). But have found it to be really inefficient when stringing a lot of these operations together, due to the creation of temporaries by the looks of it. This is why I'm trying to switch to using the BOOST uBLAS vector. The problem I'm having is that there is no constructor built into the uBLAS vector like the one in your suggestion; `Vector2(const T& x, const T& y) : mX(x), mY(y) {}` – kieranhood Dec 06 '11 at 14:50
0

There are many many ways to skin a cat:

  1. Are you looking for C++0x uniform initializers:

    std::vector<type> v { x, y };
    
  2. Or just plain old C++03:

    type arr[] = { x,y };
    std::vector<type> v(arr, arr+2);
    
  3. If you want a class with struct-like behaviour use a tuple:

    std::tuple<type, type> point(x,y);
    

    Tuples are in TR1, C++0x and in Boost. They have all kinds of nifty features (like automatic interoperability with std::pair, std::less etc.)


In the absense of all of the above, the following would be idiomatic:

typedef std::pair<type, type> point_t;

point_t p(x,y);
sehe
  • 374,641
  • 47
  • 450
  • 633