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 }