Lumiera  0.pre.03
»edit your freedom«
quantiser-basics-test.cpp
Go to the documentation of this file.
1 /*
2  QuantiserBasics(Test) - a demo quantiser to cover the basic quantiser API
3 
4  Copyright (C)
5  2011, 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 
19 #include "lib/test/run.hpp"
20 #include "lib/test/test-helper.hpp"
21 #include "lib/time/quantiser.hpp"
22 #include "lib/random.hpp"
23 #include "lib/util.hpp"
24 
25 using lumiera::error::LUMIERA_ERROR_BOTTOM_VALUE;
26 using util::isnil;
27 using lib::rani;
28 
29 
30 
31 namespace lib {
32 namespace time{
33 namespace test{
34 
35  namespace {
36 
37  const int MAX_FRAMES = 25*500;
38  const int DIRT_GRAIN = 50;
39 
40  const FSecs F25(1,25); // duration of one PAL frame
41 
42  inline Time
43  secs (int seconds)
44  {
45  return Time(FSecs(seconds));
46  }
47  }
48 
49 
50 
51 
52  /****************************************************/
68  class QuantiserBasics_test : public Test
69  {
70 
71  virtual void
72  run (Arg)
73  {
74  seedRand();
75  checkSimpleQuantisation();
76  coverQuantisationStandardCases();
77  coverQuantisationCornerCases();
78  }
79 
80 
81  void
82  checkSimpleQuantisation ()
83  {
84  FixedFrameQuantiser fixQ(25);
85 
86  int frames = rani(MAX_FRAMES);
87  FSecs dirt = (F25 / (2 + rani(DIRT_GRAIN)));
88 
89  Time rawTime = Time(frames*F25) + Duration(dirt);
90 
91  CHECK (Time( frames *F25) <= rawTime);
92  CHECK (Time((frames+1)*F25) > rawTime);
93 
94  Time quantTime (fixQ.gridLocal (rawTime));
95 
96  CHECK (Time(frames*F25) == quantTime);
97  }
98 
99 
103  struct TestQuant
105  {
106  TestQuant (int origin=0)
108  { }
109 
110  int
111  quant (int testPoint)
112  {
113  TimeVar quantised = this->gridLocal(TimeValue(testPoint));
114  return int(quantised);
115  }
116  };
117 
118  void
119  coverQuantisationStandardCases()
120  {
121  TestQuant q0;
122  TestQuant q1(1);
123 
124  CHECK ( 6 == q0.quant(7) );
125  CHECK ( 6 == q0.quant(6) );
126  CHECK ( 3 == q0.quant(5) );
127  CHECK ( 3 == q0.quant(4) );
128  CHECK ( 3 == q0.quant(3) );
129  CHECK ( 0 == q0.quant(2) );
130  CHECK ( 0 == q0.quant(1) );
131  CHECK ( 0 == q0.quant(0) );
132  CHECK (-3 == q0.quant(-1));
133  CHECK (-3 == q0.quant(-2));
134  CHECK (-3 == q0.quant(-3));
135  CHECK (-6 == q0.quant(-4));
136 
137  CHECK ( 6 == q1.quant(7) );
138  CHECK ( 3 == q1.quant(6) );
139  CHECK ( 3 == q1.quant(5) );
140  CHECK ( 3 == q1.quant(4) );
141  CHECK ( 0 == q1.quant(3) );
142  CHECK ( 0 == q1.quant(2) );
143  CHECK ( 0 == q1.quant(1) );
144  CHECK (-3 == q1.quant(0) );
145  CHECK (-3 == q1.quant(-1));
146  CHECK (-3 == q1.quant(-2));
147  CHECK (-6 == q1.quant(-3));
148  CHECK (-6 == q1.quant(-4));
149  }
150 
151 
152  void
153  coverQuantisationCornerCases()
154  {
155  // origin at lower end of the time range
156  FixedFrameQuantiser case1 (1, Time::MIN);
157  CHECK (secs(0) == case1.gridLocal(Time::MIN ));
158  CHECK (secs(0) == case1.gridLocal(Time::MIN +TimeValue(1) ));
159  CHECK (secs(1) == case1.gridLocal(Time::MIN +secs(1) ));
160  CHECK (Time::MAX -secs(1) > case1.gridLocal( secs(-1) ));
161  CHECK (Time::MAX -secs(1) <= case1.gridLocal( secs (0) ));
162  CHECK (Time::MAX > case1.gridLocal( secs (0) ));
163  CHECK (Time::MAX == case1.gridLocal( secs(+1) ));
164  CHECK (Time::MAX == case1.gridLocal( secs(+2) ));
165 
166  // origin at upper end of the time range
167  FixedFrameQuantiser case2 (1, Time::MAX);
168  CHECK (secs( 0) == case2.gridLocal(Time::MAX ));
169  CHECK (secs(-1) == case2.gridLocal(Time::MAX -TimeValue(1) )); // note: next lower frame
170  CHECK (secs(-1) == case2.gridLocal(Time::MAX -secs(1) )); // i.e. the same as a whole frame down
171  CHECK (Time::MIN +secs(1) < case2.gridLocal( secs(+2) ));
172  CHECK (Time::MIN +secs(1) >= case2.gridLocal( secs(+1) ));
173  CHECK (Time::MIN < case2.gridLocal( secs(+1) ));
174  CHECK (Time::MIN == case2.gridLocal( secs( 0) )); // note: because of downward truncating,
175  CHECK (Time::MIN == case2.gridLocal( secs(-1) )); // resulting values will already exceed
176  CHECK (Time::MIN == case2.gridLocal( secs(-2) )); // allowed range and thus will be clipped
177 
178  // use very large frame with size of half the time range
179  Duration hugeFrame(Time::MAX);
180  FixedFrameQuantiser case3 (hugeFrame);
181  CHECK (Time::MIN == case3.gridLocal(Time::MIN ));
182  CHECK (Time::MIN == case3.gridLocal(Time::MIN +TimeValue(1) ));
183  CHECK (Time::MIN == case3.gridLocal( secs(-1) ));
184  CHECK (TimeValue(0) == case3.gridLocal( secs( 0) ));
185  CHECK (TimeValue(0) == case3.gridLocal( secs(+1) ));
186  CHECK (TimeValue(0) == case3.gridLocal(Time::MAX -TimeValue(1) ));
187  CHECK (Time::MAX == case3.gridLocal(Time::MAX ));
188 
189  // now displacing this grid by +1sec....
190  FixedFrameQuantiser case4 (hugeFrame, secs(1));
191  CHECK (Time::MIN == case4.gridLocal(Time::MIN ));
192  CHECK (Time::MIN == case4.gridLocal(Time::MIN +TimeValue(1) )); // clipped...
193  CHECK (Time::MIN == case4.gridLocal(Time::MIN +secs(1) )); // but now exact (unclipped)
194  CHECK (Time::MIN == case4.gridLocal( secs(-1) ));
195  CHECK (Time::MIN == case4.gridLocal( secs( 0) ));
196  CHECK (TimeValue(0) == case4.gridLocal( secs(+1) )); //.....now exactly the frame number zero
197  CHECK (TimeValue(0) == case4.gridLocal(Time::MAX -TimeValue(1) ));
198  CHECK (TimeValue(0) == case4.gridLocal(Time::MAX )); //.......still truncated down to frame #0
199 
200  // think big...
201  Duration superHuge{secs(12345) + hugeFrame};
202  Duration extraHuge{2*hugeFrame};
203  CHECK (extraHuge == Duration::MAX);
204 
205  // Time::MAX < superHuge < Duration::Max is possible, but we can accommodate only one
206  FixedFrameQuantiser case5 (superHuge);
207  CHECK (TimeValue(0) == case5.gridLocal(Time::MAX ));
208  CHECK (TimeValue(0) == case5.gridLocal(Time::MAX -TimeValue(1) ));
209  CHECK (TimeValue(0) == case5.gridLocal( secs( 1) ));
210  CHECK (TimeValue(0) == case5.gridLocal( secs( 0) ));
211  CHECK (Time::MIN == case5.gridLocal( secs(-1) ));
212  CHECK (Time::MIN == case5.gridLocal(Time::MIN +TimeValue(1) ));
213  CHECK (Time::MIN == case5.gridLocal(Time::MIN ));
214 
215  // now with offset
216  FixedFrameQuantiser case6 (superHuge, Time::MAX-secs(1));
217  CHECK (TimeValue(0) == case6.gridLocal(Time::MAX ));
218  CHECK (TimeValue(0) == case6.gridLocal(Time::MAX -TimeValue(1) ));
219  CHECK (TimeValue(0) == case6.gridLocal(Time::MAX -secs(1) ));
220  CHECK (Time::MIN == case6.gridLocal(Time::MAX -secs(2) ));
221  CHECK (Time::MIN == case6.gridLocal( secs( 1) ));
222  CHECK (Time::MIN == case6.gridLocal( secs(-12345) ));
223  CHECK (Time::MIN == case6.gridLocal( secs(-12345-1) ));
224  CHECK (Time::MIN == case6.gridLocal( secs(-12345-2) )); // this would be one frame lower, but is clipped
225  CHECK (Time::MIN == case6.gridLocal(Time::MIN +TimeValue(1) ));
226  CHECK (Time::MIN == case6.gridLocal(Time::MIN )); // same... unable to represent time points before Time::MIN
227 
228  // maximum frame size is spanning the full time range
229  FixedFrameQuantiser case7 (extraHuge, Time::MIN+secs(1));
230  CHECK (TimeValue(0) == case7.gridLocal(Time::MAX )); // rounded down one frame, i.e. to origin
231  CHECK (TimeValue(0) == case7.gridLocal( secs( 0) ));
232  CHECK (TimeValue(0) == case7.gridLocal(Time::MIN+secs(2) ));
233  CHECK (TimeValue(0) == case7.gridLocal(Time::MIN+secs(1) )); // exactly at origin
234  CHECK (Time::MIN == case7.gridLocal(Time::MIN )); // one frame further down, but clipped to Time::MIN
235 
236  // even larger frames aren't possible
237  Duration not_really_larger(secs(10000) + extraHuge);
238  CHECK (extraHuge == not_really_larger);
239 
240  // frame sizes below the time micro grid get trapped
241  long subAtomic = 2*TimeValue::SCALE; // too small for this universe...
242  VERIFY_ERROR (BOTTOM_VALUE, FixedFrameQuantiser quark(subAtomic) );
243  VERIFY_ERROR (BOTTOM_VALUE, FixedFrameQuantiser quark(Duration (FSecs (1,subAtomic))) );
244  }
245  };
246 
247 
249  LAUNCHER (QuantiserBasics_test, "unit common");
250 
251 
252 
253 }}} // namespace lib::time::test
a mutable time value, behaving like a plain number, allowing copy and re-accessing ...
Definition: timevalue.hpp:232
static const Duration MAX
maximum possible temporal extension
Definition: timevalue.hpp:507
FixedFrameQuantiser(FrameRate const &frames_per_second, TimeValue referencePoint=TimeValue(0))
Create a quantiser based on a fixed constant spaced grid, rooted at the reference point as origin of ...
Definition: quantiser.cpp:75
Definition: run.hpp:40
Framerate specified as frames per second.
Definition: timevalue.hpp:655
static const gavl_time_t SCALE
Number of micro ticks (µs) per second as basic time scale.
Definition: timevalue.hpp:167
int rani(uint bound=_iBOUND())
Definition: random.hpp:135
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
Implementation namespace for support and library code.
Lumiera&#39;s internal time value datatype.
Definition: timevalue.hpp:299
Simplistic test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
TimeValue gridLocal(TimeValue const &) const
transform into the local time scale grid aligned.
Definition: quantiser.cpp:136
boost::rational< int64_t > FSecs
rational representation of fractional seconds
Definition: timevalue.hpp:220
A collection of frequently used helper functions to support unit testing.
Library functions to support the formation of grid-aligned time values.
Generating (pseudo) random numbers with controlled seed.
Duration is the internal Lumiera time metric.
Definition: timevalue.hpp:468
Test Quantiser allowing to use plain numbers.
basic constant internal time value.
Definition: timevalue.hpp:133
static const Time MAX
Definition: timevalue.hpp:309
Simple stand-alone Quantiser implementation based on a constant sized gird.
Definition: quantiser.hpp:135