/* Defines class distance_counter, for use in measuring the performance of certain STL generic algorithms. Objects of this class behave like those of type Distance (which should be a type capable of representing the difference between iterators of type RandomAccessIterator) but the class also keeps counts of all Distance operations, using values of type Counting. Type RandomAccessIterator is used as the result type of certain addition and subtraction operators, with the assumption that Distance is its distance type. */ #ifndef DISTCOUNT_H #define DISTCOUNT_H /* * 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. * */ template class distance_counter { typedef distance_counter self; friend bool operator==(const self& x, const self& y); friend bool operator==(const self& x, const Distance& y); friend bool operator<(const self& x, const self& y); friend bool operator<(const self& x, const Distance& y); friend bool operator<(const Distance& x, const self& y); friend self operator+(const Distance& n, const self& x); friend self operator*(const Distance& n, const self& x); friend RandomAccessIterator operator+(RandomAccessIterator i, const self& x); friend RandomAccessIterator operator+=(RandomAccessIterator& i, const self& x); friend RandomAccessIterator operator-(RandomAccessIterator i, const self& x); friend RandomAccessIterator operator-=(RandomAccessIterator& i, const self& x); protected: Distance current; Counting generation; public: static Counting constructions; static Counting copy_constructions; static Counting conversions; static Counting assignments; static Counting increments; static Counting additions; static Counting subtractions; static Counting multiplications; static Counting divisions; static Counting equality_comparisons; static Counting less_comparisons; static Counting max_generation; static void reset() { constructions = 0; copy_constructions = 0; conversions = 0; assignments = 0; increments = 0; additions = 0; subtractions = 0; multiplications = 0; divisions = 0; equality_comparisons = 0; less_comparisons = 0; max_generation = 0; } static Counting total() { return constructions + copy_constructions + conversions + assignments + increments + additions + subtractions + multiplications + divisions + equality_comparisons + less_comparisons; } static void report(ostream& o) { o << "Distance stats: \n" << " Constructions: " << constructions << "\n" << " Copies: " << copy_constructions << "\n" << " Conversions: " << conversions << "\n" << " Assignments: " << assignments << "\n" << " Increments: " << increments << "\n" << " Additions: " << additions << "\n" << " Subtractions: " << subtractions << "\n" << " Multiplications: " << multiplications << "\n" << " Divisions: " << divisions << "\n" << " Equality comps: " << equality_comparisons << "\n" << " Less comps: " << less_comparisons << "\n" << " TOTAL: " << total() << endl; o << " Maximum generation: " << max_generation << endl; } distance_counter() : generation(0) { ++constructions; } distance_counter(const Distance& x) : current(x), generation(0) { ++conversions; } operator int() const { ++coversions; return current; } distance_counter(const self& c) : current(c.current), generation(c.generation + 1) { ++copy_constructions; if (generation > max_generation) { max_generation = generation; } } Distance base() const {return current; } self& operator=(const self& x) { ++assignments; current = x.current; return *this; } self& operator++() { ++increments; ++current; return *this; } self operator++(int) { self tmp = *this; ++increments; ++current; return tmp; } self& operator--() { ++increments; --current; return *this; } self operator--(int) { self tmp = *this; ++increments; --current; return tmp; } self operator+(const self& n) const { self tmp = *this; return tmp += n; } self operator+(const Distance& n) const { self tmp = *this; return tmp += n; } self& operator+=(const self& n) { ++additions; current += n.current; return *this; } self& operator+=(const Distance& n) { ++additions; current += n; return *this; } self operator-(const self& n) const { self tmp = *this; return tmp -= n; } self operator-(const Distance& n) const { self tmp = *this; return tmp -= n; } self& operator-=(const self& n) { ++subtractions; current -= n.current; return *this; } self& operator-=(const Distance& n) { ++subtractions; current -= n; return *this; } self operator*(const self& n) const { self tmp = *this; return tmp *= n; } self operator*(const Distance& n) const { self tmp = *this; return tmp *= n; } self& operator*=(const self& n) { ++multiplications; current *= n.current; return *this; } self& operator*=(const Distance& n) { ++multiplications; current *= n; return *this; } self operator/(const self& n) const { self tmp = *this; return tmp /= n; } self operator/(const Distance& n) const { self tmp = *this; return tmp /= n; } self& operator/=(const self& n) { ++divisions; current /= n.current; return *this; } self& operator/=(const Distance& n) { ++divisions; current /= n; return *this; } }; template inline bool operator==(const distance_counter& x, const distance_counter& y) { ++distance_counter::equality_comparisons; return x.current == y.current; } template inline bool operator==(const distance_counter& x, const Distance& y) { ++distance_counter::equality_comparisons; return x.current == y; } template inline bool operator<(const distance_counter& x, const distance_counter& y) { ++distance_counter::less_comparisons; return x.current < y.current; } template inline bool operator<(const distance_counter& x, const Distance& y) { ++distance_counter::less_comparisons; return x.current < y; } template inline bool operator<(const Distance& x, const distance_counter& y) { ++distance_counter::less_comparisons; return x < y.current; } template inline RandomAccessIterator operator+(RandomAccessIterator i, const distance_counter& x) { return i + x.current; } template inline RandomAccessIterator operator+=(RandomAccessIterator& i, const distance_counter& x) { return i += x.current; } template inline RandomAccessIterator operator-(RandomAccessIterator i, const distance_counter& x) { return i - x.current; } template inline RandomAccessIterator operator-=(RandomAccessIterator &i, const distance_counter& x) { return i -= x.current; } template inline distance_counter operator-(const distance_counter& x, const distance_counter& y) { ++distance_counter::subtractions; return distance_counter(x.current - y.current); } template inline distance_counter operator+(const Distance& n, const distance_counter& x) { ++distance_counter::additions; return x + n; } template inline distance_counter operator*(const Distance& n, const distance_counter& x) { ++distance_counter::multiplications; return x * n; } template Counting distance_counter:: constructions = 0; template Counting distance_counter:: copy_constructions = 0; template Counting distance_counter:: conversions = 0; template Counting distance_counter:: assignments = 0; template Counting distance_counter:: increments = 0; template Counting distance_counter:: additions = 0; template Counting distance_counter:: subtractions = 0; template Counting distance_counter:: multiplications = 0; template Counting distance_counter:: divisions = 0; template Counting distance_counter:: equality_comparisons = 0; template Counting distance_counter:: less_comparisons = 0; template Counting distance_counter:: max_generation = 0; /* The purpose of the following version of get_temporarary_buffer is to enable the STL stable_sort generic algorithms to work with distance_counter objects. */ template pair > get_temporary_buffer(distance_counter len, T* p) { pair tmp = get_temporary_buffer((int)len, p); return pair >(tmp.first, distance_counter(tmp.second)); } #endif