Boost logo

Boost Users :

From: Andy Little (andy_at_[hidden])
Date: 2006-09-08 12:50:21


"David Abrahams" <dave_at_[hidden]> wrote
> "Andy Little" <andy_at_[hidden]> writes:
>
>> Hi,
>>
>> I am trying to transform from a fusion vector of values to a fusion
>> vector
>> of non-const references to those values, the ultimate aim being to assign the
>> original sequence from another sequence.
>>
>> The code below works ok with make_vector, but I want to be able to automate
>> it
>> for any fusion sequence. How can I do that?
>
> You can find an example of exactly that on the zip_iterator_fusion
> branch of boost/iterator/zip_iterator.hpp

Yikes. I don't really understand what I am meant to do with that. I will have to
study it in more detail.
I reckon that a get_ref_vector(fusion::vector) would be quite useful. I guess
there isnt much difference to a view though?.
Anyway I have continued hacking away and so here is my latest efforts, using
fusion to do a dot product of two vectors.
Maybe it would be a useful example in the fusion docs?. Anyway here it is FWIW:

regards
Andy Little

--------------------------
// Copyright Andrew Little 2006
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See QUAN_ROOT/quan_matters/index.html for documentation.

/*
    dot product of two vectors using fusion.
    The input vectors are just raw fusion sequences
*/

#include <quan/out/length.hpp>
#include <quan/out/reciprocal_length.hpp>
#include <quan/operators/binary_operator_functors.hpp>
#include <boost/fusion/sequence/container/vector.hpp>
#include <boost/fusion/sequence/conversion/as_vector.hpp>
#include <boost/fusion/sequence/intrinsic/at.hpp>
#include <boost/fusion/sequence/intrinsic/value_at.hpp>
#include <boost/fusion/algorithm/transformation/transform.hpp>
#include <boost/fusion/algorithm/iteration/fold.hpp>
#include <boost/ref.hpp>
#include <cassert>

// Couldnt resist this... :-)
namespace quan{ namespace fusion{

// This functor needed as fusion::fold sends
// its args the opposite way to quan::operator_XX_equals
// Lhs in invoked function is assumed to be
// a non const boost::reference_wrapper
template <typename F>
struct reverse_assign_f_args{

    template <typename Rhs, typename Lhs>
    struct result{
        BOOST_MPL_ASSERT((boost::is_reference_wrapper<Lhs>));
        BOOST_MPL_ASSERT((boost::mpl::not_<
            boost::is_const<typename Lhs::type>
>));
        typedef Lhs type;
    };
    template <typename Rhs, typename Lhs>
    typename result<Rhs,Lhs>::type
    operator()( Rhs const & rhs, Lhs lhs)const
    {
        F f;
        return boost::ref(f(lhs.get(),rhs));
    }
};

// more arg reversing
template <typename F>
struct reverse_f_args{

    template <typename Rhs, typename Lhs>
    struct result{
        typedef typename F:: template result<
            Rhs,Lhs
>::type type;
    };
    template <typename Rhs, typename Lhs>
    typename result<Rhs,Lhs>::type
    operator()( Rhs const & rhs, Lhs const & lhs )const
    {
        F f;
        f(lhs,rhs);
    }
};
}}//quan::fusion

int main()
{
  // The types of the input 'vectors'
    typedef boost::fusion::vector4<
        quan::length::mm,int,int,int
> seq1_type;

    typedef boost::fusion::vector4<
       quan::reciprocal_length::per_m,int,int,int
> seq2_type;

    // Use fusion to work out the type of the result of
    // the dot product...

    // First the result sequence of
    // multiplying the input sequences.
    typedef boost::fusion::result_of::as_vector<
        boost::fusion::result_of::transform<
            seq1_type,seq2_type,quan::operator_times
>::type
>::type multiplied_seq;

    // Now the add and accumulate result type deduction part.
    // Note that need to switch the args for use with my own functors,
    // (I have been here with boost::is_convertible, so I'll say no more;-)).
    // I am using + as the 2nd function applied, not +=, as used at runtime
    // as I am also trying to 'accumulate' the result_type at this stage.
    typedef boost::fusion::result_of::fold<
        multiplied_seq,
        boost::fusion::result_of::at_c<multiplied_seq,0>::type ,
        quan::fusion::reverse_f_args<quan::operator_plus>
>::type result_type;

    // There was a bit of fun and games to get here so ...
    BOOST_STATIC_ASSERT(( boost::is_same<result_type,double>::value !=0));

    // set up the input 'vectors'
    seq1_type seq1(quan::length::mm(1000),2,3,4);
    seq2_type seq2(quan::reciprocal_length::per_m(1),2,3,4);

    // do the dot_product
    result_type result = boost::fusion::fold(
        boost::fusion::transform(seq1,seq2,quan::operator_times()),
        boost::ref(result),
        quan::fusion::reverse_assign_f_args<quan::operator_plus_equals>()
    );
    assert(quan::compare(result,30,1e-12) ==0);
    std::cout << result <<'\n';

}
-----------------------------


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net