Tuesday, May 3, 2011

filling a boost vector or matrix

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;
From stackoverflow
  • Been a while since I used C++. Does the following work?

    for (size_t i = 0; i < N; v[i++] = myScalar) ;
    
    Mr Fooz : That'll work, though it is a full statement as opposed to an expression.
    Mikko Rantanen : True, but it is more compact way which is what you wanted to find based on the post.
    Mr Fooz : Yes, hence the +1.
    j_random_hacker : -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.
    Mikko Rantanen : 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!
  • 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.

    Mr Fooz : 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.
  • 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.

    Daniel Newby : The first example seems to be for std::vector (for which it works), not boost::numeric::ublas::vector (for which it does not work).
  • Have you tried this?

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

0 comments:

Post a Comment

Note: Only a member of this blog may post a comment.