<!--
    Licensed to the Apache Software  Foundation (ASF) under one or more
    contributor  license agreements.  See  the NOTICE  file distributed
    with  this  work  for  additional information  regarding  copyright
    ownership.   The ASF  licenses this  file to  you under  the Apache
    License, Version  2.0 (the  License); you may  not use  this file
    except in  compliance with the License.   You may obtain  a copy of
    the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the  License is distributed on an  "AS IS" BASIS,
    WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
    implied.   See  the License  for  the  specific language  governing
    permissions and limitations under the License.

    Copyright 1999-2007 Rogue Wave Software, Inc.
-->

<HTML>
<HEAD>
<TITLE>partial_sum()</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="partial-sort-copy.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="partition.html"><IMG SRC="images/bnext.gif" WIDTH=25 HEIGHT=21 ALT="Next file" BORDER=O></A><DIV CLASS="DOCUMENTNAME"><B>Apache C++ Standard Library Reference Guide</B></DIV>
<H2>partial_sum()</H2>
<P><B>Library:</B>&nbsp;&nbsp;<A HREF="2-10.html">Numerics</A></P>

<PRE><HR><B><I>Function</I></B><HR></PRE>

<UL>
<LI><A HREF="#sec1">Local Index</A></LI>
<LI><A HREF="#sec2">Summary</A></LI>
<LI><A HREF="#sec3">Synopsis</A></LI>
<LI><A HREF="#sec4">Description</A></LI>
<LI><A HREF="#sec5">Complexity</A></LI>
<LI><A HREF="#sec6">Example</A></LI>
<LI><A HREF="#sec7">See Also</A></LI>
<LI><A HREF="#sec8">Standards Conformance</A></LI>
</UL>
<A NAME="sec1"><H3>Local Index</H3></A>
No Entries
<A NAME="sec2"><H3>Summary</H3></A>
<P>Generalized numeric operation that calculates successive partial sums of a range of values</P>
<A NAME="sec3"><H3>Synopsis</H3></A>

<PRE>#include &lt;numeric&gt;

namespace std {
  template &lt;class InputIterator, class OutputIterator&gt;
  OutputIterator partial_sum(InputIterator start,
                             InputIterator finish,
                             OutputIterator result);

  template &lt;class InputIterator,
            class OutputIterator,
            class BinaryOperation&gt;
  OutputIterator partial_sum(InputIterator start,
                             InputIterator finish,
                             OutputIterator result,
                             BinaryOperation binary_op);
}
</PRE>
<A NAME="sec4"><H3>Description</H3></A>
<P>The <SAMP>partial_sum()</SAMP> algorithm creates a new sequence in which every element is formed by adding all the values of the previous elements, or, in the second form of the algorithm, by applying the operation <SAMP>binary_op</SAMP> successively on every previous element. That is, <SAMP>partial_sum()</SAMP> assigns to every iterator <SAMP>i</SAMP> in the range <SAMP>[result,  result  +  (finish - start))</SAMP> a value equal to:</P>

<UL><PRE>((...(*start + *(start + 1)) + ... ) + 
      *(start + (i - result)))
</PRE></UL>
<P> or, in the second version of the algorithm:</P>

<UL><PRE>binary_op(binary_op(..., binary_op (*start, 
          *(start + 1)),...),*(start + (i - result)))
</PRE></UL>
<P>For instance, applying <SAMP>partial_sum()</SAMP> to (1,2,3,4,) yields (1,3,6,10).</P>
<P>The <SAMP>partial_sum()</SAMP> algorithm returns <SAMP>result</SAMP> <SAMP>+ (finish - start)</SAMP>.</P>
<P>If <SAMP>result</SAMP> is equal to <SAMP>start</SAMP>, the elements of the new sequence successively replace the elements in the original sequence, effectively turning <SAMP>partial_sum()</SAMP> into an inplace transformation. </P>
<A NAME="sec5"><H3>Complexity</H3></A>
<P>Exactly <SAMP>(finish - start) - 1</SAMP> applications of the default <SAMP>+</SAMP> operator or <SAMP>binary_op</SAMP> are performed.</P>
<A NAME="sec6"><H3>Example</H3></A>

<UL><PRE>//
//  partsum.cpp
//

#include &lt;algorithm&gt;  // for copy
#include &lt;functional&gt; // for multiplies
#include &lt;iostream&gt;   // for cout, endl
#include &lt;iterator&gt;   // for ostream_iterator
#include &lt;numeric&gt;    // for partial_sum
#include &lt;vector&gt;     // for vector



int main ()
{
    typedef std::vector&lt;int, std::allocator&lt;int&gt; &gt; Vector;
    typedef std::ostream_iterator&lt;int, char,
                                  std::char_traits&lt;char&gt; &gt;
            Iter;

    // Initialize a vector using an array of integers.
    const Vector::value_type a[] = { 1, 2, 3, 4, 5, 
                                     6, 7, 8, 9, 10 };
    Vector v (a + 0, a + sizeof a / sizeof *a);

    // Create an empty vectors to store results.
    Vector sums  (Vector::size_type (10));
    Vector prods (Vector::size_type (10));

    // Compute partial_sums and partial_products.
    std::partial_sum (v.begin (), v.end (), sums.begin ());
    std::partial_sum (v.begin (), v.end (), prods.begin (),
                      std::multiplies&lt;Vector::value_type&gt;());

    // Output the results.
    std::cout &lt;&lt; "For the series: \n     ";
    std::copy (v.begin (), v.end (), Iter (std::cout, " "));

    std::cout &lt;&lt; "\n\nThe partial sums: \n     ";
    std::copy (sums.begin (), sums.end (), Iter (std::cout,
                                                 " "));
    std::cout &lt;&lt; " should each equal (N*N + N)/2\n\n";

    std::cout &lt;&lt; "The partial products: \n     ";
    std::copy (prods.begin (), prods.end (), Iter (std::cout,
                                                   " "));
    std::cout &lt;&lt; " should each equal N!" &lt;&lt; std::endl;

    return 0;
}


Program Output:
</PRE></UL>
<UL><PRE>For the series: 
     1 2 3 4 5 6 7 8 9 10 

The partial sums: 
     1 3 6 10 15 21 28 36 45 55  should each equal (N*N + N)/2

The partial products: 
     1 2 6 24 120 720 5040 40320 362880 3628800  should each
equal N!
</PRE></UL>
<A NAME="sec7"><H3>See Also</H3></A>
<P><A HREF="algorithms.html">Algorithms</A>, <A HREF="algorithm-h.html">&lt;algorithm&gt;</A></P>
<A NAME="sec8"><H3>Standards Conformance</H3></A>
<P><I>ISO/IEC 14882:1998 -- International Standard for Information Systems -- Programming Language C++, Section 26.4.3</I></P>

<BR>
<HR>
<A HREF="partial-sort-copy.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="partition.html"><IMG SRC="images/bnext.gif" WIDTH=20 HEIGHT=21 ALT="Next file" BORDER=O></A>

<!-- Google Analytics tracking code -->
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
    _uacct = "UA-1775151-1";
    urchinTracker();
</script>
<!-- end of Google Analytics tracking code -->

</BODY>
</HTML>
