Compare commits
1 commit
620ca918c3
...
59b44ed3e8
| Author | SHA1 | Date | |
|---|---|---|---|
| 59b44ed3e8 |
3 changed files with 225 additions and 11 deletions
|
|
@ -53,6 +53,11 @@ return: 0
|
|||
END
|
||||
|
||||
|
||||
TEST "Cyclic wrapping number domain" CyclicWrap_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
TEST "Deleter function collection" DelStash_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
|
|
|||
144
tests/lib/cyclic-wrap-test.cpp
Normal file
144
tests/lib/cyclic-wrap-test.cpp
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
CyclicWrap(Test) - verify cyclically wrapping number domain
|
||||
|
||||
Copyright (C)
|
||||
2026, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
**Lumiera** 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. See the file COPYING for further details.
|
||||
|
||||
* *****************************************************************/
|
||||
|
||||
/** @file util-floordiv-test.cpp
|
||||
** unit test \ref CyclicWrap_test
|
||||
*/
|
||||
|
||||
|
||||
#include "test/run.hpp"
|
||||
#include "lib/util-quant.hpp"
|
||||
#include "lib/util.hpp"
|
||||
#include "test/diagnostic-output.hpp"//////////////////TODO
|
||||
//#include "lib/format-cout.hpp"
|
||||
//#include "lib/format-string.hpp"
|
||||
|
||||
using ::Test;
|
||||
//using util::isnil;
|
||||
//using util::_Fmt;
|
||||
using util::isLimited;
|
||||
|
||||
|
||||
namespace util {
|
||||
namespace test {
|
||||
|
||||
|
||||
|
||||
namespace{ // Test helpers...
|
||||
|
||||
template<typename NUM>
|
||||
constexpr NUM _MAX = std::numeric_limits<NUM>::max();
|
||||
|
||||
template<typename NUM>
|
||||
constexpr NUM _MIN = std::numeric_limits<NUM>::lowest();
|
||||
|
||||
} // (End) Test helpers
|
||||
|
||||
|
||||
|
||||
/******************************************************************//**
|
||||
* @test Demonstrate and verify a cyclic wrapping numeric domain.
|
||||
* - show the wrapping behaviour with simple numbers
|
||||
* - verify the behaviour pattern for all integer types (signed / unsigned)
|
||||
* - verify the computation works at the very bounds of the domain
|
||||
* - verify the most difficult path with a negative minVal,
|
||||
* and the smallest number in the domain
|
||||
* @todo add coverage for floating-point numbers
|
||||
* @see util::cyclicWrap
|
||||
* @see parameter-scale-test.cpp
|
||||
*/
|
||||
class CyclicWrap_test : public Test
|
||||
{
|
||||
|
||||
virtual void
|
||||
run (Arg)
|
||||
{
|
||||
simpleDemonstration();
|
||||
|
||||
verifyIntegerTypes<int>();
|
||||
verifyIntegerTypes<uint>();
|
||||
verifyIntegerTypes<int8_t>();
|
||||
verifyIntegerTypes<uint8_t>();
|
||||
verifyIntegerTypes<int16_t> ();
|
||||
verifyIntegerTypes<uint16_t>();
|
||||
verifyIntegerTypes<int32_t> ();
|
||||
verifyIntegerTypes<uint32_t>();
|
||||
verifyIntegerTypes<int64_t> ();
|
||||
verifyIntegerTypes<uint64_t>();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
simpleDemonstration ()
|
||||
{
|
||||
CHECK (10 == cyclicWrap (10,10,15));
|
||||
CHECK (11 == cyclicWrap (11,10,15));
|
||||
CHECK (12 == cyclicWrap (12,10,15));
|
||||
CHECK (13 == cyclicWrap (13,10,15));
|
||||
CHECK (14 == cyclicWrap (14,10,15));
|
||||
CHECK (10 == cyclicWrap (15,10,15));
|
||||
CHECK (11 == cyclicWrap (16,10,15));
|
||||
CHECK (12 == cyclicWrap (17,10,15));
|
||||
CHECK (13 == cyclicWrap (18,10,15));
|
||||
CHECK (14 == cyclicWrap (19,10,15));
|
||||
CHECK (10 == cyclicWrap (20,10,15));
|
||||
|
||||
CHECK (10 == cyclicWrap ( 0,10,15));
|
||||
CHECK (14 == cyclicWrap (-1,10,15));
|
||||
}
|
||||
|
||||
|
||||
template<typename I>
|
||||
void
|
||||
verifyIntegerTypes ()
|
||||
{
|
||||
const I LOWER(-100); // note: expected to wrap for unsigned types
|
||||
const I UPPER(LOWER+5);
|
||||
|
||||
auto cyc = [&](I val){ return cyclicWrap (I(val), LOWER,UPPER); };
|
||||
|
||||
CHECK (LOWER == cyc(LOWER+0) );
|
||||
CHECK (LOWER+1 == cyc(LOWER+1) );
|
||||
CHECK (LOWER+2 == cyc(LOWER+2) );
|
||||
CHECK (LOWER+3 == cyc(LOWER+3) );
|
||||
CHECK (LOWER+4 == cyc(LOWER+4) );
|
||||
CHECK (LOWER == cyc(LOWER+5) );
|
||||
|
||||
CHECK (LOWER == cyc(LOWER-5) );
|
||||
CHECK (LOWER+1 == cyc(LOWER-4) );
|
||||
CHECK (LOWER+2 == cyc(LOWER-3) );
|
||||
CHECK (LOWER+3 == cyc(LOWER-2) );
|
||||
CHECK (LOWER+4 == cyc(LOWER-1) );
|
||||
|
||||
|
||||
CHECK (isLimited (LOWER, cyc(_MAX<I>), UPPER));
|
||||
CHECK (isLimited (LOWER, cyc(_MIN<I>), UPPER));
|
||||
|
||||
CHECK (isLimited (LOWER, cyc(_MAX<I>-1), UPPER));
|
||||
CHECK (isLimited (LOWER, cyc(_MIN<I>+1), UPPER));
|
||||
|
||||
I dist = LOWER - _MIN<I>; // guaranteed to be positive and representable in-domain
|
||||
I step = (dist / 5) * 5; // the next applicable grid point
|
||||
I excess = dist - step;
|
||||
I offset = 5 - excess; // flip orientation (since the input val lies below LOWER)
|
||||
|
||||
CHECK (LOWER + offset == cyc(_MIN<I>) );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
LAUNCHER (CyclicWrap_test, "unit common");
|
||||
|
||||
|
||||
}} // namespace util::test
|
||||
|
|
@ -86141,7 +86141,7 @@ class ScaleRegistry
|
|||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1789313909221" ID="ID_636669321" MODIFIED="1789314360236">
|
||||
<node CREATED="1789313909221" ID="ID_636669321" MODIFIED="1789423588613">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
|
|
@ -86158,7 +86158,8 @@ class ScaleRegistry
|
|||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<node BACKGROUND_COLOR="#accdc3" COLOR="#3f4015" CREATED="1789314198004" ID="ID_1198665569" MODIFIED="1789314547810" TEXT="Integral: Abdeckung der gesamten Domäne per Unsigned...">
|
||||
<linktarget COLOR="#49a8d6" DESTINATION="ID_636669321" ENDARROW="Default" ENDINCLINATION="87;46;" ID="Arrow_ID_1613615444" SOURCE="ID_945572666" STARTARROW="None" STARTINCLINATION="260;14;"/>
|
||||
<node BACKGROUND_COLOR="#accdc3" COLOR="#3f4015" CREATED="1789314198004" FOLDED="true" ID="ID_1198665569" MODIFIED="1789423416268" TEXT="Integral: Abdeckung der gesamten Domäne per Unsigned...">
|
||||
<icon BUILTIN="wizard"/>
|
||||
<node CREATED="1789314266561" ID="ID_662274868" MODIFIED="1789342378691" STYLE="bubble">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
|
|
@ -86257,7 +86258,7 @@ class ScaleRegistry
|
|||
<icon BUILTIN="wizard"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#accdc3" COLOR="#3f4015" CREATED="1789314221349" ID="ID_63841523" MODIFIED="1789314713492" TEXT="Floatingpoint: Nicht-handhabbare Bereiche beachten...">
|
||||
<node BACKGROUND_COLOR="#accdc3" COLOR="#3f4015" CREATED="1789314221349" FOLDED="true" ID="ID_63841523" MODIFIED="1789423414551" TEXT="Floatingpoint: Nicht-handhabbare Bereiche beachten...">
|
||||
<icon BUILTIN="wizard"/>
|
||||
<node CREATED="1789314574790" HGAP="49" ID="ID_1659421158" MODIFIED="1789341131113" STYLE="bubble" VSHIFT="1">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
|
|
@ -86337,7 +86338,7 @@ class ScaleRegistry
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#accdc3" COLOR="#3f4015" CREATED="1789314739520" ID="ID_900911623" MODIFIED="1789314802300" TEXT="Erläuterung der Löungsstrategie">
|
||||
<node BACKGROUND_COLOR="#accdc3" COLOR="#3f4015" CREATED="1789314739520" FOLDED="true" ID="ID_900911623" MODIFIED="1789423604616" TEXT="Erläuterung der Löungsstrategie">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
|
|
@ -86527,7 +86528,7 @@ class ScaleRegistry
|
|||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<node BACKGROUND_COLOR="#f8ecbf" CREATED="1789340923095" HGAP="104" ID="ID_921584380" MODIFIED="1789347764151" VSHIFT="56">
|
||||
<node BACKGROUND_COLOR="#f8ecbf" CREATED="1789340923095" HGAP="104" ID="ID_921584380" MODIFIED="1789423600852" VSHIFT="56">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
|
|
@ -86769,13 +86770,14 @@ Prop.1: dist%3 1 2 0 1 2 0
|
|||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<linktarget COLOR="#f8263e" DESTINATION="ID_921584380" ENDARROW="Default" ENDINCLINATION="-16;141;" ID="Arrow_ID_244758209" SOURCE="ID_380512260" STARTARROW="None" STARTINCLINATION="195;11;"/>
|
||||
<linktarget COLOR="#ff0808" DESTINATION="ID_921584380" ENDARROW="Default" ENDINCLINATION="305;-925;" ID="Arrow_ID_153243460" SOURCE="ID_662274868" STARTARROW="None" STARTINCLINATION="141;26;"/>
|
||||
<linktarget COLOR="#f8263e" DESTINATION="ID_921584380" ENDARROW="Default" ENDINCLINATION="-16;141;" ID="Arrow_ID_244758209" SOURCE="ID_380512260" STARTARROW="None" STARTINCLINATION="198;10;"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#aff8e9" COLOR="#338800" CREATED="1789340798664" HGAP="15" ID="ID_1175604381" MODIFIED="1789340850559" TEXT="damit könnte ich implementieren..." VSHIFT="18">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1789340871908" ID="ID_380512260" MODIFIED="1789342452121" STYLE="fork" TEXT="die Erläuterung für den Unsigned-Fall ist zu knapp">
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1789340871908" ID="ID_380512260" MODIFIED="1789423600852" STYLE="fork" TEXT="die Erläuterung für den Unsigned-Fall ist zu knapp">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
|
|
@ -86784,7 +86786,7 @@ Prop.1: dist%3 1 2 0 1 2 0
|
|||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<arrowlink COLOR="#f8263e" DESTINATION="ID_921584380" ENDARROW="Default" ENDINCLINATION="-16;141;" ID="Arrow_ID_244758209" STARTARROW="None" STARTINCLINATION="195;11;"/>
|
||||
<arrowlink COLOR="#f8263e" DESTINATION="ID_921584380" ENDARROW="Default" ENDINCLINATION="-16;141;" ID="Arrow_ID_244758209" STARTARROW="None" STARTINCLINATION="198;10;"/>
|
||||
<font NAME="SansSerif" SIZE="12"/>
|
||||
<icon BUILTIN="broken-line"/>
|
||||
</node>
|
||||
|
|
@ -86806,13 +86808,14 @@ Prop.1: dist%3 1 2 0 1 2 0
|
|||
</node>
|
||||
<node CREATED="1789356710360" ID="ID_521207014" MODIFIED="1789356723054" TEXT="der -1-Verschiebe-Trick nutzt Modulus-Arithmetik"/>
|
||||
</node>
|
||||
<node CREATED="1789360000999" ID="ID_879348844" MODIFIED="1789360029799" TEXT="die Limit-Definition sollte direkt bei der cyclicWrap-Funktion selber definiert sein"/>
|
||||
<node COLOR="#435e98" CREATED="1789360000999" ID="ID_879348844" MODIFIED="1789423630533" TEXT="die Limit-Definition sollte direkt bei der cyclicWrap-Funktion selber definiert sein">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1789258808256" ID="ID_1240046297" MODIFIED="1789258815646" TEXT="Einführen der Fallunterscheidung">
|
||||
<node CREATED="1789258816860" ID="ID_1706182584" MODIFIED="1789258941151" TEXT="Policy-based Design erscheint die sauberste Lösung">
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1789258816860" ID="ID_1706182584" MODIFIED="1789423431524" TEXT="Policy-based Design erscheint die sauberste Lösung">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
|
|
@ -86822,8 +86825,70 @@ Prop.1: dist%3 1 2 0 1 2 0
|
|||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="yes"/>
|
||||
<icon BUILTIN="hourglass"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1789313641938" ID="ID_1271083241" MODIFIED="1789423457169" TEXT="zunächst genügt eine generische Library-funktion als Delegate">
|
||||
<icon BUILTIN="forward"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1789423486714" ID="ID_253445206" MODIFIED="1789438207120" TEXT="neue Implementierung">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1789423493685" ID="ID_1410459624" MODIFIED="1789423506223" TEXT="entwickelt ausgehend von der naiven »modulus«-Lösung"/>
|
||||
<node BACKGROUND_COLOR="#accdc3" COLOR="#3f4015" CREATED="1789423507714" ID="ID_945572666" MODIFIED="1789423613866" TEXT="zu einer generischen Lösung ausgebaut ⟵ Claude">
|
||||
<arrowlink COLOR="#49a8d6" DESTINATION="ID_636669321" ENDARROW="Default" ENDINCLINATION="87;46;" ID="Arrow_ID_1613615444" STARTARROW="None" STARTINCLINATION="260;14;"/>
|
||||
<icon BUILTIN="wizard"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1789423635808" ID="ID_840921741" MODIFIED="1789438193575" TEXT="Testabdeckung — Grenzfälle">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1789428970477" ID="ID_1439061940" MODIFIED="1789429004081" TEXT="habe gestern schon gesehen: für sich sind util::flordiv | wrap wohl „wasserdicht“">
|
||||
<node CREATED="1789429005712" ID="ID_1890368766" MODIFIED="1789429031093" TEXT="die Division liefert stets einen kleineren Quotient als der Dividend"/>
|
||||
<node CREATED="1789429032161" ID="ID_1469836197" MODIFIED="1789429058156" TEXT="die Korrektur-Logik arbeitet »glücklicherweise« stets zur Domäne nach innen"/>
|
||||
<node COLOR="#338800" CREATED="1789433766523" ID="ID_167005830" MODIFIED="1789433779815" TEXT="dies in UtilFloordiv_test dokumentieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#435e98" CREATED="1789433789808" ID="ID_538605241" MODIFIED="1789433827387" TEXT="jeweils an die Domain-Ober/Untergrenze gehen"/>
|
||||
<node COLOR="#435e98" CREATED="1789433801119" ID="ID_1533251912" MODIFIED="1789433827418" TEXT="durch 1, 2 und 5 teilen"/>
|
||||
<node COLOR="#435e98" CREATED="1789433808102" ID="ID_1210053047" MODIFIED="1789433827419" TEXT="Vorzeichen wechseln"/>
|
||||
<node COLOR="#435e98" CREATED="1789433812805" ID="ID_1425318347" MODIFIED="1789433827421" TEXT="auch für uint, int64_t, int8_t"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1789437807095" ID="ID_932126209" MODIFIED="1789437907066" TEXT="zunächst eine einfache Demonstration (als Dokumentation)">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
.... ich könnte mir denken, daß mancher Leser das Konzept nicht gleich versteht, deshalb ist ein solches einfaches Beispiel nie verkehrt
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1789437908944" ID="ID_880098415" MODIFIED="1789437928788" TEXT="systematisch alle real-existierenden Integral-Typen abdecken">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1789437929974" ID="ID_532498668" MODIFIED="1789438198770" TEXT="die eigentliche Test-Funktion als Template">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1789437943780" ID="ID_1291965296" MODIFIED="1789438178462" TEXT="konstruiere das Test-Beispiel »trickreich«">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1789437965201" ID="ID_1576393662" MODIFIED="1789437977028" TEXT="so daß es sich für Signed und Unsigned gut testen läßt"/>
|
||||
<node CREATED="1789437977859" ID="ID_1376129649" MODIFIED="1789438001984" TEXT="soll aber auch den komplexeren Pfad ausleuchten"/>
|
||||
<node CREATED="1789438002860" ID="ID_1338563274" MODIFIED="1789438069296" TEXT="⟹ sollte die zyklische Domäne in den negativen Bereich legen">
|
||||
<node CREATED="1789438070916" ID="ID_379253711" MODIFIED="1789438081989" TEXT="für Unsigned sollte das wrappen"/>
|
||||
<node CREATED="1789438082993" ID="ID_1576673426" MODIFIED="1789438091635" TEXT="aber trotzdem noch sicher in die Domäne passen"/>
|
||||
<node CREATED="1789438092936" ID="ID_1900067766" MODIFIED="1789438108922" TEXT="und für Signed ist dann der Offset garantiert repräsentierbar"/>
|
||||
<node CREATED="1789438111305" ID="ID_1260779668" MODIFIED="1789438125620" TEXT="und zwar grade für den problematischen Fall unter der Untergrenze"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1789438130012" ID="ID_1945361876" MODIFIED="1789438175874" TEXT="teste die Domänen-Grenzen auf valides Ergebnis (in der zyklischen Domain)">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1789438158204" ID="ID_527867911" MODIFIED="1789438175875" TEXT="rechne explizit den Wert für die Domain-Untergrenze nach">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1789313641938" ID="ID_1271083241" MODIFIED="1789313655675" TEXT="man könnte aber auch versuchen, an eine generische Library-funktion zu delegieren"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1789171888403" ID="ID_1422919144" MODIFIED="1789171908101" TEXT="min/max clamp">
|
||||
|
|
|
|||
Loading…
Reference in a new issue