Library: RandomDraw - introduce policy template

to define this as a generic library component,
any reference to the actual data source moust be extracted
from the body of the implementation and supplied later
at usage site. In the actual case at hand the source
for randomness would be the node hash, and that is
absolutely an internal implementation detail.
This commit is contained in:
Fischlurch 2023-11-20 21:05:18 +01:00
parent 605c1b4a17
commit 651e28bac9
3 changed files with 123 additions and 59 deletions

View file

@ -97,36 +97,53 @@ namespace lib {
};
namespace random_draw { // Policy definitions
/**
* Default policy for RandomDraw: generate limted-range random numbers.
* @tparam max result values will be `uint` in the range `[0 ... max]`
*/
template<uint max>
struct LimitedRandomGenerate
: function<Limited<uint, max>(void)>
{
static double defaultSrc() { return rand()/double(RAND_MAX); }
};
}//(End)Policy definitions
/**
* A component and builder to draw limited parameter values
* based on some source of randomness (or hash input).
* Effectively this is a function which "draws" on invocation.
* @tparam POL configuration policy baseclass
*/
template<typename T, T max>
template<class POL>
class RandomDraw
: public function<Limited<T,max>(size_t)>
: public POL
{
using Lim = Limited<T,max>;
using Fun = function<Lim(size_t)>;
using Fun = typename _Fun<POL>::Functor;
using Tar = typename _Fun<POL>::Ret;
T maxResult_{Lim::maxVal()}; ///< maximum parameter val actually to produce < max
Tar maxResult_{Tar::maxVal()}; ///< maximum parameter val actually to produce < max
double probability_{0}; ///< probability that value is in [1 .. m]
/** @internal quantise into limited result value */
Lim
Tar
limited (double val)
{
if (probability_ == 0.0 or val == 0.0)
return Lim{0};
return Tar{0};
double q = (1.0 - probability_);
val -= q; // [0 .. [q .. 1[
val /= probability_; // [0 .. 1[
val *= maxResult_; // [0 .. m[
val += 1; // [1 .. m]
val += CAP_EPSILON; // round down yet absorb dust
return Lim{val};
return Tar{val};
}
static size_t constexpr QUANTISER = 1 << 8;
@ -143,7 +160,7 @@ namespace lib {
public:
/** Drawing is _disabled_ by default, always yielding "zero" */
RandomDraw()
: Fun{[this](size_t hash){ return limited (asRand (hash)); }}
: Fun{adaptOut(POL::defaultSrc)}
{ }
/**
@ -189,53 +206,19 @@ namespace lib {
/**
* @internal helper to expose the signature `size_t(size_t)`
* by wrapping a given lambda or functor.
*/
template<class SIG, typename SEL=void>
struct Adaptor
{
static_assert (not sizeof(SIG), "Unable to adapt given functor.");
};
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)>
{
template<typename FUN>
static auto
build (FUN&& fun)
{
return [functor=std::forward<FUN>(fun)]
(size_t)
{
return functor();
};
}
};
private:
template<class FUN>
decltype(auto)
adaptIn (FUN&& fun)
{
static_assert (lib::meta::_Fun<FUN>(), "Need something function-like.");
static_assert (lib::meta::_Fun<FUN>::ARITY <= 1, "Function with zero or one argument expected.");
using Sig = typename lib::meta::_Fun<FUN>::Sig;
using Sig = typename lib::meta::_Fun<FUN>::Sig;
using Adaptor = typename POL::template Adaptor<Sig>;
return Adaptor<Sig>::build (forward<FUN> (fun));
return Adaptor::build (forward<FUN> (fun));
}
template<class FUN>
@ -243,11 +226,10 @@ namespace lib {
adaptOut (FUN&& fun)
{
static_assert (lib::meta::_Fun<FUN>(), "Need something function-like.");
static_assert (lib::meta::_Fun<FUN>::ARITY ==1, "Function with exactly one argument required.");
using Res = typename lib::meta::_Fun<FUN>::Ret;
if constexpr (std::is_same_v<Res, Lim>)
if constexpr (std::is_same_v<Res, Tar>)
return std::forward<FUN>(fun);
else
if constexpr (std::is_same_v<Res, size_t>)
@ -279,8 +261,6 @@ namespace lib {
NOTREACHED("Handle based on return type");
}
private:
};

View file

@ -51,9 +51,52 @@ namespace test{
namespace {
// const Literal THE_END = "all dead and hero got the girl";
struct SymmetricFive
: function<Limited<int, 5,-5>(size_t)>
{
static size_t defaultSrc (size_t hash) { return hash; }
/**
* @internal helper to expose the signature `size_t(size_t)`
* by wrapping a given lambda or functor.
*/
template<class SIG>
struct Adaptor
{
static_assert (not sizeof(SIG), "Unable to adapt given functor.");
};
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)>
{
template<typename FUN>
static auto
build (FUN&& fun)
{
return [functor=std::forward<FUN>(fun)]
(size_t)
{
return functor();
};
}
};
};
}
using Draw = lib::RandomDraw<uint, 10>;
using Draw = RandomDraw<SymmetricFive>;
@ -74,6 +117,7 @@ namespace test{
{
simpleUse();
verify_policy();
verify_numerics();
verify_buildProfile();
verify_dynamicChange();
@ -88,12 +132,30 @@ namespace test{
simpleUse()
{
auto draw = Draw().probability(0.5);
CHECK (draw(0) == 0);
CHECK (draw(127) == 0);
CHECK (draw(128) == 1);
CHECK (draw(141) == 2);
CHECK (draw(255) ==10);
CHECK (draw(256) == 0);
SHOW_EXPR (int(draw(0) ));
SHOW_EXPR (int(draw(127)));
SHOW_EXPR (int(draw(128)));
SHOW_EXPR (int(draw(141)));
SHOW_EXPR (int(draw(255)));
SHOW_EXPR (int(draw(256)));
// CHECK (draw(0) == 0);
// CHECK (draw(127) == 0);
// CHECK (draw(128) == 1);
// CHECK (draw(141) == 2);
// CHECK (draw(255) ==10);
// CHECK (draw(256) == 0);
}
/** @test TODO verify configuration through policy template
* @todo WIP 11/23 🔁 define implement
*/
void
verify_policy()
{
// auto d1 = RandomDraw<random_draw::LimitedRandomGenerate<5>>().probability(1.0);
//SHOW_EXPR (uint(d1()))
}

View file

@ -96626,7 +96626,29 @@ Date:&#160;&#160;&#160;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 CREATED="1700491953800" ID="ID_75649548" MODIFIED="1700491984631" TEXT="Policy-Template einf&#xfc;hren"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700491953800" ID="ID_75649548" MODIFIED="1700515755282" TEXT="Policy-Template einf&#xfc;hren">
<icon BUILTIN="pencil"/>
<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&#xfc;ber auch implizit den Ergebnistyp"/>
<node COLOR="#435e98" CREATED="1700513474582" ID="ID_1399385360" MODIFIED="1700513889096" TEXT="liefert spezielle Adapter f&#xfc;r alle unterst&#xfc;tzten Eingangs-Typen"/>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1700513891593" ID="ID_1527819070" MODIFIED="1700513932582" TEXT="unklar: default-Eingang">
<icon BUILTIN="messagebox_warning"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1700515452147" ID="ID_1797461825" MODIFIED="1700515470815" TEXT="mu&#xdf; ich irgendwo einen Standard-Eingangstyp annehmen?">
<icon BUILTIN="help"/>
</node>
<node CREATED="1700515476582" ID="ID_474690726" MODIFIED="1700515499125" TEXT="im Grunde w&#xfc;rde das gesamte Schema mit beliebigen Eingangs-Signaturen funktionieren">
<icon BUILTIN="idea"/>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1700515519514" ID="ID_1957414628" MODIFIED="1700515559845" TEXT="&#x27f9; dann m&#xfc;&#xdf;te aber die Policy einen Default-Eingang liefern..."/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700515561328" ID="ID_408143188" MODIFIED="1700515586492" TEXT="brauche Funktions-Komposition">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1700515591564" ID="ID_9942626" MODIFIED="1700515612341" TEXT="&#xbb;beliebige Funktion&#xab; kann nicht als Lambda geschrieben werden"/>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1700515624424" ID="ID_124826134" MODIFIED="1700515633951" TEXT="hatte ich da nicht schon mal was...?">
<icon BUILTIN="help"/>
</node>
</node>
</node>
</node>
<node CREATED="1700491985219" ID="ID_460437503" MODIFIED="1700491990343" TEXT="Adaptierung restrukturieren"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700491877926" ID="ID_1958310493" MODIFIED="1700502021655" TEXT="Test zur Dokumentation">