1 /**
2 Copyright: Copyright (c) 2016- Alexander Orlov. All rights reserved.
3 License: $(LINK2 https://opensource.org/licenses/MIT, MIT License).
4 Authors: Alexander Orlov, $(LINK2 mailto:sascha.orlov@gmail.com, sascha.orlov@gmail.com) 
5 */
6 
7 /**
8 This module implements a Van Emde Boas tree container.
9 The module is still a work in progress. So, if you find an error by chance, please let me know in any way.
10 The main idea of the container is, to restrict the capacity of the tree by the next power of two universe size,
11 given an arbitrary size at the initialization. The tree can be used in two different modes: 
12 1. Tree contains keys only. Supported operations are 
13 inserting, deletion, membership testing, neighborhood searching. All queries are of order (lglg U), where U is the 
14 capacity of the tree, set on initialization. 
15 2. Tree contains keys and values. Additionally to the above operations the indexing operation is supported. It 
16 yields the pointer to a stored object, if the key is contained in the tree, otherwise null. 
17 For optimization purposes, the size limit is halfSizeT.max + 1. The tree was tested on 64- and 32-bit arch. 
18 So the largest element which can be stored is 4.294.967.295 on a 64-bit architecture. 
19 */
20 
21 // (optional) todo: provide functionality to contain non-unique keys, i. e. exercise 20.3.1 from Cormen
22 
23 /**
24 The main advantage of the Van Emde Boas tree appears on a large amount of elements, as the provided standard
25 operations of the tree are constant in time and of order O(lg2(lg2(U))), where U is the capacity of the tree. For
26 small amount of elements the overhead coming along with the structure take over. For example, for a universe size of
27 2^14 and 15872 insertion operatios the duration for the Van Emde Boas tree is about 1*10^(-3) times smaller. As one
28 of the unittests shows. 
29 */
30 
31 /**
32 Be aware, the current container is intended to be used with keys. This implies, that the capacity, fixed on its
33 initialization has two meanings. As usual, it shows the maximum amount of elements the instanciated tree can keep.
34 But also, it states, that no value bigger then capacity - 1 exists in the tree. This, and the fact, that only
35 non-negative values can be used are infered from the term "key".
36 */
37 
38 /**
39 See_also: Thomas H. Cormen, Clifford Stein, Ronald L. Rivest, and Charles E. Leiserson. 2001. <em>Introduction to
40 Algorithms</em> (2nd ed.). McGraw-Hill Higher Education.
41 */
42 
43 /**
44 As an important optimization a bottom out technique is used to compactify the tree to the level of nodes, where bit
45 operations become possible. As a side effect, the optimization now relies on the underlying architecture. This leads
46 to the fact, that the maximum of elements which can be stored is 
47 2^16 on a 32-bit architecture and 
48 2^32 on a 64-bit architecture. 
49 This was intentionally chosen for two reasons: 
50 i$(RPAREN) to keep the size of a single node also depending from the underlying architecture. 
51 ii$(RPAREN) for bitoperations, which the tree is relying on, to use the native word size of the architecture without
52 emulating bigger entities. 
53 */
54 
55 module vebtree; 
56 
57 import std.typecons : Nullable; 
58 import core.bitop;
59 import std.traits;
60 import std.range; 
61 import std.math : nextPow2; 
62 import core.stdc.limits : CHAR_BIT; 
63 import std.algorithm.iteration : each, map, uniq, sum, filter;
64 import std.algorithm.searching : until, find, canFind, maxIndex; 
65 import std.algorithm.sorting : sort; 
66 import std.algorithm.setops : setSymmetricDifference; 
67 import std.algorithm.comparison : min, max; 
68                         
69 
70 private enum vdebug = true; 
71 
72 version(unittest)
73 {
74     import std.random; 
75     import std.datetime.stopwatch; 
76     import std.conv : to;
77     import std.container; // red black tree may be used in unittests for comparison.
78     import std.math : sqrt; 
79 
80     static if(vdebug)
81     {
82         import std.stdio;
83         // helping function for output a given value in binary representation
84         void bin(size_t n)
85         {
86             /* step 1 */
87             if (n > 1) bin(n/2);
88             /* step 2 */
89             write(n % 2);
90         }
91     }
92 
93     /// precalculated powers of two table for unit testing
94     enum powersOfTwo = iota(0, CHAR_BIT * size_t.sizeof).map!(a => size_t(1) << a); 
95     
96     Random rndGenInUse; 
97 
98     // during tests it is ok a tree with a random capacity not going up to the maximum one. 
99     enum testedSize = 1 << 2 * size_t.sizeof; //3 * size_t.sizeof;
100     // during tests helping static arrays are used, which have an absolute maximum of size_t.sizeof * 2^20 elements
101     enum allowedArraySize = 1 << size_t.sizeof; //(2 * size_t.sizeof + size_t.sizeof/2); 
102     // choosed arbitrary, to avoid seg. faults
103 }
104 
105 /**
106 the baseSize defines the cutoff limit, where the node goes into the bit array mode. It is parametrized on the size
107 of size_t and changes dynamically with the architecture used. 
108 */
109 enum baseSize = CHAR_BIT * size_t.sizeof; 
110 
111 /**
112 the maxSizeBound defines the maximum the tree can be constructed with. It is parametrized on the size of size_t and
113 changes dynamically with the architecture used. 
114 */
115 enum maxSizeBound = size_t(1) << baseSize/2; // == uint.max + 1 on a 64-bit system
116 
117 /**
118 The default response of a tree node on a key request is null. I. e. if a key is not contained, null is returned. 
119 */
120 alias Response = Nullable!(size_t, maxSizeBound); 
121 
122 /// calculating the type, based on native type of the underlying system
123 static if(size_t.sizeof == 16) // future
124 {
125 	alias halfSizeT = ulong; 
126 }
127 else static if(size_t.sizeof == 8) // 64-bit case
128 {
129 	alias halfSizeT = uint; 
130 }
131 else static if(size_t.sizeof == 4) // 32-bit case 
132 {
133 	alias halfSizeT = ushort; 
134 }
135 else static if(size_t.sizeof == 2) // 16-bit case
136 {
137 	alias halfSizeT = ubyte; 
138 }
139 else 
140 {
141 	static assert(0);
142 }
143 
144 /// bit mask representing uint.max. 
145 enum size_t lowerMask = halfSizeT.max; 
146 /// bit mask representing size_t.max without uint.max. 
147 enum size_t higherMask = (size_t.max ^ lowerMask); 
148 
149 /**
150 This function returns the higher square root of the given input. It is needed in the initialization step 
151 of the VEB tree to calculate the number of children of a given layer. And this is the universe size of the
152 summary of a node. The upper square root is defined by 2^{\lceil(\lg u)/2\rceil}
153 */
154 size_t hSR(size_t value) @nogc nothrow 
155 {
156     return size_t(1) << (bsr(value)/2 + ((value.bsr & 1) || ((value != 0) && (value & (value - 1))))); 
157 }
158 ///
159 unittest
160 {
161     auto currentSeed = unpredictableSeed();
162     static if(vdebug){write("UT: hSR               "); writeln("seed: ", currentSeed);} 
163     rndGenInUse.seed(currentSeed); //initialize the random generator
164     size_t M = uniform(1U,halfSizeT.max, rndGenInUse); //set universe size to some integer. 
165     auto hSR = hSR(M); 
166 
167     assert((hSR & (hSR - 1)) == 0); 
168     if(hSR < halfSizeT.max) assert(hSR >= sqrt(to!float(M)));
169     
170     auto check = powersOfTwo.until(hSR).array; 
171     assert((check[$-1]) * (check[$-1]) < M); 
172 }
173 
174 /**
175 This function returns the lower square root of the given input. It is needed by the indexing functions
176 high(x), low(x) and index(x,y) of elements in the tree. Also, this is the universe size of a child of a node. The
177 lower square root is defined by 2^{\lfloor(\lgu)/2\rfloor}
178 */
179 size_t lSR(size_t value) @nogc nothrow 
180 {
181     return size_t(1) << (bsr(value)/2);
182 }
183 ///
184 unittest
185 {
186     auto currentSeed = unpredictableSeed();
187     static if(vdebug){write("UT: lSR               "); writeln("seed: ", currentSeed);} 
188     rndGenInUse.seed(currentSeed); //initialize the random generator
189     size_t M = uniform(1U,halfSizeT.max, rndGenInUse); //set universe size to some integer. 
190     auto lSR = lSR(M); 
191     
192     assert((lSR & (lSR - 1)) == 0); 
193     assert(lSR * lSR < M);
194     auto check = powersOfTwo.find(lSR); 
195     
196     if(lSR < halfSizeT.max) assert((check.drop(1).front) > sqrt(to!float(M))); 
197 }
198 
199 /*
200 This is an index function defined as \lfloor x/lSR(u)\rfloor. It is needed to find the appropriate cluster
201 of a element in the tree. It is a part of the ideal indexing function. 
202 */
203 private size_t high(size_t universe, size_t value) @nogc nothrow 
204 in
205 {
206     assert((universe & (universe - 1)) == 0); 
207 }
208 do
209 {
210     return value >> (bsr(universe) / 2);
211 }
212 //
213 unittest
214 {
215     auto currentSeed = unpredictableSeed();
216     static if(vdebug){write("UT: high              "); writeln("seed: ", currentSeed);} 
217     rndGenInUse.seed(currentSeed); //initialize the random generator
218     size_t M = uniform(1U,halfSizeT.max, rndGenInUse); //set universe size to some integer. 
219     size_t U = nextPow2(M); 
220     auto x = uniform(0U, U, rndGenInUse); 
221 
222     assert(high(U, x) == x / U.lSR); 
223 }
224 
225 /*
226 This is an index function defined as fmod(value, universe.lSR). It is needed to find the appropriate
227 value inside a cluster. It is part of the ideal indexing function
228 */
229 private size_t low(size_t universe, size_t value) @nogc nothrow
230 in
231 {
232     assert((universe & (universe - 1)) == 0); 
233 }
234 do
235 {
236     return value & ((size_t(1) << (bsr(universe) / 2)) - 1);
237 }
238 //
239 unittest
240 {
241     auto currentSeed = unpredictableSeed();
242     static if(vdebug){write("UT: low               "); writeln("seed: ", currentSeed);} 
243     rndGenInUse.seed(currentSeed); //initialize the random generator
244     size_t M = uniform(1U,halfSizeT.max, rndGenInUse); //set universe size to some integer. 
245     size_t U = nextPow2(M); 
246     auto x = uniform(0U, U, rndGenInUse); 
247 
248     assert(low(U, x) == (x & (U.lSR - 1)));
249 }
250 
251 /*
252 This is an index function to retain the searched value. It is defined as x * lSR(u) + y. Beyond this, the
253 relation holds: x = index(high(x), x.low). This is the ideal indexing function of the tree. 
254 */
255 private size_t index(size_t universe, size_t x, size_t y) @nogc nothrow
256 {
257     return (x * lSR(universe) + y);
258 }
259 //
260 unittest
261 {
262     auto currentSeed = unpredictableSeed();
263     static if(vdebug){write("UT: index             "); writeln("seed: ", currentSeed);} 
264     rndGenInUse.seed(currentSeed); //initialize the random generator
265     size_t M = uniform(0U,halfSizeT.max, rndGenInUse); //set universe size to some integer. 
266     
267     size_t U = nextPow2(M); 
268     auto x = uniform(0U, U, rndGenInUse); 
269     
270     assert(index(U, U.high(x), U.low(x)) == x); 
271 }
272 
273 /// convenience method for initializing a van emde boas tree root. This is the default method to get a tree. 
274 auto vebRoot(size_t universe)
275 in
276 {
277     assert(universe); 
278 }
279 do
280 {
281     return VEBroot(universe); 
282 }
283 ///
284 unittest
285 {
286     auto currentSeed = unpredictableSeed();
287     static if(vdebug){write("UT: 1. use case       "); writeln("seed: ", currentSeed);} 
288     rndGenInUse.seed(currentSeed); //initialize the random generator
289     
290     size_t M = uniform(2U, baseSize, rndGenInUse); //set universe size to some integer (small). 
291     size_t N = uniform(1U, M, rndGenInUse); //set universe size to some integer (small). 
292     
293     auto vT = vebRoot(M); 
294     assert(vT.empty); 
295 
296     size_t[] testArray = new size_t[N]; 
297     M.iota.randomCover(rndGenInUse).take(N)
298             .enumerate
299             .tee!(el => testArray[el.index] = el.value)
300             .each!(el => vT.insert(el.value));
301 
302     assert(vT.front == testArray.sort.front); 
303     assert(vT.back == testArray.sort.back); 
304     assert(vT().front == testArray.sort.front);  
305     assert(vT().back == testArray.sort.back); 
306     assert(vT[].front == 0); 
307     assert(vT[].back == vT.universe);
308     assert(vT.length == testArray.length); 
309     assert(vT() == testArray); 
310     assert(vT.capacity == baseSize); 
311     assert(vT.universe == M); 
312     assert(!vT.empty); 
313     testArray.each!(el => assert(el in vT)); 
314     size_t counter; 
315     for(auto el = vT.front; el != vT.back; el = vT.successor(el.get))
316     {
317         assert(el.get == testArray.sort[counter]); 
318         ++counter; 
319     }
320     for(auto el = vT.back; el != vT.front; el = vT.predecessor(el.get))
321     {
322         assert(el.get == testArray.sort[counter]); 
323         --counter; 
324     }
325     auto secondElementQ = vT.successor(testArray.sort[0]); 
326     if(!secondElementQ.isNull)
327     {
328         assert(testArray.sort.lowerBound(secondElementQ.get).length == 1); 
329     }
330 
331     auto randomElement = testArray[uniform(0, testArray.length, rndGenInUse)]; 
332     assert(!vT.insert(randomElement)); 
333 
334     auto vTdeepCopy = vT.dup; 
335     foreach(el; testArray)
336     {
337         vT.remove(el); 
338     }
339     assert(vT.empty); 
340     assert(!vT.length);
341     assert(vTdeepCopy.length == testArray.length); 
342 
343     auto vTdeepCopy2 = vTdeepCopy.dup; 
344 
345     vTdeepCopy2.remove(testArray[0]); 
346     assert(vTdeepCopy2.length + 1 == testArray.length); 
347     auto inclusiveSlice = vTdeepCopy[]; 
348     if(0 in vTdeepCopy)
349     {
350         assert(inclusiveSlice.length == testArray.length + 1); 
351     }
352     else
353     {
354         assert(inclusiveSlice.length == testArray.length + 2); 
355     }
356 
357     auto exclusiveSlice = vTdeepCopy(); 
358     assert(exclusiveSlice.length == vTdeepCopy.length); 
359     foreach(el; vTdeepCopy)
360     {
361         assert(el in exclusiveSlice);
362     }
363     foreach(el; exclusiveSlice)
364     {
365         assert(el in vTdeepCopy); 
366     }
367     auto shallowCopyFromRoot = vTdeepCopy; 
368     assert(!vTdeepCopy.empty); 
369     assert(vTdeepCopy.length == vTdeepCopy().length); 
370     assert(shallowCopyFromRoot == vTdeepCopy().save); 
371 
372     inclusiveSlice = vTdeepCopy[]; 
373     auto shallowCopyFromSlice = inclusiveSlice.save;
374     assert(inclusiveSlice.front == shallowCopyFromSlice.front);
375     inclusiveSlice.popFront; 
376     assert(inclusiveSlice.front != shallowCopyFromSlice.front);
377     
378     if(0 in vTdeepCopy)
379     {
380         assert(inclusiveSlice.front == vTdeepCopy.successor(0));
381     }
382     else
383     {
384         assert(inclusiveSlice.front == vTdeepCopy.front); 
385     }
386     
387     assert(vTdeepCopy() == testArray);
388     auto vTdeepCopy3 = vT.dup; 
389     auto vTshallowCopy = vT; 
390     assert(shallowCopyFromRoot.front == vTdeepCopy.front); 
391     vTdeepCopy.remove(vTdeepCopy.front.get); 
392     assert(shallowCopyFromRoot.front == vTdeepCopy.front); 
393  
394     assert(vTshallowCopy == vT);
395     assert(vTdeepCopy3 == vT); 
396 
397     assert(vT() == vT); 
398     assert(vT == vT());
399 }
400 ///
401 unittest
402 {
403     auto currentSeed = unpredictableSeed();
404     static if(vdebug){write("UT: 2. use case       "); writeln("seed: ", currentSeed);} 
405     rndGenInUse.seed(currentSeed); //initialize the random generator
406     
407     size_t M = uniform(baseSize + 1, testedSize, rndGenInUse); //set universe size to some integer (small). 
408     size_t N = uniform(1U, min(M, allowedArraySize), rndGenInUse); //set universe size to some integer (small). 
409     
410     auto vT = vebRoot(M); 
411     assert(vT.empty); 
412 
413     size_t[] testArray = new size_t[N]; 
414     
415     M.iota.randomCover(rndGenInUse).take(N)
416             .enumerate
417             .tee!(el => testArray[el.index] = el.value)
418             .each!(el => vT.insert(el.value));
419 
420     assert(vT.front == testArray.sort.front); 
421     assert(vT.back == testArray.sort.back); 
422     assert(vT().front == testArray.sort.front);  
423     assert(vT().back == testArray.sort.back); 
424     assert(vT[].front == 0); 
425     assert(vT[].back == vT.universe);
426     assert(vT.length == testArray.length); 
427     assert(vT() == testArray); 
428     assert(vT.capacity == M.nextPow2); 
429     assert(vT.universe == M); 
430     assert(!vT.empty); 
431     
432     testArray.each!(el => assert(el in vT)); 
433     size_t counter; 
434     for(auto el = vT.front; el != vT.back; el = vT.successor(el.get))
435     {
436         assert(el.get == testArray.sort[counter]); 
437         ++counter; 
438     }
439     for(auto el = vT.back; el != vT.front; el = vT.predecessor(el.get))
440     {
441         assert(el.get == testArray.sort[counter]); 
442         --counter; 
443     }
444 
445     auto secondElementQ = vT.successor(testArray.sort[0]); 
446     if(!secondElementQ.isNull)
447     {
448         assert(testArray.sort.lowerBound(secondElementQ.get).length == 1); 
449     }
450 
451     auto randomElement = testArray[uniform(0, testArray.length, rndGenInUse)]; 
452     assert(!vT.insert(randomElement)); 
453 
454     auto vTdeepCopy = vT.dup; 
455     foreach(el; testArray)
456     {
457         vT.remove(el); 
458     }
459     assert(vT.empty); 
460     assert(!vT.length);
461     assert(vTdeepCopy.length == testArray.length); 
462 
463     auto vTdeepCopy2 = vTdeepCopy.dup; 
464 
465     vTdeepCopy2.remove(testArray[0]); 
466     assert(vTdeepCopy2.length + 1 == testArray.length); 
467 
468     auto inclusiveSlice = vTdeepCopy[]; 
469     if(0 in vTdeepCopy)
470     {
471         assert(inclusiveSlice.length == testArray.length + 1); 
472     }
473     else
474     {
475         assert(inclusiveSlice.length == testArray.length + 2); 
476     }
477 
478     auto exclusiveSlice = vTdeepCopy(); 
479     assert(exclusiveSlice.length == vTdeepCopy.length); 
480     foreach(el; vTdeepCopy)
481     {
482         assert(el in exclusiveSlice);
483     }
484     foreach(el; exclusiveSlice)
485     {
486         assert(el in vTdeepCopy); 
487     }
488 
489     auto shallowCopyFromRoot = vTdeepCopy; 
490     assert(shallowCopyFromRoot == vTdeepCopy().save); 
491     inclusiveSlice = vTdeepCopy[]; 
492     auto shallowCopyFromSlice = inclusiveSlice.save;
493     assert(inclusiveSlice.front == shallowCopyFromSlice.front);
494     inclusiveSlice.popFront; 
495     assert(inclusiveSlice.front != shallowCopyFromSlice.front);
496     
497     if(0 in vTdeepCopy)
498     {
499         assert(inclusiveSlice.front == vTdeepCopy.successor(0));
500     }
501     else
502     {
503         assert(inclusiveSlice.front == vTdeepCopy.front); 
504     }
505     
506     assert(vTdeepCopy() == testArray);
507     auto vTdeepCopy3 = vT.dup; 
508     auto vTshallowCopy = vT; 
509     assert(shallowCopyFromRoot.front == vTdeepCopy.front); 
510     vTdeepCopy.remove(vTdeepCopy.front.get); 
511     assert(shallowCopyFromRoot.front == vTdeepCopy.front); 
512  
513     assert(vTshallowCopy == vT);
514     assert(vTdeepCopy3 == vT); 
515 
516     assert(vT() == vT); 
517     assert(vT == vT());
518 }
519 
520 //
521 unittest
522 {
523     auto currentSeed = unpredictableSeed(); // 83_843; 898_797_859; 
524     static if(vdebug){write("UT: vN, opBinaryIn    "); writeln("seed: ", currentSeed);} 
525     rndGenInUse.seed(currentSeed); //initialize the random generator
526 
527     auto value = uniform(0U, size_t.max, rndGenInUse);
528     auto bitNum = uniform(0U, baseSize, rndGenInUse);
529     auto vN = vebRoot(baseSize); 
530     *vN.val = value; 
531     
532     if((*vN.val & size_t(1) << bitNum) != 0 ) 
533     {
534         assert(bitNum in vN); 
535     }
536 
537     if((*vN.val & size_t(1) << bitNum) == 0 )
538     {
539         assert(!(bitNum in vN)); 
540     }
541 }
542 //
543 unittest
544 {
545     auto currentSeed = unpredictableSeed();
546     static if(vdebug){write("UT: vN, predecessor   "); writeln("seed: ", currentSeed);} 
547     rndGenInUse.seed(currentSeed); //initialize the random generator
548     auto v = uniform(2U, testedSize, rndGenInUse); //set universe size to some integer. 
549     auto x = uniform(1U, baseSize, rndGenInUse);
550     auto vN = vebRoot(baseSize); 
551     *vN.val = v; 
552 
553     bool found; 
554 
555     for(size_t index = x - 1; index >= 0; --index)
556     {
557         if (v & (size_t(1) << index)) 
558         {
559             found = true; 
560             assert(!vN.empty);
561             assert(vN.predecessor(x) == index); 
562             break; 
563         }
564         if(!index) break; 
565     }
566 
567     if(!found) assert(vN.predecessor(x).isNull); 
568 }
569 //
570 unittest
571 {
572     auto currentSeed = unpredictableSeed();
573     static if(vdebug){write("UT: vN, successor     "); writeln("seed: ", currentSeed);} 
574     rndGenInUse.seed(currentSeed); //initialize the random generator
575     auto v = uniform(0U, size_t.max, rndGenInUse); //set universe size to some integer. 
576     auto x = uniform(0U, baseSize, rndGenInUse);
577     auto vN = vebRoot(baseSize); 
578     *vN.val = v; 
579     bool found; 
580 
581     for (size_t index = x + 1; index < baseSize; ++index)
582     {
583         if (v & (size_t(1) << index)) 
584         {
585             found = true; 
586             assert(vN.successor(x).get == index); 
587             break; 
588         }
589     }
590     if(!found) assert(vN.successor(x).isNull);
591 }
592 
593 /**
594 This is the struct to represent a VEB tree node. Its members are
595 - a pointer to the stats: universe and current inserted element amount 
596 - a pointer to the min and max values. These pointee is used as a bit array in the leaf nodes. 
597 - a poitner (or array) to the child nodes, in case the node is not a leaf node
598 - a pointer (an array) to the data pointers, in case the tree is used with data. 
599 Dependent from the universe size passed in a method the stored value will be interpretated in two different ways: 
600 If the parameter passed shows, that the universe size is below the bit size of the stored value, then, it can be
601 handled as a bit array and all operations decay to operations defined in core.bitop. This case correspond to
602 the state of the node being a leaf. No children exist and the pointer should stay uninitialized
603 Otherwise, the value is interpretated as two values, the minimum and maximum stored at the same place in memory. The
604 minimum and maximum shows, which range is achievable through this node. The parameters passed to a function of the
605 node have to be well chosen, to hit the appropriate child. 
606 The first element of the children array, if present is handled different. According to literature, it has the role
607 of the summary of the remaining children cluster. With it help it is possible to achieve a very small recursion
608 level during an access. 
609 */
610 struct VEBroot
611 {
612     /**
613     yields the next power of two, based un universe size
614     */
615     @property size_t capacity() @nogc
616     in
617     {
618         assert(stats !is null); 
619     }
620     do
621     {
622         if(universe <= baseSize)
623         {
624             return baseSize; 
625         }
626         else
627         {
628             return universe.nextPow2; 
629         }
630     }
631 
632     /**
633     yields the universe size of a node. The root has the unvierse size, defined on tree creation
634     */
635     @property size_t universe() const @nogc nothrow
636     in
637     {
638         assert(stats !is null); 
639     }
640     do
641     {
642         return (*stats & higherMask) >> (size_t.sizeof * CHAR_BIT/2);     
643     }
644 
645     /**
646     yields the current inserted elements under the node, including the two elements of the node itself. 
647     */
648     @property size_t length() @nogc
649     in
650     {
651         assert(stats !is null); 
652     }
653     do
654     {
655         return *stats & lowerMask; 
656     }
657 
658     /**
659     the opApply method grants the correct foreach behavior, nogc version
660     */
661     int opApply(scope int delegate(ref size_t) @nogc operations) @nogc
662     {
663         return opApplyImpl(operations);
664     }
665 
666     /**
667     the opApply method grants the correct foreach behavior
668     */
669     int opApply(scope int delegate(ref size_t) operations)
670     {
671         return opApplyImpl(operations);
672     }
673 
674     // with the trick of https://forum.dlang.org/thread/erznqknpyxzxqivawnix@forum.dlang.org
675     private int opApplyImpl(O)(O operations)
676     {
677         int result; 
678         
679         for(auto leading = front; !leading.isNull; leading = successor(leading.get)) 
680         {
681             result = operations(leading.get);     
682             
683             if(result)
684             {
685                 break; 
686             }
687         }
688 
689         return result;
690     }
691 
692     /**
693     method returning either the lower part of the stored value (intermediate node) or the lowest bit set (bit vector
694     mode). If the node does not contain any value (min > max or value == 0) Nullable.null is returned. 
695     */
696     @property Response front() @nogc nothrow
697     {
698         /*
699             we have only a chance to get a value, if a value is present.
700             if it is a leaf, handle the val as a bit array and find the first bit set from the right. 
701             if it is not a leaf, get the minimum. 
702         */ 
703         if(!empty) 
704         {
705             if(isLeaf)
706             {
707                 return typeof(return)(bsf(*val));
708             }
709             else
710             {
711                 return typeof(return)(*val & lowerMask); 
712             }   
713         }
714         // return the result, even if it was not set to a value. 
715         return typeof(return).init;  
716     }
717 
718     /** 
719     method returning either the higher part of the stored value (intermediate node) or the highest bit set (bit
720     vector mode). If the node does not contain any value (min > max or value == 0) Nullable.null is returned. 
721     */
722     @property Response back() @nogc nothrow 
723     {
724         /*
725             we have only a chance to get a value, if a value is present. 
726             if it is a leaf, handle the val as a bit array and find the first bit set from the left. 
727             if it is not a leaf, get the max. 
728         */
729         if(!empty)
730         {
731             if(isLeaf)
732             {
733                 return typeof(return)(bsr(*val)); 
734             }   
735             else
736             {
737                 return typeof(return)((*val & higherMask) >> (size_t.sizeof * CHAR_BIT/2));
738             }
739         }
740         // return the result, even if it was not set to a value. 
741         return typeof(return).init;  
742     }
743 
744     /**
745     yields a deep copy of the node. I. e. copies all data in children and allocates another tree 
746     */
747     typeof(this) dup()
748     {
749         auto copy = this;
750         copy.stats = new size_t(); 
751         copy.val = new size_t();  
752         *copy.stats = *this.stats;
753         *copy.val = *this.val; 
754         if(!isLeaf)
755         {
756             copy.ptrArr = this.ptrArr[0 .. hSR(universe.nextPow2) + 1].dup;
757             copy.ptrArr[0 .. hSR(universe.nextPow2) + 1].each!((ref n) => n = n.dup);
758         }
759         
760         return copy;
761     }
762 
763     /**
764     []-slicing. Yields a "random access range" with the content of the tree, always containing zero and universe as keys
765     */
766     auto opIndex()
767     {
768         return VEBtree!(Yes.inclusive)(this);  
769     }
770 
771     /**
772     ()-slicing. Yields a "random access range" with the content of the tree. Keys can be isNull. 
773     */
774     auto opCall()
775     {
776         return VEBtree!(No.inclusive)(this);  
777     }
778 
779     /** 
780     method to check whether the current node holds a value
781     */
782     @property bool empty() @nogc nothrow
783     {
784         if(val is null)
785         {
786             return true; 
787         }
788         else
789         {
790             if(isLeaf)
791             {
792                 return *val == 0; 
793             }
794             else
795             {
796                 return (*val & lowerMask) > ((*val & higherMask) >> (size_t.sizeof * CHAR_BIT/2)); 
797             }
798         }
799     }
800 
801     /**
802     member method for the case universe size < base size. Overloads by passing only one parameter, which is
803     the bit number of interest. Returns whether the appropriate bit inside the bitvector is set.
804     */
805     bool opBinaryRight(string op)(size_t key) if(op == "in")  // @nogc nothrow 
806     {
807         assert(universe); 
808         if(key > universe.nextPow2)
809         {
810             return false; 
811         }
812         if(isLeaf)
813         {
814             assert(key < baseSize);
815             return bt(val, key) != 0;
816         }
817         else
818         {
819             if(empty)
820             {
821                 // if an empty intermediate node is found, nothing is stored below it. 
822                 return false; 
823             } 
824             // case of a single valued range. 
825             if(key == front || key == back)
826             {
827                 return true; 
828             }
829             
830             /*
831                 else we have to descend, using the recursive indexing: 
832                 1. take the high(value, uS)-th child and 
833                 2. ask it about the reduced low(value, uS) value
834                 3. use the lSR(uS) universe size of the childe node. 
835             */
836             
837             assert(cluster[high(key)].universe == lSR(universe.nextPow2));
838             return low(key) in cluster[high(key)]; 
839         }
840     }
841 
842     alias put = insert; 
843     /**
844     insert method. this method is called from class with a universe size given. It performs recursion calls untill
845     the universe size is reduced to the base size. Then the overloaded insert method is called. 
846     */
847     bool insert(size_t key) @nogc
848     {        
849         if(key > capacity)
850         {
851             return false;
852         }
853 
854         // if descended so far, do not use other functionality any more. 
855         if(isLeaf)
856         {
857             assert(val !is null); 
858             return length = length + (bts(val, key) == 0); 
859         }
860 
861         if(empty) // if the current node does not contain anything put the value inside. 
862         {
863             front = key; 
864             back = key; 
865 
866             assert(!empty); 
867             
868             return length = length + 1; 
869         }
870 
871         assert(!empty);
872         assert(!front.isNull); 
873         assert(!back.isNull); 
874 
875         if(key == front || key == back)
876         {
877             return false; 
878         }
879 
880         if(front == back) // if the node contains a single value only, expand the node to a range and leave. 
881         {
882             if(front > key)
883             {
884                 front = key; 
885             }
886             if(back < key)
887             {
888                 back = key; 
889             }
890             
891             return length = length + 1; 
892         }
893         /*
894             if none of the cases above was true (all of them are break conditions) we have to compare the given value
895             with the values present and adapt the range limits. This replaces the value we want to insert. 
896         */
897         // a swap can not be used here, as min is itself a (property) method 
898         if(key < front)
899         {
900             auto tmpKey = key; 
901 
902             key = front.get;
903 
904             front = tmpKey;
905             
906         }
907         // a swap can not be used here, as max is itself a (property) method 
908         if(key > back)
909         {
910             auto tmpKey = key; 
911             
912             key = back.get; 
913             
914             back = tmpKey; 
915         }
916         
917         // calculate the index of the children cluster by high(value, uS) we want to descent to. 
918         auto nextTreeIndex = high(key); 
919         
920         // if the child is happened to be null we have to update the summary and insert value of high(value, uS) into it
921         assert(summary.universe == hSR(universe.nextPow2));
922         
923         if(cluster[nextTreeIndex].empty)
924         {
925             summary.insert(high(key));
926         }
927         
928         // in any case we pass the lowered value low(value, uS) to the child. 
929         assert(cluster[nextTreeIndex].universe == universe.nextPow2.lSR);
930         return length = length + cluster[nextTreeIndex].insert(low(key)); 
931     }
932 
933     /**
934     remove method. this method is called from class with a universe size given. It performs recursion calls untill
935     the universe size is reduced to the base size. Then the overloaded remove method is called. 
936     */
937     auto remove(size_t key) @nogc // nothrow 
938     {
939         // if descended so far, do not use other functionality any more. 
940         if(isLeaf)
941         {
942             return length = length - btr(val, key) != 0; 
943         }
944 
945         if(empty) 
946         {
947             // if the current node is null, there is nothing to remove. 
948             return false;
949         }
950         
951         if(front == back) // if the current node contains only a single value
952         {
953             if(front != key)
954             {
955                 // do nothing if the given value is not the stored one 
956                 return false; 
957             } 
958 
959             this.nullify; 
960             return length = length - 1; 
961         }
962 
963         if(key == front) // if we met the minimum of a node 
964         {
965             auto treeOffset = summary.front; // calculate an offset from the summary to continue with
966             if(treeOffset.isNull) // if the offset is invalid, then there is no further hierarchy and we are going to 
967             {
968                 front = back; // store a single value in this node. 
969                 return length = length - 1; 
970             }
971             auto min = cluster[treeOffset.get].front; // otherwise we get the minimum from the offset child
972             
973             assert(cluster[treeOffset].universe == universe.nextPow2.lSR); 
974 
975             // remove it from the child 
976             cluster[treeOffset.get].remove(min); 
977             
978             // if it happens to become null during the remove process, we also remove the offset entry from the summary 
979             assert(summary.universe == universe.nextPow2.hSR);
980             if(cluster[treeOffset.get].empty)
981             {
982                 summary.remove(treeOffset.get); 
983             }
984 
985             //anyway, the new min of the current node become the restored value of the calculated offset. 
986             front = index(treeOffset.get, min); 
987             
988             return length = length - 1; 
989         }
990 
991         // if we met the maximum of a node 
992         if(key == back) 
993         {
994             // calculate an offset from the summary to contiue with 
995             auto treeOffset = summary.back; 
996             // if the offset is invalid, then there is no further hierarchy and we are going to 
997             if(treeOffset.isNull) 
998             {
999                 // store a single value in this node. 
1000                 back = front; 
1001                 return length = length - 1; 
1002             }
1003 
1004             // otherwise we get maximum from the offset child 
1005             auto max = cluster[treeOffset.get].back; 
1006             assert(cluster[treeOffset.get].universe == universe.nextPow2.lSR);
1007 
1008             // remove it from the child 
1009             cluster[treeOffset.get].remove(max); 
1010 
1011             // if it happens to become null during the remove process, we also remove the offset enty from the summary 
1012             assert(summary.universe == universe.nextPow2.hSR);
1013             if(cluster[treeOffset.get].empty) summary.remove(treeOffset.get); 
1014 
1015             // anyway, the new max of the current node become the restored value of the calculated offset. 
1016             back = index(treeOffset.get, max); 
1017             
1018             return length = length - 1; 
1019         }
1020 
1021         // if no condition was met we have to descend deeper. We get the offset by reducing the value to high(value, uS)
1022         auto treeOffset = high(key); 
1023         // and remove low(value, uS) from the offset child. 
1024         assert(cluster[treeOffset].universe == universe.nextPow2.lSR);
1025 
1026         typeof(return) res = length = length - cluster[treeOffset].remove(low(key)); 
1027         
1028         // if the cluster become null during the remove process we have to update the summary node. 
1029         assert(summary.universe == universe.nextPow2.hSR);
1030         
1031         if(cluster[treeOffset].empty)
1032         {
1033             summary.remove(treeOffset); 
1034         }
1035 
1036         return res; 
1037     }
1038 
1039     /**
1040     predecessor method. this method is called from class with a universe size given. It performs recursion calls
1041     until the universe size is reduced to the base size. Then the overloaded predecessor method is called. 
1042     */
1043     Response predecessor(size_t value) @nogc nothrow
1044     {
1045         // if descended so far, do not use other functionality any more. 
1046         if(isLeaf)
1047         {   
1048             if(!empty && (value != 0))
1049             {
1050                 /*
1051                 create a mask, which hides all higher bits of the stored value down to the given bit number, then apply
1052                 bit search from the highest bit. 
1053                 */
1054                 auto maskedVal = *val & ((size_t(1) << value) - 1); 
1055                 if(maskedVal != 0)
1056                 {
1057                      return typeof(return)(maskedVal.bsr);
1058                 }
1059             }
1060             return typeof(return).init; 
1061         }
1062         // if this node is empty, no predecessor can be found here or deeper in the tree
1063         if(empty)
1064         {
1065             return typeof(return).init;
1066         }
1067         // if given value is greater then the stored max, the predecessor is max
1068         if(value > back)
1069         {
1070             return typeof(return)(back); 
1071         }
1072         // if given value is less then the min, no predecessor exists. 
1073         if(value <= front)
1074         {
1075             return typeof(return).init; 
1076         }
1077         /*
1078         if none of the break conditions was met we have to descend further into the tree. 
1079         */
1080         auto childIndex = high(value); // calculate the child index by high(value, uS)
1081         auto minlow = cluster[childIndex].front; // look into the child for its minimum
1082         // if the minimum exists and the lowered given value is greater then the child's minimum
1083         if(!minlow.isNull && low(value) > minlow) 
1084         {
1085             // calculate an offset to continue with by asking the child on predecessor of the lowered value. 
1086             assert(cluster[childIndex].universe == universe.nextPow2.lSR);
1087             auto offset = cluster[childIndex].predecessor(low(value)); 
1088             // the result is given by reconstruction of the answer. 
1089             return typeof(return)(index(childIndex, offset)); 
1090         }
1091         else // otherwise we can not use the minimum of the child 
1092         {
1093             // ask the summary for the predecessor cluster. 
1094             assert(summary.universe == universe.nextPow2.hSR); 
1095             auto predcluster = summary.predecessor(childIndex);
1096             // if the predecessor cluster is null return the current min, as this is the last remaining value 
1097             if(predcluster.isNull)
1098             {
1099                 return typeof(return)(front); 
1100             }
1101             // if the predecessor cluster exists, the offset is given by its maximum
1102             // and the result by the reconstruction of the offset. 
1103             return typeof(return)(index(predcluster, cluster[predcluster].back)); 
1104         }
1105     }
1106 
1107     /**
1108     successor method. this method is called from class with a universe size given. It performs recursion calls until
1109     the universe size is reduced to the base size. Then the overloaded successor method is called. 
1110     */
1111     Response successor(size_t value) @nogc nothrow 
1112     {
1113         // if descended so far, do not use other functionality any more. 
1114         if(isLeaf)
1115         {        
1116             if(!empty && (value + 1 < baseSize)) 
1117             {
1118                 // create a mask, which hides all lower bits of the stored value up to the given bit number, then apply
1119                 // bit search from the lowest bit. 
1120                 auto maskedVal = *val & ~((size_t(1) << (value + 1)) - 1); 
1121                 if(maskedVal != 0) 
1122                 {
1123                     return typeof(return)(maskedVal.bsf);
1124                 }
1125             }
1126             return typeof(return).init; 
1127         } 
1128         // if this node is empty, no successor can be found here or deeper in the tree
1129         if(empty) return typeof(return).init; 
1130         // if given value is less then the min, return the min as successor
1131         if(value < front) return typeof(return)(front); 
1132         // if given value is greater then the max, no predecessor exists
1133         if(value >= back) return typeof(return).init; 
1134         
1135         // if none of the break conditions was met, we have to descent further into the tree. 
1136         // calculate the child index by high(value, uS)
1137         auto childIndex = high(value); 
1138         // look into the child for its maximum
1139         auto maxlow = cluster[childIndex].back; 
1140         // if the maximum exists and the lowered given value is less then the child's maximum 
1141         if(!maxlow.isNull && low(value) < maxlow)
1142         {
1143             // calculate an offset to continue with by asking the child on predecessor of the lowered value
1144             assert(cluster[childIndex].universe == universe.nextPow2.lSR);
1145             auto offset = cluster[childIndex].successor(low(value)); 
1146             // the result is given by reconstruction of the answer
1147             return typeof(return)(index(childIndex, offset));
1148         }
1149         else // otherwise we can not use the maximum of the child 
1150         {
1151             // ask the summary for the successor cluster. 
1152             assert(summary.universe == universe.nextPow2.hSR); 
1153             auto succcluster = summary.successor(childIndex); 
1154             // if the successor cluster is null
1155             if(succcluster.isNull)
1156             {
1157                 // return the current max, as this is the last remaining value
1158                 return typeof(return)(back); 
1159             }
1160             
1161             // if the successor cluster exists, the offset is given by its minimum
1162             // and the result by the reconstruction of the offset. 
1163             return typeof(return)(index(succcluster, cluster[succcluster].front)); 
1164         }
1165     }
1166 
1167     /**
1168     dummy toHash method. 
1169     */
1170     size_t toHash() const nothrow @safe { assert(0); }
1171 
1172     /**
1173     comparison operator for the recursive node of the same kind. 
1174     */
1175     bool opEquals(O)(ref const O input) const if(is(Unqual!O == Unqual!(typeof(this))))
1176     {
1177         // short circuit, if pointers are the same
1178         if(stats == input.stats)
1179         {
1180             assert(val == input.val); 
1181             return true; 
1182         }
1183 
1184         // otherwise we have to check the whole structure.
1185         if(*stats != *input.stats)
1186         {
1187             return false; 
1188         }
1189         if(*val != *input.val)
1190         {
1191             return false; 
1192         }
1193         if(!isLeaf)
1194         {
1195             if(summary != input.summary)
1196             {
1197                 return false; 
1198             }
1199             foreach(i, ref c; cluster)
1200             {
1201                 if(c != input.cluster[i])
1202                 {
1203                     return false; 
1204                 }
1205             }    
1206         }
1207         else
1208         {
1209             if(!input.isLeaf)
1210             {
1211                 return false; 
1212             }
1213         }
1214         return true; 
1215     }
1216 
1217     private: 
1218     /*
1219     This pointer acts as an array to nodes like this one. As the universe size is not provided, the length of the
1220     array can not be used to calculate the most of operations, so no explicit array is needed. The only remaining
1221     property is whether the pointer is set at all. From this property the node can decide, whether it is a leaf or
1222     an intermediate node. // the first member behaves different, as the others, as it is the summary node. 
1223     */
1224 
1225     typeof(this)[] ptrArr;
1226     
1227     // contains max and min, or the bit array of keys
1228     size_t* val;
1229     // contains universe size and the current length
1230     size_t* stats; 
1231     
1232     // property returning the summary node 
1233     @property auto ref summary() inout// @nogc nothrow 
1234     in
1235     {
1236         assert(!isLeaf);
1237     }
1238     do
1239     {
1240         return ptrArr[0];
1241     }
1242     
1243     // property returning the cluster array 
1244     @property auto ref cluster() inout// @nogc nothrow 
1245     in
1246     {
1247         assert(!isLeaf);
1248     }
1249     do
1250     {
1251         return ptrArr[1 .. hSR(universe.nextPow2) + 1];
1252     }
1253     
1254     @property bool universe(size_t input) @nogc
1255     in
1256     {
1257         assert(stats !is null); 
1258         assert(input < maxSizeBound);
1259     }
1260     do
1261     {
1262         const retVal = universe != input; 
1263 
1264         if(retVal)
1265         {
1266             *stats = *stats & lowerMask; 
1267             *stats = *stats | (input << (size_t.sizeof * CHAR_BIT/2));    
1268         }
1269 
1270         return retVal; 
1271     }
1272 
1273     @property bool length(size_t input) @nogc
1274     in
1275     {
1276         assert(stats !is null); 
1277         assert(input < maxSizeBound);
1278     }
1279     do
1280     {
1281         const retVal = length != input; 
1282         
1283         if(retVal)
1284         {
1285             *stats = *stats & higherMask; 
1286             *stats = *stats | input;     
1287         }
1288         
1289         return retVal; 
1290     }
1291 
1292     /**
1293     Node constructor. A universe size provided, if the size is below the cutoff there is nothing to be done, as the
1294     underlying value created and set to zero by default. 
1295     If otherwise create an array of children. This array has to be (according to Cormen) of size of higher square
1296     root of the current universe size + 1. The extra place is reserved for the summary. 
1297     For each just created child call its constructor.
1298     For the summary with the universe size of the higher square root of the current universe size. 
1299     For each other child with the universe size of the lower square root of the currennt universe size. 
1300     Then, assign the fully initialized children array to the pointer in the current node, doing approprate steps to
1301     show, that this node is an intermediate node, not containing any values yet. 
1302     The knowledge of the current universe size is lost at this moment. As this keeps every build up node smaller 
1303     (and there could be a lot of them). This is why, the VEBtree class continues to hold the global universe size,
1304     which is passed on every call to the root node. In this way this, extern saved value has the role of being
1305     outsourced array size for each (!) node in the tree, as its size is reconstructed during the access to them. 
1306     */
1307     this(size_t uS) // nothrow 
1308     {
1309         stats = new size_t(); 
1310         val = new size_t(); 
1311 
1312         universe = uS; 
1313         
1314         assert(stats !is null); 
1315         if(universe > baseSize)
1316         {
1317             // reserve enough place for the summary and the children cluster
1318             assert(stats !is null); 
1319             ptrArr.length = hSR(universe.nextPow2) + 1;
1320 
1321             // add the summary with its universe of higher squaure root of the current universe
1322             assert(stats !is null); 
1323             summary = typeof(this)(universe.nextPow2.hSR); 
1324             assert(stats !is null); 
1325             assert(ptrArr[0].stats !is null); 
1326             assert(ptrArr[0].universe == universe.nextPow2.hSR);
1327             // add higher square root children with lower square root universe each.
1328             assert(stats !is null); 
1329 
1330             cluster.each!((ref el) => el = typeof(this)(universe.nextPow2.lSR));
1331             assert(stats !is null); 
1332             ptrArr[1 .. hSR(universe.nextPow2) + 1].each!((ref el) => assert(el.universe == universe.nextPow2.lSR));
1333             
1334         }
1335         nullify; // set the value to the sentinel value to represent the empty state. 
1336     }
1337 
1338     /** convinience method to check, if the node belongs to the lowest level in the tree */
1339     @property bool isLeaf() @nogc const nothrow
1340     in
1341     {
1342         assert(stats !is null); 
1343     }
1344     do
1345     {
1346         return universe <= baseSize;
1347     }
1348 
1349     /** method executing the appropriate steps to nullify the current node */
1350     @property void nullify() @nogc // nothrow 
1351     in
1352     {
1353         assert(val !is null); 
1354     }
1355     do
1356     {
1357         if(isLeaf)
1358         {
1359             *val = 0; 
1360         }
1361         else
1362         {
1363             *val = 1; 
1364         }
1365     }  
1366 
1367     /**
1368     setter for the min, setting either the lowest bit or the min part of the value. 
1369     */
1370     @property void front(size_t key) @nogc
1371     {
1372         if(isLeaf)
1373         {
1374             assert(front > key);
1375             insert(key); 
1376         }
1377         else
1378         {
1379             // the passed value should not exceed the allowed size of a size/2
1380             assert(key < maxSizeBound);
1381             *val = *val & higherMask;
1382             *val = *val | key;
1383         }
1384     }
1385 
1386     /**
1387     setter for the max, setting either the highest bit or the max part of the value. 
1388     */
1389     @property void back(size_t key) @nogc
1390     {
1391         if(isLeaf) 
1392         {
1393             assert(back < key); 
1394             insert(key); 
1395         }
1396         else
1397         {
1398             // the passed value should not exceed the allowed size of a size/2
1399             assert(key < maxSizeBound); 
1400             *val = *val & lowerMask; 
1401             *val = *val | (key << (size_t.sizeof * CHAR_BIT/2));
1402         }
1403     }
1404 
1405     size_t low(size_t key) @nogc nothrow
1406     {
1407         return .low(universe.nextPow2, key); 
1408     }
1409 
1410     size_t high(size_t key) @nogc nothrow 
1411     {
1412         return .high(universe.nextPow2, key); 
1413     }
1414 
1415     size_t index(size_t x, size_t y) @nogc nothrow 
1416     {
1417         return .index(universe.nextPow2, x, y); 
1418     }
1419 }
1420 
1421 ///
1422 unittest
1423 {
1424     
1425     auto vN = vebRoot(baseSize); 
1426     assert(vN.empty); 
1427     static assert(vN.sizeof == 4 * size_t.sizeof); 
1428     assert(vN.isLeaf); 
1429     assert(vN.empty); 
1430     *vN.val = 3; 
1431     assert(vN.front == 0);
1432     assert(1 in vN);
1433     assert(!(2 in vN));
1434     assert(vN.isLeaf);
1435     assert(vN.ptrArr == null); 
1436     vN.nullify; 
1437     assert(vN.empty); 
1438     assert(*vN.val == 0); 
1439     
1440 }
1441 
1442 ///
1443 unittest
1444 {
1445     
1446     auto vT = vebRoot(100); 
1447     assert(vT.empty);
1448     auto result = vT.insert(2); 
1449     
1450     assert(result); 
1451     assert(!vT.empty); 
1452     assert(2 in vT);
1453     assert(vT.length == 1);      
1454     
1455     auto vT2 = vT;
1456     auto vT3 = vT.dup(); 
1457     assert(2 in vT2);
1458     assert(vT2.length == 1); 
1459     auto result2 = vT2.insert(3);
1460     assert(vT2.length == 2);
1461     assert(result2); 
1462     assert(3 in vT2); 
1463     assert(3 in vT);
1464     assert(!(3 in vT3));
1465     assert(vT2.length == 2);
1466     
1467 }
1468 
1469 ///
1470 unittest
1471 {
1472     
1473     auto currentSeed = unpredictableSeed();
1474     static if(vdebug){write("UT: vT, [], ()        "); writeln("seed: ", currentSeed);} 
1475     rndGenInUse.seed(currentSeed); //initialize the random generator
1476 
1477     size_t M = uniform(2U,testedSize, rndGenInUse); //set universe size to some integer. 
1478     auto vT = vebRoot(M); //create the tree
1479     assert(M.iota.map!(i => vT.insert(uniform(0, vT.universe, rndGenInUse))).sum == vT.length); 
1480     
1481     assert(vT[].front == 0); 
1482     assert(vT[].back == vT.universe); 
1483     
1484 }
1485 ///
1486 unittest
1487 {
1488     auto p = vebRoot(100); 
1489     assert(p.empty); 
1490     p.insert(5); 
1491     p.insert(100); 
1492     assert(!p.empty); 
1493     assert(p.successor(0) == 5); 
1494     assert(p.successor(4) == 5); 
1495     assert(p.successor(5) == 100); 
1496     auto s = p[]; 
1497     static assert(isBidirectionalRange!(typeof(s)));
1498     assert(s.front == 0); 
1499     assert(p.front == 5); 
1500     s.popFront; 
1501     assert(!s.empty); 
1502     assert(s.front == 5); 
1503     s.popFront; 
1504     assert(s.front == 100); 
1505     s.popFront; 
1506     assert(s.empty); 
1507 
1508     auto pp = vebRoot(100);
1509     assert(pp.empty); 
1510     pp.insert(5); 
1511     assert(!pp.empty); 
1512     assert(pp.successor(0) == 5); 
1513     assert(pp.successor(4) == 5); 
1514     assert(pp.successor(5).isNull);
1515     assert(pp[].successor(5) == 100); 
1516     auto ss = pp(); 
1517     static assert(isBidirectionalRange!(typeof(ss)));
1518     assert(ss.front == 5); 
1519     ss.popFront; 
1520     assert(ss.empty); 
1521     assert(ss.front.isNull); 
1522 }
1523 ///
1524 unittest
1525 {
1526     
1527     auto vT = vebRoot(1000); 
1528     assert(vT.capacity == 1024); 
1529     assert(vT.front.isNull); 
1530     assert(vT.insert(2)); 
1531     assert(vT.insert(5));
1532     assert(!(8 in vT)); 
1533     assert(vT.insert(88));
1534     assert(88 in vT); 
1535     assert(vT.predecessor(4) == 2);
1536     assert(!(8 in vT)); 
1537     assert(vT.insert(8)); 
1538     assert(8 in vT); 
1539     assert(vT.predecessor(75) == 8); 
1540     
1541     assert(vT.predecessor(90) == 88); 
1542     
1543     assert(vT.predecessor(7) == 5); 
1544     assert(vT.predecessor(4) == 2); 
1545     assert(vT.predecessor(2).isNull); 
1546     
1547     //TODO: reactivate this by slicing assert(vT[].predecessor(2) == 0); 
1548     
1549     assert(vT.predecessor(2).isNull); 
1550     
1551     assert(vT.successor(6) == 8); 
1552     assert(vT.successor(5) == 8); 
1553     
1554     assert(vT.successor(4) == 5); 
1555     assert(vT.successor(1) == 2); 
1556     assert(vT.successor(75) == 88); 
1557     assert(vT.successor(90).isNull); 
1558     //TODO: reactivate this by slicing assert(vT[].successor(90) == vT.universe);
1559     
1560     assert(!(1029 in vT)); 
1561     
1562     assert(vT.successor(1025).isNull);
1563     assert(vT.successor(1025).isNull);
1564     
1565     auto vT2 = vebRoot(500); 
1566     assert(vT2.empty); 
1567     vT2.insert(50); 
1568     vT2.insert(500); 
1569     assert(vT2.back == 500); 
1570     assert(vT2.front == 50); 
1571     assert(vT2.successor(40) == 50);
1572     assert(vT2.successor(50) == 500); 
1573     
1574     vT2 = vebRoot(500); 
1575     assert(vT2.empty); 
1576     vT2.insert(50); 
1577     vT2.insert(500); 
1578     assert(vT2.back == 500); 
1579     assert(vT2.front == 50); 
1580     assert(vT2.successor(40) == 50);
1581     assert(vT2.successor(50) == 500); 
1582 
1583     /* about 20 seconds in debug mode. 
1584     auto vT3 = vebRoot(halfSizeT.max);
1585     assert(vT3.insert(5)); 
1586     assert(vT3.member(5));
1587     assert(vT3.capacity == cast(ulong)halfSizeT.max + 1UL);
1588     //*/
1589     
1590     assert(!(1029 in vT)); 
1591     assert(!(865 in vT)); 
1592     assert(vT.insert(865)); 
1593     assert(865 in vT); 
1594     assert(!vT.insert(865)); 
1595     assert(865 in vT); 
1596     assert(!(866 in vT)); 
1597     assert(!vT.remove(866)); 
1598     assert(865 in vT); 
1599     assert(vT.remove(865)); 
1600     assert(!(865 in vT));    
1601     
1602 }
1603 
1604 ///
1605 unittest
1606 {
1607     auto currentSeed = unpredictableSeed();
1608     static if(vdebug){write("UT: rand, succ        "); writeln("seed: ", currentSeed);} 
1609     rndGenInUse.seed(currentSeed); //initialize the random generator
1610 
1611     size_t M = uniform(2U,testedSize, rndGenInUse); //set universe size to some integer. 
1612     auto vT = vebRoot(M); //create the tree
1613     assert(vT.capacity == (M-1).nextPow2); 
1614 
1615     auto filled = M.iota.map!(i => vT.insert(uniform(0, vT.universe, rndGenInUse))).sum; 
1616     assert(filled == vT.length); 
1617 
1618     size_t n; 
1619     auto i = vT.back; 
1620 
1621     // discover the thousend (or little less) values with the predecessor method
1622     while(!i.isNull)
1623     {
1624         ++n;
1625         i = vT.predecessor(i); 
1626         if(n > filled) break; 
1627     }
1628     
1629     size_t o;
1630     i = vT.front; 
1631     while(!i.isNull)
1632     {
1633         ++o; 
1634         i = vT.successor(i.get);
1635         if(o - 1 > filled) break; 
1636     }
1637     
1638     // assert, that all members are discovered, iff when no predecessors are left
1639     assert(n == filled); 
1640     assert(o == filled); 
1641 }
1642 
1643 ///
1644 unittest
1645 {
1646     auto currentSeed = unpredictableSeed(); 
1647     static if(vdebug){write("UT: rand, pred        "); writeln("seed: ", currentSeed);} 
1648     rndGenInUse.seed(currentSeed); //initialize the random generator
1649     size_t M = uniform(2U, testedSize, rndGenInUse); // set universe size to some integer. 
1650     auto vT = vebRoot(M); 
1651     assert(M.iota.map!(i => vT.insert(uniform(0, vT.universe, rndGenInUse))).sum == vT.length); 
1652     auto i = vT.back; 
1653 
1654     // remove all members beginning from the maximum
1655     bool result; 
1656     while(!i.isNull)
1657     {
1658         result = vT.remove(i); 
1659         assert(result); 
1660         auto j = vT.predecessor(i); 
1661         if(!j.isNull)
1662             assert(j != i); 
1663         i = j; 
1664     }
1665     
1666     // assert, that all members are removed, iff when no predecessors are left. 
1667     assert(vT.empty); 
1668 }
1669 
1670 ///
1671 unittest
1672 {
1673     auto currentSeed = unpredictableSeed(); 
1674     static if(vdebug){write("UT: rand, remove      "); writeln("seed: ", currentSeed);} 
1675     rndGenInUse.seed(currentSeed); //initialize the random generator
1676     size_t M = uniform(2U, testedSize, rndGenInUse); // set universe size to some integer. 
1677     auto vT = vebRoot(M); 
1678     assert(M.iota.map!(i => vT.insert(uniform(0, vT.universe, rndGenInUse))).sum == vT.length); 
1679     auto i = vT.front;
1680     
1681     // remove all members beginning from the minimum
1682     bool result; 
1683     while(!i.isNull)
1684     {        
1685         result = vT.remove(i); 
1686         assert(result); 
1687         auto j = vT.successor(i); 
1688         if(!j.isNull)
1689             assert(j != i); 
1690         i = j; 
1691     } 
1692 
1693     // assert, that all members are removed, iff when no successors are left.
1694     assert(vT.empty); 
1695 }
1696 
1697 ///
1698 unittest
1699 {
1700     size_t M = testedSize; 
1701     auto vT = vebRoot(M); 
1702     vT.insert(0x000f); 
1703     assert(vT.predecessor(0x000f).isNull);
1704     vT.insert(0x00f0);
1705     assert(vT.predecessor(0x00f0) == 0x000f); 
1706     vT.insert(0x0f00); 
1707     assert(vT.predecessor(0x0f00) == 0x00f0); 
1708     vT.insert(0xf000); 
1709     assert(vT.predecessor(0xf000) == 0x0f00);
1710     
1711     auto result = vT.remove(0xf000); 
1712     assert(result); 
1713     assert(vT.predecessor(0xf000) == 0x0f00);
1714     result = vT.remove(0x0f00); 
1715     assert(result); 
1716     assert(vT.predecessor(0x0f00) == 0x00f0); 
1717     result = vT.remove(0x00f0); 
1718     assert(result); 
1719     assert(vT.predecessor(0x00f0) == 0x000f); 
1720     result = vT.remove(0x000f); 
1721     assert(result); 
1722     assert(vT.predecessor(0x000f).isNull);
1723 }
1724 
1725 ///
1726 unittest
1727 {
1728     size_t M = testedSize; 
1729     auto vT = vebRoot(M); 
1730     vT.insert(0xf000); 
1731     assert(0xf000 in vT); 
1732     vT.insert(0x0f00); 
1733     assert(0x0f00 in vT); 
1734     vT.insert(0x00f0);
1735     assert(0x00f0 in vT);
1736     vT.insert(0x000f); 
1737     assert(0x000f in vT); 
1738     
1739     auto result = vT.remove(0xf000); 
1740     assert(result); 
1741     assert(!(0xf000 in vT)); 
1742     result = vT.remove(0x0f00); 
1743     assert(result); 
1744     assert(!(0x0f00 in vT)); 
1745     result = vT.remove(0x00f0); 
1746     assert(result); 
1747     assert(!(0x00f0 in vT)); 
1748     result = vT.remove(0x000f); 
1749     assert(result); 
1750     assert(!(0x000f in vT)); 
1751 }
1752 
1753 /// 
1754 unittest
1755 {
1756     //stress test
1757     auto currentSeed = unpredictableSeed(); 
1758     static if(vdebug){write("UT: rand, stress      "); writeln("seed: ", currentSeed);} 
1759     rndGenInUse.seed(currentSeed); //initialize the random generator
1760     // do not use more then "1 << 15", as for the red-black tree the insertion duration is almost 4 (!) minutes. 
1761     // last test says: see below. 
1762     size_t M = uniform(2U, allowedArraySize, rndGenInUse); // set universe size to some integer. 
1763     auto vT = vebRoot(M); 
1764 
1765     size_t[] arr; 
1766     arr.length = 31 * vT.capacity/typeof(vT).sizeof; 
1767     (vT.capacity - 1).iota.randomCover(rndGenInUse).take(arr.length)
1768             .enumerate
1769             .tee!(el => arr[el.index] = el.value)
1770             .each!(el => vT.insert(el.value));
1771     
1772     auto vT2 = vebRoot(M); 
1773     
1774     assert(vT2.capacity == vT.capacity); 
1775     
1776     auto rbt = redBlackTree!size_t(0); 
1777     rbt.clear; 
1778     
1779     void fill1()
1780     {
1781         foreach(size_t i; arr)
1782         {
1783             vT2.insert(i); 
1784         }
1785         
1786         foreach(size_t i; arr)
1787         {
1788             vT2.remove(i); 
1789         }
1790         assert(vT2.empty);
1791         
1792     }
1793     
1794     void fill2()
1795     {
1796         foreach(size_t i; arr)
1797         {
1798             rbt.insert(i); 
1799         }
1800     }
1801     
1802     /*
1803         this part is for speed test
1804     */
1805     /*
1806         compiled with ldc2 vebtree.d -O -main -unittest
1807         results of stress tests: 
1808             size of tree: 16777216
1809             howMuchFilled: 16252928
1810             VEB: 2 secs, 382 ms, 588 μs, and 8 hnsecs
1811     */
1812     /*
1813 
1814     writeln("size of tree: ", vT2.capacity); 
1815     writeln("howMuchFilled: ", howMuchFilled);
1816     //auto r = benchmark!(fill1, fill2)(1); 
1817     auto r = benchmark!(fill1)(1); 
1818     
1819     auto f0Result = to!Duration(r[0]); 
1820     //auto f1Result = to!Duration(r[1]); 
1821     writeln("VEB: ", f0Result); //10ms
1822     //writeln("rbt: ", f1Result); //40sec
1823     //assert(f0Result < f1Result); 
1824     //*/
1825 }
1826 
1827 ///
1828 unittest
1829 {
1830     auto currentSeed = unpredictableSeed(); 
1831     static if(vdebug){write("UT: rand, member      "); writeln("seed: ", currentSeed);} 
1832     rndGenInUse.seed(currentSeed); //initialize the random generator
1833     size_t M = uniform(2U, testedSize, rndGenInUse); // set universe size to some integer.
1834     size_t[] sourceArr; 
1835     sourceArr.length = M; 
1836     // generate a random array as the source for the tree
1837     iota(M).each!(i => sourceArr[i] = uniform(0U, M, rndGenInUse));
1838     // make the array values unique. 
1839     auto uniqueArr = sourceArr.sort.uniq;
1840     // constructor to test
1841     auto vT = vebRoot(sourceArr.length); 
1842     uniqueArr.each!(el => vT.insert(el)); 
1843     // check, that all values are filled 
1844     bool result;
1845     foreach(i; uniqueArr)
1846     {
1847         assert(i in vT); 
1848         result = vT.remove(i); 
1849         assert(result); 
1850     }
1851     // check, that no other elements are present. 
1852     assert(vT.empty); 
1853 }
1854 
1855 ///
1856 unittest
1857 {
1858     auto currentSeed = unpredictableSeed();
1859     static if(vdebug){write("UT: rand, opSlice     "); writeln("seed: ", currentSeed);}  
1860     rndGenInUse.seed(currentSeed); //initialize the random generator
1861     // do not use more then "1 << 16", as for the red-black tree the insertion duration is almost 4 (!) minutes. 
1862     size_t M = uniform(2U, allowedArraySize, rndGenInUse); // set universe size to some integer. 
1863     auto vT = vebRoot(M); 
1864     size_t[] arr; 
1865     arr.length = 16 * vT.capacity/typeof(vT).sizeof; 
1866     (vT.capacity - 1).iota.randomCover(rndGenInUse).take(arr.length)
1867             .enumerate
1868             .tee!(el => arr[el.index] = el.value)
1869             .each!(el => vT.insert(el.value));
1870 
1871     assert(setSymmetricDifference(vT(), arr.sort).empty); 
1872 }
1873 
1874 ///
1875 unittest
1876 { 
1877     static assert(!isInputRange!(VEBroot!())); 
1878     static assert(isIterable!(VEBroot!()));
1879     static assert(isBidirectionalRange!(typeof(VEBroot!()[])));
1880     static assert(is(typeof(vebRoot!(size_t)(4)[2])));
1881     static assert(!is(typeof(vebRoot(4)[2])));
1882 }
1883 
1884 ///
1885 unittest
1886 {
1887     auto vT = vebRoot(14);
1888     auto result = vT.insert(2); 
1889     assert(result); 
1890     result = vT.insert(5); 
1891     assert(result);
1892     result = vT.insert(10); 
1893     assert(result);
1894     assert(vT[] == [0, 2, 5, 10, 14]); 
1895     assert(vT() == [2, 5, 10]); 
1896 }
1897 
1898 ///
1899 unittest
1900 {
1901     /*
1902     //another stress test
1903     auto currentSeed = unpredictableSeed(); 
1904     static if(vdebug){write("UT: stress test 2  "); writeln("seed: ", currentSeed);} 
1905     rndGenInUse.seed(currentSeed); //initialize the random generator
1906     
1907     void fill16(){ auto vT = vebRoot(1 << 16); }
1908     void fill17(){ auto vT = vebRoot(1 << 17); }
1909     void fill18(){ auto vT = vebRoot(1 << 18); }
1910     void fill19(){ auto vT = vebRoot(1 << 19); }    
1911     void fill20(){ auto vT = vebRoot(1 << 20); }
1912     void fill21(){ auto vT = vebRoot(1 << 21); }
1913     void fill22(){ auto vT = vebRoot(1 << 22); }
1914     void fill23(){ auto vT = vebRoot(1 << 23); }
1915     void fill24(){ auto vT = vebRoot(1 << 24); }
1916     void fill25(){ auto vT = vebRoot(1 << 25); }
1917     void fill26(){ auto vT = vebRoot(1 << 26); }
1918     void fill27(){ auto vT = vebRoot(1 << 27); }
1919     void fill28(){ auto vT = vebRoot(1 << 28); }
1920     void fill29(){ auto vT = vebRoot(1 << 29); }
1921     void fill30(){ auto vT = vebRoot(1 << 30); }
1922     
1923     auto r = benchmark!(fill16, fill17, fill18, fill19, fill20, fill21, fill22, fill23, fill24, fill25, fill26, fill27,
1924         fill28, fill29, fill30)(1);
1925     //auto r = benchmark!(fill1)(1); 
1926     auto f16Result = to!Duration(r[0]); 
1927     auto f17Result = to!Duration(r[1]); 
1928     auto f18Result = to!Duration(r[2]); 
1929     auto f19Result = to!Duration(r[3]); 
1930     auto f20Result = to!Duration(r[4]);
1931     auto f21Result = to!Duration(r[5]);
1932     auto f22Result = to!Duration(r[6]);
1933     auto f23Result = to!Duration(r[7]);
1934     auto f24Result = to!Duration(r[8]);
1935     auto f25Result = to!Duration(r[9]);
1936     auto f26Result = to!Duration(r[10]);
1937     auto f27Result = to!Duration(r[11]);
1938     auto f28Result = to!Duration(r[12]);
1939     auto f29Result = to!Duration(r[13]);
1940     auto f30Result = to!Duration(r[14]);
1941     
1942     writeln("VEB with M of ", 1 << 16, ": ", f16Result); 
1943     writeln("VEB with M of ", 1 << 17, ": ", f17Result);
1944     writeln("VEB with M of ", 1 << 18, ": ", f18Result);
1945     writeln("VEB with M of ", 1 << 19, ": ", f19Result);
1946     writeln("VEB with M of ", 1 << 20, ": ", f20Result);
1947     writeln("VEB with M of ", 1 << 21, ": ", f21Result);
1948     writeln("VEB with M of ", 1 << 22, ": ", f22Result);
1949     writeln("VEB with M of ", 1 << 23, ": ", f23Result);
1950     writeln("VEB with M of ", 1 << 24, ": ", f24Result);
1951     writeln("VEB with M of ", 1 << 25, ": ", f25Result); 
1952     writeln("VEB with M of ", 1 << 26, ": ", f26Result); 
1953     writeln("VEB with M of ", 1 << 27, ": ", f27Result); 
1954     writeln("VEB with M of ", 1 << 28, ": ", f28Result); 
1955     writeln("VEB with M of ", 1 << 29, ": ", f29Result); 
1956     writeln("VEB with M of ", 1 << 30, ": ", f30Result); 
1957     //*/
1958     
1959 }
1960 
1961 ///
1962 unittest
1963 {
1964     //stress test
1965     auto currentSeed = unpredictableSeed(); 
1966     static if(vdebug){write("UT: rand, ranges      "); writeln("seed: ", currentSeed);} 
1967     rndGenInUse.seed(currentSeed); //initialize the random generator
1968     // do not use more then "1 << 15", as for the red-black tree the insertion duration is almost 4 (!) minutes. 
1969     // last test says: see below. 
1970     size_t M = uniform(2U, testedSize, rndGenInUse); // set universe size to some integer. 
1971     auto vT = vebRoot(M); 
1972     /*testing the range methods*/
1973     assert(vT.empty); 
1974     
1975     size_t[] sourceArr; 
1976     sourceArr.length = uniform(2U, M, rndGenInUse); 
1977     iota(sourceArr.length).each!(i => sourceArr[i] = uniform(0U, sourceArr.length, rndGenInUse));
1978     
1979     auto uniqueArr = sourceArr.sort.uniq; 
1980 
1981     // constructor to test
1982 
1983     auto vTnew = vebRoot(sourceArr.length); 
1984     uniqueArr.each!(el => vTnew.insert(el)); 
1985 
1986     assert(!vTnew.empty); 
1987     assert(vTnew.length == uniqueArr.walkLength); 
1988     auto vT2 = vTnew; 
1989     static assert(isIterable!(typeof(vTnew))); 
1990     auto slice = vTnew(); 
1991     assert(slice.front == uniqueArr.front); 
1992     assert(vTnew() == uniqueArr); 
1993     assert(!vTnew.empty);
1994     assert(!vT2.empty);
1995 
1996     size_t N = 100; 
1997     auto vT3 = vebRoot(N); 
1998     assert(vT3.empty); 
1999     auto unique3 = N.iota.map!(i => uniform(0U, N, rndGenInUse)).array.sort.uniq.array;
2000     unique3.each!(u => vT3.insert(u));
2001     unique3.each!(u => assert(u in vT3));
2002     assert(vT3.length == unique3.length); 
2003     auto sl3 = vT3[]; 
2004     
2005     if(unique3.front == 0 && unique3.back == vT3.universe)
2006     {
2007         assert(sl3.length == unique3.length);
2008     }
2009     else if(unique3.front == 0 || unique3.back == vT3.universe)
2010     {
2011         assert(sl3.length == unique3.length + 1);
2012     }
2013     else
2014     {
2015         assert(sl3.length == unique3.length + 2);
2016     }
2017     assert(sl3.length); 
2018     assert(!sl3.empty); 
2019 
2020     unique3.each!(u => vT3.remove(u));
2021     assert(vT3.empty); 
2022     
2023     //* Works. Duration in debug mode: about 35 seconds. 
2024     //auto vTT = vebRoot((size_t(1) << 27) - 1); 
2025     //assert(vTT.insert(42)); 
2026     //assert(42 in vTT);
2027     //*/
2028 }
2029 
2030 private struct VEBtree(Flag!"inclusive" inclusive)
2031 {
2032     static assert(isBidirectionalRange!(typeof(this)));
2033     
2034     VEBroot root; 
2035     
2036     auto opBinaryRight(string op)(size_t key) @nogc nothrow if(op == "in") 
2037     {
2038         return key in root; 
2039     }
2040 
2041     static if(inclusive)
2042     {
2043         size_t frontKey; 
2044         size_t backKey; 
2045     }
2046     else
2047     {
2048         Response frontKey; 
2049         Response backKey; 
2050     }
2051 
2052     size_t length; 
2053     
2054     private this(VEBroot val)
2055     {
2056         root = val;
2057         length = root.length; 
2058 
2059         static if(inclusive)
2060         {
2061             if(root.empty)
2062             {
2063                 backKey = root.universe;
2064                 assert(!length); 
2065                 length += 2; 
2066             }
2067             else
2068             {
2069                 if(root.back.get <= root.universe)
2070                 {
2071                     backKey = root.universe;
2072                     if(root.back.get < root.universe)
2073                     {
2074                         length += 1; 
2075                     }
2076                 }
2077                 else
2078                 {
2079                     assert(root.back.get < root.capacity); 
2080                     backKey = root.capacity; 
2081                     length += 1; 
2082                 }
2083 
2084                 if(root.front.get) // i. e. front != 0
2085                 {
2086                     length += 1; 
2087                 }
2088             }
2089         }
2090         else
2091         {
2092             frontKey = root.front; 
2093             backKey = root.back; 
2094         }
2095     }
2096 
2097     auto front() @nogc
2098     {
2099         return frontKey; 
2100     }
2101 
2102     void popFront() @nogc
2103     in
2104     {
2105         assert(!empty); 
2106     }
2107     do
2108     {
2109         auto front = root.successor(frontKey.get); 
2110         static if(inclusive)
2111         {
2112             if(front.isNull)
2113             {
2114                 if(frontKey <= root.universe)
2115                 {
2116                     frontKey = root.universe; 
2117                 }
2118                 else if(frontKey <= root.capacity)
2119                 {
2120                     frontKey = root.capacity; 
2121                 }
2122                 else
2123                 {
2124                     assert(0, "key exceeds tree capacity");
2125                 }
2126             }
2127             else
2128             {
2129                 frontKey = front.get; 
2130             }
2131         }
2132         else
2133         {
2134             frontKey = front; 
2135         }
2136 
2137         --length; 
2138     }
2139 
2140     auto back() @nogc
2141     {
2142         return backKey; 
2143     }
2144 
2145     void popBack()
2146     in
2147     {
2148         assert(length); 
2149     }
2150     do
2151     {
2152         auto back = root.predecessor(backKey.get); 
2153         static if(inclusive)
2154         {      
2155             if(back.isNull)
2156             {
2157                 backKey = 0; 
2158             }
2159             else
2160             {
2161                 backKey = back.get; 
2162             }
2163         }
2164         else
2165         {
2166             backKey = back; 
2167         }
2168         --length; 
2169     }
2170 
2171     auto predecessor(size_t key) @nogc
2172     {
2173         auto pred = root.predecessor(key);
2174         static if(inclusive)
2175         {
2176             if(pred.isNull)
2177             {
2178                 return 0; 
2179             }
2180             else
2181             {
2182                 return pred.get; 
2183             }
2184         }
2185         else
2186         {
2187             return pred; 
2188         }
2189     }
2190 
2191     auto successor(size_t key) @nogc
2192     {
2193         auto succ = root.successor(key);
2194         static if(inclusive)
2195         {
2196             if(succ.isNull)
2197             {
2198                 if(key <= root.universe)
2199                 {
2200                     return root.universe; 
2201                 }
2202                 else if(key <= root.capacity)
2203                 {
2204                     return root.capacity; 
2205                 }
2206                 else
2207                 {
2208                     assert(0, "key exceeds tree capacity");
2209                 }
2210             }
2211             else
2212             {
2213                 return succ.get; 
2214             }
2215         }
2216         else
2217         {
2218             return succ; 
2219         }
2220         
2221     }
2222 
2223     int opApplyImpl(O)(O operations)
2224     {
2225         int result; 
2226         
2227         //for(auto leading = front; !leading.isNull; leading = successor(leading.get)) 
2228         for(auto leading = front; !empty; popFront) 
2229         {
2230             result = operations(leading.get); 
2231 
2232             if(result)
2233             {
2234                 break; 
2235             }
2236         }
2237 
2238         return result;
2239     }
2240     
2241     int opApply(scope int delegate(size_t) operations)
2242     {
2243         return opApplyImpl(operations); 
2244     }
2245 
2246     int opApply(scope int delegate(size_t) @nogc operations) @nogc
2247     {
2248         return opApplyImpl(operations); 
2249     }
2250 
2251     bool empty() @nogc
2252     {
2253         return !length; 
2254     }
2255 
2256     auto save()
2257     {
2258         return this; 
2259     }
2260     
2261     typeof(this) dup()
2262     {
2263         auto copy = this; 
2264         copy.root = root.dup; 
2265         return copy; 
2266     }
2267 
2268     size_t toHash() const
2269     {
2270         assert(0);
2271     }
2272 
2273     /**
2274     for comparison with an iterable, the iterable will be iterated, as the current object. If the iterable object is an 
2275     input range, it will be destroyed. 
2276     */
2277     bool opEquals(T)(const auto ref T input) if(isIterable!T)
2278     {
2279         static if(is(T == typeof(this)))
2280         {
2281             return root == input.root; 
2282         }
2283 
2284         static if(hasLength!T)
2285         {
2286             if(length != input.length)
2287             {
2288                 return false; 
2289             }
2290         }
2291 
2292         auto copy = this.save; 
2293 
2294         foreach(el; input)
2295         {
2296             if(el != copy.front.get)
2297             {
2298                 return false; 
2299             }
2300             copy.popFront; 
2301         }
2302         
2303         return true; 
2304     }
2305 }
2306 
2307 private : 
2308 size_t get(size_t input) @nogc
2309 {
2310     return input; 
2311 }
2312 
2313 bool isNull(size_t) @nogc
2314 {
2315     return false; 
2316 }