Library: RandomDraw - adaptor and mapping functions
...the beautiful thing with functions and Metaprogramming is: it mostly works as designed out of the box, once you make it past the Compiler.
This commit is contained in:
parent
2578df7c1d
commit
75cbfa8991
3 changed files with 214 additions and 45 deletions
|
|
@ -162,7 +162,8 @@ namespace lib {
|
|||
class RandomDraw
|
||||
: public POL
|
||||
{
|
||||
using Fun = typename _Fun<POL>::Functor;
|
||||
using Sig = typename _Fun<POL>::Sig;
|
||||
using Fun = function<Sig>;
|
||||
using Tar = typename _Fun<POL>::Ret;
|
||||
|
||||
Tar maxResult_{Tar::maxVal()}; ///< maximum result val actually to produce < max
|
||||
|
|
@ -185,6 +186,8 @@ namespace lib {
|
|||
double q = (1.0 - probability_);
|
||||
if (val < q) // control probability of values ≠ neutral
|
||||
return Tar::zeroVal();
|
||||
if (val > 1.0)
|
||||
val = 1.0;
|
||||
val -= q; // [0 .. [q .. 1[
|
||||
val /= probability_; // [0 .. 1[
|
||||
auto org = Tar::zeroVal();
|
||||
|
|
@ -239,7 +242,7 @@ namespace lib {
|
|||
* Drawing is _disabled_ by default, always yielding "zero"
|
||||
*/
|
||||
RandomDraw()
|
||||
: Fun{adaptOut(POL::defaultSrc)}
|
||||
: POL{adaptOut(POL::defaultSrc)}
|
||||
{ }
|
||||
|
||||
/**
|
||||
|
|
@ -254,8 +257,8 @@ namespace lib {
|
|||
*/
|
||||
template<class FUN>
|
||||
RandomDraw(FUN&& fun)
|
||||
: probability_{1.0}
|
||||
, Fun{adaptOut(adaptIn(std::forward<FUN> (fun)))}
|
||||
: POL{adaptOut(adaptIn(std::forward<FUN> (fun)))}
|
||||
, probability_{1.0}
|
||||
{ }
|
||||
|
||||
|
||||
|
|
@ -290,7 +293,8 @@ namespace lib {
|
|||
RandomDraw&&
|
||||
mapping (FUN&& fun)
|
||||
{
|
||||
Fun(*this) = adaptOut(adaptIn(std::forward<FUN> (fun)));
|
||||
Fun& thisMapping = static_cast<Fun&> (*this);
|
||||
thisMapping = adaptOut(adaptIn(std::forward<FUN> (fun)));
|
||||
return move (*this);
|
||||
}
|
||||
|
||||
|
|
@ -305,12 +309,19 @@ namespace lib {
|
|||
decltype(auto)
|
||||
adaptIn (FUN&& fun)
|
||||
{
|
||||
static_assert (lib::meta::_Fun<FUN>(), "Need something function-like.");
|
||||
using _Fun = lib::meta::_Fun<FUN>;
|
||||
static_assert (_Fun(), "Need something function-like.");
|
||||
|
||||
using Sig = typename lib::meta::_Fun<FUN>::Sig;
|
||||
using Sig = typename _Fun::Sig;
|
||||
using Args = typename _Fun::Args;
|
||||
using BaseIn = typename lib::meta::_Fun<POL>::Args;
|
||||
using Adaptor = typename POL::template Adaptor<Sig>;
|
||||
|
||||
return Adaptor::build (forward<FUN> (fun));
|
||||
if constexpr (std::is_same_v<Args, BaseIn>)
|
||||
// function accepts same arguments as this RandomDraw
|
||||
return forward<FUN> (fun); // pass-through directly
|
||||
else
|
||||
return Adaptor::build (forward<FUN> (fun));
|
||||
}
|
||||
|
||||
/** @internal adapt output side of a given function, allowing to handle it's results
|
||||
|
|
|
|||
|
|
@ -46,7 +46,9 @@ namespace test{
|
|||
|
||||
|
||||
namespace { // policy and configuration for test...
|
||||
|
||||
|
||||
double ctxParameter = 1.0;
|
||||
|
||||
/**
|
||||
* @note the test uses a rather elaborate result value setting
|
||||
* - produces five distinct values
|
||||
|
|
@ -67,28 +69,34 @@ namespace test{
|
|||
static_assert (not sizeof(SIG), "Unable to adapt given functor.");
|
||||
};
|
||||
|
||||
/** allow a mapping function rely on quantisation cycles */
|
||||
template<typename RES>
|
||||
struct Adaptor<RES(size_t)>
|
||||
{
|
||||
template<typename FUN>
|
||||
static decltype(auto)
|
||||
build (FUN&& fun)
|
||||
{
|
||||
return std::forward<FUN>(fun);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename RES>
|
||||
struct Adaptor<RES(void)>
|
||||
struct Adaptor<RES(uint,uint)>
|
||||
{
|
||||
template<typename FUN>
|
||||
static auto
|
||||
build (FUN&& fun)
|
||||
{
|
||||
return [functor=std::forward<FUN>(fun)]
|
||||
(size_t)
|
||||
(size_t hash)
|
||||
{
|
||||
return functor();
|
||||
return functor(uint(hash/64), uint(hash%64));
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/** inject external contextual state into a mapping function */
|
||||
template<typename RES>
|
||||
struct Adaptor<RES(size_t, double)>
|
||||
{
|
||||
template<typename FUN>
|
||||
static auto
|
||||
build (FUN&& fun)
|
||||
{
|
||||
return [functor=std::forward<FUN>(fun)]
|
||||
(size_t hash)
|
||||
{
|
||||
return functor(hash, ctxParameter);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
@ -123,7 +131,7 @@ namespace test{
|
|||
|
||||
verify_policy();
|
||||
verify_numerics();
|
||||
verify_buildProfile();
|
||||
verify_adaptMapping();
|
||||
verify_dynamicChange();
|
||||
}
|
||||
|
||||
|
|
@ -153,8 +161,8 @@ namespace test{
|
|||
|
||||
|
||||
|
||||
/** @test TODO verify configuration through policy template
|
||||
* @todo WIP 11/23 🔁 define ⟶ 🔁 implement
|
||||
/** @test verify configuration through policy template
|
||||
* @todo WIP 11/23 ✔ define ⟶ ✔ implement
|
||||
*/
|
||||
void
|
||||
verify_policy()
|
||||
|
|
@ -549,13 +557,138 @@ namespace test{
|
|||
|
||||
|
||||
|
||||
/** @test TODO verify the Builder-API to define the profile of result values.
|
||||
* @todo WIP 11/23 🔁 define ⟶ implement
|
||||
/** @test bind custom mapping transformation functions.
|
||||
* - use different translation into positional values as input for the
|
||||
* actual result value mapping
|
||||
* - use a mapping function with different arguments, which is wired
|
||||
* by the appropriate Adapter from the Policy
|
||||
* - moreover, the concrete Policy may tap into the context, which is
|
||||
* demonstrated here by accessing a global variable. In practice,
|
||||
* this capability allows to accept custom types as data source.
|
||||
* @todo WIP 11/23 ✔ define ⟶ ✔ implement
|
||||
*/
|
||||
void
|
||||
verify_buildProfile()
|
||||
verify_adaptMapping()
|
||||
{
|
||||
UNIMPLEMENTED ("verify random number profile configuration");
|
||||
// Note: no special Adapter required for the following function,
|
||||
// since it takes the same arguments as our RandomDraw (size_t);
|
||||
// moreover, since the function yields a double, the adapter scheme
|
||||
// concludes that this function wants to feed directly into the
|
||||
// primary mapping function RandomDraw::limited(double)
|
||||
auto d1 = Draw([](size_t hash) -> double { return hash / 10.0; });
|
||||
CHECK (d1( 0) == +1);
|
||||
CHECK (d1( 1) == +1);
|
||||
CHECK (d1( 2) == +1);
|
||||
CHECK (d1( 3) == +2);
|
||||
CHECK (d1( 4) == +2);
|
||||
CHECK (d1( 5) == -2);
|
||||
CHECK (d1( 6) == -2);
|
||||
CHECK (d1( 7) == -2);
|
||||
CHECK (d1( 8) == -1);
|
||||
CHECK (d1( 9) == -1);
|
||||
CHECK (d1(10) == 0);
|
||||
CHECK (d1(11) == 0);
|
||||
CHECK (d1(12) == 0);
|
||||
CHECK (d1(13) == 0);
|
||||
|
||||
d1.probability(0.4);
|
||||
CHECK (d1( 0) == 0);
|
||||
CHECK (d1( 1) == 0);
|
||||
CHECK (d1( 2) == 0);
|
||||
CHECK (d1( 3) == 0);
|
||||
CHECK (d1( 4) == 0);
|
||||
CHECK (d1( 5) == 0);
|
||||
CHECK (d1( 6) == +1); // probability 0.4
|
||||
CHECK (d1( 7) == +2);
|
||||
CHECK (d1( 8) == -2);
|
||||
CHECK (d1( 9) == -1);
|
||||
CHECK (d1(10) == 0);
|
||||
|
||||
d1.minVal(-1).probability(0.7);
|
||||
CHECK (d1( 0) == 0);
|
||||
CHECK (d1( 1) == 0);
|
||||
CHECK (d1( 2) == 0);
|
||||
CHECK (d1( 3) == 0);
|
||||
CHECK (d1( 4) == +1);
|
||||
CHECK (d1( 5) == +1);
|
||||
CHECK (d1( 6) == +2);
|
||||
CHECK (d1( 7) == +2);
|
||||
CHECK (d1( 8) == -1);
|
||||
CHECK (d1( 9) == -1);
|
||||
CHECK (d1(10) == 0);
|
||||
|
||||
// The next example demonstrates accepting special input arguments;
|
||||
// as defined in the policy, this function will get the `(div, mod)`
|
||||
// of the hash with modulus 64
|
||||
auto d2 = Draw([](uint cycle, uint rem){ return double(rem) / ((cycle+1)*5); });
|
||||
CHECK (d2( 0) == +1);
|
||||
CHECK (d2( 1) == +1);
|
||||
CHECK (d2( 2) == +2);
|
||||
CHECK (d2( 3) == -2);
|
||||
CHECK (d2( 4) == -1); // the first cycle is only 5 steps long (0+1)*5
|
||||
CHECK (d2( 5) == 0);
|
||||
CHECK (d2( 6) == 0);
|
||||
CHECK (d2( 7) == 0);
|
||||
CHECK (d2( 8) == 0);
|
||||
CHECK (d2( 9) == 0);
|
||||
CHECK (d2(10) == 0);
|
||||
CHECK (d2(63) == 0);
|
||||
CHECK (d2(64) == +1); // the second cycle starts here...
|
||||
CHECK (d2(65) == +1);
|
||||
CHECK (d2(66) == +1);
|
||||
CHECK (d2(67) == +2);
|
||||
CHECK (d2(68) == +2);
|
||||
CHECK (d2(69) == -2);
|
||||
CHECK (d2(70) == -2);
|
||||
CHECK (d2(71) == -2);
|
||||
CHECK (d2(72) == -1);
|
||||
CHECK (d2(73) == -1);
|
||||
CHECK (d2(74) == 0); // and is 10 steps long (same pattern as in the first example above)
|
||||
CHECK (d2(75) == 0);
|
||||
|
||||
// The next example uses the other Adapter variant, which „sneaks in“ a context value
|
||||
// Moreover, we can change the mapping function of an existing RandomDraw, as demonstrated here
|
||||
d2.mapping([](size_t hash, double ctx){ return hash / ctx; });
|
||||
|
||||
ctxParameter = 4.0;
|
||||
CHECK (d2( 0) == +1);
|
||||
CHECK (d2( 1) == +2);
|
||||
CHECK (d2( 2) == -2);
|
||||
CHECK (d2( 3) == -1); // cycle-length: 4
|
||||
CHECK (d2( 4) == 0);
|
||||
CHECK (d2( 5) == 0);
|
||||
CHECK (d2( 6) == 0);
|
||||
CHECK (d2( 7) == 0);
|
||||
CHECK (d2( 8) == 0);
|
||||
CHECK (d2( 9) == 0);
|
||||
CHECK (d2(10) == 0);
|
||||
|
||||
ctxParameter = 8.0;
|
||||
CHECK (d2( 0) == +1);
|
||||
CHECK (d2( 1) == +1);
|
||||
CHECK (d2( 2) == +2);
|
||||
CHECK (d2( 3) == +2);
|
||||
CHECK (d2( 4) == -2);
|
||||
CHECK (d2( 5) == -2);
|
||||
CHECK (d2( 6) == -1);
|
||||
CHECK (d2( 7) == -1); // cycle-length: 8
|
||||
CHECK (d2( 8) == 0);
|
||||
CHECK (d2( 9) == 0);
|
||||
CHECK (d2(10) == 0);
|
||||
|
||||
// and can of course dynamically tweak the mapping profile...
|
||||
d2.maxVal(0).probability(0.5);
|
||||
CHECK (d2( 0) == 0);
|
||||
CHECK (d2( 1) == 0);
|
||||
CHECK (d2( 2) == 0);
|
||||
CHECK (d2( 3) == 0);
|
||||
CHECK (d2( 4) == -2); // start here due to probability 0.5
|
||||
CHECK (d2( 5) == -2);
|
||||
CHECK (d2( 6) == -1);
|
||||
CHECK (d2( 7) == -1); // cycle-length: 4
|
||||
CHECK (d2( 8) == 0);
|
||||
CHECK (d2( 9) == 0);
|
||||
CHECK (d2(10) == 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -567,6 +700,30 @@ namespace test{
|
|||
verify_dynamicChange()
|
||||
{
|
||||
UNIMPLEMENTED ("change the generation profile dynamically");
|
||||
SHOW_EXPR(int(d2( 0)));
|
||||
SHOW_EXPR(int(d2( 1)));
|
||||
SHOW_EXPR(int(d2( 2)));
|
||||
SHOW_EXPR(int(d2( 3)));
|
||||
SHOW_EXPR(int(d2( 4)));
|
||||
SHOW_EXPR(int(d2( 5)));
|
||||
SHOW_EXPR(int(d2( 6)));
|
||||
SHOW_EXPR(int(d2( 7)));
|
||||
SHOW_EXPR(int(d2( 8)));
|
||||
SHOW_EXPR(int(d2( 9)));
|
||||
SHOW_EXPR(int(d2(10)));
|
||||
SHOW_EXPR(int(d2(63)));
|
||||
SHOW_EXPR(int(d2(64)));
|
||||
SHOW_EXPR(int(d2(65)));
|
||||
SHOW_EXPR(int(d2(66)));
|
||||
SHOW_EXPR(int(d2(67)));
|
||||
SHOW_EXPR(int(d2(68)));
|
||||
SHOW_EXPR(int(d2(69)));
|
||||
SHOW_EXPR(int(d2(70)));
|
||||
SHOW_EXPR(int(d2(71)));
|
||||
SHOW_EXPR(int(d2(72)));
|
||||
SHOW_EXPR(int(d2(73)));
|
||||
SHOW_EXPR(int(d2(74)));
|
||||
SHOW_EXPR(int(d2(75)));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -96626,8 +96626,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node COLOR="#338800" CREATED="1700491829216" ID="ID_1294373641" MODIFIED="1700502015751" TEXT="den Spec-Subtyp in RandomDraw integrieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700491953800" ID="ID_75649548" MODIFIED="1700515755282" TEXT="Policy-Template einführen">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1700491953800" ID="ID_75649548" MODIFIED="1700623416307" TEXT="Policy-Template einführen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#435e98" CREATED="1700513461881" ID="ID_1696400503" MODIFIED="1700513889095" TEXT="definiert den Basis-Funktionstyp"/>
|
||||
<node COLOR="#435e98" CREATED="1700513505882" ID="ID_1225658406" MODIFIED="1700513889096" TEXT="definiert darüber auch implizit den Ergebnistyp"/>
|
||||
<node COLOR="#435e98" CREATED="1700513474582" ID="ID_1399385360" MODIFIED="1700513889096" TEXT="liefert spezielle Adapter für alle unterstützten Eingangs-Typen"/>
|
||||
|
|
@ -96717,13 +96717,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700542362630" ID="ID_730331755" MODIFIED="1700542375501" TEXT="mit speziellem Test ausleuchten...">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1700542362630" ID="ID_730331755" MODIFIED="1700623412095" TEXT="mit speziellem Test ausleuchten...">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1700542382819" ID="ID_1832228113" MODIFIED="1700574242519" TEXT="eine Policy die zwei Eingangs-Argumente nimmt">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700574245126" ID="ID_1720583823" MODIFIED="1700574258660" TEXT="Adaption von Manipulator-Funktionen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1700574245126" ID="ID_1720583823" MODIFIED="1700623413497" TEXT="Adaption von Manipulator-Funktionen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -96958,21 +96958,22 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700491985219" ID="ID_460437503" MODIFIED="1700577836021" TEXT="Adaptierung restrukturieren">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1700491985219" ID="ID_460437503" MODIFIED="1700623393034" TEXT="Adaptierung restrukturieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700577811739" ID="ID_1356052727" MODIFIED="1700615790193" TEXT="Konfigurations-DSL aufbauen">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1700577811739" ID="ID_1356052727" MODIFIED="1700623391805" TEXT="Konfigurations-DSL aufbauen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#435e98" CREATED="1700615802219" ID="ID_1202526627" MODIFIED="1700615816505" TEXT="probability"/>
|
||||
<node COLOR="#435e98" CREATED="1700615805467" ID="ID_1780693023" MODIFIED="1700615816505" TEXT="maxVal"/>
|
||||
<node COLOR="#435e98" CREATED="1700615809354" ID="ID_664060947" MODIFIED="1700615816506" TEXT="minVal"/>
|
||||
<node CREATED="1700615812738" ID="ID_1089110674" MODIFIED="1700615814517" TEXT="mapping"/>
|
||||
<node COLOR="#435e98" CREATED="1700615812738" ID="ID_1089110674" MODIFIED="1700623389853" TEXT="mapping"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700491877926" ID="ID_1958310493" MODIFIED="1700502021655" TEXT="Test zur Dokumentation">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700491902622" ID="ID_523469259" MODIFIED="1700615927608" TEXT="soll auch das Vorgehen zur Spezialisierung demonstrieren">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1700491902622" ID="ID_523469259" MODIFIED="1700623361146" TEXT="soll auch das Vorgehen zur Spezialisierung demonstrieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1700623368176" ID="ID_1117750034" MODIFIED="1700623381554" TEXT="demonstriert Kontext-Parameter und Adapter"/>
|
||||
<node CREATED="1700615879735" ID="ID_1206033672" MODIFIED="1700615946925" TEXT="verwende schon mal spezielle Ergebniswerte">
|
||||
<arrowlink COLOR="#382e90" DESTINATION="ID_1803348383" ENDARROW="Default" ENDINCLINATION="131;-8;" ID="Arrow_ID_1166708502" STARTARROW="None" STARTINCLINATION="-7;7;"/>
|
||||
</node>
|
||||
|
|
@ -97054,8 +97055,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700501979956" ID="ID_571312425" MODIFIED="1700577970844" TEXT="Wirkung des Builder-API dokumentieren">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1700501979956" ID="ID_571312425" MODIFIED="1700617387689" TEXT="Wirkung des Builder-API dokumentieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700501993218" ID="ID_271630234" MODIFIED="1700577970844" TEXT="dynamische Parametrisierung demonstrieren">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue