Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
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"
22#include "lib/random.hpp"
23#include "lib/util.hpp"
25
26using lumiera::error::LUMIERA_ERROR_BOTTOM_VALUE;
27using util::isnil;
28using lib::rani;
29
30
31
32namespace lib {
33namespace time{
34namespace test{
35
36 namespace {
37
38 const int MAX_FRAMES = 25*500;
39 const int DIRT_GRAIN = 50;
40
41 const FSecs F25(1,25); // duration of one PAL frame
42
43 inline Time
44 secs (int seconds)
45 {
46 return Time(FSecs(seconds));
47 }
48 }
49
50
51
52
53 /****************************************************/
69 class QuantiserBasics_test : public Test
70 {
71
72 virtual void
80
81
82 void
84 {
85 FixedFrameQuantiser fixQ(25);
86
87 int frames = rani(MAX_FRAMES);
88 FSecs dirt = (F25 / (2 + rani(DIRT_GRAIN)));
89
90 Time rawTime = Time(frames*F25) + Duration(dirt);
91
92 CHECK (Time( frames *F25) <= rawTime);
93 CHECK (Time((frames+1)*F25) > rawTime);
94
95 Time quantTime (fixQ.gridLocal (rawTime));
96
97 CHECK (Time(frames*F25) == quantTime);
98 }
99
100
106 {
107 TestQuant (int origin=0)
108 : FixedFrameQuantiser( FrameRate(TimeValue::SCALE, 3 ), TimeValue(origin))
109 { }
110
111 int
112 quant (int testPoint)
113 {
114 TimeVar quantised = this->gridLocal(TimeValue(testPoint));
115 return _raw(quantised);
116 }
117 };
118
119 void
121 {
122 TestQuant q0;
123 TestQuant q1(1);
124
125 CHECK ( 6 == q0.quant(7) );
126 CHECK ( 6 == q0.quant(6) );
127 CHECK ( 3 == q0.quant(5) );
128 CHECK ( 3 == q0.quant(4) );
129 CHECK ( 3 == q0.quant(3) );
130 CHECK ( 0 == q0.quant(2) );
131 CHECK ( 0 == q0.quant(1) );
132 CHECK ( 0 == q0.quant(0) );
133 CHECK (-3 == q0.quant(-1));
134 CHECK (-3 == q0.quant(-2));
135 CHECK (-3 == q0.quant(-3));
136 CHECK (-6 == q0.quant(-4));
137
138 CHECK ( 6 == q1.quant(7) );
139 CHECK ( 3 == q1.quant(6) );
140 CHECK ( 3 == q1.quant(5) );
141 CHECK ( 3 == q1.quant(4) );
142 CHECK ( 0 == q1.quant(3) );
143 CHECK ( 0 == q1.quant(2) );
144 CHECK ( 0 == q1.quant(1) );
145 CHECK (-3 == q1.quant(0) );
146 CHECK (-3 == q1.quant(-1));
147 CHECK (-3 == q1.quant(-2));
148 CHECK (-6 == q1.quant(-3));
149 CHECK (-6 == q1.quant(-4));
150 }
151
152
153 void
155 {
156 // For this test we exploit the limits of the time system
157 Time SUB_MIN{-Duration::MAX};
158 Time SUP_MAX{ Duration::MAX};
159
160 // origin at lower end of the time range
161 FixedFrameQuantiser case1 (1, SUB_MIN);
162 CHECK (secs(0) == case1.gridLocal(SUB_MIN ));
163 CHECK (secs(0) == case1.gridLocal(SUB_MIN +TimeValue(1) ));
164 CHECK (secs(1) == case1.gridLocal(SUB_MIN +secs(1) ));
165 CHECK (SUP_MAX -secs(1) > case1.gridLocal( secs(-1) ));
166 CHECK (SUP_MAX -secs(1) <= case1.gridLocal( secs (0) ));
167 CHECK (SUP_MAX > case1.gridLocal( secs (0) ));
168 CHECK (SUP_MAX > case1.gridLocal( secs(+1) ));
169 CHECK (SUP_MAX > case1.gridLocal( secs(+2) ));
170
171 TimeValue largestPoint = case1.gridLocal(secs (0));
172 CHECK (largestPoint == case1.gridLocal( secs(+1) ));
173 CHECK (largestPoint == case1.gridLocal( secs(+2) ));
174 CHECK (largestPoint < SUP_MAX);
175 CHECK (largestPoint == Offset{secs(1)} * case1.gridPoint(secs(0)));
176
177 // origin at upper end of the time range
178 FixedFrameQuantiser case2 (1, SUP_MAX);
179 CHECK (secs( 0) == case2.gridLocal(SUP_MAX ));
180 CHECK (secs(-1) == case2.gridLocal(SUP_MAX -TimeValue(1) )); // note: next lower frame
181 CHECK (secs(-1) == case2.gridLocal(SUP_MAX -secs(1) )); // i.e. the same as a whole frame down
182 CHECK (SUB_MIN +secs(1) < case2.gridLocal( secs(+2) ));
183 CHECK (SUB_MIN +secs(1) >= case2.gridLocal( secs(+1) ));
184 CHECK (SUB_MIN < case2.gridLocal( secs(+1) ));
185 CHECK (SUB_MIN == case2.gridLocal( secs( 0) )); // note: because of downward truncating,
186 CHECK (SUB_MIN == case2.gridLocal( secs(-1) )); // resulting values will already exceed
187 CHECK (SUB_MIN == case2.gridLocal( secs(-2) )); // allowed range and thus will be clipped
188
189 // use very large frame with size of half the time range
190 Duration hugeFrame(SUP_MAX);
191 FixedFrameQuantiser case3 (hugeFrame);
192 CHECK (SUB_MIN == case3.gridLocal(SUB_MIN ));
193 CHECK (SUB_MIN == case3.gridLocal(SUB_MIN +TimeValue(1) ));
194 CHECK (SUB_MIN == case3.gridLocal( secs(-1) ));
195 CHECK (TimeValue(0) == case3.gridLocal( secs( 0) ));
196 CHECK (TimeValue(0) == case3.gridLocal( secs(+1) ));
197 CHECK (TimeValue(0) == case3.gridLocal(SUP_MAX -TimeValue(1) ));
198 CHECK (SUP_MAX == case3.gridLocal(SUP_MAX ));
199
200 // now displacing this grid by +1sec....
201 FixedFrameQuantiser case4 (hugeFrame, secs(1));
202 CHECK (SUB_MIN == case4.gridLocal(SUB_MIN ));
203 CHECK (SUB_MIN == case4.gridLocal(SUB_MIN +TimeValue(1) )); // clipped...
204 CHECK (SUB_MIN == case4.gridLocal(SUB_MIN +secs(1) )); // but now exact (unclipped)
205 CHECK (SUB_MIN == case4.gridLocal( secs(-1) ));
206 CHECK (SUB_MIN == case4.gridLocal( secs( 0) ));
207 CHECK (TimeValue(0) == case4.gridLocal( secs(+1) )); //.....now exactly the frame number zero
208 CHECK (TimeValue(0) == case4.gridLocal(SUP_MAX -TimeValue(1) ));
209
210
211 // think big...
212 TimeVar excess{SUP_MAX +secs(1)}; // this is a *loophole* to slide by the limitation of Time values
213 CHECK (SUP_MAX < excess);
214 CHECK (Duration{excess} < excess); // ...yet as soon as we construct another entity, the limitation applies
215 CHECK (Duration{excess} == SUP_MAX);
216
217 CHECK (SUP_MAX == case4.gridLocal(excess )); // Thus, more by accident, the next higher grid point can be computed
218
219 CHECK (secs(1) == case4.timeOf(0));
220 CHECK (excess == case4.timeOf(1)); // The same loophole also allows to generate this next higher grid point
221 CHECK (excess == case4.timeOf(2)); // ...while the next after next will limited in computation
222
223 FixedFrameQuantiser broken (Duration::MAX, SUP_MAX); // Can drive this loophole to the extreme...
224 CHECK (secs(0) == broken.timeOf(-1)); // since there is leeway by one order of magnitude
225 CHECK (SUP_MAX == broken.timeOf(0));
226 CHECK (SUP_MAX+SUP_MAX > Duration::MAX);
227 CHECK (SUP_MAX+SUP_MAX == broken.timeOf(1));
228 CHECK (SUP_MAX+SUP_MAX == broken.timeOf(2));
229
230 // frame sizes below the time micro grid get trapped
231 long subAtomic = 2*TimeValue::SCALE; // too small for this universe...
232 VERIFY_ERROR (BOTTOM_VALUE, FixedFrameQuantiser quark(subAtomic) );
233 VERIFY_ERROR (BOTTOM_VALUE, FixedFrameQuantiser quark(Duration (FSecs (1,subAtomic))) );
234 }
235 };
236
237
240
241
242
243}}} // namespace lib::time::test
Duration is the internal Lumiera time metric.
static const Duration MAX
maximum possible temporal extension
Simple stand-alone Quantiser implementation based on a constant sized gird.
FrameCnt gridPoint(TimeValue const &) const override
grid quantisation (alignment).
Offset gridLocal(TimeValue const &) const override
transform into the local time scale grid aligned.
TimeValue timeOf(FrameCnt gridPoint) const override
calculate time value of a grid interval (frame) start point
Framerate specified as frames per second.
Offset measures a distance in time.
basic constant internal time value.
static const raw_time_64 SCALE
Number of micro ticks (µs) per second as basic time scale.
a mutable time value, behaving like a plain number, allowing copy and re-accessing
Lumiera's internal time value datatype.
Helpers typically used while writing tests.
boost::rational< int64_t > FSecs
rational representation of fractional seconds
Implementation namespace for support and library code.
int rani(uint bound=_iBOUND())
Definition random.hpp:135
Test runner and basic definitions for tests.
bool isnil(lib::time::Duration const &dur)
Library functions to support the formation of grid-aligned time values.
Generating (pseudo) random numbers with controlled seed.
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
Test Quantiser allowing to use plain numbers.
A collection of frequently used helper functions to support unit testing.
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...