demos/spectrum/3rdparty/fftreal/stopwatch/ClockCycleCounter.cpp
changeset 25 e24348a560a6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/spectrum/3rdparty/fftreal/stopwatch/ClockCycleCounter.cpp	Fri Jun 11 14:24:45 2010 +0300
@@ -0,0 +1,285 @@
+/*****************************************************************************
+
+        ClockCycleCounter.cpp
+        Copyright (c) 2003 Laurent de Soras
+
+--- Legal stuff ---
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*Tab=3***********************************************************************/
+
+
+
+#if defined (_MSC_VER)
+	#pragma warning (1 : 4130) // "'operator' : logical operation on address of string constant"
+	#pragma warning (1 : 4223) // "nonstandard extension used : non-lvalue array converted to pointer"
+	#pragma warning (1 : 4705) // "statement has no effect"
+	#pragma warning (1 : 4706) // "assignment within conditional expression"
+	#pragma warning (4 : 4786) // "identifier was truncated to '255' characters in the debug information"
+	#pragma warning (4 : 4800) // "forcing value to bool 'true' or 'false' (performance warning)"
+	#pragma warning (4 : 4355) // "'this' : used in base member initializer list"
+#endif
+
+
+
+/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
+
+#include	"ClockCycleCounter.h"
+
+#include	<cassert>
+
+
+
+namespace stopwatch
+{
+
+
+
+/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
+
+
+
+/*
+==============================================================================
+Name: ctor
+Description:
+	The first object constructed initialise global data. This first
+	construction may be a bit slow.
+Throws: Nothing
+==============================================================================
+*/
+
+ClockCycleCounter::ClockCycleCounter ()
+:	_start_time (0)
+,	_state (0)
+,	_best_score (-1)
+{
+	if (! _init_flag)
+	{
+		// Should be executed in this order
+		compute_clk_mul ();
+		compute_measure_time_total ();
+		compute_measure_time_lap ();
+
+		// Restores object state
+		_start_time = 0;
+		_state      = 0;
+		_best_score = -1;
+
+		_init_flag = true;
+	}
+}
+
+
+
+/*
+==============================================================================
+Name: get_time_total
+Description:
+	Gives the time elapsed between the latest stop_lap() and start() calls.
+Returns:
+	The duration, in clock cycles.
+Throws: Nothing
+==============================================================================
+*/
+
+Int64	ClockCycleCounter::get_time_total () const
+{
+	const Int64		duration = _state - _start_time;
+	assert (duration >= 0);
+
+	const Int64		t = max (
+		duration - _measure_time_total,
+		static_cast <Int64> (0)
+	);
+
+	return (t * _clk_mul);
+}
+
+
+
+/*
+==============================================================================
+Name: get_time_best_lap
+Description:
+	Gives the smallest time between two consecutive stop_lap() or between
+	the stop_lap() and start(). The value is reset by a call to start().
+	Call this function only after a stop_lap().
+	The time is amputed from the duration of the stop_lap() call itself.
+Returns:
+	The smallest duration, in clock cycles.
+Throws: Nothing
+==============================================================================
+*/
+
+Int64	ClockCycleCounter::get_time_best_lap () const
+{
+	assert (_best_score >= 0);
+
+	const Int64		t1 = max (
+		_best_score - _measure_time_lap,
+		static_cast <Int64> (0)
+	);
+	const Int64		t = min (t1, get_time_total ());
+
+	return (t * _clk_mul);
+}
+
+
+
+/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
+
+
+
+/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
+
+
+
+#if defined (__MACOS__)
+
+static inline double	stopwatch_ClockCycleCounter_get_time_s ()
+{
+	const Nanoseconds	ns = AbsoluteToNanoseconds (UpTime ());
+
+	return (ns.hi * 4294967296e-9 + ns.lo * 1e-9);
+}
+
+#endif	// __MACOS__
+
+
+
+/*
+==============================================================================
+Name: compute_clk_mul
+Description:
+	This function, only for PowerPC/MacOS computers, computes the multiplier
+	required to deduce clock cycles from the internal counter.
+Throws: Nothing
+==============================================================================
+*/
+
+void	ClockCycleCounter::compute_clk_mul ()
+{
+	assert (! _init_flag);
+
+#if defined (__MACOS__)
+
+	long				clk_speed_mhz = CurrentProcessorSpeed ();
+	const Int64		clk_speed =
+		static_cast <Int64> (clk_speed_mhz) * (1000L*1000L);
+
+	const double	start_time_s = stopwatch_ClockCycleCounter_get_time_s ();
+	start ();
+
+	const double	duration = 0.01;	// Seconds
+	while (stopwatch_ClockCycleCounter_get_time_s () - start_time_s < duration)
+	{
+		continue;
+	}
+
+	const double	stop_time_s = stopwatch_ClockCycleCounter_get_time_s ();
+	stop ();
+
+	const double	diff_time_s = stop_time_s - start_time_s;
+	const double	nbr_cycles = diff_time_s * static_cast <double> (clk_speed);
+
+	const Int64		diff_time_c = _state - _start_time;
+	const double	clk_mul = nbr_cycles / static_cast <double> (diff_time_c);
+
+	_clk_mul = round_int (clk_mul);
+
+#endif	// __MACOS__
+}
+
+
+
+void	ClockCycleCounter::compute_measure_time_total ()
+{
+	start ();
+	spend_time ();
+
+	Int64				best_result = 0x7FFFFFFFL;	// Should be enough
+	long				nbr_tests = 100;
+	for (long cnt = 0; cnt < nbr_tests; ++cnt)
+	{
+		start ();
+		stop_lap ();
+		const Int64		duration = _state - _start_time;
+		best_result = min (best_result, duration);
+	}
+
+	_measure_time_total = best_result;
+}
+
+
+
+/*
+==============================================================================
+Name: compute_measure_time_lap
+Description:
+	Computes the duration of one stop_lap() call and store it. It will be used
+	later to get the real duration of the measured operation (by substracting
+	the measurement duration).
+Throws: Nothing
+==============================================================================
+*/
+
+void	ClockCycleCounter::compute_measure_time_lap ()
+{
+	start ();
+	spend_time ();
+
+	long				nbr_tests = 10;
+	for (long cnt = 0; cnt < nbr_tests; ++cnt)
+	{
+		stop_lap ();
+		stop_lap ();
+		stop_lap ();
+		stop_lap ();
+	}
+
+	_measure_time_lap = _best_score;
+}
+
+
+
+void	ClockCycleCounter::spend_time ()
+{
+	const Int64		nbr_clocks = 500;	// Number of clock cycles to spend
+
+	const Int64		start = read_clock_counter ();
+	Int64				current;
+
+	do
+	{
+		current = read_clock_counter ();
+	}
+	while ((current - start) * _clk_mul < nbr_clocks);
+}
+
+
+
+Int64	ClockCycleCounter::_measure_time_total = 0;
+Int64	ClockCycleCounter::_measure_time_lap = 0;
+int	ClockCycleCounter::_clk_mul = 1;
+bool	ClockCycleCounter::_init_flag = false;
+
+
+}	// namespace stopwatch
+
+
+
+/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/