From c3c103e1a9ae4e1ad0725c775da64b29a1e2e9ba Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 11 Sep 2026 23:22:03 +0200 Subject: [PATCH] Parameters: mark out the base operations of a Scale Scales are defined as descriptor records and will be used as const. Besides some information functions, a Scale * allows to conform a value to be compliant with the Scale's constraints * can ''join'' and thus apply a ''feed'' on top of a ''base value''; this is the foundation for applying an automation function, while handling multiplicative and logarithmic cases properly --- src/lib/allocation-cluster.hpp | 4 +- src/lib/par/scale.hpp | 88 +++++++++++++++++++++++++- tests/lib/par/parameter-scale-test.cpp | 15 +++-- wiki/thinkPad.ichthyo.mm | 81 +++++++++++++++++------- 4 files changed, 157 insertions(+), 31 deletions(-) diff --git a/src/lib/allocation-cluster.hpp b/src/lib/allocation-cluster.hpp index 6734a224b..4e591039a 100644 --- a/src/lib/allocation-cluster.hpp +++ b/src/lib/allocation-cluster.hpp @@ -27,9 +27,9 @@ ** mostly at start and then hold and use the memory, the allocation is never ** actually _closed_ — implying that further allocations can be added during ** the whole life time, which may possibly even trigger a further base allocation - ** if storage space in the last Extent is exhausted. In theory, it would be possible + ** if storage space if the last Extent is exhausted. In theory, it would be possible ** to use a custom allocation (in the AllocationCluster::StorageManager::Extents, - ** which is a lib::LinkedElements and could be parametrised with a allocator template). + ** which is a lib::LinkedElements and could be parametrised with an allocator template). ** Allocations are never discarded, and thus any alloted memory will be kept until ** the whole AllocationCluster is destroyed as a compound. ** \par using as STL allocator diff --git a/src/lib/par/scale.hpp b/src/lib/par/scale.hpp index bb219c76e..aaa12fe60 100644 --- a/src/lib/par/scale.hpp +++ b/src/lib/par/scale.hpp @@ -63,12 +63,98 @@ namespace par { optional minUse{}; optional maxUse{}; optional neutral{}; - optional defaultVal{}; + optional defVal{}; /////////////////////////////OOO »Sentinels« and nominal scales? bool zyclic{false}; + + /* ===== information functions ===== */ + + bool isValid() const; + + /* ===== conforming operations ===== */ + + VAL conform (VAL const&) const; + + template + VAL join (VAL const&, SRC const&, Scale const&) const; + VAL join (VAL const&, VAL const&) const; }; + /* ===== information functions ===== */ + + /** self consistency check */ + template + inline bool + Scale::isValid() const + { + return ((not minVal or not maxVal) + or *minVal <= *maxVal + ) + and (not minUse + or (not minVal or *minVal <= *minUse) + ) + and (not maxUse + or (not maxVal or *maxUse <= *maxVal) + ) + and ((not minUse or not maxUse) + or *minUse <= *maxUse + ) + and (not neutral + or ( (not maxVal or *neutral <= *maxVal) + and (not minVal or *minVal <= *neutral) + ) + ) + and (not defVal + or ( (not maxVal or *defVal <= *maxVal) + and (not minVal or *minVal <= *defVal) + ) + ) + and (not zyclic + or (minVal and maxVal) + or (minVal and neutral) + or (neutral and maxVal) + ) + ; + } + + + /* ===== conforming operations ===== */ + + /** + * Accommodate a raw value from the underlying domain, + * so that it conforms with this Scale definition. + */ + template + inline VAL + Scale::conform (VAL const& rawVal) const + { + UNIMPLEMENTED ("Scale conforming"); + } + + /** + * Join and combine an additional feed value with an anchor value. + * @note actual joining operation is picked based on both scales and types involved. + * @remark notably multiplicative contributions and logarithmic scales to be considered. + */ + template + template + inline VAL + Scale::join (VAL const& value, SRC const& feed, Scale const& feedScale) const + { + UNIMPLEMENTED ("join a feed with a base value, observing Scale constraints"); + } + + /** + * Simplified join() variant, assuming the feed is based on the same scale. + */ + template + inline VAL + Scale::join (VAL const& vaule, VAL const& feed) const + { + UNIMPLEMENTED ("join a feed with a base value within same Scale"); + } + }} // namespace lib::par #endif /*LIB_PAR_SCALE_H*/ diff --git a/tests/lib/par/parameter-scale-test.cpp b/tests/lib/par/parameter-scale-test.cpp index 9de75e9bd..e6dc296e0 100644 --- a/tests/lib/par/parameter-scale-test.cpp +++ b/tests/lib/par/parameter-scale-test.cpp @@ -18,7 +18,7 @@ #include "test/run.hpp" //#include "test/test-helper.hpp" -#include "lib/par/parameter.hpp" +#include "lib/par/scale.hpp" #include "test/diagnostic-output.hpp"/////////////TODO //#include @@ -58,14 +58,21 @@ namespace test{ run (Arg) { simpleUsage(); - verify_typeMarker(); + verify_Bounds(); } void simpleUsage() { - UNIMPLEMENTED ("nebbich"); + Scale scale = {.minVal = -5, .maxVal = 23}; + CHECK (scale.isValid()); + + CHECK (-5 == scale.conform (-55)); + CHECK (23 == scale.conform (+55)); + + CHECK ( 5 == scale.join (2,3) ); + CHECK (-5 == scale.join (23,-55)); } @@ -73,7 +80,7 @@ namespace test{ * @todo WIP 9/26 🔁 define ⟶ implement */ void - verify_typeMarker() + verify_Bounds() { } }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 5e3529027..64d7146f1 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -85424,7 +85424,8 @@ - + + @@ -85551,9 +85552,10 @@ - + + - + @@ -85564,8 +85566,15 @@ + + + + + + - + + @@ -85593,7 +85602,8 @@ - + + @@ -85867,7 +85877,8 @@ - + + @@ -85916,11 +85927,19 @@ - + + + + +

+ während dem Neuhinzufügen könnten Render-Worker concurrent den Index verwenden — hierfür gibt es aber keinerlei Konsistenz-Garantie (nur die Payload Storage-Adressen in der Deque sind garantiert stabil) ⟹ »undefined behaviour« +

+ +
- + @@ -85933,27 +85952,24 @@ address computation touches nothing a writer mutates.

-
-
-
-
-class ScaleRegistry
+      

+class ScaleRegistry
   {
     static constexpr size_t CHUNK = 256;
-    static constexpr size_t MAX   = 256;          // ≙ 65536 scales
+    static constexpr size_t MAX   = 256;          // &#8793; 65536 scales
 
     struct Chunk { ScaleDescriptor slot[CHUNK]; };
 
-    std::array, MAX> chunk_{};
-    std::mutex                           writeGuard_;   // writers only
-    size_t                               next_ {0};     // guarded
+    std::array<std atomic="#DEFAULT" size="2"><chunk size="2">, MAX&gt; chunk_{};
+    std::mutex writeGuard_;   // writers only
+    size_t     next_ {0};     // guarded
 
   public:
-    ScaleDescriptor const&
+    ScaleDescriptor const&amp;
     operator[] (ScaleID id)  const                      // lock-free, engine path
       {
         return chunk_[id / CHUNK].load (std::memory_order_acquire)
-                    ->slot[id % CHUNK];
+                    -&gt;slot[id % CHUNK];
       }
 
     ScaleID
@@ -85961,16 +85977,13 @@
       {
         std::lock_guard lock{writeGuard_};
         size_t id = next_++;
-        auto& head = chunk_[id / CHUNK];
+        auto&amp; head = chunk_[id / CHUNK];
         if (not head.load (std::memory_order_relaxed))
           head.store (new Chunk{}, std::memory_order_release);
-        head.load (std::memory_order_relaxed)->slot[id % CHUNK] = std::move(def);
+        head.load (std::memory_order_relaxed)-&gt;slot[id % CHUNK] = std::move(def);
         return ScaleID{id};
       }
   };
-
-
-

@@ -85998,6 +86011,7 @@

+
@@ -86024,6 +86038,10 @@
+ + + +
@@ -86231,6 +86249,21 @@
+ + + + + + +

+ ...nicht aber die Registrierung und Einbindung in die Parameter +

+ +
+ + +
+