// Class for counting assignments and comparisons;
// adapted from code written by Dave Musser.

/*

Defines class counter<T>, for use in measuring
the performance of certain STL generic algorithms.  Objects of this
class behave like those of type T with respect to assignments
and comparison operations, but the class also keeps counts of those
operations.

*/

/*
 * Copyright (c) 1997 Rensselaer Polytechnic Institute
 *
 * 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.  Rensselaer Polytechnic Institute makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 */

#ifndef COUNTER_H
#define COUNTER_H

template <class T>
class counter {
protected:
  T value;
public:
  static unsigned assignments;
  static unsigned comparisons;

  counter() : value(T()) { ++assignments; }

  counter(const T& v) : value(v) { ++assignments; }

  counter(const counter<T>& x) : value(x.value) { ++assignments; }

  static void reset() { assignments = comparisons = 0; }

  friend bool operator<(const counter<T>& x, const counter<T>& y) 
  {
    ++counter<T>::comparisons;
    return x.value < y.value;
  }

  friend bool operator>(const counter<T>& x, const counter<T>& y) 
  {
    ++counter<T>::comparisons;
    return x.value > y.value;
  }

  friend std::ostream& operator<<(std::ostream& o, const counter<T>& x) {
    return o << x.value;
  }

  counter<T>& operator=(const counter<T>& x) {
    if (*this != x) 
    {
      ++assignments;
      value = x.value;
    }
    return *this;
  }

  bool operator==(const counter<T>& x) const {
    ++comparisons;
    return value == x.value;
  }

  bool operator!=(const counter<T>& x) const {
    ++comparisons;
    return value != x.value;
  }
};

template <class T>
unsigned counter<T>::assignments = 0;

template <class T>
unsigned counter<T>::comparisons = 0;


#endif

