views:

1627

answers:

4

Is there a single-expression way to assign a scalar to all elements of of a boost matrix or vector? I'm trying to find a more compact way of representing:

boost::numeric::ublas::c_vector<float, N> v;
for (size_t i=0; i<N; i++) {
    v[i] = myScalar;
 }

The following do not work:

boost::numeric::ublas::c_vector<float, N> 
   v(myScalar, myScalar, ...and so on..., myScalar);

boost::numeric::ublas::c_vector<float, N> v;
v = myScalar;
A: 

Been a while since I used C++. Does the following work?

for (size_t i = 0; i < N; v[i++] = myScalar) ;
Mikko Rantanen
That'll work, though it is a full statement as opposed to an expression.
Mr Fooz
True, but it is more compact way which is what you wanted to find based on the post.
Mikko Rantanen
Yes, hence the +1.
Mr Fooz
-1 sorry. You must use "v[i++]" -- "v[++i]" will skip initialisation of v[0] and overwrite the memory past the end of the vector.
j_random_hacker
Ack. Sorry! I did acknowledge that I had to use the correct unary operator but for some reason I kept thinking ++i is the one that increments i after evaluating. Mostly since everyone prefer i++ and the "i += 1" behaviour seems more logical. Fixed now in any case.. And I guess I should thank you as well, I like 600 rep more than 601!
Mikko Rantanen
+6  A: 

Because the vector models a standard random access container you should be able to use the standard STL algorithms. Something like:

c_vector<float,N> vec;
std::fill_n(vec.begin(),N,0.0f);

or

std::fill(vec.begin(),vec.end(),0.0f);

It probably also is compatible with Boost.Assign but you'd have to check.

The STL algorithms do seem to work. Thanks. Boost.Assign doesn't seem to work for me, but I think it's because I'm using a c_vector (const-sized vector) instead of a vector (dynamically sized vector), so push_back doesn't work.
Mr Fooz
+3  A: 

I have started using boost::assign for cases that I want to statically assign specific values (examples lifted from link above).

#include <boost/assign/std/vector.hpp>
using namespace boost::assign; // bring 'operator+()' into scope

{
  vector<int> values;
  values += 1,2,3,4,5,6,7,8,9;
}

You can also use boost::assign for maps.

#include <boost/assign/list_inserter.hpp>
#include <string>
using boost::assign;

std::map<std::string, int> months;
insert( months )
        ( "january",   31 )( "february", 28 )
        ( "march",     31 )( "april",    30 )
        ( "may",       31 )( "june",     30 )
        ( "july",      31 )( "august",   31 )
        ( "september", 30 )( "october",  31 )
        ( "november",  30 )( "december", 31 );

You can allow do direct assignment with list_of() and map_list_of()

#include <boost/assign/list_of.hpp> // for 'list_of()'
#include <list>
#include <stack>
#include <string>
#include <map>
using namespace std;
using namespace boost::assign; // bring 'list_of()' into scope

{
    const list<int> primes = list_of(2)(3)(5)(7)(11);
    const stack<string> names = list_of( "Mr. Foo" )( "Mr. Bar")
                                       ( "Mrs. FooBar" ).to_adapter();

    map<int,int> next = map_list_of(1,2)(2,3)(3,4)(4,5)(5,6);

    // or we can use 'list_of()' by specifying what type
    // the list consists of
    next = list_of< pair<int,int> >(6,7)(7,8)(8,9);

}

There are also functions for repeat(), repeat_fun(), and range() which allows you to add repeating values or ranges of values.

chrish
The first example seems to be for std::vector (for which it works), not boost::numeric::ublas::vector (for which it does not work).
Daniel Newby
A: 

Have you tried this?

ublas::c_vector v = ublas::scalar_vector(N, myScalar);

dario