// -*- C++ -*-
/***************************************************************************
 *
 * numeric - Declarations for the Standard Library algorithms
 *
 * $Id: numeric 550991 2007-06-26 23:58:07Z sebor $
 *
 ***************************************************************************
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Hewlett-Packard Company makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 ***************************************************************************
 *
 * 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 1994-2006 Rogue Wave Software.
 * 
 **************************************************************************/

#ifndef _RWSTD_NUMERIC_INCLUDED
#define _RWSTD_NUMERIC_INCLUDED


#include <rw/_iterbase.h>
#include <rw/_defs.h>


_RWSTD_NAMESPACE (std) { 


// 26.4.1 - Accumulate
template <class _InputIter, class _TypeT>
inline _TypeT accumulate (_InputIter __first, _InputIter __last, _TypeT __n)
{
    for (; __first != __last; ++__first)
        __n += *__first;
    return __n;
}


template <class _InputIter, class _TypeT, class _BinaryOperation>
inline _TypeT accumulate (_InputIter __first, _InputIter __last,
                          _TypeT __n, _BinaryOperation __oper)
{
    for (; __first != __last; ++__first)
        __n = __oper (__n, *__first);
    return __n;
}


// 26.4.2 - Inner product
template <class _InputIter1, class _InputIter2, class _TypeT>
inline _TypeT inner_product (_InputIter1 __first1, _InputIter1 __last1,
                             _InputIter2 __first2, _TypeT __n) {

    for (; __first1 != __last1; ++__first1, ++__first2)
        __n += *__first1 * *__first2;
    return __n;
}


template <class _InputIter1, class _InputIter2, 
          class _TypeT, class _BinaryOperation1, class _BinaryOperation2>
inline _TypeT
inner_product (_InputIter1 __first1, _InputIter1 __last1,
               _InputIter2 __first2, _TypeT __n,
               _BinaryOperation1 __oper1, _BinaryOperation2 __oper2)
{
    for (; __first1 != __last1; ++__first1, ++__first2) 
        __n = __oper1 (__n, __oper2 (*__first1, *__first2));
    return __n;
}


template <class _InputIter, class _OutputIter, class _TypeT>
inline _OutputIter
__partial_sum (_InputIter __first, _InputIter __last, _OutputIter __res,
               _TypeT*)
{
    _TypeT __val = *__first;
    while (++__first != __last) {
        __val = __val + *__first;
        *++__res = __val;
    }
    return ++__res;
}


// 26.4.3 - Partial sum
template <class _InputIter, class _OutputIter>
inline _OutputIter
partial_sum (_InputIter __first, _InputIter __last, _OutputIter __res)
{
    return __first == __last
        ? __res : (*__res = *__first,
                   __partial_sum (__first, __last, __res,
                                  _RWSTD_VALUE_TYPE (_InputIter)));
}


template <class _InputIter, class _OutputIter,
class _TypeT, class _BinaryOperation>
inline _OutputIter __partial_sum (_InputIter __first, _InputIter __last,
                                  _OutputIter __res, _TypeT*,
                                  _BinaryOperation __oper)
{
    _TypeT __val = *__first;
    while (++__first != __last) {
        __val = __oper (__val, *__first);
        *++__res = __val;
    }
    return ++__res;
}


template <class _InputIter, class _OutputIter, class _BinaryOperation>
inline _OutputIter partial_sum (_InputIter __first, _InputIter __last,
                                _OutputIter __res, _BinaryOperation __oper)
{
    return __first == __last ?
        __res : (*__res = *__first,
                 __partial_sum (__first, __last, __res,
                                _RWSTD_VALUE_TYPE (_InputIter),__oper));
}


template <class _InputIter, class _OutputIter, class _TypeT>
inline _OutputIter
__adjacent_difference (_InputIter __first, _InputIter __last, _OutputIter __res,
                       _TypeT*)
{
    _TypeT __val = *__first;
    while (++__first != __last) {
        _TypeT __tmp = *__first;
        *++__res = __tmp - __val;
        __val = __tmp;
    }
    return ++__res;
}


// 26.4.4 - Adjacent difference
template <class _InputIter, class _OutputIter>
inline _OutputIter
adjacent_difference (_InputIter __first, _InputIter  __last, _OutputIter __res)
{
    return __first == __last
        ? __res
        : (*__res = *__first,
           __adjacent_difference(__first, __last, __res,
                                 _RWSTD_VALUE_TYPE (_InputIter)));
}

template <class _InputIter, class _OutputIter,
          class _TypeT, class _BinaryOperation>
inline _OutputIter
__adjacent_difference (_InputIter __first, _InputIter __last, 
                       _OutputIter __res, _TypeT*, _BinaryOperation __oper)
{
    _TypeT __val = *__first;
    while (++__first != __last) {
        _TypeT __tmp = *__first;
        *++__res = __oper (__tmp, __val);
        __val = __tmp;
    }
    return ++__res;
}


template <class _InputIter, class _OutputIter, class _BinaryOperation>
inline _OutputIter
adjacent_difference (_InputIter __first, _InputIter __last,
                     _OutputIter __res, _BinaryOperation __oper)
{
    return __first == __last
        ? __res
        : (*__res = *__first,
           __adjacent_difference(__first, __last, __res,
                                 _RWSTD_VALUE_TYPE (_InputIter), __oper));
}


}   // namespace std


#endif   // _RWSTD_NUMERIC_INCLUDED
