1 // Written in the D programming language.
2 /**
3 This is a submodule of $(MREF std, algorithm).
4 It contains generic mutation algorithms.
5 
6 $(SCRIPT inhibitQuickIndex = 1;)
7 $(BOOKTABLE Cheat Sheet,
8 $(TR $(TH Function Name) $(TH Description))
9 $(T2 bringToFront,
10         If `a = [1, 2, 3]` and `b = [4, 5, 6, 7]`,
11         `bringToFront(a, b)` leaves `a = [4, 5, 6]` and
12         `b = [7, 1, 2, 3]`.)
13 $(T2 copy,
14         Copies a range to another. If
15         `a = [1, 2, 3]` and `b = new int[5]`, then `copy(a, b)`
16         leaves `b = [1, 2, 3, 0, 0]` and returns `b[3 .. $]`.)
17 $(T2 fill,
18         Fills a range with a pattern,
19         e.g., if `a = new int[3]`, then `fill(a, 4)`
20         leaves `a = [4, 4, 4]` and `fill(a, [3, 4])` leaves
21         `a = [3, 4, 3]`.)
22 $(T2 initializeAll,
23         If `a = [1.2, 3.4]`, then `initializeAll(a)` leaves
24         `a = [double.init, double.init]`.)
25 $(T2 move,
26         `move(a, b)` moves `a` into `b`. `move(a)` reads `a`
27         destructively when necessary.)
28 $(T2 moveEmplace,
29         Similar to `move` but assumes `target` is uninitialized.)
30 $(T2 moveAll,
31         Moves all elements from one range to another.)
32 $(T2 moveEmplaceAll,
33         Similar to `moveAll` but assumes all elements in `target` are uninitialized.)
34 $(T2 moveSome,
35         Moves as many elements as possible from one range to another.)
36 $(T2 moveEmplaceSome,
37         Similar to `moveSome` but assumes all elements in `target` are uninitialized.)
38 $(T2 remove,
39         Removes elements from a range in-place, and returns the shortened
40         range.)
41 $(T2 reverse,
42         If `a = [1, 2, 3]`, `reverse(a)` changes it to `[3, 2, 1]`.)
43 $(T2 strip,
44         Strips all leading and trailing elements equal to a value, or that
45         satisfy a predicate.
46         If `a = [1, 1, 0, 1, 1]`, then `strip(a, 1)` and
47         `strip!(e => e == 1)(a)` returns `[0]`.)
48 $(T2 stripLeft,
49         Strips all leading elements equal to a value, or that satisfy a
50         predicate.  If `a = [1, 1, 0, 1, 1]`, then `stripLeft(a, 1)` and
51         `stripLeft!(e => e == 1)(a)` returns `[0, 1, 1]`.)
52 $(T2 stripRight,
53         Strips all trailing elements equal to a value, or that satisfy a
54         predicate.
55         If `a = [1, 1, 0, 1, 1]`, then `stripRight(a, 1)` and
56         `stripRight!(e => e == 1)(a)` returns `[1, 1, 0]`.)
57 $(T2 swap,
58         Swaps two values.)
59 $(T2 swapAt,
60         Swaps two values by indices.)
61 $(T2 swapRanges,
62         Swaps all elements of two ranges.)
63 $(T2 uninitializedFill,
64         Fills a range (assumed uninitialized) with a value.)
65 )
66 
67 Copyright: Andrei Alexandrescu 2008-.
68 
69 License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
70 
71 Authors: $(HTTP erdani.com, Andrei Alexandrescu)
72 
73 Source: $(PHOBOSSRC std/algorithm/mutation.d)
74 
75 Macros:
76 T2=$(TR $(TDNW $(LREF $1)) $(TD $+))
77  */
78 module std.algorithm.mutation;
79 
80 import std.range.primitives;
81 import std.traits : isArray, isAssignable, isBlitAssignable, isNarrowString,
82        Unqual, isSomeChar, isMutable;
83 import std.meta : allSatisfy;
84 import std.typecons : tuple, Tuple;
85 
86 // bringToFront
87 /**
88 `bringToFront` takes two ranges `front` and `back`, which may
89 be of different types. Considering the concatenation of `front` and
90 `back` one unified range, `bringToFront` rotates that unified
91 range such that all elements in `back` are brought to the beginning
92 of the unified range. The relative ordering of elements in `front`
93 and `back`, respectively, remains unchanged.
94 
95 The `bringToFront` function treats strings at the code unit
96 level and it is not concerned with Unicode character integrity.
97 `bringToFront` is designed as a function for moving elements
98 in ranges, not as a string function.
99 
100 Performs $(BIGOH max(front.length, back.length)) evaluations of $(D
101 swap).
102 
103 The `bringToFront` function can rotate elements in one buffer left or right, swap
104 buffers of equal length, and even move elements across disjoint
105 buffers of different types and different lengths.
106 
107 Preconditions:
108 
109 Either `front` and `back` are disjoint, or `back` is
110 reachable from `front` and `front` is not reachable from $(D
111 back).
112 
113 Params:
114     front = an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
115     back = a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
116 
117 Returns:
118     The number of elements brought to the front, i.e., the length of `back`.
119 
120 See_Also:
121     $(LINK2 http://en.cppreference.com/w/cpp/algorithm/rotate, STL's `rotate`)
122 */
123 size_t bringToFront(InputRange, ForwardRange)(InputRange front, ForwardRange back)
124 if (isInputRange!InputRange && isForwardRange!ForwardRange)
125 {
126     import std.string : representation;
127 
128     static if (isNarrowString!InputRange)
129     {
130         auto frontW = representation(front);
131     }
132     else
133     {
134         alias frontW = front;
135     }
136     static if (isNarrowString!ForwardRange)
137     {
138         auto backW = representation(back);
139     }
140     else
141     {
142         alias backW = back;
143     }
144 
145     return bringToFrontImpl(frontW, backW);
146 }
147 
148 /**
149 The simplest use of `bringToFront` is for rotating elements in a
150 buffer. For example:
151 */
152 @safe unittest
153 {
154     auto arr = [4, 5, 6, 7, 1, 2, 3];
155     auto p = bringToFront(arr[0 .. 4], arr[4 .. $]);
156     assert(p == arr.length - 4);
157     assert(arr == [ 1, 2, 3, 4, 5, 6, 7 ]);
158 }
159 
160 /**
161 The `front` range may actually "step over" the `back`
162 range. This is very useful with forward ranges that cannot compute
163 comfortably right-bounded subranges like `arr[0 .. 4]` above. In
164 the example below, `r2` is a right subrange of `r1`.
165 */
166 @safe unittest
167 {
168     import std.algorithm.comparison : equal;
169     import std.container : SList;
170     import std.range.primitives : popFrontN;
171 
172     auto list = SList!(int)(4, 5, 6, 7, 1, 2, 3);
173     auto r1 = list[];
174     auto r2 = list[]; popFrontN(r2, 4);
175     assert(equal(r2, [ 1, 2, 3 ]));
176     bringToFront(r1, r2);
177     assert(equal(list[], [ 1, 2, 3, 4, 5, 6, 7 ]));
178 }
179 
180 /**
181 Elements can be swapped across ranges of different types:
182 */
183 @safe unittest
184 {
185     import std.algorithm.comparison : equal;
186     import std.container : SList;
187 
188     auto list = SList!(int)(4, 5, 6, 7);
189     auto vec = [ 1, 2, 3 ];
190     bringToFront(list[], vec);
191     assert(equal(list[], [ 1, 2, 3, 4 ]));
192     assert(equal(vec, [ 5, 6, 7 ]));
193 }
194 
195 /**
196 Unicode integrity is not preserved:
197 */
198 @safe unittest
199 {
200     import std.string : representation;
201     auto ar = representation("a".dup);
202     auto br = representation("ç".dup);
203 
204     bringToFront(ar, br);
205 
206     auto a = cast(char[]) ar;
207     auto b = cast(char[]) br;
208 
209     // Illegal UTF-8
210     assert(a == "\303");
211     // Illegal UTF-8
212     assert(b == "\247a");
213 }
214 
215 private size_t bringToFrontImpl(InputRange, ForwardRange)(InputRange front, ForwardRange back)
216 if (isInputRange!InputRange && isForwardRange!ForwardRange)
217 {
218     import std.array : sameHead;
219     import std.range : take, Take;
220     enum bool sameHeadExists = is(typeof(front.sameHead(back)));
221     size_t result;
222 
223     for (bool semidone; !front.empty && !back.empty; )
224     {
225         static if (sameHeadExists)
226         {
227             if (front.sameHead(back)) break; // shortcut
228         }
229         // Swap elements until front and/or back ends.
230         auto back0 = back.save;
231         size_t nswaps;
232         do
233         {
234             static if (sameHeadExists)
235             {
236                 // Detect the stepping-over condition.
237                 if (front.sameHead(back0)) back0 = back.save;
238             }
239             swapFront(front, back);
240             ++nswaps;
241             front.popFront();
242             back.popFront();
243         }
244         while (!front.empty && !back.empty);
245 
246         if (!semidone) result += nswaps;
247 
248         // Now deal with the remaining elements.
249         if (back.empty)
250         {
251             if (front.empty) break;
252             // Right side was shorter, which means that we've brought
253             // all the back elements to the front.
254             semidone = true;
255             // Next pass: bringToFront(front, back0) to adjust the rest.
256             back = back0;
257         }
258         else
259         {
260             assert(front.empty, "Expected front to be empty");
261             // Left side was shorter. Let's step into the back.
262             static if (is(InputRange == Take!ForwardRange))
263             {
264                 front = take(back0, nswaps);
265             }
266             else
267             {
268                 immutable subresult = bringToFront(take(back0, nswaps),
269                                                    back);
270                 if (!semidone) result += subresult;
271                 break; // done
272             }
273         }
274     }
275     return result;
276 }
277 
278 @safe unittest
279 {
280     import std.algorithm.comparison : equal;
281     import std.conv : text;
282     import std.random : Random = Xorshift, uniform;
283 
284     // a more elaborate test
285     {
286         auto rnd = Random(123_456_789);
287         int[] a = new int[uniform(100, 200, rnd)];
288         int[] b = new int[uniform(100, 200, rnd)];
289         foreach (ref e; a) e = uniform(-100, 100, rnd);
290         foreach (ref e; b) e = uniform(-100, 100, rnd);
291         int[] c = a ~ b;
292         // writeln("a= ", a);
293         // writeln("b= ", b);
294         auto n = bringToFront(c[0 .. a.length], c[a.length .. $]);
295         //writeln("c= ", c);
296         assert(n == b.length);
297         assert(c == b ~ a, text(c, "\n", a, "\n", b));
298     }
299     // different types, moveFront, no sameHead
300     {
R(T)301         static struct R(T)
302         {
303             T[] data;
304             size_t i;
305             @property
306             {
307                 R save() { return this; }
308                 bool empty() { return i >= data.length; }
309                 T front() { return data[i]; }
310                 T front(real e) { return data[i] = cast(T) e; }
311             }
312             void popFront() { ++i; }
313         }
314         auto a = R!int([1, 2, 3, 4, 5]);
315         auto b = R!real([6, 7, 8, 9]);
316         auto n = bringToFront(a, b);
317         assert(n == 4);
318         assert(a.data == [6, 7, 8, 9, 1]);
319         assert(b.data == [2, 3, 4, 5]);
320     }
321     // front steps over back
322     {
323         int[] arr, r1, r2;
324 
325         // back is shorter
326         arr = [4, 5, 6, 7, 1, 2, 3];
327         r1 = arr;
328         r2 = arr[4 .. $];
329         bringToFront(r1, r2) == 3 || assert(0);
330         assert(equal(arr, [1, 2, 3, 4, 5, 6, 7]));
331 
332         // front is shorter
333         arr = [5, 6, 7, 1, 2, 3, 4];
334         r1 = arr;
335         r2 = arr[3 .. $];
336         bringToFront(r1, r2) == 4 || assert(0);
337         assert(equal(arr, [1, 2, 3, 4, 5, 6, 7]));
338     }
339 
340     // https://issues.dlang.org/show_bug.cgi?id=16959
341     auto arr = ['4', '5', '6', '7', '1', '2', '3'];
342     auto p = bringToFront(arr[0 .. 4], arr[4 .. $]);
343 
344     assert(p == arr.length - 4);
345     assert(arr == ['1', '2', '3', '4', '5', '6', '7']);
346 }
347 
348 // Tests if types are arrays and support slice assign.
349 private enum bool areCopyCompatibleArrays(T1, T2) =
350     isArray!T1 && isArray!T2 && is(typeof(T2.init[] = T1.init[]));
351 
352 // copy
353 /**
354 Copies the content of `source` into `target` and returns the
355 remaining (unfilled) part of `target`.
356 
357 Preconditions: `target` shall have enough room to accommodate
358 the entirety of `source`.
359 
360 Params:
361     source = an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
362     target = an output range
363 
364 Returns:
365     The unfilled part of target
366  */
367 TargetRange copy(SourceRange, TargetRange)(SourceRange source, TargetRange target)
368 if (isInputRange!SourceRange && isOutputRange!(TargetRange, ElementType!SourceRange))
369 {
370     static if (areCopyCompatibleArrays!(SourceRange, TargetRange))
371     {
372         const tlen = target.length;
373         const slen = source.length;
374         assert(tlen >= slen,
375                 "Cannot copy a source range into a smaller target range.");
376 
377         immutable overlaps = () @trusted {
378             return source.ptr < target.ptr + tlen &&
379                 target.ptr < source.ptr + slen; }();
380 
381         if (overlaps)
382         {
383             if (source.ptr < target.ptr)
384             {
385                 foreach_reverse (idx; 0 .. slen)
386                     target[idx] = source[idx];
387             }
388             else
389             {
390                 foreach (idx; 0 .. slen)
391                     target[idx] = source[idx];
392             }
393             return target[slen .. tlen];
394         }
395         else
396         {
397             // Array specialization.  This uses optimized memory copying
398             // routines under the hood and is about 10-20x faster than the
399             // generic implementation.
400             target[0 .. slen] = source[];
401             return target[slen .. $];
402         }
403     }
404     else
405     {
406         // Specialize for 2 random access ranges.
407         // Typically 2 random access ranges are faster iterated by common
408         // index than by x.popFront(), y.popFront() pair
409         static if (isRandomAccessRange!SourceRange &&
410                 hasLength!SourceRange &&
411                 hasSlicing!TargetRange &&
412                 isRandomAccessRange!TargetRange &&
413                 hasLength!TargetRange)
414         {
415             auto len = source.length;
416             foreach (idx; 0 .. len)
417                 target[idx] = source[idx];
418             return target[len .. target.length];
419         }
420         else
421         {
422             foreach (element; source)
423                 put(target, element);
424             return target;
425         }
426     }
427 }
428 
429 ///
430 @safe unittest
431 {
432     int[] a = [ 1, 5 ];
433     int[] b = [ 9, 8 ];
434     int[] buf = new int[](a.length + b.length + 10);
435     auto rem = a.copy(buf);    // copy a into buf
436     rem = b.copy(rem);         // copy b into remainder of buf
437     assert(buf[0 .. a.length + b.length] == [1, 5, 9, 8]);
438     assert(rem.length == 10);   // unused slots in buf
439 }
440 
441 /**
442 As long as the target range elements support assignment from source
443 range elements, different types of ranges are accepted:
444 */
445 @safe unittest
446 {
447     float[] src = [ 1.0f, 5 ];
448     double[] dest = new double[src.length];
449     src.copy(dest);
450 }
451 
452 /**
453 To _copy at most `n` elements from a range, you may want to use
454 $(REF take, std,range):
455 */
456 @safe unittest
457 {
458     import std.range;
459     int[] src = [ 1, 5, 8, 9, 10 ];
460     auto dest = new int[](3);
461     src.take(dest.length).copy(dest);
462     assert(dest == [ 1, 5, 8 ]);
463 }
464 
465 /**
466 To _copy just those elements from a range that satisfy a predicate,
467 use $(LREF filter):
468 */
469 @safe unittest
470 {
471     import std.algorithm.iteration : filter;
472     int[] src = [ 1, 5, 8, 9, 10, 1, 2, 0 ];
473     auto dest = new int[src.length];
474     auto rem = src
475         .filter!(a => (a & 1) == 1)
476         .copy(dest);
477     assert(dest[0 .. $ - rem.length] == [ 1, 5, 9, 1 ]);
478 }
479 
480 /**
481 $(REF retro, std,range) can be used to achieve behavior similar to
482 $(LINK2 http://en.cppreference.com/w/cpp/algorithm/copy_backward, STL's `copy_backward`'):
483 */
484 @safe unittest
485 {
486     import std.algorithm, std.range;
487     int[] src = [1, 2, 4];
488     int[] dest = [0, 0, 0, 0, 0];
489     src.retro.copy(dest.retro);
490     assert(dest == [0, 0, 1, 2, 4]);
491 }
492 
493 // Test CTFE copy.
494 @safe unittest
495 {
496     enum c = copy([1,2,3], [4,5,6,7]);
497     assert(c == [7]);
498 }
499 
500 
501 @safe unittest
502 {
503     import std.algorithm.iteration : filter;
504 
505     {
506         int[] a = [ 1, 5 ];
507         int[] b = [ 9, 8 ];
508         auto e = copy(filter!("a > 1")(a), b);
509         assert(b[0] == 5 && e.length == 1);
510     }
511 
512     {
513         int[] a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
514         copy(a[5 .. 10], a[4 .. 9]);
515         assert(a[4 .. 9] == [6, 7, 8, 9, 10]);
516     }
517 
518     // https://issues.dlang.org/show_bug.cgi?id=21724
519     {
520         int[] a = [1, 2, 3, 4];
521         copy(a[0 .. 2], a[1 .. 3]);
522         assert(a == [1, 1, 2, 4]);
523     }
524 
525     // https://issues.dlang.org/show_bug.cgi?id=7898
526     {
527         enum v =
528         {
529             import std.algorithm;
530             int[] arr1 = [10, 20, 30, 40, 50];
531             int[] arr2 = arr1.dup;
532             copy(arr1, arr2);
533             return 35;
534         }();
535         assert(v == 35);
536     }
537 }
538 
539 // https://issues.dlang.org/show_bug.cgi?id=13650
540 @safe unittest
541 {
542     import std.meta : AliasSeq;
543     static foreach (Char; AliasSeq!(char, wchar, dchar))
544     {{
545         Char[3] a1 = "123";
546         Char[6] a2 = "456789";
547         assert(copy(a1[], a2[]) is a2[3..$]);
548         assert(a1[] == "123");
549         assert(a2[] == "123789");
550     }}
551 }
552 
553 // https://issues.dlang.org/show_bug.cgi?id=18804
554 @safe unittest
555 {
556     static struct NullSink
557     {
putNullSink558         void put(E)(E) {}
559     }
560     int line = 0;
561     struct R
562     {
563         int front;
emptyR564         @property bool empty() { return line == 1; }
popFrontR565         void popFront() { line = 1; }
566     }
567     R r;
568     copy(r, NullSink());
569     assert(line == 1);
570 }
571 
572 /**
573 Assigns `value` to each element of input range `range`.
574 
575 Alternatively, instead of using a single `value` to fill the `range`,
576 a `filter` $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
577 can be provided. The length of `filler` and `range` do not need to match, but
578 `filler` must not be empty.
579 
580 Params:
581         range = An
582                 $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
583                 that exposes references to its elements and has assignable
584                 elements
585         value = Assigned to each element of range
586         filler = A
587                 $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
588                 representing the _fill pattern.
589 
590 Throws: If `filler` is empty.
591 
592 See_Also:
593         $(LREF uninitializedFill)
594         $(LREF initializeAll)
595  */
596 void fill(Range, Value)(auto ref Range range, auto ref Value value)
597 if ((isInputRange!Range && is(typeof(range.front = value)) ||
598     isSomeChar!Value && is(typeof(range[] = value))))
599 {
600     alias T = ElementType!Range;
601 
602     static if (is(typeof(range[] = value)))
603     {
604         range[] = value;
605     }
606     else static if (is(typeof(range[] = T(value))))
607     {
608         range[] = T(value);
609     }
610     else
611     {
612         for ( ; !range.empty; range.popFront() )
613         {
614             range.front = value;
615         }
616     }
617 }
618 
619 ///
620 @safe unittest
621 {
622     int[] a = [ 1, 2, 3, 4 ];
623     fill(a, 5);
624     assert(a == [ 5, 5, 5, 5 ]);
625 }
626 
627 // test fallback on mutable narrow strings
628 // https://issues.dlang.org/show_bug.cgi?id=16342
629 @safe unittest
630 {
631     char[] chars = ['a', 'b'];
632     fill(chars, 'c');
633     assert(chars == "cc");
634 
635     char[2] chars2 = ['a', 'b'];
636     fill(chars2, 'c');
637     assert(chars2 == "cc");
638 
639     wchar[] wchars = ['a', 'b'];
640     fill(wchars, wchar('c'));
641     assert(wchars == "cc"w);
642 
643     dchar[] dchars = ['a', 'b'];
644     fill(dchars, dchar('c'));
645     assert(dchars == "cc"d);
646 }
647 
648 @nogc @safe unittest
649 {
650     const(char)[] chars;
651     assert(chars.length == 0);
652     static assert(!__traits(compiles, fill(chars, 'c')));
653     wstring wchars;
654     assert(wchars.length == 0);
655     static assert(!__traits(compiles, fill(wchars, wchar('c'))));
656 }
657 
658 @nogc @safe unittest
659 {
660     char[] chars;
661     fill(chars, 'c');
662     assert(chars == ""c);
663 }
664 
665 @safe unittest
666 {
667     shared(char)[] chrs = ['r'];
668     fill(chrs, 'c');
669     assert(chrs == [shared(char)('c')]);
670 }
671 
672 @nogc @safe unittest
673 {
Str(size_t len)674     struct Str(size_t len)
675     {
676         private char[len] _data;
677         void opIndexAssign(char value) @safe @nogc
678         {_data[] = value;}
679     }
680     Str!2 str;
681     str.fill(':');
682     assert(str._data == "::");
683 }
684 
685 @safe unittest
686 {
687     char[] chars = ['a','b','c','d'];
688     chars[1 .. 3].fill(':');
689     assert(chars == "a::d");
690 }
691 // end https://issues.dlang.org/show_bug.cgi?id=16342
692 
693 @safe unittest
694 {
695     import std.conv : text;
696     import std.internal.test.dummyrange;
697 
698     int[] a = [ 1, 2, 3 ];
699     fill(a, 6);
700     assert(a == [ 6, 6, 6 ], text(a));
701 
fun0()702     void fun0()
703     {
704         foreach (i; 0 .. 1000)
705         {
706             foreach (ref e; a) e = 6;
707         }
708     }
fun1()709     void fun1() { foreach (i; 0 .. 1000) fill(a, 6); }
710 
711     // fill should accept InputRange
712     alias InputRange = DummyRange!(ReturnBy.Reference, Length.No, RangeType.Input);
713     enum filler = uint.max;
714     InputRange range;
715     fill(range, filler);
716     foreach (value; range.arr)
717         assert(value == filler);
718 }
719 
720 @safe unittest
721 {
722     //ER8638_1 IS_NOT self assignable
723     static struct ER8638_1
724     {
opAssignER8638_1725         void opAssign(int){}
726     }
727 
728     //ER8638_1 IS self assignable
729     static struct ER8638_2
730     {
opAssign(ER8638_2)731         void opAssign(ER8638_2){}
opAssign(int)732         void opAssign(int){}
733     }
734 
735     auto er8638_1 = new ER8638_1[](10);
736     auto er8638_2 = new ER8638_2[](10);
737     er8638_1.fill(5); //generic case
738     er8638_2.fill(5); //opSlice(T.init) case
739 }
740 
741 @safe unittest
742 {
743     {
744         int[] a = [1, 2, 3];
745         immutable(int) b = 0;
746         a.fill(b);
747         assert(a == [0, 0, 0]);
748     }
749     {
750         double[] a = [1, 2, 3];
751         immutable(int) b = 0;
752         a.fill(b);
753         assert(a == [0, 0, 0]);
754     }
755 }
756 
757 /// ditto
758 void fill(InputRange, ForwardRange)(InputRange range, ForwardRange filler)
759 if (isInputRange!InputRange
760     && (isForwardRange!ForwardRange
761     || (isInputRange!ForwardRange && isInfinite!ForwardRange))
762     && is(typeof(InputRange.init.front = ForwardRange.init.front)))
763 {
764     static if (isInfinite!ForwardRange)
765     {
766         //ForwardRange is infinite, no need for bounds checking or saving
767         static if (hasSlicing!ForwardRange && hasLength!InputRange
768             && is(typeof(filler[0 .. range.length])))
769         {
770             copy(filler[0 .. range.length], range);
771         }
772         else
773         {
774             //manual feed
775             for ( ; !range.empty; range.popFront(), filler.popFront())
776             {
777                 range.front = filler.front;
778             }
779         }
780     }
781     else
782     {
783         import std.exception : enforce;
784 
785         enforce(!filler.empty, "Cannot fill range with an empty filler");
786 
787         static if (hasLength!InputRange && hasLength!ForwardRange
788             && is(typeof(range.length > filler.length)))
789         {
790             //Case we have access to length
791             immutable len = filler.length;
792             //Start by bulk copies
793             while (range.length > len)
794             {
795                 range = copy(filler.save, range);
796             }
797 
798             //and finally fill the partial range. No need to save here.
799             static if (hasSlicing!ForwardRange && is(typeof(filler[0 .. range.length])))
800             {
801                 //use a quick copy
802                 auto len2 = range.length;
803                 range = copy(filler[0 .. len2], range);
804             }
805             else
806             {
807                 //iterate. No need to check filler, it's length is longer than range's
808                 for (; !range.empty; range.popFront(), filler.popFront())
809                 {
810                     range.front = filler.front;
811                 }
812             }
813         }
814         else
815         {
816             //Most basic case.
817             auto bck = filler.save;
818             for (; !range.empty; range.popFront(), filler.popFront())
819             {
820                 if (filler.empty) filler = bck.save;
821                 range.front = filler.front;
822             }
823         }
824     }
825 }
826 
827 ///
828 @safe unittest
829 {
830     int[] a = [ 1, 2, 3, 4, 5 ];
831     int[] b = [ 8, 9 ];
832     fill(a, b);
833     assert(a == [ 8, 9, 8, 9, 8 ]);
834 }
835 
836 @safe unittest
837 {
838     import std.exception : assertThrown;
839     import std.internal.test.dummyrange;
840 
841     int[] a = [ 1, 2, 3, 4, 5 ];
842     int[] b = [1, 2];
843     fill(a, b);
844     assert(a == [ 1, 2, 1, 2, 1 ]);
845 
846     // fill should accept InputRange
847     alias InputRange = DummyRange!(ReturnBy.Reference, Length.No, RangeType.Input);
848     InputRange range;
849     fill(range,[1,2]);
850     foreach (i,value;range.arr)
851     assert(value == (i%2 == 0?1:2));
852 
853     //test with a input being a "reference forward" range
854     fill(a, new ReferenceForwardRange!int([8, 9]));
855     assert(a == [8, 9, 8, 9, 8]);
856 
857     //test with a input being an "infinite input" range
858     fill(a, new ReferenceInfiniteInputRange!int());
859     assert(a == [0, 1, 2, 3, 4]);
860 
861     //empty filler test
862     assertThrown(fill(a, a[$..$]));
863 }
864 
865 /**
866 Initializes all elements of `range` with their `.init` value.
867 Assumes that the elements of the range are uninitialized.
868 
869 Params:
870         range = An
871                 $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
872                 that exposes references to its elements and has assignable
873                 elements
874 
875 See_Also:
876         $(LREF fill)
877         $(LREF uninitializeFill)
878  */
879 void initializeAll(Range)(Range range)
880 if (isInputRange!Range && hasLvalueElements!Range && hasAssignableElements!Range)
881 {
882     import core.stdc.string : memset, memcpy;
883     import std.traits : hasElaborateAssign, isDynamicArray;
884 
885     alias T = ElementType!Range;
886     static if (hasElaborateAssign!T)
887     {
888         import std.algorithm.internal : addressOf;
889         //Elaborate opAssign. Must go the memcpy road.
890         //We avoid calling emplace here, because our goal is to initialize to
891         //the static state of T.init,
892         //So we want to avoid any un-necassarilly CC'ing of T.init
893         static if (!__traits(isZeroInit, T))
894         {
895             auto p = typeid(T).initializer();
896             for ( ; !range.empty ; range.popFront() )
897             {
898                 static if (__traits(isStaticArray, T))
899                 {
900                     // static array initializer only contains initialization
901                     // for one element of the static array.
902                     auto elemp = cast(void *) addressOf(range.front);
903                     auto endp = elemp + T.sizeof;
904                     while (elemp < endp)
905                     {
906                         memcpy(elemp, p.ptr, p.length);
907                         elemp += p.length;
908                     }
909                 }
910                 else
911                 {
912                     memcpy(addressOf(range.front), p.ptr, T.sizeof);
913                 }
914             }
915         }
916         else
917             static if (isDynamicArray!Range)
918                 memset(range.ptr, 0, range.length * T.sizeof);
919             else
920                 for ( ; !range.empty ; range.popFront() )
921                     memset(addressOf(range.front), 0, T.sizeof);
922     }
923     else
924         fill(range, T.init);
925 }
926 
927 /// ditto
928 void initializeAll(Range)(Range range)
929 if (is(Range == char[]) || is(Range == wchar[]))
930 {
931     alias T = ElementEncodingType!Range;
932     range[] = T.init;
933 }
934 
935 ///
936 @system unittest
937 {
938     import core.stdc.stdlib : malloc, free;
939 
940     struct S
941     {
942         int a = 10;
943     }
944 
945     auto s = (cast(S*) malloc(5 * S.sizeof))[0 .. 5];
946     initializeAll(s);
947     assert(s == [S(10), S(10), S(10), S(10), S(10)]);
948 
949     scope(exit) free(s.ptr);
950 }
951 
952 @system unittest
953 {
954     import std.algorithm.iteration : filter;
955     import std.meta : AliasSeq;
956     import std.traits : hasElaborateAssign;
957 
958     //Test strings:
959     //Must work on narrow strings.
960     //Must reject const
961     char[3] a = void;
962     a[].initializeAll();
963     assert(a[] == [char.init, char.init, char.init]);
964     string s;
965     assert(!__traits(compiles, s.initializeAll()));
966     assert(!__traits(compiles, s.initializeAll()));
967     assert(s.empty);
968 
969     //Note: Cannot call uninitializedFill on narrow strings
970 
971     enum e {e1, e2}
972     e[3] b1 = void;
973     b1[].initializeAll();
974     assert(b1[] == [e.e1, e.e1, e.e1]);
975     e[3] b2 = void;
976     b2[].uninitializedFill(e.e2);
977     assert(b2[] == [e.e2, e.e2, e.e2]);
978 
979     static struct S1
980     {
981         int i;
982     }
983     static struct S2
984     {
985         int i = 1;
986     }
987     static struct S3
988     {
989         int i;
thisS3990         this(this){}
991     }
992     static struct S4
993     {
994         int i = 1;
this(this)995         this(this){}
996     }
997     static assert(!hasElaborateAssign!S1);
998     static assert(!hasElaborateAssign!S2);
999     static assert( hasElaborateAssign!S3);
1000     static assert( hasElaborateAssign!S4);
1001     assert(!typeid(S1).initializer().ptr);
1002     assert( typeid(S2).initializer().ptr);
1003     assert(!typeid(S3).initializer().ptr);
1004     assert( typeid(S4).initializer().ptr);
1005 
1006     static foreach (S; AliasSeq!(S1, S2, S3, S4))
1007     {
1008         //initializeAll
1009         {
1010             //Array
1011             S[3] ss1 = void;
1012             ss1[].initializeAll();
1013             assert(ss1[] == [S.init, S.init, S.init]);
1014 
1015             //Not array
1016             S[3] ss2 = void;
1017             auto sf = ss2[].filter!"true"();
1018 
1019             sf.initializeAll();
1020             assert(ss2[] == [S.init, S.init, S.init]);
1021         }
1022         //uninitializedFill
1023         {
1024             //Array
1025             S[3] ss1 = void;
1026             ss1[].uninitializedFill(S(2));
1027             assert(ss1[] == [S(2), S(2), S(2)]);
1028 
1029             //Not array
1030             S[3] ss2 = void;
1031             auto sf = ss2[].filter!"true"();
1032             sf.uninitializedFill(S(2));
1033             assert(ss2[] == [S(2), S(2), S(2)]);
1034         }
1035     }
1036 }
1037 
1038 // test that initializeAll works for arrays of static arrays of structs with
1039 // elaborate assigns.
1040 @system unittest
1041 {
1042     struct Int {
~thisInt1043         ~this() {}
1044         int x = 3;
1045     }
1046     Int[2] xs = [Int(1), Int(2)];
1047     struct R {
1048         bool done;
emptyR1049         bool empty() { return done; }
frontR1050         ref Int[2] front() { return xs; }
popFrontR1051         void popFront() { done = true; }
1052     }
1053     initializeAll(R());
1054     assert(xs[0].x == 3);
1055     assert(xs[1].x == 3);
1056 }
1057 
1058 // move
1059 /**
1060 Moves `source` into `target`, via a destructive copy when necessary.
1061 
1062 If `T` is a struct with a destructor or postblit defined, source is reset
1063 to its `.init` value after it is moved into target, otherwise it is
1064 left unchanged.
1065 
1066 Preconditions:
1067 If source has internal pointers that point to itself and doesn't define
1068 opPostMove, it cannot be moved, and will trigger an assertion failure.
1069 
1070 Params:
1071     source = Data to copy.
1072     target = Where to copy into. The destructor, if any, is invoked before the
1073         copy is performed.
1074 */
move(T)1075 void move(T)(ref T source, ref T target)
1076 {
1077     moveImpl(target, source);
1078 }
1079 
1080 /// For non-struct types, `move` just performs `target = source`:
1081 @safe unittest
1082 {
1083     Object obj1 = new Object;
1084     Object obj2 = obj1;
1085     Object obj3;
1086 
1087     move(obj2, obj3);
1088     assert(obj3 is obj1);
1089     // obj2 unchanged
1090     assert(obj2 is obj1);
1091 }
1092 
1093 ///
1094 pure nothrow @safe @nogc unittest
1095 {
1096     // Structs without destructors are simply copied
1097     struct S1
1098     {
1099         int a = 1;
1100         int b = 2;
1101     }
1102     S1 s11 = { 10, 11 };
1103     S1 s12;
1104 
1105     move(s11, s12);
1106 
1107     assert(s12 == S1(10, 11));
1108     assert(s11 == s12);
1109 
1110     // But structs with destructors or postblits are reset to their .init value
1111     // after copying to the target.
1112     struct S2
1113     {
1114         int a = 1;
1115         int b = 2;
1116 
~thisS21117         ~this() pure nothrow @safe @nogc { }
1118     }
1119     S2 s21 = { 3, 4 };
1120     S2 s22;
1121 
1122     move(s21, s22);
1123 
1124     assert(s21 == S2(1, 2));
1125     assert(s22 == S2(3, 4));
1126 }
1127 
1128 @safe unittest
1129 {
1130     import std.exception : assertCTFEable;
1131     import std.traits;
1132 
1133     assertCTFEable!((){
1134         Object obj1 = new Object;
1135         Object obj2 = obj1;
1136         Object obj3;
1137         move(obj2, obj3);
1138         assert(obj3 is obj1);
1139 
1140         static struct S1 { int a = 1, b = 2; }
1141         S1 s11 = { 10, 11 };
1142         S1 s12;
1143         move(s11, s12);
1144         assert(s11.a == 10 && s11.b == 11 && s12.a == 10 && s12.b == 11);
1145 
1146         static struct S2 { int a = 1; int * b; }
1147         S2 s21 = { 10, null };
1148         s21.b = new int;
1149         S2 s22;
1150         move(s21, s22);
1151         assert(s21 == s22);
1152     });
1153     // https://issues.dlang.org/show_bug.cgi?id=5661 test(1)
1154     static struct S3
1155     {
~thisS3::X1156         static struct X { int n = 0; ~this(){n = 0;} }
1157         X x;
1158     }
1159     static assert(hasElaborateDestructor!S3);
1160     S3 s31, s32;
1161     s31.x.n = 1;
1162     move(s31, s32);
1163     assert(s31.x.n == 0);
1164     assert(s32.x.n == 1);
1165 
1166     // https://issues.dlang.org/show_bug.cgi?id=5661 test(2)
1167     static struct S4
1168     {
thisS4::X1169         static struct X { int n = 0; this(this){n = 0;} }
1170         X x;
1171     }
1172     static assert(hasElaborateCopyConstructor!S4);
1173     S4 s41, s42;
1174     s41.x.n = 1;
1175     move(s41, s42);
1176     assert(s41.x.n == 0);
1177     assert(s42.x.n == 1);
1178 
1179     // https://issues.dlang.org/show_bug.cgi?id=13990 test
1180     class S5;
1181 
1182     S5 s51;
1183     S5 s52 = s51;
1184     S5 s53;
1185     move(s52, s53);
1186     assert(s53 is s51);
1187 }
1188 
1189 /// Ditto
move(T)1190 T move(T)(return scope ref T source)
1191 {
1192     return moveImpl(source);
1193 }
1194 
1195 /// Non-copyable structs can still be moved:
1196 pure nothrow @safe @nogc unittest
1197 {
1198     struct S
1199     {
1200         int a = 1;
1201         @disable this(this);
~thisS1202         ~this() pure nothrow @safe @nogc {}
1203     }
1204     S s1;
1205     s1.a = 2;
1206     S s2 = move(s1);
1207     assert(s1.a == 1);
1208     assert(s2.a == 2);
1209 }
1210 
1211 /// `opPostMove` will be called if defined:
1212 pure nothrow @safe @nogc unittest
1213 {
1214     struct S
1215     {
1216         int a;
opPostMoveS1217         void opPostMove(const ref S old)
1218         {
1219             assert(a == old.a);
1220             a++;
1221         }
1222     }
1223     S s1;
1224     s1.a = 41;
1225     S s2 = move(s1);
1226     assert(s2.a == 42);
1227 }
1228 
1229 // https://issues.dlang.org/show_bug.cgi?id=20869
1230 // `move` should propagate the attributes of `opPostMove`
1231 @system unittest
1232 {
1233     static struct S
1234     {
opPostMoveS1235         void opPostMove(const ref S old) nothrow @system
1236         {
1237             __gshared int i;
1238             new int(i++); // Force @gc impure @system
1239         }
1240     }
1241 
1242     alias T = void function() @system nothrow;
1243     static assert(is(typeof({ S s; move(s); }) == T));
1244     static assert(is(typeof({ S s; move(s, s); }) == T));
1245 }
1246 
moveImpl(T)1247 private void moveImpl(T)(ref scope T target, ref return scope T source)
1248 {
1249     import std.traits : hasElaborateDestructor;
1250 
1251     static if (is(T == struct))
1252     {
1253         //  Unsafe when compiling without -dip1000
1254         if ((() @trusted => &source == &target)()) return;
1255 
1256         // Destroy target before overwriting it
1257         static if (hasElaborateDestructor!T) target.__xdtor();
1258     }
1259     // move and emplace source into target
1260     moveEmplaceImpl(target, source);
1261 }
1262 
moveImpl(T)1263 private T moveImpl(T)(ref return scope T source)
1264 {
1265     // Properly infer safety from moveEmplaceImpl as the implementation below
1266     // might void-initialize pointers in result and hence needs to be @trusted
1267     if (false) moveEmplaceImpl(source, source);
1268 
1269     return trustedMoveImpl(source);
1270 }
1271 
trustedMoveImpl(T)1272 private T trustedMoveImpl(T)(ref return scope T source) @trusted
1273 {
1274     T result = void;
1275     moveEmplaceImpl(result, source);
1276     return result;
1277 }
1278 
1279 @safe unittest
1280 {
1281     import std.exception : assertCTFEable;
1282     import std.traits;
1283 
1284     assertCTFEable!((){
1285         Object obj1 = new Object;
1286         Object obj2 = obj1;
1287         Object obj3 = move(obj2);
1288         assert(obj3 is obj1);
1289 
1290         static struct S1 { int a = 1, b = 2; }
1291         S1 s11 = { 10, 11 };
1292         S1 s12 = move(s11);
1293         assert(s11.a == 10 && s11.b == 11 && s12.a == 10 && s12.b == 11);
1294 
1295         static struct S2 { int a = 1; int * b; }
1296         S2 s21 = { 10, null };
1297         s21.b = new int;
1298         S2 s22 = move(s21);
1299         assert(s21 == s22);
1300     });
1301 
1302     // https://issues.dlang.org/show_bug.cgi?id=5661 test(1)
1303     static struct S3
1304     {
~thisS3::X1305         static struct X { int n = 0; ~this(){n = 0;} }
1306         X x;
1307     }
1308     static assert(hasElaborateDestructor!S3);
1309     S3 s31;
1310     s31.x.n = 1;
1311     S3 s32 = move(s31);
1312     assert(s31.x.n == 0);
1313     assert(s32.x.n == 1);
1314 
1315     // https://issues.dlang.org/show_bug.cgi?id=5661 test(2)
1316     static struct S4
1317     {
thisS4::X1318         static struct X { int n = 0; this(this){n = 0;} }
1319         X x;
1320     }
1321     static assert(hasElaborateCopyConstructor!S4);
1322     S4 s41;
1323     s41.x.n = 1;
1324     S4 s42 = move(s41);
1325     assert(s41.x.n == 0);
1326     assert(s42.x.n == 1);
1327 
1328     // https://issues.dlang.org/show_bug.cgi?id=13990 test
1329     class S5;
1330 
1331     S5 s51;
1332     S5 s52 = s51;
1333     S5 s53;
1334     s53 = move(s52);
1335     assert(s53 is s51);
1336 }
1337 
1338 @system unittest
1339 {
~thisS1340     static struct S { int n = 0; ~this() @system { n = 0; } }
1341     S a, b;
1342     static assert(!__traits(compiles, () @safe { move(a, b); }));
1343     static assert(!__traits(compiles, () @safe { move(a); }));
1344     a.n = 1;
1345     () @trusted { move(a, b); }();
1346     assert(a.n == 0);
1347     a.n = 1;
1348     () @trusted { move(a); }();
1349     assert(a.n == 0);
1350 }
1351 
1352 // https://issues.dlang.org/show_bug.cgi?id=6217
1353 @safe unittest
1354 {
1355     import std.algorithm.iteration : map;
1356     auto x = map!"a"([1,2,3]);
1357     x = move(x);
1358 }
1359 
1360 // https://issues.dlang.org/show_bug.cgi?id=8055
1361 @safe unittest
1362 {
1363     static struct S
1364     {
1365         int x;
~thisS1366         ~this()
1367         {
1368             assert(x == 0);
1369         }
1370     }
foo(S s)1371     S foo(S s)
1372     {
1373         return move(s);
1374     }
1375     S a;
1376     a.x = 0;
1377     auto b = foo(a);
1378     assert(b.x == 0);
1379 }
1380 
1381 // https://issues.dlang.org/show_bug.cgi?id=8057
1382 @system unittest
1383 {
1384     int n = 10;
1385     struct S
1386     {
1387         int x;
~thisS1388         ~this()
1389         {
1390             // Access to enclosing scope
1391             assert(n == 10);
1392         }
1393     }
foo(S s)1394     S foo(S s)
1395     {
1396         // Move nested struct
1397         return move(s);
1398     }
1399     S a;
1400     a.x = 1;
1401     auto b = foo(a);
1402     assert(b.x == 1);
1403 
1404     // Regression https://issues.dlang.org/show_bug.cgi?id=8171
Array(T)1405     static struct Array(T)
1406     {
1407         // nested struct has no member
1408         struct Payload
1409         {
1410             ~this() {}
1411         }
1412     }
1413     Array!int.Payload x = void;
1414     move(x);
1415     move(x, x);
1416 }
1417 
1418 private void moveEmplaceImpl(T)(ref scope T target, ref return scope T source)
1419 {
1420     import core.stdc.string : memcpy, memset;
1421     import std.traits : hasAliasing, hasElaborateAssign,
1422                         hasElaborateCopyConstructor, hasElaborateDestructor,
1423                         hasElaborateMove,
1424                         isAssignable, isStaticArray;
1425 
1426     static if (!is(T == class) && hasAliasing!T) if (!__ctfe)
1427     {
1428         import std.exception : doesPointTo;
1429         assert(!(doesPointTo(source, source) && !hasElaborateMove!T),
1430             "Cannot move object with internal pointer unless `opPostMove` is defined.");
1431     }
1432 
1433     static if (is(T == struct))
1434     {
1435         //  Unsafe when compiling without -dip1000
1436         assert((() @trusted => &source !is &target)(), "source and target must not be identical");
1437 
1438         static if (hasElaborateAssign!T || !isAssignable!T)
1439             () @trusted { memcpy(&target, &source, T.sizeof); }();
1440         else
1441             target = source;
1442 
1443         static if (hasElaborateMove!T)
1444             __move_post_blt(target, source);
1445 
1446         // If the source defines a destructor or a postblit hook, we must obliterate the
1447         // object in order to avoid double freeing and undue aliasing
1448         static if (hasElaborateDestructor!T || hasElaborateCopyConstructor!T)
1449         {
1450             // If T is nested struct, keep original context pointer
1451             static if (__traits(isNested, T))
1452                 enum sz = T.sizeof - (void*).sizeof;
1453             else
1454                 enum sz = T.sizeof;
1455 
1456             static if (__traits(isZeroInit, T))
1457                 () @trusted { memset(&source, 0, sz); }();
1458             else
1459             {
1460                 auto init = typeid(T).initializer();
1461                 () @trusted { memcpy(&source, init.ptr, sz); }();
1462             }
1463         }
1464     }
1465     else static if (isStaticArray!T)
1466     {
1467         for (size_t i = 0; i < source.length; ++i)
1468             move(source[i], target[i]);
1469     }
1470     else
1471     {
1472         // Primitive data (including pointers and arrays) or class -
1473         // assignment works great
1474         target = source;
1475     }
1476 }
1477 
1478 /**
1479  * Similar to $(LREF move) but assumes `target` is uninitialized. This
1480  * is more efficient because `source` can be blitted over `target`
1481  * without destroying or initializing it first.
1482  *
1483  * Params:
1484  *   source = value to be moved into target
1485  *   target = uninitialized value to be filled by source
1486  */
1487 void moveEmplace(T)(ref T source, ref T target) pure @system
1488 {
1489     moveEmplaceImpl(target, source);
1490 }
1491 
1492 ///
1493 pure nothrow @nogc @system unittest
1494 {
1495     static struct Foo
1496     {
1497     pure nothrow @nogc:
1498         this(int* ptr) { _ptr = ptr; }
1499         ~this() { if (_ptr) ++*_ptr; }
1500         int* _ptr;
1501     }
1502 
1503     int val;
1504     Foo foo1 = void; // uninitialized
1505     auto foo2 = Foo(&val); // initialized
1506     assert(foo2._ptr is &val);
1507 
1508     // Using `move(foo2, foo1)` would have an undefined effect because it would destroy
1509     // the uninitialized foo1.
1510     // moveEmplace directly overwrites foo1 without destroying or initializing it first.
1511     moveEmplace(foo2, foo1);
1512     assert(foo1._ptr is &val);
1513     assert(foo2._ptr is null);
1514     assert(val == 0);
1515 }
1516 
1517 // https://issues.dlang.org/show_bug.cgi?id=18913
1518 @safe unittest
1519 {
1520     static struct NoCopy
1521     {
1522         int payload;
1523         ~this() { }
1524         @disable this(this);
1525     }
1526 
1527     static void f(NoCopy[2]) { }
1528 
1529     NoCopy[2] ncarray = [ NoCopy(1), NoCopy(2) ];
1530 
1531     static assert(!__traits(compiles, f(ncarray)));
1532     f(move(ncarray));
1533 }
1534 
1535 // moveAll
1536 /**
1537 Calls `move(a, b)` for each element `a` in `src` and the corresponding
1538 element `b` in `tgt`, in increasing order.
1539 
1540 Preconditions:
1541 `walkLength(src) <= walkLength(tgt)`.
1542 This precondition will be asserted. If you cannot ensure there is enough room in
1543 `tgt` to accommodate all of `src` use $(LREF moveSome) instead.
1544 
1545 Params:
1546     src = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) with
1547         movable elements.
1548     tgt = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) with
1549         elements that elements from `src` can be moved into.
1550 
1551 Returns: The leftover portion of `tgt` after all elements from `src` have
1552 been moved.
1553  */
1554 InputRange2 moveAll(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt)
1555 if (isInputRange!InputRange1 && isInputRange!InputRange2
1556         && is(typeof(move(src.front, tgt.front))))
1557 {
1558     return moveAllImpl!move(src, tgt);
1559 }
1560 
1561 ///
1562 pure nothrow @safe @nogc unittest
1563 {
1564     int[3] a = [ 1, 2, 3 ];
1565     int[5] b;
1566     assert(moveAll(a[], b[]) is b[3 .. $]);
1567     assert(a[] == b[0 .. 3]);
1568     int[3] cmp = [ 1, 2, 3 ];
1569     assert(a[] == cmp[]);
1570 }
1571 
1572 /**
1573  * Similar to $(LREF moveAll) but assumes all elements in `tgt` are
1574  * uninitialized. Uses $(LREF moveEmplace) to move elements from
1575  * `src` over elements from `tgt`.
1576  */
1577 InputRange2 moveEmplaceAll(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt) @system
1578 if (isInputRange!InputRange1 && isInputRange!InputRange2
1579         && is(typeof(moveEmplace(src.front, tgt.front))))
1580 {
1581     return moveAllImpl!moveEmplace(src, tgt);
1582 }
1583 
1584 ///
1585 pure nothrow @nogc @system unittest
1586 {
1587     static struct Foo
1588     {
1589         ~this() pure nothrow @nogc { if (_ptr) ++*_ptr; }
1590         int* _ptr;
1591     }
1592     int[3] refs = [0, 1, 2];
1593     Foo[3] src = [Foo(&refs[0]), Foo(&refs[1]), Foo(&refs[2])];
1594     Foo[5] dst = void;
1595 
1596     auto tail = moveEmplaceAll(src[], dst[]); // move 3 value from src over dst
1597     assert(tail.length == 2); // returns remaining uninitialized values
1598     initializeAll(tail);
1599 
1600     import std.algorithm.searching : all;
1601     assert(src[].all!(e => e._ptr is null));
1602     assert(dst[0 .. 3].all!(e => e._ptr !is null));
1603 }
1604 
1605 @system unittest
1606 {
1607     struct InputRange
1608     {
1609         ref int front() { return data[0]; }
1610         void popFront() { data.popFront; }
1611         bool empty() { return data.empty; }
1612         int[] data;
1613     }
1614     auto a = InputRange([ 1, 2, 3 ]);
1615     auto b = InputRange(new int[5]);
1616     moveAll(a, b);
1617     assert(a.data == b.data[0 .. 3]);
1618     assert(a.data == [ 1, 2, 3 ]);
1619 }
1620 
1621 private InputRange2 moveAllImpl(alias moveOp, InputRange1, InputRange2)(
1622     ref InputRange1 src, ref InputRange2 tgt)
1623 {
1624     import std.exception : enforce;
1625 
1626     static if (isRandomAccessRange!InputRange1 && hasLength!InputRange1 && hasLength!InputRange2
1627          && hasSlicing!InputRange2 && isRandomAccessRange!InputRange2)
1628     {
1629         auto toMove = src.length;
1630         assert(toMove <= tgt.length, "Source buffer needs to be smaller or equal to the target buffer.");
1631         foreach (idx; 0 .. toMove)
1632             moveOp(src[idx], tgt[idx]);
1633         return tgt[toMove .. tgt.length];
1634     }
1635     else
1636     {
1637         for (; !src.empty; src.popFront(), tgt.popFront())
1638         {
1639             assert(!tgt.empty, "Source buffer needs to be smaller or equal to the target buffer.");
1640             moveOp(src.front, tgt.front);
1641         }
1642         return tgt;
1643     }
1644 }
1645 
1646 // moveSome
1647 /**
1648 Calls `move(a, b)` for each element `a` in `src` and the corresponding
1649 element `b` in `tgt`, in increasing order, stopping when either range has been
1650 exhausted.
1651 
1652 Params:
1653     src = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) with
1654         movable elements.
1655     tgt = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) with
1656         elements that elements from `src` can be moved into.
1657 
1658 Returns: The leftover portions of the two ranges after one or the other of the
1659 ranges have been exhausted.
1660  */
1661 Tuple!(InputRange1, InputRange2) moveSome(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt)
1662 if (isInputRange!InputRange1 && isInputRange!InputRange2
1663         && is(typeof(move(src.front, tgt.front))))
1664 {
1665     return moveSomeImpl!move(src, tgt);
1666 }
1667 
1668 ///
1669 pure nothrow @safe @nogc unittest
1670 {
1671     int[5] a = [ 1, 2, 3, 4, 5 ];
1672     int[3] b;
1673     assert(moveSome(a[], b[])[0] is a[3 .. $]);
1674     assert(a[0 .. 3] == b);
1675     assert(a == [ 1, 2, 3, 4, 5 ]);
1676 }
1677 
1678 /**
1679  * Same as $(LREF moveSome) but assumes all elements in `tgt` are
1680  * uninitialized. Uses $(LREF moveEmplace) to move elements from
1681  * `src` over elements from `tgt`.
1682  */
1683 Tuple!(InputRange1, InputRange2) moveEmplaceSome(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt) @system
1684 if (isInputRange!InputRange1 && isInputRange!InputRange2
1685         && is(typeof(move(src.front, tgt.front))))
1686 {
1687     return moveSomeImpl!moveEmplace(src, tgt);
1688 }
1689 
1690 ///
1691 pure nothrow @nogc @system unittest
1692 {
1693     static struct Foo
1694     {
1695         ~this() pure nothrow @nogc { if (_ptr) ++*_ptr; }
1696         int* _ptr;
1697     }
1698     int[4] refs = [0, 1, 2, 3];
1699     Foo[4] src = [Foo(&refs[0]), Foo(&refs[1]), Foo(&refs[2]), Foo(&refs[3])];
1700     Foo[3] dst = void;
1701 
1702     auto res = moveEmplaceSome(src[], dst[]);
1703     assert(res.length == 2);
1704 
1705     import std.algorithm.searching : all;
1706     assert(src[0 .. 3].all!(e => e._ptr is null));
1707     assert(src[3]._ptr !is null);
1708     assert(dst[].all!(e => e._ptr !is null));
1709 }
1710 
1711 private Tuple!(InputRange1, InputRange2) moveSomeImpl(alias moveOp, InputRange1, InputRange2)(
1712     ref InputRange1 src, ref InputRange2 tgt)
1713 {
1714     for (; !src.empty && !tgt.empty; src.popFront(), tgt.popFront())
1715         moveOp(src.front, tgt.front);
1716     return tuple(src, tgt);
1717  }
1718 
1719 
1720 // SwapStrategy
1721 /**
1722 Defines the swapping strategy for algorithms that need to swap
1723 elements in a range (such as partition and sort). The strategy
1724 concerns the swapping of elements that are not the core concern of the
1725 algorithm. For example, consider an algorithm that sorts $(D [ "abc",
1726 "b", "aBc" ]) according to `toUpper(a) < toUpper(b)`. That
1727 algorithm might choose to swap the two equivalent strings `"abc"`
1728 and `"aBc"`. That does not affect the sorting since both
1729 `["abc", "aBc", "b" ]` and `[ "aBc", "abc", "b" ]` are valid
1730 outcomes.
1731 
1732 Some situations require that the algorithm must NOT ever change the
1733 relative ordering of equivalent elements (in the example above, only
1734 `[ "abc", "aBc", "b" ]` would be the correct result). Such
1735 algorithms are called $(B stable). If the ordering algorithm may swap
1736 equivalent elements discretionarily, the ordering is called $(B
1737 unstable).
1738 
1739 Yet another class of algorithms may choose an intermediate tradeoff by
1740 being stable only on a well-defined subrange of the range. There is no
1741 established terminology for such behavior; this library calls it $(B
1742 semistable).
1743 
1744 Generally, the `stable` ordering strategy may be more costly in
1745 time and/or space than the other two because it imposes additional
1746 constraints. Similarly, `semistable` may be costlier than $(D
1747 unstable). As (semi-)stability is not needed very often, the ordering
1748 algorithms in this module parameterized by `SwapStrategy` all
1749 choose `SwapStrategy.unstable` as the default.
1750 */
1751 
1752 enum SwapStrategy
1753 {
1754     /**
1755        Allows freely swapping of elements as long as the output
1756        satisfies the algorithm's requirements.
1757     */
1758     unstable,
1759     /**
1760        In algorithms partitioning ranges in two, preserve relative
1761        ordering of elements only to the left of the partition point.
1762     */
1763     semistable,
1764     /**
1765        Preserve the relative ordering of elements to the largest
1766        extent allowed by the algorithm's requirements.
1767     */
1768     stable,
1769 }
1770 
1771 ///
1772 @safe unittest
1773 {
1774     int[] a = [0, 1, 2, 3];
1775     assert(remove!(SwapStrategy.stable)(a, 1) == [0, 2, 3]);
1776     a = [0, 1, 2, 3];
1777     assert(remove!(SwapStrategy.unstable)(a, 1) == [0, 3, 2]);
1778 }
1779 
1780 ///
1781 @safe unittest
1782 {
1783     import std.algorithm.sorting : partition;
1784 
1785     // Put stuff greater than 3 on the left
1786     auto arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
1787     assert(partition!(a => a > 3, SwapStrategy.stable)(arr) == [1, 2, 3]);
1788     assert(arr == [4, 5, 6, 7, 8, 9, 10, 1, 2, 3]);
1789 
1790     arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
1791     assert(partition!(a => a > 3, SwapStrategy.semistable)(arr) == [2, 3, 1]);
1792     assert(arr == [4, 5, 6, 7, 8, 9, 10, 2, 3, 1]);
1793 
1794     arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
1795     assert(partition!(a => a > 3, SwapStrategy.unstable)(arr) == [3, 2, 1]);
1796     assert(arr == [10, 9, 8, 4, 5, 6, 7, 3, 2, 1]);
1797 }
1798 
1799 private template isValidIntegralTuple(T)
1800 {
1801     import std.traits : isIntegral;
1802     import std.typecons : isTuple;
1803     static if (isTuple!T)
1804     {
1805         enum isValidIntegralTuple = T.length == 2 &&
1806                 isIntegral!(typeof(T.init[0])) && isIntegral!(typeof(T.init[0]));
1807     }
1808     else
1809     {
1810         enum isValidIntegralTuple = isIntegral!T;
1811     }
1812 }
1813 
1814 
1815 /**
1816 Eliminates elements at given offsets from `range` and returns the shortened
1817 range.
1818 
1819 For example, here is how to remove a single element from an array:
1820 
1821 ----
1822 string[] a = [ "a", "b", "c", "d" ];
1823 a = a.remove(1); // remove element at offset 1
1824 assert(a == [ "a", "c", "d"]);
1825 ----
1826 
1827 Note that `remove` does not change the length of the original range directly;
1828 instead, it returns the shortened range. If its return value is not assigned to
1829 the original range, the original range will retain its original length, though
1830 its contents will have changed:
1831 
1832 ----
1833 int[] a = [ 3, 5, 7, 8 ];
1834 assert(remove(a, 1) == [ 3, 7, 8 ]);
1835 assert(a == [ 3, 7, 8, 8 ]);
1836 ----
1837 
1838 The element at offset `1` has been removed and the rest of the elements have
1839 shifted up to fill its place, however, the original array remains of the same
1840 length. This is because all functions in `std.algorithm` only change $(I
1841 content), not $(I topology). The value `8` is repeated because $(LREF move) was
1842 invoked to rearrange elements, and on integers `move` simply copies the source
1843 to the destination.  To replace `a` with the effect of the removal, simply
1844 assign the slice returned by `remove` to it, as shown in the first example.
1845 
1846 Multiple indices can be passed into `remove`. In that case,
1847 elements at the respective indices are all removed. The indices must
1848 be passed in increasing order, otherwise an exception occurs.
1849 
1850 ----
1851 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
1852 assert(remove(a, 1, 3, 5) ==
1853     [ 0, 2, 4, 6, 7, 8, 9, 10 ]);
1854 ----
1855 
1856 (Note that all indices refer to slots in the $(I original) array, not
1857 in the array as it is being progressively shortened.)
1858 
1859 Tuples of two integral offsets can be used to remove an indices range:
1860 
1861 ----
1862 int[] a = [ 3, 4, 5, 6, 7];
1863 assert(remove(a, 1, tuple(1, 3), 9) == [ 3, 6, 7 ]);
1864 ----
1865 
1866 The tuple passes in a range closed to the left and open to
1867 the right (consistent with built-in slices), e.g. `tuple(1, 3)`
1868 means indices `1` and `2` but not `3`.
1869 
1870 Finally, any combination of integral offsets and tuples composed of two integral
1871 offsets can be passed in:
1872 
1873 ----
1874 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
1875 assert(remove(a, 1, tuple(3, 5), 9) == [ 0, 2, 5, 6, 7, 8, 10 ]);
1876 ----
1877 
1878 In this case, the slots at positions 1, 3, 4, and 9 are removed from
1879 the array.
1880 
1881 If the need is to remove some elements in the range but the order of
1882 the remaining elements does not have to be preserved, you may want to
1883 pass `SwapStrategy.unstable` to `remove`.
1884 
1885 ----
1886 int[] a = [ 0, 1, 2, 3 ];
1887 assert(remove!(SwapStrategy.unstable)(a, 1) == [ 0, 3, 2 ]);
1888 ----
1889 
1890 In the case above, the element at slot `1` is removed, but replaced
1891 with the last element of the range. Taking advantage of the relaxation
1892 of the stability requirement, `remove` moved elements from the end
1893 of the array over the slots to be removed. This way there is less data
1894 movement to be done which improves the execution time of the function.
1895 
1896 The function `remove` works on bidirectional ranges that have assignable
1897 lvalue elements. The moving strategy is (listed from fastest to slowest):
1898 
1899 $(UL
1900         $(LI If $(D s == SwapStrategy.unstable && isRandomAccessRange!Range &&
1901 hasLength!Range && hasLvalueElements!Range), then elements are moved from the
1902 end of the range into the slots to be filled. In this case, the absolute
1903 minimum of moves is performed.)
1904         $(LI Otherwise, if $(D s ==
1905 SwapStrategy.unstable && isBidirectionalRange!Range && hasLength!Range
1906 && hasLvalueElements!Range), then elements are still moved from the
1907 end of the range, but time is spent on advancing between slots by repeated
1908 calls to `range.popFront`.)
1909         $(LI Otherwise, elements are moved
1910 incrementally towards the front of `range`; a given element is never
1911 moved several times, but more elements are moved than in the previous
1912 cases.)
1913 )
1914 
1915 Params:
1916     s = a SwapStrategy to determine if the original order needs to be preserved
1917     range = a $(REF_ALTTEXT bidirectional range, isBidirectionalRange, std,range,primitives)
1918     with a length member
1919     offset = which element(s) to remove
1920 
1921 Returns:
1922     A range containing all of the elements of range with offset removed.
1923 */
1924 Range remove
1925 (SwapStrategy s = SwapStrategy.stable, Range, Offset ...)
1926 (Range range, Offset offset)
1927 if (Offset.length >= 1 && allSatisfy!(isValidIntegralTuple, Offset))
1928 {
1929     // Activate this check when the deprecation of non-integral tuples is over
1930     //import std.traits : isIntegral;
1931     //import std.typecons : isTuple;
1932     //static foreach (T; Offset)
1933     //{
1934         //static if (isTuple!T)
1935         //{
1936             //static assert(T.length == 2 &&
1937                     //isIntegral!(typeof(T.init[0])) && isIntegral!(typeof(T.init[0])),
1938                 //"Each offset must be an integral or a tuple of two integrals." ~
1939                 //"Use `arr.remove(pos1, pos2)` or `arr.remove(tuple(start, begin))`");
1940         //}
1941         //else
1942         //{
1943             //static assert(isIntegral!T,
1944                 //"Each offset must be an integral or a tuple of two integrals." ~
1945                 //"Use `arr.remove(pos1, pos2)` or `arr.remove(tuple(start, begin))`");
1946         //}
1947     //}
1948     return removeImpl!s(range, offset);
1949 }
1950 
1951 deprecated("Use of non-integral tuples is deprecated. Use remove(tuple(start, end).")
1952 Range remove
1953 (SwapStrategy s = SwapStrategy.stable, Range, Offset ...)
1954 (Range range, Offset offset)
1955 if (Offset.length >= 1 && !allSatisfy!(isValidIntegralTuple, Offset))
1956 {
1957     return removeImpl!s(range, offset);
1958 }
1959 
1960 ///
1961 @safe pure unittest
1962 {
1963     import std.typecons : tuple;
1964 
1965     auto a = [ 0, 1, 2, 3, 4, 5 ];
1966     assert(remove!(SwapStrategy.stable)(a, 1) == [ 0, 2, 3, 4, 5 ]);
1967     a = [ 0, 1, 2, 3, 4, 5 ];
1968     assert(remove!(SwapStrategy.stable)(a, 1, 3) == [ 0, 2, 4, 5] );
1969     a = [ 0, 1, 2, 3, 4, 5 ];
1970     assert(remove!(SwapStrategy.stable)(a, 1, tuple(3, 6)) == [ 0, 2 ]);
1971 
1972     a = [ 0, 1, 2, 3, 4, 5 ];
1973     assert(remove!(SwapStrategy.unstable)(a, 1) == [0, 5, 2, 3, 4]);
1974     a = [ 0, 1, 2, 3, 4, 5 ];
1975     assert(remove!(SwapStrategy.unstable)(a, tuple(1, 4)) == [0, 5, 4]);
1976 }
1977 
1978 ///
1979 @safe pure unittest
1980 {
1981     import std.typecons : tuple;
1982 
1983     // Delete an index
1984     assert([4, 5, 6].remove(1) == [4, 6]);
1985 
1986     // Delete multiple indices
1987     assert([4, 5, 6, 7, 8].remove(1, 3) == [4, 6, 8]);
1988 
1989     // Use an indices range
1990     assert([4, 5, 6, 7, 8].remove(tuple(1, 3)) == [4, 7, 8]);
1991 
1992     // Use an indices range and individual indices
1993     assert([4, 5, 6, 7, 8].remove(0, tuple(1, 3), 4) == [7]);
1994 }
1995 
1996 /// `SwapStrategy.unstable` is faster, but doesn't guarantee the same order of the original array
1997 @safe pure unittest
1998 {
1999     assert([5, 6, 7, 8].remove!(SwapStrategy.stable)(1) == [5, 7, 8]);
2000     assert([5, 6, 7, 8].remove!(SwapStrategy.unstable)(1) == [5, 8, 7]);
2001 }
2002 
2003 private auto removeImpl(SwapStrategy s, Range, Offset...)(Range range, Offset offset)
2004 {
2005     static if (isNarrowString!Range)
2006     {
2007         static assert(isMutable!(typeof(range[0])),
2008                 "Elements must be mutable to remove");
2009         static assert(s == SwapStrategy.stable,
2010                 "Only stable removing can be done for character arrays");
2011         return removeStableString(range, offset);
2012     }
2013     else
2014     {
2015         static assert(isBidirectionalRange!Range,
2016                 "Range must be bidirectional");
2017         static assert(hasLvalueElements!Range,
2018                 "Range must have Lvalue elements (see std.range.hasLvalueElements)");
2019 
2020         static if (s == SwapStrategy.unstable)
2021         {
2022             static assert(hasLength!Range,
2023                     "Range must have `length` for unstable remove");
2024             return removeUnstable(range, offset);
2025         }
2026         else static if (s == SwapStrategy.stable)
2027             return removeStable(range, offset);
2028         else
2029             static assert(false,
2030                     "Only SwapStrategy.stable and SwapStrategy.unstable are supported");
2031     }
2032 }
2033 
2034 @safe unittest
2035 {
2036     import std.exception : assertThrown;
2037     import std.range;
2038 
2039     // https://issues.dlang.org/show_bug.cgi?id=10173
2040     int[] test = iota(0, 10).array();
2041     assertThrown(remove!(SwapStrategy.stable)(test, tuple(2, 4), tuple(1, 3)));
2042     assertThrown(remove!(SwapStrategy.unstable)(test, tuple(2, 4), tuple(1, 3)));
2043     assertThrown(remove!(SwapStrategy.stable)(test, 2, 4, 1, 3));
2044     assertThrown(remove!(SwapStrategy.unstable)(test, 2, 4, 1, 3));
2045 }
2046 
2047 @safe unittest
2048 {
2049     import std.range;
2050     int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2051     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2052     assert(remove!(SwapStrategy.stable)(a, 1) ==
2053         [ 0, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]);
2054 
2055     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2056     assert(remove!(SwapStrategy.unstable)(a, 0, 10) ==
2057            [ 9, 1, 2, 3, 4, 5, 6, 7, 8 ]);
2058 
2059     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2060     assert(remove!(SwapStrategy.unstable)(a, 0, tuple(9, 11)) ==
2061             [ 8, 1, 2, 3, 4, 5, 6, 7 ]);
2062     // https://issues.dlang.org/show_bug.cgi?id=5224
2063     a = [ 1, 2, 3, 4 ];
2064     assert(remove!(SwapStrategy.unstable)(a, 2) ==
2065            [ 1, 2, 4 ]);
2066 
2067     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2068     assert(remove!(SwapStrategy.stable)(a, 1, 5) ==
2069         [ 0, 2, 3, 4, 6, 7, 8, 9, 10 ]);
2070 
2071     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2072     assert(remove!(SwapStrategy.stable)(a, 1, 3, 5)
2073             == [ 0, 2, 4, 6, 7, 8, 9, 10]);
2074     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2075     assert(remove!(SwapStrategy.stable)(a, 1, tuple(3, 5))
2076             == [ 0, 2, 5, 6, 7, 8, 9, 10]);
2077 
2078     a = iota(0, 10).array();
2079     assert(remove!(SwapStrategy.unstable)(a, tuple(1, 4), tuple(6, 7))
2080             == [0, 9, 8, 7, 4, 5]);
2081 }
2082 
2083 // https://issues.dlang.org/show_bug.cgi?id=11576
2084 @safe unittest
2085 {
2086     auto arr = [1,2,3];
2087     arr = arr.remove!(SwapStrategy.unstable)(2);
2088     assert(arr == [1,2]);
2089 
2090 }
2091 
2092 // https://issues.dlang.org/show_bug.cgi?id=12889
2093 @safe unittest
2094 {
2095     import std.range;
2096     int[1][] arr = [[0], [1], [2], [3], [4], [5], [6]];
2097     auto orig = arr.dup;
2098     foreach (i; iota(arr.length))
2099     {
2100         assert(orig == arr.remove!(SwapStrategy.unstable)(tuple(i,i)));
2101         assert(orig == arr.remove!(SwapStrategy.stable)(tuple(i,i)));
2102     }
2103 }
2104 
2105 @safe unittest
2106 {
2107     char[] chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
2108     remove(chars, 4);
2109     assert(chars == ['a', 'b', 'c', 'd', 'f', 'g', 'h', 'h']);
2110 
2111     char[] bigChars = "∑œ∆¬é˚˙ƒé∂ß¡¡".dup;
2112     assert(remove(bigChars, tuple(4, 6), 8) == ("∑œ∆¬˙ƒ∂ß¡¡"));
2113 
2114     import std.exception : assertThrown;
2115     assertThrown(remove(bigChars.dup, 1, 0));
2116     assertThrown(remove(bigChars.dup, tuple(4, 3)));
2117 }
2118 
2119 private Range removeUnstable(Range, Offset...)(Range range, Offset offset)
2120 {
2121     Tuple!(size_t, "pos", size_t, "len")[offset.length] blackouts;
2122     foreach (i, v; offset)
2123     {
2124         static if (is(typeof(v[0]) : size_t) && is(typeof(v[1]) : size_t))
2125         {
2126             blackouts[i].pos = v[0];
2127             blackouts[i].len = v[1] - v[0];
2128         }
2129         else
2130         {
2131             static assert(is(typeof(v) : size_t), typeof(v).stringof);
2132             blackouts[i].pos = v;
2133             blackouts[i].len = 1;
2134         }
2135         static if (i > 0)
2136         {
2137             import std.exception : enforce;
2138 
2139             enforce(blackouts[i - 1].pos + blackouts[i - 1].len
2140                     <= blackouts[i].pos,
2141                 "remove(): incorrect ordering of elements to remove");
2142         }
2143     }
2144 
2145     size_t left = 0, right = offset.length - 1;
2146     auto tgt = range.save;
2147     size_t tgtPos = 0;
2148 
2149     while (left <= right)
2150     {
2151         // Look for a blackout on the right
2152         if (blackouts[right].pos + blackouts[right].len >= range.length)
2153         {
2154             range.popBackExactly(blackouts[right].len);
2155 
2156             // Since right is unsigned, we must check for this case, otherwise
2157             // we might turn it into size_t.max and the loop condition will not
2158             // fail when it should.
2159             if (right > 0)
2160             {
2161                 --right;
2162                 continue;
2163             }
2164             else
2165                 break;
2166         }
2167         // Advance to next blackout on the left
2168         assert(blackouts[left].pos >= tgtPos, "Next blackout on the left shouldn't appear before the target.");
2169         tgt.popFrontExactly(blackouts[left].pos - tgtPos);
2170         tgtPos = blackouts[left].pos;
2171 
2172         // Number of elements to the right of blackouts[right]
2173         immutable tailLen = range.length - (blackouts[right].pos + blackouts[right].len);
2174         size_t toMove = void;
2175         if (tailLen < blackouts[left].len)
2176         {
2177             toMove = tailLen;
2178             blackouts[left].pos += toMove;
2179             blackouts[left].len -= toMove;
2180         }
2181         else
2182         {
2183             toMove = blackouts[left].len;
2184             ++left;
2185         }
2186         tgtPos += toMove;
2187         foreach (i; 0 .. toMove)
2188         {
2189             move(range.back, tgt.front);
2190             range.popBack();
2191             tgt.popFront();
2192         }
2193     }
2194 
2195     return range;
2196 }
2197 
2198 private Range removeStable(Range, Offset...)(Range range, Offset offset)
2199 {
2200     auto result = range;
2201     auto src = range, tgt = range;
2202     size_t pos;
2203     foreach (pass, i; offset)
2204     {
2205         static if (is(typeof(i[0])) && is(typeof(i[1])))
2206         {
2207             auto from = i[0], delta = i[1] - i[0];
2208         }
2209         else
2210         {
2211             auto from = i;
2212             enum delta = 1;
2213         }
2214 
2215         static if (pass > 0)
2216         {
2217             import std.exception : enforce;
2218             enforce(pos <= from,
2219                     "remove(): incorrect ordering of elements to remove");
2220 
2221             for (; pos < from; ++pos, src.popFront(), tgt.popFront())
2222             {
2223                 move(src.front, tgt.front);
2224             }
2225         }
2226         else
2227         {
2228             src.popFrontExactly(from);
2229             tgt.popFrontExactly(from);
2230             pos = from;
2231         }
2232         // now skip source to the "to" position
2233         src.popFrontExactly(delta);
2234         result.popBackExactly(delta);
2235         pos += delta;
2236     }
2237     // leftover move
2238     moveAll(src, tgt);
2239     return result;
2240 }
2241 
2242 private Range removeStableString(Range, Offset...)(Range range, Offset offsets)
2243 {
2244     import std.utf : stride;
2245     size_t charIdx = 0;
2246     size_t dcharIdx = 0;
2247     size_t charShift = 0;
2248 
2249     void skipOne()
2250     {
2251         charIdx += stride(range[charIdx .. $]);
2252         ++dcharIdx;
2253     }
2254 
2255     void copyBackOne()
2256     {
2257         auto encodedLen = stride(range[charIdx .. $]);
2258         foreach (j; charIdx .. charIdx + encodedLen)
2259             range[j - charShift] = range[j];
2260         charIdx += encodedLen;
2261         ++dcharIdx;
2262     }
2263 
2264     foreach (pass, i; offsets)
2265     {
2266         static if (is(typeof(i[0])) && is(typeof(i[1])))
2267         {
2268             auto from = i[0];
2269             auto delta = i[1] - i[0];
2270         }
2271         else
2272         {
2273             auto from = i;
2274             enum delta = 1;
2275         }
2276 
2277         import std.exception : enforce;
2278         enforce(dcharIdx <= from && delta >= 0,
2279                 "remove(): incorrect ordering of elements to remove");
2280 
2281         while (dcharIdx < from)
2282             static if (pass == 0)
2283                 skipOne();
2284             else
2285                 copyBackOne();
2286 
2287         auto mark = charIdx;
2288         while (dcharIdx < from + delta)
2289             skipOne();
2290         charShift += charIdx - mark;
2291     }
2292 
2293     foreach (i; charIdx .. range.length)
2294         range[i - charShift] = range[i];
2295 
2296     return range[0 .. $ - charShift];
2297 }
2298 
2299 // Use of dynamic arrays as offsets is too error-prone
2300 // https://issues.dlang.org/show_bug.cgi?id=12086
2301 // Activate these tests once the deprecation period of remove with non-integral tuples is over
2302 @safe unittest
2303 {
2304     //static assert(!__traits(compiles, [0, 1, 2, 3, 4].remove([1, 3]) == [0, 3, 4]));
2305     static assert(__traits(compiles, [0, 1, 2, 3, 4].remove(1, 3) == [0, 2, 4]));
2306     //static assert(!__traits(compiles, assert([0, 1, 2, 3, 4].remove([1, 3, 4]) == [0, 3, 4])));
2307     //static assert(!__traits(compiles, assert([0, 1, 2, 3, 4].remove(tuple(1, 3, 4)) == [0, 3, 4])));
2308 
2309     import std.range : only;
2310     //static assert(!__traits(compiles, assert([0, 1, 2, 3, 4].remove(only(1, 3)) == [0, 3, 4])));
2311     static assert(__traits(compiles, assert([0, 1, 2, 3, 4].remove(1, 3) == [0, 2, 4])));
2312 }
2313 
2314 /**
2315 Reduces the length of the
2316 $(REF_ALTTEXT bidirectional range, isBidirectionalRange, std,range,primitives) `range` by removing
2317 elements that satisfy `pred`. If `s = SwapStrategy.unstable`,
2318 elements are moved from the right end of the range over the elements
2319 to eliminate. If `s = SwapStrategy.stable` (the default),
2320 elements are moved progressively to front such that their relative
2321 order is preserved. Returns the filtered range.
2322 
2323 Params:
2324     range = a bidirectional ranges with lvalue elements
2325         or mutable character arrays
2326 
2327 Returns:
2328     the range with all of the elements where `pred` is `true`
2329     removed
2330 */
2331 Range remove(alias pred, SwapStrategy s = SwapStrategy.stable, Range)(Range range)
2332 {
2333     import std.functional : unaryFun;
2334     alias pred_ = unaryFun!pred;
2335     static if (isNarrowString!Range)
2336     {
2337         static assert(isMutable!(typeof(range[0])),
2338                 "Elements must be mutable to remove");
2339         static assert(s == SwapStrategy.stable,
2340                 "Only stable removing can be done for character arrays");
2341         return removePredString!pred_(range);
2342     }
2343     else
2344     {
2345         static assert(isBidirectionalRange!Range,
2346                 "Range must be bidirectional");
2347         static assert(hasLvalueElements!Range,
2348                 "Range must have Lvalue elements (see std.range.hasLvalueElements)");
2349         static if (s == SwapStrategy.unstable)
2350             return removePredUnstable!pred_(range);
2351         else static if (s == SwapStrategy.stable)
2352             return removePredStable!pred_(range);
2353         else
2354             static assert(false,
2355                     "Only SwapStrategy.stable and SwapStrategy.unstable are supported");
2356     }
2357 }
2358 
2359 ///
2360 @safe unittest
2361 {
2362     static immutable base = [1, 2, 3, 2, 4, 2, 5, 2];
2363 
2364     int[] arr = base[].dup;
2365 
2366     // using a string-based predicate
2367     assert(remove!("a == 2")(arr) == [ 1, 3, 4, 5 ]);
2368 
2369     // The original array contents have been modified,
2370     // so we need to reset it to its original state.
2371     // The length is unmodified however.
2372     arr[] = base[];
2373 
2374     // using a lambda predicate
2375     assert(remove!(a => a == 2)(arr) == [ 1, 3, 4, 5 ]);
2376 }
2377 
2378 @safe unittest
2379 {
2380     int[] a = [ 1, 2, 3, 2, 3, 4, 5, 2, 5, 6 ];
2381     assert(remove!("a == 2", SwapStrategy.unstable)(a) ==
2382             [ 1, 6, 3, 5, 3, 4, 5 ]);
2383     a = [ 1, 2, 3, 2, 3, 4, 5, 2, 5, 6 ];
2384     assert(remove!("a == 2", SwapStrategy.stable)(a) ==
2385             [ 1, 3, 3, 4, 5, 5, 6 ]);
2386 }
2387 
2388 @nogc @safe unittest
2389 {
2390     // @nogc test
2391     static int[] arr = [0,1,2,3,4,5,6,7,8,9];
2392     alias pred = e => e < 5;
2393 
2394     auto r = arr[].remove!(SwapStrategy.unstable)(0);
2395     r = r.remove!(SwapStrategy.stable)(0);
2396     r = r.remove!(pred, SwapStrategy.unstable);
2397     r = r.remove!(pred, SwapStrategy.stable);
2398 }
2399 
2400 @safe unittest
2401 {
2402     import std.algorithm.comparison : min;
2403     import std.algorithm.searching : all, any;
2404     import std.algorithm.sorting : isStrictlyMonotonic;
2405     import std.array : array;
2406     import std.meta : AliasSeq;
2407     import std.range : iota, only;
2408     import std.typecons : Tuple;
2409     alias E = Tuple!(int, int);
2410     alias S = Tuple!(E);
2411     S[] soffsets;
2412     foreach (start; 0 .. 5)
2413     foreach (end; min(start+1,5) .. 5)
2414           soffsets ~= S(E(start,end));
2415     alias D = Tuple!(E, E);
2416     D[] doffsets;
2417     foreach (start1; 0 .. 10)
2418     foreach (end1; min(start1+1,10) .. 10)
2419     foreach (start2; end1 .. 10)
2420     foreach (end2; min(start2+1,10) .. 10)
2421           doffsets ~= D(E(start1,end1),E(start2,end2));
2422     alias T = Tuple!(E, E, E);
2423     T[] toffsets;
2424     foreach (start1; 0 .. 15)
2425     foreach (end1; min(start1+1,15) .. 15)
2426     foreach (start2; end1 .. 15)
2427     foreach (end2; min(start2+1,15) .. 15)
2428     foreach (start3; end2 .. 15)
2429     foreach (end3; min(start3+1,15) .. 15)
2430             toffsets ~= T(E(start1,end1),E(start2,end2),E(start3,end3));
2431 
2432     static void verify(O...)(int[] r, int len, int removed, bool stable, O offsets)
2433     {
2434         assert(r.length == len - removed);
2435         assert(!stable || r.isStrictlyMonotonic);
2436         assert(r.all!(e => all!(o => e < o[0] || e >= o[1])(offsets.only)));
2437     }
2438 
2439     static foreach (offsets; AliasSeq!(soffsets,doffsets,toffsets))
2440     foreach (os; offsets)
2441     {
2442         int len = 5*os.length;
2443         auto w = iota(0, len).array;
2444         auto x = w.dup;
2445         auto y = w.dup;
2446         auto z = w.dup;
2447         alias pred = e => any!(o => o[0] <= e && e < o[1])(only(os.expand));
2448         w = w.remove!(SwapStrategy.unstable)(os.expand);
2449         x = x.remove!(SwapStrategy.stable)(os.expand);
2450         y = y.remove!(pred, SwapStrategy.unstable);
2451         z = z.remove!(pred, SwapStrategy.stable);
2452         int removed;
2453         foreach (o; os)
2454             removed += o[1] - o[0];
2455         verify(w, len, removed, false, os[]);
2456         verify(x, len, removed, true, os[]);
2457         verify(y, len, removed, false, os[]);
2458         verify(z, len, removed, true, os[]);
2459         assert(w == y);
2460         assert(x == z);
2461     }
2462 }
2463 
2464 @safe unittest
2465 {
2466     char[] chars = "abcdefg".dup;
2467     assert(chars.remove!(dc => dc == 'c' || dc == 'f') == "abdeg");
2468     assert(chars == "abdegfg");
2469 
2470     assert(chars.remove!"a == 'd'" == "abegfg");
2471 
2472     char[] bigChars = "¥^¨^©é√∆π".dup;
2473     assert(bigChars.remove!(dc => dc == "¨"d[0] || dc == "é"d[0]) ==  "¥^^©√∆π");
2474 }
2475 
2476 private Range removePredUnstable(alias pred, Range)(Range range)
2477 {
2478     auto result = range;
2479     for (;!range.empty;)
2480     {
2481         if (!pred(range.front))
2482         {
2483             range.popFront();
2484             continue;
2485         }
2486         move(range.back, range.front);
2487         range.popBack();
2488         result.popBack();
2489     }
2490     return result;
2491 }
2492 
2493 private Range removePredStable(alias pred, Range)(Range range)
2494 {
2495     auto result = range;
2496     auto tgt = range;
2497     for (; !range.empty; range.popFront())
2498     {
2499         if (pred(range.front))
2500         {
2501             // yank this guy
2502             result.popBack();
2503             continue;
2504         }
2505         // keep this guy
2506         move(range.front, tgt.front);
2507         tgt.popFront();
2508     }
2509     return result;
2510 }
2511 
2512 private Range removePredString(alias pred, SwapStrategy s = SwapStrategy.stable, Range)
2513 (Range range)
2514 {
2515     import std.utf : decode;
2516     import std.functional : unaryFun;
2517 
2518     alias pred_ = unaryFun!pred;
2519 
2520     size_t charIdx = 0;
2521     size_t charShift = 0;
2522     while (charIdx < range.length)
2523     {
2524         size_t start = charIdx;
2525         if (pred_(decode(range, charIdx)))
2526         {
2527             charShift += charIdx - start;
2528             break;
2529         }
2530     }
2531     while (charIdx < range.length)
2532     {
2533         size_t start = charIdx;
2534         auto doRemove = pred_(decode(range, charIdx));
2535         auto encodedLen = charIdx - start;
2536         if (doRemove)
2537             charShift += encodedLen;
2538         else
2539             foreach (i; start .. charIdx)
2540                 range[i - charShift] = range[i];
2541     }
2542 
2543     return range[0 .. $ - charShift];
2544 }
2545 
2546 // reverse
2547 /**
2548 Reverses `r` in-place.  Performs `r.length / 2` evaluations of `swap`.
2549 UTF sequences consisting of multiple code units are preserved properly.
2550 
2551 Params:
2552     r = a $(REF_ALTTEXT bidirectional range, isBidirectionalRange, std,range,primitives)
2553         with either swappable elements, a random access range with a length member,
2554         or a narrow string
2555 
2556 Returns: `r`
2557 
2558 Note:
2559     When passing a string with unicode modifiers on characters, such as `\u0301`,
2560     this function will not properly keep the position of the modifier. For example,
2561     reversing `ba\u0301d` ("bád") will result in d\u0301ab ("d́ab") instead of
2562     `da\u0301b` ("dáb").
2563 
2564 See_Also: $(REF retro, std,range) for a lazy reverse without changing `r`
2565 */
2566 Range reverse(Range)(Range r)
2567 if (isBidirectionalRange!Range &&
2568         (hasSwappableElements!Range ||
2569          (hasAssignableElements!Range && hasLength!Range && isRandomAccessRange!Range) ||
2570          (isNarrowString!Range && isAssignable!(ElementType!Range))))
2571 {
2572     static if (isRandomAccessRange!Range && hasLength!Range)
2573     {
2574         //swapAt is in fact the only way to swap non lvalue ranges
2575         immutable last = r.length - 1;
2576         immutable steps = r.length / 2;
2577         for (size_t i = 0; i < steps; i++)
2578         {
2579             r.swapAt(i, last - i);
2580         }
2581         return r;
2582     }
2583     else static if (isNarrowString!Range && isAssignable!(ElementType!Range))
2584     {
2585         import std.string : representation;
2586         import std.utf : stride;
2587 
2588         auto raw = representation(r);
2589         for (size_t i = 0; i < r.length;)
2590         {
2591             immutable step = stride(r, i);
2592             if (step > 1)
2593             {
2594                 .reverse(raw[i .. i + step]);
2595                 i += step;
2596             }
2597             else
2598             {
2599                 ++i;
2600             }
2601         }
2602         reverse(raw);
2603         return r;
2604     }
2605     else
2606     {
2607         while (!r.empty)
2608         {
2609             swap(r.front, r.back);
2610             r.popFront();
2611             if (r.empty) break;
2612             r.popBack();
2613         }
2614         return r;
2615     }
2616 }
2617 
2618 ///
2619 @safe unittest
2620 {
2621     int[] arr = [ 1, 2, 3 ];
2622     assert(arr.reverse == [ 3, 2, 1 ]);
2623 }
2624 
2625 @safe unittest
2626 {
2627     int[] range = null;
2628     reverse(range);
2629     range = [ 1 ];
2630     reverse(range);
2631     assert(range == [1]);
2632     range = [1, 2];
2633     reverse(range);
2634     assert(range == [2, 1]);
2635     range = [1, 2, 3];
2636     assert(range.reverse == [3, 2, 1]);
2637 }
2638 
2639 ///
2640 @safe unittest
2641 {
2642     char[] arr = "hello\U00010143\u0100\U00010143".dup;
2643     assert(arr.reverse == "\U00010143\u0100\U00010143olleh");
2644 }
2645 
2646 @safe unittest
2647 {
2648     void test(string a, string b)
2649     {
2650         auto c = a.dup;
2651         reverse(c);
2652         assert(c == b, c ~ " != " ~ b);
2653     }
2654 
2655     test("a", "a");
2656     test(" ", " ");
2657     test("\u2029", "\u2029");
2658     test("\u0100", "\u0100");
2659     test("\u0430", "\u0430");
2660     test("\U00010143", "\U00010143");
2661     test("abcdefcdef", "fedcfedcba");
2662     test("hello\U00010143\u0100\U00010143", "\U00010143\u0100\U00010143olleh");
2663 }
2664 
2665 /**
2666     The strip group of functions allow stripping of either leading, trailing,
2667     or both leading and trailing elements.
2668 
2669     The `stripLeft` function will strip the `front` of the range,
2670     the `stripRight` function will strip the `back` of the range,
2671     while the `strip` function will strip both the `front` and `back`
2672     of the range.
2673 
2674     Note that the `strip` and `stripRight` functions require the range to
2675     be a $(LREF BidirectionalRange) range.
2676 
2677     All of these functions come in two varieties: one takes a target element,
2678     where the range will be stripped as long as this element can be found.
2679     The other takes a lambda predicate, where the range will be stripped as
2680     long as the predicate returns true.
2681 
2682     Params:
2683         range = a $(REF_ALTTEXT bidirectional range, isBidirectionalRange, std,range,primitives)
2684         or $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
2685         element = the elements to remove
2686 
2687     Returns:
2688         a Range with all of range except element at the start and end
2689 */
2690 Range strip(Range, E)(Range range, E element)
2691 if (isBidirectionalRange!Range && is(typeof(range.front == element) : bool))
2692 {
2693     return range.stripLeft(element).stripRight(element);
2694 }
2695 
2696 /// ditto
2697 Range strip(alias pred, Range)(Range range)
2698 if (isBidirectionalRange!Range && is(typeof(pred(range.back)) : bool))
2699 {
2700     return range.stripLeft!pred().stripRight!pred();
2701 }
2702 
2703 /// ditto
2704 Range stripLeft(Range, E)(Range range, E element)
2705 if (isInputRange!Range && is(typeof(range.front == element) : bool))
2706 {
2707     import std.algorithm.searching : find;
2708     return find!((auto ref a) => a != element)(range);
2709 }
2710 
2711 /// ditto
2712 Range stripLeft(alias pred, Range)(Range range)
2713 if (isInputRange!Range && is(typeof(pred(range.front)) : bool))
2714 {
2715     import std.algorithm.searching : find;
2716     import std.functional : not;
2717 
2718     return find!(not!pred)(range);
2719 }
2720 
2721 /// ditto
2722 Range stripRight(Range, E)(Range range, E element)
2723 if (isBidirectionalRange!Range && is(typeof(range.back == element) : bool))
2724 {
2725     for (; !range.empty; range.popBack())
2726     {
2727         if (range.back != element)
2728             break;
2729     }
2730     return range;
2731 }
2732 
2733 /// ditto
2734 Range stripRight(alias pred, Range)(Range range)
2735 if (isBidirectionalRange!Range && is(typeof(pred(range.back)) : bool))
2736 {
2737     for (; !range.empty; range.popBack())
2738     {
2739         if (!pred(range.back))
2740             break;
2741     }
2742     return range;
2743 }
2744 
2745 /// Strip leading and trailing elements equal to the target element.
2746 @safe pure unittest
2747 {
2748     assert("  foobar  ".strip(' ') == "foobar");
2749     assert("00223.444500".strip('0') == "223.4445");
2750     assert("ëëêéüŗōpéêëë".strip('ë') == "êéüŗōpéê");
2751     assert([1, 1, 0, 1, 1].strip(1) == [0]);
2752     assert([0.0, 0.01, 0.01, 0.0].strip(0).length == 2);
2753 }
2754 
2755 /// Strip leading and trailing elements while the predicate returns true.
2756 @safe pure unittest
2757 {
2758     assert("  foobar  ".strip!(a => a == ' ')() == "foobar");
2759     assert("00223.444500".strip!(a => a == '0')() == "223.4445");
2760     assert("ëëêéüŗōpéêëë".strip!(a => a == 'ë')() == "êéüŗōpéê");
2761     assert([1, 1, 0, 1, 1].strip!(a => a == 1)() == [0]);
2762     assert([0.0, 0.01, 0.5, 0.6, 0.01, 0.0].strip!(a => a < 0.4)().length == 2);
2763 }
2764 
2765 /// Strip leading elements equal to the target element.
2766 @safe pure unittest
2767 {
2768     assert("  foobar  ".stripLeft(' ') == "foobar  ");
2769     assert("00223.444500".stripLeft('0') == "223.444500");
2770     assert("ůůűniçodêéé".stripLeft('ů') == "űniçodêéé");
2771     assert([1, 1, 0, 1, 1].stripLeft(1) == [0, 1, 1]);
2772     assert([0.0, 0.01, 0.01, 0.0].stripLeft(0).length == 3);
2773 }
2774 
2775 /// Strip leading elements while the predicate returns true.
2776 @safe pure unittest
2777 {
2778     assert("  foobar  ".stripLeft!(a => a == ' ')() == "foobar  ");
2779     assert("00223.444500".stripLeft!(a => a == '0')() == "223.444500");
2780     assert("ůůűniçodêéé".stripLeft!(a => a == 'ů')() == "űniçodêéé");
2781     assert([1, 1, 0, 1, 1].stripLeft!(a => a == 1)() == [0, 1, 1]);
2782     assert([0.0, 0.01, 0.10, 0.5, 0.6].stripLeft!(a => a < 0.4)().length == 2);
2783 }
2784 
2785 /// Strip trailing elements equal to the target element.
2786 @safe pure unittest
2787 {
2788     assert("  foobar  ".stripRight(' ') == "  foobar");
2789     assert("00223.444500".stripRight('0') == "00223.4445");
2790     assert("ùniçodêéé".stripRight('é') == "ùniçodê");
2791     assert([1, 1, 0, 1, 1].stripRight(1) == [1, 1, 0]);
2792     assert([0.0, 0.01, 0.01, 0.0].stripRight(0).length == 3);
2793 }
2794 
2795 /// Strip trailing elements while the predicate returns true.
2796 @safe pure unittest
2797 {
2798     assert("  foobar  ".stripRight!(a => a == ' ')() == "  foobar");
2799     assert("00223.444500".stripRight!(a => a == '0')() == "00223.4445");
2800     assert("ùniçodêéé".stripRight!(a => a == 'é')() == "ùniçodê");
2801     assert([1, 1, 0, 1, 1].stripRight!(a => a == 1)() == [1, 1, 0]);
2802     assert([0.0, 0.01, 0.10, 0.5, 0.6].stripRight!(a => a > 0.4)().length == 3);
2803 }
2804 
2805 // swap
2806 /**
2807 Swaps `lhs` and `rhs`. The instances `lhs` and `rhs` are moved in
2808 memory, without ever calling `opAssign`, nor any other function. `T`
2809 need not be assignable at all to be swapped.
2810 
2811 If `lhs` and `rhs` reference the same instance, then nothing is done.
2812 
2813 `lhs` and `rhs` must be mutable. If `T` is a struct or union, then
2814 its fields must also all be (recursively) mutable.
2815 
2816 Params:
2817     lhs = Data to be swapped with `rhs`.
2818     rhs = Data to be swapped with `lhs`.
2819 */
2820 void swap(T)(ref T lhs, ref T rhs) @trusted pure nothrow @nogc
2821 if (isBlitAssignable!T && !is(typeof(lhs.proxySwap(rhs))))
2822 {
2823     import std.traits : hasAliasing, hasElaborateAssign, isAssignable,
2824                         isStaticArray;
2825     static if (hasAliasing!T) if (!__ctfe)
2826     {
2827         import std.exception : doesPointTo;
2828         assert(!doesPointTo(lhs, lhs), "Swap: lhs internal pointer.");
2829         assert(!doesPointTo(rhs, rhs), "Swap: rhs internal pointer.");
2830         assert(!doesPointTo(lhs, rhs), "Swap: lhs points to rhs.");
2831         assert(!doesPointTo(rhs, lhs), "Swap: rhs points to lhs.");
2832     }
2833 
2834     static if (hasElaborateAssign!T || !isAssignable!T)
2835     {
2836         if (&lhs != &rhs)
2837         {
2838             // For structs with non-trivial assignment, move memory directly
2839             ubyte[T.sizeof] t = void;
2840             auto a = (cast(ubyte*) &lhs)[0 .. T.sizeof];
2841             auto b = (cast(ubyte*) &rhs)[0 .. T.sizeof];
2842             t[] = a[];
2843             a[] = b[];
2844             b[] = t[];
2845         }
2846     }
2847     else
2848     {
2849         //Avoid assigning overlapping arrays. Dynamic arrays are fine, because
2850         //it's their ptr and length properties which get assigned rather
2851         //than their elements when assigning them, but static arrays are value
2852         //types and therefore all of their elements get copied as part of
2853         //assigning them, which would be assigning overlapping arrays if lhs
2854         //and rhs were the same array.
2855         static if (isStaticArray!T)
2856         {
2857             if (lhs.ptr == rhs.ptr)
2858                 return;
2859         }
2860 
2861         // For non-elaborate-assign types, suffice to do the classic swap
2862         static if (__traits(hasCopyConstructor, T))
2863         {
2864             // don't invoke any elaborate constructors either
2865             T tmp = void;
2866             tmp = lhs;
2867         }
2868         else
2869             auto tmp = lhs;
2870         lhs = rhs;
2871         rhs = tmp;
2872     }
2873 }
2874 
2875 ///
2876 @safe unittest
2877 {
2878     // Swapping POD (plain old data) types:
2879     int a = 42, b = 34;
2880     swap(a, b);
2881     assert(a == 34 && b == 42);
2882 
2883     // Swapping structs with indirection:
2884     static struct S { int x; char c; int[] y; }
2885     S s1 = { 0, 'z', [ 1, 2 ] };
2886     S s2 = { 42, 'a', [ 4, 6 ] };
2887     swap(s1, s2);
2888     assert(s1.x == 42);
2889     assert(s1.c == 'a');
2890     assert(s1.y == [ 4, 6 ]);
2891 
2892     assert(s2.x == 0);
2893     assert(s2.c == 'z');
2894     assert(s2.y == [ 1, 2 ]);
2895 
2896     // Immutables cannot be swapped:
2897     immutable int imm1 = 1, imm2 = 2;
2898     static assert(!__traits(compiles, swap(imm1, imm2)));
2899 
2900     int c = imm1 + 0;
2901     int d = imm2 + 0;
2902     swap(c, d);
2903     assert(c == 2);
2904     assert(d == 1);
2905 }
2906 
2907 ///
2908 @safe unittest
2909 {
2910     // Non-copyable types can still be swapped.
2911     static struct NoCopy
2912     {
2913         this(this) { assert(0); }
2914         int n;
2915         string s;
2916     }
2917     NoCopy nc1, nc2;
2918     nc1.n = 127; nc1.s = "abc";
2919     nc2.n = 513; nc2.s = "uvwxyz";
2920 
2921     swap(nc1, nc2);
2922     assert(nc1.n == 513 && nc1.s == "uvwxyz");
2923     assert(nc2.n == 127 && nc2.s == "abc");
2924 
2925     swap(nc1, nc1);
2926     swap(nc2, nc2);
2927     assert(nc1.n == 513 && nc1.s == "uvwxyz");
2928     assert(nc2.n == 127 && nc2.s == "abc");
2929 
2930     // Types containing non-copyable fields can also be swapped.
2931     static struct NoCopyHolder
2932     {
2933         NoCopy noCopy;
2934     }
2935     NoCopyHolder h1, h2;
2936     h1.noCopy.n = 31; h1.noCopy.s = "abc";
2937     h2.noCopy.n = 65; h2.noCopy.s = null;
2938 
2939     swap(h1, h2);
2940     assert(h1.noCopy.n == 65 && h1.noCopy.s == null);
2941     assert(h2.noCopy.n == 31 && h2.noCopy.s == "abc");
2942 
2943     swap(h1, h1);
2944     swap(h2, h2);
2945     assert(h1.noCopy.n == 65 && h1.noCopy.s == null);
2946     assert(h2.noCopy.n == 31 && h2.noCopy.s == "abc");
2947 
2948     // Const types cannot be swapped.
2949     const NoCopy const1, const2;
2950     assert(const1.n == 0 && const2.n == 0);
2951     static assert(!__traits(compiles, swap(const1, const2)));
2952 }
2953 
2954 // https://issues.dlang.org/show_bug.cgi?id=4789
2955 @safe unittest
2956 {
2957     int[1] s = [1];
2958     swap(s, s);
2959 
2960     int[3] a = [1, 2, 3];
2961     swap(a[1], a[2]);
2962     assert(a == [1, 3, 2]);
2963 }
2964 
2965 @safe unittest
2966 {
2967     static struct NoAssign
2968     {
2969         int i;
2970         void opAssign(NoAssign) @disable;
2971     }
2972     auto s1 = NoAssign(1);
2973     auto s2 = NoAssign(2);
2974     swap(s1, s2);
2975     assert(s1.i == 2);
2976     assert(s2.i == 1);
2977 }
2978 
2979 @safe unittest
2980 {
2981     struct S
2982     {
2983         const int i;
2984         int i2 = 2;
2985         int i3 = 3;
2986     }
2987     S s;
2988     static assert(!__traits(compiles, swap(s, s)));
2989     swap(s.i2, s.i3);
2990     assert(s.i2 == 3);
2991     assert(s.i3 == 2);
2992 }
2993 
2994 // https://issues.dlang.org/show_bug.cgi?id=11853
2995 @safe unittest
2996 {
2997     import std.traits : isAssignable;
2998     alias T = Tuple!(int, double);
2999     static assert(isAssignable!T);
3000 }
3001 
3002 // https://issues.dlang.org/show_bug.cgi?id=12024
3003 @safe unittest
3004 {
3005     import std.datetime;
3006     SysTime a, b;
3007     swap(a, b);
3008 }
3009 
3010 // https://issues.dlang.org/show_bug.cgi?id=9975
3011 @system unittest
3012 {
3013     import std.exception : doesPointTo, mayPointTo;
3014     static struct S2
3015     {
3016         union
3017         {
3018             size_t sz;
3019             string s;
3020         }
3021     }
3022     S2 a , b;
3023     a.sz = -1;
3024     assert(!doesPointTo(a, b));
3025     assert( mayPointTo(a, b));
3026     swap(a, b);
3027 
3028     //Note: we can catch an error here, because there is no RAII in this test
3029     import std.exception : assertThrown;
3030     void* p, pp;
3031     p = &p;
3032     assertThrown!Error(move(p));
3033     assertThrown!Error(move(p, pp));
3034     assertThrown!Error(swap(p, pp));
3035 }
3036 
3037 @system unittest
3038 {
3039     static struct A
3040     {
3041         int* x;
3042         this(this) { x = new int; }
3043     }
3044     A a1, a2;
3045     swap(a1, a2);
3046 
3047     static struct B
3048     {
3049         int* x;
3050         void opAssign(B) { x = new int; }
3051     }
3052     B b1, b2;
3053     swap(b1, b2);
3054 }
3055 
3056 // issue 20732
3057 @safe unittest
3058 {
3059     static struct A
3060     {
3061         int x;
3062         this(scope ref return const A other)
3063         {
3064             import std.stdio;
3065             x = other.x;
3066             // note, struct functions inside @safe functions infer ALL
3067             // attributes, so the following 3 lines are meant to prevent this.
3068             new int; // prevent @nogc inference
3069             writeln("impure"); // prevent pure inference
3070             throw new Exception(""); // prevent nothrow inference
3071         }
3072     }
3073 
3074     A a1, a2;
3075     swap(a1, a2);
3076 
3077     A[1] a3, a4;
3078     swap(a3, a4);
3079 }
3080 
3081 /// ditto
3082 void swap(T)(ref T lhs, ref T rhs)
3083 if (is(typeof(lhs.proxySwap(rhs))))
3084 {
3085     lhs.proxySwap(rhs);
3086 }
3087 
3088 /**
3089 Swaps two elements in-place of a range `r`,
3090 specified by their indices `i1` and `i2`.
3091 
3092 Params:
3093     r  = a range with swappable elements
3094     i1 = first index
3095     i2 = second index
3096 */
3097 void swapAt(R)(auto ref R r, size_t i1, size_t i2)
3098 {
3099     static if (is(typeof(&r.swapAt)))
3100     {
3101         r.swapAt(i1, i2);
3102     }
3103     else static if (is(typeof(&r[i1])))
3104     {
3105         swap(r[i1], r[i2]);
3106     }
3107     else
3108     {
3109         if (i1 == i2) return;
3110         auto t1 = r.moveAt(i1);
3111         auto t2 = r.moveAt(i2);
3112         r[i2] = t1;
3113         r[i1] = t2;
3114     }
3115 }
3116 
3117 ///
3118 pure @safe nothrow unittest
3119 {
3120     import std.algorithm.comparison : equal;
3121     auto a = [1, 2, 3];
3122     a.swapAt(1, 2);
3123     assert(a.equal([1, 3, 2]));
3124 }
3125 
3126 pure @safe nothrow unittest
3127 {
3128     import std.algorithm.comparison : equal;
3129     auto a = [4, 5, 6];
3130     a.swapAt(1, 1);
3131     assert(a.equal([4, 5, 6]));
3132 }
3133 
3134 pure @safe nothrow unittest
3135 {
3136     // test non random access ranges
3137     import std.algorithm.comparison : equal;
3138     import std.array : array;
3139 
3140     char[] b = ['a', 'b', 'c'];
3141     b.swapAt(1, 2);
3142     assert(b.equal(['a', 'c', 'b']));
3143 
3144     int[3] c = [1, 2, 3];
3145     c.swapAt(1, 2);
3146     assert(c.array.equal([1, 3, 2]));
3147 
3148     // opIndex returns lvalue
3149     struct RandomIndexType(T)
3150     {
3151         T payload;
3152 
3153         @property ref auto opIndex(size_t i)
3154         {
3155            return payload[i];
3156         }
3157 
3158     }
3159     auto d = RandomIndexType!(int[])([4, 5, 6]);
3160     d.swapAt(1, 2);
3161     assert(d.payload.equal([4, 6, 5]));
3162 
3163     // custom moveAt and opIndexAssign
3164     struct RandomMoveAtType(T)
3165     {
3166         T payload;
3167 
3168         ElementType!T moveAt(size_t i)
3169         {
3170            return payload.moveAt(i);
3171         }
3172 
3173         void opIndexAssign(ElementType!T val, size_t idx)
3174         {
3175             payload[idx] = val;
3176         }
3177     }
3178     auto e = RandomMoveAtType!(int[])([7, 8, 9]);
3179     e.swapAt(1, 2);
3180     assert(e.payload.equal([7, 9, 8]));
3181 
3182 
3183     // custom swapAt
3184     struct RandomSwapAtType(T)
3185     {
3186         T payload;
3187 
3188         void swapAt(size_t i)
3189         {
3190            return payload.swapAt(i);
3191         }
3192     }
3193     auto f = RandomMoveAtType!(int[])([10, 11, 12]);
3194     swapAt(f, 1, 2);
3195     assert(f.payload.equal([10, 12, 11]));
3196 }
3197 
3198 private void swapFront(R1, R2)(R1 r1, R2 r2)
3199 if (isInputRange!R1 && isInputRange!R2)
3200 {
3201     static if (is(typeof(swap(r1.front, r2.front))))
3202     {
3203         swap(r1.front, r2.front);
3204     }
3205     else
3206     {
3207         auto t1 = moveFront(r1), t2 = moveFront(r2);
3208         r1.front = move(t2);
3209         r2.front = move(t1);
3210     }
3211 }
3212 
3213 // swapRanges
3214 /**
3215 Swaps all elements of `r1` with successive elements in `r2`.
3216 Returns a tuple containing the remainder portions of `r1` and $(D
3217 r2) that were not swapped (one of them will be empty). The ranges may
3218 be of different types but must have the same element type and support
3219 swapping.
3220 
3221 Params:
3222     r1 = an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
3223          with swappable elements
3224     r2 = an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
3225          with swappable elements
3226 
3227 Returns:
3228     Tuple containing the remainder portions of r1 and r2 that were not swapped
3229 */
3230 Tuple!(InputRange1, InputRange2)
3231 swapRanges(InputRange1, InputRange2)(InputRange1 r1, InputRange2 r2)
3232 if (hasSwappableElements!InputRange1 && hasSwappableElements!InputRange2
3233     && is(ElementType!InputRange1 == ElementType!InputRange2))
3234 {
3235     for (; !r1.empty && !r2.empty; r1.popFront(), r2.popFront())
3236     {
3237         swap(r1.front, r2.front);
3238     }
3239     return tuple(r1, r2);
3240 }
3241 
3242 ///
3243 @safe unittest
3244 {
3245     import std.range : empty;
3246     int[] a = [ 100, 101, 102, 103 ];
3247     int[] b = [ 0, 1, 2, 3 ];
3248     auto c = swapRanges(a[1 .. 3], b[2 .. 4]);
3249     assert(c[0].empty && c[1].empty);
3250     assert(a == [ 100, 2, 3, 103 ]);
3251     assert(b == [ 0, 1, 101, 102 ]);
3252 }
3253 
3254 /**
3255 Initializes each element of `range` with `value`.
3256 Assumes that the elements of the range are uninitialized.
3257 This is of interest for structs that
3258 define copy constructors (for all other types, $(LREF fill) and
3259 uninitializedFill are equivalent).
3260 
3261 Params:
3262         range = An
3263                 $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
3264                 that exposes references to its elements and has assignable
3265                 elements
3266         value = Assigned to each element of range
3267 
3268 See_Also:
3269         $(LREF fill)
3270         $(LREF initializeAll)
3271  */
3272 void uninitializedFill(Range, Value)(Range range, Value value)
3273 if (isInputRange!Range && hasLvalueElements!Range && is(typeof(range.front = value)))
3274 {
3275     import std.traits : hasElaborateAssign;
3276 
3277     alias T = ElementType!Range;
3278     static if (hasElaborateAssign!T)
3279     {
3280         import core.internal.lifetime : emplaceRef;
3281 
3282         // Must construct stuff by the book
3283         for (; !range.empty; range.popFront())
3284             emplaceRef!T(range.front, value);
3285     }
3286     else
3287         // Doesn't matter whether fill is initialized or not
3288         return fill(range, value);
3289 }
3290 
3291 ///
3292 nothrow @system unittest
3293 {
3294     import core.stdc.stdlib : malloc, free;
3295 
3296     auto s = (cast(int*) malloc(5 * int.sizeof))[0 .. 5];
3297     uninitializedFill(s, 42);
3298     assert(s == [ 42, 42, 42, 42, 42 ]);
3299 
3300     scope(exit) free(s.ptr);
3301 }
3302