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.array, 36 std.functional, 37 std.range, 38 std..string, 39 std.traits, 40 std.typecons; 41 42 debug import std.stdio; 43 44 import carbon.functional, 45 carbon.templates, 46 carbon.traits; 47 48 49 /** 50 true if isInputRange!R is true and isInputRange!R is false. 51 */ 52 enum isSimpleRange(R, alias I = isInputRange) = 53 I!(R) && !I!(ElementType!R); 54 55 56 /** 57 true if both isInputRange!R and isInputRange!R are true. 58 */ 59 enum isRangeOfRanges(R, alias I = isInputRange) = 60 I!(R) && I!(ElementType!R); 61 62 63 64 /** 65 あるレンジのN個の連続する要素のリストを返します。 66 67 Example: 68 ---- 69 auto r1 = [0, 1, 2, 3, 4, 5]; 70 auto s = segment!2(r1); 71 assert(equal(s, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4), tuple(4, 5)][])); 72 assert(s.length == 5); // .length 73 // back/popBack: 74 assert(equal(retro(s), retro([tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4), tuple(4, 5)][]))); 75 assert(s[3] == tuple(3, 4)); // opIndex 76 s[3] = tuple(0, 0); // opIndexAssign not ref opIndex 77 assert(s[2] == tuple(2, 0)); // it affects its neighbors. 78 assert(s[4] == tuple(0, 5)); 79 assert(r1 == [0, 1, 2, 0, 0, 5][]); // affects r1 back (no .dup internally) 80 81 82 auto st = ["a","b","c","d","e","f"]; 83 auto s2 = segment!3(st); 84 assert(s2.front == tuple("a","b","c")); 85 86 87 auto r1 = [0,1,2,3,4,5]; // regenerates r1 88 auto s3 = segment!1(r1); 89 assert(equal(s3, [tuple(0), tuple(1), tuple(2), tuple(3), tuple(4), tuple(5)][])); 90 auto r2 = map!"a*a"(r1); 91 auto s4 = segment!2(r2); // On a forward range 92 assert(equal(s4, [tuple(0,1), tuple(1,4), tuple(4,9), tuple(9,16), tuple(16,25)][])); 93 94 95 int[] e; 96 auto s5 = segment!2(e); 97 assert(s5.empty); 98 ---- 99 100 Authors: Komatsu Kazuki 101 */ 102 template SegmentType(size_t N, R) 103 if(isInputRange!(Unqual!R) && N > 0) 104 { 105 alias typeof(segment!N(R.init)) SegmentType; 106 } 107 108 109 ///ditto 110 template segment(size_t N : 1, Range) 111 if(isInputRange!(Unqual!Range)) 112 { 113 Segment segment(Range range) 114 { 115 return Segment(range); 116 } 117 118 alias Unqual!Range R; 119 alias ElementType!Range E; 120 121 struct Segment{ 122 private: 123 R _range; 124 125 public: 126 this(R range) 127 { 128 _range = range; 129 } 130 131 132 static if(isInfinite!R) 133 enum bool e = false; 134 else 135 @property bool empty() 136 { 137 return _range.empty; 138 } 139 140 141 void popFront() 142 { 143 _range.popFront(); 144 } 145 static if(isBidirectionalRange!R) 146 void popBack() 147 { 148 _range.popBack(); 149 } 150 151 152 static if(isForwardRange!R) 153 @property typeof(this) save() 154 { 155 typeof(this) dst = this; 156 dst._range = dst._range.save; 157 return dst; 158 } 159 160 static if(hasLength!R) 161 { 162 @property size_t length() 163 { 164 return _range.length; 165 } 166 167 alias length opDollar; 168 } 169 170 static if(hasSlicing!R) 171 { 172 Segment opSlice() 173 { 174 static if(isForwardRange!R) 175 return save; 176 else 177 return typeof(this)(_range); 178 } 179 180 181 auto opSlice(size_t i, size_t j) 182 { 183 return segment!1(_range[i .. j]); 184 } 185 } 186 187 188 @property Tuple!E front() 189 { 190 return tuple(_range.front); 191 } 192 193 static if(isBidirectionalRange!R) 194 @property Tuple!E back() 195 { 196 return tuple(_range.back); 197 } 198 199 static if(isRandomAccessRange!R) 200 Tuple!E opIndex(size_t i) 201 { 202 return tuple(_range[i]); 203 } 204 205 static if(hasAssignableElements!R || hasSwappableElements!R || hasLvalueElements!R) 206 { 207 @property void front(Tuple!E e) 208 { 209 _range.front = e[0]; 210 } 211 212 213 static if(isBidirectionalRange!R) 214 { 215 @property void back(Tuple!E e) 216 { 217 _range.back = e[0]; 218 } 219 } 220 221 static if(isRandomAccessRange!R) 222 { 223 void opIndexAssign(Tuple!E e, size_t i) 224 { 225 _range[i] = e[0]; 226 } 227 } 228 } 229 230 } 231 } 232 233 234 unittest 235 { 236 //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__); 237 debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();} 238 239 auto a = [0, 1, 2, 3, 4]; 240 auto sg = segment!1(a); 241 242 assert(equal(sg, [tuple(0), tuple(1), tuple(2), tuple(3), tuple(4)])); 243 assert(equal(sg.retro, [tuple(0), tuple(1), tuple(2), tuple(3), tuple(4)].retro)); 244 245 sg.front = tuple(3); 246 assert(equal(sg, [tuple(3), tuple(1), tuple(2), tuple(3), tuple(4)])); 247 248 sg[3] = tuple(2); 249 assert(equal(sg, [tuple(3), tuple(1), tuple(2), tuple(2), tuple(4)])); 250 251 assert(sg.length == 5); 252 253 sg.back = tuple(8); 254 assert(equal(sg, [tuple(3), tuple(1), tuple(2), tuple(2), tuple(8)])); 255 assert(sg[$-1] == tuple(8)); 256 257 assert(equal(sg[2..4], [tuple(2), tuple(2)])); 258 259 auto sv = sg.save; 260 sv.popFront(); 261 assert(equal(sg, [tuple(3), tuple(1), tuple(2), tuple(2), tuple(8)])); 262 assert(equal(sv, [tuple(1), tuple(2), tuple(2), tuple(8)])); 263 264 auto sl = sv[]; 265 sv.popFront(); 266 assert(equal(sl, [tuple(1), tuple(2), tuple(2), tuple(8)])); 267 assert(equal(sv, [tuple(2), tuple(2), tuple(8)])); 268 } 269 270 271 ///ditto 272 template segment(size_t N, Range) 273 if (isInputRange!(Unqual!Range) 274 && (isForwardRange!(Unqual!Range) ? (!isBidirectionalRange!(Unqual!Range) 275 && !isRandomAccessRange!(Unqual!Range)) : true)) 276 { 277 Segment segment(Range range) 278 { 279 return Segment(range); 280 } 281 282 alias Unqual!Range R; 283 alias ElementType!R E; 284 285 enum assE = isForwardRange!R && (hasAssignableElements!R || hasLvalueElements!R || hasSwappableElements!R); 286 287 struct Segment{ 288 private: 289 R _range; 290 E[] _front; 291 292 static if(assE) 293 R _assignRange; 294 295 public: 296 this(R range) 297 { 298 _range = range; 299 300 static if(assE) 301 _assignRange = _range.save; 302 303 for(int i = 0; i < N && !_range.empty; ++i, _range.popFront()) 304 _front ~= _range.front; 305 } 306 307 308 void popFront() 309 { 310 if(_range.empty) 311 _front = _front[1..$]; 312 else{ 313 _front = _front[1..$]; 314 _front ~= _range.front; 315 _range.popFront(); 316 static if(assE) 317 _assignRange.popFront(); 318 } 319 } 320 321 @property 322 Tuple!(TypeNuple!(E, N)) front() 323 { 324 return (cast(typeof(return)[])(cast(ubyte[])_front))[0]; 325 } 326 327 328 static if(assE) 329 @property void front(Tuple!(TypeNuple!(E, N)) e) 330 { 331 R _tmpRange = _assignRange.save; 332 333 _front = [e.field]; 334 335 for(int i = 0; i < N; ++i, _tmpRange.popFront) 336 _tmpRange.front = _front[i]; 337 } 338 339 340 static if(isForwardRange!R) { 341 @property Segment save() 342 { 343 Segment dst = this; 344 dst._range = dst._range.save; 345 346 static if(assE) 347 dst._assignRange = dst._assignRange.save; 348 349 return dst; 350 } 351 } 352 353 static if(isInfinite!R) 354 enum bool empty = false; 355 else 356 @property 357 bool empty() 358 { 359 return _front.length != N; 360 } 361 362 363 static if(hasLength!R){ 364 @property 365 size_t length() 366 { 367 return _range.length + !this.empty; 368 } 369 370 alias length opDollar; 371 } 372 373 static if(hasSlicing!R) 374 { 375 Segment opSlice() 376 { 377 static if(isInputRange!R) 378 return this; 379 else 380 return save; 381 } 382 383 auto opSlice(size_t i, size_t j) 384 { 385 return segment!N(_assignRange[i..j + (N-1)]); 386 } 387 } 388 } 389 } 390 391 392 unittest 393 { 394 //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__); 395 debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();} 396 397 struct TRange 398 { 399 int _front, _end; 400 @property int front(){return _front;} 401 void popFront(){_front += 1;} 402 @property bool empty(){return _front == _end;} 403 @property TRange save(){return this;} 404 @property size_t length(){return _end - _front;} 405 alias length opDollar; 406 } 407 408 auto tr = TRange(0, 5); 409 auto sg2 = segment!2(tr); 410 assert(equal(sg2, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)])); 411 412 auto sg2sv = sg2.save; 413 sg2sv.popFront(); 414 assert(equal(sg2, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)])); 415 assert(equal(sg2sv, [tuple(1, 2), tuple(2, 3), tuple(3, 4)])); 416 417 assert(sg2.length == 4); 418 419 auto sg3 = segment!3(tr); 420 assert(equal(sg3, [tuple(0, 1, 2), tuple(1, 2, 3), tuple(2, 3, 4)])); 421 assert(sg3.length == 3); 422 423 auto sg4 = segment!4(tr); 424 assert(equal(sg4, [tuple(0, 1, 2, 3), tuple(1, 2, 3, 4)])); 425 assert(sg4.length == 2); 426 427 auto sg5 = segment!5(tr); 428 assert(equal(sg5, [tuple(0, 1, 2, 3, 4)])); 429 assert(sg5.length == 1); 430 431 auto sg6 = segment!6(tr); 432 assert(sg6.empty); 433 assert(sg6.length == 0); 434 435 auto tremp = TRange(0, 0); 436 assert(tremp.empty); 437 assert(segment!2(tremp).empty); 438 } 439 unittest 440 { 441 //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__); 442 debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();} 443 444 struct TRange 445 { 446 int _front, _end; 447 @property int front(){return _front;} 448 void popFront(){_front += 1;} 449 @property bool empty(){return _front == _end;} 450 @property TRange save(){return this;} 451 @property size_t length(){return _end - _front;} 452 alias length opDollar; 453 } 454 455 auto tr = TRange(0, 5); 456 auto sg2 = segment!2(tr); 457 assert(equal(sg2, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)])); 458 459 assert(sg2.length == 4); 460 461 auto sg3 = segment!3(tr); 462 assert(equal(sg3, [tuple(0, 1, 2), tuple(1, 2, 3), tuple(2, 3, 4)])); 463 assert(sg3.length == 3); 464 465 auto sg4 = segment!4(tr); 466 assert(equal(sg4, [tuple(0, 1, 2, 3), tuple(1, 2, 3, 4)])); 467 assert(sg4.length == 2); 468 469 auto sg5 = segment!5(tr); 470 assert(equal(sg5, [tuple(0, 1, 2, 3, 4)])); 471 assert(sg5.length == 1); 472 473 auto sg6 = segment!6(tr); 474 assert(sg6.empty); 475 assert(sg6.length == 0); 476 477 auto tremp = TRange(0, 0); 478 assert(tremp.empty); 479 assert(segment!2(tremp).empty); 480 } 481 unittest 482 { 483 //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__); 484 debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();} 485 486 struct TRange 487 { 488 int[] a; 489 @property ref int front(){return a.front;} 490 @property bool empty(){return a.empty;} 491 void popFront(){a.popFront;} 492 @property TRange save(){return TRange(a.save);} 493 @property size_t length(){return a.length;} 494 alias length opDollar; 495 TRange opSlice(size_t i, size_t j){return TRange(a[i..j]);} 496 } 497 498 499 int[] a = [0, 1, 2, 3, 4]; 500 auto r = TRange(a); 501 auto sg = segment!2(r); 502 assert(equal(sg, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)])); 503 assert(equal(sg[2..4], [tuple(2, 3), tuple(3, 4)])); 504 505 sg.front = tuple(3, 2); 506 assert(equal(sg, [tuple(3, 2), tuple(2, 2), tuple(2, 3), tuple(3, 4)])); 507 508 assert(sg.length == 4); 509 sg.popFront(); 510 assert(sg.length == 3); 511 sg.popFront(); 512 assert(sg.length == 2); 513 sg.popFront(); 514 assert(sg.length == 1); 515 sg.popFront(); 516 assert(sg.length == 0); 517 assert(sg.empty); 518 519 a = [0, 1, 2, 3, 4]; 520 r = TRange(a); 521 auto sg3 = segment!3(r); 522 assert(equal(sg3, [tuple(0, 1, 2), tuple(1, 2, 3), tuple(2, 3, 4)])); 523 sg3.front = tuple(2, 3, 1); 524 assert(equal(sg3, [tuple(2, 3, 1), tuple(3, 1, 3), tuple(1, 3, 4)])); 525 526 auto sl3 = sg3[]; 527 sl3.popFront(); 528 assert(equal(sg3, [tuple(2, 3, 1), tuple(3, 1, 3), tuple(1, 3, 4)])); 529 assert(equal(sl3, [tuple(3, 1, 3), tuple(1, 3, 4)])); 530 531 auto sv3 = sg3.save; 532 sv3.popFront(); 533 assert(equal(sg3, [tuple(2, 3, 1), tuple(3, 1, 3), tuple(1, 3, 4)])); 534 assert(equal(sv3, [tuple(3, 1, 3), tuple(1, 3, 4)])); 535 536 assert(sg3.length == 3); 537 sg3.popFront(); 538 assert(sg3.length == 2); 539 sg3.popFront(); 540 assert(sg3.length == 1); 541 sg3.popFront(); 542 assert(sg3.length == 0); 543 assert(sg3.empty); 544 } 545 546 547 ///ditto 548 template segment(size_t N, Range) 549 if(isRandomAccessRange!(Unqual!Range) 550 && isBidirectionalRange!(Unqual!Range) 551 && hasLength!(Unqual!Range)) 552 { 553 Segment segment(Range range) 554 { 555 return Segment(range); 556 } 557 558 559 alias Unqual!Range R; 560 alias ElementType!R E; 561 562 struct Segment{ 563 private: 564 R _range; 565 size_t _fidx; 566 size_t _bidx; 567 E[] _front; 568 E[] _back; 569 570 void reConstruct() 571 { 572 if(!empty){ 573 _front.length = 0; 574 _back.length = 0; 575 foreach(i; 0..N) 576 { 577 _front ~= _range[_fidx + i]; 578 _back ~= _range[_bidx + i]; 579 } 580 } 581 } 582 583 584 public: 585 this(R range) 586 { 587 _range = range; 588 _fidx = 0; 589 _bidx = _range.length - N; 590 591 reConstruct(); 592 } 593 594 595 @property bool empty() const 596 { 597 return (cast(int)_bidx - cast(int)_fidx) < 0; 598 } 599 600 601 void popFront() 602 { 603 ++_fidx; 604 if(!empty){ 605 _front = _front[1..$]; 606 _front ~= _range[_fidx + (N - 1)]; 607 } 608 } 609 610 611 void popBack() 612 { 613 --_bidx; 614 if(!empty){ 615 _back = _back[0..$-1]; 616 _back = [_range[_bidx]] ~ _back; 617 } 618 } 619 620 621 @property Segment save() 622 { 623 Segment dst = cast(Segment)this; 624 dst._range = dst._range.save; 625 dst._front = dst._front.dup; 626 dst._back = dst._back.dup; 627 return dst; 628 } 629 630 631 @property size_t length() const 632 { 633 return _bidx - _fidx + 1; 634 } 635 636 637 alias length opDollar; 638 639 640 auto opSlice() 641 { 642 return save; 643 } 644 645 646 Segment opSlice(size_t i, size_t j) 647 { 648 Segment dst = this.save; 649 dst._fidx += i; 650 dst._bidx -= this.length - j; 651 652 dst.reConstruct(); 653 return dst; 654 } 655 656 657 @property Tuple!(TypeNuple!(E, N)) front() 658 { 659 return (cast(typeof(return)[])cast(ubyte[])_front)[0]; 660 } 661 662 663 @property Tuple!(TypeNuple!(E, N)) back() 664 { 665 return (cast(typeof(return)[])cast(ubyte[])_back)[0]; 666 } 667 668 669 Tuple!(TypeNuple!(E, N)) opIndex(size_t i) 670 { 671 if(i == 0) 672 return this.front; 673 else if(i == this.length - 1) 674 return this.back; 675 else 676 { 677 E[N] dst; 678 foreach(j; 0 .. N) 679 dst[j] = _range[_fidx + i + j]; 680 return (cast(typeof(return)[])(cast(ubyte[])(dst[])))[0]; 681 } 682 } 683 684 685 static if(hasSwappableElements!R || hasLvalueElements!R || hasAssignableElements!R) 686 { 687 @property void front(Tuple!(TypeNuple!(E, N)) e) 688 { 689 E[] eSlice = [e.field]; 690 691 foreach(i; 0 .. N) 692 _range[i + _fidx] = eSlice[i]; 693 694 reConstruct(); 695 } 696 697 698 @property void back(Tuple!(TypeNuple!(E, N)) e) 699 { 700 E[] eSlice = [e.field]; 701 702 foreach(i; 0..N) 703 _range[i + _bidx] = eSlice[i]; 704 705 reConstruct(); 706 } 707 708 709 void opIndexAssign(Tuple!(TypeNuple!(E, N)) e, size_t i) 710 { 711 E[] eSlice = [e.field]; 712 713 foreach(j; 0..N) 714 _range[_fidx + i + j] = eSlice[j]; 715 716 reConstruct(); 717 } 718 } 719 } 720 } 721 722 723 unittest 724 { 725 //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__); 726 debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();} 727 728 auto r1 = [0,1,2,3,4,5]; 729 auto s = segment!2(r1); 730 assert(equal(s, [tuple(0,1), tuple(1,2), tuple(2,3), tuple(3,4), tuple(4,5)][])); 731 assert(s.length == 5); // .length 732 // back/popBack: 733 assert(equal(retro(s), retro([tuple(0,1), tuple(1,2), tuple(2,3), tuple(3,4), tuple(4,5)][]))); 734 assert(s[3] == tuple(3,4)); // opIndex 735 s[3] = tuple(0,0); // opIndexAssign 736 assert(s[2] == tuple(2,0)); // it affects its neighbors. 737 assert(s[4] == tuple(0,5)); 738 assert(r1 == [0,1,2,0,0,5][]); // affects r1 back (no .dup internally) 739 740 s = segment!2(r1); 741 s.front = tuple(2, 0); 742 assert(s[0] == tuple(2, 0)); 743 744 s.back = tuple(100, 500); 745 assert(s[s.length - 1] == tuple(100, 500)); 746 747 auto sl = s[]; 748 assert(equal(sl, s)); 749 sl.popFront(); 750 sl.popBack(); 751 assert(equal(sl, s[1 .. s.length - 1])); 752 } 753 unittest 754 { 755 //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__); 756 debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();} 757 758 auto st = ["a","b","c","d","e","f"]; 759 auto s2 = segment!3(st); 760 assert(s2.front == tuple("a","b","c")); 761 } 762 unittest 763 { 764 //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__); 765 debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();} 766 767 auto r1 = [0,1,2,3,4,5]; // regenerates r1 768 auto s3 = segment!1(r1); 769 assert(equal(s3, [tuple(0), tuple(1), tuple(2), tuple(3), tuple(4), tuple(5)][])); 770 assert(equal(s3.retro, [tuple(0), tuple(1), tuple(2), tuple(3), tuple(4), tuple(5)].retro)); 771 auto r2 = map!"a*a"(r1); 772 auto s4 = segment!2(r2); // On a forward range 773 auto s4_2 = segment!2(r2); 774 assert(equal(s4_2, [tuple(0,1), tuple(1,4), tuple(4,9), tuple(9,16), tuple(16,25)][])); 775 } 776 unittest 777 { 778 //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__); 779 debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();} 780 781 int[] e; 782 auto s5 = segment!2(e); 783 assert(s5.empty); 784 } 785 unittest 786 { 787 //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__); 788 debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();} 789 790 auto ri = iota(0, 5); 791 auto sg = segment!2(ri); 792 assert(equal(sg, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)])); 793 assert(equal(sg.retro, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)].retro)); 794 assert(sg[0] == tuple(0, 1)); 795 assert(sg[1] == tuple(1, 2)); 796 assert(sg[2] == tuple(2, 3)); 797 assert(sg[3] == tuple(3, 4)); 798 assert(sg.length == 4); 799 } 800 801 ///ditto 802 template segment(size_t N, Range) 803 if(isRandomAccessRange!(Unqual!Range) 804 && !isBidirectionalRange!(Unqual!Range) 805 && isInfinite!(Unqual!Range)) 806 { 807 Segment segment(Range range) 808 { 809 return Segment(range); 810 } 811 812 813 alias Unqual!Range R; 814 alias ElementType!R E; 815 816 struct Segment{ 817 private: 818 R _range; 819 size_t _fidx; 820 E[] _front; 821 822 void reConstruct() 823 { 824 if(!empty){ 825 _front.length = 0; 826 foreach(i; 0..N) 827 _front ~= _range[_fidx + i]; 828 } 829 } 830 831 public: 832 this(R range) 833 { 834 _range = range; 835 _fidx = 0; 836 837 reConstruct(); 838 } 839 840 841 enum bool empty = false; 842 843 844 void popFront() 845 { 846 ++_fidx; 847 if(!empty){ 848 _front = _front[1..$]; 849 _front ~= _range[_fidx + (N - 1)]; 850 } 851 } 852 853 854 @property Segment save() 855 { 856 Segment dst = this; 857 dst._range = dst._range.save; 858 return dst; 859 } 860 861 862 @property Tuple!(TypeNuple!(E, N)) front() 863 { 864 return (cast(typeof(return)[])(cast(ubyte[])_front))[0]; 865 } 866 867 868 Tuple!(TypeNuple!(E, N)) opIndex(size_t i) 869 { 870 if(i == 0) 871 return this.front; 872 else 873 { 874 E[] dst; 875 foreach(j; 0 .. N) 876 dst ~= _range[_fidx + i + j]; 877 return (cast(typeof(return)[])(cast(ubyte[])dst))[0]; 878 } 879 } 880 881 882 static if(hasSwappableElements!R || hasLvalueElements!R || hasAssignableElements!R) 883 { 884 @property void front(Tuple!(TypeNuple!(E, N)) e) 885 { 886 E[] eSlice = [e.field]; 887 888 foreach(i; 0 .. N) 889 _range[i + _fidx] = eSlice[i]; 890 891 reConstruct(); 892 } 893 894 895 void opIndexAssign(Tuple!(TypeNuple!(E, N)) e, size_t i) 896 { 897 E[] eSlice = [e.field]; 898 899 foreach(j; 0..N) 900 _range[_fidx + i + j] = eSlice[j]; 901 902 reConstruct(); 903 } 904 } 905 } 906 } 907 908 909 unittest 910 { 911 //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__); 912 debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();} 913 914 struct TRange 915 { 916 int[] a, s; 917 918 this(int[] r){ 919 a = r.save; 920 s = r.save; 921 } 922 923 @property ref int front(){return a.front;} 924 enum bool empty = false; 925 void popFront(){a.popFront; if(a.empty)a = s;} 926 @property typeof(this) save(){return this;} 927 ref int opIndex(size_t i){return a[i%s.length];} 928 } 929 930 931 auto r = segment!2(TRange([0, 1, 2, 3, 4])); 932 assert(equal(r.take(4), [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)])); 933 934 auto sv = r.save; 935 sv.popFront(); 936 assert(equal(r.take(4), [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)])); 937 assert(equal(sv.take(3), [tuple(1, 2), tuple(2, 3), tuple(3, 4)])); 938 939 assert(r[2] == tuple(2, 3)); 940 assert(r[0] == tuple(0, 1)); 941 942 r.front = tuple(100, 50); 943 assert(equal(r.take(4), [tuple(100, 50), tuple(50, 2), tuple(2, 3), tuple(3, 4)])); 944 945 r[1] = tuple(10, 20); 946 assert(equal(r.take(4), [tuple(100, 10), tuple(10, 20), tuple(20, 3), tuple(3, 4)])); 947 } 948 949 950 ///ditto 951 template segment(size_t N, Range) 952 if(isBidirectionalRange!(Unqual!Range) 953 && (isRandomAccessRange!(Unqual!Range) ? (!hasLength!(Unqual!Range) && isInfinite!(Unqual!Range)) : true)) 954 { 955 Segment segment(Range range) 956 { 957 return Segment(range); 958 } 959 960 961 alias Unqual!Range R; 962 alias ElementType!R E; 963 enum assE = hasAssignableElements!R && hasLvalueElements!R && hasSwappableElements!R; 964 965 966 struct Segment{ 967 private: 968 R _fRange; 969 R _bRange; 970 E[] _front; 971 E[] _back; 972 973 static if(assE || isRandomAccessRange!R) 974 R _assignRange; 975 976 static if(assE || isRandomAccessRange!R) 977 void reConstruct(){ 978 _front.length = 0; 979 _back.length = 0; 980 981 _fRange = _assignRange.save; 982 _bRange = _assignRange.save; 983 984 for(int i = 0; i < N && !_fRange.empty; ++i, _fRange.popFront()) 985 _front ~= _fRange.front(); 986 987 for(int i = 0; i < N && !_bRange.empty; ++i, _bRange.popBack()) 988 _back ~= _bRange.back(); 989 990 _back.reverse(); 991 } 992 993 994 995 public: 996 this(R range) 997 { 998 _fRange = range.save; 999 _bRange = range.save; 1000 1001 static if(assE || isRandomAccessRange!R) 1002 _assignRange = range.save; 1003 1004 for(int i = 0; i < N && !_fRange.empty; ++i, _fRange.popFront()) 1005 _front ~= _fRange.front(); 1006 1007 for(int i = 0; i < N && !_bRange.empty; ++i, _bRange.popBack()) 1008 _back ~= _bRange.back(); 1009 1010 _back.reverse(); 1011 } 1012 1013 1014 static if(isInfinite!R) 1015 enum bool empty = false; 1016 else 1017 @property bool empty() 1018 { 1019 return (_front.length < N) || (_back.length < N); 1020 } 1021 1022 1023 void popFront() 1024 { 1025 _front = _front[1..$]; 1026 1027 if(!_fRange.empty){ 1028 _front ~= _fRange.front; 1029 1030 _fRange.popFront(); 1031 _bRange.popFront(); 1032 } 1033 1034 static if(assE || isRandomAccessRange!R) 1035 _assignRange.popFront(); 1036 } 1037 1038 1039 void popBack() 1040 { 1041 _back = _back[0..$-1]; 1042 1043 if(!_bRange.empty){ 1044 _back = [_bRange.back] ~ _back; 1045 1046 _fRange.popBack(); 1047 _bRange.popBack(); 1048 } 1049 1050 static if(assE || isRandomAccessRange!R) 1051 _assignRange.popBack(); 1052 } 1053 1054 1055 @property Segment save() 1056 { 1057 Segment dst = this; 1058 dst._fRange = dst._fRange.save; 1059 dst._bRange = dst._bRange.save; 1060 1061 static if(assE) 1062 dst._assignRange = dst._assignRange.save; 1063 1064 return dst; 1065 } 1066 1067 1068 static if(hasLength!R) 1069 { 1070 @property size_t length() 1071 { 1072 return _fRange.length + ((_front.length == N && _back.length == N) ? 1 : 0); 1073 } 1074 1075 1076 alias length opDollar; 1077 } 1078 1079 1080 static if(hasSlicing!R) 1081 { 1082 Segment opSlice() 1083 { 1084 return save; 1085 } 1086 1087 1088 static if(assE || isRandomAccessRange!R) 1089 auto opSlice(size_t i, size_t j) 1090 { 1091 return segment!N(_assignRange[i..j + (N-1)]); 1092 } 1093 //else 1094 } 1095 1096 1097 @property Tuple!(TypeNuple!(E, N)) front() 1098 { 1099 return (cast(typeof(return)[])(cast(ubyte[])_front))[0]; 1100 } 1101 1102 1103 @property Tuple!(TypeNuple!(E, N)) back() 1104 { 1105 return (cast(typeof(return)[])(cast(ubyte[])_back))[0]; 1106 } 1107 1108 1109 static if(isRandomAccessRange!R) 1110 Tuple!(TypeNuple!(E, N)) opIndex(size_t i) 1111 { 1112 E[] dst; 1113 1114 foreach(j; 0..N) 1115 dst ~= _assignRange[i + j]; 1116 1117 return (cast(typeof(return)[])(cast(ubyte[])dst))[0]; 1118 } 1119 1120 1121 1122 static if(assE) 1123 { 1124 @property void front(Tuple!(TypeNuple!(E, N)) e) 1125 { 1126 R _tmp = _assignRange.save; 1127 _front = [e.field]; 1128 1129 for(int i = 0; i < N; ++i, _tmp.popFront()) 1130 _tmp.front = _front[i]; 1131 1132 reConstruct(); 1133 } 1134 1135 1136 @property void back(Tuple!(TypeNuple!(E, N)) e) 1137 { 1138 R _tmp = _assignRange.save; 1139 _back = [e.field]; 1140 1141 for(int i = N-1; i >= 0; --i, _tmp.popBack()) 1142 _tmp.back = _back[i]; 1143 1144 reConstruct(); 1145 } 1146 1147 static if(isRandomAccessRange!R) 1148 void opIndexAssign(Tuple!(TypeNuple!(E, N)) e, size_t i) 1149 { 1150 foreach(j; 0..N) 1151 _assignRange[i + j] = [e.field][j]; 1152 1153 reConstruct(); 1154 } 1155 } 1156 } 1157 } 1158 1159 unittest 1160 { 1161 //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__); 1162 debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();} 1163 1164 struct TRange{ 1165 int[] a; 1166 @property int front(){return a.front;} 1167 @property bool empty(){return a.empty;} 1168 void popFront(){a.popFront();} 1169 void popBack(){a.popBack();} 1170 @property int back(){return a.back();} 1171 @property TRange save(){return TRange(a.save);} 1172 @property size_t length(){return a.length;} 1173 alias length opDollar; 1174 } 1175 1176 1177 auto r = TRange([0, 1, 2, 3, 4]); 1178 auto sg = segment!2(r); 1179 assert(equal(sg, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)])); 1180 assert(equal(sg.retro, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)].retro)); 1181 assert(sg.length == 4); 1182 1183 sg.popFront(); 1184 assert(equal(sg, [tuple(1, 2), tuple(2, 3), tuple(3, 4)])); 1185 assert(sg.length == 3); 1186 assert(!sg.empty); 1187 1188 auto sv = sg.save; 1189 sv.popFront(); 1190 assert(equal(sg, [tuple(1, 2), tuple(2, 3), tuple(3, 4)])); 1191 assert(equal(sv, [tuple(2, 3), tuple(3, 4)])); 1192 assert(sg.length == 3); 1193 assert(sv.length == 2); 1194 assert(!sg.empty); 1195 assert(!sv.empty); 1196 1197 sg.popFront(); 1198 assert(equal(sg, [tuple(2, 3), tuple(3, 4)])); 1199 assert(sg.length == 2); 1200 assert(!sg.empty); 1201 1202 sg.popFront(); 1203 assert(equal(sg, [tuple(3, 4)])); 1204 assert(sg.length == 1); 1205 assert(!sg.empty); 1206 1207 sg.popFront(); 1208 assert(sg.length == 0); 1209 assert(sg.empty); 1210 } 1211 unittest 1212 { 1213 //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__); 1214 debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();} 1215 1216 struct TRange{ 1217 int[] a; 1218 @property ref int front(){return a.front;} 1219 @property bool empty(){return a.empty;} 1220 void popFront(){a.popFront();} 1221 void popBack(){a.popBack();} 1222 @property ref int back(){return a.back();} 1223 @property TRange save(){return TRange(a.save);} 1224 @property size_t length(){return a.length;} 1225 TRange opSlice(size_t i, size_t j){return TRange(a[i..j]);} 1226 alias length opDollar; 1227 } 1228 1229 1230 auto r = TRange([0, 1, 2, 3, 4]); 1231 auto sg = segment!2(r); 1232 assert(equal(sg, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)])); 1233 assert(equal(retro(sg), [tuple(3, 4), tuple(2, 3), tuple(1, 2), tuple(0, 1)])); 1234 assert(sg.length == 4); 1235 assert(equal(sg[2..4], [tuple(2, 3), tuple(3, 4)])); 1236 1237 auto sgsv = sg.save; 1238 sgsv.popFront(); 1239 assert(equal(sg, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)])); 1240 assert(equal(sgsv, [tuple(1, 2), tuple(2, 3), tuple(3, 4)])); 1241 1242 auto sgsv2 = sg[]; 1243 sgsv2.popFront(); 1244 assert(equal(sg, [tuple(0, 1), tuple(1, 2), tuple(2, 3), tuple(3, 4)])); 1245 assert(equal(sgsv2, [tuple(1, 2), tuple(2, 3), tuple(3, 4)])); 1246 1247 1248 sg.front = tuple(2, 2); 1249 assert(equal(sg, [tuple(2, 2), tuple(2, 2), tuple(2, 3), tuple(3, 4)])); 1250 assert(equal(retro(sg), [tuple(3, 4), tuple(2, 3), tuple(2, 2), tuple(2, 2)])); 1251 1252 sg.popFront(); 1253 assert(equal(sg, [tuple(2, 2), tuple(2, 3), tuple(3, 4)])); 1254 assert(equal(retro(sg), [tuple(3, 4), tuple(2, 3), tuple(2, 2)])); 1255 assert(sg.length == 3); 1256 assert(!sg.empty); 1257 1258 sg.popFront(); 1259 assert(equal(sg, [tuple(2, 3), tuple(3, 4)])); 1260 assert(equal(retro(sg), [tuple(3, 4), tuple(2, 3)])); 1261 assert(sg.length == 2); 1262 assert(!sg.empty); 1263 1264 sg.popFront(); 1265 assert(equal(sg, [tuple(3, 4)])); 1266 assert(equal(retro(sg), [tuple(3, 4)])); 1267 assert(sg.length == 1); 1268 assert(!sg.empty); 1269 1270 sg.front = tuple(2, 5); 1271 assert(equal(sg, [tuple(2, 5)])); 1272 assert(equal(retro(sg), [tuple(2, 5)])); 1273 assert(sg.length == 1); 1274 assert(!sg.empty); 1275 1276 sg.front = tuple(2, 1); 1277 assert(equal(sg, [tuple(2, 1)])); 1278 assert(sg.length == 1); 1279 assert(!sg.empty); 1280 1281 sg.popFront(); 1282 assert(sg.length == 0); 1283 assert(sg.empty); 1284 } 1285 unittest 1286 { 1287 //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__); 1288 debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();} 1289 1290 struct TRange{ 1291 int[] a; 1292 @property ref int front(){return a.front;} 1293 @property bool empty(){return a.empty;} 1294 void popFront(){a.popFront();} 1295 void popBack(){a.popBack();} 1296 @property ref int back(){return a.back();} 1297 @property TRange save(){return TRange(a.save);} 1298 @property size_t length(){return a.length;} 1299 TRange opSlice(size_t i, size_t j){return TRange(a[i..j]);} 1300 alias length opDollar; 1301 } 1302 1303 1304 auto r = TRange([0, 1, 2, 3, 4]); 1305 auto sg = segment!3(r); 1306 assert(equal(sg, [tuple(0, 1, 2), tuple(1, 2, 3), tuple(2, 3, 4)])); 1307 assert(equal(retro(sg), [tuple(0, 1, 2), tuple(1, 2, 3), tuple(2, 3, 4)].retro)); 1308 assert(sg.length == 3); 1309 assert(equal(sg[2..3], [tuple(2, 3, 4)])); 1310 1311 sg.front = tuple(2, 2, 2); 1312 assert(equal(sg, [tuple(2, 2, 2), tuple(2, 2, 3), tuple(2, 3, 4)])); 1313 assert(equal(sg.retro, [tuple(2, 2, 2), tuple(2, 2, 3), tuple(2, 3, 4)].retro)); 1314 1315 sg.popFront(); 1316 assert(equal(sg, [tuple(2, 2, 3), tuple(2, 3, 4)])); 1317 assert(equal(sg.retro, [tuple(2, 2, 3), tuple(2, 3, 4)].retro)); 1318 assert(sg.length == 2); 1319 assert(!sg.empty); 1320 1321 sg.back = tuple(4, 4, 4); 1322 assert(equal(sg, [tuple(2, 4, 4), tuple(4, 4, 4)])); 1323 assert(equal(sg.retro, [tuple(2, 4, 4), tuple(4, 4, 4)].retro)); 1324 assert(sg.length == 2); 1325 assert(!sg.empty); 1326 1327 sg.popFront(); 1328 assert(equal(sg, [tuple(4, 4, 4)])); 1329 assert(equal(sg.retro, [tuple(4, 4, 4)].retro)); 1330 assert(sg.length == 1); 1331 assert(!sg.empty); 1332 1333 sg.popFront(); 1334 assert(sg.length == 0); 1335 assert(sg.empty); 1336 } 1337 unittest 1338 { 1339 //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__); 1340 debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();} 1341 1342 struct TRange{ 1343 size_t f, b; 1344 int[] s; 1345 1346 this(int[] r){ 1347 f = 0; 1348 s = r; 1349 b = s.length - 1; 1350 } 1351 1352 @property ref int front(){return s[f];} 1353 enum bool empty = false; 1354 void popFront(){++f; if(f == s.length)f = 0;} 1355 void popBack(){b = (b == 0 ? s.length - 1 : b-1);} 1356 @property ref int back(){return s[b];} 1357 @property typeof(this) save(){return this;} 1358 auto opSlice(size_t i, size_t j){auto dst = this; dst.popFrontN(i); return dst.take(j - i);} 1359 ref int opIndex(size_t i){return s[(i+f)%s.length];} 1360 } 1361 1362 alias TRange Range; 1363 static assert(isInputRange!TRange); 1364 1365 auto r = TRange([0, 1, 2, 3, 4]); 1366 auto sg = segment!3(r); 1367 assert(equal(sg.take(3), [tuple(0, 1, 2), tuple(1, 2, 3), tuple(2, 3, 4)])); 1368 assert(equal(retro(sg).take(3), [tuple(2, 3, 4), tuple(1, 2, 3), tuple(0, 1, 2)])); 1369 assert(sg[2] == tuple(2, 3, 4)); 1370 //assert(equal(sg[2..3], [tuple(2, 3, 4)])); 1371 1372 sg.front = tuple(2, 2, 2); //[2, 2, 2, 3, 4] 1373 assert(equal(sg.take(3), [tuple(2, 2, 2), tuple(2, 2, 3), tuple(2, 3, 4)])); 1374 assert(equal(retro(sg).take(3), [tuple(2, 3, 4), tuple(2, 2, 3), tuple(2, 2, 2)])); 1375 1376 sg.popFront(); 1377 assert(equal(sg.take(3), [tuple(2, 2, 3), tuple(2, 3, 4), tuple(3, 4, 2)])); 1378 assert(equal(retro(sg).take(3), [tuple(2, 3, 4), tuple(2, 2, 3), tuple(2, 2, 2)])); 1379 assert(!sg.empty); 1380 1381 sg[1] = tuple(3, 3, 3); //[2, 2, 3, 3, 3] 1382 assert(equal(sg.take(3), [tuple(2, 3, 3), tuple(3, 3, 3), tuple(3, 3, 2)])); 1383 assert(equal(sg.retro.take(3), [tuple(3, 3, 3), tuple(2, 3, 3), tuple(2, 2, 3)])); 1384 assert(!sg.empty); 1385 1386 sg.back = tuple(2, 3, 4);//[2, 2, 2, 3, 4] 1387 assert(equal(sg.take(3), [tuple(2, 2, 3), tuple(2, 3, 4), tuple(3, 4, 2)])); 1388 assert(equal(sg.retro.take(3), [tuple(2, 3, 4), tuple(2, 2, 3), tuple(2, 2, 2)])); 1389 assert(!sg.empty); 1390 1391 sg.popBack(); 1392 assert(equal(sg.take(3), [tuple(2, 2, 3), tuple(2, 3, 4), tuple(3, 4, 2)])); 1393 assert(equal(sg.retro.take(3), [tuple(2, 2, 3), tuple(2, 2, 2), tuple(4, 2, 2)])); 1394 assert(!sg.empty); 1395 } 1396 1397 1398 /** 1399 Dynamic Array Segment 1400 */ 1401 template dsegment(Range) 1402 if(isInputRange!Range) 1403 { 1404 alias E = Unqual!(ElementType!Range); 1405 1406 1407 Segment dsegment(Range r, size_t n) 1408 { 1409 Segment dst; 1410 1411 dst._r = r; 1412 dst._arr = new E[n]; 1413 dst._empty = false; 1414 1415 foreach(i; 0 .. n){ 1416 if(dst._r.empty){ 1417 dst._empty = true; 1418 break; 1419 } 1420 1421 dst._arr[i] = dst._r.front; 1422 dst._r.popFront(); 1423 } 1424 1425 return dst; 1426 } 1427 1428 1429 struct Segment 1430 { 1431 E[] front() @property { return _arr; } 1432 const(E)[] front() const @property { return _arr; } 1433 1434 1435 static if(isInfinite!Range) 1436 enum bool empty = false; 1437 else 1438 { 1439 bool empty() const @property { return _empty; } 1440 } 1441 1442 1443 void popFront() 1444 { 1445 if(_r.empty){ 1446 _empty = true; 1447 return; 1448 } 1449 1450 foreach(i; 1 .. _arr.length) 1451 _arr[i-1] = _arr[i]; 1452 1453 _arr[$-1] = _r.front; 1454 _r.popFront(); 1455 } 1456 1457 1458 static if(isForwardRange!Range) 1459 { 1460 typeof(this) save() @property 1461 { 1462 typeof(this) dst; 1463 1464 dst._r = this._r.save; 1465 dst._arr = this._arr.dup; 1466 dst._empty = this._empty; 1467 1468 return dst; 1469 } 1470 } 1471 1472 1473 private: 1474 Range _r; 1475 E[] _arr; 1476 bool _empty; 1477 } 1478 } 1479 1480 unittest 1481 { 1482 //debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__); 1483 debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();} 1484 1485 static struct TRange 1486 { 1487 int _front, _end; 1488 @property int front(){return _front;} 1489 void popFront(){_front += 1;} 1490 @property bool empty(){return _front == _end;} 1491 @property TRange save(){return this;} 1492 @property size_t length(){return _end - _front;} 1493 alias length opDollar; 1494 } 1495 1496 auto tr = TRange(0, 5); 1497 auto sg2 = dsegment(tr, 2); 1498 import std.stdio; 1499 assert(equal(sg2, [[0, 1], [1, 2], [2, 3], [3, 4]])); 1500 } 1501 1502 1503 /** 1504 concats elements 1505 */ 1506 auto concat(R)(R range) if (isRangeOfRanges!R) 1507 { 1508 static struct Concat 1509 { 1510 private: 1511 R _range; 1512 alias ElementType!R ET0; 1513 alias ElementType!ET0 ET1; 1514 ET0 _subrange; 1515 1516 static if(isRangeOfRanges!(R, isBidirectionalRange)) 1517 { 1518 ET0 _backSubrange; 1519 } 1520 1521 public: 1522 static if(isInfinite!R) 1523 enum bool empty = false; 1524 else 1525 { 1526 @property 1527 bool empty() 1528 { 1529 return _range.empty; 1530 } 1531 } 1532 1533 1534 @property 1535 auto ref front() 1536 { 1537 return _subrange.front; 1538 } 1539 1540 1541 static if(hasAssignableElements!ET0) 1542 { 1543 @property 1544 void front(ET1 v) 1545 { 1546 _subrange.front = v; 1547 } 1548 } 1549 1550 1551 /* 1552 static if(isRangeOfRange!(R, isForwardRange)) 1553 { 1554 @property 1555 Concat save() 1556 { 1557 return this; 1558 } 1559 } 1560 */ 1561 1562 1563 void popFront() 1564 { 1565 if (!_subrange.empty) _subrange.popFront; 1566 1567 while(_subrange.empty && !_range.empty){ 1568 _range.popFront; 1569 1570 if (!_range.empty) 1571 _subrange = _range.front; 1572 } 1573 } 1574 1575 1576 static if (isRangeOfRanges!(R, isBidirectionalRange)) 1577 { 1578 @property 1579 auto ref back() 1580 { 1581 return _backSubrange.back; 1582 } 1583 1584 1585 static if(hasAssignableElements!ET0) 1586 { 1587 @property 1588 void back(ET1 v) 1589 { 1590 _backSubrange.back = v; 1591 } 1592 } 1593 1594 1595 void popBack() 1596 { 1597 if (!_backSubrange.empty) _backSubrange.popBack; 1598 1599 while (_backSubrange.empty && !_range.empty) { 1600 _range.popBack; 1601 if (!_range.empty) _backSubrange = _range.back; 1602 } 1603 } 1604 1605 1606 auto retro() @property 1607 { 1608 static struct RetroConcat 1609 { 1610 auto ref front() @property 1611 { 1612 return _r.back; 1613 } 1614 1615 1616 auto ref back() @property 1617 { 1618 return _r.front; 1619 } 1620 1621 1622 static if(hasAssignableElements!ET0) 1623 { 1624 void front(ET1 v) @property 1625 { 1626 _r.back = v; 1627 } 1628 1629 1630 void back(ET1 v) @property 1631 { 1632 _r.front = v; 1633 } 1634 } 1635 1636 1637 void popFront() 1638 { 1639 _r.popBack(); 1640 } 1641 1642 1643 void popBack() 1644 { 1645 _r.popFront(); 1646 } 1647 1648 1649 static if(isInfinite!R) 1650 enum bool empty = false; 1651 else 1652 bool empty() @property 1653 { 1654 return _r.empty; 1655 } 1656 1657 1658 // save.. 1659 1660 1661 auto retro() @property 1662 { 1663 return _r; 1664 } 1665 1666 1667 private: 1668 Concat _r; 1669 } 1670 1671 1672 return RetroConcat(this); 1673 } 1674 } 1675 } 1676 1677 1678 Concat dst = {_range : range}; 1679 1680 enum initMethod = 1681 q{ 1682 if (!dst._range.empty){ 1683 %1$s = dst._range.%2$s; 1684 while (%1$s.empty && !dst._range.empty){ 1685 dst._range.%3$s; 1686 1687 if (!dst._range.empty) 1688 %1$s = dst._range.%2$s; 1689 } 1690 } 1691 }; 1692 1693 mixin(format(initMethod, "dst._subrange", "front", "popFront")); 1694 1695 static if (isRangeOfRanges!(R, isBidirectionalRange)) 1696 { 1697 mixin(format(initMethod, "dst._backSubrange", "back", "popBack")); 1698 } 1699 1700 return dst; 1701 } 1702 1703 /// ditto 1704 R concat(R)(R range) 1705 if(isSimpleRange!R) 1706 { 1707 return range; 1708 } 1709 1710 /// 1711 unittest 1712 { 1713 debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__); 1714 debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();} 1715 1716 int[][] r1 = [[0, 1, 2, 3], [4, 5, 6], [7, 8], [9], []]; 1717 auto c = concat(r1); 1718 assert(equal(c, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])); 1719 assert(equal(c.retro(), retro([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))); // bidir range 1720 assert(equal(c.retro.retro, c)); 1721 1722 assert(equal(concat(c), c)); 1723 1724 auto r2 = [0, 1, 2, 3, 4, 5]; 1725 assert(equal(r2.map!"[a, 2]".concat, [0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5, 2])); 1726 assert(equal(r2[0 .. 4].map!(a => repeat(a, a)).concat, [1, 2, 2, 3, 3, 3])); 1727 assert(equal(r2[0 .. 3].repeat(2).map!(map!"a + 1").concat, [1, 2, 3, 1, 2, 3])); 1728 1729 int[] emp; 1730 assert(emp.repeat(15).concat.empty); 1731 assert(emp.concat.empty); 1732 } 1733 1734 1735 /// 1736 auto flatten(size_t N = size_t.max, R)(R r) 1737 if(isInputRange!R) 1738 { 1739 static if(N > 0 && isRangeOfRanges!R) 1740 return r.concat.flatten!(N-1); 1741 else 1742 return r; 1743 } 1744 1745 /// 1746 unittest 1747 { 1748 auto d1 = [0, 1, 2, 3, 4, 5, 6, 7, 8]; 1749 assert(equal(d1.flatten, d1)); 1750 assert(equal(d1.flatten!0, d1)); 1751 1752 auto d2 = [[0, 1], [], [2, 3], [4, 5, 6, 7], [8]]; 1753 assert(equal(d2.flatten, d1)); 1754 assert(equal(d2.flatten!1, d1)); 1755 assert(equal(d2.flatten!0, d2)); 1756 1757 auto d3 = [[[0, 1], [], [2, 3]], [[4, 5, 6, 7], [8]]]; 1758 assert(equal(d3.flatten, d1)); 1759 assert(equal(d3.flatten!0, d3)); 1760 assert(equal(d3.flatten!1, d2)); 1761 assert(equal(d3.flatten!2, d1)); 1762 } 1763 1764 1765 /** 1766 Haskell等の言語での$(D takeWhile)の実装です。 1767 この実装では、predは任意個数の引数を取ることができます。 1768 たとえば、2引数関数の場合、第一引数にはレンジの先頭の値が、第二引数にはレンジの次の値が格納されます。 1769 */ 1770 auto takeWhile(alias pred, R, T...)(R range, T args) 1771 if(isInputRange!R) 1772 { 1773 template Parameter(U...) 1774 { 1775 enum bool empty = false; 1776 alias front = U; 1777 alias tail() = Parameter!(ElementType!R, U); 1778 } 1779 1780 alias _pred = naryFun!pred; 1781 enum arityN = argumentInfo!(_pred, Parameter!T).arity - T.length; 1782 1783 static if(arityN <= 1) 1784 return TakeWhileResult!(_pred, arityN, R, T)(range, args); 1785 else 1786 return TakeWhileResult!(_pred, arityN, typeof(segment!arityN(range)), T)(segment!arityN(range), args); 1787 } 1788 1789 private struct TakeWhileResult(alias _pred, size_t arityN, SegR, T...) 1790 { 1791 @property 1792 bool empty() 1793 { 1794 if(_r.empty) 1795 return true; 1796 1797 static if(arityN == 0) 1798 return !_pred(_subArgs); 1799 else static if(arityN == 1) 1800 return !_pred(_r.front, _subArgs); 1801 else 1802 return !_pred(_r.front.field, _subArgs); 1803 } 1804 1805 1806 @property 1807 auto front() 1808 { 1809 static if(arityN <= 1) 1810 return _r.front; 1811 else 1812 return _r.front.field[0]; 1813 } 1814 1815 1816 void popFront() 1817 { 1818 _r.popFront(); 1819 } 1820 1821 1822 static if(isForwardRange!(typeof(_r))) 1823 { 1824 @property 1825 auto save() 1826 { 1827 return TakeWhileResult!(_pred, arityN, typeof(_r.save), T)(_r.save, _subArgs); 1828 } 1829 } 1830 1831 private: 1832 SegR _r; 1833 T _subArgs; 1834 } 1835 1836 /// ditto 1837 unittest 1838 { 1839 debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__); 1840 debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();} 1841 1842 int[] em; 1843 assert(takeWhile!"true"(em).empty); 1844 1845 auto r1 = [1, 2, 3, 4, 3, 2, 1]; 1846 auto tw1 = takeWhile!"a < b"(r1); 1847 assert(equal(tw1, [1, 2, 3])); 1848 1849 auto tw2 = takeWhile!"a < b && b < c"(r1); 1850 assert(equal(tw2, [1, 2])); 1851 1852 auto tw3 = takeWhile!"a == (b - c)"(r1, 1); 1853 assert(equal(tw3, [1, 2, 3])); 1854 1855 auto tw4 = takeWhile!"true"(r1); 1856 assert(equal(tw4, r1)); 1857 1858 auto tw5 = takeWhile!"false"(r1); 1859 assert(tw5.empty); 1860 } 1861 1862 1863 1864 /** 1865 受け取ったレンジの要素をそれぞれ連続してn回繰り返すようなレンジを返します。 1866 */ 1867 auto resampling(R)(R range, size_t n) 1868 { 1869 alias E = ElementType!R; 1870 1871 static struct SamplerResult 1872 { 1873 E front() @property { return _f; } 1874 1875 1876 void popFront() 1877 { 1878 ++_cnt; 1879 if(_cnt == _n){ 1880 if(!_r.empty){ 1881 _f = _r.front; 1882 _r.popFront(); 1883 _cnt = 0; 1884 } 1885 } 1886 } 1887 1888 1889 bool empty() const 1890 { 1891 return (_n == 0) || (_cnt == _n && _r.empty); 1892 } 1893 1894 1895 private: 1896 size_t _cnt; 1897 size_t _n; 1898 R _r; 1899 E _f; 1900 } 1901 1902 if(range.empty) 1903 return SamplerResult.init; 1904 1905 auto f = range.front; 1906 range.popFront(); 1907 1908 return SamplerResult(0, n, range, f); 1909 } 1910 1911 /// 1912 unittest 1913 { 1914 debug scope(failure) writefln("unittest Failure :%s(%s)", __FILE__, __LINE__); 1915 debug scope(success) {writefln("Unittest Success :%s(%s)", __FILE__, __LINE__); stdout.flush();} 1916 1917 import std.stdio; 1918 uint[] arr = [0, 1, 2]; 1919 //writeln(arr.resampling(3)); 1920 assert(arr.resampling(3).equal([0,0,0,1,1,1,2,2,2,])); 1921 1922 assert(arr.resampling(0).empty); 1923 1924 uint[] emp = []; 1925 assert(emp.resampling(3).empty); 1926 } 1927 1928 1929 /** 1930 std.range.iotaを汎用的にしたものです. 1931 */ 1932 auto giota(alias add = "a + b", alias pred = "a == b", S, E, D)(S start, E end, D diff) 1933 if(is(typeof((S s, E e, D d){ s = binaryFun!add(s, d); if(binaryFun!pred(s, e)){} }))) 1934 { 1935 static struct Iota 1936 { 1937 inout(S) front() inout @property { return _value; } 1938 bool empty() @property { return !!binaryFun!pred(_value, _end); } 1939 void popFront() { _value = binaryFun!add(_value, _diff); } 1940 1941 private: 1942 S _value; 1943 E _end; 1944 D _diff; 1945 } 1946 1947 1948 return Iota(start, end, diff); 1949 } 1950 1951 1952 /// ditt 1953 auto giotaInf(alias add = "a + b", S, D)(S start, D diff) 1954 if(is(typeof((S s, D d){ s = binaryFun!add(s, d); }))) 1955 { 1956 static struct IotaInf 1957 { 1958 inout(S) front() inout @property { return _value; } 1959 enum bool empty = false; 1960 void popFront() { _value = binaryFun!add(_value, _diff); } 1961 1962 private: 1963 S _value; 1964 D _diff; 1965 } 1966 1967 1968 return IotaInf(start, diff); 1969 } 1970 1971 1972 /// 1973 unittest 1974 { 1975 import std.datetime; 1976 import core.time; 1977 1978 auto ds1 = giota(Date(2004, 1, 1), Date(2005, 1, 1), days(1)); 1979 assert(ds1.walkLength() == 366); 1980 1981 1982 auto ds2 = giotaInf(Date(2004, 1, 1), days(2)); 1983 assert(ds2.front == Date(2004, 1, 1)); ds2.popFront(); 1984 assert(ds2.front == Date(2004, 1, 3)); ds2.popFront(); 1985 assert(ds2.front == Date(2004, 1, 5)); 1986 } 1987 1988 1989 auto whenEmpty(alias func, R)(R range) 1990 if(isInputRange!R && isCallable!func) 1991 { 1992 static struct ResultRangeOfWhenEmpty 1993 { 1994 auto ref front() { return _r.front; } 1995 1996 static if(isInfinite!R) 1997 enum bool empty = false; 1998 else 1999 { 2000 bool empty() @property { return _r.empty; } 2001 } 2002 2003 2004 void popFront() 2005 { 2006 _r.popFront(); 2007 if(_r.empty){ 2008 func(); 2009 } 2010 } 2011 2012 private: 2013 R _r; 2014 } 2015 2016 2017 ResultRangeOfWhenEmpty res; 2018 res._r = range; 2019 return res; 2020 } 2021 2022 /// 2023 unittest 2024 { 2025 { 2026 static auto arrA = [1, 2, 3]; 2027 auto r = arrA.whenEmpty!((){ arrA = null; }); 2028 assert(equal(r, arrA)); 2029 assert(arrA is null); 2030 } 2031 { 2032 static auto arrB = [1, 2, 3]; 2033 auto r = arrB.whenEmpty!((){ arrB = null; }); 2034 //assert(equal(r, arr)); 2035 r.popFront(); r.popFront(); 2036 assert(arrB !is null); 2037 r.popFront(); 2038 assert(arrB is null); 2039 } 2040 } 2041 2042 2043 auto whenEmpty(R, Fn)(R range, Fn fn) 2044 if(isCallable!Fn) 2045 { 2046 static struct ResultRangeOfWhenEmpty 2047 { 2048 auto ref front() { return _r.front; } 2049 2050 static if(isInfinite!R) 2051 enum bool empty = false; 2052 else 2053 { 2054 bool empty() @property { return _r.empty; } 2055 } 2056 2057 2058 void popFront() 2059 { 2060 _r.popFront(); 2061 if(_r.empty){ 2062 _fn(); 2063 } 2064 } 2065 2066 private: 2067 R _r; 2068 Fn _fn; 2069 } 2070 2071 2072 ResultRangeOfWhenEmpty res; 2073 res._r = range; 2074 res._fn = fn; 2075 return res; 2076 } 2077 2078 /// 2079 unittest 2080 { 2081 { 2082 auto arr = [1, 2, 3]; 2083 auto r = arr.whenEmpty((){ arr = null; }); 2084 assert(equal(r, arr)); 2085 assert(arr is null); 2086 } 2087 { 2088 auto arr = [1, 2, 3]; 2089 auto r = arr.whenEmpty((){ arr = null; }); 2090 //assert(equal(r, arr)); 2091 r.popFront(); r.popFront(); 2092 assert(arr !is null); 2093 r.popFront(); 2094 assert(arr is null); 2095 } 2096 }