crafting a integer scale wrapping util, for timecode conversions

This commit is contained in:
Fischlurch 2011-01-20 13:21:14 +01:00
parent e1c025778b
commit 05383ea44a
7 changed files with 218 additions and 39 deletions

View file

@ -85,7 +85,7 @@ extern "C" { /* ===================== C interface ======================== */
#endif
#define NTSC_DROP_FRAME_FPS 29.97
/* TODO: replace this by lib/time/FrameRate::NTSC */
/* TODO: replace this by lib::time::FrameRate::NTSC */
/**
* Formats a time value in H:MM:SS.mmm format into a temporary buffer.

View file

@ -255,6 +255,7 @@ namespace time {
void
operator= (NUM n)
{
if (n == value_) return;
NUM changedValue = mutator(n);
this->setValueRaw (changedValue);
}

View file

@ -59,8 +59,9 @@ namespace time {
}
/** build up a frame count
* by quantising the given time value
/** build up a SMPTE timecode
* by quantising the given time value and then splitting it
* into hours, minutes, seconds and frame offset
*/
void
Smpte::rebuild (SmpteTC& tc, QuantR quantiser, TimeValue const& rawTime)
@ -69,7 +70,8 @@ namespace time {
UNIMPLEMENTED("build smpte components from raw time");
}
/** calculate the time point denoted by this frame count */
/** calculate the time point denoted by this SMPTE timecode,
* by summing up the timecode's components */
TimeValue
Smpte::evaluate (SmpteTC const& tc, QuantR quantiser)
{
@ -79,6 +81,38 @@ namespace time {
}
namespace { // Timecode implementation details
int
wrapFrames (SmpteTC& thisTC, int rawFrames)
{
int fps = 25; ////////////////////////////////TODO outch
thisTC.secs += rawFrames / fps;
return rawFrames % fps;
//////////////////////////////////TODO need floorwrap-util
}
int
wrapSeconds (SmpteTC& thisTC, int rawSecs)
{
}
int
wrapMinutes (SmpteTC& thisTC, int rawMins)
{
}
int
wrapHours (SmpteTC& thisTC, int rawHours)
{
}
}//(End)implementation details
/** */

View file

@ -17,6 +17,7 @@
// 1/10 - can we determine at compile time the presence of a certain function (for duck-typing)?
// 4/10 - pretty printing STL containers with python enabled GDB?
// 1/11 - exploring numeric limits
// 1/11 - integer floor and wrap operation(s)
//#include <nobug.h>
@ -38,31 +39,24 @@ using std::string;
using std::cout;
using std::endl;
long
floordiv (long num, long den)
{
if (0 < (num^den))
return num/den;
else
{
ldiv_t res = ldiv(num,den);
return (res.rem)? res.quot-1
: res.quot;
}
}
long
floordiv2 (long num, long den)
{
ldiv_t res = ldiv(num,den);
return (0 >= res.quot && res.rem)? res.quot-1
: res.quot;
}
div_t
floorwrap (int num, int den)
{
div_t res = div (num,den);
if (0 > (num^den) && res.rem)
{ // wrap similar to floor()
--res.quot;
res.rem = den - (-res.rem);
}
return res;
}
void
checkDiv(int lhs, int rhs)
{
cout << format ("%f / %f = %f \tfloor=%f floordiv=%f \n") % lhs % rhs % (lhs / rhs) % floor(double(lhs)/rhs) % floordiv2(lhs,rhs);
div_t wrap = floorwrap(lhs,rhs);
cout << format ("%2d / %2d = %2d %% = % d \tfloor=%6.2f wrap = (%2d, %2d) \n")
% lhs % rhs % (lhs/rhs) % (lhs%rhs) % floor(double(lhs)/rhs) % wrap.quot % wrap.rem;
}
int
@ -87,17 +81,6 @@ main (int, char**)
checkDiv (-1,4);
checkDiv (-1,-4);
int64_t muks = std::numeric_limits<int64_t>::max();
muks /= 30;
double murks(muks);
cout << format("%f // %f || %g \n") % muks % murks % std::numeric_limits<double>::epsilon();
int64_t glucks = murks;
cout << glucks <<endl;
cout << "\n.gulp.\n";
return 0;

View file

@ -1094,6 +1094,36 @@ return: 0
END
PLANNED "integer scale wrapping utility" UtilFloorwrap_test <<END
out-lit: 12 / 4 = 3 % = 0 floor= 3.0 wrap = ( 3, 0)
out-lit: 11 / 4 = 2 % = 3 floor= 2.0 wrap = ( 2, 3)
out-lit: 10 / 4 = 2 % = 2 floor= 2.0 wrap = ( 2, 2)
out-lit: 9 / 4 = 2 % = 1 floor= 2.0 wrap = ( 2, 1)
out-lit: 8 / 4 = 2 % = 0 floor= 2.0 wrap = ( 2, 0)
out-lit: 7 / 4 = 1 % = 3 floor= 1.0 wrap = ( 1, 3)
out-lit: 6 / 4 = 1 % = 2 floor= 1.0 wrap = ( 1, 2)
out-lit: 5 / 4 = 1 % = 1 floor= 1.0 wrap = ( 1, 1)
out-lit: 4 / 4 = 1 % = 0 floor= 1.0 wrap = ( 1, 0)
out-lit: 3 / 4 = 0 % = 3 floor= 0.0 wrap = ( 0, 3)
out-lit: 2 / 4 = 0 % = 2 floor= 0.0 wrap = ( 0, 2)
out-lit: 1 / 4 = 0 % = 1 floor= 0.0 wrap = ( 0, 1)
out-lit: 0 / 4 = 0 % = 0 floor= 0.0 wrap = ( 0, 0)
out-lit: -1 / 4 = 0 % =-1 floor=-1.0 wrap = (-1, 3)
out-lit: -2 / 4 = 0 % =-2 floor=-1.0 wrap = (-1, 2)
out-lit: -3 / 4 = 0 % =-3 floor=-1.0 wrap = (-1, 1)
out-lit: -4 / 4 =-1 % = 0 floor=-1.0 wrap = (-1, 0)
out-lit: -5 / 4 =-1 % =-1 floor=-2.0 wrap = (-2, 3)
out-lit: -6 / 4 =-1 % =-2 floor=-2.0 wrap = (-2, 2)
out-lit: -7 / 4 =-1 % =-3 floor=-2.0 wrap = (-2, 1)
out-lit: -8 / 4 =-2 % = 0 floor=-2.0 wrap = (-2, 0)
out-lit: -9 / 4 =-2 % =-1 floor=-3.0 wrap = (-3, 3)
out-lit:-10 / 4 =-2 % =-2 floor=-3.0 wrap = (-3, 2)
out-lit:-11 / 4 =-2 % =-3 floor=-3.0 wrap = (-3, 1)
out-lit:-12 / 4 =-3 % = 0 floor=-3.0 wrap = (-3, 0)
return: 0
END
TEST "for-each operations" UtilForeach_test 10 <<END
out: ---:check_foreach_plain
out: :10:9:8:7:6:5:4:3:2:1

View file

@ -0,0 +1,131 @@
/*
UtilFloorwrap(Test) - verify integer scale remainder wrapping
Copyright (C) Lumiera.org
2011, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
#include "lib/test/run.hpp"
#include "lib/util.hpp"
#include <cmath>
//#include <vector>
#include <iostream>
#include <boost/format.hpp>
using ::Test;
using std::cout;
//using std::rand;
using boost::format;
namespace util {
namespace test {
namespace{ // Test data and operations
div_t
floorwrap (int num, int den)
{
div_t res = div (num,den);
if (0 > (num^den) && res.rem)
{ // wrap similar to floor()
--res.quot;
res.rem = den - (-res.rem);
}
return res;
}
void
showWrap (int val, int scale)
{
div_t wrap = floorwrap(val,scale);
cout << format ("% 3d /% 1d =% 1d %% =% d floor=% 4.1f wrap = (%2d,%2d) \n")
% val % scale % (val/scale)
% (val%scale) % floor(double(val)/scale)
% wrap.quot % wrap.rem;
}
} // (End) test data and operations
/**********************************************************************
* @test Evaluate a custom built integer floor function.
* This function is crucial for Lumiera's rule of quantisation
* of time values into frame intervals. This rule requires time
* points to be rounded towards the next lower frame border always,
* irrespective of the relation to the actual time origin.
* Contrast this to the built-in integer division operator, which
* truncates towards zero.
*
* @note if invoked with an non empty parameter, this test performs
* some interesting timing comparisons, which initially were
* used to tweak the implementation a bit.
* @see util.hpp
* @see QuantiserBasics_test
*/
class UtilFloorwrap_test : public Test
{
virtual void
run (Arg arg)
{
showWrap ( 12,4);
showWrap ( 11,4);
showWrap ( 10,4);
showWrap ( 9,4);
showWrap ( 8,4);
showWrap ( 7,4);
showWrap ( 6,4);
showWrap ( 5,4);
showWrap ( 4,4);
showWrap ( 3,4);
showWrap ( 2,4);
showWrap ( 1,4);
showWrap ( 0,4);
showWrap (- 1,4);
showWrap (- 2,4);
showWrap (- 3,4);
showWrap (- 4,4);
showWrap (- 5,4);
showWrap (- 6,4);
showWrap (- 7,4);
showWrap (- 8,4);
showWrap (- 9,4);
showWrap (-10,4);
showWrap (-11,4);
showWrap (-12,4);
}
};
LAUNCHER (UtilFloorwrap_test, "unit common");
}} // namespace util::test

View file

@ -6746,7 +6746,7 @@ Question is: how fine grained and configurable needs this to be?
</pre>
</div>
<div title="TimecodeFormat" modifier="Ichthyostega" modified="201101151404" created="201101100308" tags="Player spec discuss draft" changecount="17">
<div title="TimecodeFormat" modifier="Ichthyostega" modified="201101190857" created="201101100308" tags="Player spec discuss draft" changecount="18">
<pre>The handling of [[Timecode]] is closely related to [[time representation and quantisation|TimeQuant]]. In fact, these two topics blend into one another. Time will be quantised into a //grid,// but this grid only makes sense when linked to a externally relevant meaning and representation, which is the Timecode. But a timecode value also denotes a specific point in time -- performing operations on a timecode is equivalent to manipulating a quantised time value.
!Problem of dependencies
@ -6771,9 +6771,9 @@ And last but not least, it is possible to get a new ~TimeValue, reflecting the c
!!{{red{WIP 1/11}}}design tasks
* @@color:green;✔@@ find out about the connection to the MetaAsset &amp;rarr; [[Advice]]
* @@color:green;✔@@ determine the primitives which need to be on the //effective quantiser API.//
* find out how a format can address the individual components it's comprised of
* @@color:green;✔@@ find out how a format can address the individual components it's comprised of &amp;rarr; direct access by concrete type
* @@color:green;✔@@ decide how a concrete TC value can refer to his quantiser &amp;rarr; always using smart-ptr
* maybe coin a //value handle// -- to tie the three required parts together
* @@color:red;??@@ maybe coin a //value handle// -- to tie the three required parts together
</pre>
</div>
<div title="Timeline" modifier="Ichthyostega" modified="201011220126" created="200706250721" tags="def" changecount="21">