1 // Written in the D programming language.
2 /*
3 NYSL Version 0.9982
4 
5 A. This software is "Everyone'sWare". It means:
6   Anybody who has this software can use it as if he/she is
7   the author.
8 
9   A-1. Freeware. No fee is required.
10   A-2. You can freely redistribute this software.
11   A-3. You can freely modify this software. And the source
12       may be used in any software with no limitation.
13   A-4. When you release a modified version to public, you
14       must publish it with your name.
15 
16 B. The author is not responsible for any kind of damages or loss
17   while using or misusing this software, which is distributed
18   "AS IS". No warranty of any kind is expressed or implied.
19   You use AT YOUR OWN RISK.
20 
21 C. Copyrighted to Kazuki KOMATSU
22 
23 D. Above three clauses are applied both to source and binary
24   form of this software.
25 */
26 
27 /**
28 このモジュールは、標準ライブラリのstd.rangeを強化します。
29 */
30 
31 module carbon.range;
32 
33 
34 import std.algorithm,
35        std.range,
36        std.string,
37        std.traits;
38 
39 debug import std.stdio;
40 
41 import carbon.templates;
42 
43 
44 /**
45 true if isInputRange!R is true and isInputRange!R is false.
46 */
47 enum isSimpleRange(R, alias I = isInputRange) = 
48     I!(R) && !I!(ElementType!R);
49 
50 
51 /**
52 true if both isInputRange!R and isInputRange!R are true.
53 */
54 enum isRangeOfRanges(R, alias I = isInputRange) = 
55     I!(R) && I!(ElementType!R);
56 
57 
58 
59 /**
60 あるレンジのN個の連続する要素のリストを返します。
61 
62 Example:
63 ----
64 auto r1 = [0, 1, 2, 3, 4, 5];
65 auto s = segment!2(r1);
66 assert(equal(s, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4), tuple(4, 5)][]));
67 assert(s.length == 5);         // .length
68 // back/popBack:
69 assert(equal(retro(s), retro([tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4), tuple(4, 5)][])));
70 assert(s[3] == tuple(3, 4));    // opIndex
71 s[3] = tuple(0, 0);             // opIndexAssign not ref opIndex
72 assert(s[2] == tuple(2, 0));    // it affects its neighbors.
73 assert(s[4] == tuple(0, 5));
74 assert(r1 == [0, 1, 2, 0, 0, 5][]); // affects r1 back (no .dup internally)
75 
76 
77 auto st = ["a","b","c","d","e","f"];
78 auto s2 = segment!3(st);
79 assert(s2.front == tuple("a","b","c"));
80 
81 
82 auto r1 = [0,1,2,3,4,5]; // regenerates r1
83 auto s3 = segment!1(r1);
84 assert(equal(s3, [tuple(0), tuple(1), tuple(2), tuple(3), tuple(4), tuple(5)][]));
85 auto r2 = map!"a*a"(r1);
86 auto s4 = segment!2(r2); // On a forward range
87 assert(equal(s4, [tuple(0,1), tuple(1,4), tuple(4,9), tuple(9,16), tuple(16,25)][]));
88 
89 
90 int[] e;
91 auto s5 = segment!2(e);
92 assert(s5.empty);
93 ----
94 
95 Authors: Komatsu Kazuki
96 */
97 template SegmentType(size_t N, R)
98 if(isInputRange!(Unqual!R) && N > 0)
99 {
100     alias typeof(segment!N(R.init)) SegmentType;
101 }
102 
103 
104 ///ditto
105 template segment(size_t N : 1, Range)
106 if(isInputRange!(Unqual!Range))
107 {
108     Segment segment(Range range)
109     {
110         return Segment(range);
111     }
112 
113     alias Unqual!Range R;
114     alias ElementType!Range E;
115 
116     struct Segment{
117     private:
118         R _range;
119 
120     public:
121         this(R range)
122         {
123             _range = range;
124         }
125 
126 
127       static if(isInfinite!R)
128         enum bool e = false;
129       else
130         @property bool empty()
131         {
132             return _range.empty;
133         }
134         
135         
136         void popFront()
137         {
138             _range.popFront();
139         }
140       static if(isBidirectionalRange!R)
141         void popBack()
142         {
143             _range.popBack();
144         }
145         
146         
147       static if(isForwardRange!R)
148         @property typeof(this) save()
149         {
150             typeof(this) dst = this;
151             dst._range = dst._range.save;
152             return dst;
153         }
154       
155       static if(hasLength!R)
156       {
157         @property size_t length()
158         {
159             return _range.length;
160         }
161 
162         alias length opDollar;
163       }
164       
165       static if(hasSlicing!R)
166       {
167         Segment opSlice()
168         {
169           static if(isForwardRange!R)
170             return save;
171           else
172             return typeof(this)(_range);
173         }
174 
175 
176         auto opSlice(size_t i, size_t j)
177         {
178             return segment!1(_range[i .. j]);
179         }
180       }
181       
182       
183         @property Tuple!E front()
184         {
185             return tuple(_range.front);
186         }
187         
188       static if(isBidirectionalRange!R)
189         @property Tuple!E back()
190         {
191             return tuple(_range.back);
192         }
193       
194       static if(isRandomAccessRange!R)
195         Tuple!E opIndex(size_t i)
196         {
197             return tuple(_range[i]);
198         }
199 
200       static if(hasAssignableElements!R || hasSwappableElements!R || hasLvalueElements!R)
201       {
202         @property void front(Tuple!E e)
203         {
204             _range.front = e[0];
205         }
206 
207         
208         static if(isBidirectionalRange!R)
209         {
210           @property void back(Tuple!E e)
211           {
212               _range.back = e[0];
213           }
214         }
215         
216         static if(isRandomAccessRange!R)
217         {
218           void opIndexAssign(Tuple!E e, size_t i)
219           {
220               _range[i] = e[0];
221           }
222         }
223       }
224     
225     }
226 }
227 
228 
229 unittest
230 {
231     //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__);
232     debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();}
233 
234     auto a = [0, 1, 2, 3, 4];
235     auto sg = segment!1(a);
236 
237     assert(equal(sg, [tuple(0), tuple(1), tuple(2), tuple(3), tuple(4)]));
238     assert(equal(sg.retro, [tuple(0), tuple(1), tuple(2), tuple(3), tuple(4)].retro));
239 
240     sg.front = tuple(3);
241     assert(equal(sg, [tuple(3), tuple(1), tuple(2), tuple(3), tuple(4)]));
242 
243     sg[3] = tuple(2);
244     assert(equal(sg, [tuple(3), tuple(1), tuple(2), tuple(2), tuple(4)]));
245 
246     assert(sg.length == 5);
247 
248     sg.back = tuple(8);
249     assert(equal(sg, [tuple(3), tuple(1), tuple(2), tuple(2), tuple(8)]));
250     assert(sg[$-1] == tuple(8));
251 
252     assert(equal(sg[2..4], [tuple(2), tuple(2)]));
253 
254     auto sv = sg.save;
255     sv.popFront();
256     assert(equal(sg, [tuple(3), tuple(1), tuple(2), tuple(2), tuple(8)]));
257     assert(equal(sv, [tuple(1), tuple(2), tuple(2), tuple(8)]));
258 
259     auto sl = sv[];
260     sv.popFront();
261     assert(equal(sl, [tuple(1), tuple(2), tuple(2), tuple(8)]));
262     assert(equal(sv, [tuple(2), tuple(2), tuple(8)]));
263 }
264 
265 
266 ///ditto
267 template segment(size_t N, Range)
268 if (isInputRange!(Unqual!Range) 
269 && (isForwardRange!(Unqual!Range) ? (!isBidirectionalRange!(Unqual!Range)
270                                       && !isRandomAccessRange!(Unqual!Range)) : true))
271 {
272     Segment segment(Range range)
273     {
274         return Segment(range);
275     }
276 
277     alias Unqual!Range R;
278     alias ElementType!R E;
279 
280     enum assE = isForwardRange!R && (hasAssignableElements!R || hasLvalueElements!R || hasSwappableElements!R);
281 
282     struct Segment{
283     private:
284         R _range;
285         E[] _front;
286 
287       static if(assE)
288         R _assignRange;
289 
290     public:
291         this(R range)
292         {
293             _range = range;
294 
295           static if(assE)
296             _assignRange = _range.save;
297 
298             for(int i = 0; i < N && !_range.empty; ++i, _range.popFront())
299                 _front ~= _range.front;
300         }
301 
302 
303         void popFront()
304         {
305             if(_range.empty)
306                 _front = _front[1..$];
307             else{
308                 _front = _front[1..$];
309                 _front ~= _range.front;
310                 _range.popFront();
311               static if(assE)
312                 _assignRange.popFront();
313             }
314         }
315 
316         @property
317         Tuple!(TypeNuple!(E, N)) front()
318         {
319             return (cast(typeof(return)[])(cast(ubyte[])_front))[0];
320         }
321 
322 
323       static if(assE)
324         @property void front(Tuple!(TypeNuple!(E, N)) e)
325         {
326             R _tmpRange = _assignRange.save;
327 
328             _front = [e.field];
329 
330             for(int i = 0; i < N; ++i, _tmpRange.popFront)
331                 _tmpRange.front = _front[i];
332         }
333 
334 
335       static if(isForwardRange!R) {
336         @property Segment save()
337         {
338             Segment dst = this;
339             dst._range = dst._range.save;
340 
341           static if(assE)
342             dst._assignRange = dst._assignRange.save;
343 
344             return dst;
345         }
346       }
347 
348       static if(isInfinite!R)
349         enum bool empty = false;        
350       else
351         @property
352         bool empty()
353         {
354             return _front.length != N;
355         }
356         
357 
358       static if(hasLength!R){
359         @property
360         size_t length()
361         {
362           return _range.length + !this.empty;
363         }
364 
365         alias length opDollar;
366       }
367 
368       static if(hasSlicing!R)
369       {
370           Segment opSlice()
371           {
372             static if(isInputRange!R)
373               return this;
374             else
375               return save;
376           }
377 
378           auto opSlice(size_t i, size_t j)
379           {
380               return segment!N(_assignRange[i..j + (N-1)]);
381           }
382       }
383     }
384 }
385 
386 
387 unittest
388 {
389     //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__);
390     debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();}
391 
392     struct TRange
393     {
394         int _front, _end;
395         @property int front(){return _front;}
396         void popFront(){_front += 1;}
397         @property bool empty(){return _front == _end;}
398         @property TRange save(){return this;}
399         @property size_t length(){return _end - _front;}
400         alias length opDollar;
401     }
402 
403     auto tr = TRange(0, 5);
404     auto sg2 = segment!2(tr);
405     assert(equal(sg2, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)]));
406 
407     auto sg2sv = sg2.save;
408     sg2sv.popFront();
409     assert(equal(sg2, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)]));
410     assert(equal(sg2sv, [tuple(1, 2), tuple(2, 3), tuple(3, 4)]));
411 
412     assert(sg2.length == 4);
413 
414     auto sg3 = segment!3(tr);
415     assert(equal(sg3, [tuple(0, 1, 2), tuple(1, 2, 3), tuple(2, 3, 4)]));
416     assert(sg3.length == 3);
417 
418     auto sg4 = segment!4(tr);
419     assert(equal(sg4, [tuple(0, 1, 2, 3), tuple(1, 2, 3, 4)]));
420     assert(sg4.length == 2);
421 
422     auto sg5 = segment!5(tr);
423     assert(equal(sg5, [tuple(0, 1, 2, 3, 4)]));
424     assert(sg5.length == 1);
425 
426     auto sg6 = segment!6(tr);
427     assert(sg6.empty);
428     assert(sg6.length == 0);
429 
430     auto tremp = TRange(0, 0);
431     assert(tremp.empty);
432     assert(segment!2(tremp).empty);
433 }
434 unittest
435 {
436     //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__);
437     debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();}
438 
439     struct TRange
440     {
441         int _front, _end;
442         @property int front(){return _front;}
443         void popFront(){_front += 1;}
444         @property bool empty(){return _front == _end;}
445         @property TRange save(){return this;}
446         @property size_t length(){return _end - _front;}
447         alias length opDollar;
448     }
449 
450     auto tr = TRange(0, 5);
451     auto sg2 = segment!2(tr);
452     assert(equal(sg2, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)]));
453 
454     assert(sg2.length == 4);
455 
456     auto sg3 = segment!3(tr);
457     assert(equal(sg3, [tuple(0, 1, 2), tuple(1, 2, 3), tuple(2, 3, 4)]));
458     assert(sg3.length == 3);
459 
460     auto sg4 = segment!4(tr);
461     assert(equal(sg4, [tuple(0, 1, 2, 3), tuple(1, 2, 3, 4)]));
462     assert(sg4.length == 2);
463 
464     auto sg5 = segment!5(tr);
465     assert(equal(sg5, [tuple(0, 1, 2, 3, 4)]));
466     assert(sg5.length == 1);
467 
468     auto sg6 = segment!6(tr);
469     assert(sg6.empty);
470     assert(sg6.length == 0);
471 
472     auto tremp = TRange(0, 0);
473     assert(tremp.empty);
474     assert(segment!2(tremp).empty);
475 }
476 unittest
477 {
478     //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__);
479     debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();}
480 
481     struct TRange
482     {
483         int[] a;
484         @property ref int front(){return a.front;}
485         @property bool empty(){return a.empty;}
486         void popFront(){a.popFront;}
487         @property TRange save(){return TRange(a.save);}
488         @property size_t length(){return a.length;}
489         alias length opDollar;
490         TRange opSlice(size_t i, size_t j){return TRange(a[i..j]);}
491     }
492 
493 
494     int[] a = [0, 1, 2, 3, 4];
495     auto r = TRange(a);
496     auto sg = segment!2(r);
497     assert(equal(sg, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)]));
498     assert(equal(sg[2..4], [tuple(2, 3), tuple(3, 4)]));
499 
500     sg.front = tuple(3, 2);
501     assert(equal(sg, [tuple(3, 2), tuple(2, 2), tuple(2, 3), tuple(3, 4)]));
502 
503     assert(sg.length == 4);
504     sg.popFront();
505     assert(sg.length == 3);
506     sg.popFront();
507     assert(sg.length == 2);
508     sg.popFront();
509     assert(sg.length == 1);
510     sg.popFront();
511     assert(sg.length == 0);
512     assert(sg.empty);
513 
514     a = [0, 1, 2, 3, 4];
515     r = TRange(a);
516     auto sg3 = segment!3(r);
517     assert(equal(sg3, [tuple(0, 1, 2), tuple(1, 2, 3), tuple(2, 3, 4)]));
518     sg3.front = tuple(2, 3, 1);
519     assert(equal(sg3, [tuple(2, 3, 1), tuple(3, 1, 3), tuple(1, 3, 4)]));
520 
521     auto sl3 = sg3[];
522     sl3.popFront();
523     assert(equal(sg3, [tuple(2, 3, 1), tuple(3, 1, 3), tuple(1, 3, 4)]));
524     assert(equal(sl3, [tuple(3, 1, 3), tuple(1, 3, 4)]));
525 
526     auto sv3 = sg3.save;
527     sv3.popFront();
528     assert(equal(sg3, [tuple(2, 3, 1), tuple(3, 1, 3), tuple(1, 3, 4)]));
529     assert(equal(sv3, [tuple(3, 1, 3), tuple(1, 3, 4)]));
530 
531     assert(sg3.length == 3);
532     sg3.popFront();
533     assert(sg3.length == 2);
534     sg3.popFront();
535     assert(sg3.length == 1);
536     sg3.popFront();
537     assert(sg3.length == 0);
538     assert(sg3.empty);
539 }
540 
541 
542 ///ditto
543 template segment(size_t N, Range)
544 if(isRandomAccessRange!(Unqual!Range)
545 && isBidirectionalRange!(Unqual!Range)
546 && hasLength!(Unqual!Range))
547 {
548     Segment segment(Range range)
549     {
550         return Segment(range);
551     }
552 
553 
554     alias Unqual!Range R;
555     alias ElementType!R E;
556     
557     struct Segment{
558       private:
559         R _range;
560         size_t _fidx;
561         size_t _bidx;
562         E[] _front;
563         E[] _back;
564 
565         void reConstruct()
566         {
567             if(!empty){
568                 _front.length = 0;
569                 _back.length = 0;
570                 foreach(i; 0..N)
571                 {
572                     _front ~= _range[_fidx + i];
573                     _back ~= _range[_bidx + i];
574                 }
575             }
576         }
577 
578 
579       public:
580         this(R range)
581         {
582             _range = range;
583             _fidx = 0;
584             _bidx = _range.length - N;
585 
586             reConstruct();
587         }
588 
589         
590         @property bool empty() const
591         {
592             return (cast(int)_bidx - cast(int)_fidx) < 0;
593         }
594 
595         
596         void popFront()
597         {
598             ++_fidx;
599             if(!empty){
600                 _front = _front[1..$];
601                 _front ~= _range[_fidx + (N - 1)];
602             }
603         }
604 
605 
606         void popBack()
607         {
608             --_bidx;
609             if(!empty){
610                 _back = _back[0..$-1];
611                 _back = [_range[_bidx]] ~ _back;
612             }
613         }
614         
615         
616         @property Segment save()
617         {
618             Segment dst = cast(Segment)this;
619             dst._range = dst._range.save;
620             dst._front = dst._front.dup;
621             dst._back = dst._back.dup;
622             return dst;
623         }
624       
625 
626         @property size_t length() const
627         {
628             return _bidx - _fidx + 1;
629         }
630 
631 
632         alias length opDollar;
633       
634 
635         auto opSlice()
636         {
637             return save;
638         }
639 
640 
641         Segment opSlice(size_t i, size_t j)
642         {
643             Segment dst = this.save;
644             dst._fidx += i;
645             dst._bidx -= this.length - j;
646 
647             dst.reConstruct();
648             return dst;
649         }
650       
651 
652         @property Tuple!(TypeNuple!(E, N)) front()
653         {
654             return (cast(typeof(return)[])(cast(ubyte[])_front))[0];
655         }
656 
657 
658         @property Tuple!(TypeNuple!(E, N)) back()
659         {
660             return (cast(typeof(return)[])(cast(ubyte[])_back))[0];
661         }
662 
663 
664         Tuple!(TypeNuple!(E, N)) opIndex(size_t i)
665         {
666             if(i == 0)
667                 return this.front;
668             else if(i == this.length - 1)
669                 return this.back;
670             else
671             {
672                 E[] dst;
673                 foreach(j; 0 .. N)
674                     dst ~= _range[_fidx + i + j];
675                 return (cast(typeof(return)[])(cast(ubyte[])dst))[0];
676             }
677         }
678 
679 
680       static if(hasSwappableElements!R || hasLvalueElements!R || hasAssignableElements!R)
681       {
682         @property void front(Tuple!(TypeNuple!(E, N)) e)
683         {
684             E[] eSlice = [e.field];
685 
686             foreach(i; 0 .. N)
687                 _range[i + _fidx] = eSlice[i];
688             
689             reConstruct();
690         }
691 
692 
693         @property void back(Tuple!(TypeNuple!(E, N)) e)
694         {
695             E[] eSlice = [e.field];
696 
697             foreach(i; 0..N)
698                 _range[i + _bidx] = eSlice[i];
699 
700             reConstruct();
701         }
702 
703 
704         void opIndexAssign(Tuple!(TypeNuple!(E, N)) e, size_t i)
705         {
706             E[] eSlice = [e.field];
707 
708             foreach(j; 0..N)
709                 _range[_fidx + i + j] = eSlice[j];
710 
711             reConstruct();
712         }
713       }
714     }
715 }
716 
717 
718 unittest
719 {
720     //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__);
721     debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();}
722 
723     auto r1 = [0,1,2,3,4,5];
724     auto s = segment!2(r1);
725     assert(equal(s, [tuple(0,1), tuple(1,2), tuple(2,3), tuple(3,4), tuple(4,5)][]));
726     assert(s.length == 5);         // .length
727     // back/popBack:
728     assert(equal(retro(s), retro([tuple(0,1), tuple(1,2), tuple(2,3), tuple(3,4), tuple(4,5)][])));
729     assert(s[3] == tuple(3,4));    // opIndex
730     s[3] = tuple(0,0);             // opIndexAssign
731     assert(s[2] == tuple(2,0));    // it affects its neighbors.
732     assert(s[4] == tuple(0,5));
733     assert(r1 == [0,1,2,0,0,5][]); // affects r1 back (no .dup internally)
734 
735     s = segment!2(r1);
736     s.front = tuple(2, 0);
737     assert(s[0] == tuple(2, 0));
738 
739     s.back = tuple(100, 500);
740     assert(s[s.length - 1] == tuple(100, 500));
741 
742     auto sl = s[];
743     assert(equal(sl, s));
744     sl.popFront();
745     sl.popBack();
746     assert(equal(sl, s[1 .. s.length - 1]));
747 }
748 unittest
749 {
750     //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__);
751     debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();}
752 
753     auto st = ["a","b","c","d","e","f"];
754     auto s2 = segment!3(st);
755     assert(s2.front == tuple("a","b","c"));
756 }
757 unittest
758 {
759     //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__);
760     debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();}
761 
762     auto r1 = [0,1,2,3,4,5]; // regenerates r1
763     auto s3 = segment!1(r1);
764     assert(equal(s3, [tuple(0), tuple(1), tuple(2), tuple(3), tuple(4), tuple(5)][]));
765     assert(equal(s3.retro, [tuple(0), tuple(1), tuple(2), tuple(3), tuple(4), tuple(5)].retro));
766     auto r2 = map!"a*a"(r1);
767     auto s4 = segment!2(r2); // On a forward range
768     assert(equal(s4, [tuple(0,1), tuple(1,4), tuple(4,9), tuple(9,16), tuple(16,25)][]));
769 }
770 unittest
771 {
772     //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__);
773     debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();}
774 
775     int[] e;
776     auto s5 = segment!2(e);
777     assert(s5.empty);
778 }
779 unittest
780 {
781     //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__);
782     debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();}
783 
784     auto ri = iota(0, 5);
785     auto sg = segment!2(ri);
786     assert(equal(sg, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)]));
787     assert(equal(sg.retro, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)].retro));
788     assert(sg[0] == tuple(0, 1));
789     assert(sg[1] == tuple(1, 2));
790     assert(sg[2] == tuple(2, 3));
791     assert(sg[3] == tuple(3, 4));
792     assert(sg.length == 4);
793 }
794 
795 ///ditto
796 template segment(size_t N, Range)
797 if(isRandomAccessRange!(Unqual!Range)
798 && !isBidirectionalRange!(Unqual!Range)
799 && isInfinite!(Unqual!Range))
800 {
801     Segment segment(Range range)
802     {
803         return Segment(range);
804     }
805 
806 
807     alias Unqual!Range R;
808     alias ElementType!R E;
809     
810     struct Segment{
811       private:
812         R _range;
813         size_t _fidx;
814         E[] _front;
815 
816         void reConstruct()
817         {
818             if(!empty){
819                 _front.length = 0;
820                 foreach(i; 0..N)
821                     _front ~= _range[_fidx + i];
822             }
823         }
824 
825       public:
826         this(R range)
827         {
828             _range = range;
829             _fidx = 0;
830 
831             reConstruct();
832         }
833 
834         
835         enum bool empty = false;
836 
837         
838         void popFront()
839         {
840             ++_fidx;
841             if(!empty){
842                 _front = _front[1..$];
843                 _front ~= _range[_fidx + (N - 1)];
844             }
845         }
846         
847         
848         @property Segment save()
849         {
850             Segment dst = this;
851             dst._range = dst._range.save;
852             return dst;
853         }
854       
855 
856       @property Tuple!(TypeNuple!(E, N)) front()
857       {
858           return (cast(typeof(return)[])(cast(ubyte[])_front))[0];
859       }
860 
861 
862       Tuple!(TypeNuple!(E, N)) opIndex(size_t i)
863       {
864           if(i == 0)
865               return this.front;
866           else
867           {
868               E[] dst;
869               foreach(j; 0 .. N)
870                   dst ~= _range[_fidx + i + j];
871               return (cast(typeof(return)[])(cast(ubyte[])dst))[0];
872           }
873       }
874 
875 
876       static if(hasSwappableElements!R || hasLvalueElements!R || hasAssignableElements!R)
877       {
878         @property void front(Tuple!(TypeNuple!(E, N)) e)
879         {
880             E[] eSlice = [e.field];
881 
882             foreach(i; 0 .. N)
883                 _range[i + _fidx] = eSlice[i];
884             
885             reConstruct();
886         }
887 
888 
889         void opIndexAssign(Tuple!(TypeNuple!(E, N)) e, size_t i)
890         {
891             E[] eSlice = [e.field];
892 
893             foreach(j; 0..N)
894                 _range[_fidx + i + j] = eSlice[j];
895 
896             reConstruct();
897         }
898       }
899     }
900 }
901 
902 
903 unittest
904 {
905     //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__);
906     debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();}
907 
908     struct TRange
909     {
910         int[] a, s;
911 
912         this(int[] r){
913             a = r.save;
914             s = r.save;
915         }
916 
917         @property ref int front(){return a.front;}
918         enum bool empty = false;
919         void popFront(){a.popFront; if(a.empty)a = s;}
920         @property typeof(this) save(){return this;}
921         ref int opIndex(size_t i){return a[i%s.length];}
922     }
923 
924     
925     auto r = segment!2(TRange([0, 1, 2, 3, 4]));
926     assert(equal(r.take(4), [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)]));
927 
928     auto sv = r.save;
929     sv.popFront();
930     assert(equal(r.take(4), [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)]));
931     assert(equal(sv.take(3), [tuple(1, 2), tuple(2, 3), tuple(3, 4)]));
932 
933     assert(r[2] == tuple(2, 3));
934     assert(r[0] == tuple(0, 1));
935 
936     r.front = tuple(100, 50);
937     assert(equal(r.take(4), [tuple(100, 50), tuple(50, 2), tuple(2, 3), tuple(3, 4)]));
938 
939     r[1] = tuple(10, 20);
940     assert(equal(r.take(4), [tuple(100, 10), tuple(10, 20), tuple(20, 3), tuple(3, 4)]));
941 }
942 
943 
944 ///ditto
945 template segment(size_t N, Range)
946 if(isBidirectionalRange!(Unqual!Range)
947 && (isRandomAccessRange!(Unqual!Range) ? (!hasLength!(Unqual!Range) && isInfinite!(Unqual!Range)) : true))
948 {
949     Segment segment(Range range)
950     {
951         return Segment(range);
952     }
953 
954 
955     alias Unqual!Range R;
956     alias ElementType!R E;
957     enum assE = hasAssignableElements!R && hasLvalueElements!R && hasSwappableElements!R;
958 
959 
960     struct Segment{
961       private:
962         R _fRange;
963         R _bRange;
964         E[] _front;
965         E[] _back;
966 
967       static if(assE || isRandomAccessRange!R)
968         R _assignRange;
969 
970       static if(assE || isRandomAccessRange!R)
971         void reConstruct(){
972             _front.length = 0;
973             _back.length = 0;
974 
975             _fRange = _assignRange.save;
976             _bRange = _assignRange.save;
977 
978             for(int i = 0; i < N && !_fRange.empty; ++i, _fRange.popFront())
979                 _front ~= _fRange.front();
980 
981             for(int i = 0; i < N && !_bRange.empty; ++i, _bRange.popBack())
982                 _back ~= _bRange.back();
983 
984             _back = _back.reverse;
985         }
986 
987 
988 
989       public:
990         this(R range)
991         {
992             _fRange = range.save;
993             _bRange = range.save;
994 
995           static if(assE || isRandomAccessRange!R)
996             _assignRange = range.save;
997 
998             for(int i = 0; i < N && !_fRange.empty; ++i, _fRange.popFront())
999                 _front ~= _fRange.front();
1000 
1001             for(int i = 0; i < N && !_bRange.empty; ++i, _bRange.popBack())
1002                 _back ~= _bRange.back();
1003             _back = _back.reverse;
1004         }
1005 
1006         
1007       static if(isInfinite!R)
1008         enum bool empty = false;
1009       else
1010         @property bool empty()
1011         {
1012             return (_front.length < N) || (_back.length < N);
1013         }
1014         
1015         
1016         void popFront()
1017         {
1018             _front = _front[1..$];
1019 
1020             if(!_fRange.empty){
1021               _front ~= _fRange.front;
1022 
1023               _fRange.popFront();
1024               _bRange.popFront();
1025             }
1026 
1027           static if(assE || isRandomAccessRange!R)
1028             _assignRange.popFront();
1029         }
1030 
1031 
1032         void popBack()
1033         {
1034             _back = _back[0..$-1];
1035 
1036             if(!_bRange.empty){
1037               _back = [_bRange.back] ~ _back;
1038 
1039               _fRange.popBack();
1040               _bRange.popBack();
1041             }
1042 
1043           static if(assE || isRandomAccessRange!R)
1044             _assignRange.popBack();
1045         }
1046         
1047         
1048         @property Segment save()
1049         {
1050             Segment dst = this;
1051             dst._fRange = dst._fRange.save;
1052             dst._bRange = dst._bRange.save;
1053 
1054           static if(assE)
1055             dst._assignRange = dst._assignRange.save;
1056 
1057             return dst;
1058         }
1059 
1060       
1061       static if(hasLength!R)
1062       {
1063         @property size_t length()
1064         {
1065             return _fRange.length + ((_front.length == N && _back.length == N) ? 1 : 0);
1066         }
1067 
1068 
1069         alias length opDollar;
1070       }
1071       
1072 
1073       static if(hasSlicing!R)
1074       {
1075         Segment opSlice()
1076         {
1077             return save;
1078         }
1079 
1080 
1081         static if(assE || isRandomAccessRange!R)
1082           auto opSlice(size_t i, size_t j)
1083           {
1084               return segment!N(_assignRange[i..j + (N-1)]);
1085           }
1086         //else
1087       }
1088       
1089 
1090         @property Tuple!(TypeNuple!(E, N)) front()
1091         {
1092             return (cast(typeof(return)[])(cast(ubyte[])_front))[0];
1093         }
1094 
1095         
1096         @property Tuple!(TypeNuple!(E, N)) back()
1097         {
1098             return (cast(typeof(return)[])(cast(ubyte[])_back))[0];
1099         }
1100 
1101 
1102       static if(isRandomAccessRange!R)
1103         Tuple!(TypeNuple!(E, N)) opIndex(size_t i)
1104         {
1105             E[] dst;
1106 
1107             foreach(j; 0..N)
1108                 dst ~= _assignRange[i + j];
1109 
1110             return (cast(typeof(return)[])(cast(ubyte[])dst))[0];
1111         }
1112 
1113 
1114 
1115       static if(assE)
1116       {
1117         @property void front(Tuple!(TypeNuple!(E, N)) e)
1118         {
1119             R _tmp = _assignRange.save;
1120             _front = [e.field];
1121 
1122             for(int i = 0; i < N; ++i, _tmp.popFront())
1123                 _tmp.front = _front[i];
1124 
1125             reConstruct();
1126         }
1127 
1128 
1129         @property void back(Tuple!(TypeNuple!(E, N)) e)
1130         {
1131             R _tmp = _assignRange.save;
1132             _back = [e.field];
1133 
1134             for(int i = N-1; i >= 0; --i, _tmp.popBack())
1135                 _tmp.back = _back[i];
1136 
1137             reConstruct();
1138         }
1139 
1140         static if(isRandomAccessRange!R)
1141         void opIndexAssign(Tuple!(TypeNuple!(E, N)) e, size_t i)
1142         {
1143             foreach(j; 0..N)
1144                 _assignRange[i + j] = [e.field][j];
1145 
1146             reConstruct();
1147         }
1148       }
1149     }
1150 }
1151 
1152 unittest
1153 {
1154     //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__);
1155     debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();}
1156 
1157     struct TRange{
1158         int[] a;
1159         @property int front(){return a.front;}
1160         @property bool empty(){return a.empty;}
1161         void popFront(){a.popFront();}
1162         void popBack(){a.popBack();}
1163         @property int back(){return a.back();}
1164         @property TRange save(){return TRange(a.save);}
1165         @property size_t length(){return a.length;}
1166         alias length opDollar;
1167     }
1168 
1169 
1170     auto r = TRange([0, 1, 2, 3, 4]);
1171     auto sg = segment!2(r);
1172     assert(equal(sg, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)]));
1173     assert(equal(sg.retro, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)].retro));
1174     assert(sg.length == 4);
1175 
1176     sg.popFront();
1177     assert(equal(sg, [tuple(1, 2), tuple(2, 3), tuple(3, 4)]));
1178     assert(sg.length == 3);
1179     assert(!sg.empty);
1180 
1181     auto sv = sg.save;
1182     sv.popFront();
1183     assert(equal(sg, [tuple(1, 2), tuple(2, 3), tuple(3, 4)]));
1184     assert(equal(sv, [tuple(2, 3), tuple(3, 4)]));
1185     assert(sg.length == 3);
1186     assert(sv.length == 2);
1187     assert(!sg.empty);
1188     assert(!sv.empty);
1189 
1190     sg.popFront();
1191     assert(equal(sg, [tuple(2, 3), tuple(3, 4)]));
1192     assert(sg.length == 2);
1193     assert(!sg.empty);
1194 
1195     sg.popFront();
1196     assert(equal(sg, [tuple(3, 4)]));
1197     assert(sg.length == 1);
1198     assert(!sg.empty);
1199 
1200     sg.popFront();
1201     assert(sg.length == 0);
1202     assert(sg.empty);
1203 }
1204 unittest
1205 {
1206     //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__);
1207     debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();}
1208 
1209     struct TRange{
1210         int[] a;
1211         @property ref int front(){return a.front;}
1212         @property bool empty(){return a.empty;}
1213         void popFront(){a.popFront();}
1214         void popBack(){a.popBack();}
1215         @property ref int back(){return a.back();}
1216         @property TRange save(){return TRange(a.save);}
1217         @property size_t length(){return a.length;}
1218         TRange opSlice(size_t i, size_t j){return TRange(a[i..j]);}
1219         alias length opDollar;
1220     }
1221 
1222 
1223     auto r = TRange([0, 1, 2, 3, 4]);
1224     auto sg = segment!2(r);
1225     assert(equal(sg, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)]));
1226     assert(equal(retro(sg), [tuple(3, 4), tuple(2, 3), tuple(1, 2), tuple(0, 1)]));
1227     assert(sg.length == 4);
1228     assert(equal(sg[2..4], [tuple(2, 3), tuple(3, 4)]));
1229 
1230     auto sgsv = sg.save;
1231     sgsv.popFront();
1232     assert(equal(sg, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)]));
1233     assert(equal(sgsv, [tuple(1, 2), tuple(2, 3), tuple(3, 4)]));
1234 
1235     auto sgsv2 = sg[];
1236     sgsv2.popFront();
1237     assert(equal(sg, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)]));
1238     assert(equal(sgsv2, [tuple(1, 2), tuple(2, 3), tuple(3, 4)]));
1239 
1240 
1241     sg.front = tuple(2, 2);
1242     assert(equal(sg, [tuple(2, 2), tuple(2, 2), tuple(2, 3), tuple(3, 4)]));
1243     assert(equal(retro(sg), [tuple(3, 4), tuple(2, 3), tuple(2, 2), tuple(2, 2)]));
1244 
1245     sg.popFront();
1246     assert(equal(sg, [tuple(2, 2), tuple(2, 3), tuple(3, 4)]));
1247     assert(equal(retro(sg), [tuple(3, 4), tuple(2, 3), tuple(2, 2)]));
1248     assert(sg.length == 3);
1249     assert(!sg.empty);
1250 
1251     sg.popFront();
1252     assert(equal(sg, [tuple(2, 3), tuple(3, 4)]));
1253     assert(equal(retro(sg), [tuple(3, 4), tuple(2, 3)]));
1254     assert(sg.length == 2);
1255     assert(!sg.empty);
1256 
1257     sg.popFront();
1258     assert(equal(sg, [tuple(3, 4)]));
1259     assert(equal(retro(sg), [tuple(3, 4)]));
1260     assert(sg.length == 1);
1261     assert(!sg.empty);
1262 
1263     sg.front = tuple(2, 5);
1264     assert(equal(sg, [tuple(2, 5)]));
1265     assert(equal(retro(sg), [tuple(2, 5)]));
1266     assert(sg.length == 1);
1267     assert(!sg.empty);
1268 
1269     sg.front = tuple(2, 1);
1270     assert(equal(sg, [tuple(2, 1)]));
1271     assert(sg.length == 1);
1272     assert(!sg.empty);
1273 
1274     sg.popFront();
1275     assert(sg.length == 0);
1276     assert(sg.empty);
1277 }
1278 unittest
1279 {
1280     //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__);
1281     debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();}
1282 
1283     struct TRange{
1284         int[] a;
1285         @property ref int front(){return a.front;}
1286         @property bool empty(){return a.empty;}
1287         void popFront(){a.popFront();}
1288         void popBack(){a.popBack();}
1289         @property ref int back(){return a.back();}
1290         @property TRange save(){return TRange(a.save);}
1291         @property size_t length(){return a.length;}
1292         TRange opSlice(size_t i, size_t j){return TRange(a[i..j]);}
1293         alias length opDollar;
1294     }
1295 
1296 
1297     auto r = TRange([0, 1, 2, 3, 4]);
1298     auto sg = segment!3(r);
1299     assert(equal(sg, [tuple(0, 1, 2), tuple(1, 2, 3), tuple(2, 3, 4)]));
1300     assert(equal(retro(sg), [tuple(0, 1, 2), tuple(1, 2, 3), tuple(2, 3, 4)].retro));
1301     assert(sg.length == 3);
1302     assert(equal(sg[2..3], [tuple(2, 3, 4)]));
1303 
1304     sg.front = tuple(2, 2, 2);
1305     assert(equal(sg, [tuple(2, 2, 2), tuple(2, 2, 3), tuple(2, 3, 4)]));
1306     assert(equal(sg.retro, [tuple(2, 2, 2), tuple(2, 2, 3), tuple(2, 3, 4)].retro));
1307 
1308     sg.popFront();
1309     assert(equal(sg, [tuple(2, 2, 3), tuple(2, 3, 4)]));
1310     assert(equal(sg.retro, [tuple(2, 2, 3), tuple(2, 3, 4)].retro));
1311     assert(sg.length == 2);
1312     assert(!sg.empty);
1313 
1314     sg.back = tuple(4, 4, 4);
1315     assert(equal(sg, [tuple(2, 4, 4), tuple(4, 4, 4)]));
1316     assert(equal(sg.retro, [tuple(2, 4, 4), tuple(4, 4, 4)].retro));
1317     assert(sg.length == 2);
1318     assert(!sg.empty);
1319 
1320     sg.popFront();
1321     assert(equal(sg, [tuple(4, 4, 4)]));
1322     assert(equal(sg.retro, [tuple(4, 4, 4)].retro));
1323     assert(sg.length == 1);
1324     assert(!sg.empty);
1325 
1326     sg.popFront();
1327     assert(sg.length == 0);
1328     assert(sg.empty);
1329 }
1330 unittest
1331 {
1332     //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__);
1333     debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();}
1334 
1335     struct TRange{
1336         size_t f, b;
1337         int[] s;
1338 
1339         this(int[] r){
1340             f = 0;
1341             s = r;
1342             b = s.length - 1;
1343         }
1344 
1345         @property ref int front(){return s[f];}
1346         enum bool empty = false;
1347         void popFront(){++f; if(f == s.length)f = 0;}
1348         void popBack(){b = (b == 0 ? s.length - 1 : b-1);}
1349         @property ref int back(){return s[b];}
1350         @property typeof(this) save(){return this;}
1351         auto opSlice(size_t i, size_t j){auto dst = this; dst.popFrontN(i); return dst.take(j - i);}
1352         ref int opIndex(size_t i){return s[(i+f)%s.length];}
1353     }
1354 
1355     alias TRange Range;
1356     static assert(isInputRange!TRange);
1357 
1358     auto r = TRange([0, 1, 2, 3, 4]);
1359     auto sg = segment!3(r);
1360     assert(equal(sg.take(3), [tuple(0, 1, 2), tuple(1, 2, 3), tuple(2, 3, 4)]));
1361     assert(equal(retro(sg).take(3), [tuple(2, 3, 4), tuple(1, 2, 3), tuple(0, 1, 2)]));
1362     assert(sg[2] == tuple(2, 3, 4));
1363     //assert(equal(sg[2..3], [tuple(2, 3, 4)]));
1364 
1365     sg.front = tuple(2, 2, 2); //[2, 2, 2, 3, 4]
1366     assert(equal(sg.take(3), [tuple(2, 2, 2), tuple(2, 2, 3), tuple(2, 3, 4)]));
1367     assert(equal(retro(sg).take(3), [tuple(2, 3, 4), tuple(2, 2, 3), tuple(2, 2, 2)]));
1368 
1369     sg.popFront();
1370     assert(equal(sg.take(3), [tuple(2, 2, 3), tuple(2, 3, 4), tuple(3, 4, 2)]));
1371     assert(equal(retro(sg).take(3), [tuple(2, 3, 4), tuple(2, 2, 3), tuple(2, 2, 2)]));
1372     assert(!sg.empty);
1373 
1374     sg[1] = tuple(3, 3, 3); //[2, 2, 3, 3, 3] 
1375     assert(equal(sg.take(3), [tuple(2, 3, 3), tuple(3, 3, 3), tuple(3, 3, 2)]));
1376     assert(equal(sg.retro.take(3), [tuple(3, 3, 3), tuple(2, 3, 3), tuple(2, 2, 3)]));
1377     assert(!sg.empty);
1378 
1379     sg.back = tuple(2, 3, 4);//[2, 2, 2, 3, 4]
1380     assert(equal(sg.take(3), [tuple(2, 2, 3), tuple(2, 3, 4), tuple(3, 4, 2)]));
1381     assert(equal(sg.retro.take(3), [tuple(2, 3, 4), tuple(2, 2, 3), tuple(2, 2, 2)]));
1382     assert(!sg.empty);
1383 
1384     sg.popBack();
1385     assert(equal(sg.take(3), [tuple(2, 2, 3), tuple(2, 3, 4), tuple(3, 4, 2)]));
1386     assert(equal(sg.retro.take(3), [tuple(2, 2, 3), tuple(2, 2, 2), tuple(4, 2, 2)]));
1387     assert(!sg.empty);
1388 }
1389 
1390 
1391 /**
1392 concats elements
1393 */
1394 auto concat(R)(R range) if (isRangeOfRanges!R)
1395 {
1396     static struct Concat
1397     {
1398       private:
1399         R _range;
1400         alias ElementType!R ET0;
1401         alias ElementType!ET0 ET1;
1402         ET0 _subrange;
1403 
1404       static if(isRangeOfRanges!(R, isBidirectionalRange))
1405       {
1406         ET0 _backSubrange;
1407       }
1408 
1409       public:
1410       static if(isInfinite!R)
1411         enum bool empty = false;
1412       else
1413       {
1414         @property
1415         bool empty()
1416         {
1417             return _range.empty;
1418         }
1419       }
1420 
1421 
1422         @property
1423         auto ref front()
1424         {
1425             return _subrange.front;
1426         }
1427 
1428 
1429       static if(hasAssignableElements!ET0)
1430       {
1431         @property
1432         void front(ET1 v)
1433         {
1434             _subrange.front = v;
1435         }
1436       }
1437 
1438 
1439       /*
1440       static if(isRangeOfRange!(R, isForwardRange))
1441       {
1442         @property
1443         Concat save()
1444         {
1445             return this;
1446         }
1447       }
1448       */
1449 
1450 
1451         void popFront()
1452         {
1453             if (!_subrange.empty) _subrange.popFront;
1454 
1455             while(_subrange.empty && !_range.empty){
1456                 _range.popFront;
1457 
1458                 if (!_range.empty)
1459                     _subrange = _range.front;
1460             }
1461         }
1462 
1463 
1464       static if (isRangeOfRanges!(R, isBidirectionalRange))
1465       {
1466         @property
1467         auto ref back()
1468         {
1469             return _backSubrange.back;
1470         }
1471 
1472 
1473         static if(hasAssignableElements!ET0)
1474         {
1475             @property
1476             void back(ET1 v)
1477             {
1478                 _backSubrange.back = v;
1479             }
1480         }
1481 
1482 
1483         void popBack()
1484         {
1485             if (!_backSubrange.empty) _backSubrange.popBack;
1486 
1487             while (_backSubrange.empty && !_range.empty) {
1488                 _range.popBack;
1489                 if (!_range.empty) _backSubrange = _range.back;
1490             }
1491         }
1492 
1493 
1494         auto retro() @property
1495         {
1496             static struct RetroConcat
1497             {
1498                 auto ref front() @property
1499                 {
1500                     return _r.back;
1501                 }
1502 
1503 
1504                 auto ref back() @property
1505                 {
1506                     return _r.front;
1507                 }
1508 
1509 
1510               static if(hasAssignableElements!ET0)
1511               {
1512                 void front(ET1 v) @property
1513                 {
1514                     _r.back = v;
1515                 }
1516 
1517 
1518                 void back(ET1 v) @property
1519                 {
1520                     _r.front = v;
1521                 }
1522               }
1523 
1524 
1525                 void popFront()
1526                 {
1527                     _r.popBack();
1528                 }
1529 
1530 
1531                 void popBack()
1532                 {
1533                     _r.popFront();
1534                 }
1535 
1536 
1537               static if(isInfinite!R)
1538                 enum bool empty = false;
1539               else
1540                 bool empty() @property
1541                 {
1542                     return _r.empty;
1543                 }
1544 
1545 
1546                 // save..
1547 
1548 
1549                 auto retro() @property
1550                 {
1551                     return _r;
1552                 }
1553 
1554 
1555               private:
1556                 Concat _r;
1557             }
1558 
1559 
1560             return RetroConcat(this);
1561         }
1562       }
1563     }
1564 
1565 
1566     Concat dst = {_range : range};
1567 
1568     enum initMethod = 
1569     q{
1570         if (!dst._range.empty){
1571             %1$s = dst._range.%2$s;
1572             while (%1$s.empty && !dst._range.empty){
1573                 dst._range.%3$s;
1574 
1575                 if (!dst._range.empty)
1576                     %1$s = dst._range.%2$s;
1577             }
1578         }
1579     };
1580 
1581     mixin(format(initMethod, "dst._subrange", "front", "popFront"));
1582 
1583   static if (isRangeOfRanges!(R, isBidirectionalRange))
1584   {
1585     mixin(format(initMethod, "dst._backSubrange", "back", "popBack"));
1586   }
1587 
1588     return dst;
1589 }
1590 
1591 /// ditto
1592 R concat(R)(R range)
1593 if(isSimpleRange!R)
1594 {
1595     return range;
1596 }
1597 
1598 ///
1599 unittest
1600 {
1601     debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__);
1602     debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();}
1603 
1604     int[][] r1 = [[0, 1, 2, 3], [4, 5, 6], [7, 8], [9], []];
1605     auto c = concat(r1);
1606     assert(equal(c, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
1607     assert(equal(c.retro(), retro([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))); // bidir range
1608     assert(equal(c.retro.retro, c));
1609 
1610     assert(equal(concat(c), c));
1611 
1612     auto r2 = [0, 1, 2, 3, 4, 5];
1613     assert(equal(r2.map!"[a, 2]".concat, [0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5, 2]));
1614     assert(equal(r2[0 .. 4].map!(a => repeat(a, a)).concat, [1, 2, 2, 3, 3, 3]));
1615     assert(equal(r2[0 .. 3].repeat(2).map!(map!"a + 1").concat, [1, 2, 3, 1, 2, 3]));
1616 
1617     int[] emp;
1618     assert(emp.repeat(15).concat.empty);
1619     assert(emp.concat.empty);
1620 }
1621 
1622 
1623 ///
1624 auto flatten(size_t N = size_t.max, R)(R r)
1625 if(isInputRange!R)
1626 {
1627   static if(N > 0 && isRangeOfRanges!R)
1628     return r.concat.flatten!(N-1);
1629   else
1630     return r;
1631 }
1632 
1633 ///
1634 unittest
1635 {
1636     auto d1 = [0, 1, 2, 3, 4, 5, 6, 7, 8];
1637     assert(equal(d1.flatten, d1));
1638     assert(equal(d1.flatten!0, d1));
1639 
1640     auto d2 = [[0, 1], [], [2, 3], [4, 5, 6, 7], [8]];
1641     assert(equal(d2.flatten, d1));
1642     assert(equal(d2.flatten!1, d1));
1643     assert(equal(d2.flatten!0, d2));
1644 
1645     auto d3 = [[[0, 1], [], [2, 3]], [[4, 5, 6, 7], [8]]];
1646     assert(equal(d3.flatten, d1));
1647     assert(equal(d3.flatten!0, d3));
1648     assert(equal(d3.flatten!1, d2));
1649     assert(equal(d3.flatten!2, d1));
1650 }