Segmentation: setup for simple demo test case works

due to having extracted the Algo implementation as template,
we can now instantiate it for isolated tests with simple integer intervals
This commit is contained in:
Fischlurch 2023-05-04 02:07:38 +02:00
parent 00ca84a2aa
commit f9a4d6134c
3 changed files with 139 additions and 63 deletions

View file

@ -79,22 +79,6 @@ namespace lib {
class Algo
: util::NonCopyable
{
enum Verb { NIL
, DROP
, TRUNC
, INS_NOP
, SEAMLESS
};
Verb opPred_ = NIL,
opSucc_ = NIL;
POS pred_, succ_;
ORD start_, after_;
using OptORD = std::optional<ORD>;
/* ======= elementary operations ======= */
ASSERT_VALID_SIGNATURE (START, ORD(POS))
@ -111,8 +95,30 @@ namespace lib {
CLONE cloneSeg;
DELETE discard;
using OptORD = std::optional<ORD>;
const ORD AXIS_END;
/* ======= working state ======= */
POS pred_, succ_;
struct SegBounds
{ // can be assigned in one step (ORD may be immutable)
ORD start,
after;
} b_;
enum Verb { NIL
, DROP
, TRUNC
, INS_NOP
, SEAMLESS
};
Verb opPred_ = NIL,
opSucc_ = NIL;
public:
/**
* @param startAll (forward) iterator pointing at the overall Segmentation begin
@ -136,15 +142,16 @@ namespace lib {
, cloneSeg{fun_cloneSeg}
, discard {fun_discard}
, AXIS_END{axisEnd}
, pred_{}
, succ_{}
, b_{establishSplitPoint (startAll,afterAll, start,after)}
{
auto [start_,after_] = establishSplitPoint (startAll,afterAll, start,after);
// Postcondition: ordered start and end times
ENSURE (pred_ != afterAll);
ENSURE (succ_ != afterAll);
ENSURE (start_ < after_);
ENSURE (getStart(pred_) <= start_);
ENSURE (start_ <= getStart(succ_) or pred_ == succ_);
ENSURE (b_.start < b_.after);
ENSURE (getStart(pred_) <= b_.start);
ENSURE (b_.start <= getStart(succ_) or pred_ == succ_);
}
/**
@ -152,7 +159,7 @@ namespace lib {
* and establish the actual start and end point of the new segment
* @return
*/
std::pair<ORD,ORD>
SegBounds
establishSplitPoint (POS startAll, POS afterAll
,OptORD start, OptORD after)
{ // nominal break point
@ -197,15 +204,15 @@ namespace lib {
ORD startPred = getStart (pred_),
afterPred = getAfter (pred_);
if (startPred < start_)
if (startPred < b_.start)
{
if (afterPred < start_) opPred_ = INS_NOP;
if (afterPred < b_.start) opPred_ = INS_NOP;
else
if (afterPred == start_) opPred_ = SEAMLESS;
if (afterPred == b_.start) opPred_ = SEAMLESS;
else
{
opPred_ = TRUNC;
if (afterPred > after_)
if (afterPred > b_.after)
{ // predecessor actually spans the new segment
// thus use it also as successor and truncate both (=SPLIT)
succ_ = pred_;
@ -214,9 +221,9 @@ namespace lib {
} } }
else
{
REQUIRE (startPred == start_, "predecessor does not precede start point");
REQUIRE (startPred == b_.start, "predecessor does not precede start point");
opPred_ = DROP;
if (after_ < afterPred )
if (b_.after < afterPred )
{ // predecessor coincides with start of new segment
// thus use it rather as successor and truncate at start
succ_ = pred_;
@ -225,21 +232,21 @@ namespace lib {
} }
ORD startSucc = getStart (succ_);
if (startSucc < after_)
if (startSucc < b_.after)
{
while (getAfter(succ_) < after_)
while (getAfter(succ_) < b_.after)
++succ_;
ASSERT (getStart(succ_) < after_ // in case we dropped a successor completely spanned,
ASSERT (getStart(succ_) < b_.after // in case we dropped a successor completely spanned,
,"seamless segmentation"); // even the next one must start within the new segment
if (after_ == getAfter(succ_)) opSucc_ = DROP;
if (b_.after == getAfter(succ_)) opSucc_ = DROP;
else
if (after_ < getAfter(succ_)) opSucc_ = TRUNC;
if (b_.after < getAfter(succ_)) opSucc_ = TRUNC;
}
else
{
if (after_ == startSucc) opSucc_ = SEAMLESS;
else opSucc_ = INS_NOP;
if (b_.after == startSucc) opSucc_ = SEAMLESS;
else opSucc_ = INS_NOP;
}
}
@ -265,22 +272,22 @@ namespace lib {
++succ_;
// insert the new elements /before/ the range to be dropped, i.e. at pred_
POS n = createSeg (pred_, start_, after_);
POS n = createSeg (pred_, b_.start, b_.after);
POS s = n;
//
// possibly adapt the predecessor
if (opPred_ == INS_NOP)
s = emptySeg (n, getAfter(refPred), start_);
s = emptySeg (n, getAfter(refPred), b_.start);
else
if (opPred_ == TRUNC)
s = cloneSeg (n, getStart(refPred), start_, refPred);
s = cloneSeg (n, getStart(refPred), b_.start, refPred);
//
// possibly adapt the successor
if (opSucc_ == INS_NOP)
emptySeg (pred_, after_, getStart(refSucc));
emptySeg (pred_, b_.after, getStart(refSucc));
else
if (opPred_ == TRUNC)
cloneSeg (pred_, after_, getAfter(refSucc), refSucc);
cloneSeg (pred_, b_.after, getAfter(refSucc), refSucc);
// finally discard superseded segments
POS e = discard (pred_, succ_);

View file

@ -63,6 +63,12 @@ namespace test {
int after;
bool empty;
~Seg()
{
check -= id;
if (id) --cnt;
}
Seg (int s, int a, bool nil=false)
: start{s}
, after{a}
@ -73,12 +79,18 @@ namespace test {
check += id;
}
~Seg()
/** create a clone, but modify bounds */
Seg (Seg const& ref, int s, int a)
: start{s}
, after{a}
, empty{ref.empty}
, id{ref.id}
{
check -= id;
if (id) --cnt;
++cnt;
check += id;
}
/** move-init: causes source-ref to be invalidated */
Seg (Seg&& rr)
: start{rr.start}
, after{rr.after}
@ -222,7 +234,37 @@ namespace test {
void
demonstrate_usage()
{
TODO ("simple usage example");
SegL segments;
cout << segments <<endl;
using OInt = std::optional<int>;
using Iter = typename SegL::iterator;
auto getStart = [](Iter elm) -> int { return elm->start; };
auto getAfter = [](Iter elm) -> int { return elm->after; };
auto createSeg= [&](Iter pos, int start, int after) -> Iter { return segments.emplace (pos, start, after); };
auto emptySeg = [&](Iter pos, int start, int after) -> Iter { return segments.emplace (pos, start, after, true); };
auto cloneSeg = [&](Iter pos, int start, int after, Iter src) -> Iter { return segments.emplace (pos, *src, start, after); };
auto discard = [&](Iter pos, Iter after) -> Iter { return segments.erase (pos,after); };
lib::splitsplice::Algo splicer{ getStart
, getAfter
, createSeg
, emptySeg
, cloneSeg
, discard
, SMAX
, segments.begin(),segments.end()
, OInt{5}, OInt{23}
};
splicer.determineRelations();
auto [s,n,e] = splicer.performSplitSplice();
cout << segments <<endl;
cout << "s:"<<*s <<endl;
cout << "n:"<<*n <<endl;
cout << "e:"<<*e <<endl;
}
@ -230,6 +272,8 @@ namespace test {
void
verify_testFixture()
{
CHECK (0 == Seg::check);
Seg::idGen = 0;
{
Seg x{1,3}; // a segment 1 (inclusive) to 3 (exclusive)
Seg u{2,4,true}; // an "empty" segment 2 (incl) to 4 (excl)

View file

@ -70281,25 +70281,7 @@
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1683046958233" ID="ID_226373762" MODIFIED="1683047000567" TEXT="isoliert testbar machen">
<arrowlink COLOR="#e31dc4" DESTINATION="ID_1714211009" ENDARROW="Default" ENDINCLINATION="-141;9;" ID="Arrow_ID_816334190" STARTARROW="None" STARTINCLINATION="-192;20;"/>
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1682993091685" ID="ID_988617455" MODIFIED="1682993099148" TEXT="systematische Testabdeckung">
<icon BUILTIN="hourglass"/>
<node CREATED="1682993100755" ID="ID_1651031348" MODIFIED="1682993128370" TEXT="es sind 12 Basis-F&#xe4;lle">
<icon BUILTIN="info"/>
</node>
<node CREATED="1682993108314" ID="ID_317827435" MODIFIED="1682993122827" TEXT="hinzu kommt die Variante, da&#xdf; leere Intervalle zusammengef&#xfc;hrt werden"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1683046966788" ID="ID_1714211009" MODIFIED="1683120265331" TEXT="splitSplice-Algo isoliert testen">
<linktarget COLOR="#e31dc4" DESTINATION="ID_1714211009" ENDARROW="Default" ENDINCLINATION="-141;9;" ID="Arrow_ID_816334190" SOURCE="ID_226373762" STARTARROW="None" STARTINCLINATION="-192;20;"/>
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1683120139366" ID="ID_255513798" MODIFIED="1683120148509" TEXT="Test-Setup mit einfachen int-Intevallen">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1683120149579" ID="ID_523859522" MODIFIED="1683120164828" TEXT="Diagnose-setup f&#xfc;r valide Segmentation">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1683120165480" ID="ID_1260440964" MODIFIED="1683120205165" TEXT="Diagnose-Setup f&#xfc;r Memory-Management">
<node COLOR="#338800" CREATED="1683158281268" ID="ID_1471352554" MODIFIED="1683158303513" TEXT="Verdrahtung f&#xfc;r Dummy-Integer-Segmente">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1683153490521" ID="ID_855593043" MODIFIED="1683153582188" TEXT="Diagnose-Helper zum Vergleichen mit erwartetem Inhalt">
@ -70324,6 +70306,49 @@
</html></richcontent>
<icon BUILTIN="idea"/>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1682993091685" ID="ID_988617455" MODIFIED="1682993099148" TEXT="systematische Testabdeckung">
<icon BUILTIN="hourglass"/>
<node CREATED="1682993100755" ID="ID_1651031348" MODIFIED="1682993128370" TEXT="es sind 12 Basis-F&#xe4;lle">
<icon BUILTIN="info"/>
</node>
<node CREATED="1682993108314" ID="ID_317827435" MODIFIED="1682993122827" TEXT="hinzu kommt die Variante, da&#xdf; leere Intervalle zusammengef&#xfc;hrt werden"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1683046966788" ID="ID_1714211009" MODIFIED="1683120265331" TEXT="splitSplice-Algo isoliert testen">
<linktarget COLOR="#e31dc4" DESTINATION="ID_1714211009" ENDARROW="Default" ENDINCLINATION="-141;9;" ID="Arrow_ID_816334190" SOURCE="ID_226373762" STARTARROW="None" STARTINCLINATION="-192;20;"/>
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1683120139366" ID="ID_255513798" MODIFIED="1683120148509" TEXT="Test-Setup mit einfachen int-Intevallen">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1683120149579" ID="ID_523859522" MODIFIED="1683120164828" TEXT="Diagnose-setup f&#xfc;r valide Segmentation">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1683120165480" ID="ID_1260440964" MODIFIED="1683120205165" TEXT="Diagnose-Setup f&#xfc;r Memory-Management">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1683158346179" ID="ID_1729448638" MODIFIED="1683158373910" TEXT="Demonstration: einfache Anwendung">
<icon BUILTIN="button_ok"/>
<node CREATED="1683158410507" ID="ID_1394829232" MODIFIED="1683158528764">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
<font face="Monospaced" color="#2d258b">[-100~100[&#9508; </font>
</p>
<p>
<font face="Monospaced" color="#2d258b">[-100~5[[5_23[[23~100[&#9508;</font>
</p>
</body>
</html></richcontent>
<icon BUILTIN="ksmiletris"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1683158382175" ID="ID_1213737514" MODIFIED="1683158390534" TEXT="Setup f&#xfc;r Einzelfall-Tests">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1683047015402" ID="ID_1729864005" MODIFIED="1683120259296" TEXT="M&#xf6;gliche Intervall-Anordnungen">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1683047146727" ID="ID_1666065871" MODIFIED="1683047163542" TEXT="Seg in leer">