// Author: Jeff Hill, LANL #include #include #include #include #include "epicsStdio.h" #include "cvtFast.h" #include "epicsTime.h" #include "testMain.h" using namespace std; typedef void ( * PTestFunc ) ( const double &, char * pBug, size_t bufSize ); class Test { public: Test (); virtual ~Test (); void execute (); protected: char _pDst[128]; double _srcVal; unsigned short _prec; static unsigned const _nUnrolled = 10; static const unsigned _uSecPerSec = 1000000; static unsigned const _nIterations = 10000; virtual void _target () = 0; void _measure (); Test ( const Test & ); Test & operator = ( Test & ); }; class TestCvtFastDouble : public Test { protected: void _target (); }; class TestSNPrintf : public Test { protected: void _target (); }; Test :: Test () : _srcVal ( 0.0 ), _prec ( 0 ) { } Test :: ~Test () { } void Test :: execute () { static const unsigned lowPrecision = 2; static const unsigned highPrecision = DBL_MANT_DIG; for ( unsigned i = 0; i < 3; i++ ) { double mVal = rand (); mVal /= (RAND_MAX + 1); double fEVal = rand (); fEVal /= (RAND_MAX + 1); fEVal *= DBL_MAX_EXP - DBL_MIN_EXP; fEVal += DBL_MIN_EXP; int eVal = static_cast < int > ( fEVal + 0.5 ); _srcVal = ldexp ( mVal, eVal ); for ( _prec = lowPrecision; _prec <= highPrecision; _prec += 4u ) { _measure (); } _srcVal = rand (); _srcVal /= (RAND_MAX + 1); _srcVal *= 10.0; _srcVal -= 5.0; for ( _prec = lowPrecision; _prec <= highPrecision; _prec += 4u ) { _measure (); } } } void Test :: _measure () { epicsTime beg = epicsTime :: getCurrent (); for ( unsigned i = 0; i < _nIterations; i++ ) { _target (); } epicsTime end = epicsTime :: getCurrent (); double elapsed = end - beg; elapsed /= _nIterations * _nUnrolled; elapsed *= _uSecPerSec; printf ( " %4.4f usec, prec=%i, val=%4.4g, for %s\n", elapsed, _prec, _srcVal, typeid ( *this ).name () ); } void TestCvtFastDouble :: _target () { cvtDoubleToString ( _srcVal, _pDst, _prec ); cvtDoubleToString ( _srcVal, _pDst, _prec ); cvtDoubleToString ( _srcVal, _pDst, _prec ); cvtDoubleToString ( _srcVal, _pDst, _prec ); cvtDoubleToString ( _srcVal, _pDst, _prec ); cvtDoubleToString ( _srcVal, _pDst, _prec ); cvtDoubleToString ( _srcVal, _pDst, _prec ); cvtDoubleToString ( _srcVal, _pDst, _prec ); cvtDoubleToString ( _srcVal, _pDst, _prec ); cvtDoubleToString ( _srcVal, _pDst, _prec ); } void TestSNPrintf :: _target () { epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g", static_cast < int > ( _prec ), _srcVal ); epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g", static_cast < int > ( _prec ), _srcVal ); epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g", static_cast < int > ( _prec ), _srcVal ); epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g", static_cast < int > ( _prec ), _srcVal ); epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g", static_cast < int > ( _prec ), _srcVal ); epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g", static_cast < int > ( _prec ), _srcVal ); epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g", static_cast < int > ( _prec ), _srcVal ); epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g", static_cast < int > ( _prec ), _srcVal ); epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g", static_cast < int > ( _prec ), _srcVal ); epicsSnprintf ( _pDst, sizeof ( _pDst ), "%.*g", static_cast < int > ( _prec ), _srcVal ); } MAIN(cvtFastPerform) { TestCvtFastDouble testCvtFastDouble; TestSNPrintf testSNPrintf; testCvtFastDouble.execute (); testSNPrintf.execute (); return 0; }