change the way the Digxel mutator is invoked
this refactoring prepares a change to address the problems with negative extended SMPTE Timecode
This commit is contained in:
parent
14f233f83b
commit
ac9e9a99df
4 changed files with 138 additions and 66 deletions
|
|
@ -195,6 +195,11 @@ namespace time {
|
|||
|
||||
|
||||
|
||||
using std::tr1::bind;
|
||||
using std::tr1::function;
|
||||
using std::tr1::placeholders::_1;
|
||||
|
||||
|
||||
/**
|
||||
* A number element for building structured numeric displays.
|
||||
* The purpose is to represent parts of a numeric format, like
|
||||
|
|
@ -224,23 +229,35 @@ namespace time {
|
|||
FMT buffer_;
|
||||
NUM value_;
|
||||
|
||||
static NUM use_newValue_as_is (NUM n) { return n; }
|
||||
typedef std::tr1::function<NUM(NUM)> _Mutator;
|
||||
typedef Digxel<NUM,FMT> _Digxel;
|
||||
typedef function<void(NUM)> _Mutator;
|
||||
|
||||
|
||||
_Mutator mutator; ///< Functor for setting a new digxel value
|
||||
|
||||
public:
|
||||
/** a functor to be applied on any new digxel value.
|
||||
/** install an external functor to be applied on any new digxel value.
|
||||
* This allows individual instances to limit the possible digxel values,
|
||||
* or to update an compound value (e.g. a time comprised of hour, minute
|
||||
* and second digxel elements). By default, new values can be set without
|
||||
* any restrictions or side effects.
|
||||
* and second digxel elements). The installed functor needs to accept
|
||||
* a "this" pointer and actually perform any desired state change
|
||||
* as sideeffect. The default is to accept any value as-is.
|
||||
* @warning using a mutator creates significant overhead;
|
||||
* measurements indicate a factor of 4
|
||||
* @see Digxel_test
|
||||
*/
|
||||
_Mutator mutator;
|
||||
template<typename FUN, class THIS>
|
||||
void
|
||||
installMutator (FUN mutate, THIS& self)
|
||||
{
|
||||
mutator = bind (mutate, &self, _1 );
|
||||
}
|
||||
|
||||
|
||||
Digxel ()
|
||||
: buffer_()
|
||||
, value_ ()
|
||||
, mutator(use_newValue_as_is)
|
||||
, mutator()
|
||||
{ }
|
||||
|
||||
// using the standard copy operations
|
||||
|
|
@ -262,8 +279,10 @@ namespace time {
|
|||
operator= (NUM n)
|
||||
{
|
||||
if (n == value_) return;
|
||||
NUM changedValue = mutator(n);
|
||||
this->setValueRaw (changedValue);
|
||||
if (mutator)
|
||||
mutator (n);
|
||||
else
|
||||
setValueRaw (n);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -305,24 +324,22 @@ namespace time {
|
|||
class Signum
|
||||
: public Digxel<int,digxel::SignFormatter>
|
||||
{
|
||||
static int
|
||||
just_the_sign (int val)
|
||||
typedef Digxel<int, digxel::SignFormatter> _Par;
|
||||
|
||||
void
|
||||
storeSign (int val)
|
||||
{
|
||||
return val<0? -1:+1;
|
||||
setValueRaw (val<0? -1:+1);
|
||||
}
|
||||
|
||||
public:
|
||||
Signum()
|
||||
{
|
||||
setValueRaw(1);
|
||||
mutator = just_the_sign;
|
||||
installMutator (&Signum::storeSign, *this);
|
||||
}
|
||||
|
||||
void
|
||||
operator= (int n)
|
||||
{
|
||||
this->setValueRaw (mutator(n));
|
||||
}
|
||||
using _Par::operator=;
|
||||
|
||||
friend int operator*= (Signum& s, int c) { s = c*s; return s; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -221,10 +221,10 @@ namespace time {
|
|||
inline void
|
||||
setupComponentNormalisation (SmpteTC * thisTC)
|
||||
{
|
||||
thisTC->hours.mutator = bind (wrapHours, thisTC, _1 );
|
||||
thisTC->mins.mutator = bind (wrapMinutes, thisTC, _1 );
|
||||
thisTC->secs.mutator = bind (wrapSeconds, thisTC, _1 );
|
||||
thisTC->frames.mutator = bind (wrapFrames, thisTC, _1 );
|
||||
// thisTC->hours.mutator = bind (wrapHours, thisTC, _1 );
|
||||
// thisTC->mins.mutator = bind (wrapMinutes, thisTC, _1 );
|
||||
// thisTC->secs.mutator = bind (wrapSeconds, thisTC, _1 );
|
||||
// thisTC->frames.mutator = bind (wrapFrames, thisTC, _1 );
|
||||
}
|
||||
|
||||
}//(End)implementation details
|
||||
|
|
|
|||
|
|
@ -234,8 +234,7 @@ END
|
|||
TEST "A Digxel (numeric component)" Digxel_test <<END
|
||||
out-lit: empty____## +0.0 ##
|
||||
out-lit: value____##-88.8 ##
|
||||
out: without reformatting = .+sec
|
||||
out: with reformatting = .+sec
|
||||
out: timings\(\w+\)....*ns
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
|
|
|||
|
|
@ -27,8 +27,9 @@
|
|||
#include "lib/time/digxel.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
using lumiera::error::LUMIERA_ERROR_ASSERTION;
|
||||
using util::isSameObject;
|
||||
|
|
@ -66,35 +67,6 @@ namespace test{
|
|||
|
||||
/* === special Digxel configuration for this test === */
|
||||
|
||||
double sum(0),
|
||||
checksum(0);
|
||||
|
||||
double
|
||||
sideeffectSum (double val)
|
||||
{
|
||||
sum += val;
|
||||
return val;
|
||||
}
|
||||
|
||||
double preval(0), newval(0);
|
||||
|
||||
double
|
||||
protocollingMutator (double val)
|
||||
{
|
||||
preval = newval;
|
||||
newval = val;
|
||||
return val;
|
||||
}
|
||||
|
||||
double
|
||||
limitingMutator (double value2set)
|
||||
{
|
||||
return (+1 < value2set) ? 1.0
|
||||
: (-1 > value2set) ? -1.0
|
||||
: value2set;
|
||||
}
|
||||
|
||||
|
||||
struct VerySpecialFormat
|
||||
: digxel::PrintfFormatter<double, 11>
|
||||
{
|
||||
|
|
@ -103,6 +75,47 @@ namespace test{
|
|||
|
||||
typedef Digxel<double, VerySpecialFormat> TestDigxel;
|
||||
|
||||
|
||||
double sum(0),
|
||||
checksum(0);
|
||||
|
||||
void
|
||||
sideeffectSum (TestDigxel* digxel, double val)
|
||||
{
|
||||
sum += val;
|
||||
digxel->setValueRaw (val);
|
||||
}
|
||||
|
||||
double preval(0), newval(0);
|
||||
|
||||
void
|
||||
protocollingMutator (TestDigxel* digxel, double val)
|
||||
{
|
||||
preval = newval;
|
||||
newval = val;
|
||||
digxel->setValueRaw (val);
|
||||
}
|
||||
|
||||
void
|
||||
limitingMutator (TestDigxel* digxel, double value2set)
|
||||
{
|
||||
digxel->setValueRaw ((+1 < value2set) ? +1.0
|
||||
: (-1 > value2set) ? -1.0
|
||||
: value2set);
|
||||
}
|
||||
|
||||
void
|
||||
trivialMutator (TestDigxel* digxel, double value2set)
|
||||
{
|
||||
digxel->setValueRaw (value2set);
|
||||
}
|
||||
|
||||
void
|
||||
emptyMutator (TestDigxel*, double)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
}//(End)Test setup
|
||||
|
||||
|
||||
|
|
@ -158,7 +171,7 @@ namespace test{
|
|||
TestDigxel digi;
|
||||
|
||||
// configure what the Digxel does on "mutation"
|
||||
digi.mutator = sideeffectSum;
|
||||
digi.installMutator (sideeffectSum, digi);
|
||||
|
||||
CHECK (0 == digi);
|
||||
sum = checksum = 0;
|
||||
|
|
@ -187,7 +200,7 @@ namespace test{
|
|||
CHECK (12.3 == digi);
|
||||
|
||||
// a special mutator to limit the value
|
||||
digi.mutator = limitingMutator;
|
||||
digi.installMutator (limitingMutator, digi);
|
||||
CHECK (12.3 == digi);
|
||||
digi = 12.3;
|
||||
CHECK (12.3 == digi); // triggered on real change only
|
||||
|
|
@ -215,7 +228,7 @@ namespace test{
|
|||
verifyAssignMutatingOperators ()
|
||||
{
|
||||
TestDigxel digi;
|
||||
digi.mutator = protocollingMutator;
|
||||
digi.installMutator (protocollingMutator, digi);
|
||||
|
||||
digi = 12.3;
|
||||
CHECK ( 0.0 == preval && 12.3 == newval);
|
||||
|
|
@ -312,7 +325,7 @@ namespace test{
|
|||
* we'll take some timings.
|
||||
* @warning the results of such tests could be unreliable,
|
||||
* but in this case here I saw a significant difference,
|
||||
* with values of about 0.1sec / 0.7sec */
|
||||
* with values of about 10ns / 45ns */
|
||||
void
|
||||
verifyDisplayCaching ()
|
||||
{
|
||||
|
|
@ -320,26 +333,69 @@ namespace test{
|
|||
digi = 1;
|
||||
|
||||
clock_t start(0), stop(0);
|
||||
start = clock();
|
||||
boost::format resultDisplay("timings(%s)%|36T.|%4.0fns\n");
|
||||
|
||||
#define START_TIMINGS start=clock();
|
||||
#define DISPLAY_TIMINGS(ID)\
|
||||
stop = clock(); \
|
||||
uint ID = stop-start;\
|
||||
cout << resultDisplay % STRINGIFY (ID) % (double(ID)/CLOCKS_PER_SEC/TIMING_CNT*1e9) ;
|
||||
|
||||
|
||||
START_TIMINGS
|
||||
for (uint i=0; i < TIMING_CNT; ++i)
|
||||
{
|
||||
isOdd (i);
|
||||
}
|
||||
DISPLAY_TIMINGS (empty_loop)
|
||||
|
||||
|
||||
START_TIMINGS
|
||||
for (uint i=0; i < TIMING_CNT; ++i)
|
||||
{
|
||||
digi = 1;
|
||||
isOdd (i);
|
||||
}
|
||||
stop = clock();
|
||||
uint without_reformatting = stop - start;
|
||||
DISPLAY_TIMINGS (without_reformatting)
|
||||
|
||||
|
||||
start = clock();
|
||||
START_TIMINGS
|
||||
for (uint i=0; i < TIMING_CNT; ++i)
|
||||
{
|
||||
digi = isOdd (i);
|
||||
}
|
||||
stop = clock();
|
||||
uint with_reformatting = stop - start;
|
||||
DISPLAY_TIMINGS (with_reformatting)
|
||||
|
||||
|
||||
digi.installMutator (emptyMutator, digi);
|
||||
|
||||
START_TIMINGS
|
||||
for (uint i=0; i < TIMING_CNT; ++i)
|
||||
{
|
||||
digi = isOdd (i);
|
||||
}
|
||||
DISPLAY_TIMINGS (with_empty_mutator)
|
||||
|
||||
|
||||
digi.installMutator (trivialMutator, digi);
|
||||
|
||||
START_TIMINGS
|
||||
for (uint i=0; i < TIMING_CNT; ++i)
|
||||
{
|
||||
digi = isOdd (i);
|
||||
}
|
||||
DISPLAY_TIMINGS (with_trivial_mutator)
|
||||
|
||||
|
||||
digi.installMutator (&TestDigxel::setValueRaw, digi);
|
||||
|
||||
START_TIMINGS
|
||||
for (uint i=0; i < TIMING_CNT; ++i)
|
||||
{
|
||||
digi = isOdd (i);
|
||||
}
|
||||
DISPLAY_TIMINGS (with_memfun_mutator)
|
||||
|
||||
cout << "without reformatting = "<< double(without_reformatting)/CLOCKS_PER_SEC <<"sec"<< endl;
|
||||
cout << "with reformatting = "<< double(with_reformatting )/CLOCKS_PER_SEC <<"sec"<< endl;
|
||||
|
||||
CHECK (without_reformatting < with_reformatting);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue