Segmentation: structure analysis for splitSplice operation

There are 12 distinct cases regarding the orientation of two intervals;
The Segmentation::splitSplice() operation shall insert a new Segment
and adjust / truncate / expand / split / delete existing segments
such as to retain the *Invariant* (seamless segmentation covering
the complete time axis)
This commit is contained in:
Fischlurch 2023-05-02 04:16:39 +02:00
parent a807705185
commit b582c35c9f
8 changed files with 262 additions and 16 deletions

View file

@ -115,14 +115,11 @@
#include <string> #include <string>
#include <deque> #include <deque>
namespace lib { namespace lib {
namespace diff{ namespace diff{
namespace error = lumiera::error; namespace error = lumiera::error;
using std::string;
struct GenNode; struct GenNode;
struct Ref; struct Ref;
@ -474,6 +471,7 @@ namespace diff{
bool hasAttribute (string key) const; bool hasAttribute (string key) const;
bool isNested() const; bool isNested() const;
bool hasChildren() const;
protected: protected:
@ -590,7 +588,7 @@ namespace diff{
/** /**
* Building block for monad-like depth-first expansion of a GenNode. * Building block for monad-like depth-first expansion of a GenNode.
* When used within lib::IterStateWrapper, the result is an Iterator * When used within lib::IterStateWrapper, the result is an Iterator
* to visit the contents of a GenNodet tree recursively depth-fist. * to visit the contents of a GenNode tree recursively depth-fist.
*/ */
class GenNode::ScopeExplorer class GenNode::ScopeExplorer
{ {
@ -814,6 +812,13 @@ namespace diff{
return data.isNested(); return data.isNested();
} }
inline bool
GenNode::hasChildren() const
{
return not isnil (data.childIter());
}

View file

@ -64,13 +64,31 @@ namespace fixture {
/** */ /**
// bool * @param start (optional) definition of the new Segment's start point (inclusive)
// ModelPortRegistry::contains (ID<Pipe> key) const * @param after (optional) definition of the end point (exclusive)
// { * @param jobTicket specification of provided render functionality for the new Segment
// return bool(key) * @remarks missing definitions will be derived or interpolated according to context
// && util::contains (transaction_, key); * - if start point is omitted, the new Segment will start seamlessly after
// } * any preceding Segment's end, in case this preceding Segment ends earlier
* - otherwise the preceding Segment's start point will be used, thereby effectively
* replacing and expanding or trimming or inserting into the preceding Segment
* - similar for the end point: if the definition is omitted, the new Segment
* will cover the time range until the next Segmen's start
* - if upper/lower boundaries can not be established, the covered range will be
* expanded from Time::ANYTIME up to Time::ANYTIME in as fitting current context
* - after start and end point have been established by the above rules, the actual
* splicing operation will be determined; either an existing Segment is replaced
* altogether, or it is trimmed to fit, or the new Segment is inserted, thereby
* creating a second (copied) part of the encompassing old Segment.
* - in case the JobTicket is omitted, the new Segment will be marked as _passive_
* and any job created from such a Segment will then be a »NOP-job«
*/
Segment const&
Segmentation::splitSplice (OptTime start, OptTime after, const engine::JobTicket* jobTicket)
{
UNIMPLEMENTED ("determine predecessor, successor and orientation and perform del/trunc/split/swap/insert");
}

View file

@ -53,6 +53,7 @@
#include "lib/nocopy.hpp" #include "lib/nocopy.hpp"
#include <list> #include <list>
#include <optional>
namespace steam { namespace steam {
@ -64,6 +65,8 @@ namespace fixture {
using lib::time::TimeValue; using lib::time::TimeValue;
using util::_Fmt; using util::_Fmt;
using OptTime = std::optional<lib::time::Time>;
/** /**
* For the purpose of building and rendering, the fixture (for each timeline) * For the purpose of building and rendering, the fixture (for each timeline)
* is partitioned such that each segment is _structurally constant._ * is partitioned such that each segment is _structurally constant._
@ -108,6 +111,10 @@ namespace fixture {
return seg; return seg;
throw error::State (_Fmt{"Fixture datastructure corrupted: Time %s not covered"} % time); throw error::State (_Fmt{"Fixture datastructure corrupted: Time %s not covered"} % time);
} }
/** rework the existing Segmentation to include a new Segment as specified */
Segment const&
splitSplice (OptTime start, OptTime after, const engine::JobTicket* =nullptr);
}; };

View file

@ -2,7 +2,7 @@ TESTING "Component Test Suite: GUI Model Parts" ./test-suite --group=stage
TEST "Self-check: testing GUI backbone parts" TestGui_test <<END PLANNED "Self-check: testing GUI backbone parts" TestGui_test <<END
return: 0 return: 0
END END

View file

@ -76,7 +76,7 @@ namespace test {
// using lib::time::Offset; // using lib::time::Offset;
// using lib::time::TimeVar; // using lib::time::TimeVar;
using lib::time::TimeValue; using lib::time::TimeValue;
// using lib::time::Time; using lib::time::Time;
// using mobject::ModelPort; // using mobject::ModelPort;
// using play::Timings; // using play::Timings;
using lib::HashVal; using lib::HashVal;
@ -207,8 +207,14 @@ namespace test {
{ {
for (auto& spec : specs) for (auto& spec : specs)
{ {
auto seed = spec.retrieveAttribute<HashVal>("mark"); JobTicket* newTicket = nullptr;
auto seed = spec.retrieveAttribute<HashVal> ("mark");
tickets_.emplace_back (seed? *seed : HashVal(rand() % 1000)); tickets_.emplace_back (seed? *seed : HashVal(rand() % 1000));
newTicket = & tickets_.back();
auto start = spec.retrieveAttribute<Time> ("start");
auto after = spec.retrieveAttribute<Time> ("after");
Segmentation::splitSplice (start, after, newTicket);
} }
} }
}; };

View file

@ -368,6 +368,9 @@ namespace test{
++child; ++child;
CHECK (isnil (child)); CHECK (isnil (child));
CHECK (n.hasChildren());
CHECK (not GenNode{42}.hasChildren());
} }
@ -993,6 +996,10 @@ namespace test{
CHECK (Time(3,2,1) == *n3.retrieveAttribute<Time>("Ψ")); CHECK (Time(3,2,1) == *n3.retrieveAttribute<Time>("Ψ"));
CHECK (std::nullopt == n2.retrieveAttribute<Time>("Ψ")); CHECK (std::nullopt == n2.retrieveAttribute<Time>("Ψ"));
CHECK (not n1.hasChildren()); // a simple value GenNode is not nested and thus can not have children
CHECK (not n2.hasChildren()); // n2 is nested (holds a Rec), but has an empty scope
CHECK (not n3.hasChildren()); // n3 is likewise nested, but holds only attributes, no children
} }
}; };

View file

@ -7101,7 +7101,7 @@ We need to detect attaching and detaching of
* root &amp;harr; [[Fork]] * root &amp;harr; [[Fork]]
</pre> </pre>
</div> </div>
<div title="Segmentation" modifier="Ichthyostega" created="201012121901" modified="202304162242" tags="def spec Builder" changecount="4"> <div title="Segmentation" modifier="Ichthyostega" created="201012121901" modified="202305020219" tags="def spec Builder" changecount="5">
<pre>//Segmentation of timeline// denotes a data structure and a step in the BuildProcess. <pre>//Segmentation of timeline// denotes a data structure and a step in the BuildProcess.
When [[building the fixture|BuildFixture]], ~MObjects -- as handled by their Placements -- are grouped below each timeline using them; Placements are then to be resolved into [[explicit Placements|ExplicitPlacement]], resulting in a single well defined time interval for each object. This allows to cut this effective timeline into slices of constant wiring structure, which are represented through the ''Segmentation Datastructure'', a time axis with segments holding object placements and [[exit nodes|ExitNode]]. &amp;nbsp;&amp;rarr; see [[structure of the Fixture|Fixture]] When [[building the fixture|BuildFixture]], ~MObjects -- as handled by their Placements -- are grouped below each timeline using them; Placements are then to be resolved into [[explicit Placements|ExplicitPlacement]], resulting in a single well defined time interval for each object. This allows to cut this effective timeline into slices of constant wiring structure, which are represented through the ''Segmentation Datastructure'', a time axis with segments holding object placements and [[exit nodes|ExitNode]]. &amp;nbsp;&amp;rarr; see [[structure of the Fixture|Fixture]]
* for each Timeline we get a Segmentation * for each Timeline we get a Segmentation
@ -7116,7 +7116,7 @@ When [[building the fixture|BuildFixture]], ~MObjects -- as handled by their Pla
:&amp;rarr; after //sorting,// the segmentation can be established, thereby copying placements spanning multiple segments :&amp;rarr; after //sorting,// the segmentation can be established, thereby copying placements spanning multiple segments
:&amp;rarr; only //after running the complete build process for each segment,// the list of model ports and exit nodes can be established :&amp;rarr; only //after running the complete build process for each segment,// the list of model ports and exit nodes can be established
;(2) commit stage ;(2) commit stage
: -- after the build process(es) are completed, the new fixture gets ''committed'', thus becoming the officially valid state to be rendered. As render processes might be going on in parallel, some kind of locking or barrier is required. It seems advisable to make the change into a single atomic hot-swap. Meaning we'd get a single access point to be protected. But there is another twist: We need to find out which render processes to cancel and restart, to pick up the changes introduced by this build process -- which might include adding and deleting of timelines as a whole, and any conceivable change to the segmentation grid. Because of the highly dynamic nature of the placements, on the other hand it isn't viable to expect the high-level model to provide this information. Thus we need to find out about a ''change coverage'' at this point. We might expand on that idea to //prune any new segments which aren't changed.// This way, only a write barrier would be necessary on switching the actually changed segments, and any render processes touching these would be //tainted.// Old allocations could be released after all tainted processes are known to be terminated. : -- after the build process(es) are completed, the new fixture gets ''committed'', thus becoming the officially valid state to be rendered. As render processes might be going on in parallel, some kind of locking or barrier is required. It seems advisable to make the change into a single atomic hot-swap. Meaning we'd get a single access point to be protected. But there is another twist: We need to find out which render processes to cancel and restart, to pick up the changes introduced by this build process -- which might include adding and deleting of timelines as a whole, and any conceivable change to the segmentation grid. Because of the highly dynamic nature of the placements, on the other hand it isn't viable to expect the high-level model to provide this information. Thus we need to find out about a ''change coverage'' at this point. We might expand on that idea to //prune any new segments which aren't changed.// This way, only a write barrier would be necessary on switching the actually changed segments, and any render processes touching these would be //tainted.// Old allocations could be released after all tainted processes are known to be terminated. &amp;rarr; SegmentationChange
;(3) rendering use ;(3) rendering use
:Each play/render process employs a ''frame dispatch step'' to get the right exit node for pulling a given frame (&amp;rarr; [[Dispatcher|FrameDispatcher]]). Planning appropriate [[render jobs|RenderJob]] involves support by the JobTicket for each Segment and port, which provides //a blueprint for rendering and connectivity.// From there on, the calculation process -- transmitted through [[Scheduler activity|RenderActivity]] -- proceeds into the [[processing nodes|ProcNode]]. The storage of these processing nodes and accompanying wiring descriptors is hooked up behind the individual segments, by sharing a common {{{AllocationCluster}}}. Yet the calculation of individual frames also depends on ''parameters'' and especially ''automation'' linked with objects in the high-level model. It is likely that there might be some sharing or some kind of additional communication interface, as the intention was to allow ''live changes'' to automated values. &lt;br/&gt;{{red{WIP 4/2023}}} details about to be elaborated &amp;rarr; PlaybackVerticalSlice :Each play/render process employs a ''frame dispatch step'' to get the right exit node for pulling a given frame (&amp;rarr; [[Dispatcher|FrameDispatcher]]). Planning appropriate [[render jobs|RenderJob]] involves support by the JobTicket for each Segment and port, which provides //a blueprint for rendering and connectivity.// From there on, the calculation process -- transmitted through [[Scheduler activity|RenderActivity]] -- proceeds into the [[processing nodes|ProcNode]]. The storage of these processing nodes and accompanying wiring descriptors is hooked up behind the individual segments, by sharing a common {{{AllocationCluster}}}. Yet the calculation of individual frames also depends on ''parameters'' and especially ''automation'' linked with objects in the high-level model. It is likely that there might be some sharing or some kind of additional communication interface, as the intention was to allow ''live changes'' to automated values. &lt;br/&gt;{{red{WIP 4/2023}}} details about to be elaborated &amp;rarr; PlaybackVerticalSlice
!!!observations !!!observations
@ -7141,6 +7141,82 @@ The Fixture is mostly comprised of the Segementation datastructure, but some oth
Largely the storage of the render nodes network is hooked up behind the Fixture &amp;rarr; [[storage considerations|FixtureStorage]] Largely the storage of the render nodes network is hooked up behind the Fixture &amp;rarr; [[storage considerations|FixtureStorage]]
</pre> </pre>
</div> </div>
<div title="SegmentationChange" creator="Ichthyostega" modifier="Ichthyostega" created="202305020227" modified="202305020228" tags="spec operational Builder draft" changecount="3">
<pre>At the end of the build process, the existing [[Segmentation]] possibly needs to be changed, extended or adapted.
This change must be performed as a //transactional switch,// since render or playback processes might be performed concurrently. All Fixture and low-level-Model datastructures are //immutable// -- thus for any changes, suitably adapted structures will be built as a replacement.
!Adapting the Segmentation by »split splice«
This is an implementation level operation, which analyses the existing Segmentation and determines the changes necessary to introduce a new or altered Segment. This operation has to retain the Segmentation ''Invariant'': it is a seamless sequence of Time intervals covering the complete time axis.
!!!Structure of the split-splice operation
{{red{1.5.2023 : Analysis and implementation draft}}}
{{{
Algorithmus
Invariante
vollständige lückenlose Abdeckung der gesamten Zeitachse
alle Einträge sind aufsteigend sortiert
Vorgänger und Nachfolger finden
Predecessor
sep ≔ start oder after (wenn start fehlt)
Pstart &gt;= sep ⟹ ↯ Predecessor
suche größten mit Pstart &lt; sep
Succsessor ist erster, der diese Bedingung verletzt
andernfalls: Successor == Predecessor (split)
Start- und Endpunkt festsetzen
definerter start/after-Punkt ist stets verbindlich
fehlernder start
sep ≡ after
Pend &lt; sep ⟹ start ≔ Pend
sonst ⟹ start ≔ Pstart (replace or trunc)
fehlender after
sep ≡ start ∧ Sstart &gt;= sep
Sstart &gt; sep ⟹ after ≔ Sstart
sonst ⟹ after ≔ Send (replace or trunc)
POST
start &lt; after
sonst ⟹ REJECT
Pstart &lt;= start
Pstart == Sstart start &lt;= Sstart
Relation zum Vor/Nachfolger bestimmen
Pstart &lt; start
Pend &lt; start ⟹ ins NOP-Predecessor
Pend == start ⟹ seamless
Pend &lt;= after ⟹ truc(Predecessor)
Pend &gt; after ⟹ split(Predecessor)
Pstart == start
Pend &lt;= after ⟹ del(Predecessor)
Pend &gt; after ⟹ swap_trunc(Predecessor)
Predecessor == Successor
Pend == after == Time::NEVER ⟹ trunc(Predecessor)
Pend &gt; after ⟹ split(Predecessor)
Sstart &lt; after
Send &lt; after ⟹ del(Successor) and ++Successor and recurse (same base case)
Send == after ⟹ del(Successor)
Send &gt; after ⟹ trunc(Successor)
Sstart == after ⟹ seamless
after &lt; Sstart ⟹ ins NOP-Successor
einfügen und löschen
Predecessor
trunc ⟹ del
split ⟹ del
del ⟹ del
swap_trunc ⟹ del
Successor
de++ ⟹ del
trunc ⟹ del
insert
before
ins NOP-Predecessor
trunc(Predecessor) ⟹ ins copy Predecessor-shortened-end
split(Predecessor) ⟹ ins copy Predecessor shortened-end
new Segment
after
split(Predecessor) ⟹ ins copy Predecessor shortened-start
swap_trunc(Predecessor) ⟹ ins copy Predecessor shortened-start
trunc(Successor) ⟹ ins copy Successor shortened-start
ins NOP-Successor
}}}</pre>
</div>
<div title="Sequence" modifier="Ichthyostega" created="201001252327" modified="201505310118" tags="def" changecount="2"> <div title="Sequence" modifier="Ichthyostega" created="201001252327" modified="201505310118" tags="def" changecount="2">
<pre>A sequence is a collection of media objects, arranged onto a fork (&quot;track tree&quot;). Sequences are the building blocks within the session. To be visible and editable, a session needs to be bound into a top-level [[Timeline]]. Alternatively, it may be used as a VirtualClip nested within another sequence. <pre>A sequence is a collection of media objects, arranged onto a fork (&quot;track tree&quot;). Sequences are the building blocks within the session. To be visible and editable, a session needs to be bound into a top-level [[Timeline]]. Alternatively, it may be used as a VirtualClip nested within another sequence.

View file

@ -70022,6 +70022,133 @@
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1682627110771" ID="ID_183754275" MODIFIED="1682627133820" TEXT="Invariante: l&#xfc;ckenlose Abdeckung"> <node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1682627110771" ID="ID_183754275" MODIFIED="1682627133820" TEXT="Invariante: l&#xfc;ckenlose Abdeckung">
<icon BUILTIN="messagebox_warning"/> <icon BUILTIN="messagebox_warning"/>
</node> </node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1682985654543" ID="ID_433290925" MODIFIED="1682993072525" TEXT="Algorithmus">
<icon BUILTIN="info"/>
<node CREATED="1682987424458" ID="ID_419424512" MODIFIED="1682987433683" TEXT="Invariante">
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="info"/>
<node CREATED="1682987436544" ID="ID_274517946" MODIFIED="1682987447444" TEXT="vollst&#xe4;ndige l&#xfc;ckenlose Abdeckung der gesamten Zeitachse"/>
<node CREATED="1682987448551" ID="ID_1538436206" MODIFIED="1682987455003" TEXT="alle Eintr&#xe4;ge sind aufsteigend sortiert"/>
</node>
<node CREATED="1682985661822" ID="ID_851188636" MODIFIED="1682986190931" TEXT="Vorg&#xe4;nger und Nachfolger finden">
<icon BUILTIN="full-1"/>
<node CREATED="1682986432658" ID="ID_792953434" MODIFIED="1682989149768" TEXT="Predecessor">
<node CREATED="1682986511215" ID="ID_493462626" MODIFIED="1682986543401" TEXT="sep &#x2254; start oder after (wenn start fehlt)"/>
<node CREATED="1682986554783" ID="ID_750576553" MODIFIED="1682989185654" TEXT="Pstart &gt;= sep &#x27f9; &#x21af; Predecessor"/>
<node CREATED="1682986826346" ID="ID_727853130" MODIFIED="1682989193099" TEXT="suche gr&#xf6;&#xdf;ten mit Pstart &lt; sep">
<linktarget COLOR="#a9b4c1" DESTINATION="ID_727853130" ENDARROW="Default" ENDINCLINATION="158;0;" ID="Arrow_ID_1115982284" SOURCE="ID_408822268" STARTARROW="None" STARTINCLINATION="158;0;"/>
</node>
</node>
<node CREATED="1682987368050" ID="ID_1970941364" MODIFIED="1682989212975" TEXT="Succsessor ist erster, der diese Bedingung verletzt"/>
<node CREATED="1682987507623" ID="ID_395536171" MODIFIED="1682989230851" TEXT="andernfalls: Successor == Predecessor (split)"/>
</node>
<node CREATED="1682985733848" ID="ID_1672899650" MODIFIED="1682986193244" TEXT="Start- und Endpunkt festsetzen">
<icon BUILTIN="full-2"/>
<node CREATED="1682987322728" ID="ID_320248563" MODIFIED="1682987335524" TEXT="definerter start/after-Punkt ist stets verbindlich">
<icon BUILTIN="yes"/>
</node>
<node CREATED="1682987561688" ID="ID_1309770929" MODIFIED="1682987568688" TEXT="fehlernder start">
<node CREATED="1682987742720" ID="ID_1884018589" MODIFIED="1682987759318" TEXT="sep &#x2261; after">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1682987571207" ID="ID_571245598" MODIFIED="1682989244395" TEXT="Pend &lt; sep &#x27f9; start &#x2254; Pend"/>
<node CREATED="1682987616722" ID="ID_1354576577" MODIFIED="1682989250339" TEXT="sonst &#x27f9; start &#x2254; Pstart (replace or trunc)"/>
</node>
<node CREATED="1682987667594" ID="ID_1011955521" MODIFIED="1682987671861" TEXT="fehlender after">
<node CREATED="1682987742720" ID="ID_408822268" MODIFIED="1682989269792" TEXT="sep &#x2261; start &#x2227; Sstart &gt;= sep ">
<arrowlink DESTINATION="ID_727853130" ENDARROW="Default" ENDINCLINATION="158;0;" ID="Arrow_ID_1115982284" STARTARROW="None" STARTINCLINATION="158;0;"/>
<icon BUILTIN="idea"/>
</node>
<node CREATED="1682987571207" ID="ID_491456235" MODIFIED="1682989275719" TEXT="Sstart &gt; sep &#x27f9; after &#x2254; Sstart"/>
<node CREATED="1682987616722" ID="ID_548072579" MODIFIED="1682989279922" TEXT="sonst &#x27f9; after &#x2254; Send (replace or trunc)"/>
</node>
<node CREATED="1682988627722" ID="ID_1905015650" MODIFIED="1682988633654" TEXT="POST">
<icon BUILTIN="yes"/>
<node CREATED="1682988637176" ID="ID_1261626912" MODIFIED="1682988645668" TEXT="start &lt; after">
<node CREATED="1682988713966" ID="ID_1690550958" MODIFIED="1682988744556">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
sonst &#10233; <b>REJECT</b>
</p>
</body>
</html></richcontent>
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
<node CREATED="1682988779297" ID="ID_28501272" MODIFIED="1682989283846" TEXT="Pstart &lt;= start"/>
<node CREATED="1682988911963" ID="ID_1061830050" MODIFIED="1682989418556" TEXT="Pstart == Sstart &#x2228; start &lt;= Sstart"/>
</node>
</node>
<node CREATED="1682985780238" ID="ID_1935969711" MODIFIED="1682986195716" TEXT="Relation zum Vor/Nachfolger bestimmen">
<icon BUILTIN="full-3"/>
<node CREATED="1682989072565" ID="ID_574776010" MODIFIED="1682989310210" TEXT="Pstart &lt; start">
<node CREATED="1682989100107" ID="ID_1303238476" MODIFIED="1682989331640" TEXT="Pend &lt; start &#x27f9; ins NOP-Predecessor"/>
<node CREATED="1682989363818" ID="ID_626589766" MODIFIED="1682989412757" TEXT="Pend == start &#x27f9; seamless"/>
<node CREATED="1682989432318" ID="ID_1285136346" MODIFIED="1682989453085" TEXT="Pend &lt;= after &#x27f9; truc(Predecessor)"/>
<node CREATED="1682989463146" ID="ID_1057868667" MODIFIED="1682990037890" TEXT="Pend &gt; after &#x27f9; split(Predecessor)">
<linktarget COLOR="#a9b4c1" DESTINATION="ID_1057868667" ENDARROW="Default" ENDINCLINATION="192;0;" ID="Arrow_ID_638145525" SOURCE="ID_242314941" STARTARROW="Default" STARTINCLINATION="321;12;"/>
</node>
</node>
<node CREATED="1682989518809" ID="ID_994366359" MODIFIED="1682989523086" TEXT="Pstart == start">
<node CREATED="1682989432318" ID="ID_1069008527" MODIFIED="1682989559145" TEXT="Pend &lt;= after &#x27f9; del(Predecessor)"/>
<node CREATED="1682989463146" ID="ID_514650224" MODIFIED="1682989628688" TEXT="Pend &gt; after &#x27f9; swap_trunc(Predecessor)"/>
</node>
<node CREATED="1682989799344" ID="ID_1899821024" MODIFIED="1682989806256" TEXT="Predecessor == Successor">
<node CREATED="1682989855439" ID="ID_7906079" MODIFIED="1682989886621" TEXT="Pend == after == Time::NEVER &#x27f9; trunc(Predecessor)"/>
<node CREATED="1682989964471" ID="ID_242314941" MODIFIED="1682990037890" TEXT="Pend &gt; after &#x27f9; split(Predecessor)">
<arrowlink DESTINATION="ID_1057868667" ENDARROW="Default" ENDINCLINATION="192;0;" ID="Arrow_ID_638145525" STARTARROW="Default" STARTINCLINATION="321;12;"/>
</node>
</node>
<node CREATED="1682990361746" ID="ID_540769988" MODIFIED="1682990378568" TEXT="Sstart &lt; after">
<node CREATED="1682990416619" ID="ID_1218355846" MODIFIED="1682990512242" TEXT="Send &lt; after &#x27f9; del(Successor) and ++Successor and recurse (same base case)"/>
<node CREATED="1682990517405" ID="ID_1733924563" MODIFIED="1682990537807" TEXT="Send == after &#x27f9; del(Successor)"/>
<node CREATED="1682990575017" ID="ID_1792970357" MODIFIED="1682990587208" TEXT="Send &gt; after &#x27f9; trunc(Successor)"/>
</node>
<node CREATED="1682990756277" ID="ID_1049988377" MODIFIED="1682990797692" TEXT="Sstart == after &#x27f9; seamless"/>
<node CREATED="1682990800343" ID="ID_744397196" MODIFIED="1682990839270" TEXT="after &lt; Sstart &#x27f9; ins NOP-Successor"/>
</node>
<node CREATED="1682986173785" ID="ID_1746212572" MODIFIED="1682986198143" TEXT="einf&#xfc;gen und l&#xf6;schen">
<icon BUILTIN="full-4"/>
<node CREATED="1682991925184" ID="ID_80874811" MODIFIED="1682991934113" TEXT="Predecessor">
<node CREATED="1682991935183" ID="ID_100248576" MODIFIED="1682991953832" TEXT="trunc &#x27f9; del"/>
<node CREATED="1682991959963" ID="ID_1359030638" MODIFIED="1682991991739" TEXT="split &#x27f9; del"/>
<node CREATED="1682991992375" ID="ID_1138806541" MODIFIED="1682991996168" TEXT="del &#x27f9; del"/>
<node CREATED="1682991997084" ID="ID_1555435391" MODIFIED="1682992007785" TEXT="swap_trunc &#x27f9; del"/>
</node>
<node CREATED="1682992015840" ID="ID_1551079661" MODIFIED="1682992017823" TEXT="Successor">
<node CREATED="1682992042818" ID="ID_750532199" MODIFIED="1682992082750" TEXT="de++ &#x27f9; del"/>
<node CREATED="1682992086602" ID="ID_79310561" MODIFIED="1682992091821" TEXT="trunc &#x27f9; del"/>
</node>
<node CREATED="1682992101946" ID="ID_556573150" MODIFIED="1682992140097" TEXT="insert">
<node CREATED="1682992189962" ID="ID_981883843" MODIFIED="1682992192417" TEXT="before">
<node CREATED="1682992193388" ID="ID_230175279" MODIFIED="1682992198623" TEXT="ins NOP-Predecessor"/>
<node CREATED="1682992206197" ID="ID_1040208552" MODIFIED="1682992381127" TEXT="trunc(Predecessor) &#x27f9; ins copy Predecessor-shortened-end"/>
<node CREATED="1682992241669" ID="ID_817365471" MODIFIED="1682992378287" TEXT="split(Predecessor) &#x27f9; ins copy Predecessor shortened-end"/>
</node>
<node CREATED="1682992335801" ID="ID_1805568665" MODIFIED="1682992339549" TEXT="new Segment"/>
<node CREATED="1682992340041" ID="ID_196520321" MODIFIED="1682992341444" TEXT="after">
<node CREATED="1682992352925" ID="ID_1724212588" MODIFIED="1682992384559" TEXT="split(Predecessor) &#x27f9; ins copy Predecessor shortened-start"/>
<node CREATED="1682992393801" ID="ID_1960696922" MODIFIED="1682992413823" TEXT="swap_trunc(Predecessor) &#x27f9; ins copy Predecessor shortened-start"/>
<node CREATED="1682992484030" ID="ID_1216933300" MODIFIED="1682992501055" TEXT="trunc(Successor) &#x27f9; ins copy Successor shortened-start"/>
<node CREATED="1682992519007" ID="ID_804784169" MODIFIED="1682992526523" TEXT="ins NOP-Successor"/>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1682993086565" ID="ID_469257294" MODIFIED="1682993090645" TEXT="Implementierung">
<icon BUILTIN="flag-yellow"/>
</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>
</node> </node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1682627621082" ID="ID_1110039315" MODIFIED="1682948822157" TEXT="ein Segment hinzuf&#xfc;gen"> <node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1682627621082" ID="ID_1110039315" MODIFIED="1682948822157" TEXT="ein Segment hinzuf&#xfc;gen">
<arrowlink COLOR="#48417c" DESTINATION="ID_1371147624" ENDARROW="Default" ENDINCLINATION="-48;56;" ID="Arrow_ID_1753796050" STARTARROW="None" STARTINCLINATION="-284;-8;"/> <arrowlink COLOR="#48417c" DESTINATION="ID_1371147624" ENDARROW="Default" ENDINCLINATION="-48;56;" ID="Arrow_ID_1753796050" STARTARROW="None" STARTINCLINATION="-284;-8;"/>