Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 1738

Show
Ignore:
Timestamp:
07/09/10 03:47:03 (14 years ago)
Author:
andrei
Message:

Optimization for fill; added uninitializedFill and initializeAll; changed copy to work with put(r, e) instead of r.put(e).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/phobos/std/algorithm.d

    r1725 r1738  
    463463Example: 
    464464---- 
    465465int[] a = [ 1, 2, 3, 4 ]; 
    466466fill(a, 5); 
    467467assert(a == [ 5, 5, 5, 5 ]); 
    468468---- 
    469469 */ 
    470470void fill(Range, Value)(Range range, Value filler) 
    471471if (isForwardRange!Range && is(typeof(range.front = filler))) 
    472472{ 
    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 
    475486        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        } 
    476498    } 
    477499} 
    478500 
    479501unittest 
    480502{ 
    481503    int[] a = [ 1, 2, 3 ]; 
    482504    fill(a, 6); 
    483     assert(a == [ 6, 6, 6 ]); 
     505    assert(a == [ 6, 6, 6 ], text(a)); 
    484506    void fun0() 
    485507    { 
    486508        foreach (i; 0 .. 1000) 
    487509        { 
    488510            foreach (ref e; a) e = 6; 
    489511        } 
    490512    } 
    491513    void fun1() { foreach (i; 0 .. 1000) fill(a, 6); } 
    492514    //void fun2() { foreach (i; 0 .. 1000) fill2(a, 6); } 
    493515    //writeln(benchmark!(fun0, fun1, fun2)(10000)); 
     
    519541        range.front = t.front; 
    520542    } 
    521543} 
    522544 
    523545unittest 
    524546{ 
    525547    int[] a = [ 1, 2, 3, 4, 5 ]; 
    526548    int[] b = [1, 2]; 
    527549    fill(a, b); 
    528550    assert(a == [ 1, 2, 1, 2, 1 ]); 
     551} 
     552 
     553/** 
     554Fills a range with a value. Assumes that the range does not currently 
     555contain meaningful content. This is of interest for structs that 
     556define copy constructors (for all other types, fill and 
     557uninitializedFill are equivalent). 
     558 
     559Example: 
     560---- 
     561struct S { ... } 
     562S[] s = (cast(S*) malloc(5 * S.sizeof))[0 .. 5]; 
     563uninitializedFill(s, 42); 
     564assert(s == [ 42, 42, 42, 42, 42 ]); 
     565---- 
     566 */ 
     567void uninitializedFill(Range, Value)(Range range, Value filler) 
     568if (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 
     587unittest 
     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/** 
     605Initializes all elements of a range with their $(D .init) 
     606value. Assumes that the range does not currently contain meaningful 
     607content. 
     608 
     609Example: 
     610---- 
     611struct S { ... } 
     612S[] s = (cast(S*) malloc(5 * S.sizeof))[0 .. 5]; 
     613initialize(s); 
     614assert(s == [ 0, 0, 0, 0, 0 ]); 
     615---- 
     616 */ 
     617void initializeAll(Range)(Range range) 
     618if (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 
     649unittest 
     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)); 
    529664} 
    530665 
    531666// filter 
    532667/** 
    533668Implements the homonym function present in various programming 
    534669languages of functional flavor. The call $(D filter!(fun)(range)) 
    535670returns a new range only containing elements $(D x) in $(D r) for 
    536671which $(D pred(x)) is $(D true). 
    537672 
    538673Example: 
     
    32223357Example: 
    32233358---- 
    32243359int[] a = [ 1, 5, 8, 9, 10, 1, 2, 0 ]; 
    32253360auto b = new int[a.length]; 
    32263361auto c = copy(filter!("(a & 1) == 1")(a), b); 
    32273362assert(b[0 .. $ - c.length] == [ 1, 5, 9, 1 ]); 
    32283363---- 
    32293364 
    32303365 */ 
    32313366Range2 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); 
     3367if (isInputRange!Range1 && isOutputRange!(Range2, ElementType!Range1)) 
     3368
     3369    for (; !source.empty; source.popFront()) 
     3370    { 
     3371        put(target, source.front); 
    32383372    } 
    32393373    return target; 
    32403374} 
    32413375 
    32423376unittest 
    32433377{ 
    32443378    { 
    32453379        int[] a = [ 1, 5 ]; 
    32463380        int[] b = [ 9, 8 ]; 
    32473381        int[] c = new int[a.length + b.length + 10]; 
     
    34003534Example: 
    34013535 
    34023536---- 
    34033537auto arr = [4, 5, 6, 7, 1, 2, 3]; 
    34043538auto p = rotate(arr, begin(arr) + 4); 
    34053539assert(p - begin(arr) == 3); 
    34063540assert(arr == [ 1, 2, 3, 4, 5, 6, 7 ]); 
    34073541---- 
    34083542*/ 
    34093543size_t bringToFront(Range1, Range2)(Range1 front, Range2 back) 
    3410     if (isForwardRange!(Range1) && isForwardRange!(Range2)
     3544    if (isForwardRange!Range1 && isForwardRange!Range2
    34113545{ 
    34123546    enum bool sameHeadExists = is(typeof(front.sameHead(back))); 
    34133547    size_t result; 
    34143548    for (;;) 
    34153549    { 
    34163550        if (back.empty || front.empty) return result; 
    34173551        static if (sameHeadExists) 
    34183552            if (front.sameHead(back)) return result; 
    34193553 
    34203554        auto front2 = front.save;