Changeset 1738
- Timestamp:
- 07/09/10 03:47:03 (14 years ago)
- Files:
-
- trunk/phobos/std/algorithm.d (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/phobos/std/algorithm.d
r1725 r1738 463 463 Example: 464 464 ---- 465 465 int[] a = [ 1, 2, 3, 4 ]; 466 466 fill(a, 5); 467 467 assert(a == [ 5, 5, 5, 5 ]); 468 468 ---- 469 469 */ 470 470 void fill(Range, Value)(Range range, Value filler) 471 471 if (isForwardRange!Range && is(typeof(range.front = filler))) 472 472 { 473 for (; !range.empty; range.popFront) 474 { 473 alias ElementType!Range T; 474 static if (hasElaborateCopyConstructor!T || !isDynamicArray!Range) 475 { 476 for (; !range.empty; range.popFront) 477 { 478 range.front = filler; 479 } 480 } 481 else 482 { 483 if (range.empty) return; 484 // Range is a dynamic array of bald values, just fill memory 485 // Can't use memcpy or memmove coz ranges overlap 475 486 range.front = filler; 487 auto bytesToFill = T.sizeof * (range.length - 1); 488 auto bytesFilled = T.sizeof; 489 while (bytesToFill) 490 { 491 auto fillNow = min(bytesToFill, bytesFilled); 492 memcpy(cast(void*) range.ptr + bytesFilled, 493 cast(void*) range.ptr, 494 fillNow); 495 bytesToFill -= fillNow; 496 bytesFilled += fillNow; 497 } 476 498 } 477 499 } 478 500 479 501 unittest 480 502 { 481 503 int[] a = [ 1, 2, 3 ]; 482 504 fill(a, 6); 483 assert(a == [ 6, 6, 6 ] );505 assert(a == [ 6, 6, 6 ], text(a)); 484 506 void fun0() 485 507 { 486 508 foreach (i; 0 .. 1000) 487 509 { 488 510 foreach (ref e; a) e = 6; 489 511 } 490 512 } 491 513 void fun1() { foreach (i; 0 .. 1000) fill(a, 6); } 492 514 //void fun2() { foreach (i; 0 .. 1000) fill2(a, 6); } 493 515 //writeln(benchmark!(fun0, fun1, fun2)(10000)); … … 519 541 range.front = t.front; 520 542 } 521 543 } 522 544 523 545 unittest 524 546 { 525 547 int[] a = [ 1, 2, 3, 4, 5 ]; 526 548 int[] b = [1, 2]; 527 549 fill(a, b); 528 550 assert(a == [ 1, 2, 1, 2, 1 ]); 551 } 552 553 /** 554 Fills a range with a value. Assumes that the range does not currently 555 contain meaningful content. This is of interest for structs that 556 define copy constructors (for all other types, fill and 557 uninitializedFill are equivalent). 558 559 Example: 560 ---- 561 struct S { ... } 562 S[] s = (cast(S*) malloc(5 * S.sizeof))[0 .. 5]; 563 uninitializedFill(s, 42); 564 assert(s == [ 42, 42, 42, 42, 42 ]); 565 ---- 566 */ 567 void uninitializedFill(Range, Value)(Range range, Value filler) 568 if (isForwardRange!Range && is(typeof(range.front = filler))) 569 { 570 alias ElementType!Range T; 571 if (range.empty) return; 572 static if (hasElaborateCopyConstructor!T) 573 { 574 // Must construct stuff by the book 575 for (; !range.empty; range.popFront) 576 { 577 emplace!T((cast(void*) &range.front)[0 .. T.sizeof], filler); 578 } 579 } 580 else 581 { 582 // Doesn't matter whether fill is initialized or not 583 return fill(range, filler); 584 } 585 } 586 587 unittest 588 { 589 int[] a = [ 1, 2, 3 ]; 590 uninitializedFill(a, 6); 591 assert(a == [ 6, 6, 6 ]); 592 void fun0() 593 { 594 foreach (i; 0 .. 1000) 595 { 596 foreach (ref e; a) e = 6; 597 } 598 } 599 void fun1() { foreach (i; 0 .. 1000) fill(a, 6); } 600 //void fun2() { foreach (i; 0 .. 1000) fill2(a, 6); } 601 //writeln(benchmark!(fun0, fun1, fun2)(10000)); 602 } 603 604 /** 605 Initializes all elements of a range with their $(D .init) 606 value. Assumes that the range does not currently contain meaningful 607 content. 608 609 Example: 610 ---- 611 struct S { ... } 612 S[] s = (cast(S*) malloc(5 * S.sizeof))[0 .. 5]; 613 initialize(s); 614 assert(s == [ 0, 0, 0, 0, 0 ]); 615 ---- 616 */ 617 void initializeAll(Range)(Range range) 618 if (isForwardRange!Range && is(typeof(range.front = range.front))) 619 { 620 alias ElementType!Range T; 621 static assert(is(typeof(&(range.front()))) || !hasElaborateAssign!T, 622 "Cannot initialize a range that does not expose" 623 " references to its elements"); 624 static if (!isDynamicArray!Range) 625 { 626 static if (is(typeof(&(range.front())))) 627 { 628 // Range exposes references 629 for (; !range.empty; range.popFront) 630 { 631 memcpy(&(range.front()), &T.init, T.sizeof); 632 } 633 } 634 else 635 { 636 // Go the slow route 637 for (; !range.empty; range.popFront) 638 { 639 range.front = filler; 640 } 641 } 642 } 643 else 644 { 645 fill(range, T.init); 646 } 647 } 648 649 unittest 650 { 651 int[] a = [ 1, 2, 3 ]; 652 uninitializedFill(a, 6); 653 assert(a == [ 6, 6, 6 ]); 654 void fun0() 655 { 656 foreach (i; 0 .. 1000) 657 { 658 foreach (ref e; a) e = 6; 659 } 660 } 661 void fun1() { foreach (i; 0 .. 1000) fill(a, 6); } 662 //void fun2() { foreach (i; 0 .. 1000) fill2(a, 6); } 663 //writeln(benchmark!(fun0, fun1, fun2)(10000)); 529 664 } 530 665 531 666 // filter 532 667 /** 533 668 Implements the homonym function present in various programming 534 669 languages of functional flavor. The call $(D filter!(fun)(range)) 535 670 returns a new range only containing elements $(D x) in $(D r) for 536 671 which $(D pred(x)) is $(D true). 537 672 538 673 Example: … … 3222 3357 Example: 3223 3358 ---- 3224 3359 int[] a = [ 1, 5, 8, 9, 10, 1, 2, 0 ]; 3225 3360 auto b = new int[a.length]; 3226 3361 auto c = copy(filter!("(a & 1) == 1")(a), b); 3227 3362 assert(b[0 .. $ - c.length] == [ 1, 5, 9, 1 ]); 3228 3363 ---- 3229 3364 3230 3365 */ 3231 3366 Range2 copy(Range1, Range2)(Range1 source, Range2 target) 3232 if (isInputRange!(Range1) 3233 && isOutputRange!(Range2, ElementType!(Range1))) 3234 { 3235 foreach (e; source) 3236 { 3237 target.put(e); 3367 if (isInputRange!Range1 && isOutputRange!(Range2, ElementType!Range1)) 3368 { 3369 for (; !source.empty; source.popFront()) 3370 { 3371 put(target, source.front); 3238 3372 } 3239 3373 return target; 3240 3374 } 3241 3375 3242 3376 unittest 3243 3377 { 3244 3378 { 3245 3379 int[] a = [ 1, 5 ]; 3246 3380 int[] b = [ 9, 8 ]; 3247 3381 int[] c = new int[a.length + b.length + 10]; … … 3400 3534 Example: 3401 3535 3402 3536 ---- 3403 3537 auto arr = [4, 5, 6, 7, 1, 2, 3]; 3404 3538 auto p = rotate(arr, begin(arr) + 4); 3405 3539 assert(p - begin(arr) == 3); 3406 3540 assert(arr == [ 1, 2, 3, 4, 5, 6, 7 ]); 3407 3541 ---- 3408 3542 */ 3409 3543 size_t bringToFront(Range1, Range2)(Range1 front, Range2 back) 3410 if (isForwardRange! (Range1) && isForwardRange!(Range2))3544 if (isForwardRange!Range1 && isForwardRange!Range2) 3411 3545 { 3412 3546 enum bool sameHeadExists = is(typeof(front.sameHead(back))); 3413 3547 size_t result; 3414 3548 for (;;) 3415 3549 { 3416 3550 if (back.empty || front.empty) return result; 3417 3551 static if (sameHeadExists) 3418 3552 if (front.sameHead(back)) return result; 3419 3553 3420 3554 auto front2 = front.save;
