Topic: accumulate algorithm


Author: Kenshin <kenshin.himura.sakabato@gmail.com>
Date: Thu, 3 Dec 2009 12:01:28 CST
Raw View
As "Bo Persson" states:
"the intention is to accumulate the values into the parameter".


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "subramanian100in@yahoo.com, India" <subramanian100in@yahoo.com>
Date: Thu, 12 Nov 2009 11:23:45 CST
Raw View
The accumulate algorithm in the C++ Standard library have the
following forms:

template <class InputIterator, class T>
T accumulate(InputIterator first, InputIterator last, T init);

template <class InputIterator, class T, class BinaryOperation>
T accumulate(InputIterator first, InputIterator last, T init,
                      BinaryOperation binary_op);

My question is why these algorithms take 'T init' as a parameter
instead of 'const T& init' ? ie Why don't we have

template <class InputIterator, class T>
T accumulate(InputIterator first, InputIterator last, const T& init);

template <class InputIterator, class T, class BinaryOperation>
T accumulate(InputIterator first, InputIterator last, const T& init,
                      BinaryOperation binary_op);


Kindly explain the reason.

Thanks
V.Subramanian

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Bo Persson" <bop@gmb.dk>
Date: Thu, 12 Nov 2009 16:23:20 CST
Raw View
subramanian100in@yahoo.com wrote:
> The accumulate algorithm in the C++ Standard library have the
> following forms:
>
> template <class InputIterator, class T>
> T accumulate(InputIterator first, InputIterator last, T init);
>
> template <class InputIterator, class T, class BinaryOperation>
> T accumulate(InputIterator first, InputIterator last, T init,
>                      BinaryOperation binary_op);
>
> My question is why these algorithms take 'T init' as a parameter
> instead of 'const T& init' ? ie Why don't we have
>
> template <class InputIterator, class T>
> T accumulate(InputIterator first, InputIterator last, const T&
> init);
>
> template <class InputIterator, class T, class BinaryOperation>
> T accumulate(InputIterator first, InputIterator last, const T& init,
>                      BinaryOperation binary_op);
>
>
> Kindly explain the reason.
>

I believe the intention is to accumulate the values into the
parameter. That avoids the requirement of T being copyable or
zero/default initializable.


Bo Persson



--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Fri, 13 Nov 2009 11:31:48 CST
Raw View
On Nov 12, 10:23 pm, "Bo Persson" <b...@gmb.dk> wrote:
> subramanian10...@yahoo.com wrote:
> > The accumulate algorithm in the C++ Standard library have the
> > following forms:

> > template <class InputIterator, class T>
> > T accumulate(InputIterator first, InputIterator last, T init);

> > template <class InputIterator, class T, class BinaryOperation>
> > T accumulate(InputIterator first, InputIterator last, T init,
> >                      BinaryOperation binary_op);

> > My question is why these algorithms take 'T init' as a
> > parameter instead of 'const T& init' ? ie Why don't we have

> > template <class InputIterator, class T>
> > T accumulate(InputIterator first, InputIterator last, const T&
> > init);

> > template <class InputIterator, class T, class BinaryOperation>
> > T accumulate(InputIterator first, InputIterator last, const T& init,
> >                      BinaryOperation binary_op);

> > Kindly explain the reason.

> I believe the intention is to accumulate the values into the
> parameter. That avoids the requirement of T being copyable or
> zero/default initializable.

I think T has to be copiable anyway---otherwise, how do you
return it or pass it as a parameter?  It also has to be
assignable.  I imagine that the real reason for passing it as a
value here is that accumulate needs a copy that it can modify
anyway; in some cases, it may be cheaper for the user to
construct this copy directly as an argument, rather than to let
accumulate do it.  (In practice, of course, it probably doesn't
matter most of the time, given the number of times you're going
to assign to it.)

A more interesting question is why accumulate uses:
       accu = accu + *iter
or
       accu = binary_op(accu, *iter)
rather than:
       accu += *iter
or
       binary_op(accu, *iter)
(with the requirement that binary_op modify its first argument,
along the lines of operator+=).  Copying the accumulator once,
when calling the function, is generally acceptable; copying it
twice for each operation can get to be pretty expensive.

(I've designed my hasher class template to use std::accumulator,
i.e. you can write something like:

       std::string s;
       //  ...
       s += std::accumulate(s.begin(), s.end(), SHA1());

and get the SHA1 hash appended to the end of s.  This is
excessively slow, however, since the SHA1 accumulator has a
certain size, and is getting copied a lot.  In my latest
version, I've added the following to the interface because of
this:

   //!@name Using += with std::accumulate
   //!     By default, <tt>std::accumulate</tt> uses
   //!     <tt>acc&nbsp;=&nbsp;acc&nbsp;+&nbsp;*iter</tt>,resulting
   //!     in a copy of the Hasher each time.  To avoid this, we
   //!     define a binary operator, which can be passed as the
   //!     fourth parameter (a binary operator) to
   //!     <tt>std::accumulate</tt>, which plays on the particular
   //!     definition of the function: the binary operator has
   //!     semantics which are more like to <tt>+=</tt>, and returns
   //!     a type for which we have overloaded assignment to be a
   //!     no-op.  So while the expression in
   //!     <tt>std::accumulate</tt> is
   //!     <tt>acc&nbsp;=&nbsp;binary_op(acc,&nbsp;*i)</tt>, there
   //!     will be no copying.
   //!
   //!     Although the wording in the current version of the
   //!     standard would seem to guarantee that this works, I'm not
   //!     too sure that this guarantee is intentional; use at your
   //!     own risk.
   //!@{
   //
-----------------------------------------------------------------------
   //!     This is the type used for the no-op assignment.
   //
-----------------------------------------------------------------------
   enum DummyType { dummy } ;

   //!     This is the binary operator.  Note that the first
   //!     parameter is a non-const reference.  If the implementation
   //!     of <tt>std::accumulate</tt> somehow tries to call this
   //!     operator on an rvalue, we're hosed.  (If the standard
   //!     really means that the expression must look exactly like
   //!     the one given, we're OK, because they use <tt>acc</tt> on
   //!     the left side of an assignment, so it must be an lvalue.)
   //
-----------------------------------------------------------------------
   struct BinOp
   {
       DummyType       operator()( Hasher& dest, Byte src ) const ;
   } ;

   //!     Finally, the "dummy" assignment operator.
   //
-----------------------------------------------------------------------
   Hasher&             operator=( DummyType ) ;
   //!@}

It makes a very significant difference.)

--
James Kanze

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "subramanian100in@yahoo.com, India" <subramanian100in@yahoo.com>
Date: Fri, 13 Nov 2009 11:57:07 CST
Raw View
*) On Nov 13, 3:23 am, "Bo Persson" <b...@gmb.dk> wrote:
> subramanian10...@yahoo.com wrote:
> > The accumulate algorithm in the C++ Standard library have the
> > following forms:
>
> > template <class InputIterator, class T>
> > T accumulate(InputIterator first, InputIterator last, T init);
>
> > template <class InputIterator, class T, class BinaryOperation>
> > T accumulate(InputIterator first, InputIterator last, T init,
> >                      BinaryOperation binary_op);
>
> > My question is why these algorithms take 'T init' as a parameter
> > instead of 'const T& init' ? ie Why don't we have
>
> > template <class InputIterator, class T>
> > T accumulate(InputIterator first, InputIterator last, const T&
> > init);
>
> > template <class InputIterator, class T, class BinaryOperation>
> > T accumulate(InputIterator first, InputIterator last, const T& init,
> >                      BinaryOperation binary_op);
>
> > Kindly explain the reason.
>
> I believe the intention is to accumulate the values into the
> parameter. That avoids the requirement of T being copyable or
> zero/default initializable.
>
> Bo Persson
>
> --

Kindly bear with me for the following post and correct me where-ever I
am wrong.

template <class InputIterator, class T>
T accumulate(InputIterator first, InputIterator last, T init);

Here since the accumulate algorithm receives a value of type T, T
should be already copyable. Am I correct ?
Default initialization is not needed anyway, I think. For example

template <class InputIterator, class T>
T accumulate(InputIterator first, InputIterator last, const T& init)
{
   T sum(init);
    while (first != last)
    {
          sum = sum + *first;
          ++first;
     }
     return sum;
}

If the above is correct, there should be a different reason for
receiving as 'T init'
rather than 'const T& init'.

Kindly clarify.

Thanks
V.Subramanian

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Bo Persson" <bop@gmb.dk>
Date: Fri, 13 Nov 2009 14:14:19 CST
Raw View
subramanian100in@yahoo.com wrote:
> *) On Nov 13, 3:23 am, "Bo Persson" <b...@gmb.dk> wrote:
>> subramanian10...@yahoo.com wrote:
>>> The accumulate algorithm in the C++ Standard library have the
>>> following forms:
>>
>>> template <class InputIterator, class T>
>>> T accumulate(InputIterator first, InputIterator last, T init);
>>
>>> template <class InputIterator, class T, class BinaryOperation>
>>> T accumulate(InputIterator first, InputIterator last, T init,
>>>                      BinaryOperation binary_op);
>>
>>> My question is why these algorithms take 'T init' as a parameter
>>> instead of 'const T& init' ? ie Why don't we have
>>
>>> template <class InputIterator, class T>
>>> T accumulate(InputIterator first, InputIterator last, const T&
>>> init);
>>
>>> template <class InputIterator, class T, class BinaryOperation>
>>> T accumulate(InputIterator first, InputIterator last, const T&
>>>                      init, BinaryOperation binary_op);
>>
>>> Kindly explain the reason.
>>
>> I believe the intention is to accumulate the values into the
>> parameter. That avoids the requirement of T being copyable or
>> zero/default initializable.
>>
>> Bo Persson
>>
>> --
>
> Kindly bear with me for the following post and correct me
> where-ever I am wrong.
>
> template <class InputIterator, class T>
> T accumulate(InputIterator first, InputIterator last, T init);
>
> Here since the accumulate algorithm receives a value of type T, T
> should be already copyable. Am I correct ?

Yes, it has to be copyable, for the return value. Sorry.

> Default initialization is not needed anyway, I think. For example
>
> template <class InputIterator, class T>
> T accumulate(InputIterator first, InputIterator last, const T& init)
> {
>   T sum(init);
>    while (first != last)
>    {
>          sum = sum + *first;
>          ++first;
>     }
>     return sum;
> }
>
> If the above is correct, there should be a different reason for
> receiving as 'T init'
> rather than 'const T& init'.
>
> Kindly clarify.

A slightly different implementation would be:

 template <class InputIterator, class T>
 T accumulate(InputIterator first, InputIterator last, T value)
 {
   while (first != last)
   {
         value = value + *first;
         ++first;

   }
    return value;
 }

Which does away with one copying of the value. The standard library is
sometimes a bit minimalistic this way. The caller has to provide the
initial value somehow, and the library doesn't have to know how to do
that.


Bo Persson



--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Nevin :-] Liber" <nevin@eviloverlord.com>
Date: Fri, 13 Nov 2009 16:46:31 CST
Raw View
In article
<ee671b0a-57c6-4d19-aa1d-9dfcb88d96fc@o9g2000prg.googlegroups.com>,
 "subramanian100in@yahoo.com, India" <subramanian100in@yahoo.com>
 wrote:

> template <class InputIterator, class T>
> T accumulate(InputIterator first, InputIterator last, const T& init)
> {
>    T sum(init);
>     while (first != last)
>     {
>           sum = sum + *first;
>           ++first;
>      }
>      return sum;
> }
>
> If the above is correct, there should be a different reason for
> receiving as 'T init'
> rather than 'const T& init'.

The algorithm pretty much requires one to copy init (and makes it easier
to reason about, as you know there are no aliasing issues), so why not
have that copy in the interface?  I don't see how anything is improved
by passing it in as a const reference.

--
 Nevin ":-)" Liber  <mailto:nevin@eviloverlord.com>  773 961-1620

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]