// file: ToolsetArrayComparableNumericM.hpp

#ifndef TOOLSET_ARRAY_COMPARABLE_NUMERIC_M_HPP_
#define TOOLSET_ARRAY_COMPARABLE_NUMERIC_M_HPP_

#include <cassert>
#include <vector>

#include "ToolsetArrayComparableM.hpp"

	namespace ToolsetArrayComparable
	{
		template <typename T>
		void determine_range_with_max_sum
			(const std::vector<T> & array, int & max_low, int & max_high, T & max_sum)
			// Instantiation condition: T is a comparable numeric type.
		{
			int low = 0; 
			T sum = array[low];
			max_low = low;
			max_high = low;
			max_sum = sum;
			for (int high = low + 1; high < array.size(); ++high) {
				if (sum <= 0) {
					low = high;
					sum = 0;
				}
				sum += array[high];
				if (sum > max_sum) {
					max_low = low;
					max_high = high;
					max_sum = sum;
				}
			}
			assert(0 <= max_low);							// postcondition
			assert(max_low <= max_high);					// postcondition
			assert(max_high < array.size());				// postcondition
		}

		template <typename T> T sum (const std::vector<T> & v)
		{
			T result = 0;
			for (int i = 0; i < v.size(); ++i)
			{
				result += v[i];
			}
			return result;
		}

		template <typename T> T sum1 (const std::vector<T> & v)
		{
			T result = 0;
			for (int i = 0; i < v.size(); result += v[i++]);
			return result;
		}

		// template typedefs don't work!
		// template <typename T> typedef bool (*Property) (const T &);
		// typedef template <typename T> bool (*Property) (const T &);

		template <typename T>
		bool exists_p (const std::vector<T> & v, bool (*property) (const T &))
		{
			int i = 0;
			while (i < v.size() && !property(v[i]))
			{
				++i;
			}
			return i < v.size();
		}

		template <typename T>
		bool exists_p1 (const std::vector<T> & v, bool (*property) (const T &))
		{
			int i;
			for (i = 0; i < v.size() && !property(v[i]); ++i);
			return i < v.size();
		}

	} // ToolsetArrayComparable

#endif // TOOLSET_ARRAY_COMPARABLE_NUMERIC_M_HPP_
