diff --git a/tests/vault/gear/test-chain-load-test.cpp b/tests/vault/gear/test-chain-load-test.cpp index d72ef9f1c..0975694f0 100644 --- a/tests/vault/gear/test-chain-load-test.cpp +++ b/tests/vault/gear/test-chain-load-test.cpp @@ -54,8 +54,8 @@ namespace test { namespace { // shorthands and parameters for test... /** shorthand for specific parameters employed by the following tests */ - using ChainLoad32 = TestChainLoad<32,16>; - using Node = ChainLoad32::Node; + using ChainLoad16 = TestChainLoad<16>; + using Node = ChainLoad16::Node; auto isStartNode = [](Node& n){ return isStart(n); }; auto isInnerNode = [](Node& n){ return isInner(n); }; auto isExitNode = [](Node& n){ return isExit(n); }; @@ -106,8 +106,6 @@ namespace test { void verify_Node() { - using Node = TestChainLoad<>::Node; - Node n0; // Default-created empty Node CHECK (n0.hash == 0); CHECK (n0.level == 0); @@ -194,7 +192,7 @@ namespace test { void verify_Topology() { - auto graph = ChainLoad32{} + auto graph = ChainLoad16{32} .buildToplolgy(); CHECK (graph.topLevel() == 31); @@ -249,7 +247,7 @@ namespace test { void showcase_Expansion() { - ChainLoad32 graph; + ChainLoad16 graph{32}; // moderate symmetrical expansion with 40% probability and maximal +2 links graph.expansionRule(graph.rule().probability(0.4).maxVal(2)) @@ -289,7 +287,7 @@ namespace test { // if the generation is allowed to run for longer, // while more constrained in width... - TestChainLoad<256,8> gra_2; + TestChainLoad<8> gra_2{256}; gra_2.expansionRule(gra_2.rule().probability(0.4).maxVal(2).shuffle(23)) .buildToplolgy() // .printTopologyDOT() @@ -319,7 +317,7 @@ namespace test { void showcase_Reduction() { - ChainLoad32 graph; + ChainLoad16 graph{32}; // expand immediately at start and then gradually reduce / join chains graph.expansionRule(graph.rule_atStart(8)) @@ -389,7 +387,7 @@ namespace test { void showcase_SeedChains() { - ChainLoad32 graph; + ChainLoad16 graph{32}; // randomly start new chains, to be carried-on linearly graph.seedingRule(graph.rule().probability(0.2).maxVal(3).shuffle()) @@ -448,7 +446,7 @@ namespace test { void showcase_PruneChains() { - ChainLoad32 graph; + ChainLoad16 graph{32}; // terminate chains randomly graph.pruningRule(graph.rule().probability(0.2)) @@ -589,7 +587,7 @@ namespace test { void showcase_StablePattern() { - TestChainLoad<256> graph; + ChainLoad16 graph{256}; // This example creates a repetitive, non-expanding stable pattern // comprised of four small graph segments, generated interleaved @@ -852,7 +850,7 @@ namespace test { void verify_reseed_recalculate() { - ChainLoad32 graph; + ChainLoad16 graph{32}; graph.expansionRule(graph.rule().probability(0.8).maxVal(1)) .pruningRule(graph.rule().probability(0.6)) .buildToplolgy(); @@ -961,7 +959,7 @@ namespace test { p2.level = 1; e.level = 2; - RandomChainCalcFunctor<32,16> chainJob{nodes[0]}; + RandomChainCalcFunctor<16> chainJob{nodes[0]}; Job job0{chainJob ,chainJob.encodeNodeID(0) ,chainJob.encodeLevel(0)}; diff --git a/tests/vault/gear/test-chain-load.hpp b/tests/vault/gear/test-chain-load.hpp index 7c9b06a09..6d4097f47 100644 --- a/tests/vault/gear/test-chain-load.hpp +++ b/tests/vault/gear/test-chain-load.hpp @@ -155,7 +155,7 @@ namespace test { * @tparam maxFan maximal fan-in/out from a node, also limits maximal parallel strands. * @see TestChainLoad_test */ - template + template class TestChainLoad : util::MoveOnly { @@ -276,33 +276,40 @@ namespace test { private: using NodeTab = typename Node::Tab; - using NodeStorage = std::array; + using NodeIT = lib::RangeIter; - std::unique_ptr nodes_; + std::unique_ptr nodes_; + size_t numNodes_; Rule seedingRule_ {}; Rule expansionRule_{}; Rule reductionRule_{}; Rule pruningRule_ {}; + Node* frontNode() { return &nodes_[0]; } + Node* afterNode() { return &nodes_[numNodes_]; } + Node* backNode() { return &nodes_[numNodes_-1];} + public: - TestChainLoad() - : nodes_{new NodeStorage} - { } + explicit + TestChainLoad(size_t nodeCnt =DEFAULT_SIZ) + : nodes_{new Node[nodeCnt]} + , numNodes_{nodeCnt} + { + REQUIRE (1 < nodeCnt); + } - size_t size() const { return nodes_->size(); } - size_t topLevel() const { return nodes_->back().level; } - size_t getSeed() const { return nodes_->front().hash; } - size_t getHash() const { return nodes_->back().hash; } + size_t size() const { return afterNode() - frontNode(); } + size_t topLevel() const { return unConst(this)->backNode()->level; } + size_t getSeed() const { return unConst(this)->frontNode()->hash; } + size_t getHash() const { return unConst(this)->backNode()->hash; } /////////////////////TODO combine hash of all exit nodes - using NodeIter = decltype(lib::explore (std::declval())); - - NodeIter + auto allNodes() { - return lib::explore (*nodes_); + return lib::explore (NodeIT{frontNode(),afterNode()}); } auto allNodePtr() @@ -311,7 +318,7 @@ namespace test { } /** @return the node's index number, based on its storage location */ - size_t nodeID(Node const* n){ return size_t(n - &nodes_->front()); }; + size_t nodeID(Node const* n){ return n - frontNode(); }; size_t nodeID(Node const& n){ return nodeID (&n); }; @@ -406,7 +413,7 @@ namespace test { NodeTab a,b, // working data for generation *curr{&a}, // the current set of nodes to carry on *next{&b}; // the next set of nodes connected to current - Node* node = &nodes_->front(); + Node* node = frontNode(); size_t level{0}; // transient snapshot of rules (non-copyable, once engaged) @@ -417,7 +424,7 @@ namespace test { // prepare building blocks for the topology generation... auto moreNext = [&]{ return next->size() < maxFan; }; - auto moreNodes = [&]{ return node < &nodes_->back(); }; + auto moreNodes = [&]{ return node < backNode(); }; auto spaceLeft = [&]{ return moreNext() and moreNodes(); }; auto addNode = [&](size_t seed =0) { @@ -480,7 +487,7 @@ namespace test { ENSURE (not next->empty()); ++level; } - ENSURE (node == &nodes_->back()); + ENSURE (node == backNode()); // connect ends of all remaining chains to top-Node node->clear(); node->level = level; @@ -502,7 +509,7 @@ namespace test { TestChainLoad&& setSeed (size_t seed = rand()) { - nodes_->front().hash = seed; + frontNode()->hash = seed; return move(*this); } @@ -611,8 +618,8 @@ namespace test { * and pruning._ The RandomDraw component used to implement those rules provides a builder-DSL * and accepts λ-bindings in various forms to influence mapping of Node hash into result parameters. */ - template - class TestChainLoad::NodeControlBinding + template + class TestChainLoad::NodeControlBinding : public std::function { protected: @@ -631,8 +638,8 @@ namespace test { static double guessHeight (size_t level) - { // heuristic guess, typically too low - double expectedHeight = max (1u, numNodes/maxFan); + { // heuristic guess for a »fully stable state« + double expectedHeight = 2*maxFan; return level / expectedHeight; } @@ -662,7 +669,8 @@ namespace test { }; /** allow rules additionally involving the height of the graph, - * which also represents time. 1.0 refers to (guessed) _full height. */ + * which also represents time. 1.0 refers to _stable state generation,_ + * guessed as height Level ≡ 2·maxFan . */ template struct Adaptor { @@ -879,9 +887,9 @@ namespace test { * - the weight centre of this category members * - the weight centre of according to density */ - template + template inline Statistic - TestChainLoad::computeGraphStatistics() + TestChainLoad::computeGraphStatistics() { auto totalLevels = uint(topLevel()); auto classify = prepareEvaluaions(); @@ -962,9 +970,9 @@ namespace test { * *no reliable indication of subgraphs*. The `SEGS` statistics may be misleading, * since these count only completely severed and restarted graphs. */ - template - inline TestChainLoad&& - TestChainLoad::printTopologyStatistics() + template + inline TestChainLoad&& + TestChainLoad::printTopologyStatistics() { cout << "INDI: cnt frac ∅pS ∅pL ∅pLW γL◆ γLW◆ γL⬙ γLW⬙\n"; _Fmt line{"%4s: %3d %3.0f%% %5.1f %5.2f %4.2f %4.2f %4.2f %4.2f %4.2f\n"}; @@ -1000,11 +1008,11 @@ namespace test { /* ========= Render Job generation and Scheduling ========= */ - template + template class RandomChainCalcFunctor : public NopJobFunctor { - using Node = typename TestChainLoad::Node; + using Node = typename TestChainLoad::Node; public: RandomChainCalcFunctor(Node& startNode) diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index ddaf8016f..966c40164 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -79737,9 +79737,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

⟹ man könnte Argumente encodieren @@ -79763,9 +79761,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

denn damit wäre nicht nur die Segmentation zu erhalten, sondern auch der Play-Prozess-Translator-Record — solange bis kein Job mehr „anrufen“ kann @@ -79783,9 +79779,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

Fazit: nein und YAGNI @@ -99371,9 +99365,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

stattet jede seed-Node sofort mit einem festen Branch-Faktor aus @@ -100350,9 +100342,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

Stand: noch nicht volltändig umgesetzt @@ -100382,9 +100372,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

für den eigentlichen Aufruf genügt ein Node* @@ -100397,9 +100385,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

....und das hängt vom Template-Parameter der TestChainLoad ab (size_t maxFan) @@ -100421,9 +100407,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

weiß ja noch nicht, wie das für ProcNode implementiert wird @@ -100439,9 +100423,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

formal-Logisch entspräche der Node-Index dem srcRef-Parameter @@ -100489,9 +100471,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

also nicht um den gesamten Playback-Prozeß. Es müssen keinerlei Deadline-Planungen gemacht werden; das kommt alles Fix per Test-Setup @@ -100502,9 +100482,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

das könnten Varianten des Test-Setup sein; weiß noch nicht was hier gebraucht wird. Rein intuitiv würde ich erst mal nur nach dem Level vorgehen @@ -100514,9 +100492,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

das paßt doch hervorragend; LevelNr ≡ nominal time @@ -100596,16 +100572,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

wir wissen, daß es keine concurrent Aufrufe geben wird, und auch Allokation stellt kein Problem dar; wir können einfach State im »Test-Rahmen« liegen lassen

- -
+
@@ -100624,6 +100597,218 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + +

+ die Node-Anzahl ist inhaltlich keine Typ-Eigenschaft +

+ +
+ + + +

+ ...sie ist rein aus Bequemlichkeit der Implementierung zum Template-Parameter geworden: ich hab nämlich ein std::array genommen +

+ +
+
+ + + + + + + + + + +

+ aber dann muß er unter zwei Namen auftreten +

+ +
+ + + +

+ ...und zwar, weil ich im Klassen-Scope einen Template-Namen nicht verdecken darf. Leider verteilt sich der Node-bezogene Code zu ziemlich gleichen Teilen auf die Node-Klasse selber, und den umschließenen Scope +

+ +
+ +
+
+ + + + + + + + + + + + +

+ hier ist zwar die maxCapacity festgelegt, aber nur zur Erstellungs-Zeit. Das wäre ja genau, was hier gebraucht wird +

+ +
+
+ + + +
+ + + + + + + + + + + + + + + +

+ weil wir aufbauen auf can_STL_ForEach. +

+
    +
  • + hat nested-type "iterator" +
  • +
  • + hat member-Funktionen begin() und end() +
  • +
+

+ ....außerdem wird dann das Hilfs-Template + StlRange auch noch + initialisiert mit
+ RangeIter{begin(con), end(con} + .... �� +

+ +
+ +
+ + + + + + + + + +

+ ...darauf deuten die Komentare zur Typ-Inferenz hin: +

+

+ "when IT is just a pointer, we use the pointee as value type" +

+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + +

+ Template-Parameter numNodes zurückbauen +

+ +
+ + + + + + + + + + +

+ wird in den Adaptoren verwendet — und die sind statisch +

+ +
+
+
+ + + + + +

+ das war mal eine offensichtlich einfache Idee +

+ +
+
+ + + + + + + + + + + + + +

+ man könnte das anders interpretieren +

+ +
+ + + + + + + + +
+ + + +
+
+
@@ -111121,9 +111306,7 @@ class Something - - - +

Da alignof(char) ≡ 1, ist es gradezu eine »Steilvorlage« für Probleme, wenn man einen Allocation-Buffer per char[] deklariert. GCC macht das nicht (er fängt Allokationen immer an 64bit-Grenzen an), aber grundsätzlich dürfte ein Compiler ein char[] anfangen, wo er grad' lustig ist. Besonders gefährlich, wenn das Array in ein anderes Objekt eingebettet wird. Nur den zuletzt genannten Fall habe ich 2019 abgeklärt; gegen alle sonstigen Schnaps-Ideen gibt es keinen Schutz — es sei denn, man hält sich an die Sprachmittel