#ifndef INCLUDED_L3_TIME_H #define INCLUDED_L3_TIME_H // *Time dependent tools* Copyright (C) Krzysztof Bosak 2000-11-16...2000-12-07. // All rights reserved. // kbosak@box43.pl // http://www.kbosak.prv.pl #include #include "l3_array.h" #include "l3_str.h" ///////////////////////////////////////////////////////////////////////////// // Note: MS eMbedded Visual 4.0 has no time.h. // Note: Only x86 MS Visual C++ has inline assembler, MS eMbedded Visual 4.0 hasn't. #ifdef _MSC_VER // with MS Visual C++ #ifndef UNDER_CE // but not with MS eMbedded Visual #ifndef USING_INTEL_ICL // nor with Intel C++ compiler (icl) #define TSC_USING_x86ASSEMBLER #endif #endif #endif #ifdef UNDER_CE typedef long clock_t; #include const double CLOCKS_PER_SEC=1000; clock_t L3CLOCK() { return static_cast(::GetTickCount()); } #else #undef _No_Time_OS_Support #include clock_t L3CLOCK() { return clock(); } #endif ///////////////////////////////////////////////////////////////////////////// inline void PSleep(double duration_in_seconds) { // duration_in_seconds is 200 seconds max. // Even less with faster processor. assert(duration_in_seconds>0); assert(duration_in_seconds<200); const clock_t delay_clock=static_cast(CLOCKS_PER_SEC*duration_in_seconds); assert(delay_clock!=static_cast(-1)); assert(CLOCKS_PER_SEC*duration_in_seconds < INT_MAX); const clock_t start_clock=L3CLOCK(); assert(start_clock!=static_cast(-1)); while(L3CLOCK()-start_clock <= delay_clock) { ; } } ///////////////////////////////////////////////////////////////////////////// #ifdef TSC_USING_x86ASSEMBLER inline __int64 readTSC() { __int64 t; unsigned int a,b; unsigned int * const c=reinterpret_cast(&t); _asm { _emit 0x0f; _emit 0x31; mov a,eax; mov b,edx; } c[0]=a; c[1]=b; return t; } #endif class Timing { private: clock_t _start_clock; #ifdef TSC_USING_x86ASSEMBLER __int64 _TSC; #endif mutable basearray_s _buffer; public: inline void SetZeroTime() { _start_clock=L3CLOCK(); assert(_start_clock!=static_cast(-1)); #ifdef TSC_USING_x86ASSEMBLER _TSC=readTSC(); #endif } inline Timing(): _buffer(50) { SetZeroTime(); } inline double GetTime() const { #ifdef TSC_USING_x86ASSEMBLER return (readTSC()-_TSC)/1700e6;// xxx Processor dependent! set for 1700 MHz now. //return (readTSC()-_TSC)/933e6; #else const clock_t current_clock=L3CLOCK(); assert(current_clock!=static_cast(-1)); return (current_clock-_start_clock)/static_cast(CLOCKS_PER_SEC); #endif } inline TextString GetStringTime() const { #ifdef TSC_USING_x86ASSEMBLER sprintf(&_buffer[0], "%.3fs", GetTime()); #else sprintf(&_buffer[0], "%.2fs", GetTime()); #endif return TextString(&_buffer[0]); } Timing& operator=(const Timing&);// Forbidden. explicit Timing(const Timing&);// Forbidden. }; ostream& operator<<(ostream& str, const Timing& timing) { return str<(CLOCKS_PER_SEC)<<"s, "<<_clocktime<<" clocks"; if(_numcalls>1) { cout<<", about "<<_clocktime/static_cast(CLOCKS_PER_SEC)/_numcalls<<"s per call."; } else { cout<<'.'; } cout<(-1)); } inline void End() { const clock_t current_clock=L3CLOCK(); assert(current_clock!=static_cast(-1)); _clocktime+=current_clock-_clockstart; } private: explicit Profiler(const Profiler&);// Forbidden. Profiler& operator=(const Profiler&);// Forbidden. }; ///////////////////////////////////////////////////////////////////////////// class SmartLastCommonUser { protected: static SmartLastCommonUser * _lastcommonuser; public: virtual ~SmartLastCommonUser() { } }; SmartLastCommonUser* SmartLastCommonUser::_lastcommonuser=NULL; template class DynamicValue: public SmartLastCommonUser { private: double _dynamictime; Timing _timedstep; Type _min; Type _max; Type _val; Type _oldval; Type _basestep; enum LastStep {None=0, Up=1, Down=2}; LastStep _laststep; public: inline DynamicValue(const Type& min, const Type& max, const Type& t) : _val(t), _oldval(min-1), _basestep(1) { Range(min, max); DynamicReset(); } inline DynamicValue& operator=(const Type& n) { _val=n; return *this; } inline void operator+=(const Type& n) { _val+=n; if(_val>_max) { _val=_max; } } inline void operator++() { operator+=(Type(1)); } inline void operator--() { operator-=(Type(1)); } inline void operator-=(const Type& n) { _val-=n; if(_val<_min) { _val=_min; } } inline void Range(Type min, Type max) { assert(max>=min); if(max_max) { _val=_max; } } inline Type Value() const { return _val; } inline Type MaxValue() const { return _max; } inline Type MinValue() const { return _min; } inline Type OldValue() const { return _oldval; } inline bool IsFresh() { if(_oldval!=_val) { _oldval=_val; return true; } return false; } inline void DynamicUp(Type basestep=Type(1)) { _DynamicValidator(); assert(basestep>0); if(_laststep!=Up) { if(basestep>=0) { _basestep=basestep; } else { _basestep=-basestep; } _laststep=Up; } else { _Dynamizer(basestep); } operator+=(basestep); } inline void DynamicDown(Type basestep=Type(1)) { _DynamicValidator(); assert(basestep>0); if(_laststep!=Down) { if(basestep>=0) { _basestep=basestep; } else { _basestep=-basestep; } _laststep=Down; } else { _Dynamizer(basestep); } operator-=(basestep); } inline void DynamicTime(double dyntime=0.2) { assert(dyntime>0); _dynamictime=dyntime; } inline void DynamicReset(double dyntime=0.2) { assert(dyntime>0); _dynamictime=dyntime; _laststep=None; _basestep=Type(1); } private: void operator++(int);// forget it - efficiency void operator--(int);// forget it - efficiency inline void _DynamicValidator() { if(_timedstep.GetTime()>_dynamictime) { DynamicReset(); } else if(_lastcommonuser!=this) { DynamicReset(); _lastcommonuser=this; } _timedstep.SetZeroTime(); } inline void _Dynamizer(Type basestep) { _basestep+=basestep; if(_basestep>0) { _basestep=0; } const Type max_basestep=(_max-_min)/16+1; if(_basestep _times; int _iteration; int _max_iterations; double _clock_duration; clock_t _lastclock; // double _start_time; public: inline explicit TimePredictor(int max_iterations) : _times(max_iterations), _iteration(0), _max_iterations(max_iterations), _clock_duration(1.0/CLOCKS_PER_SEC), _lastclock(L3CLOCK())/*, _start_time(_lastclock*_clock_duration)*/ { assert(_lastclock!=static_cast(-1)); } inline void Update() { _times[_iteration]=_clock_duration*static_cast((L3CLOCK()-_lastclock)); _lastclock=L3CLOCK(); assert(_lastclock!=static_cast(-1)); _iteration++; } inline double LastEntryBasedPrediction() const { assert(_iteration>0); return _times[_iteration-1]*(_max_iterations-_iteration); } inline double AverageEntryBasedPrediction() const { assert(_iteration>0); double avg=0; for(int i=0; i<_iteration; i++) { avg+=_times[i]; } if(_iteration>0) { avg/=_iteration; } return avg*(_max_iterations-_iteration); } inline double WorstCasePrediction() const { assert(_iteration>0); double max=_times[0]; for(int i=1; i<_iteration; i++) { if(_times[i]>max) { max=_times[i]; } } return max*(_max_iterations-_iteration); } }; ///////////////////////////////////////////////////////////////////////////// #endif //_INCLUDED_L3_TIME_H