1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-18 06:54:26 +03:00
inform7/docs/BasicInformKit/S-rlt.html
Graham Nelson 1268a0f40e Colonised
2020-04-14 17:56:54 +01:00

2064 lines
416 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Relation Kind Template</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../index.html">
<img src="../docs-src/Figures/Inform.png" height=72">
</a></h1>
<ul><li><a href="../compiler.html">compiler tools</a></li>
<li><a href="../other.html">other tools</a></li>
<li><a href="../extensions.html">extensions and kits</a></li>
<li><a href="../units.html">unit test tools</a></li>
</ul><h2>Extensions</h2><ul>
<li><a href="../basic_inform/index.html">basic_inform</a></li>
<li><a href="../standard_rules/index.html">standard_rules</a></li>
</ul><h2>Kits</h2><ul>
<li><a href="index.html"><span class="selectedlink">BasicInformKit</span></a></li>
<li><a href="../BasicInformExtrasKit/index.html">BasicInformExtrasKit</a></li>
<li><a href="../CommandParserKit/index.html">CommandParserKit</a></li>
<li><a href="../EnglishLanguageKit/index.html">EnglishLanguageKit</a></li>
<li><a href="../WorldModelKit/index.html">WorldModelKit</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'Relation Kind Template' generated by 7-->
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../extensions.html">Kits</a></li><li><a href="index.html">BasicInformKit</a></li><li><b>Relation Kind Template</b></li></ul><p class="purpose">Code to support the relation kind.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Block Format</a></li><li><a href="#SP2">&#167;2. KOV Support</a></li><li><a href="#SP3">&#167;3. Other Definitions</a></li><li><a href="#SP4">&#167;4. Tunable Parameters</a></li><li><a href="#SP5">&#167;5. Abstract Relations</a></li><li><a href="#SP6">&#167;6. Empty Relations</a></li><li><a href="#SP7">&#167;7. Creation</a></li><li><a href="#SP8">&#167;8. Destruction</a></li><li><a href="#SP9">&#167;9. Copying</a></li><li><a href="#SP10">&#167;10. Comparison</a></li><li><a href="#SP11">&#167;11. Printing</a></li><li><a href="#SP12">&#167;12. Naming</a></li><li><a href="#SP13">&#167;13. Choose Relation Handler</a></li><li><a href="#SP14">&#167;14. Valency</a></li><li><a href="#SP15">&#167;15. Double Hash Set Relation Handler</a></li><li><a href="#SP16">&#167;16. Hash List Relation Handler</a></li><li><a href="#SP17">&#167;17. Hash Table Relation Handler</a></li><li><a href="#SP18">&#167;18. Reversed Hash Table Relation Handler</a></li><li><a href="#SP19">&#167;19. Symmetric Relation Handlers</a></li><li><a href="#SP20">&#167;20. Hash Core Relation Handler</a></li><li><a href="#SP21">&#167;21. Equivalence Hash Table Relation Handler</a></li><li><a href="#SP22">&#167;22. Two-In-One Hash Table Relation Handler</a></li><li><a href="#SP23">&#167;23. Empty</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Block Format. </b>Inform uses a rich variety of relations, with many different data representations,
but we aim to hide that complexity from the user. At run-time, a relation is
represented by a block value. The short block of this BV is simply a pointer
to a long block. This always begins with at least six words of metadata, but
actual data sometimes follows on, and sometimes doesn't: and its format is
something the customer needn't know about.
</p>
<p class="inwebparagraph">The low-level routines in "Relations.i6t" access this metadata by direct use
of <code class="display"><span class="extract">--&gt;</span></code>, for speed, and they use the offset constants <code class="display"><span class="extract">RR_NAME</span></code> and so on;
but we will use the <code class="display"><span class="extract">BlkValueRead</span></code> and <code class="display"><span class="extract">BlkValueWrite</span></code> routines in this
section, which need offsets in the form <code class="display"><span class="extract">RRV_NAME</span></code>. (The discrepancy of 5 is
to allow for the five-word block header.)
</p>
<pre class="display">
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRV_NAME</span><span class="plain"> </span><span class="identifier">RR_NAME</span><span class="plain">-5; </span><span class="comment">Packed string, e.g. "containment relation"</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRV_PERMISSIONS</span><span class="plain"> </span><span class="identifier">RR_PERMISSIONS</span><span class="plain">-5; </span><span class="comment">A bitmap of what operations this supports</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRV_STORAGE</span><span class="plain"> </span><span class="identifier">RR_STORAGE</span><span class="plain">-5; </span><span class="comment">Data location, depending on format</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRV_KIND</span><span class="plain"> </span><span class="identifier">RR_KIND</span><span class="plain">-5; </span><span class="comment">Strong kind ID of the relation</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRV_HANDLER</span><span class="plain"> </span><span class="identifier">RR_HANDLER</span><span class="plain">-5; </span><span class="comment">Routine to perform operations on this</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRV_DESCRIPTION</span><span class="plain"> </span><span class="identifier">RR_DESCRIPTION</span><span class="plain">-5; </span><span class="comment">Packed string, e.g. "contains"</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRV_USED</span><span class="plain"> </span><span class="constant">6</span><span class="plain">;</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRV_FILLED</span><span class="plain"> </span><span class="constant">7</span><span class="plain">;</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> </span><span class="constant">8</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. KOV Support. </b>See the "BlockValues.i6t" segment for the specification of the following
routines.
</p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">RELATION_TY_Support</span><span class="plain"> </span><span class="identifier">task</span><span class="plain"> </span><span class="identifier">arg1</span><span class="plain"> </span><span class="identifier">arg2</span><span class="plain"> </span><span class="identifier">arg3</span><span class="plain">;</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">task</span><span class="plain">) {</span>
<span class="identifier">CREATE_KOVS</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">RELATION_TY_Create</span><span class="plain">(</span><span class="identifier">arg1</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">arg2</span><span class="plain">);</span>
<span class="identifier">DESTROY_KOVS</span><span class="plain">: </span><span class="identifier">RELATION_TY_Destroy</span><span class="plain">(</span><span class="identifier">arg1</span><span class="plain">);</span>
<span class="identifier">MAKEMUTABLE_KOVS</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">1</span><span class="plain">;</span>
<span class="identifier">COPYQUICK_KOVS</span><span class="plain">: </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="identifier">COPYSB_KOVS</span><span class="plain">: </span><span class="identifier">BlkValueCopySB1</span><span class="plain">(</span><span class="identifier">arg1</span><span class="plain">, </span><span class="identifier">arg2</span><span class="plain">);</span>
<span class="identifier">KINDDATA_KOVS</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">EXTENT_KOVS</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> -1;</span>
<span class="identifier">COPY_KOVS</span><span class="plain">: </span><span class="identifier">RELATION_TY_Copy</span><span class="plain">(</span><span class="identifier">arg1</span><span class="plain">, </span><span class="identifier">arg2</span><span class="plain">);</span>
<span class="identifier">COMPARE_KOVS</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">RELATION_TY_Compare</span><span class="plain">(</span><span class="identifier">arg1</span><span class="plain">, </span><span class="identifier">arg2</span><span class="plain">);</span>
<span class="identifier">HASH_KOVS</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">arg1</span><span class="plain">;</span>
<span class="identifier">DEBUG_KOVS</span><span class="plain">: </span><span class="reserved">print</span><span class="plain"> </span><span class="string">" = "</span><span class="plain">, (</span><span class="identifier">RELATION_TY_Say</span><span class="plain">) </span><span class="identifier">arg1</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="comment">We choose not to respond to: CAST_KOVS, COPYKIND_KOVS, READ_FILE_KOVS, WRITE_FILE_KOVS</span>
<span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. Other Definitions. </b></p>
<pre class="display">
<span class="comment">valencies</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRVAL_V_TO_V</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRVAL_V_TO_O</span><span class="plain"> </span><span class="identifier">RELS_Y_UNIQUE</span><span class="plain">;</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRVAL_O_TO_V</span><span class="plain"> </span><span class="identifier">RELS_X_UNIQUE</span><span class="plain">;</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRVAL_O_TO_O</span><span class="plain"> </span><span class="identifier">RELS_X_UNIQUE</span><span class="plain">+</span><span class="identifier">RELS_Y_UNIQUE</span><span class="plain">;</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRVAL_EQUIV</span><span class="plain"> </span><span class="identifier">RELS_EQUIVALENCE</span><span class="plain">+</span><span class="identifier">RELS_SYMMETRIC</span><span class="plain">;</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRVAL_SYM_V_TO_V</span><span class="plain"> </span><span class="identifier">RELS_SYMMETRIC</span><span class="plain">;</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRVAL_SYM_O_TO_O</span><span class="plain"> </span><span class="identifier">RELS_SYMMETRIC</span><span class="plain">+</span><span class="identifier">RELS_X_UNIQUE</span><span class="plain">+</span><span class="identifier">RELS_Y_UNIQUE</span><span class="plain">;</span>
<span class="comment">dictionary entry flags</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRF_USED</span><span class="plain"> </span><span class="constant">$0001</span><span class="plain">; </span><span class="comment">entry contains a value</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRF_DELETED</span><span class="plain"> </span><span class="constant">$0002</span><span class="plain">; </span><span class="comment">entry used to contain a value</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRF_SINGLE</span><span class="plain"> </span><span class="constant">$0004</span><span class="plain">; </span><span class="comment">entry's Y is a value, not a list</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRF_HASX</span><span class="plain"> </span><span class="constant">$0010</span><span class="plain">; </span><span class="comment">2-in-1 entry contains a corresponding key</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRF_HASY</span><span class="plain"> </span><span class="constant">$0020</span><span class="plain">; </span><span class="comment">2-in-1 entry contains a corresponding value</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRF_ENTKEYX</span><span class="plain"> </span><span class="constant">$0040</span><span class="plain">; </span><span class="comment">2-in-1 entry key is left side KOV</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRF_ENTKEYY</span><span class="plain"> </span><span class="constant">$0080</span><span class="plain">; </span><span class="comment">2-in-1 entry key is right side KOV</span>
<span class="comment">permission/task constants (those commented out here are generated by I7)</span>
<span class="comment">onstant RELS_SYMMETRIC \(8000;</span>
<span class="comment">onstant RELS_EQUIVALENCE \(4000;</span>
<span class="comment">onstant RELS_X_UNIQUE \(2000;</span>
<span class="comment">onstant RELS_Y_UNIQUE \(1000;</span>
<span class="comment">onstant RELS_TEST \(0800;</span>
<span class="comment">onstant RELS_ASSERT_TRUE \(0400;</span>
<span class="comment">onstant RELS_ASSERT_FALSE \(0200;</span>
<span class="comment">onstant RELS_SHOW \(0100;</span>
<span class="comment">onstant RELS_ROUTE_FIND \(0080;</span>
<span class="comment">onstant RELS_ROUTE_FIND_COUNT \(0040;</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RELS_COPY</span><span class="plain"> </span><span class="constant">$0020</span><span class="plain">;</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RELS_DESTROY</span><span class="plain"> </span><span class="constant">$0010</span><span class="plain">;</span>
<span class="comment">onstant RELS_LOOKUP_ANY \(0008;</span>
<span class="comment">onstant RELS_LOOKUP_ALL_X \(0004;</span>
<span class="comment">onstant RELS_LOOKUP_ALL_Y \(0002;</span>
<span class="comment">onstant RELS_LIST \(0001;</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RELS_EMPTY</span><span class="plain"> </span><span class="constant">$0003</span><span class="plain">;</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RELS_SET_VALENCY</span><span class="plain"> </span><span class="constant">$0005</span><span class="plain">;</span>
<span class="comment">RELS_LOOKUP_ANY mode selection constants</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RLANY_GET_X</span><span class="plain"> </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RLANY_GET_Y</span><span class="plain"> </span><span class="constant">2</span><span class="plain">;</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RLANY_CAN_GET_X</span><span class="plain"> </span><span class="constant">3</span><span class="plain">;</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RLANY_CAN_GET_Y</span><span class="plain"> </span><span class="constant">4</span><span class="plain">;</span>
<span class="comment">RELS_LIST mode selection constant</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RLIST_ALL_X</span><span class="plain"> </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RLIST_ALL_Y</span><span class="plain"> </span><span class="constant">2</span><span class="plain">;</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RLIST_ALL_PAIRS</span><span class="plain"> </span><span class="constant">3</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Tunable Parameters. </b>These constants affect the performance characteristics of the dictionary
structures used for relations on the heap. Changing their values may alter the
balance between memory consumption and running time.
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">RRP_MIN_SIZE</span></code>, <code class="display"><span class="extract">RRP_RESIZE_SMALL</span></code>, and <code class="display"><span class="extract">RRP_RESIZE_LARGE</span></code> must all be
powers of two.
</p>
<pre class="display">
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRP_MIN_SIZE</span><span class="plain"> </span><span class="constant">8</span><span class="plain">; </span><span class="comment">minimum number of entries (DO NOT CHANGE)</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRP_PERTURB_SHIFT</span><span class="plain"> </span><span class="constant">5</span><span class="plain">; </span><span class="comment">affects the probe sequence</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">MINUS_RRP_PERTURB_SHIFT</span><span class="plain"> -5; </span><span class="comment">affects the probe sequence</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRP_RESIZE_SMALL</span><span class="plain"> </span><span class="constant">4</span><span class="plain">; </span><span class="comment">resize factor for small tables</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRP_RESIZE_LARGE</span><span class="plain"> </span><span class="constant">2</span><span class="plain">; </span><span class="comment">resize factor for large tables</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRP_LARGE_IS</span><span class="plain"> </span><span class="constant">256</span><span class="plain">; </span><span class="comment">how many entries make a table "large"?</span>
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">RRP_CROWDED_IS</span><span class="plain"> </span><span class="constant">2</span><span class="plain">; </span><span class="comment">when filled entries outnumber unfilled by _ to 1</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. Abstract Relations. </b>As the following shows, we can abstractly use a relation &mdash; that is, we can
use a relation whose identity we know little about &mdash; by calling its handler
routine <code class="display"><span class="extract">R</span></code> in the form <code class="display"><span class="extract">R(rel, task, X, Y)</span></code>.
</p>
<p class="inwebparagraph">The task should be one of: <code class="display"><span class="extract">RELS_TEST</span></code>, <code class="display"><span class="extract">RELS_ASSERT_TRUE</span></code>, <code class="display"><span class="extract">RELS_ASSERT_FALSE</span></code>,
<code class="display"><span class="extract">RELS_SHOW</span></code>, <code class="display"><span class="extract">RELS_ROUTE_FIND</span></code>, <code class="display"><span class="extract">RELS_ROUTE_FIND_COUNT</span></code>, <code class="display"><span class="extract">RELS_COPY</span></code>,
<code class="display"><span class="extract">RELS_DESTROY</span></code>, <code class="display"><span class="extract">RELS_LOOKUP_ANY</span></code>, <code class="display"><span class="extract">RELS_LOOKUP_ALL_X</span></code>, <code class="display"><span class="extract">RELS_LOOKUP_ALL_Y</span></code>,
<code class="display"><span class="extract">RELS_LIST</span></code>, or <code class="display"><span class="extract">RELS_EMPTY</span></code>.
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">RELS_SHOW</span></code> produces output for the SHOWME testing command.
<code class="display"><span class="extract">RELS_ROUTE_FIND</span></code> finds the next step in a route from <code class="display"><span class="extract">X</span></code> to <code class="display"><span class="extract">Y</span></code>, and
<code class="display"><span class="extract">RELS_ROUTE_FIND_COUNT</span></code> counts the shortest number of steps or returns \(-1\)
if no route exists. <code class="display"><span class="extract">RELS_COPY</span></code> makes a deep copy of the relation by
replacing all block values with duplicates, and <code class="display"><span class="extract">RELS_DESTROY</span></code> frees all
block values. <code class="display"><span class="extract">RELS_LOOKUP_ANY</span></code> finds any one of the <code class="display"><span class="extract">X</span></code> values related to
a given <code class="display"><span class="extract">Y</span></code>, or vice versa, or checks whether such an <code class="display"><span class="extract">X</span></code> or <code class="display"><span class="extract">Y</span></code> value
exists. <code class="display"><span class="extract">RELS_LOOKUP_ALL_X</span></code> and <code class="display"><span class="extract">RELS_LOOKUP_ALL_Y</span></code> produce a list of all
the <code class="display"><span class="extract">X</span></code> values related to a given <code class="display"><span class="extract">Y</span></code>, or vice versa. <code class="display"><span class="extract">RELS_LIST</span></code> produces
a list of all <code class="display"><span class="extract">X</span></code> values for which a corresponding <code class="display"><span class="extract">Y</span></code> exists, or vice
versa, or a list of all <code class="display"><span class="extract">(X,Y)</span></code> pairs for which <code class="display"><span class="extract">X</span></code> is related to <code class="display"><span class="extract">Y</span></code>.
<code class="display"><span class="extract">RELS_EMPTY</span></code> either makes the relation empty (if <code class="display"><span class="extract">X</span></code> is 1) or non-empty (if
<code class="display"><span class="extract">X</span></code> is 0) or makes no change (if <code class="display"><span class="extract">X</span></code> is negative), and in any case returns
true or false indicating whether the relation is now empty.
</p>
<p class="inwebparagraph">Because not every relation supports all of these operations, the
"permissions" word in the block is always a bitmap which is a sum of those
operations it does offer.
</p>
<p class="inwebparagraph">At present, these permissions are not checked as rigorously as they should be
(they're correctly set, but not much monitored).
</p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">RelationTest</span><span class="plain"> </span><span class="identifier">relation</span><span class="plain"> </span><span class="identifier">task</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain"> </span><span class="identifier">handler</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
<span class="identifier">handler</span><span class="plain"> = </span><span class="identifier">RlnGetF</span><span class="plain">(</span><span class="identifier">relation</span><span class="plain">, </span><span class="identifier">RR_HANDLER</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">handler</span><span class="plain">(</span><span class="identifier">relation</span><span class="plain">, </span><span class="identifier">task</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="plain">];</span>
<span class="plain">[ </span><span class="identifier">RlnGetF</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">fld</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="identifier">rel</span><span class="plain"> = </span><span class="identifier">BlkValueGetLongBlock</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain">--&gt;</span><span class="identifier">fld</span><span class="plain">;</span>
<span class="plain">];</span>
<span class="plain">[ </span><span class="identifier">RlnSetF</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">fld</span><span class="plain"> </span><span class="identifier">v</span><span class="plain">;</span>
<span class="identifier">rel</span><span class="plain"> = </span><span class="identifier">BlkValueGetLongBlock</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">);</span>
<span class="identifier">rel</span><span class="plain">--&gt;</span><span class="identifier">fld</span><span class="plain"> = </span><span class="identifier">v</span><span class="plain">;</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. Empty Relations. </b>The absolute minimum relation is one which can only be tested, and which is
always empty, that is, where no two values are ever related to each other.
The necessary handler routine is <code class="display"><span class="extract">EmptyRelationHandler</span></code>.
</p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">EmptyRelationHandler</span><span class="plain"> </span><span class="identifier">relation</span><span class="plain"> </span><span class="identifier">task</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_EMPTY</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. Creation. </b>Something we have to be careful about is what we mean by copying, or indeed
creating, a relation. For example, if we write
</p>
<blockquote>
<p>let Q be a relation of objects to objects;</p>
</blockquote>
<blockquote>
<p>let Q be the containment relation;</p>
</blockquote>
<p class="inwebparagraph">...we aren't literally asking for Q to be a duplicate copy of containment,
which can then independently evolve &mdash; we mean in some sense that Q is a
pointer to the one and only containment relation. On the other hand, if we
write
</p>
<blockquote>
<p>let Q be a relation of numbers to numbers;</p>
</blockquote>
<blockquote>
<p>make Q relate 3 to 7;</p>
</blockquote>
<p class="inwebparagraph">then the second line clearly expects Q to be its own relation, newly created.
</p>
<p class="inwebparagraph">We cope with this at creation time. If we're invited to create a copy of an
existing relation, we look to see if it is empty &mdash; which we detect by its
use of the <code class="display"><span class="extract">EmptyRelationHandler</span></code> handler. The empty relations are exactly
those used as default values for the relation kinds; thus that's what will
happen when Q is created. If we find this handler, we intercept and replace
it with one of the heap relation handlers, which thus makes the relation a
newly constructed data structure which can grow freely from here.
</p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">RELATION_TY_Create</span><span class="plain"> </span><span class="identifier">kov</span><span class="plain"> </span><span class="identifier">from</span><span class="plain"> </span><span class="identifier">sb</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> </span><span class="identifier">skov</span><span class="plain"> </span><span class="identifier">handler</span><span class="plain">;</span>
<span class="identifier">rel</span><span class="plain"> = </span><span class="identifier">FlexAllocate</span><span class="plain">((</span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">RRP_MIN_SIZE</span><span class="plain">)*</span><span class="identifier">WORDSIZE</span><span class="plain">,</span>
<span class="identifier">RELATION_TY</span><span class="plain">, </span><span class="identifier">BLK_FLAG_WORD</span><span class="plain">+</span><span class="identifier">BLK_FLAG_MULTIPLE</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">from</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) &amp;&amp; (</span><span class="identifier">kov</span><span class="plain"> ~= </span><span class="constant">0</span><span class="plain">)) </span><span class="identifier">from</span><span class="plain"> = </span><span class="identifier">DefaultValueFinder</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0: </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">RRV_DATA_BASE</span><span class="plain">: </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">), </span><span class="reserved">true</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">RRV_HANDLER</span><span class="plain">) == </span><span class="identifier">EmptyRelationHandler</span><span class="plain">) {</span>
<span class="identifier">handler</span><span class="plain"> = </span><span class="identifier">ChooseRelationHandler</span><span class="plain">(</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_KIND</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">));</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_NAME</span><span class="plain">, </span><span class="string">"anonymous relation"</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_PERMISSIONS</span><span class="plain">,</span>
<span class="identifier">RELS_TEST</span><span class="plain">+</span><span class="identifier">RELS_ASSERT_TRUE</span><span class="plain">+</span><span class="identifier">RELS_ASSERT_FALSE</span><span class="plain">+</span><span class="identifier">RELS_SHOW</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_HANDLER</span><span class="plain">, </span><span class="identifier">handler</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">, </span><span class="identifier">RRP_MIN_SIZE</span><span class="plain">-1, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DESCRIPTION</span><span class="plain">, </span><span class="string">"an anonymous relation"</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">handler</span><span class="plain"> = </span><span class="identifier">ChooseRelationHandler</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_NAME</span><span class="plain">, </span><span class="string">"anonymous relation"</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_PERMISSIONS</span><span class="plain">,</span>
<span class="identifier">RELS_TEST</span><span class="plain">+</span><span class="identifier">RELS_ASSERT_TRUE</span><span class="plain">+</span><span class="identifier">RELS_ASSERT_FALSE</span><span class="plain">+</span><span class="identifier">RELS_SHOW</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">, </span><span class="identifier">RRP_MIN_SIZE</span><span class="plain">-1, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_KIND</span><span class="plain">, </span><span class="identifier">kov</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_HANDLER</span><span class="plain">, </span><span class="identifier">handler</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DESCRIPTION</span><span class="plain">, </span><span class="string">"an anonymous relation"</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">BlkValueCreateSB1</span><span class="plain">(</span><span class="identifier">sb</span><span class="plain">, </span><span class="identifier">rel</span><span class="plain">);</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. Destruction. </b>If the relation stores block values on either side, invoke the handler using a special task
value to free the memory associated with them.
</p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">RELATION_TY_Destroy</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">handler</span><span class="plain">;</span>
<span class="identifier">handler</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_HANDLER</span><span class="plain">);</span>
<span class="identifier">handler</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RELS_DESTROY</span><span class="plain">);</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. Copying. </b>Same as destruction: invoke the handler using a special value to tell it to perform
deep copying.
</p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">RELATION_TY_Copy</span><span class="plain"> </span><span class="identifier">lto</span><span class="plain"> </span><span class="identifier">lfrom</span><span class="plain"> </span><span class="identifier">handler</span><span class="plain">;</span>
<span class="identifier">handler</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">lto</span><span class="plain">, </span><span class="identifier">RRV_HANDLER</span><span class="plain">);</span>
<span class="identifier">handler</span><span class="plain">(</span><span class="identifier">lto</span><span class="plain">, </span><span class="identifier">RELS_COPY</span><span class="plain">);</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. Comparison. </b>It really isn't clear how to define equality for relations, but we follow
the doctrine above. What we don't do is to test its actual state &mdash; that
would be very slow and might be impossible.
</p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">RELATION_TY_Compare</span><span class="plain"> </span><span class="identifier">rleft</span><span class="plain"> </span><span class="identifier">rright</span><span class="plain"> </span><span class="identifier">ind1</span><span class="plain"> </span><span class="identifier">ind2</span><span class="plain">;</span>
<span class="identifier">ind1</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rleft</span><span class="plain">, </span><span class="identifier">RRV_HANDLER</span><span class="plain">);</span>
<span class="identifier">ind2</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rright</span><span class="plain">, </span><span class="identifier">RRV_HANDLER</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ind1</span><span class="plain"> ~= </span><span class="identifier">ind2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">ind1</span><span class="plain"> - </span><span class="identifier">ind2</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">IsMutableRelationHandler</span><span class="plain">(</span><span class="identifier">ind1</span><span class="plain">) == </span><span class="reserved">false</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rleft</span><span class="plain"> - </span><span class="identifier">rright</span><span class="plain">;</span>
<span class="plain">];</span>
<span class="plain">[ </span><span class="identifier">RELATION_TY_Distinguish</span><span class="plain"> </span><span class="identifier">rleft</span><span class="plain"> </span><span class="identifier">rright</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">RELATION_TY_Compare</span><span class="plain">(</span><span class="identifier">rleft</span><span class="plain">, </span><span class="identifier">rright</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. Printing. </b></p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">RELATION_TY_Say</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rel</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">print</span><span class="plain"> </span><span class="string">"(null relation)"</span><span class="plain">; </span><span class="comment">shouldn't happen</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">print</span><span class="plain"> (</span><span class="reserved">string</span><span class="plain">) </span><span class="identifier">RlnGetF</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RR_NAME</span><span class="plain">);</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. Naming. </b></p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">RELATION_TY_Name</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">txt</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rel</span><span class="plain">) {</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_NAME</span><span class="plain">, </span><span class="identifier">txt</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DESCRIPTION</span><span class="plain">, </span><span class="identifier">txt</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. Choose Relation Handler. </b>We implement two different various-to-various handler routines for the
sake of efficiency. The choice of handler routines is made based on
the kinds of value being related. Each handler also has a corresponding
wrapper for symmetric relations.
</p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">ChooseRelationHandler</span><span class="plain"> </span><span class="identifier">kov</span><span class="plain"> </span><span class="identifier">sym</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="constant">0</span><span class="plain">))) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sym</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">SymHashListRelationHandler</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">HashListRelationHandler</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sym</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">SymDoubleHashSetRelationHandler</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">DoubleHashSetRelationHandler</span><span class="plain">;</span>
<span class="plain">];</span>
<span class="plain">[ </span><span class="identifier">IsMutableRelationHandler</span><span class="plain"> </span><span class="identifier">h</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain"> == </span><span class="identifier">SymHashListRelationHandler</span><span class="plain"> </span><span class="reserved">or</span><span class="plain"> </span><span class="identifier">HashListRelationHandler</span><span class="plain"> </span><span class="reserved">or</span>
<span class="identifier">SymDoubleHashSetRelationHandler</span><span class="plain"> </span><span class="reserved">or</span><span class="plain"> </span><span class="identifier">DoubleHashSetRelationHandler</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. Valency. </b>"Valency" refers to the number of participants allowed on either side
of the relation: various-to-various, one-to-various, various-to-one, or
one-to-one. A newly created relation is always various-to-various. We
allow the author to change the valency, but only if no entries have
been added yet.
</p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">RELATION_TY_SetValency</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">val</span><span class="plain"> </span><span class="identifier">kov</span><span class="plain"> </span><span class="identifier">filled</span><span class="plain"> </span><span class="identifier">cur</span><span class="plain"> </span><span class="identifier">handler</span><span class="plain"> </span><span class="identifier">ext</span><span class="plain">;</span>
<span class="identifier">filled</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">filled</span><span class="plain">) { </span><span class="identifier">RunTimeProblem</span><span class="plain">(</span><span class="identifier">RTP_RELATIONCHANGEIMPOSSIBLE</span><span class="plain">); </span><span class="reserved">rfalse</span><span class="plain">; }</span>
<span class="identifier">kov</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_KIND</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">val</span><span class="plain"> == </span><span class="identifier">RRVAL_EQUIV</span><span class="plain"> </span><span class="reserved">or</span><span class="plain"> </span><span class="identifier">RRVAL_SYM_V_TO_V</span><span class="plain"> </span><span class="reserved">or</span><span class="plain"> </span><span class="identifier">RRVAL_SYM_O_TO_O</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="constant">0</span><span class="plain">) ~= </span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="constant">1</span><span class="plain">)) {</span>
<span class="identifier">RunTimeProblem</span><span class="plain">(</span><span class="identifier">RTP_RELATIONCHANGEIMPOSSIBLE</span><span class="plain">); </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">cur</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_HANDLER</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">val</span><span class="plain">) {</span>
<span class="identifier">RRVAL_V_TO_V</span><span class="plain">: </span><span class="identifier">handler</span><span class="plain"> = </span><span class="identifier">ChooseRelationHandler</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="reserved">false</span><span class="plain">);</span>
<span class="identifier">RRVAL_V_TO_O</span><span class="plain">: </span><span class="identifier">handler</span><span class="plain"> = </span><span class="identifier">HashTableRelationHandler</span><span class="plain">;</span>
<span class="identifier">RRVAL_O_TO_V</span><span class="plain">: </span><span class="identifier">handler</span><span class="plain"> = </span><span class="identifier">ReversedHashTableRelationHandler</span><span class="plain">;</span>
<span class="identifier">RRVAL_O_TO_O</span><span class="plain">: </span><span class="identifier">handler</span><span class="plain"> = </span><span class="identifier">TwoInOneHashTableRelationHandler</span><span class="plain">;</span>
<span class="identifier">RRVAL_EQUIV</span><span class="plain">: </span><span class="identifier">handler</span><span class="plain"> = </span><span class="identifier">EquivHashTableRelationHandler</span><span class="plain">;</span>
<span class="identifier">RRVAL_SYM_V_TO_V</span><span class="plain">: </span><span class="identifier">handler</span><span class="plain"> = </span><span class="identifier">ChooseRelationHandler</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">RRVAL_SYM_O_TO_O</span><span class="plain">: </span><span class="identifier">handler</span><span class="plain"> = </span><span class="identifier">Sym2in1HashTableRelationHandler</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">: </span><span class="identifier">RunTimeProblem</span><span class="plain">(</span><span class="identifier">RTP_RELATIONCHANGEIMPOSSIBLE</span><span class="plain">); </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cur</span><span class="plain"> == </span><span class="identifier">handler</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="comment">adjust size when going to or from 2-in-1</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cur</span><span class="plain"> == </span><span class="identifier">TwoInOneHashTableRelationHandler</span><span class="plain">) {</span>
<span class="identifier">ext</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">;</span>
<span class="identifier">BlkValueSetLBCapacity</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">ext</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">handler</span><span class="plain"> == </span><span class="identifier">TwoInOneHashTableRelationHandler</span><span class="plain">) {</span>
<span class="identifier">ext</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">;</span>
<span class="identifier">BlkValueSetLBCapacity</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">ext</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_HANDLER</span><span class="plain">, </span><span class="identifier">handler</span><span class="plain">);</span>
<span class="plain">];</span>
<span class="plain">[ </span><span class="identifier">RELATION_TY_GetValency</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">handler</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_PERMISSIONS</span><span class="plain">) &amp; </span><span class="identifier">VALENCY_MASK</span><span class="plain">;</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. Double Hash Set Relation Handler. </b>This implements relations which are stored as a double-hashed set.
The storage comprises a list of three-word entries \((F, X, Y)\), where
\(F\) is a flags word. The ordering of the list is determined by a probe
sequence which depends on the combined hash values of \(X\) and \(Y\).
</p>
<p class="inwebparagraph">The "storage" word in the header stores one less than the number of
entries in the list; the number of entries in the list is always a
power of two, so this will always be a bit mask. The "used" and
"filled" words store the number of entries which currently hold a
value, and the number of entries which have ever held a value (even
if it was since deleted), respectively.
</p>
<p class="inwebparagraph">The utility routine <code class="display"><span class="extract">DoubleHashSetLookUp</span></code> locates the hash entry for
a key/value pair. It returns either the (non-negative) number of the
entry where the pair was found, or the (negative) bitwise NOT of the
number of the first unused entry where the pair could be inserted. It
uses the utility routine <code class="display"><span class="extract">DoubleHashSetEntryMatches</span></code> to compare
entries to the sought pair.
</p>
<p class="inwebparagraph">The utility routine <code class="display"><span class="extract">DoubleHashSetCheckResize</span></code> checks whether the
dictionary has become too full after inserting a pair, and expands it
if so.
</p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">DoubleHashSetRelationHandler</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">task</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain"> </span><span class="identifier">sym</span><span class="plain"> </span><span class="identifier">kov</span><span class="plain"> </span><span class="identifier">kx</span><span class="plain"> </span><span class="identifier">ky</span><span class="plain"> </span><span class="identifier">at</span><span class="plain"> </span><span class="identifier">tmp</span><span class="plain"> </span><span class="identifier">v</span><span class="plain">;</span>
<span class="identifier">kov</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_KIND</span><span class="plain">);</span>
<span class="identifier">kx</span><span class="plain"> = </span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="constant">0</span><span class="plain">); </span><span class="identifier">ky</span><span class="plain"> = </span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_SET_VALENCY</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">RELATION_TY_SetValency</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_DESTROY</span><span class="plain">) {</span>
<span class="comment">clear</span>
<span class="identifier">kx</span><span class="plain"> = </span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">); </span><span class="identifier">ky</span><span class="plain"> = </span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (~~(</span><span class="identifier">kx</span><span class="plain"> || </span><span class="identifier">ky</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tmp</span><span class="plain"> &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kx</span><span class="plain">) </span><span class="identifier">BlkValueFree</span><span class="plain">(</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ky</span><span class="plain">) </span><span class="identifier">BlkValueFree</span><span class="plain">(</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="identifier">at</span><span class="plain">--;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_COPY</span><span class="plain">) {</span>
<span class="identifier">X</span><span class="plain"> = </span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">); </span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (~~(</span><span class="identifier">X</span><span class="plain"> || </span><span class="identifier">Y</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">);</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tmp</span><span class="plain"> &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">X</span><span class="plain">) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueCopy</span><span class="plain">(</span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">), </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain">) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueCopy</span><span class="plain">(</span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">), </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">at</span><span class="plain">--;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_SHOW</span><span class="plain">) {</span>
<span class="reserved">print</span><span class="plain"> (</span><span class="reserved">string</span><span class="plain">) </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DESCRIPTION</span><span class="plain">), </span><span class="string">":^"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sym</span><span class="plain">) {</span>
<span class="identifier">kov</span><span class="plain"> = </span><span class="identifier">KOVComparisonFunction</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (~~</span><span class="identifier">kov</span><span class="plain">) </span><span class="identifier">kov</span><span class="plain"> = </span><span class="identifier">UnsignedCompare</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tmp</span><span class="plain"> &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="identifier">X</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sym</span><span class="plain"> &amp;&amp; (</span><span class="identifier">kov</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">)) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="reserved">print</span><span class="plain"> </span><span class="string">" "</span><span class="plain">;</span>
<span class="identifier">PrintKindValuePair</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sym</span><span class="plain">) </span><span class="reserved">print</span><span class="plain"> </span><span class="string">" &lt;=&gt; "</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">print</span><span class="plain"> </span><span class="string">" &gt;=&gt; "</span><span class="plain">;</span>
<span class="identifier">PrintKindValuePair</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="reserved">print</span><span class="plain"> </span><span class="string">"^"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_EMPTY</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">X</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">) {</span>
<span class="identifier">DoubleHashSetRelationHandler</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RELS_DESTROY</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_LOOKUP_ANY</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">) &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain"> == </span><span class="identifier">RLANY_GET_X</span><span class="plain"> </span><span class="reserved">or</span><span class="plain"> </span><span class="identifier">RLANY_CAN_GET_X</span><span class="plain">) {</span>
<span class="identifier">v</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueCompare</span><span class="plain">(</span><span class="identifier">v</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">) ~= </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">v</span><span class="plain"> ~= </span><span class="identifier">X</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain"> == </span><span class="identifier">RLANY_CAN_GET_X</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">v</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueCompare</span><span class="plain">(</span><span class="identifier">v</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">) ~= </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">v</span><span class="plain"> ~= </span><span class="identifier">X</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain"> == </span><span class="identifier">RLANY_CAN_GET_Y</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain"> == </span><span class="identifier">RLANY_GET_X</span><span class="plain"> </span><span class="reserved">or</span><span class="plain"> </span><span class="identifier">RLANY_GET_Y</span><span class="plain">)</span>
<span class="reserved">print</span><span class="plain"> </span><span class="string">"*** Lookup failed: value not found ***^"</span><span class="plain">;</span>
<span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_LOOKUP_ALL_X</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueWeakKind</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">) ~= </span><span class="identifier">LIST_OF_TY</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="identifier">LIST_OF_TY_SetLength</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">) &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="identifier">v</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueCompare</span><span class="plain">(</span><span class="identifier">v</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">) ~= </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">v</span><span class="plain"> ~= </span><span class="identifier">X</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">LIST_OF_TY_InsertItem</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_LOOKUP_ALL_Y</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueWeakKind</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">) ~= </span><span class="identifier">LIST_OF_TY</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="identifier">LIST_OF_TY_SetLength</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">) &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="identifier">v</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueCompare</span><span class="plain">(</span><span class="identifier">v</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">) ~= </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">v</span><span class="plain"> ~= </span><span class="identifier">X</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">LIST_OF_TY_InsertItem</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_LIST</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">X</span><span class="plain"> == </span><span class="constant">0</span><span class="plain"> || </span><span class="identifier">BlkValueWeakKind</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">) ~= </span><span class="identifier">LIST_OF_TY</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="identifier">LIST_OF_TY_SetLength</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain">) {</span>
<span class="identifier">RLIST_ALL_X</span><span class="plain">, </span><span class="identifier">RLIST_ALL_Y</span><span class="plain">:</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">) &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="identifier">tmp</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain"> == </span><span class="identifier">RLIST_ALL_Y</span><span class="plain">) </span><span class="identifier">tmp</span><span class="plain">++;</span>
<span class="identifier">v</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="identifier">LIST_OF_TY_InsertItem</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">v</span><span class="plain">, </span><span class="reserved">false</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">X</span><span class="plain">;</span>
<span class="identifier">RLIST_ALL_PAIRS</span><span class="plain">:</span>
<span class="comment">LIST_OF_TY_InsertItem will make a deep copy of the item,</span>
<span class="comment">so we can reuse a single combination value here</span>
<span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">) &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="identifier">v</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">COMBINATION_ITEM_BASE</span><span class="plain">, </span><span class="identifier">v</span><span class="plain">);</span>
<span class="identifier">v</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">COMBINATION_ITEM_BASE</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">v</span><span class="plain">);</span>
<span class="identifier">LIST_OF_TY_InsertItem</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">COMBINATION_ITEM_BASE</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">COMBINATION_ITEM_BASE</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueFree</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">X</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">DoubleHashSetLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">task</span><span class="plain">) {</span>
<span class="identifier">RELS_TEST</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="reserved">rfalse</span><span class="plain">;</span>
<span class="identifier">RELS_ASSERT_TRUE</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="identifier">at</span><span class="plain"> = ~</span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">RRF_USED</span><span class="plain">+</span><span class="identifier">RRF_SINGLE</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">)) { </span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">BlkValueCopy</span><span class="plain">(</span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">), </span><span class="identifier">X</span><span class="plain">); }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">)) { </span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">BlkValueCopy</span><span class="plain">(</span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">), </span><span class="identifier">Y</span><span class="plain">); }</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="identifier">DoubleHashSetCheckResize</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">);</span>
<span class="reserved">rtrue</span><span class="plain">;</span>
<span class="identifier">RELS_ASSERT_FALSE</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">) - </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">))</span>
<span class="identifier">BlkValueFree</span><span class="plain">(</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">))</span>
<span class="identifier">BlkValueFree</span><span class="plain">(</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">));</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">RRF_DELETED</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">];</span>
<span class="plain">[ </span><span class="identifier">DoubleHashSetLookUp</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">kx</span><span class="plain"> </span><span class="identifier">ky</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain"> </span><span class="identifier">hashv</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> </span><span class="identifier">free</span><span class="plain"> </span><span class="identifier">mask</span><span class="plain"> </span><span class="identifier">perturb</span><span class="plain"> </span><span class="identifier">flags</span><span class="plain">;</span>
<span class="comment">calculate a hash value for the pair</span>
<span class="identifier">hashv</span><span class="plain"> = </span><span class="identifier">GetHashValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">) + </span><span class="identifier">GetHashValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="comment">look in the first expected slot</span>
<span class="identifier">mask</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain"> = </span><span class="identifier">hashv</span><span class="plain"> &amp; </span><span class="identifier">mask</span><span class="plain">;</span>
<span class="identifier">flags</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">flags</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> ~</span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">DoubleHashSetEntryMatches</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="comment">not here, keep looking in sequence</span>
<span class="identifier">free</span><span class="plain"> = -1;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">flags</span><span class="plain"> &amp; </span><span class="identifier">RRF_DELETED</span><span class="plain">) </span><span class="identifier">free</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">;</span>
<span class="identifier">perturb</span><span class="plain"> = </span><span class="identifier">hashv</span><span class="plain">;</span>
<span class="identifier">hashv</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (::) {</span>
<span class="identifier">hashv</span><span class="plain"> = </span><span class="identifier">hashv</span><span class="plain">*5 + </span><span class="identifier">perturb</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">;</span>
<span class="identifier">i</span><span class="plain"> = </span><span class="identifier">hashv</span><span class="plain"> &amp; </span><span class="identifier">mask</span><span class="plain">;</span>
<span class="identifier">flags</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">flags</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">free</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> ~</span><span class="identifier">free</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> ~</span><span class="identifier">i</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">DoubleHashSetEntryMatches</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">free</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) &amp;&amp; (</span><span class="identifier">flags</span><span class="plain"> &amp; </span><span class="identifier">RRF_DELETED</span><span class="plain">)) </span><span class="identifier">free</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">TARGET_ZCODE</span><span class="plain">;</span>
<span class="plain">@</span><span class="identifier">log_shift</span><span class="plain"> </span><span class="identifier">perturb</span><span class="plain"> </span><span class="identifier">MINUS_RRP_PERTURB_SHIFT</span><span class="plain"> -&gt; </span><span class="identifier">perturb</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">ifnot</span><span class="plain">;</span>
<span class="plain">@</span><span class="identifier">ushiftr</span><span class="plain"> </span><span class="identifier">perturb</span><span class="plain"> </span><span class="identifier">RRP_PERTURB_SHIFT</span><span class="plain"> </span><span class="identifier">perturb</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">];</span>
<span class="plain">[ </span><span class="identifier">DoubleHashSetCheckResize</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">filled</span><span class="plain"> </span><span class="identifier">ext</span><span class="plain"> </span><span class="identifier">newext</span><span class="plain"> </span><span class="identifier">temp</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> </span><span class="identifier">at</span><span class="plain"> </span><span class="identifier">kov</span><span class="plain"> </span><span class="identifier">kx</span><span class="plain"> </span><span class="identifier">ky</span><span class="plain"> </span><span class="identifier">F</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain">;</span>
<span class="identifier">filled</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">);</span>
<span class="identifier">ext</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">filled</span><span class="plain"> &gt;= (</span><span class="identifier">ext</span><span class="plain"> - </span><span class="identifier">filled</span><span class="plain">) * </span><span class="identifier">RRP_CROWDED_IS</span><span class="plain">) {</span>
<span class="comment">copy entries to temporary space</span>
<span class="identifier">temp</span><span class="plain"> = </span><span class="identifier">FlexAllocate</span><span class="plain">(</span><span class="identifier">ext</span><span class="plain"> * (3*</span><span class="identifier">WORDSIZE</span><span class="plain">), </span><span class="identifier">TEXT_TY</span><span class="plain">, </span><span class="identifier">BLK_FLAG_WORD</span><span class="plain">+</span><span class="identifier">BLK_FLAG_MULTIPLE</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0: </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">ext</span><span class="plain">*3: </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">temp</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain">+</span><span class="identifier">i</span><span class="plain">), </span><span class="reserved">true</span><span class="plain">);</span>
<span class="comment">resize and clear our data</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ext</span><span class="plain"> &gt;= </span><span class="identifier">RRP_LARGE_IS</span><span class="plain">) </span><span class="identifier">newext</span><span class="plain"> = </span><span class="identifier">ext</span><span class="plain"> * </span><span class="identifier">RRP_RESIZE_LARGE</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">newext</span><span class="plain"> = </span><span class="identifier">ext</span><span class="plain"> * </span><span class="identifier">RRP_RESIZE_SMALL</span><span class="plain">;</span>
<span class="identifier">BlkValueSetLBCapacity</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="identifier">newext</span><span class="plain">*3);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">, </span><span class="identifier">newext</span><span class="plain"> - </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">));</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0: </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">newext</span><span class="plain">*3: </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain">+</span><span class="identifier">i</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="comment">copy entries back from temporary space</span>
<span class="identifier">kov</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_KIND</span><span class="plain">);</span>
<span class="identifier">kx</span><span class="plain"> = </span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="constant">0</span><span class="plain">); </span><span class="identifier">ky</span><span class="plain"> = </span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0: </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">ext</span><span class="plain">: </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="identifier">F</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">temp</span><span class="plain">, </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">i</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">F</span><span class="plain"> == </span><span class="constant">0</span><span class="plain"> || (</span><span class="identifier">F</span><span class="plain"> &amp; </span><span class="identifier">RRF_DELETED</span><span class="plain">)) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="identifier">X</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">temp</span><span class="plain">, </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">i</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">temp</span><span class="plain">, </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">i</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">DoubleHashSetLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) { </span><span class="reserved">print</span><span class="plain"> </span><span class="string">"*** Duplicate entry while resizing ***^"</span><span class="plain">; </span><span class="reserved">rfalse</span><span class="plain">; }</span>
<span class="identifier">at</span><span class="plain"> = ~</span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">F</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="comment">done with temporary space</span>
<span class="identifier">FlexFree</span><span class="plain">(</span><span class="identifier">temp</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">];</span>
<span class="plain">[ </span><span class="identifier">DoubleHashSetEntryMatches</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">at</span><span class="plain"> </span><span class="identifier">kx</span><span class="plain"> </span><span class="identifier">ky</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain"> </span><span class="identifier">cx</span><span class="plain"> </span><span class="identifier">cy</span><span class="plain">;</span>
<span class="identifier">cx</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueCompare</span><span class="plain">(</span><span class="identifier">cx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">) ~= </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cx</span><span class="plain"> ~= </span><span class="identifier">X</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">cy</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueCompare</span><span class="plain">(</span><span class="identifier">cy</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">) ~= </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cy</span><span class="plain"> ~= </span><span class="identifier">Y</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP16"></a><b>&#167;16. Hash List Relation Handler. </b>This implements relations which are stored as a hash table mapping
keys to either single values or lists of values. The storage comprises a list
of three-word entries, either \((F, X, Y)\) or \((F, X, L)\), where \(F\) is a
flags word distinguishing between the two cases (among other things). In the
latter case, \(L\) is a pointer to a list (<code class="display"><span class="extract">LIST_OF_TY</span></code>) containing the values.
</p>
<p class="inwebparagraph">The "storage", "used", and "filled" words have the same meanings as
above.
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">HashListRelationHandler</span></code> is a thin wrapper around <code class="display"><span class="extract">HashCoreRelationHandler</span></code>,
which is shared with two other handlers below.
</p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">HashListRelationHandler</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">task</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain"> </span><span class="identifier">sym</span><span class="plain"> </span><span class="identifier">kov</span><span class="plain"> </span><span class="identifier">kx</span><span class="plain"> </span><span class="identifier">ky</span><span class="plain">;</span>
<span class="identifier">kov</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_KIND</span><span class="plain">);</span>
<span class="identifier">kx</span><span class="plain"> = </span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="constant">0</span><span class="plain">); </span><span class="identifier">ky</span><span class="plain"> = </span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">HashCoreRelationHandler</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">task</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">, </span><span class="constant">1</span><span class="plain">);</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP17"></a><b>&#167;17. Hash Table Relation Handler. </b>This is the same as the Hash List Relation Handler above, except that only
one value may be stored for each key. This implements various-to-one
relations.
</p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">HashTableRelationHandler</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">task</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain"> </span><span class="identifier">kov</span><span class="plain"> </span><span class="identifier">kx</span><span class="plain"> </span><span class="identifier">ky</span><span class="plain">;</span>
<span class="identifier">kov</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_KIND</span><span class="plain">);</span>
<span class="identifier">kx</span><span class="plain"> = </span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="constant">0</span><span class="plain">); </span><span class="identifier">ky</span><span class="plain"> = </span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">HashCoreRelationHandler</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">task</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP18"></a><b>&#167;18. Reversed Hash Table Relation Handler. </b>This is the same as the Hash Table Relation Handler except that the sides
are reversed. This implements one-to-various relations.
</p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">ReversedHashTableRelationHandler</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">task</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain"> </span><span class="identifier">kov</span><span class="plain"> </span><span class="identifier">kx</span><span class="plain"> </span><span class="identifier">ky</span><span class="plain"> </span><span class="identifier">swap</span><span class="plain">;</span>
<span class="identifier">kov</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_KIND</span><span class="plain">);</span>
<span class="identifier">kx</span><span class="plain"> = </span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="constant">0</span><span class="plain">); </span><span class="identifier">ky</span><span class="plain"> = </span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain">) {</span>
<span class="identifier">RELS_SET_VALENCY</span><span class="plain">:</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">RELATION_TY_SetValency</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="identifier">RELS_TEST</span><span class="plain">, </span><span class="identifier">RELS_ASSERT_TRUE</span><span class="plain">, </span><span class="identifier">RELS_ASSERT_FALSE</span><span class="plain">:</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">HashCoreRelationHandler</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">task</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">RELS_LOOKUP_ANY</span><span class="plain">:</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain">) {</span>
<span class="identifier">RLANY_GET_X</span><span class="plain">: </span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">RLANY_GET_Y</span><span class="plain">;</span>
<span class="identifier">RLANY_GET_Y</span><span class="plain">: </span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">RLANY_GET_X</span><span class="plain">;</span>
<span class="identifier">RLANY_CAN_GET_X</span><span class="plain">: </span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">RLANY_CAN_GET_Y</span><span class="plain">;</span>
<span class="identifier">RLANY_CAN_GET_Y</span><span class="plain">: </span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">RLANY_CAN_GET_X</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">RELS_LOOKUP_ALL_X</span><span class="plain">:</span>
<span class="identifier">task</span><span class="plain"> = </span><span class="identifier">RELS_LOOKUP_ALL_Y</span><span class="plain">;</span>
<span class="identifier">RELS_LOOKUP_ALL_Y</span><span class="plain">:</span>
<span class="identifier">task</span><span class="plain"> = </span><span class="identifier">RELS_LOOKUP_ALL_X</span><span class="plain">;</span>
<span class="identifier">RELS_SHOW</span><span class="plain">:</span>
<span class="identifier">swap</span><span class="plain">=</span><span class="identifier">X</span><span class="plain">; </span><span class="identifier">X</span><span class="plain">=</span><span class="identifier">Y</span><span class="plain">; </span><span class="identifier">Y</span><span class="plain">=</span><span class="identifier">swap</span><span class="plain">;</span>
<span class="identifier">swap</span><span class="plain">=</span><span class="identifier">kx</span><span class="plain">; </span><span class="identifier">kx</span><span class="plain">=</span><span class="identifier">ky</span><span class="plain">; </span><span class="identifier">ky</span><span class="plain">=</span><span class="identifier">swap</span><span class="plain">;</span>
<span class="identifier">RELS_LIST</span><span class="plain">:</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain">) {</span>
<span class="identifier">RLIST_ALL_X</span><span class="plain">: </span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">RLIST_ALL_Y</span><span class="plain">;</span>
<span class="identifier">RLIST_ALL_Y</span><span class="plain">: </span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">RLIST_ALL_X</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">HashCoreRelationHandler</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">task</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP19"></a><b>&#167;19. Symmetric Relation Handlers. </b>These are simple wrappers around the asymmetric handlers defined above.
When a pair is inserted or removed, the wrappers insert or remove the
reversed pair as well.
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">SymDoubleHashSetRelationHandler</span></code> and <code class="display"><span class="extract">SymHashListRelationHandler</span></code>
implement symmetric V-to-V relations.
<code class="display"><span class="extract">Sym2in1HashTableRelationHandler</span></code> implements symmetric 1-to-1.
("<code class="display"><span class="extract">SymTwoInOneHashTableRelationHandler</span></code>" would have
exceeded Inform 6's 32-character name limit.)
</p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">SymDoubleHashSetRelationHandler</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">task</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_ASSERT_TRUE</span><span class="plain"> </span><span class="reserved">or</span><span class="plain"> </span><span class="identifier">RELS_ASSERT_FALSE</span><span class="plain">)</span>
<span class="identifier">DoubleHashSetRelationHandler</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">task</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">DoubleHashSetRelationHandler</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">task</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">, </span><span class="constant">1</span><span class="plain">);</span>
<span class="plain">];</span>
<span class="plain">[ </span><span class="identifier">SymHashListRelationHandler</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">task</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_ASSERT_TRUE</span><span class="plain"> </span><span class="reserved">or</span><span class="plain"> </span><span class="identifier">RELS_ASSERT_FALSE</span><span class="plain">)</span>
<span class="identifier">HashListRelationHandler</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">task</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">HashListRelationHandler</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">task</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="plain">];</span>
<span class="plain">[ </span><span class="identifier">Sym2in1HashTableRelationHandler</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">task</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_ASSERT_TRUE</span><span class="plain"> </span><span class="reserved">or</span><span class="plain"> </span><span class="identifier">RELS_ASSERT_FALSE</span><span class="plain">)</span>
<span class="identifier">TwoInOneHashTableRelationHandler</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">task</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TwoInOneHashTableRelationHandler</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">task</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">, </span><span class="constant">1</span><span class="plain">);</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP20"></a><b>&#167;20. Hash Core Relation Handler. </b>This implements the core functionality that is shared between
<code class="display"><span class="extract">HashListRelationHandler</span></code>, <code class="display"><span class="extract">HashTableRelationHandler</span></code>, and
<code class="display"><span class="extract">ReversedHashTableRelationHandler</span></code>. All three handlers are the same except
for whether the left or right side is the "key" and whether or not
multiple values may be stored for a single key.
</p>
<p class="inwebparagraph">As noted above, the table contains three-word entries, \((F, X, Y)\),
where \(F\) is a flags word. Only the hash code of \(X\) is used. If \(F\)
includes <code class="display"><span class="extract">RRF_SINGLE</span></code>, \(Y\) is a single value; otherwise, \(Y\) is a list
(<code class="display"><span class="extract">LIST_OF_TY</span></code>) of values. If <code class="display"><span class="extract">mult</span></code> is zero, <code class="display"><span class="extract">RRF_SINGLE</span></code> must always be
set, allowing only one value per key: a new pair \((X, Y')\) will replace
the existing pair \((X, Y)\).
</p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">HashCoreRelationHandler</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">task</span><span class="plain"> </span><span class="identifier">kx</span><span class="plain"> </span><span class="identifier">ky</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain"> </span><span class="identifier">mult</span><span class="plain"> </span><span class="identifier">sym</span><span class="plain"> </span><span class="identifier">rev</span><span class="plain"> </span><span class="identifier">at</span><span class="plain"> </span><span class="identifier">tmp</span><span class="plain"> </span><span class="identifier">fl</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_SET_VALENCY</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">RELATION_TY_SetValency</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_DESTROY</span><span class="plain">) {</span>
<span class="comment">clear</span>
<span class="identifier">kx</span><span class="plain"> = </span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">); </span><span class="identifier">ky</span><span class="plain"> = </span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (~~(</span><span class="identifier">kx</span><span class="plain"> || </span><span class="identifier">ky</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">);</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kx</span><span class="plain">) </span><span class="identifier">BlkValueFree</span><span class="plain">(</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ky</span><span class="plain"> || ~~(</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_SINGLE</span><span class="plain">))</span>
<span class="identifier">BlkValueFree</span><span class="plain">(</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="identifier">at</span><span class="plain">--;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_COPY</span><span class="plain">) {</span>
<span class="identifier">X</span><span class="plain"> = </span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">); </span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (~~(</span><span class="identifier">X</span><span class="plain"> || </span><span class="identifier">Y</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">);</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">X</span><span class="plain">) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueCopy</span><span class="plain">(</span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">), </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain"> || ~~(</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_SINGLE</span><span class="plain">)) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueCopy</span><span class="plain">(</span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">BlkValueWeakKind</span><span class="plain">(</span><span class="identifier">tmp</span><span class="plain">)), </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">at</span><span class="plain">--;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_SHOW</span><span class="plain">) {</span>
<span class="reserved">print</span><span class="plain"> (</span><span class="reserved">string</span><span class="plain">) </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DESCRIPTION</span><span class="plain">), </span><span class="string">":^"</span><span class="plain">;</span>
<span class="comment">Z-machine doesn't have the room to let us pass sym/rev as parameters</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">RELATION_TY_GetValency</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">)) {</span>
<span class="identifier">RRVAL_SYM_V_TO_V</span><span class="plain">:</span>
<span class="identifier">sym</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">KOVComparisonFunction</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (~~</span><span class="identifier">tmp</span><span class="plain">) </span><span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">UnsignedCompare</span><span class="plain">;</span>
<span class="identifier">RRVAL_O_TO_V</span><span class="plain">:</span>
<span class="identifier">rev</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="identifier">X</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_SINGLE</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sym</span><span class="plain"> &amp;&amp; </span><span class="identifier">tmp</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="reserved">print</span><span class="plain"> </span><span class="string">" "</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rev</span><span class="plain">) </span><span class="identifier">PrintKindValuePair</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">PrintKindValuePair</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sym</span><span class="plain">) </span><span class="reserved">print</span><span class="plain"> </span><span class="string">" &lt;=&gt; "</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">print</span><span class="plain"> </span><span class="string">" &gt;=&gt; "</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rev</span><span class="plain">) </span><span class="identifier">PrintKindValuePair</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">PrintKindValuePair</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="reserved">print</span><span class="plain"> </span><span class="string">"^"</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">mult</span><span class="plain">=1: </span><span class="identifier">mult</span><span class="plain">&lt;=</span><span class="identifier">LIST_OF_TY_GetLength</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">): </span><span class="identifier">mult</span><span class="plain">++) {</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">LIST_OF_TY_GetItem</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">mult</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sym</span><span class="plain"> &amp;&amp; </span><span class="identifier">tmp</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">fl</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="reserved">print</span><span class="plain"> </span><span class="string">" "</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rev</span><span class="plain">) </span><span class="identifier">PrintKindValuePair</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">fl</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">PrintKindValuePair</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sym</span><span class="plain">) </span><span class="reserved">print</span><span class="plain"> </span><span class="string">" &lt;=&gt; "</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">print</span><span class="plain"> </span><span class="string">" &gt;=&gt; "</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rev</span><span class="plain">) </span><span class="identifier">PrintKindValuePair</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">PrintKindValuePair</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">fl</span><span class="plain">);</span>
<span class="reserved">print</span><span class="plain"> </span><span class="string">"^"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_EMPTY</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">X</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">) {</span>
<span class="identifier">HashCoreRelationHandler</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RELS_DESTROY</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_LOOKUP_ANY</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain"> == </span><span class="identifier">RLANY_GET_Y</span><span class="plain"> </span><span class="reserved">or</span><span class="plain"> </span><span class="identifier">RLANY_CAN_GET_Y</span><span class="plain">) {</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">HashCoreLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain"> == </span><span class="identifier">RLANY_CAN_GET_Y</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_SINGLE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">tmp</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">LIST_OF_TY_GetItem</span><span class="plain">(</span><span class="identifier">tmp</span><span class="plain">, </span><span class="constant">1</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="identifier">sym</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_SINGLE</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueCompare</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">sym</span><span class="plain">) ~= </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">X</span><span class="plain"> ~= </span><span class="identifier">sym</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">LIST_OF_TY_FindItem</span><span class="plain">(</span><span class="identifier">sym</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain"> == </span><span class="identifier">RLANY_CAN_GET_X</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain"> == </span><span class="identifier">RLANY_GET_X</span><span class="plain"> </span><span class="reserved">or</span><span class="plain"> </span><span class="identifier">RLANY_GET_Y</span><span class="plain">)</span>
<span class="reserved">print</span><span class="plain"> </span><span class="string">"*** Lookup failed: value not found ***^"</span><span class="plain">;</span>
<span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_LOOKUP_ALL_X</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueWeakKind</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">) ~= </span><span class="identifier">LIST_OF_TY</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="identifier">LIST_OF_TY_SetLength</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="identifier">sym</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_SINGLE</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueCompare</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">sym</span><span class="plain">) ~= </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">X</span><span class="plain"> ~= </span><span class="identifier">sym</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">LIST_OF_TY_FindItem</span><span class="plain">(</span><span class="identifier">sym</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">LIST_OF_TY_InsertItem</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_LOOKUP_ALL_Y</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueWeakKind</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">) ~= </span><span class="identifier">LIST_OF_TY</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="identifier">LIST_OF_TY_SetLength</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">HashCoreLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_SINGLE</span><span class="plain">)</span>
<span class="identifier">LIST_OF_TY_InsertItem</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">LIST_OF_TY_AppendList</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_LIST</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueWeakKind</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">) ~= </span><span class="identifier">LIST_OF_TY</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="identifier">LIST_OF_TY_SetLength</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain">) {</span>
<span class="identifier">RLIST_ALL_X</span><span class="plain">:</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_USED</span><span class="plain">)</span>
<span class="identifier">LIST_OF_TY_InsertItem</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">X</span><span class="plain">;</span>
<span class="identifier">RLIST_ALL_Y</span><span class="plain">:</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_SINGLE</span><span class="plain">)</span>
<span class="identifier">LIST_OF_TY_InsertItem</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">, </span><span class="reserved">false</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">LIST_OF_TY_AppendList</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">, </span><span class="reserved">false</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">X</span><span class="plain">;</span>
<span class="identifier">RLIST_ALL_PAIRS</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">RELATION_TY_GetValency</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">) == </span><span class="identifier">RRVAL_O_TO_V</span><span class="plain">) </span><span class="identifier">rev</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="comment">LIST_OF_TY_InsertItem will make a deep copy of the item,</span>
<span class="comment">so we can reuse a single combination value here</span>
<span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">COMBINATION_TY</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">COMBINATION_ITEM_BASE</span><span class="plain"> + </span><span class="identifier">rev</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">));</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_SINGLE</span><span class="plain">) {</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">COMBINATION_ITEM_BASE</span><span class="plain"> + </span><span class="constant">1</span><span class="plain"> - </span><span class="identifier">rev</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="identifier">LIST_OF_TY_InsertItem</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">mult</span><span class="plain"> = </span><span class="identifier">LIST_OF_TY_GetLength</span><span class="plain">(</span><span class="identifier">tmp</span><span class="plain">): </span><span class="identifier">mult</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">mult</span><span class="plain">--) {</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">COMBINATION_ITEM_BASE</span><span class="plain"> + </span><span class="constant">1</span><span class="plain"> - </span><span class="identifier">rev</span><span class="plain">,</span>
<span class="identifier">LIST_OF_TY_GetItem</span><span class="plain">(</span><span class="identifier">tmp</span><span class="plain">, </span><span class="identifier">mult</span><span class="plain">));</span>
<span class="identifier">LIST_OF_TY_InsertItem</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">COMBINATION_ITEM_BASE</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">COMBINATION_ITEM_BASE</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueFree</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">X</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">HashCoreLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">task</span><span class="plain">) {</span>
<span class="identifier">RELS_TEST</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_SINGLE</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueCompare</span><span class="plain">(</span><span class="identifier">tmp</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tmp</span><span class="plain"> == </span><span class="identifier">Y</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">LIST_OF_TY_FindItem</span><span class="plain">(</span><span class="identifier">tmp</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">RELS_ASSERT_TRUE</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="comment">no entry exists for this key, just add one</span>
<span class="identifier">at</span><span class="plain"> = ~</span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">RRF_USED</span><span class="plain">+</span><span class="identifier">RRF_SINGLE</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">)) { </span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">BlkValueCopy</span><span class="plain">(</span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">), </span><span class="identifier">X</span><span class="plain">); }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">)) { </span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">BlkValueCopy</span><span class="plain">(</span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">), </span><span class="identifier">Y</span><span class="plain">); }</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="identifier">HashCoreCheckResize</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="comment">an entry exists: could be a list or a single value</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">); </span><span class="comment">flags</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">); </span><span class="comment">value or list</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_SINGLE</span><span class="plain">) {</span>
<span class="comment">if Y is the same as the stored key, we have nothing to do</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueCompare</span><span class="plain">(</span><span class="identifier">tmp</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tmp</span><span class="plain"> == </span><span class="identifier">Y</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="comment">it's different: either replace it or expand into a list,</span>
<span class="comment">depending on the value of mult</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">mult</span><span class="plain">) {</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">LIST_OF_TY</span><span class="plain">); </span><span class="comment">new list</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">fl</span><span class="plain">, </span><span class="identifier">LIST_ITEM_KOV_F</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">);</span>
<span class="identifier">LIST_OF_TY_SetLength</span><span class="plain">(</span><span class="identifier">fl</span><span class="plain">, </span><span class="constant">2</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">fl</span><span class="plain">, </span><span class="identifier">LIST_ITEM_BASE</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">); </span><span class="comment">do not copy</span>
<span class="identifier">LIST_OF_TY_PutItem</span><span class="plain">(</span><span class="identifier">fl</span><span class="plain">, </span><span class="constant">2</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">); </span><span class="comment">copy if needed</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="identifier">fl</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">RRF_USED</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">)) {</span>
<span class="identifier">BlkValueFree</span><span class="plain">(</span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">BlkValueCopy</span><span class="plain">(</span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">), </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="comment">if Y is present already, do nothing. otherwise add it.</span>
<span class="identifier">LIST_OF_TY_InsertItem</span><span class="plain">(</span><span class="identifier">tmp</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">1</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">rtrue</span><span class="plain">;</span>
<span class="identifier">RELS_ASSERT_FALSE</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="comment">an entry exists: could be a list or a single value</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">); </span><span class="comment">flags</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">); </span><span class="comment">value or list</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_SINGLE</span><span class="plain">) {</span>
<span class="comment">if the stored key isn't Y, we have nothing to do</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueCompare</span><span class="plain">(</span><span class="identifier">tmp</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">) ~= </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tmp</span><span class="plain"> ~= </span><span class="identifier">Y</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="comment">delete the entry</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">))</span>
<span class="identifier">BlkValueFree</span><span class="plain">(</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">));</span>
<span class="plain">.</span><span class="identifier">DeleteEntryIgnoringY</span><span class="plain">;</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">) - </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">))</span>
<span class="identifier">BlkValueFree</span><span class="plain">(</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">));</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">RRF_DELETED</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="comment">remove Y from the list if present</span>
<span class="identifier">LIST_OF_TY_RemoveValue</span><span class="plain">(</span><span class="identifier">tmp</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">, </span><span class="constant">1</span><span class="plain">);</span>
<span class="comment">if the list is now empty, delete the whole entry</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">LIST_OF_TY_GetLength</span><span class="plain">(</span><span class="identifier">tmp</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">BlkValueFree</span><span class="plain">(</span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="reserved">jump</span><span class="plain"> </span><span class="identifier">DeleteEntryIgnoringY</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">];</span>
<span class="plain">[ </span><span class="identifier">HashCoreLookUp</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">kx</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">hashv</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> </span><span class="identifier">free</span><span class="plain"> </span><span class="identifier">mask</span><span class="plain"> </span><span class="identifier">perturb</span><span class="plain"> </span><span class="identifier">flags</span><span class="plain">;</span>
<span class="comment">rint "[HCLU rel=", rel, " kx=", kx, " X=", X, ": ";</span>
<span class="comment">calculate a hash value for the key</span>
<span class="identifier">hashv</span><span class="plain"> = </span><span class="identifier">GetHashValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="comment">look in the first expected slot</span>
<span class="identifier">mask</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain"> = </span><span class="identifier">hashv</span><span class="plain"> &amp; </span><span class="identifier">mask</span><span class="plain">;</span>
<span class="comment">rint "hv=", hashv, ", trying ", i;</span>
<span class="identifier">flags</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">flags</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) {</span>
<span class="comment">rint " - not found]^";</span>
<span class="reserved">return</span><span class="plain"> ~</span><span class="identifier">i</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">HashCoreEntryMatches</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">)) {</span>
<span class="comment">rint " - found]^";</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="comment">not here, keep looking in sequence</span>
<span class="identifier">free</span><span class="plain"> = -1;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">flags</span><span class="plain"> &amp; </span><span class="identifier">RRF_DELETED</span><span class="plain">) </span><span class="identifier">free</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">;</span>
<span class="identifier">perturb</span><span class="plain"> = </span><span class="identifier">hashv</span><span class="plain">;</span>
<span class="identifier">hashv</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (::) {</span>
<span class="identifier">hashv</span><span class="plain"> = </span><span class="identifier">hashv</span><span class="plain">*5 + </span><span class="identifier">perturb</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">;</span>
<span class="identifier">i</span><span class="plain"> = </span><span class="identifier">hashv</span><span class="plain"> &amp; </span><span class="identifier">mask</span><span class="plain">;</span>
<span class="comment">rint ", ", i;</span>
<span class="identifier">flags</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">flags</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) {</span>
<span class="comment">rint " - not found]^";</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">free</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> ~</span><span class="identifier">free</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> ~</span><span class="identifier">i</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">HashCoreEntryMatches</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">)) {</span>
<span class="comment">rint " - found]^";</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">free</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) &amp;&amp; (</span><span class="identifier">flags</span><span class="plain"> &amp; </span><span class="identifier">RRF_DELETED</span><span class="plain">)) </span><span class="identifier">free</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">TARGET_ZCODE</span><span class="plain">;</span>
<span class="plain">@</span><span class="identifier">log_shift</span><span class="plain"> </span><span class="identifier">perturb</span><span class="plain"> </span><span class="identifier">MINUS_RRP_PERTURB_SHIFT</span><span class="plain"> -&gt; </span><span class="identifier">perturb</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">ifnot</span><span class="plain">;</span>
<span class="plain">@</span><span class="identifier">ushiftr</span><span class="plain"> </span><span class="identifier">perturb</span><span class="plain"> </span><span class="identifier">RRP_PERTURB_SHIFT</span><span class="plain"> </span><span class="identifier">perturb</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">];</span>
<span class="plain">[ </span><span class="identifier">HashCoreCheckResize</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">filled</span><span class="plain"> </span><span class="identifier">ext</span><span class="plain"> </span><span class="identifier">newext</span><span class="plain"> </span><span class="identifier">temp</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> </span><span class="identifier">at</span><span class="plain"> </span><span class="identifier">kov</span><span class="plain"> </span><span class="identifier">kx</span><span class="plain"> </span><span class="identifier">F</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain">;</span>
<span class="identifier">filled</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">);</span>
<span class="identifier">ext</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">filled</span><span class="plain"> &gt;= (</span><span class="identifier">ext</span><span class="plain"> - </span><span class="identifier">filled</span><span class="plain">) * </span><span class="identifier">RRP_CROWDED_IS</span><span class="plain">) {</span>
<span class="comment">copy entries to temporary space</span>
<span class="identifier">temp</span><span class="plain"> = </span><span class="identifier">FlexAllocate</span><span class="plain">(</span><span class="identifier">ext</span><span class="plain"> * (3*</span><span class="identifier">WORDSIZE</span><span class="plain">), </span><span class="identifier">TEXT_TY</span><span class="plain">, </span><span class="identifier">BLK_FLAG_WORD</span><span class="plain">+</span><span class="identifier">BLK_FLAG_MULTIPLE</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0: </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">ext</span><span class="plain">*3: </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">temp</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain">+</span><span class="identifier">i</span><span class="plain">), </span><span class="reserved">true</span><span class="plain">);</span>
<span class="comment">resize and clear our data</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ext</span><span class="plain"> &gt;= </span><span class="identifier">RRP_LARGE_IS</span><span class="plain">) </span><span class="identifier">newext</span><span class="plain"> = </span><span class="identifier">ext</span><span class="plain"> * </span><span class="identifier">RRP_RESIZE_LARGE</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">newext</span><span class="plain"> = </span><span class="identifier">ext</span><span class="plain"> * </span><span class="identifier">RRP_RESIZE_SMALL</span><span class="plain">;</span>
<span class="identifier">BlkValueSetLBCapacity</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="identifier">newext</span><span class="plain">*3);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">, </span><span class="identifier">newext</span><span class="plain"> - </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">));</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0: </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">newext</span><span class="plain">*3: </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain">+</span><span class="identifier">i</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="comment">copy entries back from temporary space</span>
<span class="identifier">kov</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_KIND</span><span class="plain">);</span>
<span class="identifier">kx</span><span class="plain"> = </span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0: </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">ext</span><span class="plain">: </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="identifier">F</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">temp</span><span class="plain">, </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">i</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">F</span><span class="plain"> == </span><span class="constant">0</span><span class="plain"> || (</span><span class="identifier">F</span><span class="plain"> &amp; </span><span class="identifier">RRF_DELETED</span><span class="plain">)) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="identifier">X</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">temp</span><span class="plain">, </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">i</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">temp</span><span class="plain">, </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">i</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">HashCoreLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) { </span><span class="reserved">print</span><span class="plain"> </span><span class="string">"*** Duplicate entry while resizing ***^"</span><span class="plain">; </span><span class="reserved">rfalse</span><span class="plain">; }</span>
<span class="identifier">at</span><span class="plain"> = ~</span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">F</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="comment">done with temporary space</span>
<span class="identifier">FlexFree</span><span class="plain">(</span><span class="identifier">temp</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">];</span>
<span class="plain">[ </span><span class="identifier">HashCoreEntryMatches</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">at</span><span class="plain"> </span><span class="identifier">kx</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">cx</span><span class="plain"> </span><span class="identifier">cy</span><span class="plain">;</span>
<span class="identifier">cx</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueCompare</span><span class="plain">(</span><span class="identifier">cx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">) ~= </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cx</span><span class="plain"> ~= </span><span class="identifier">X</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP21"></a><b>&#167;21. Equivalence Hash Table Relation Handler. </b>This implements group relations. The table format is identical to that used
by <code class="display"><span class="extract">HashCoreRelationHandler</span></code>, but we use it differently. Although the
relation appears to relate Xs to Xs as far as the game is concerned, the
table actually relates Xs to numbers, where each number identifies a
group of related items. Any X not listed in the table is implicitly in
a single-member group.
</p>
<p class="inwebparagraph">When a pair \((X, Y)\) is inserted, one of four cases occurs:
</p>
<p class="inwebparagraph">1. Neither \(X\) nor \(Y\) has a table entry. We search the table to find the
next unused group number, then add both \(X\) and \(Y\) to that group.
</p>
<p class="inwebparagraph">2. Both \(X\) and \(Y\) have existing table entries. If the group numbers
differ, we walk through the table and change all occurrences of the
higher number to the lower one.
</p>
<p class="inwebparagraph">3. \(X\) has an existing table entry but \(Y\) does not. We add a \(Y\) entry
using the group number of \(X\).
</p>
<p class="inwebparagraph">4. \(Y\) has an existing table entry but \(X\) does not. We add an \(X\) entry
using the group number of \(Y\).
</p>
<p class="inwebparagraph">When a pair \((X, Y)\) is removed, we first verify that \(X\) and \(Y\) are
in the same group, then delete the table entry for \(X\). This may leave
\(Y\) in a single-member group, which could be deleted, but detecting that
situation would be inefficient, so we keep the \(Y\) entry regardless.
</p>
<p class="inwebparagraph">This code uses the Hash Core utility functions defined above.
</p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">EquivHashTableRelationHandler</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">task</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain"> </span><span class="identifier">kx</span><span class="plain"> </span><span class="identifier">at</span><span class="plain"> </span><span class="identifier">at2</span><span class="plain"> </span><span class="identifier">tmp</span><span class="plain"> </span><span class="identifier">fl</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> </span><span class="identifier">ext</span><span class="plain">;</span>
<span class="identifier">kx</span><span class="plain"> = </span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_KIND</span><span class="plain">), </span><span class="constant">0</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_SET_VALENCY</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">RELATION_TY_SetValency</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_DESTROY</span><span class="plain">) {</span>
<span class="comment">clear</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">)) {</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">);</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="identifier">BlkValueFree</span><span class="plain">(</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="identifier">at</span><span class="plain">--;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_COPY</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">)) {</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">);</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueCopy</span><span class="plain">(</span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">), </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">at</span><span class="plain">--;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_SHOW</span><span class="plain">) {</span>
<span class="reserved">print</span><span class="plain"> (</span><span class="reserved">string</span><span class="plain">) </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DESCRIPTION</span><span class="plain">), </span><span class="string">":^"</span><span class="plain">;</span>
<span class="identifier">ext</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">);</span>
<span class="comment">flag all items by negating their group numbers</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain">=0, </span><span class="identifier">X</span><span class="plain">=</span><span class="identifier">RRV_DATA_BASE</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">&lt;=</span><span class="identifier">ext</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">++, </span><span class="identifier">X</span><span class="plain">=</span><span class="identifier">X</span><span class="plain">+3)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">) &amp; </span><span class="identifier">RRF_USED</span><span class="plain">)</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">X</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, -(</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">X</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">)));</span>
<span class="comment">display groups, unflagging them as we go</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain">=0, </span><span class="identifier">X</span><span class="plain">=</span><span class="identifier">RRV_DATA_BASE</span><span class="plain">, </span><span class="identifier">fl</span><span class="plain">=0: </span><span class="identifier">at</span><span class="plain">&lt;=</span><span class="identifier">ext</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">++, </span><span class="identifier">X</span><span class="plain">=</span><span class="identifier">X</span><span class="plain">+3, </span><span class="identifier">fl</span><span class="plain">=0) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">) &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">X</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">; </span><span class="comment">already visited</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">X</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, -</span><span class="identifier">fl</span><span class="plain">); </span><span class="comment">unflag it</span>
<span class="comment">display the group starting with this member, but only</span>
<span class="comment">if there are more members in the group</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">X</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at2</span><span class="plain">=</span><span class="identifier">at</span><span class="plain">+1, </span><span class="identifier">Y</span><span class="plain">=</span><span class="identifier">RRV_DATA_BASE</span><span class="plain">+3*</span><span class="identifier">at2</span><span class="plain">: </span><span class="identifier">at2</span><span class="plain">&lt;=</span><span class="identifier">ext</span><span class="plain">: </span><span class="identifier">at2</span><span class="plain">++, </span><span class="identifier">Y</span><span class="plain">=</span><span class="identifier">Y</span><span class="plain">+3) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">) &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">) ~= </span><span class="identifier">fl</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, -</span><span class="identifier">fl</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (~~</span><span class="identifier">i</span><span class="plain">) {</span>
<span class="comment">print the saved first member</span>
<span class="reserved">print</span><span class="plain"> </span><span class="string">" { "</span><span class="plain">;</span>
<span class="identifier">PrintKindValuePair</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">print</span><span class="plain"> </span><span class="string">", "</span><span class="plain">;</span>
<span class="identifier">PrintKindValuePair</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">) </span><span class="reserved">print</span><span class="plain"> </span><span class="string">" }^"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_EMPTY</span><span class="plain">) {</span>
<span class="comment">never empty since R(x,x) is always true</span>
<span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_LOOKUP_ANY</span><span class="plain">) {</span>
<span class="comment">kind of a cheat, but it's faster than searching for a better value to return</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain"> == </span><span class="identifier">RLANY_CAN_GET_X</span><span class="plain"> </span><span class="reserved">or</span><span class="plain"> </span><span class="identifier">RLANY_CAN_GET_Y</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">X</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_LOOKUP_ALL_X</span><span class="plain"> </span><span class="reserved">or</span><span class="plain"> </span><span class="identifier">RELS_LOOKUP_ALL_Y</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueWeakKind</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">) ~= </span><span class="identifier">LIST_OF_TY</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="identifier">LIST_OF_TY_SetLength</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">LIST_ITEM_KOV_F</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">);</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">HashCoreLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">LIST_OF_TY_InsertItem</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">X</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">) ~= </span><span class="identifier">X</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="identifier">LIST_OF_TY_InsertItem</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_LIST</span><span class="plain">) {</span>
<span class="reserved">print</span><span class="plain"> </span><span class="string">"*** Domains of equivalence relations cannot be listed ***^"</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">X</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">HashCoreLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="identifier">at2</span><span class="plain"> = </span><span class="identifier">HashCoreLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">task</span><span class="plain">) {</span>
<span class="identifier">RELS_TEST</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="comment">X is a loner, but could still be true if X == Y</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueCompare</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">X</span><span class="plain"> == </span><span class="identifier">Y</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at2</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> == </span><span class="identifier">at2</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">) == </span><span class="identifier">tmp</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="reserved">rfalse</span><span class="plain">;</span>
<span class="identifier">RELS_ASSERT_TRUE</span><span class="plain">:</span>
<span class="comment">if X and Y are the same, we have nothing to do</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueCompare</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">X</span><span class="plain"> == </span><span class="identifier">Y</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at2</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="comment">X and Y both missing: find a new group number and add both entries</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="comment">candidate group number</span>
<span class="identifier">ext</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0: </span><span class="identifier">i</span><span class="plain">&lt;=</span><span class="identifier">ext</span><span class="plain">: </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">i</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &gt; </span><span class="identifier">tmp</span><span class="plain">) </span><span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">fl</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">tmp</span><span class="plain">++; </span><span class="comment">new group number</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">) + </span><span class="constant">2</span><span class="plain">);</span>
<span class="comment">add X entry</span>
<span class="identifier">at</span><span class="plain"> = ~</span><span class="identifier">at</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">)) { </span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">BlkValueCopy</span><span class="plain">(</span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">), </span><span class="identifier">X</span><span class="plain">); }</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">RRF_USED</span><span class="plain">+</span><span class="identifier">RRF_SINGLE</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="comment">add Y entry. at2 might change if X and Y have the same hash code.</span>
<span class="identifier">at2</span><span class="plain"> = ~(</span><span class="identifier">HashCoreLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">)) { </span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">BlkValueCopy</span><span class="plain">(</span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">), </span><span class="identifier">Y</span><span class="plain">); }</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain">, </span><span class="identifier">RRF_USED</span><span class="plain">+</span><span class="identifier">RRF_SINGLE</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="reserved">jump</span><span class="plain"> </span><span class="identifier">CheckResize</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="comment">X missing, Y present: add a new X entry</span>
<span class="identifier">at</span><span class="plain"> = ~</span><span class="identifier">at</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">)) { </span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">BlkValueCopy</span><span class="plain">(</span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">), </span><span class="identifier">X</span><span class="plain">); }</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">RRF_USED</span><span class="plain">+</span><span class="identifier">RRF_SINGLE</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="reserved">jump</span><span class="plain"> </span><span class="identifier">CheckResize</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at2</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="comment">X present, Y missing: add a new Y entry</span>
<span class="identifier">at2</span><span class="plain"> = ~</span><span class="identifier">at2</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">)) { </span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">BlkValueCopy</span><span class="plain">(</span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">), </span><span class="identifier">Y</span><span class="plain">); }</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain">, </span><span class="identifier">RRF_USED</span><span class="plain">+</span><span class="identifier">RRF_SINGLE</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="reserved">jump</span><span class="plain"> </span><span class="identifier">CheckResize</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="comment">X and Y both present: merge higher group into lower group</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">); </span><span class="comment">higher group</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">); </span><span class="comment">lower group</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tmp</span><span class="plain"> &lt; </span><span class="identifier">fl</span><span class="plain">) { </span><span class="identifier">i</span><span class="plain"> = </span><span class="identifier">tmp</span><span class="plain">; </span><span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">fl</span><span class="plain">; </span><span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">; }</span>
<span class="identifier">ext</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain">=0: </span><span class="identifier">at</span><span class="plain">&lt;=</span><span class="identifier">ext</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">++) {</span>
<span class="identifier">i</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) == </span><span class="identifier">tmp</span><span class="plain">)</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">fl</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">.</span><span class="identifier">CheckResize</span><span class="plain">;</span>
<span class="identifier">HashCoreCheckResize</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">);</span>
<span class="reserved">rtrue</span><span class="plain">;</span>
<span class="identifier">RELS_ASSERT_FALSE</span><span class="plain">:</span>
<span class="comment">if X and Y are already in different groups, we have nothing to do</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain"> || </span><span class="identifier">at2</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">) ~= </span><span class="identifier">tmp</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="comment">delete the entry for X</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">) - </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">))</span>
<span class="identifier">BlkValueFree</span><span class="plain">(</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">));</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">RRF_DELETED</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP22"></a><b>&#167;22. Two-In-One Hash Table Relation Handler. </b>This implements one-to-one relations, which are stored as a hash table
mapping keys to single values and vice versa. To enforce the one-to-one
constraint, we need the ability to quickly check whether a value is
present. This could be done with two separate hash tables, one mapping X to Y
and one the opposite, but in the interest of conserving memory, we use a
single table for both.
</p>
<p class="inwebparagraph">Each four-word entry \((F, E, K, V)\) consists of a flags word \(F\), an entry
key \(E\) (which may be a "key" or "value" in the hash table sense), a
corresponding key \(K\) (when \(E\) is used as a value), and a corresponding
value \(V\) (when \(E\) is used as a key). The pair of related values \((X, Y)\)
is represented as two table entries: \((F, X, _, Y)\) and \((F, Y, X, _)\).
</p>
<p class="inwebparagraph">To conserve memory when block values are used, we only create one copy
of \(X\) and/or \(Y\) to share between both entries. When adding a key or value
which already exists on either side of the relation, the previous copy will
be used. Copies are freed when they are no longer used as entry keys.
</p>
<p class="inwebparagraph">Each entry's flags word \(F\) indicates, in addition to the standard flags
<code class="display"><span class="extract">RRF_USED</span></code> and <code class="display"><span class="extract">RRF_DELETED</span></code>, also whether the entry contains a
corresponding key \(K\) and/or value \(V\) (<code class="display"><span class="extract">RRF_HASX</span></code>, <code class="display"><span class="extract">RRF_HASY</span></code>) and
whether the entry's key is the same kind of value as \(X\) or \(Y\)
(<code class="display"><span class="extract">RRF_ENTKEYX</span></code>, <code class="display"><span class="extract">RRF_ENTKEYY</span></code>). If both sides of the relation use the
same kind of value, or if both sides are word values, both <code class="display"><span class="extract">RRF_ENTKEYX</span></code>
and <code class="display"><span class="extract">RRF_ENTKEYY</span></code> will be set on every used entry.
</p>
<p class="inwebparagraph">Of particular note for this handler is the utility function <code class="display"><span class="extract">TwoInOneDelete</span></code>,
which clears one half of an entry (given its entry key), and optionally
clears the corresponding other half stored in a different entry. That is,
given the entries \((F, X, _, Y)\) at index <code class="display"><span class="extract">i</span></code> and \((F, Y, X, _)\) elsewhere,
<code class="display"><span class="extract">TwoInOneDelete(rel, i, kx, ky, RRF_ENTKEYX, 1)</span></code> will clear both entries
and mark them as deleted. If, however, those entries overlap with other
pairs &mdash; say they're \((F, X, A, Y)\) and \((F, Y, X, B)\) &mdash; then the same call
to <code class="display"><span class="extract">TwoInOneDelete</span></code> will leave us with \((F, X, A, _)\) and \((F, Y, _, B)\),
having cleared the parts corresponding to the pair \((X, Y)\) but not the
parts corresponding to the pairs \((A, X)\) and \((Y, B)\), and will not mark
either as deleted. (Such overlap is only possible when the domains of \(X\)
and \(Y\) are the same kind of value.)
</p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">TwoInOneHashTableRelationHandler</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">task</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain"> </span><span class="identifier">sym</span><span class="plain"> </span><span class="identifier">kov</span><span class="plain"> </span><span class="identifier">kx</span><span class="plain"> </span><span class="identifier">ky</span><span class="plain"> </span><span class="identifier">at</span><span class="plain"> </span><span class="identifier">at2</span><span class="plain"> </span><span class="identifier">tmp</span><span class="plain"> </span><span class="identifier">fl</span><span class="plain">;</span>
<span class="identifier">kov</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_KIND</span><span class="plain">);</span>
<span class="identifier">kx</span><span class="plain"> = </span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="constant">0</span><span class="plain">); </span><span class="identifier">ky</span><span class="plain"> = </span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_SET_VALENCY</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">RELATION_TY_SetValency</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_DESTROY</span><span class="plain">) {</span>
<span class="comment">clear</span>
<span class="identifier">kx</span><span class="plain"> = </span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">); </span><span class="identifier">ky</span><span class="plain"> = </span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (~~(</span><span class="identifier">kx</span><span class="plain"> || </span><span class="identifier">ky</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">);</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_USED</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">kx</span><span class="plain"> &amp;&amp; (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_ENTKEYX</span><span class="plain">)) || (</span><span class="identifier">ky</span><span class="plain"> &amp;&amp; (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_ENTKEYY</span><span class="plain">))) {</span>
<span class="identifier">BlkValueFree</span><span class="plain">(</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="identifier">at</span><span class="plain">--;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_COPY</span><span class="plain">) {</span>
<span class="identifier">X</span><span class="plain"> = </span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">); </span><span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (~~(</span><span class="identifier">X</span><span class="plain"> || </span><span class="identifier">Y</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">);</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_USED</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">X</span><span class="plain"> &amp;&amp; (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_ENTKEYX</span><span class="plain">)) || (</span><span class="identifier">Y</span><span class="plain"> &amp;&amp; (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_ENTKEYY</span><span class="plain">))) {</span>
<span class="comment">copy the entry key</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_ENTKEYX</span><span class="plain">)</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueCopy</span><span class="plain">(</span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">), </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueCopy</span><span class="plain">(</span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">), </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="comment">update references in X/Y fields pointing here</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_HASX</span><span class="plain">) {</span>
<span class="identifier">at2</span><span class="plain"> = </span><span class="identifier">TwoInOneLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">,</span>
<span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">),</span>
<span class="identifier">RRF_ENTKEYX</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at2</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_HASY</span><span class="plain">) {</span>
<span class="identifier">at2</span><span class="plain"> = </span><span class="identifier">TwoInOneLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">,</span>
<span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">),</span>
<span class="identifier">RRF_ENTKEYY</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at2</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">at</span><span class="plain">--;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_SHOW</span><span class="plain">) {</span>
<span class="reserved">print</span><span class="plain"> (</span><span class="reserved">string</span><span class="plain">) </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DESCRIPTION</span><span class="plain">), </span><span class="string">":^"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sym</span><span class="plain">) {</span>
<span class="identifier">kov</span><span class="plain"> = </span><span class="identifier">KOVComparisonFunction</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (~~</span><span class="identifier">kov</span><span class="plain">) </span><span class="identifier">kov</span><span class="plain"> = </span><span class="identifier">UnsignedCompare</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">fl</span><span class="plain"> &amp; (</span><span class="identifier">RRF_USED</span><span class="plain">+</span><span class="identifier">RRF_ENTKEYX</span><span class="plain">+</span><span class="identifier">RRF_HASY</span><span class="plain">)) ==</span>
<span class="plain">(</span><span class="identifier">RRF_USED</span><span class="plain">+</span><span class="identifier">RRF_ENTKEYX</span><span class="plain">+</span><span class="identifier">RRF_HASY</span><span class="plain">)) {</span>
<span class="identifier">X</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sym</span><span class="plain"> &amp;&amp; </span><span class="identifier">kov</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="reserved">print</span><span class="plain"> </span><span class="string">" "</span><span class="plain">;</span>
<span class="identifier">PrintKindValuePair</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sym</span><span class="plain">) </span><span class="reserved">print</span><span class="plain"> </span><span class="string">" &lt;=&gt; "</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">print</span><span class="plain"> </span><span class="string">" &gt;=&gt; "</span><span class="plain">;</span>
<span class="identifier">PrintKindValuePair</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="reserved">print</span><span class="plain"> </span><span class="string">"^"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_EMPTY</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">X</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">) {</span>
<span class="identifier">TwoInOneHashTableRelationHandler</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RELS_DESTROY</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_LOOKUP_ANY</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain">) {</span>
<span class="identifier">RLANY_GET_X</span><span class="plain">, </span><span class="identifier">RLANY_CAN_GET_X</span><span class="plain">:</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">TwoInOneLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">RRF_ENTKEYY</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">) &amp; </span><span class="identifier">RRF_HASX</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain"> == </span><span class="identifier">RLANY_CAN_GET_X</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">RLANY_GET_Y</span><span class="plain">, </span><span class="identifier">RLANY_CAN_GET_Y</span><span class="plain">:</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">TwoInOneLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">RRF_ENTKEYX</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">) &amp; </span><span class="identifier">RRF_HASY</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain"> == </span><span class="identifier">RLANY_CAN_GET_Y</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain"> == </span><span class="identifier">RLANY_GET_X</span><span class="plain"> </span><span class="reserved">or</span><span class="plain"> </span><span class="identifier">RLANY_GET_Y</span><span class="plain">)</span>
<span class="reserved">print</span><span class="plain"> </span><span class="string">"*** Lookup failed: value not found ***^"</span><span class="plain">;</span>
<span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_LOOKUP_ALL_X</span><span class="plain">) {</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">TwoInOneLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">RRF_ENTKEYY</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">) &amp; </span><span class="identifier">RRF_HASX</span><span class="plain">)</span>
<span class="identifier">LIST_OF_TY_InsertItem</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_LOOKUP_ALL_Y</span><span class="plain">) {</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">TwoInOneLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">RRF_ENTKEYX</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">) &amp; </span><span class="identifier">RRF_HASY</span><span class="plain">)</span>
<span class="identifier">LIST_OF_TY_InsertItem</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain"> == </span><span class="identifier">RELS_LIST</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">Y</span><span class="plain">) {</span>
<span class="identifier">RLIST_ALL_X</span><span class="plain">:</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">RRF_USED</span><span class="plain">+</span><span class="identifier">RRF_ENTKEYX</span><span class="plain">+</span><span class="identifier">RRF_HASY</span><span class="plain">;</span>
<span class="reserved">jump</span><span class="plain"> </span><span class="identifier">ListEntryKeys</span><span class="plain">;</span>
<span class="identifier">RLIST_ALL_Y</span><span class="plain">:</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">RRF_USED</span><span class="plain">+</span><span class="identifier">RRF_ENTKEYY</span><span class="plain">+</span><span class="identifier">RRF_HASX</span><span class="plain">;</span>
<span class="plain">.</span><span class="identifier">ListEntryKeys</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">) &amp; </span><span class="identifier">fl</span><span class="plain">) == </span><span class="identifier">fl</span><span class="plain">)</span>
<span class="identifier">LIST_OF_TY_InsertItem</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">), </span><span class="reserved">false</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">RLIST_ALL_PAIRS</span><span class="plain">:</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">LIST_ITEM_KOV_F</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KindAtomic</span><span class="plain">(</span><span class="identifier">tmp</span><span class="plain">) ~= </span><span class="identifier">COMBINATION_TY</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="comment">LIST_OF_TY_InsertItem will make a deep copy of the item,</span>
<span class="comment">so we can reuse a single combination value here</span>
<span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">): </span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">: </span><span class="identifier">at</span><span class="plain">--) {</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">fl</span><span class="plain"> &amp; (</span><span class="identifier">RRF_USED</span><span class="plain">+</span><span class="identifier">RRF_ENTKEYX</span><span class="plain">+</span><span class="identifier">RRF_HASY</span><span class="plain">)) ==</span>
<span class="plain">(</span><span class="identifier">RRF_USED</span><span class="plain">+</span><span class="identifier">RRF_ENTKEYX</span><span class="plain">+</span><span class="identifier">RRF_HASY</span><span class="plain">)) {</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">COMBINATION_ITEM_BASE</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">));</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">COMBINATION_ITEM_BASE</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">));</span>
<span class="identifier">LIST_OF_TY_InsertItem</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">COMBINATION_ITEM_BASE</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">COMBINATION_ITEM_BASE</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueFree</span><span class="plain">(</span><span class="identifier">Y</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">X</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">X</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">at</span><span class="plain"> = </span><span class="identifier">TwoInOneLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">RRF_ENTKEYX</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">task</span><span class="plain">) {</span>
<span class="identifier">RELS_TEST</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (~~(</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_HASY</span><span class="plain">)) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueCompare</span><span class="plain">(</span><span class="identifier">tmp</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tmp</span><span class="plain"> == </span><span class="identifier">Y</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">rfalse</span><span class="plain">;</span>
<span class="identifier">RELS_ASSERT_TRUE</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="comment">create a new forward entry</span>
<span class="identifier">at</span><span class="plain"> = ~</span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">RRF_USED</span><span class="plain">+</span><span class="identifier">RRF_HASY</span><span class="plain">+</span><span class="identifier">RRF_ENTKEYX</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kx</span><span class="plain"> == </span><span class="identifier">ky</span><span class="plain"> || ~~(</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">) || </span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">)))</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">fl</span><span class="plain"> + </span><span class="identifier">RRF_ENTKEYY</span><span class="plain">;</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">fl</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">)) { </span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">BlkValueCopy</span><span class="plain">(</span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">), </span><span class="identifier">X</span><span class="plain">); }</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_HASY</span><span class="plain">) {</span>
<span class="comment">if the Y we're inserting is already there, we're done</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueCompare</span><span class="plain">(</span><span class="identifier">tmp</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tmp</span><span class="plain"> == </span><span class="identifier">Y</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="comment">it's different, so delete the reverse entry</span>
<span class="identifier">at2</span><span class="plain"> = </span><span class="identifier">TwoInOneLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">tmp</span><span class="plain">, </span><span class="identifier">RRF_ENTKEYY</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at2</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">TwoInOneDelete</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">at2</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">RRF_ENTKEYY</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">fl</span><span class="plain"> + </span><span class="identifier">RRF_HASY</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="comment">use the existing copy of X</span>
<span class="identifier">X</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="comment">use the existing copy of Y if there is one</span>
<span class="identifier">at2</span><span class="plain"> = </span><span class="identifier">TwoInOneLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">, </span><span class="identifier">RRF_ENTKEYY</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at2</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">BlkValueCopy</span><span class="plain">(</span><span class="identifier">BlkValueCreate</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">), </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at2</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="comment">delete existing reverse entry (and its own forward entry)</span>
<span class="identifier">TwoInOneDelete</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">at2</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">RRF_ENTKEYY</span><span class="plain">, </span><span class="constant">1</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">at2</span><span class="plain"> = ~</span><span class="identifier">at2</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="comment">create reverse entry</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">fl</span><span class="plain"> | (</span><span class="identifier">RRF_USED</span><span class="plain">+</span><span class="identifier">RRF_HASX</span><span class="plain">+</span><span class="identifier">RRF_ENTKEYY</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kx</span><span class="plain"> == </span><span class="identifier">ky</span><span class="plain"> || ~~(</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">) || </span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">)))</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">fl</span><span class="plain"> | </span><span class="identifier">RRF_ENTKEYX</span><span class="plain">;</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain">, </span><span class="identifier">fl</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at2</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="identifier">TwoInOneCheckResize</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">);</span>
<span class="reserved">rtrue</span><span class="plain">;</span>
<span class="identifier">RELS_ASSERT_FALSE</span><span class="plain">:</span>
<span class="comment">we only have work to do if the entry exists and has a Y which</span>
<span class="comment">matches the Y we're deleting</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_HASY</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="identifier">tmp</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueCompare</span><span class="plain">(</span><span class="identifier">tmp</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">) ~= </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tmp</span><span class="plain"> ~= </span><span class="identifier">Y</span><span class="plain">) </span><span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">TwoInOneDelete</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">RRF_ENTKEYX</span><span class="plain">, </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">];</span>
<span class="plain">[ </span><span class="identifier">TwoInOneDelete</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">at</span><span class="plain"> </span><span class="identifier">kx</span><span class="plain"> </span><span class="identifier">ky</span><span class="plain"> </span><span class="identifier">ekflag</span><span class="plain"> </span><span class="identifier">both</span><span class="plain"> </span><span class="identifier">fl</span><span class="plain"> </span><span class="identifier">at2</span><span class="plain"> </span><span class="identifier">E</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="comment">rint "[2in1DEL at=", at, " (E=", BlkValueRead(rel, RRV_DATA_BASE + 4*at + 1), ") ekflag=", ekflag, " both=", both, "]^";</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ekflag</span><span class="plain"> == </span><span class="identifier">RRF_ENTKEYX</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_HASY</span><span class="plain">) {</span>
<span class="identifier">i</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">both</span><span class="plain">) </span><span class="identifier">E</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="comment">delete matching Y&lt;-X entry if needed</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">both</span><span class="plain">) {</span>
<span class="identifier">at2</span><span class="plain"> = </span><span class="identifier">TwoInOneLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">, </span><span class="identifier">RRF_ENTKEYY</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at2</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">TwoInOneDelete</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">at2</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">RRF_ENTKEYY</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at2</span><span class="plain"> == </span><span class="identifier">at</span><span class="plain">) </span><span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">fl</span><span class="plain"> &amp; ~</span><span class="identifier">RRF_HASY</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_HASX</span><span class="plain">) {</span>
<span class="identifier">i</span><span class="plain"> = </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">both</span><span class="plain">) </span><span class="identifier">E</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="comment">delete matching X-&gt;Y entry if needed</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">both</span><span class="plain">) {</span>
<span class="identifier">at2</span><span class="plain"> = </span><span class="identifier">TwoInOneLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">, </span><span class="identifier">RRF_ENTKEYX</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at2</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">TwoInOneDelete</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">at2</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">RRF_ENTKEYX</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at2</span><span class="plain"> == </span><span class="identifier">at</span><span class="plain">) </span><span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">fl</span><span class="plain"> = </span><span class="identifier">fl</span><span class="plain"> &amp; ~</span><span class="identifier">RRF_HASX</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">fl</span><span class="plain"> &amp; (</span><span class="identifier">RRF_HASX</span><span class="plain">+</span><span class="identifier">RRF_HASY</span><span class="plain">)) == </span><span class="constant">0</span><span class="plain">) {</span>
<span class="comment">entry is now empty, mark it deleted</span>
<span class="reserved">if</span><span class="plain"> (((</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_ENTKEYX</span><span class="plain">) &amp;&amp; </span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">)) ||</span>
<span class="plain">((</span><span class="identifier">ky</span><span class="plain"> ~= </span><span class="identifier">kx</span><span class="plain">) &amp;&amp; (</span><span class="identifier">fl</span><span class="plain"> &amp; </span><span class="identifier">RRF_ENTKEYY</span><span class="plain">) &amp;&amp; </span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ky</span><span class="plain">))) {</span>
<span class="identifier">BlkValueFree</span><span class="plain">(</span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">RRF_DELETED</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">) - </span><span class="constant">1</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">fl</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">];</span>
<span class="plain">[ </span><span class="identifier">TwoInOneLookUp</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">ke</span><span class="plain"> </span><span class="identifier">E</span><span class="plain"> </span><span class="identifier">ekflag</span><span class="plain"> </span><span class="identifier">hashv</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> </span><span class="identifier">free</span><span class="plain"> </span><span class="identifier">mask</span><span class="plain"> </span><span class="identifier">perturb</span><span class="plain"> </span><span class="identifier">flags</span><span class="plain">;</span>
<span class="comment">rint "[2in1LU rel=", rel, " ke=", ke, " E=", E, " ekf=", ekflag, ": ";</span>
<span class="comment">calculate a hash value for the key</span>
<span class="identifier">hashv</span><span class="plain"> = </span><span class="identifier">GetHashValue</span><span class="plain">(</span><span class="identifier">ke</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">);</span>
<span class="comment">look in the first expected slot</span>
<span class="identifier">mask</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain"> = </span><span class="identifier">hashv</span><span class="plain"> &amp; </span><span class="identifier">mask</span><span class="plain">;</span>
<span class="comment">rint "hv=", hashv, ", trying ", i;</span>
<span class="identifier">flags</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">flags</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) {</span>
<span class="comment">rint " - not found]^";</span>
<span class="reserved">return</span><span class="plain"> ~</span><span class="identifier">i</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">flags</span><span class="plain"> &amp; </span><span class="identifier">ekflag</span><span class="plain">) &amp;&amp; </span><span class="identifier">TwoInOneEntryMatches</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">ke</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">)) {</span>
<span class="comment">rint " - found]^";</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="comment">not here, keep looking in sequence</span>
<span class="identifier">free</span><span class="plain"> = -1;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">flags</span><span class="plain"> &amp; </span><span class="identifier">RRF_DELETED</span><span class="plain">) </span><span class="identifier">free</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">;</span>
<span class="identifier">perturb</span><span class="plain"> = </span><span class="identifier">hashv</span><span class="plain">;</span>
<span class="identifier">hashv</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (::) {</span>
<span class="identifier">hashv</span><span class="plain"> = </span><span class="identifier">hashv</span><span class="plain">*5 + </span><span class="identifier">perturb</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">;</span>
<span class="identifier">i</span><span class="plain"> = </span><span class="identifier">hashv</span><span class="plain"> &amp; </span><span class="identifier">mask</span><span class="plain">;</span>
<span class="comment">rint ", ", i;</span>
<span class="identifier">flags</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">flags</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) {</span>
<span class="comment">rint " - not found]^";</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">free</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> ~</span><span class="identifier">free</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> ~</span><span class="identifier">i</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">flags</span><span class="plain"> &amp; </span><span class="identifier">ekflag</span><span class="plain">) &amp;&amp; </span><span class="identifier">TwoInOneEntryMatches</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">ke</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">)) {</span>
<span class="comment">rint " - found]^";</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">free</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) &amp;&amp; (</span><span class="identifier">flags</span><span class="plain"> &amp; </span><span class="identifier">RRF_DELETED</span><span class="plain">)) </span><span class="identifier">free</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">TARGET_ZCODE</span><span class="plain">;</span>
<span class="plain">@</span><span class="identifier">log_shift</span><span class="plain"> </span><span class="identifier">perturb</span><span class="plain"> </span><span class="identifier">MINUS_RRP_PERTURB_SHIFT</span><span class="plain"> -&gt; </span><span class="identifier">perturb</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">ifnot</span><span class="plain">;</span>
<span class="plain">@</span><span class="identifier">ushiftr</span><span class="plain"> </span><span class="identifier">perturb</span><span class="plain"> </span><span class="identifier">RRP_PERTURB_SHIFT</span><span class="plain"> </span><span class="identifier">perturb</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">];</span>
<span class="plain">[ </span><span class="identifier">TwoInOneCheckResize</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">filled</span><span class="plain"> </span><span class="identifier">ext</span><span class="plain"> </span><span class="identifier">newext</span><span class="plain"> </span><span class="identifier">temp</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> </span><span class="identifier">at</span><span class="plain"> </span><span class="identifier">kov</span><span class="plain"> </span><span class="identifier">kx</span><span class="plain"> </span><span class="identifier">ky</span><span class="plain"> </span><span class="identifier">F</span><span class="plain"> </span><span class="identifier">E</span><span class="plain"> </span><span class="identifier">X</span><span class="plain"> </span><span class="identifier">Y</span><span class="plain">;</span>
<span class="identifier">filled</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">);</span>
<span class="identifier">ext</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">) + </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">filled</span><span class="plain"> &gt;= (</span><span class="identifier">ext</span><span class="plain"> - </span><span class="identifier">filled</span><span class="plain">) * </span><span class="identifier">RRP_CROWDED_IS</span><span class="plain">) {</span>
<span class="comment">copy entries to temporary space</span>
<span class="identifier">temp</span><span class="plain"> = </span><span class="identifier">FlexAllocate</span><span class="plain">(</span><span class="identifier">ext</span><span class="plain"> * (4*</span><span class="identifier">WORDSIZE</span><span class="plain">), </span><span class="identifier">TEXT_TY</span><span class="plain">, </span><span class="identifier">BLK_FLAG_WORD</span><span class="plain">+</span><span class="identifier">BLK_FLAG_MULTIPLE</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0: </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">ext</span><span class="plain">*4: </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">temp</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain">+</span><span class="identifier">i</span><span class="plain">), </span><span class="reserved">true</span><span class="plain">);</span>
<span class="comment">resize and clear our data</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ext</span><span class="plain"> &gt;= </span><span class="identifier">RRP_LARGE_IS</span><span class="plain">) </span><span class="identifier">newext</span><span class="plain"> = </span><span class="identifier">ext</span><span class="plain"> * </span><span class="identifier">RRP_RESIZE_LARGE</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">newext</span><span class="plain"> = </span><span class="identifier">ext</span><span class="plain"> * </span><span class="identifier">RRP_RESIZE_SMALL</span><span class="plain">;</span>
<span class="identifier">BlkValueSetLBCapacity</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="identifier">newext</span><span class="plain">*4);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_STORAGE</span><span class="plain">, </span><span class="identifier">newext</span><span class="plain"> - </span><span class="constant">1</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_FILLED</span><span class="plain">, </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_USED</span><span class="plain">));</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0: </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">newext</span><span class="plain">*4: </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain">+</span><span class="identifier">i</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="comment">copy entries back from temporary space</span>
<span class="identifier">kov</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_KIND</span><span class="plain">);</span>
<span class="identifier">kx</span><span class="plain"> = </span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="constant">0</span><span class="plain">); </span><span class="identifier">ky</span><span class="plain"> = </span><span class="identifier">KindBaseTerm</span><span class="plain">(</span><span class="identifier">kov</span><span class="plain">, </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0: </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">ext</span><span class="plain">: </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="identifier">F</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">temp</span><span class="plain">, </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">i</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">F</span><span class="plain"> == </span><span class="constant">0</span><span class="plain"> || (</span><span class="identifier">F</span><span class="plain"> &amp; </span><span class="identifier">RRF_DELETED</span><span class="plain">)) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="identifier">E</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">temp</span><span class="plain">, </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">i</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">X</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">temp</span><span class="plain">, </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">i</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="identifier">Y</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">temp</span><span class="plain">, </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">i</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">, </span><span class="reserved">true</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">F</span><span class="plain"> &amp; </span><span class="identifier">RRF_ENTKEYX</span><span class="plain">) </span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">TwoInOneLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">, </span><span class="identifier">RRF_ENTKEYX</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">TwoInOneLookUp</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">, </span><span class="identifier">RRF_ENTKEYY</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) { </span><span class="reserved">print</span><span class="plain"> </span><span class="string">"*** Duplicate entry while resizing ***^"</span><span class="plain">; </span><span class="reserved">rfalse</span><span class="plain">; }</span>
<span class="identifier">at</span><span class="plain"> = ~</span><span class="identifier">at</span><span class="plain">;</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">F</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">2</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="identifier">BlkValueWrite</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">3</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="comment">done with temporary space</span>
<span class="identifier">FlexFree</span><span class="plain">(</span><span class="identifier">temp</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">];</span>
<span class="plain">[ </span><span class="identifier">TwoInOneEntryMatches</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">at</span><span class="plain"> </span><span class="identifier">ke</span><span class="plain"> </span><span class="identifier">E</span><span class="plain"> </span><span class="identifier">ce</span><span class="plain">;</span>
<span class="identifier">ce</span><span class="plain"> = </span><span class="identifier">BlkValueRead</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RRV_DATA_BASE</span><span class="plain"> + </span><span class="constant">4</span><span class="plain">*</span><span class="identifier">at</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">KOVIsBlockValue</span><span class="plain">(</span><span class="identifier">ke</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">BlkValueCompare</span><span class="plain">(</span><span class="identifier">ce</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">) ~= </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ce</span><span class="plain"> ~= </span><span class="identifier">E</span><span class="plain">) </span><span class="reserved">rfalse</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">rtrue</span><span class="plain">;</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP23"></a><b>&#167;23. Empty. </b>This implements the "empty" adjective. We can always check whether a relation
is empty. For most relation types, we can cause the relation to become empty by
removing all pairs: but this is impossible for equivalence relations, which are
never empty, since any \(X\) is equivalent to itself. And we can never force a
relation to become non-empty, since that would require making up data.
</p>
<p class="inwebparagraph">In any case, the implementation is delegated to the relation handler.
</p>
<pre class="display">
<span class="plain">[ </span><span class="identifier">RELATION_TY_Empty</span><span class="plain"> </span><span class="identifier">rel</span><span class="plain"> </span><span class="identifier">set</span><span class="plain"> </span><span class="identifier">handler</span><span class="plain">;</span>
<span class="identifier">handler</span><span class="plain"> = </span><span class="identifier">RlnGetF</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RR_HANDLER</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">handler</span><span class="plain">(</span><span class="identifier">rel</span><span class="plain">, </span><span class="identifier">RELS_EMPTY</span><span class="plain">, </span><span class="identifier">set</span><span class="plain">);</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<hr class="tocbar">
<ul class="toc"><li><a href="S-cmb.html">Back to 'Combinations Template'</a></li><li><a href="S-rlt2.html">Continue with 'Relations Template'</a></li></ul><hr class="tocbar">
<!--End of weave-->
<script>
MathJax = {
tex: {
inlineMath: '$', '$'], ['\\(', '\\)'
},
svg: {
fontCache: 'global'
}
};
</script>
<script type="text/javascript" id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
</script>
</main>
</body>
</html>