allow for fractional scaling of time durations

implemented as extension to the linear combinations.
I decided to use the same "always floor" rule
as employed for time quantisation. Moreover,
we don't support floating point, only rationals
This commit is contained in:
Fischlurch 2012-03-17 00:49:58 +01:00
parent 22322dfec4
commit 9aec2a9806
3 changed files with 51 additions and 7 deletions

View file

@ -23,12 +23,14 @@
#include "lib/time/timevalue.hpp" #include "lib/time/timevalue.hpp"
#include "lib/time.h" #include "lib/time.h"
#include "lib/util-quant.hpp"
#include <limits> #include <limits>
#include <string> #include <string>
#include <boost/rational.hpp> #include <boost/rational.hpp>
using std::string; using std::string;
using util::floordiv;
namespace lib { namespace lib {
@ -122,6 +124,16 @@ namespace time {
} }
Offset
operator* (boost::rational<int64_t> factor, Offset const& o)
{
boost::rational<int64_t> distance (_raw(o));
distance *= factor;
gavl_time_t microTicks = floordiv (distance.numerator(), distance.denominator());
return Offset(TimeValue(microTicks));
}
/** offset by the given number of frames. */ /** offset by the given number of frames. */
Offset::Offset (int64_t count, FrameRate const& fps) Offset::Offset (int64_t count, FrameRate const& fps)
: TimeValue (count? (count<0? -1:+1) * lumiera_framecount_to_time (::abs(count), fps) : TimeValue (count? (count<0? -1:+1) * lumiera_framecount_to_time (::abs(count), fps)

View file

@ -223,6 +223,13 @@ namespace time {
return Offset(distance); return Offset(distance);
} }
template<typename INT>
inline Offset
operator* (Offset const& distance, INT factor)
{
return factor*distance;
}
inline Offset inline Offset
operator* (int factor, Offset const& o) operator* (int factor, Offset const& o)
{ {
@ -231,12 +238,12 @@ namespace time {
return Offset(distance); return Offset(distance);
} }
inline Offset /** stretch offset by a possibly fractional factor */
operator* (Offset const& distance, int factor) Offset
{ operator* (boost::rational<int64_t> factor, Offset const& o);
return factor*distance;
}
/** flip offset direction */
inline Offset inline Offset
Offset::operator- () const Offset::operator- () const
{ {
@ -365,14 +372,16 @@ namespace time {
return Offset(base) + Offset(toAdd); return Offset(base) + Offset(toAdd);
} }
template<typename INT>
inline Offset inline Offset
operator* (int factor, Duration const& dur) operator* (INT factor, Duration const& dur)
{ {
return factor * Offset(dur); return factor * Offset(dur);
} }
template<typename INT>
inline Offset inline Offset
operator* (Duration const& dur, int factor) operator* (Duration const& dur, INT factor)
{ {
return factor*dur; return factor*dur;
} }

View file

@ -76,6 +76,7 @@ namespace test{
buildTimeSpan (ref); buildTimeSpan (ref);
compareTimeSpan (Time(ref)); compareTimeSpan (Time(ref));
relateTimeIntervals (ref); relateTimeIntervals (ref);
verify_fractionalOffset();
} }
@ -286,6 +287,28 @@ namespace test{
} }
void
verify_fractionalOffset ()
{
typedef boost::rational<int64_t> Frac;
Duration three (TimeValue(3)); // three micro seconds
Offset o1 = Frac(1,2) * three;
CHECK (o1 > Time::ZERO);
CHECK (o1 == TimeValue(1)); // bias towards the next lower micro grid position
Offset o2 = -Frac(1,2) * three;
CHECK (o2 < Time::ZERO);
CHECK (o2 == TimeValue(-2));
CHECK (three * Frac(1,2) * 2 != three);
CHECK (three *(Frac(1,2) * 2) == three);
// integral arithmetics is precise,
// but not necessarily exact!
}
void void
buildTimeSpan (TimeValue org) buildTimeSpan (TimeValue org)
{ {