elementwise product or sum of two vectors

Discussion in 'C++' started by er, Sep 4, 2007.

  1. er

    er Guest

    hi,

    i'm trying to implement x*=y or x+=y; where x and y are containers and
    *= and += are element wise i.e. x*=y is meant as
    x[1]*=y[1],...,x[n]*=y[n] and likewise for +=;
    i'm wondering if
    a) there exists a function already defined for this purpose for the
    types that i intend it for (see below)
    b) is there a way to make * or + a parameter so that i don't have to
    write two (nearly identical) pieces of code for each (see below).
    c) more generally, is there a better way to do this?

    // possible types for B and D:
    // type boost::numeric::ublas::vector<double>
    //
    boost::numeric::ublas::vector_range<boost::numeric::ublas::vector<double>
    >


    //code starts here:
    template<typename D> class Op_product_term_by_term{
    public:
    Op_product_term_by_term(D& dest):iter(dest.begin()),end(dest.end())
    {};
    void operator()(double elem);
    private:
    typename D::iterator iter;
    typename D::iterator end;
    };
    template<typename D> void Op_product_term_by_term<D>::eek:perator()
    (double elem){
    if(iter<end){
    *(iter++)*=elem;
    }else{
    throw std::runtime_error("Aux::Op_product_term_by_term");
    };
    };
    template<typename D> class Op_sum_term_by_term{
    public:
    Op_sum_term_by_term(D& dest):iter(dest.begin()),end(dest.end()){};
    void operator()(double elem);
    private:
    typename D::iterator iter;
    typename D::iterator end;
    };
    template<typename D> void Op_sum_term_by_term<D>::eek:perator()(double
    elem){
    if(iter<end){
    *(iter++)+=elem;
    }else{
    throw std::runtime_error("Aux::Op_sum_term_by_term");
    };
    };
    }
    template<typename D, typename B> void product_term_by_term(D&
    dest,const B& by){
    if(dest.size()==by.size()){
    for_each(by.begin(),by.end(),Op_product_term_by_term<D>(dest));
    }else{
    throw std::runtime_error("Aux::product_term_by_term");
    };
    };
    template<typename D, typename B> void sum_term_by_term(D& dest,const
    B& by){
    if(dest.size()==by.size()){
    for_each(by.begin(),by.end(),Op_sum_term_by_term<D>(dest));
    }else{
    throw std::runtime_error("Aux::sum_term_by_term");
    };
    };
     
    er, Sep 4, 2007
    #1
    1. Advertising

  2. er wrote:
    > i'm trying to implement x*=y or x+=y; where x and y are containers and
    > *= and += are element wise i.e. x*=y is meant as
    > x[1]*=y[1],...,x[n]*=y[n] and likewise for +=;
    > i'm wondering if
    > a) there exists a function already defined for this purpose for the
    > types that i intend it for (see below)


    You mean, like 'std::for_each'?

    > b) is there a way to make * or + a parameter so that i don't have to
    > write two (nearly identical) pieces of code for each (see below).


    Probably. See 'std::plus' and 'std::multiplies'...

    > c) more generally, is there a better way to do this?


    You mean, like using 'valarray', for example?

    > [..]


    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Sep 4, 2007
    #2
    1. Advertising

  3. er

    er Guest

    On Sep 4, 2:50 pm, "Victor Bazarov" <> wrote:
    > er wrote:
    > > i'm trying to implement x*=y or x+=y; where x and y are containers and
    > > *= and += are element wise i.e. x*=y is meant as
    > > x[1]*=y[1],...,x[n]*=y[n] and likewise for +=;
    > > i'm wondering if
    > > a) there exists a function already defined for this purpose for the
    > > types that i intend it for (see below)

    >
    > You mean, like 'std::for_each'?
    >
    > > b) is there a way to make * or + a parameter so that i don't have to
    > > write two (nearly identical) pieces of code for each (see below).

    >
    > Probably. See 'std::plus' and 'std::multiplies'...
    >
    > > c) more generally, is there a better way to do this?

    >
    > You mean, like using 'valarray', for example?
    >
    > > [..]

    >
    > V
    > --
    > Please remove capital 'A's when replying by e-mail
    > I do not respond to top-posted replies, please don't ask


    like this?
    std::transform(vec.begin(), vec.end(), dest.begin(),
    dest.end(),std::plus<double>());
     
    er, Sep 4, 2007
    #3
  4. er wrote:
    > On Sep 4, 2:50 pm, "Victor Bazarov" <> wrote:
    >> er wrote:
    >>> i'm trying to implement x*=y or x+=y; where x and y are containers
    >>> and *= and += are element wise i.e. x*=y is meant as
    >>> x[1]*=y[1],...,x[n]*=y[n] and likewise for +=;
    >>> i'm wondering if
    >>> a) there exists a function already defined for this purpose for the
    >>> types that i intend it for (see below)

    >>
    >> You mean, like 'std::for_each'?
    >>
    >>> b) is there a way to make * or + a parameter so that i don't have to
    >>> write two (nearly identical) pieces of code for each (see below).

    >>
    >> Probably. See 'std::plus' and 'std::multiplies'...
    >>
    >>> c) more generally, is there a better way to do this?

    >>
    >> You mean, like using 'valarray', for example?
    >>
    >>> [..]

    >>
    >> V
    >> --
    >> Please remove capital 'A's when replying by e-mail
    >> I do not respond to top-posted replies, please don't ask

    >
    > like this?
    > std::transform(vec.begin(), vec.end(), dest.begin(),
    > dest.end(),std::plus<double>());


    Yes, probably. Does it work?

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Sep 4, 2007
    #4
  5. er

    er Guest


    > like this?
    > std::transform(vec.begin(), vec.end(), dest.begin(),
    > dest.end(),std::plus<double>());


    i mean

    std::transform(vec.begin(), vec.end(),
    dest.begin(),dest.begin(),std::plus<double>())

    definitely cleaner. thanks.
     
    er, Sep 4, 2007
    #5
  6. er

    er Guest

    On Sep 4, 3:37 pm, er <> wrote:
    > > like this?
    > > std::transform(vec.begin(), vec.end(), dest.begin(),
    > > dest.end(),std::plus<double>());

    >
    > i mean
    >
    > std::transform(vec.begin(), vec.end(),
    > dest.begin(),dest.begin(),std::plus<double>())
    >
    > definitely cleaner. thanks.


    another thought:

    it definitely achieves x+=y but i'm wondering if it's quite in the
    spirit of x+=y, and not instead x=x+y. i believe the 2nd
    creates a temp object to store x?
     
    er, Sep 4, 2007
    #6
  7. er wrote:
    > On Sep 4, 3:37 pm, er <> wrote:
    >>> like this?
    >>> std::transform(vec.begin(), vec.end(), dest.begin(),
    >>> dest.end(),std::plus<double>());

    >>
    >> i mean
    >>
    >> std::transform(vec.begin(), vec.end(),
    >> dest.begin(),dest.begin(),std::plus<double>())
    >>
    >> definitely cleaner. thanks.

    >
    > another thought:
    >
    > it definitely achieves x+=y but i'm wondering if it's quite in the
    > spirit of x+=y, and not instead x=x+y. i believe the 2nd
    > creates a temp object to store x?


    I think you need to trust your compiler to be able to opimize the
    expression

    A = A + B

    as if it were written

    A += B

    Basically, when in doubt, profile.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Sep 4, 2007
    #7
  8. er

    terminator Guest

    On Sep 4, 10:49 pm, er <> wrote:
    > On Sep 4, 3:37 pm, er <> wrote:
    >
    > > > like this?
    > > > std::transform(vec.begin(), vec.end(), dest.begin(),
    > > > dest.end(),std::plus<double>());

    >
    > > i mean

    >
    > > std::transform(vec.begin(), vec.end(),
    > > dest.begin(),dest.begin(),std::plus<double>())

    >
    > > definitely cleaner. thanks.

    >
    > another thought:
    >
    > it definitely achieves x+=y but i'm wondering if it's quite in the
    > spirit of x+=y, and not instead x=x+y. i believe the 2nd
    > creates a temp object to store x?


    write your own plus functor.

    regards,
    FM.
     
    terminator, Sep 5, 2007
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. padma
    Replies:
    0
    Views:
    360
    padma
    Oct 3, 2007
  2. vsoler
    Replies:
    8
    Views:
    355
    John Nagle
    Aug 31, 2009
  3. harryos
    Replies:
    6
    Views:
    775
    Peter Otten
    Sep 20, 2010
  4. Nathan Rice
    Replies:
    10
    Views:
    370
    Ethan Furman
    Dec 21, 2011
  5. Replies:
    4
    Views:
    338
    Phrogz
    Nov 2, 2007
Loading...

Share This Page