Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
timevalue.hpp
Go to the documentation of this file.
1/*
2 TIMEVALUE.hpp - basic definitions for time values and time intervals
3
4 Copyright (C)
5 2010, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12*/
13
95#ifndef LIB_TIME_TIMEVALUE_H
96#define LIB_TIME_TIMEVALUE_H
97
98#include "lib/error.hpp"
99
100#include <boost/operators.hpp>
101#include <boost/rational.hpp>
102#include <compare>
103#include <cstdlib>
104#include <string>
105
106
107namespace lib {
108namespace time {
109
110 namespace error = lumiera::error;
111
112 // forwards...
113 class FrameRate;
114 class Duration;
115 class TimeSpan;
116 class Mutation;
117
118
127 using raw_time_64 = int64_t;
128
129
143 {
144 protected:
148
149
152 TimeValue&
154 {
155 t_ = o.t_;
156 return *this;
157 }
158
160 friend class Mutation;
161
165 static raw_time_64 limitedDelta (raw_time_64 origin, raw_time_64 target);
166
168 TimeValue (TimeValue const& origin, TimeValue const& target)
169 : t_{limitedDelta (origin.t_, target.t_)}
170 { }
171
172 public:
174 static const raw_time_64 SCALE;
175
176
177 explicit
179 : t_{limitedTime (val)}
180 { }
181
184 : t_(o.t_)
185 { }
186
188 friend raw_time_64 _raw (TimeValue const& time) { return time.t_; }
189 friend HashVal hash_value (TimeValue const&);
191
193 explicit operator std::string() const;
194
196 bool isRegular() const;
197
198 // Supporting strong total ordering
199 std::strong_ordering operator<=> (TimeValue const&) const =default;
200 bool operator== (TimeValue const&) const =default;
201
202 std::strong_ordering operator<=> (raw_time_64 tt) const { return t_ <=> tt; }
203 bool operator== (raw_time_64 tt) const { return t_ == tt; }
204 };
205
206
207
208
209
210
211
212 /* ======= specific Time entities ==================== */
213
223 using FrameCnt = int64_t;
224
227 using FSecs = boost::rational<int64_t>;
228
229
230
240 : public TimeValue
241 , boost::additive<TimeVar,
242 boost::additive<TimeVar, TimeValue,
243 boost::multipliable<TimeVar, int>
244 > >
245 {
246 public:
248 : TimeValue(time)
249 { }
250
253 TimeVar (FSecs const&);
254
256 TimeVar (TimeVar const& o)
257 : TimeValue(o)
258 { }
259
260 TimeVar& operator= (TimeVar const&) = default;
262 {
263 *this = TimeVar(o);
264 return *this;
265 }
266
268 operator FSecs() const { return FSecs{t_, TimeValue::SCALE}; }
269
271 TimeVar& operator+= (TimeVar const& tx) { t_ += tx.t_; return *this; }
272 TimeVar& operator-= (TimeVar const& tx) { t_ -= tx.t_; return *this; }
273
275 TimeVar& operator*= (int64_t fact) { t_ *= fact; return *this; }
276
278 TimeVar operator- () const { return TimeVar(*this)*=-1; }
279
280 // baseclass TimeValue is already totally_ordered
281 };
282
283
284
285
286 /**********************************************************/
304 class Time
305 : public TimeValue
306 {
309
311 Time(int);
312
313 public:
314 static const Time MAX ;
315 static const Time MIN ;
316 static const Time ZERO;
317
318 static const Time ANYTIME;
319 static const Time NEVER;
320
321 explicit
322 Time (TimeValue const& val =TimeValue(0))
323 : TimeValue(val)
324 { }
325
326 explicit
327 Time (FSecs const& fractionalSeconds);
328
329 Time (Time const&) = default;
330
331 Time (TimeVar const& calcResult)
332 : TimeValue(calcResult)
333 { }
334
335 Time ( long millis
336 , uint secs
337 , uint mins =0
338 , uint hours=0
339 );
340
342 explicit operator std::string() const;
343
345 TimeVar operator+ (TimeValue const& tval) const { return TimeVar(*this) + tval; }
346 TimeVar operator- (TimeValue const& tval) const { return TimeVar(*this) - tval; }
347 TimeVar operator- () const { return -TimeVar(*this); }
348 };
349
350
351
352
365 class Offset
366 : public TimeValue
367 {
368 protected:
372 Offset&
374 {
376 return *this;
377 }
378
379 public:
380 explicit
381 Offset (TimeValue const& distance =Time::ZERO);
382
383 explicit
384 Offset (FSecs const& delta_in_secs);
385
386 Offset (Offset const&) = default;
387
388 Offset (FrameCnt count, FrameRate const& fps);
389
390 Offset (TimeValue const& origin, TimeValue const& target)
391 : TimeValue{origin, target}
392 { }
393
394 static const Offset ZERO;
395
397 Duration abs() const;
398
401 Offset stretchedByRationalFactor (boost::rational<int64_t>) const;
402 Offset stretchedByFloatFactor (double) const;
403
405 explicit operator std::string() const;
406
407 // Supporting sign flip
408 Offset operator- () const;
409 };
410
411 //-- support linear offset chaining ---------------
412
413 inline Offset
414 operator+ (Offset const& start, Offset const& toChain)
415 {
416 TimeVar distance(start);
417 distance += toChain;
418 return Offset(distance);
419 }
420
421 inline Offset
422 operator- (Offset const& start, Offset const& toSubtract)
423 {
424 TimeVar distance(start);
425 distance -= toSubtract;
426 return Offset(distance);
427 }
428
429 template<typename FAC>
430 inline Offset
431 operator* (Offset const& distance, FAC factor)
432 {
433 return factor*distance;
434 }
435
436 template<typename INT>
437 inline Offset
438 operator* (INT factor, Offset const& o)
439 {
440 TimeVar distance(o);
441 distance *= factor;
442 return Offset(distance);
443 }
444
445 template<typename INTX>
446 inline Offset
447 operator* (boost::rational<INTX> factor, Offset const& offset)
448 {
449 return offset.stretchedByRationalFactor (boost::rational<int64_t>(factor.numerator(), factor.denominator()));
450 }
451
452 inline Offset
453 operator* (double factor, Offset const& offset)
454 {
455 return offset.stretchedByFloatFactor (factor);
456 }
457
458
460 inline Offset
462 {
463 return -1 * (*this);
464 }
465
466
467
468
478 : public TimeValue
479 {
482
483 public:
485 : TimeValue{Time::ZERO}
486 { }
487
488 Duration (Offset const& distance)
489 : TimeValue{buildRaw_(llabs (_raw(distance)))}
490 { }
491
492 explicit
493 Duration (TimeValue const& timeSpec)
494 : Duration{Offset{timeSpec}}
495 { }
496
497 Duration (FSecs const& timeSpan_in_secs)
498 : Duration{Offset{timeSpan_in_secs}}
499 { }
500
503 Duration (FrameCnt count, FrameRate const& fps)
504 : Duration{Offset{count,fps}}
505 { }
506
507 Duration (TimeSpan const& interval);
508
510 : TimeValue{o}
511 {// assuming that negative Duration can not be constructed....
512 REQUIRE (t_ >= 0, "Copy rejected: negative Duration %lu", o.t_);
513 }
514
515 static const Duration NIL;
516 static const Duration MAX ;
517
518 void accept (Mutation const&);
519
520
522 explicit operator std::string() const;
523
525 Offset operator- () const;
526
527 };
528
529 //-- support combining and Durations ---------------
530
531 inline Duration
532 operator+ (Duration const& base, Duration const& toAdd)
533 {
534 return Offset(base) + Offset(toAdd);
535 }
536
537 inline Duration
538 operator- (Duration const& base, Duration const& toRemove)
539 {
540 return base > toRemove? Offset(base) - Offset(toRemove)
542 }
543
544 template<typename NUM>
545 inline Offset
546 operator* (NUM factor, Duration const& dur)
547 {
548 return factor * Offset(dur);
549 }
550
551 template<typename NUM>
552 inline Offset
553 operator* (Duration const& dur, NUM factor)
554 {
555 return factor*dur;
556 }
557
558 inline Offset
560 {
561 return -1 * (*this);
562 }
563
564
565
583 : public Time
584 {
586
587 public:
588 TimeSpan(TimeValue const& start, Duration const& length)
589 : Time(start)
590 , dur_(length)
591 { }
592
593 TimeSpan(TimeValue const& start, FSecs(duration_in_secs))
594 : Time(start)
595 , dur_(duration_in_secs)
596 { }
597
599 : Time(start<=end? start:end)
600 , dur_(Offset(start,end))
601 { }
602
603 TimeSpan(TimeValue const& start, Offset const& reference_distance)
604 : TimeSpan{start, Time{start} + reference_distance}
605 { }
606
609 { }
610
611 TimeSpan conform() const;
612
613 static const TimeSpan ALL;
614
615 Duration&
617 {
618 return dur_;
619 }
620
622 duration() const
623 {
624 return dur_;
625 }
626
627 Time
628 start() const
629 {
630 return *this;
631 }
632
633 Time
634 end() const
635 {
636 return TimeVar(*this) += dur_;
637 }
638
639 bool
640 contains (TimeValue const& tp) const
641 {
642 return *this <= tp
643 and tp < end();
644 }
645
647 void accept (Mutation const&);
648
650 explicit operator std::string() const;
651
653 std::strong_ordering
654 operator<=> (TimeSpan const& ts) const
655 {
656 auto ord{ t_ <=> ts.t_ };
657 return ord != 0? ord
658 : dur_ <=> ts.dur_;
659 }
660 bool operator== (TimeSpan const& ts) const =default;
661 };
662
663
669 : public boost::rational<uint>
670 {
671 public:
672 FrameRate (uint fps) ;
673 FrameRate (uint num, uint denom);
674 FrameRate (size_t count, Duration timeReference);
675 explicit
676 FrameRate (boost::rational<uint> fractionalRate);
677
678 static FrameRate approx(double fps);
679
680 // standard copy acceptable;
681
682 double asDouble() const;
683
684 static const FrameRate PAL;
685 static const FrameRate NTSC;
686 static const FrameRate STEP;
687
688 static const FrameRate HALTED;
689
691 Duration duration() const;
692
694 std::strong_ordering operator<=>(FrameRate const&) const = default;
695
696 explicit operator std::string() const;
697 };
698
700 inline FSecs
702 {
703 return FSecs{ n*rate.denominator(), rate.numerator()};
704 }
705
706
707
708
709 /* == implementations == */
710
711 namespace { // implementation helpers...
712
713 template<typename NUM>
714 inline NUM
716 {
717 if (n == NUM{0})
718 throw error::Logic ("Degenerated frame grid not allowed"
719 , LERR_(BOTTOM_VALUE));
720 return n;
721 }
722
723 inline raw_time_64
725 {
726 return raw > lim? _raw(lim)
727 : -raw > lim? -_raw(lim)
728 : raw;
729 }
730 }//(End) implementation helpers
731
732
733
734
740 inline HashVal
742 {
743 HashVal x = _raw(time); // possibly cap to size of hash
744 const uint width = sizeof(HashVal) * CHAR_BIT;
745 const uint mask = width-1;
746 const uint n = width / 2;
747
748 static_assert (0 < n and n <= mask);
749 return (x<<n) | (x>>((-n)&mask ));
750 }
751
752
759 inline raw_time_64
761 {
762 return symmetricLimit (raw, Time::MAX);
763 }
764
765 inline raw_time_64
767 {
768 if (0 > (origin^target))
769 {// prevent possible numeric wrap
770 origin = symmetricLimit (origin, Duration::MAX);
771 target = symmetricLimit (target, Duration::MAX);
772 }
773 raw_time_64 res = target - origin;
774 return symmetricLimit (res, Duration::MAX);
775 }
776
777 inline TimeSpan
779 {
780 Offset extension{dur_};
781 TimeValue start{_raw(*this)};
782 return Offset{start} + extension > Time::MAX? TimeSpan{Time::MAX-extension, Time::MAX}
783 : TimeSpan{start, extension};
784 }
785
786 inline bool
788 {
789 return Time::MIN < *this
790 and *this < Time::MAX;
791 }
792
793
794 inline
795 TimeVar::TimeVar (FSecs const& fractionalSeconds)
796 : TimeVar{Time(fractionalSeconds)}
797 { }
798
799 inline
800 Offset::Offset (TimeValue const& distance)
801 : TimeValue{buildRaw_(symmetricLimit(_raw(distance)
802 , Duration::MAX))}
803 { }
804
805 inline
806 Duration::Duration (TimeSpan const& interval)
807 : Duration{interval.duration()}
808 { }
809
810 inline
812 : boost::rational<uint> (__ensure_nonzero(fps))
813 { }
814
815 inline
817 : boost::rational<uint> (__ensure_nonzero(num), denom)
818 { }
819
820 inline
821 FrameRate::FrameRate (boost::rational<uint> fractionalRate)
822 : boost::rational<uint> (__ensure_nonzero(fractionalRate))
823 { }
824
825 boost::rational<uint> __framerate_approximation (size_t, Duration);
826 boost::rational<uint> __framerate_approximation (double);
827
828 inline
829 FrameRate::FrameRate (size_t count, Duration timeReference)
830 : FrameRate{__framerate_approximation (count, timeReference)}
831 { }
832
833 inline FrameRate
834 FrameRate::approx (double fps)
835 {
837 }
838
839
840 inline double
842 {
843 return boost::rational_cast<double> (*this);
844 }
845
846 inline Duration
848 {
849 return Duration{*this};
850 }
851
852
853
854}} // lib::time
855
856
857namespace util {
858
859 inline bool
861 {
862 return 0 == dur;
863 }
864
865 // repeated or forward declaration, see meta/util.hpp
866 template<typename X, typename COND>
867 struct StringConv;
868
870 template<>
872 {
873 static std::string
874 invoke (lib::time::FSecs) noexcept;
875 };
876}
877#endif /*LIB_TIME_TIMEVALUE_H*/
static unsigned int rate
Definition alsa.c:33
Duration is the internal Lumiera time metric.
static const Duration MAX
maximum possible temporal extension
Duration(FrameCnt count, FrameRate const &fps)
duration of the given number of frames.
Duration(FSecs const &timeSpan_in_secs)
Offset operator-() const
Supporting backwards use as offset.
Duration(Duration const &o)
Duration(TimeValue const &timeSpec)
static const Duration NIL
constant to indicate "no duration"
Duration & operator=(Duration const &)
direct assignment prohibited
void accept(Mutation const &)
Definition mutation.hpp:122
Duration(Offset const &distance)
Framerate specified as frames per second.
static const FrameRate STEP
1 frame per second
Duration duration() const
duration of one frame
Definition time.cpp:286
static const FrameRate PAL
predefined constant for PAL framerate
std::strong_ordering operator<=>(FrameRate const &) const =default
derive total ordering from base class
static FrameRate approx(double fps)
static const FrameRate NTSC
double asDouble() const
static const FrameRate HALTED
Interface: an opaque change imposed onto some time value.
Definition mutation.hpp:92
Offset measures a distance in time.
Offset stretchedByFloatFactor(double) const
Definition time.cpp:368
Offset(TimeValue const &distance=Time::ZERO)
Offset & operator=(Offset const &o)
generally immutable, but derived classes allow some limited mutation through special API calls
Duration abs() const
interpret the distance given by this offset as a time duration
static const Offset ZERO
Offset operator-() const
flip offset direction
Offset(TimeValue const &origin, TimeValue const &target)
Offset(Offset const &)=default
Offset stretchedByRationalFactor(boost::rational< int64_t >) const
Definition time.cpp:357
A time interval anchored at a specific point in time.
static const TimeSpan ALL
bool contains(TimeValue const &tp) const
TimeSpan(TimeValue const &start, Duration const &length)
Duration duration() const
TimeSpan(TimeValue const &start, FSecs(duration_in_secs))
TimeSpan conform() const
<
Time start() const
TimeSpan(TimeValue const &start, TimeValue const &end)
bool operator==(TimeSpan const &ts) const =default
Duration & duration()
std::strong_ordering operator<=>(TimeSpan const &ts) const
Supporting extended strong total ordering, based on start and interval length.
TimeSpan(TimeValue const &start, Offset const &reference_distance)
basic constant internal time value.
static const raw_time_64 SCALE
Number of micro ticks (µs) per second as basic time scale.
TimeValue & operator=(TimeValue const &o)
Assigning of time values is not allowed, but derived classed might allow that.
std::strong_ordering operator<=>(TimeValue const &) const =default
static raw_time_64 limitedTime(raw_time_64 raw)
explicit limit of allowed time range
static TimeValue buildRaw_(raw_time_64)
Definition time.cpp:268
raw_time_64 t_
the raw (internal) time value used to implement the time types
static raw_time_64 limitedDelta(raw_time_64 origin, raw_time_64 target)
safe calculation of explicitly limited time offset
TimeValue(raw_time_64 val)
friend raw_time_64 _raw(TimeValue const &time)
TimeValue(TimeValue const &o)
copy initialisation allowed
bool operator==(TimeValue const &) const =default
TimeValue(TimeValue const &origin, TimeValue const &target)
friend HashVal hash_value(TimeValue const &)
derive a hash from the µ-tick value
bool isRegular() const
a mutable time value, behaving like a plain number, allowing copy and re-accessing
TimeVar & operator=(TimeVar const &)=default
TimeVar & operator-=(TimeVar const &tx)
TimeVar(TimeValue const &time=TimeValue(0))
TimeVar(TimeVar const &o)
Allowing copy and assignment.
TimeVar & operator*=(int64_t fact)
Supporting multiplication with integral factor.
TimeVar operator-() const
Supporting sign flip.
TimeVar & operator+=(TimeVar const &tx)
Supporting additive.
Lumiera's internal time value datatype.
static const Time NEVER
border condition marker value. NEVER >= any time value
TimeVar operator+(TimeValue const &tval) const
convenience start for time calculations
static const Time MIN
static const Time ANYTIME
border condition marker value. ANYTIME <= any time value
Time & operator=(Time const)
direct assignment prohibited
Time(Time const &)=default
Time(TimeValue const &val=TimeValue(0))
static const Time ZERO
TimeVar operator-() const
static const Time MAX
Time(TimeVar const &calcResult)
Time(int)
suppress possible direct conversions
Lumiera error handling (C++ interface).
#define LERR_(_NAME_)
Definition error.hpp:45
unsigned int uint
Definition integral.hpp:29
int64_t FrameCnt
Definition job.h:80
raw_time_64 symmetricLimit(raw_time_64 raw, TimeValue lim)
HashVal hash_value(TimeValue const &time)
derive a hash from the µ-tick value
int64_t FrameCnt
relative framecount or frame number.
Definition digxel.hpp:310
FSecs operator/(int n, FrameRate rate)
convenient conversion to duration in fractional seconds
Offset operator+(Offset const &start, Offset const &toChain)
int64_t raw_time_64
Raw µ-tick time representation used in Lumiera.
Offset operator*(Offset const &distance, FAC factor)
Offset operator-(Offset const &start, Offset const &toSubtract)
boost::rational< int64_t > FSecs
rational representation of fractional seconds
boost::rational< uint > __framerate_approximation(double fps)
Definition time.cpp:309
Implementation namespace for support and library code.
size_t HashVal
a STL compatible hash value
Definition hash-value.h:52
LumieraError< LERR_(LOGIC)> Logic
Definition error.hpp:207
bool isnil(lib::time::Duration const &dur)
failsafe invocation of custom string conversion.
static std::string invoke(X const &x) noexcept
#define MAX(A, B)
the inevitable MAX macro, sometimes still necessary in template code
Definition util.hpp:518