// Numeric extensions -*- C++ -*-

// Copyright (C) 2002-2019 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/*
 *
 * 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.
 *
 *
 * Copyright (c) 1996
 * Silicon Graphics Computer Systems, Inc.
 *
 * 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.  Silicon Graphics makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 */

/** @file ext/numeric
 *  This file is a GNU extension to the Standard C++ Library (possibly
 *  containing extensions from the HP/SGI STL subset). 
 */

#ifndef _EXT_NUMERIC
#define _EXT_NUMERIC 1

#pragma GCC system_header

#include <bits/concept_check.h>
#include <numeric>

#include <ext/functional> // For identity_element

namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  // Returns __x ** __n, where __n >= 0.  _Note that "multiplication"
  // is required to be associative, but not necessarily commutative.
  template<typename _Tp, typename _Integer, typename _MonoidOperation>
    _Tp
    __power(_Tp __x, _Integer __n, _MonoidOperation __monoid_op)
    {
      if (__n == 0)
	return identity_element(__monoid_op);
      else
	{
	  while ((__n & 1) == 0)
	    {
	      __n >>= 1;
	      __x = __monoid_op(__x, __x);
	    }

	  _Tp __result = __x;
	  __n >>= 1;
	  while (__n != 0)
	    {
	      __x = __monoid_op(__x, __x);
	      if ((__n & 1) != 0)
		__result = __monoid_op(__result, __x);
	      __n >>= 1;
	    }
	  return __result;
	}
    }

  template<typename _Tp, typename _Integer>
    inline _Tp
    __power(_Tp __x, _Integer __n)
    { return __power(__x, __n, std::multiplies<_Tp>()); }

  /**
   *  This is an SGI extension.
   *  @ingroup SGIextensions
   *  @doctodo
  */
  // Alias for the internal name __power.  Note that power is an extension,
  // not part of the C++ standard.
  template<typename _Tp, typename _Integer, typename _MonoidOperation>
    inline _Tp
    power(_Tp __x, _Integer __n, _MonoidOperation __monoid_op)
    { return __power(__x, __n, __monoid_op); }

  /**
   *  This is an SGI extension.
   *  @ingroup SGIextensions
   *  @doctodo
  */
  template<typename _Tp, typename _Integer>
    inline _Tp
    power(_Tp __x, _Integer __n)
    { return __power(__x, __n); }

#if __cplusplus >= 201103L
  using std::iota;
#else
  /**
   *  This is an SGI extension.
   *  @ingroup SGIextensions
   *  @doctodo
  */
  // iota is not part of the C++ standard.  It is an extension.
  template<typename _ForwardIter, typename _Tp>
    void
    iota(_ForwardIter __first, _ForwardIter __last, _Tp __value)
    {
      // concept requirements
      __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter>)
      __glibcxx_function_requires(_ConvertibleConcept<_Tp,
	    typename std::iterator_traits<_ForwardIter>::value_type>)

      while (__first != __last)
	*__first++ = __value++;
    }
#endif  // C++11

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace

#endif
