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     {
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     {
558         void put(E)(E) {}
559     }
560     int line = 0;
561     struct R
562     {
563         int front;
564         @property bool empty() { return line == 1; }
565         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 `filler` $(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 {
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 
702     void fun0()
703     {
704         foreach (i; 0 .. 1000)
705         {
706             foreach (ref e; a) e = 6;
707         }
708     }
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     {
725         void opAssign(int){}
726     }
727 
728     //ER8638_1 IS self assignable
729     static struct ER8638_2
730     {
731         void opAssign(ER8638_2){}
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 This function is unavailable if `T` is a `struct` and  `T.this()` is annotated
870 with `@disable`.
871 
872 Params:
873         range = An
874                 $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
875                 that exposes references to its elements and has assignable
876                 elements
877 
878 See_Also:
879         $(LREF fill)
880         $(LREF uninitializedFill)
881  */
882 void initializeAll(Range)(Range range)
883 if (isInputRange!Range && hasLvalueElements!Range && hasAssignableElements!Range
884     && __traits(compiles, { static ElementType!Range _; }))
885 {
886     import core.stdc.string : memset, memcpy;
887     import std.traits : hasElaborateAssign, isDynamicArray;
888 
889     alias T = ElementType!Range;
890     static if (hasElaborateAssign!T)
891     {
892         import std.algorithm.internal : addressOf;
893         //Elaborate opAssign. Must go the memcpy/memset road.
894         static if (!__traits(isZeroInit, T))
895         {
896             for ( ; !range.empty ; range.popFront() )
897             {
898                 import core.internal.lifetime : emplaceInitializer;
899                 emplaceInitializer(range.front);
900             }
901         }
902         else
903             static if (isDynamicArray!Range)
904                 memset(range.ptr, 0, range.length * T.sizeof);
905             else
906                 for ( ; !range.empty ; range.popFront() )
907                     memset(addressOf(range.front), 0, T.sizeof);
908     }
909     else
910         fill(range, T.init);
911 }
912 
913 /// ditto
914 void initializeAll(Range)(Range range)
915 if (is(Range == char[]) || is(Range == wchar[]))
916 {
917     alias T = ElementEncodingType!Range;
918     range[] = T.init;
919 }
920 
921 ///
922 @system unittest
923 {
924     import core.stdc.stdlib : malloc, free;
925 
926     struct S
927     {
928         int a = 10;
929     }
930 
931     auto s = (cast(S*) malloc(5 * S.sizeof))[0 .. 5];
932     initializeAll(s);
933     assert(s == [S(10), S(10), S(10), S(10), S(10)]);
934 
935     scope(exit) free(s.ptr);
936 }
937 
938 @system unittest
939 {
940     import std.algorithm.iteration : filter;
941     import std.meta : AliasSeq;
942     import std.traits : hasElaborateAssign;
943 
944     //Test strings:
945     //Must work on narrow strings.
946     //Must reject const
947     char[3] a = void;
948     a[].initializeAll();
949     assert(a[] == [char.init, char.init, char.init]);
950     string s;
951     assert(!__traits(compiles, s.initializeAll()));
952     assert(!__traits(compiles, s.initializeAll()));
953     assert(s.empty);
954 
955     //Note: Cannot call uninitializedFill on narrow strings
956 
957     enum e {e1, e2}
958     e[3] b1 = void;
959     b1[].initializeAll();
960     assert(b1[] == [e.e1, e.e1, e.e1]);
961     e[3] b2 = void;
962     b2[].uninitializedFill(e.e2);
963     assert(b2[] == [e.e2, e.e2, e.e2]);
964 
965     static struct S1
966     {
967         int i;
968     }
969     static struct S2
970     {
971         int i = 1;
972     }
973     static struct S3
974     {
975         int i;
976         this(this){}
977     }
978     static struct S4
979     {
980         int i = 1;
981         this(this){}
982     }
983     static assert(!hasElaborateAssign!S1);
984     static assert(!hasElaborateAssign!S2);
985     static assert( hasElaborateAssign!S3);
986     static assert( hasElaborateAssign!S4);
987     assert(!typeid(S1).initializer().ptr);
988     assert( typeid(S2).initializer().ptr);
989     assert(!typeid(S3).initializer().ptr);
990     assert( typeid(S4).initializer().ptr);
991 
992     static foreach (S; AliasSeq!(S1, S2, S3, S4))
993     {
994         //initializeAll
995         {
996             //Array
997             S[3] ss1 = void;
998             ss1[].initializeAll();
999             assert(ss1[] == [S.init, S.init, S.init]);
1000 
1001             //Not array
1002             S[3] ss2 = void;
1003             auto sf = ss2[].filter!"true"();
1004 
1005             sf.initializeAll();
1006             assert(ss2[] == [S.init, S.init, S.init]);
1007         }
1008         //uninitializedFill
1009         {
1010             //Array
1011             S[3] ss1 = void;
1012             ss1[].uninitializedFill(S(2));
1013             assert(ss1[] == [S(2), S(2), S(2)]);
1014 
1015             //Not array
1016             S[3] ss2 = void;
1017             auto sf = ss2[].filter!"true"();
1018             sf.uninitializedFill(S(2));
1019             assert(ss2[] == [S(2), S(2), S(2)]);
1020         }
1021     }
1022 }
1023 
1024 // test that initializeAll works for arrays of static arrays of structs with
1025 // elaborate assigns.
1026 @system unittest
1027 {
1028     struct Int {
1029         ~this() {}
1030         int x = 3;
1031     }
1032     Int[2] xs = [Int(1), Int(2)];
1033     struct R {
1034         bool done;
1035         bool empty() { return done; }
1036         ref Int[2] front() { return xs; }
1037         void popFront() { done = true; }
1038     }
1039     initializeAll(R());
1040     assert(xs[0].x == 3);
1041     assert(xs[1].x == 3);
1042 }
1043 
1044 // https://issues.dlang.org/show_bug.cgi?id=22105
1045 @system unittest
1046 {
1047     struct NoDefaultCtor
1048     {
1049         @disable this();
1050     }
1051 
1052     NoDefaultCtor[1] array = void;
1053     static assert(!__traits(compiles, array[].initializeAll));
1054 }
1055 
1056 // move
1057 /**
1058 Moves `source` into `target`, via a destructive copy when necessary.
1059 
1060 If `T` is a struct with a destructor or postblit defined, source is reset
1061 to its `.init` value after it is moved into target, otherwise it is
1062 left unchanged.
1063 
1064 Preconditions:
1065 If source has internal pointers that point to itself and doesn't define
1066 opPostMove, it cannot be moved, and will trigger an assertion failure.
1067 
1068 Params:
1069     source = Data to copy.
1070     target = Where to copy into. The destructor, if any, is invoked before the
1071         copy is performed.
1072 */
1073 void move(T)(ref T source, ref T target)
1074 if (__traits(compiles, target = T.init))
1075 {
1076     moveImpl(target, source);
1077 }
1078 
1079 /// ditto
1080 template move(T)
1081 if (!__traits(compiles, imported!"std.traits".lvalueOf!T = T.init))
1082 {
1083     ///
1084     deprecated("Can't move into `target` as `" ~ T.stringof ~ "` can't be assigned")
1085     void move(ref T source, ref T target) => moveImpl(target, source);
1086 }
1087 
1088 /// For non-struct types, `move` just performs `target = source`:
1089 @safe unittest
1090 {
1091     Object obj1 = new Object;
1092     Object obj2 = obj1;
1093     Object obj3;
1094 
1095     move(obj2, obj3);
1096     assert(obj3 is obj1);
1097     // obj2 unchanged
1098     assert(obj2 is obj1);
1099 }
1100 
1101 ///
1102 pure nothrow @safe @nogc unittest
1103 {
1104     // Structs without destructors are simply copied
1105     struct S1
1106     {
1107         int a = 1;
1108         int b = 2;
1109     }
1110     S1 s11 = { 10, 11 };
1111     S1 s12;
1112 
1113     move(s11, s12);
1114 
1115     assert(s12 == S1(10, 11));
1116     assert(s11 == s12);
1117 
1118     // But structs with destructors or postblits are reset to their .init value
1119     // after copying to the target.
1120     struct S2
1121     {
1122         int a = 1;
1123         int b = 2;
1124 
1125         ~this() pure nothrow @safe @nogc { }
1126     }
1127     S2 s21 = { 3, 4 };
1128     S2 s22;
1129 
1130     move(s21, s22);
1131 
1132     assert(s21 == S2(1, 2));
1133     assert(s22 == S2(3, 4));
1134 }
1135 
1136 @safe unittest
1137 {
1138     import std.exception : assertCTFEable;
1139     import std.traits;
1140 
1141     assertCTFEable!((){
1142         Object obj1 = new Object;
1143         Object obj2 = obj1;
1144         Object obj3;
1145         move(obj2, obj3);
1146         assert(obj3 is obj1);
1147 
1148         static struct S1 { int a = 1, b = 2; }
1149         S1 s11 = { 10, 11 };
1150         S1 s12;
1151         move(s11, s12);
1152         assert(s11.a == 10 && s11.b == 11 && s12.a == 10 && s12.b == 11);
1153 
1154         static struct S2 { int a = 1; int * b; }
1155         S2 s21 = { 10, null };
1156         s21.b = new int;
1157         S2 s22;
1158         move(s21, s22);
1159         assert(s21 == s22);
1160     });
1161     // https://issues.dlang.org/show_bug.cgi?id=5661 test(1)
1162     static struct S3
1163     {
1164         static struct X { int n = 0; ~this(){n = 0;} }
1165         X x;
1166     }
1167     static assert(hasElaborateDestructor!S3);
1168     S3 s31, s32;
1169     s31.x.n = 1;
1170     move(s31, s32);
1171     assert(s31.x.n == 0);
1172     assert(s32.x.n == 1);
1173 
1174     // https://issues.dlang.org/show_bug.cgi?id=5661 test(2)
1175     static struct S4
1176     {
1177         static struct X { int n = 0; this(this){n = 0;} }
1178         X x;
1179     }
1180     static assert(hasElaborateCopyConstructor!S4);
1181     S4 s41, s42;
1182     s41.x.n = 1;
1183     move(s41, s42);
1184     assert(s41.x.n == 0);
1185     assert(s42.x.n == 1);
1186 
1187     // https://issues.dlang.org/show_bug.cgi?id=13990 test
1188     class S5;
1189 
1190     S5 s51;
1191     S5 s52 = s51;
1192     S5 s53;
1193     move(s52, s53);
1194     assert(s53 is s51);
1195 }
1196 
1197 @system unittest
1198 {
1199     static struct S
1200     {
1201         immutable int i;
1202         ~this() @safe {}
1203     }
1204     alias ol = __traits(getOverloads, std.algorithm.mutation, "move", true)[1];
1205     static assert(__traits(isDeprecated, ol!S));
1206     // uncomment after deprecation
1207     //static assert(!__traits(compiles, { S a, b; move(a, b); }));
1208 }
1209 
1210 /// Ditto
1211 T move(T)(return scope ref T source)
1212 {
1213     return moveImpl(source);
1214 }
1215 
1216 /// Non-copyable structs can still be moved:
1217 pure nothrow @safe @nogc unittest
1218 {
1219     struct S
1220     {
1221         int a = 1;
1222         @disable this(this);
1223         ~this() pure nothrow @safe @nogc {}
1224     }
1225     S s1;
1226     s1.a = 2;
1227     S s2 = move(s1);
1228     assert(s1.a == 1);
1229     assert(s2.a == 2);
1230 }
1231 
1232 /// `opPostMove` will be called if defined:
1233 pure nothrow @safe @nogc unittest
1234 {
1235     struct S
1236     {
1237         int a;
1238         void opPostMove(const ref S old)
1239         {
1240             assert(a == old.a);
1241             a++;
1242         }
1243     }
1244     S s1;
1245     s1.a = 41;
1246     S s2 = move(s1);
1247     assert(s2.a == 42);
1248 }
1249 
1250 // https://issues.dlang.org/show_bug.cgi?id=20869
1251 // `move` should propagate the attributes of `opPostMove`
1252 @system unittest
1253 {
1254     static struct S
1255     {
1256         void opPostMove(const ref S old) nothrow @system
1257         {
1258             __gshared int i;
1259             new int(i++); // Force @gc impure @system
1260         }
1261     }
1262 
1263     alias T = void function() @system nothrow;
1264     static assert(is(typeof({ S s; move(s); }) == T));
1265     static assert(is(typeof({ S s; move(s, s); }) == T));
1266 }
1267 
1268 private void moveImpl(T)(ref scope T target, ref return scope T source)
1269 {
1270     import std.traits : hasElaborateDestructor;
1271 
1272     static if (is(T == struct))
1273     {
1274         //  Unsafe when compiling without -dip1000
1275         if ((() @trusted => &source == &target)()) return;
1276 
1277         // Destroy target before overwriting it
1278         static if (hasElaborateDestructor!T) target.__xdtor();
1279     }
1280     // move and emplace source into target
1281     moveEmplaceImpl(target, source);
1282 }
1283 
1284 private T moveImpl(T)(ref return scope T source)
1285 {
1286     // Properly infer safety from moveEmplaceImpl as the implementation below
1287     // might void-initialize pointers in result and hence needs to be @trusted
1288     if (false) moveEmplaceImpl(source, source);
1289 
1290     return trustedMoveImpl(source);
1291 }
1292 
1293 private T trustedMoveImpl(T)(ref return scope T source) @trusted
1294 {
1295     T result = void;
1296     moveEmplaceImpl(result, source);
1297     return result;
1298 }
1299 
1300 @safe unittest
1301 {
1302     import std.exception : assertCTFEable;
1303     import std.traits;
1304 
1305     assertCTFEable!((){
1306         Object obj1 = new Object;
1307         Object obj2 = obj1;
1308         Object obj3 = move(obj2);
1309         assert(obj3 is obj1);
1310 
1311         static struct S1 { int a = 1, b = 2; }
1312         S1 s11 = { 10, 11 };
1313         S1 s12 = move(s11);
1314         assert(s11.a == 10 && s11.b == 11 && s12.a == 10 && s12.b == 11);
1315 
1316         static struct S2 { int a = 1; int * b; }
1317         S2 s21 = { 10, null };
1318         s21.b = new int;
1319         S2 s22 = move(s21);
1320         assert(s21 == s22);
1321     });
1322 
1323     // https://issues.dlang.org/show_bug.cgi?id=5661 test(1)
1324     static struct S3
1325     {
1326         static struct X { int n = 0; ~this(){n = 0;} }
1327         X x;
1328     }
1329     static assert(hasElaborateDestructor!S3);
1330     S3 s31;
1331     s31.x.n = 1;
1332     S3 s32 = move(s31);
1333     assert(s31.x.n == 0);
1334     assert(s32.x.n == 1);
1335 
1336     // https://issues.dlang.org/show_bug.cgi?id=5661 test(2)
1337     static struct S4
1338     {
1339         static struct X { int n = 0; this(this){n = 0;} }
1340         X x;
1341     }
1342     static assert(hasElaborateCopyConstructor!S4);
1343     S4 s41;
1344     s41.x.n = 1;
1345     S4 s42 = move(s41);
1346     assert(s41.x.n == 0);
1347     assert(s42.x.n == 1);
1348 
1349     // https://issues.dlang.org/show_bug.cgi?id=13990 test
1350     class S5;
1351 
1352     S5 s51;
1353     S5 s52 = s51;
1354     S5 s53;
1355     s53 = move(s52);
1356     assert(s53 is s51);
1357 }
1358 
1359 @system unittest
1360 {
1361     static struct S { int n = 0; ~this() @system { n = 0; } }
1362     S a, b;
1363     static assert(!__traits(compiles, () @safe { move(a, b); }));
1364     static assert(!__traits(compiles, () @safe { move(a); }));
1365     a.n = 1;
1366     () @trusted { move(a, b); }();
1367     assert(a.n == 0);
1368     a.n = 1;
1369     () @trusted { move(a); }();
1370     assert(a.n == 0);
1371 }
1372 
1373 // https://issues.dlang.org/show_bug.cgi?id=6217
1374 @safe unittest
1375 {
1376     import std.algorithm.iteration : map;
1377     auto x = map!"a"([1,2,3]);
1378     x = move(x);
1379 }
1380 
1381 // https://issues.dlang.org/show_bug.cgi?id=8055
1382 @safe unittest
1383 {
1384     static struct S
1385     {
1386         int x;
1387         ~this()
1388         {
1389             assert(x == 0);
1390         }
1391     }
1392     S foo(S s)
1393     {
1394         return move(s);
1395     }
1396     S a;
1397     a.x = 0;
1398     auto b = foo(a);
1399     assert(b.x == 0);
1400 }
1401 
1402 // https://issues.dlang.org/show_bug.cgi?id=8057
1403 @system unittest
1404 {
1405     int n = 10;
1406     struct S
1407     {
1408         int x;
1409         ~this()
1410         {
1411             // Access to enclosing scope
1412             assert(n == 10);
1413         }
1414     }
1415     S foo(S s)
1416     {
1417         // Move nested struct
1418         return move(s);
1419     }
1420     S a;
1421     a.x = 1;
1422     auto b = foo(a);
1423     assert(b.x == 1);
1424 
1425     // Regression https://issues.dlang.org/show_bug.cgi?id=8171
1426     static struct Array(T)
1427     {
1428         // nested struct has no member
1429         struct Payload
1430         {
1431             ~this() {}
1432         }
1433     }
1434     Array!int.Payload x = void;
1435     move(x);
1436     move(x, x);
1437 }
1438 
1439 private void moveEmplaceImpl(T)(ref scope T target, ref return scope T source)
1440 {
1441     import core.stdc.string : memcpy, memset;
1442     import std.traits : hasAliasing, hasElaborateAssign,
1443                         hasElaborateCopyConstructor, hasElaborateDestructor,
1444                         hasElaborateMove,
1445                         isAssignable, isStaticArray;
1446 
1447     static if (!is(T == class) && hasAliasing!T) if (!__ctfe)
1448     {
1449         import std.exception : doesPointTo;
1450         assert(!(doesPointTo(source, source) && !hasElaborateMove!T),
1451             "Cannot move object of type " ~ T.stringof ~ " with internal pointer unless `opPostMove` is defined.");
1452     }
1453 
1454     static if (is(T == struct))
1455     {
1456         //  Unsafe when compiling without -dip1000
1457         assert((() @trusted => &source !is &target)(), "source and target must not be identical");
1458 
1459         static if (hasElaborateAssign!T || !isAssignable!T)
1460             () @trusted { memcpy(&target, &source, T.sizeof); }();
1461         else
1462             target = source;
1463 
1464         static if (hasElaborateMove!T)
1465             __move_post_blt(target, source);
1466 
1467         // If the source defines a destructor or a postblit hook, we must obliterate the
1468         // object in order to avoid double freeing and undue aliasing
1469         static if (hasElaborateDestructor!T || hasElaborateCopyConstructor!T)
1470         {
1471             // If T is nested struct, keep original context pointer
1472             static if (__traits(isNested, T))
1473                 enum sz = T.sizeof - (void*).sizeof;
1474             else
1475                 enum sz = T.sizeof;
1476 
1477             static if (__traits(isZeroInit, T))
1478                 () @trusted { memset(&source, 0, sz); }();
1479             else
1480                 () @trusted { memcpy(&source, __traits(initSymbol, T).ptr, sz); }();
1481         }
1482     }
1483     else static if (isStaticArray!T)
1484     {
1485         for (size_t i = 0; i < source.length; ++i)
1486             move(source[i], target[i]);
1487     }
1488     else
1489     {
1490         // Primitive data (including pointers and arrays) or class -
1491         // assignment works great
1492         target = source;
1493     }
1494 }
1495 
1496 /**
1497  * Similar to $(LREF move) but assumes `target` is uninitialized. This
1498  * is more efficient because `source` can be blitted over `target`
1499  * without destroying or initializing it first.
1500  *
1501  * Params:
1502  *   source = value to be moved into target
1503  *   target = uninitialized value to be filled by source
1504  */
1505 void moveEmplace(T)(ref T source, ref T target) pure @system
1506 {
1507     moveEmplaceImpl(target, source);
1508 }
1509 
1510 ///
1511 pure nothrow @nogc @system unittest
1512 {
1513     static struct Foo
1514     {
1515     pure nothrow @nogc:
1516         this(int* ptr) { _ptr = ptr; }
1517         ~this() { if (_ptr) ++*_ptr; }
1518         int* _ptr;
1519     }
1520 
1521     int val;
1522     Foo foo1 = void; // uninitialized
1523     auto foo2 = Foo(&val); // initialized
1524     assert(foo2._ptr is &val);
1525 
1526     // Using `move(foo2, foo1)` would have an undefined effect because it would destroy
1527     // the uninitialized foo1.
1528     // moveEmplace directly overwrites foo1 without destroying or initializing it first.
1529     moveEmplace(foo2, foo1);
1530     assert(foo1._ptr is &val);
1531     assert(foo2._ptr is null);
1532     assert(val == 0);
1533 }
1534 
1535 // https://issues.dlang.org/show_bug.cgi?id=18913
1536 @safe unittest
1537 {
1538     static struct NoCopy
1539     {
1540         int payload;
1541         ~this() { }
1542         @disable this(this);
1543     }
1544 
1545     static void f(NoCopy[2]) { }
1546 
1547     NoCopy[2] ncarray = [ NoCopy(1), NoCopy(2) ];
1548 
1549     static assert(!__traits(compiles, f(ncarray)));
1550     f(move(ncarray));
1551 }
1552 
1553 // moveAll
1554 /**
1555 Calls `move(a, b)` for each element `a` in `src` and the corresponding
1556 element `b` in `tgt`, in increasing order.
1557 
1558 Preconditions:
1559 `walkLength(src) <= walkLength(tgt)`.
1560 This precondition will be asserted. If you cannot ensure there is enough room in
1561 `tgt` to accommodate all of `src` use $(LREF moveSome) instead.
1562 
1563 Params:
1564     src = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) with
1565         movable elements.
1566     tgt = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) with
1567         elements that elements from `src` can be moved into.
1568 
1569 Returns: The leftover portion of `tgt` after all elements from `src` have
1570 been moved.
1571  */
1572 InputRange2 moveAll(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt)
1573 if (isInputRange!InputRange1 && isInputRange!InputRange2
1574         && is(typeof(move(src.front, tgt.front))))
1575 {
1576     return moveAllImpl!move(src, tgt);
1577 }
1578 
1579 ///
1580 pure nothrow @safe @nogc unittest
1581 {
1582     int[3] a = [ 1, 2, 3 ];
1583     int[5] b;
1584     assert(moveAll(a[], b[]) is b[3 .. $]);
1585     assert(a[] == b[0 .. 3]);
1586     int[3] cmp = [ 1, 2, 3 ];
1587     assert(a[] == cmp[]);
1588 }
1589 
1590 /**
1591  * Similar to $(LREF moveAll) but assumes all elements in `tgt` are
1592  * uninitialized. Uses $(LREF moveEmplace) to move elements from
1593  * `src` over elements from `tgt`.
1594  */
1595 InputRange2 moveEmplaceAll(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt) @system
1596 if (isInputRange!InputRange1 && isInputRange!InputRange2
1597         && is(typeof(moveEmplace(src.front, tgt.front))))
1598 {
1599     return moveAllImpl!moveEmplace(src, tgt);
1600 }
1601 
1602 ///
1603 pure nothrow @nogc @system unittest
1604 {
1605     static struct Foo
1606     {
1607         ~this() pure nothrow @nogc { if (_ptr) ++*_ptr; }
1608         int* _ptr;
1609     }
1610     int[3] refs = [0, 1, 2];
1611     Foo[3] src = [Foo(&refs[0]), Foo(&refs[1]), Foo(&refs[2])];
1612     Foo[5] dst = void;
1613 
1614     auto tail = moveEmplaceAll(src[], dst[]); // move 3 value from src over dst
1615     assert(tail.length == 2); // returns remaining uninitialized values
1616     initializeAll(tail);
1617 
1618     import std.algorithm.searching : all;
1619     assert(src[].all!(e => e._ptr is null));
1620     assert(dst[0 .. 3].all!(e => e._ptr !is null));
1621 }
1622 
1623 @system unittest
1624 {
1625     struct InputRange
1626     {
1627         ref int front() { return data[0]; }
1628         void popFront() { data.popFront; }
1629         bool empty() { return data.empty; }
1630         int[] data;
1631     }
1632     auto a = InputRange([ 1, 2, 3 ]);
1633     auto b = InputRange(new int[5]);
1634     moveAll(a, b);
1635     assert(a.data == b.data[0 .. 3]);
1636     assert(a.data == [ 1, 2, 3 ]);
1637 }
1638 
1639 private InputRange2 moveAllImpl(alias moveOp, InputRange1, InputRange2)(
1640     ref InputRange1 src, ref InputRange2 tgt)
1641 {
1642     import std.exception : enforce;
1643 
1644     static if (isRandomAccessRange!InputRange1 && hasLength!InputRange1 && hasLength!InputRange2
1645          && hasSlicing!InputRange2 && isRandomAccessRange!InputRange2)
1646     {
1647         auto toMove = src.length;
1648         assert(toMove <= tgt.length, "Source buffer needs to be smaller or equal to the target buffer.");
1649         foreach (idx; 0 .. toMove)
1650             moveOp(src[idx], tgt[idx]);
1651         return tgt[toMove .. tgt.length];
1652     }
1653     else
1654     {
1655         for (; !src.empty; src.popFront(), tgt.popFront())
1656         {
1657             assert(!tgt.empty, "Source buffer needs to be smaller or equal to the target buffer.");
1658             moveOp(src.front, tgt.front);
1659         }
1660         return tgt;
1661     }
1662 }
1663 
1664 // moveSome
1665 /**
1666 Calls `move(a, b)` for each element `a` in `src` and the corresponding
1667 element `b` in `tgt`, in increasing order, stopping when either range has been
1668 exhausted.
1669 
1670 Params:
1671     src = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) with
1672         movable elements.
1673     tgt = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) with
1674         elements that elements from `src` can be moved into.
1675 
1676 Returns: The leftover portions of the two ranges after one or the other of the
1677 ranges have been exhausted.
1678  */
1679 Tuple!(InputRange1, InputRange2) moveSome(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt)
1680 if (isInputRange!InputRange1 && isInputRange!InputRange2
1681         && is(typeof(move(src.front, tgt.front))))
1682 {
1683     return moveSomeImpl!move(src, tgt);
1684 }
1685 
1686 ///
1687 pure nothrow @safe @nogc unittest
1688 {
1689     int[5] a = [ 1, 2, 3, 4, 5 ];
1690     int[3] b;
1691     assert(moveSome(a[], b[])[0] is a[3 .. $]);
1692     assert(a[0 .. 3] == b);
1693     assert(a == [ 1, 2, 3, 4, 5 ]);
1694 }
1695 
1696 /**
1697  * Same as $(LREF moveSome) but assumes all elements in `tgt` are
1698  * uninitialized. Uses $(LREF moveEmplace) to move elements from
1699  * `src` over elements from `tgt`.
1700  */
1701 Tuple!(InputRange1, InputRange2) moveEmplaceSome(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt) @system
1702 if (isInputRange!InputRange1 && isInputRange!InputRange2
1703         && is(typeof(move(src.front, tgt.front))))
1704 {
1705     return moveSomeImpl!moveEmplace(src, tgt);
1706 }
1707 
1708 ///
1709 pure nothrow @nogc @system unittest
1710 {
1711     static struct Foo
1712     {
1713         ~this() pure nothrow @nogc { if (_ptr) ++*_ptr; }
1714         int* _ptr;
1715     }
1716     int[4] refs = [0, 1, 2, 3];
1717     Foo[4] src = [Foo(&refs[0]), Foo(&refs[1]), Foo(&refs[2]), Foo(&refs[3])];
1718     Foo[3] dst = void;
1719 
1720     auto res = moveEmplaceSome(src[], dst[]);
1721     assert(res.length == 2);
1722 
1723     import std.algorithm.searching : all;
1724     assert(src[0 .. 3].all!(e => e._ptr is null));
1725     assert(src[3]._ptr !is null);
1726     assert(dst[].all!(e => e._ptr !is null));
1727 }
1728 
1729 private Tuple!(InputRange1, InputRange2) moveSomeImpl(alias moveOp, InputRange1, InputRange2)(
1730     ref InputRange1 src, ref InputRange2 tgt)
1731 {
1732     for (; !src.empty && !tgt.empty; src.popFront(), tgt.popFront())
1733         moveOp(src.front, tgt.front);
1734     return tuple(src, tgt);
1735  }
1736 
1737 
1738 // SwapStrategy
1739 /**
1740 Defines the swapping strategy for algorithms that need to swap
1741 elements in a range (such as partition and sort). The strategy
1742 concerns the swapping of elements that are not the core concern of the
1743 algorithm. For example, consider an algorithm that sorts $(D [ "abc",
1744 "b", "aBc" ]) according to `toUpper(a) < toUpper(b)`. That
1745 algorithm might choose to swap the two equivalent strings `"abc"`
1746 and `"aBc"`. That does not affect the sorting since both
1747 `["abc", "aBc", "b" ]` and `[ "aBc", "abc", "b" ]` are valid
1748 outcomes.
1749 
1750 Some situations require that the algorithm must NOT ever change the
1751 relative ordering of equivalent elements (in the example above, only
1752 `[ "abc", "aBc", "b" ]` would be the correct result). Such
1753 algorithms are called $(B stable). If the ordering algorithm may swap
1754 equivalent elements discretionarily, the ordering is called $(B
1755 unstable).
1756 
1757 Yet another class of algorithms may choose an intermediate tradeoff by
1758 being stable only on a well-defined subrange of the range. There is no
1759 established terminology for such behavior; this library calls it $(B
1760 semistable).
1761 
1762 Generally, the `stable` ordering strategy may be more costly in
1763 time and/or space than the other two because it imposes additional
1764 constraints. Similarly, `semistable` may be costlier than $(D
1765 unstable). As (semi-)stability is not needed very often, the ordering
1766 algorithms in this module parameterized by `SwapStrategy` all
1767 choose `SwapStrategy.unstable` as the default.
1768 */
1769 
1770 enum SwapStrategy
1771 {
1772     /**
1773        Allows freely swapping of elements as long as the output
1774        satisfies the algorithm's requirements.
1775     */
1776     unstable,
1777     /**
1778        In algorithms partitioning ranges in two, preserve relative
1779        ordering of elements only to the left of the partition point.
1780     */
1781     semistable,
1782     /**
1783        Preserve the relative ordering of elements to the largest
1784        extent allowed by the algorithm's requirements.
1785     */
1786     stable,
1787 }
1788 
1789 ///
1790 @safe unittest
1791 {
1792     int[] a = [0, 1, 2, 3];
1793     assert(remove!(SwapStrategy.stable)(a, 1) == [0, 2, 3]);
1794     a = [0, 1, 2, 3];
1795     assert(remove!(SwapStrategy.unstable)(a, 1) == [0, 3, 2]);
1796 }
1797 
1798 ///
1799 @safe unittest
1800 {
1801     import std.algorithm.sorting : partition;
1802 
1803     // Put stuff greater than 3 on the left
1804     auto arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
1805     assert(partition!(a => a > 3, SwapStrategy.stable)(arr) == [1, 2, 3]);
1806     assert(arr == [4, 5, 6, 7, 8, 9, 10, 1, 2, 3]);
1807 
1808     arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
1809     assert(partition!(a => a > 3, SwapStrategy.semistable)(arr) == [2, 3, 1]);
1810     assert(arr == [4, 5, 6, 7, 8, 9, 10, 2, 3, 1]);
1811 
1812     arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
1813     assert(partition!(a => a > 3, SwapStrategy.unstable)(arr) == [3, 2, 1]);
1814     assert(arr == [10, 9, 8, 4, 5, 6, 7, 3, 2, 1]);
1815 }
1816 
1817 private template isValidIntegralTuple(T)
1818 {
1819     import std.traits : isIntegral;
1820     import std.typecons : isTuple;
1821     static if (isTuple!T)
1822     {
1823         enum isValidIntegralTuple = T.length == 2 &&
1824                 isIntegral!(typeof(T.init[0])) && isIntegral!(typeof(T.init[0]));
1825     }
1826     else
1827     {
1828         enum isValidIntegralTuple = isIntegral!T;
1829     }
1830 }
1831 
1832 
1833 /**
1834 Eliminates elements at given offsets from `range` and returns the shortened
1835 range.
1836 
1837 For example, here is how to remove a single element from an array:
1838 
1839 $(RUNNABLE_EXAMPLE
1840 ----
1841 import std.algorithm.mutation;
1842 string[] a = [ "a", "b", "c", "d" ];
1843 a = a.remove(1); // remove element at offset 1
1844 assert(a == [ "a", "c", "d"]);
1845 ----
1846 )
1847 
1848 Note that `remove` does not change the length of the original range directly;
1849 instead, it returns the shortened range. If its return value is not assigned to
1850 the original range, the original range will retain its original length, though
1851 its contents will have changed:
1852 
1853 $(RUNNABLE_EXAMPLE
1854 ----
1855 import std.algorithm.mutation;
1856 int[] a = [ 3, 5, 7, 8 ];
1857 assert(remove(a, 1) == [ 3, 7, 8 ]);
1858 assert(a == [ 3, 7, 8, 8 ]);
1859 ----
1860 )
1861 
1862 The element at offset `1` has been removed and the rest of the elements have
1863 shifted up to fill its place, however, the original array remains of the same
1864 length. This is because all functions in `std.algorithm` only change $(I
1865 content), not $(I topology). The value `8` is repeated because $(LREF move) was
1866 invoked to rearrange elements, and on integers `move` simply copies the source
1867 to the destination.  To replace `a` with the effect of the removal, simply
1868 assign the slice returned by `remove` to it, as shown in the first example.
1869 
1870 $(H3 $(LNAME2 remove-multiple, Removing multiple elements))
1871 
1872 Multiple indices can be passed into `remove`. In that case,
1873 elements at the respective indices are all removed. The indices must
1874 be passed in increasing order, otherwise an exception occurs.
1875 
1876 $(RUNNABLE_EXAMPLE
1877 ----
1878 import std.algorithm.mutation;
1879 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
1880 assert(remove(a, 1, 3, 5) ==
1881     [ 0, 2, 4, 6, 7, 8, 9, 10 ]);
1882 ----
1883 )
1884 
1885 Note that all indices refer to slots in the $(I original) array, not
1886 in the array as it is being progressively shortened.
1887 
1888 Tuples of two integral offsets can be supplied to remove a range of indices:
1889 
1890 $(RUNNABLE_EXAMPLE
1891 ----
1892 import std.algorithm.mutation, std.typecons;
1893 int[] a = [ 3, 4, 5, 6, 7];
1894 // remove elements at indices 1 and 2
1895 assert(remove(a, tuple(1, 3)) == [ 3, 6, 7 ]);
1896 ----
1897 )
1898 
1899 The tuple passes in a range closed to the left and open to
1900 the right (consistent with built-in slices), e.g. `tuple(1, 3)`
1901 means indices `1` and `2` but not `3`.
1902 
1903 Finally, any combination of integral offsets and tuples composed of two integral
1904 offsets can be passed in:
1905 
1906 $(RUNNABLE_EXAMPLE
1907 ----
1908 import std.algorithm.mutation, std.typecons;
1909 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
1910 a = remove(a, 1, tuple(3, 5), 9);
1911 assert(a == [ 0, 2, 5, 6, 7, 8, 10 ]);
1912 ----
1913 )
1914 
1915 In this case, the slots at positions 1, 3, 4, and 9 are removed from
1916 the array.
1917 
1918 $(H3 $(LNAME2 remove-moving, Moving strategy))
1919 
1920 If the need is to remove some elements in the range but the order of
1921 the remaining elements does not have to be preserved, you may want to
1922 pass `SwapStrategy.unstable` to `remove`.
1923 
1924 $(RUNNABLE_EXAMPLE
1925 ----
1926 import std.algorithm.mutation;
1927 int[] a = [ 0, 1, 2, 3 ];
1928 assert(remove!(SwapStrategy.unstable)(a, 1) == [ 0, 3, 2 ]);
1929 ----
1930 )
1931 
1932 In the case above, the element at slot `1` is removed, but replaced
1933 with the last element of the range. Taking advantage of the relaxation
1934 of the stability requirement, `remove` moved elements from the end
1935 of the array over the slots to be removed. This way there is less data
1936 movement to be done which improves the execution time of the function.
1937 
1938 `remove` works on bidirectional ranges that have assignable
1939 lvalue elements. The moving strategy is (listed from fastest to slowest):
1940 
1941 $(UL
1942         $(LI If $(D s == SwapStrategy.unstable && isRandomAccessRange!Range &&
1943 hasLength!Range && hasLvalueElements!Range), then elements are moved from the
1944 end of the range into the slots to be filled. In this case, the absolute
1945 minimum of moves is performed.)
1946         $(LI Otherwise, if $(D s ==
1947 SwapStrategy.unstable && isBidirectionalRange!Range && hasLength!Range
1948 && hasLvalueElements!Range), then elements are still moved from the
1949 end of the range, but time is spent on advancing between slots by repeated
1950 calls to `range.popFront`.)
1951         $(LI Otherwise, elements are moved
1952 incrementally towards the front of `range`; a given element is never
1953 moved several times, but more elements are moved than in the previous
1954 cases.)
1955 )
1956 
1957 Params:
1958     s = a SwapStrategy to determine if the original order needs to be preserved
1959     range = a $(REF_ALTTEXT bidirectional range, isBidirectionalRange, std,range,primitives)
1960     with a length member
1961     offset = which element(s) to remove
1962 
1963 Returns:
1964     A range containing elements of `range` with 1 or more elements removed.
1965 */
1966 Range remove
1967 (SwapStrategy s = SwapStrategy.stable, Range, Offset ...)
1968 (Range range, Offset offset)
1969 if (Offset.length >= 1 && allSatisfy!(isValidIntegralTuple, Offset))
1970 {
1971     // Activate this check when the deprecation of non-integral tuples is over
1972     //import std.traits : isIntegral;
1973     //import std.typecons : isTuple;
1974     //static foreach (T; Offset)
1975     //{
1976         //static if (isTuple!T)
1977         //{
1978             //static assert(T.length == 2 &&
1979                     //isIntegral!(typeof(T.init[0])) && isIntegral!(typeof(T.init[0])),
1980                 //"Each offset must be an integral or a tuple of two integrals." ~
1981                 //"Use `arr.remove(pos1, pos2)` or `arr.remove(tuple(start, begin))`");
1982         //}
1983         //else
1984         //{
1985             //static assert(isIntegral!T,
1986                 //"Each offset must be an integral or a tuple of two integrals." ~
1987                 //"Use `arr.remove(pos1, pos2)` or `arr.remove(tuple(start, begin))`");
1988         //}
1989     //}
1990     return removeImpl!s(range, offset);
1991 }
1992 
1993 /// ditto
1994 deprecated("Use of non-integral tuples is deprecated. Use remove(tuple(start, end).")
1995 Range remove
1996 (SwapStrategy s = SwapStrategy.stable, Range, Offset ...)
1997 (Range range, Offset offset)
1998 if (Offset.length >= 1 && !allSatisfy!(isValidIntegralTuple, Offset))
1999 {
2000     return removeImpl!s(range, offset);
2001 }
2002 
2003 ///
2004 @safe pure unittest
2005 {
2006     import std.typecons : tuple;
2007 
2008     auto a = [ 0, 1, 2, 3, 4, 5 ];
2009     assert(remove!(SwapStrategy.stable)(a, 1) == [ 0, 2, 3, 4, 5 ]);
2010     a = [ 0, 1, 2, 3, 4, 5 ];
2011     assert(remove!(SwapStrategy.stable)(a, 1, 3) == [ 0, 2, 4, 5] );
2012     a = [ 0, 1, 2, 3, 4, 5 ];
2013     assert(remove!(SwapStrategy.stable)(a, 1, tuple(3, 6)) == [ 0, 2 ]);
2014 
2015     a = [ 0, 1, 2, 3, 4, 5 ];
2016     assert(remove!(SwapStrategy.unstable)(a, 1) == [0, 5, 2, 3, 4]);
2017     a = [ 0, 1, 2, 3, 4, 5 ];
2018     assert(remove!(SwapStrategy.unstable)(a, tuple(1, 4)) == [0, 5, 4]);
2019 }
2020 
2021 ///
2022 @safe pure unittest
2023 {
2024     import std.typecons : tuple;
2025 
2026     // Delete an index
2027     assert([4, 5, 6].remove(1) == [4, 6]);
2028 
2029     // Delete multiple indices
2030     assert([4, 5, 6, 7, 8].remove(1, 3) == [4, 6, 8]);
2031 
2032     // Use an indices range
2033     assert([4, 5, 6, 7, 8].remove(tuple(1, 3)) == [4, 7, 8]);
2034 
2035     // Use an indices range and individual indices
2036     assert([4, 5, 6, 7, 8].remove(0, tuple(1, 3), 4) == [7]);
2037 }
2038 
2039 /// `SwapStrategy.unstable` is faster, but doesn't guarantee the same order of the original array
2040 @safe pure unittest
2041 {
2042     assert([5, 6, 7, 8].remove!(SwapStrategy.stable)(1) == [5, 7, 8]);
2043     assert([5, 6, 7, 8].remove!(SwapStrategy.unstable)(1) == [5, 8, 7]);
2044 }
2045 
2046 private auto removeImpl(SwapStrategy s, Range, Offset...)(Range range, Offset offset)
2047 {
2048     static if (isNarrowString!Range)
2049     {
2050         static assert(isMutable!(typeof(range[0])),
2051                 "Elements must be mutable to remove");
2052         static assert(s == SwapStrategy.stable,
2053                 "Only stable removing can be done for character arrays");
2054         return removeStableString(range, offset);
2055     }
2056     else
2057     {
2058         static assert(isBidirectionalRange!Range,
2059                 "Range must be bidirectional");
2060         static assert(hasLvalueElements!Range,
2061                 "Range must have Lvalue elements (see std.range.hasLvalueElements)");
2062 
2063         static if (s == SwapStrategy.unstable)
2064         {
2065             static assert(hasLength!Range,
2066                     "Range must have `length` for unstable remove");
2067             return removeUnstable(range, offset);
2068         }
2069         else static if (s == SwapStrategy.stable)
2070             return removeStable(range, offset);
2071         else
2072             static assert(false,
2073                     "Only SwapStrategy.stable and SwapStrategy.unstable are supported");
2074     }
2075 }
2076 
2077 @safe unittest
2078 {
2079     import std.exception : assertThrown;
2080     import std.range;
2081 
2082     // https://issues.dlang.org/show_bug.cgi?id=10173
2083     int[] test = iota(0, 10).array();
2084     assertThrown(remove!(SwapStrategy.stable)(test, tuple(2, 4), tuple(1, 3)));
2085     assertThrown(remove!(SwapStrategy.unstable)(test, tuple(2, 4), tuple(1, 3)));
2086     assertThrown(remove!(SwapStrategy.stable)(test, 2, 4, 1, 3));
2087     assertThrown(remove!(SwapStrategy.unstable)(test, 2, 4, 1, 3));
2088 }
2089 
2090 @safe unittest
2091 {
2092     import std.range;
2093     int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2094     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2095     assert(remove!(SwapStrategy.stable)(a, 1) ==
2096         [ 0, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]);
2097 
2098     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2099     assert(remove!(SwapStrategy.unstable)(a, 0, 10) ==
2100            [ 9, 1, 2, 3, 4, 5, 6, 7, 8 ]);
2101 
2102     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2103     assert(remove!(SwapStrategy.unstable)(a, 0, tuple(9, 11)) ==
2104             [ 8, 1, 2, 3, 4, 5, 6, 7 ]);
2105     // https://issues.dlang.org/show_bug.cgi?id=5224
2106     a = [ 1, 2, 3, 4 ];
2107     assert(remove!(SwapStrategy.unstable)(a, 2) ==
2108            [ 1, 2, 4 ]);
2109 
2110     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2111     assert(remove!(SwapStrategy.stable)(a, 1, 5) ==
2112         [ 0, 2, 3, 4, 6, 7, 8, 9, 10 ]);
2113 
2114     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2115     assert(remove!(SwapStrategy.stable)(a, 1, 3, 5)
2116             == [ 0, 2, 4, 6, 7, 8, 9, 10]);
2117     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2118     assert(remove!(SwapStrategy.stable)(a, 1, tuple(3, 5))
2119             == [ 0, 2, 5, 6, 7, 8, 9, 10]);
2120 
2121     a = iota(0, 10).array();
2122     assert(remove!(SwapStrategy.unstable)(a, tuple(1, 4), tuple(6, 7))
2123             == [0, 9, 8, 7, 4, 5]);
2124 }
2125 
2126 // https://issues.dlang.org/show_bug.cgi?id=11576
2127 @safe unittest
2128 {
2129     auto arr = [1,2,3];
2130     arr = arr.remove!(SwapStrategy.unstable)(2);
2131     assert(arr == [1,2]);
2132 
2133 }
2134 
2135 // https://issues.dlang.org/show_bug.cgi?id=12889
2136 @safe unittest
2137 {
2138     import std.range;
2139     int[1][] arr = [[0], [1], [2], [3], [4], [5], [6]];
2140     auto orig = arr.dup;
2141     foreach (i; iota(arr.length))
2142     {
2143         assert(orig == arr.remove!(SwapStrategy.unstable)(tuple(i,i)));
2144         assert(orig == arr.remove!(SwapStrategy.stable)(tuple(i,i)));
2145     }
2146 }
2147 
2148 @safe unittest
2149 {
2150     char[] chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
2151     remove(chars, 4);
2152     assert(chars == ['a', 'b', 'c', 'd', 'f', 'g', 'h', 'h']);
2153 
2154     char[] bigChars = "∑œ∆¬é˚˙ƒé∂ß¡¡".dup;
2155     assert(remove(bigChars, tuple(4, 6), 8) == ("∑œ∆¬˙ƒ∂ß¡¡"));
2156 
2157     import std.exception : assertThrown;
2158     assertThrown(remove(bigChars.dup, 1, 0));
2159     assertThrown(remove(bigChars.dup, tuple(4, 3)));
2160 }
2161 
2162 private Range removeUnstable(Range, Offset...)(Range range, Offset offset)
2163 {
2164     Tuple!(size_t, "pos", size_t, "len")[offset.length] blackouts;
2165     foreach (i, v; offset)
2166     {
2167         static if (is(typeof(v[0]) : size_t) && is(typeof(v[1]) : size_t))
2168         {
2169             blackouts[i].pos = v[0];
2170             blackouts[i].len = v[1] - v[0];
2171         }
2172         else
2173         {
2174             static assert(is(typeof(v) : size_t), typeof(v).stringof);
2175             blackouts[i].pos = v;
2176             blackouts[i].len = 1;
2177         }
2178         static if (i > 0)
2179         {
2180             import std.exception : enforce;
2181 
2182             enforce(blackouts[i - 1].pos + blackouts[i - 1].len
2183                     <= blackouts[i].pos,
2184                 "remove(): incorrect ordering of elements to remove");
2185         }
2186     }
2187 
2188     size_t left = 0, right = offset.length - 1;
2189     auto tgt = range.save;
2190     size_t tgtPos = 0;
2191 
2192     while (left <= right)
2193     {
2194         // Look for a blackout on the right
2195         if (blackouts[right].pos + blackouts[right].len >= range.length)
2196         {
2197             range.popBackExactly(blackouts[right].len);
2198 
2199             // Since right is unsigned, we must check for this case, otherwise
2200             // we might turn it into size_t.max and the loop condition will not
2201             // fail when it should.
2202             if (right > 0)
2203             {
2204                 --right;
2205                 continue;
2206             }
2207             else
2208                 break;
2209         }
2210         // Advance to next blackout on the left
2211         assert(blackouts[left].pos >= tgtPos, "Next blackout on the left shouldn't appear before the target.");
2212         tgt.popFrontExactly(blackouts[left].pos - tgtPos);
2213         tgtPos = blackouts[left].pos;
2214 
2215         // Number of elements to the right of blackouts[right]
2216         immutable tailLen = range.length - (blackouts[right].pos + blackouts[right].len);
2217         size_t toMove = void;
2218         if (tailLen < blackouts[left].len)
2219         {
2220             toMove = tailLen;
2221             blackouts[left].pos += toMove;
2222             blackouts[left].len -= toMove;
2223         }
2224         else
2225         {
2226             toMove = blackouts[left].len;
2227             ++left;
2228         }
2229         tgtPos += toMove;
2230         foreach (i; 0 .. toMove)
2231         {
2232             move(range.back, tgt.front);
2233             range.popBack();
2234             tgt.popFront();
2235         }
2236     }
2237 
2238     return range;
2239 }
2240 
2241 private Range removeStable(Range, Offset...)(Range range, Offset offset)
2242 {
2243     auto result = range;
2244     auto src = range, tgt = range;
2245     size_t pos;
2246     foreach (pass, i; offset)
2247     {
2248         static if (is(typeof(i[0])) && is(typeof(i[1])))
2249         {
2250             auto from = i[0], delta = i[1] - i[0];
2251         }
2252         else
2253         {
2254             auto from = i;
2255             enum delta = 1;
2256         }
2257 
2258         static if (pass > 0)
2259         {
2260             import std.exception : enforce;
2261             enforce(pos <= from,
2262                     "remove(): incorrect ordering of elements to remove");
2263 
2264             for (; pos < from; ++pos, src.popFront(), tgt.popFront())
2265             {
2266                 move(src.front, tgt.front);
2267             }
2268         }
2269         else
2270         {
2271             src.popFrontExactly(from);
2272             tgt.popFrontExactly(from);
2273             pos = from;
2274         }
2275         // now skip source to the "to" position
2276         src.popFrontExactly(delta);
2277         result.popBackExactly(delta);
2278         pos += delta;
2279     }
2280     // leftover move
2281     moveAll(src, tgt);
2282     return result;
2283 }
2284 
2285 private Range removeStableString(Range, Offset...)(Range range, Offset offsets)
2286 {
2287     import std.utf : stride;
2288     size_t charIdx = 0;
2289     size_t dcharIdx = 0;
2290     size_t charShift = 0;
2291 
2292     void skipOne()
2293     {
2294         charIdx += stride(range[charIdx .. $]);
2295         ++dcharIdx;
2296     }
2297 
2298     void copyBackOne()
2299     {
2300         auto encodedLen = stride(range[charIdx .. $]);
2301         foreach (j; charIdx .. charIdx + encodedLen)
2302             range[j - charShift] = range[j];
2303         charIdx += encodedLen;
2304         ++dcharIdx;
2305     }
2306 
2307     foreach (pass, i; offsets)
2308     {
2309         static if (is(typeof(i[0])) && is(typeof(i[1])))
2310         {
2311             auto from = i[0];
2312             auto delta = i[1] - i[0];
2313         }
2314         else
2315         {
2316             auto from = i;
2317             enum delta = 1;
2318         }
2319 
2320         import std.exception : enforce;
2321         enforce(dcharIdx <= from && delta >= 0,
2322                 "remove(): incorrect ordering of elements to remove");
2323 
2324         while (dcharIdx < from)
2325             static if (pass == 0)
2326                 skipOne();
2327             else
2328                 copyBackOne();
2329 
2330         auto mark = charIdx;
2331         while (dcharIdx < from + delta)
2332             skipOne();
2333         charShift += charIdx - mark;
2334     }
2335 
2336     foreach (i; charIdx .. range.length)
2337         range[i - charShift] = range[i];
2338 
2339     return range[0 .. $ - charShift];
2340 }
2341 
2342 // Use of dynamic arrays as offsets is too error-prone
2343 // https://issues.dlang.org/show_bug.cgi?id=12086
2344 // Activate these tests once the deprecation period of remove with non-integral tuples is over
2345 @safe unittest
2346 {
2347     //static assert(!__traits(compiles, [0, 1, 2, 3, 4].remove([1, 3]) == [0, 3, 4]));
2348     static assert(__traits(compiles, [0, 1, 2, 3, 4].remove(1, 3) == [0, 2, 4]));
2349     //static assert(!__traits(compiles, assert([0, 1, 2, 3, 4].remove([1, 3, 4]) == [0, 3, 4])));
2350     //static assert(!__traits(compiles, assert([0, 1, 2, 3, 4].remove(tuple(1, 3, 4)) == [0, 3, 4])));
2351 
2352     import std.range : only;
2353     //static assert(!__traits(compiles, assert([0, 1, 2, 3, 4].remove(only(1, 3)) == [0, 3, 4])));
2354     static assert(__traits(compiles, assert([0, 1, 2, 3, 4].remove(1, 3) == [0, 2, 4])));
2355 }
2356 
2357 /**
2358 Reduces the length of the
2359 $(REF_ALTTEXT bidirectional range, isBidirectionalRange, std,range,primitives) `range` by removing
2360 elements that satisfy `pred`. If `s = SwapStrategy.unstable`,
2361 elements are moved from the right end of the range over the elements
2362 to eliminate. If `s = SwapStrategy.stable` (the default),
2363 elements are moved progressively to front such that their relative
2364 order is preserved. Returns the filtered range.
2365 
2366 Params:
2367     range = a bidirectional ranges with lvalue elements
2368         or mutable character arrays
2369 
2370 Returns:
2371     the range with all of the elements where `pred` is `true`
2372     removed
2373 */
2374 Range remove(alias pred, SwapStrategy s = SwapStrategy.stable, Range)(Range range)
2375 {
2376     import std.functional : unaryFun;
2377     alias pred_ = unaryFun!pred;
2378     static if (isNarrowString!Range)
2379     {
2380         static assert(isMutable!(typeof(range[0])),
2381                 "Elements must be mutable to remove");
2382         static assert(s == SwapStrategy.stable,
2383                 "Only stable removing can be done for character arrays");
2384         return removePredString!pred_(range);
2385     }
2386     else
2387     {
2388         static assert(isBidirectionalRange!Range,
2389                 "Range must be bidirectional");
2390         static assert(hasLvalueElements!Range,
2391                 "Range must have Lvalue elements (see std.range.hasLvalueElements)");
2392         static if (s == SwapStrategy.unstable)
2393             return removePredUnstable!pred_(range);
2394         else static if (s == SwapStrategy.stable)
2395             return removePredStable!pred_(range);
2396         else
2397             static assert(false,
2398                     "Only SwapStrategy.stable and SwapStrategy.unstable are supported");
2399     }
2400 }
2401 
2402 ///
2403 @safe unittest
2404 {
2405     static immutable base = [1, 2, 3, 2, 4, 2, 5, 2];
2406 
2407     int[] arr = base[].dup;
2408 
2409     // using a string-based predicate
2410     assert(remove!("a == 2")(arr) == [ 1, 3, 4, 5 ]);
2411 
2412     // The original array contents have been modified,
2413     // so we need to reset it to its original state.
2414     // The length is unmodified however.
2415     arr[] = base[];
2416 
2417     // using a lambda predicate
2418     assert(remove!(a => a == 2)(arr) == [ 1, 3, 4, 5 ]);
2419 }
2420 
2421 @safe unittest
2422 {
2423     int[] a = [ 1, 2, 3, 2, 3, 4, 5, 2, 5, 6 ];
2424     assert(remove!("a == 2", SwapStrategy.unstable)(a) ==
2425             [ 1, 6, 3, 5, 3, 4, 5 ]);
2426     a = [ 1, 2, 3, 2, 3, 4, 5, 2, 5, 6 ];
2427     assert(remove!("a == 2", SwapStrategy.stable)(a) ==
2428             [ 1, 3, 3, 4, 5, 5, 6 ]);
2429 }
2430 
2431 @nogc @safe unittest
2432 {
2433     // @nogc test
2434     static int[] arr = [0,1,2,3,4,5,6,7,8,9];
2435     alias pred = e => e < 5;
2436 
2437     auto r = arr[].remove!(SwapStrategy.unstable)(0);
2438     r = r.remove!(SwapStrategy.stable)(0);
2439     r = r.remove!(pred, SwapStrategy.unstable);
2440     r = r.remove!(pred, SwapStrategy.stable);
2441 }
2442 
2443 @safe unittest
2444 {
2445     import std.algorithm.comparison : min;
2446     import std.algorithm.searching : all, any;
2447     import std.algorithm.sorting : isStrictlyMonotonic;
2448     import std.array : array;
2449     import std.meta : AliasSeq;
2450     import std.range : iota, only;
2451     import std.typecons : Tuple;
2452     alias E = Tuple!(int, int);
2453     alias S = Tuple!(E);
2454     S[] soffsets;
2455     foreach (start; 0 .. 5)
2456     foreach (end; min(start+1,5) .. 5)
2457           soffsets ~= S(E(start,end));
2458     alias D = Tuple!(E, E);
2459     D[] doffsets;
2460     foreach (start1; 0 .. 10)
2461     foreach (end1; min(start1+1,10) .. 10)
2462     foreach (start2; end1 .. 10)
2463     foreach (end2; min(start2+1,10) .. 10)
2464           doffsets ~= D(E(start1,end1),E(start2,end2));
2465     alias T = Tuple!(E, E, E);
2466     T[] toffsets;
2467     foreach (start1; 0 .. 15)
2468     foreach (end1; min(start1+1,15) .. 15)
2469     foreach (start2; end1 .. 15)
2470     foreach (end2; min(start2+1,15) .. 15)
2471     foreach (start3; end2 .. 15)
2472     foreach (end3; min(start3+1,15) .. 15)
2473             toffsets ~= T(E(start1,end1),E(start2,end2),E(start3,end3));
2474 
2475     static void verify(O...)(int[] r, int len, int removed, bool stable, O offsets)
2476     {
2477         assert(r.length == len - removed);
2478         assert(!stable || r.isStrictlyMonotonic);
2479         assert(r.all!(e => all!(o => e < o[0] || e >= o[1])(offsets.only)));
2480     }
2481 
2482     static foreach (offsets; AliasSeq!(soffsets,doffsets,toffsets))
2483     foreach (os; offsets)
2484     {
2485         int len = 5*os.length;
2486         auto w = iota(0, len).array;
2487         auto x = w.dup;
2488         auto y = w.dup;
2489         auto z = w.dup;
2490         alias pred = e => any!(o => o[0] <= e && e < o[1])(only(os.expand));
2491         w = w.remove!(SwapStrategy.unstable)(os.expand);
2492         x = x.remove!(SwapStrategy.stable)(os.expand);
2493         y = y.remove!(pred, SwapStrategy.unstable);
2494         z = z.remove!(pred, SwapStrategy.stable);
2495         int removed;
2496         foreach (o; os)
2497             removed += o[1] - o[0];
2498         verify(w, len, removed, false, os[]);
2499         verify(x, len, removed, true, os[]);
2500         verify(y, len, removed, false, os[]);
2501         verify(z, len, removed, true, os[]);
2502         assert(w == y);
2503         assert(x == z);
2504     }
2505 }
2506 
2507 @safe unittest
2508 {
2509     char[] chars = "abcdefg".dup;
2510     assert(chars.remove!(dc => dc == 'c' || dc == 'f') == "abdeg");
2511     assert(chars == "abdegfg");
2512 
2513     assert(chars.remove!"a == 'd'" == "abegfg");
2514 
2515     char[] bigChars = "¥^¨^©é√∆π".dup;
2516     assert(bigChars.remove!(dc => dc == "¨"d[0] || dc == "é"d[0]) ==  "¥^^©√∆π");
2517 }
2518 
2519 private Range removePredUnstable(alias pred, Range)(Range range)
2520 {
2521     auto result = range;
2522     for (;!range.empty;)
2523     {
2524         if (!pred(range.front))
2525         {
2526             range.popFront();
2527             continue;
2528         }
2529         move(range.back, range.front);
2530         range.popBack();
2531         result.popBack();
2532     }
2533     return result;
2534 }
2535 
2536 private Range removePredStable(alias pred, Range)(Range range)
2537 {
2538     auto result = range;
2539     auto tgt = range;
2540     for (; !range.empty; range.popFront())
2541     {
2542         if (pred(range.front))
2543         {
2544             // yank this guy
2545             result.popBack();
2546             continue;
2547         }
2548         // keep this guy
2549         move(range.front, tgt.front);
2550         tgt.popFront();
2551     }
2552     return result;
2553 }
2554 
2555 private Range removePredString(alias pred, SwapStrategy s = SwapStrategy.stable, Range)
2556 (Range range)
2557 {
2558     import std.utf : decode;
2559     import std.functional : unaryFun;
2560 
2561     alias pred_ = unaryFun!pred;
2562 
2563     size_t charIdx = 0;
2564     size_t charShift = 0;
2565     while (charIdx < range.length)
2566     {
2567         size_t start = charIdx;
2568         if (pred_(decode(range, charIdx)))
2569         {
2570             charShift += charIdx - start;
2571             break;
2572         }
2573     }
2574     while (charIdx < range.length)
2575     {
2576         size_t start = charIdx;
2577         auto doRemove = pred_(decode(range, charIdx));
2578         auto encodedLen = charIdx - start;
2579         if (doRemove)
2580             charShift += encodedLen;
2581         else
2582             foreach (i; start .. charIdx)
2583                 range[i - charShift] = range[i];
2584     }
2585 
2586     return range[0 .. $ - charShift];
2587 }
2588 
2589 // reverse
2590 /**
2591 Reverses `r` in-place.  Performs `r.length / 2` evaluations of `swap`.
2592 UTF sequences consisting of multiple code units are preserved properly.
2593 
2594 Params:
2595     r = a $(REF_ALTTEXT bidirectional range, isBidirectionalRange, std,range,primitives)
2596         with either swappable elements, a random access range with a length member,
2597         or a narrow string
2598 
2599 Returns: `r`
2600 
2601 Note:
2602     When passing a string with unicode modifiers on characters, such as `\u0301`,
2603     this function will not properly keep the position of the modifier. For example,
2604     reversing `ba\u0301d` ("bád") will result in d\u0301ab ("d́ab") instead of
2605     `da\u0301b` ("dáb").
2606 
2607 See_Also: $(REF retro, std,range) for a lazy reverse without changing `r`
2608 */
2609 Range reverse(Range)(Range r)
2610 if (isBidirectionalRange!Range &&
2611         (hasSwappableElements!Range ||
2612          (hasAssignableElements!Range && hasLength!Range && isRandomAccessRange!Range) ||
2613          (isNarrowString!Range && isAssignable!(ElementType!Range))))
2614 {
2615     static if (isRandomAccessRange!Range && hasLength!Range)
2616     {
2617         //swapAt is in fact the only way to swap non lvalue ranges
2618         immutable last = r.length - 1;
2619         immutable steps = r.length / 2;
2620         for (size_t i = 0; i < steps; i++)
2621         {
2622             r.swapAt(i, last - i);
2623         }
2624         return r;
2625     }
2626     else static if (isNarrowString!Range && isAssignable!(ElementType!Range))
2627     {
2628         import std.string : representation;
2629         import std.utf : stride;
2630 
2631         auto raw = representation(r);
2632         for (size_t i = 0; i < r.length;)
2633         {
2634             immutable step = stride(r, i);
2635             if (step > 1)
2636             {
2637                 .reverse(raw[i .. i + step]);
2638                 i += step;
2639             }
2640             else
2641             {
2642                 ++i;
2643             }
2644         }
2645         reverse(raw);
2646         return r;
2647     }
2648     else
2649     {
2650         while (!r.empty)
2651         {
2652             swap(r.front, r.back);
2653             r.popFront();
2654             if (r.empty) break;
2655             r.popBack();
2656         }
2657         return r;
2658     }
2659 }
2660 
2661 ///
2662 @safe unittest
2663 {
2664     int[] arr = [ 1, 2, 3 ];
2665     assert(arr.reverse == [ 3, 2, 1 ]);
2666 }
2667 
2668 @safe unittest
2669 {
2670     int[] range = null;
2671     reverse(range);
2672     range = [ 1 ];
2673     reverse(range);
2674     assert(range == [1]);
2675     range = [1, 2];
2676     reverse(range);
2677     assert(range == [2, 1]);
2678     range = [1, 2, 3];
2679     assert(range.reverse == [3, 2, 1]);
2680 }
2681 
2682 ///
2683 @safe unittest
2684 {
2685     char[] arr = "hello\U00010143\u0100\U00010143".dup;
2686     assert(arr.reverse == "\U00010143\u0100\U00010143olleh");
2687 }
2688 
2689 @safe unittest
2690 {
2691     void test(string a, string b)
2692     {
2693         auto c = a.dup;
2694         reverse(c);
2695         assert(c == b, c ~ " != " ~ b);
2696     }
2697 
2698     test("a", "a");
2699     test(" ", " ");
2700     test("\u2029", "\u2029");
2701     test("\u0100", "\u0100");
2702     test("\u0430", "\u0430");
2703     test("\U00010143", "\U00010143");
2704     test("abcdefcdef", "fedcfedcba");
2705     test("hello\U00010143\u0100\U00010143", "\U00010143\u0100\U00010143olleh");
2706 }
2707 
2708 /**
2709     The strip group of functions allow stripping of either leading, trailing,
2710     or both leading and trailing elements.
2711 
2712     The `stripLeft` function will strip the `front` of the range,
2713     the `stripRight` function will strip the `back` of the range,
2714     while the `strip` function will strip both the `front` and `back`
2715     of the range.
2716 
2717     Note that the `strip` and `stripRight` functions require the range to
2718     be a $(LREF BidirectionalRange) range.
2719 
2720     All of these functions come in two varieties: one takes a target element,
2721     where the range will be stripped as long as this element can be found.
2722     The other takes a lambda predicate, where the range will be stripped as
2723     long as the predicate returns true.
2724 
2725     Params:
2726         range = a $(REF_ALTTEXT bidirectional range, isBidirectionalRange, std,range,primitives)
2727         or $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
2728         element = the elements to remove
2729 
2730     Returns:
2731         a Range with all of range except element at the start and end
2732 */
2733 Range strip(Range, E)(Range range, E element)
2734 if (isBidirectionalRange!Range && is(typeof(range.front == element) : bool))
2735 {
2736     return range.stripLeft(element).stripRight(element);
2737 }
2738 
2739 /// ditto
2740 Range strip(alias pred, Range)(Range range)
2741 if (isBidirectionalRange!Range && is(typeof(pred(range.back)) : bool))
2742 {
2743     return range.stripLeft!pred().stripRight!pred();
2744 }
2745 
2746 /// ditto
2747 Range stripLeft(Range, E)(Range range, E element)
2748 if (isInputRange!Range && is(typeof(range.front == element) : bool))
2749 {
2750     import std.algorithm.searching : find;
2751     return find!((auto ref a) => a != element)(range);
2752 }
2753 
2754 /// ditto
2755 Range stripLeft(alias pred, Range)(Range range)
2756 if (isInputRange!Range && is(typeof(pred(range.front)) : bool))
2757 {
2758     import std.algorithm.searching : find;
2759     import std.functional : not;
2760 
2761     return find!(not!pred)(range);
2762 }
2763 
2764 /// ditto
2765 Range stripRight(Range, E)(Range range, E element)
2766 if (isBidirectionalRange!Range && is(typeof(range.back == element) : bool))
2767 {
2768     for (; !range.empty; range.popBack())
2769     {
2770         if (range.back != element)
2771             break;
2772     }
2773     return range;
2774 }
2775 
2776 /// ditto
2777 Range stripRight(alias pred, Range)(Range range)
2778 if (isBidirectionalRange!Range && is(typeof(pred(range.back)) : bool))
2779 {
2780     for (; !range.empty; range.popBack())
2781     {
2782         if (!pred(range.back))
2783             break;
2784     }
2785     return range;
2786 }
2787 
2788 /// Strip leading and trailing elements equal to the target element.
2789 @safe pure unittest
2790 {
2791     assert("  foobar  ".strip(' ') == "foobar");
2792     assert("00223.444500".strip('0') == "223.4445");
2793     assert("ëëêéüŗōpéêëë".strip('ë') == "êéüŗōpéê");
2794     assert([1, 1, 0, 1, 1].strip(1) == [0]);
2795     assert([0.0, 0.01, 0.01, 0.0].strip(0).length == 2);
2796 }
2797 
2798 /// Strip leading and trailing elements while the predicate returns true.
2799 @safe pure unittest
2800 {
2801     assert("  foobar  ".strip!(a => a == ' ')() == "foobar");
2802     assert("00223.444500".strip!(a => a == '0')() == "223.4445");
2803     assert("ëëêéüŗōpéêëë".strip!(a => a == 'ë')() == "êéüŗōpéê");
2804     assert([1, 1, 0, 1, 1].strip!(a => a == 1)() == [0]);
2805     assert([0.0, 0.01, 0.5, 0.6, 0.01, 0.0].strip!(a => a < 0.4)().length == 2);
2806 }
2807 
2808 /// Strip leading elements equal to the target element.
2809 @safe pure unittest
2810 {
2811     assert("  foobar  ".stripLeft(' ') == "foobar  ");
2812     assert("00223.444500".stripLeft('0') == "223.444500");
2813     assert("ůůűniçodêéé".stripLeft('ů') == "űniçodêéé");
2814     assert([1, 1, 0, 1, 1].stripLeft(1) == [0, 1, 1]);
2815     assert([0.0, 0.01, 0.01, 0.0].stripLeft(0).length == 3);
2816 }
2817 
2818 /// Strip leading elements while the predicate returns true.
2819 @safe pure unittest
2820 {
2821     assert("  foobar  ".stripLeft!(a => a == ' ')() == "foobar  ");
2822     assert("00223.444500".stripLeft!(a => a == '0')() == "223.444500");
2823     assert("ůůűniçodêéé".stripLeft!(a => a == 'ů')() == "űniçodêéé");
2824     assert([1, 1, 0, 1, 1].stripLeft!(a => a == 1)() == [0, 1, 1]);
2825     assert([0.0, 0.01, 0.10, 0.5, 0.6].stripLeft!(a => a < 0.4)().length == 2);
2826 }
2827 
2828 /// Strip trailing elements equal to the target element.
2829 @safe pure unittest
2830 {
2831     assert("  foobar  ".stripRight(' ') == "  foobar");
2832     assert("00223.444500".stripRight('0') == "00223.4445");
2833     assert("ùniçodêéé".stripRight('é') == "ùniçodê");
2834     assert([1, 1, 0, 1, 1].stripRight(1) == [1, 1, 0]);
2835     assert([0.0, 0.01, 0.01, 0.0].stripRight(0).length == 3);
2836 }
2837 
2838 /// Strip trailing elements while the predicate returns true.
2839 @safe pure unittest
2840 {
2841     assert("  foobar  ".stripRight!(a => a == ' ')() == "  foobar");
2842     assert("00223.444500".stripRight!(a => a == '0')() == "00223.4445");
2843     assert("ùniçodêéé".stripRight!(a => a == 'é')() == "ùniçodê");
2844     assert([1, 1, 0, 1, 1].stripRight!(a => a == 1)() == [1, 1, 0]);
2845     assert([0.0, 0.01, 0.10, 0.5, 0.6].stripRight!(a => a > 0.4)().length == 3);
2846 }
2847 
2848 // swap
2849 /**
2850 Swaps `lhs` and `rhs`. The instances `lhs` and `rhs` are moved in
2851 memory, without ever calling `opAssign`, nor any other function. `T`
2852 need not be assignable at all to be swapped.
2853 
2854 If `lhs` and `rhs` reference the same instance, then nothing is done.
2855 
2856 `lhs` and `rhs` must be mutable. If `T` is a struct or union, then
2857 its fields must also all be (recursively) mutable.
2858 
2859 Params:
2860     lhs = Data to be swapped with `rhs`.
2861     rhs = Data to be swapped with `lhs`.
2862 */
2863 void swap(T)(ref T lhs, ref T rhs) @trusted pure nothrow @nogc
2864 if (isBlitAssignable!T && !is(typeof(lhs.proxySwap(rhs))))
2865 {
2866     import std.traits : hasAliasing, hasElaborateAssign, isAssignable,
2867                         isStaticArray;
2868     static if (hasAliasing!T) if (!__ctfe)
2869     {
2870         import std.exception : doesPointTo;
2871         assert(!doesPointTo(lhs, lhs), "Swap: lhs internal pointer.");
2872         assert(!doesPointTo(rhs, rhs), "Swap: rhs internal pointer.");
2873         assert(!doesPointTo(lhs, rhs), "Swap: lhs points to rhs.");
2874         assert(!doesPointTo(rhs, lhs), "Swap: rhs points to lhs.");
2875     }
2876 
2877     static if (hasElaborateAssign!T || !isAssignable!T)
2878     {
2879         if (&lhs != &rhs)
2880         {
2881             // For structs with non-trivial assignment, move memory directly
2882             ubyte[T.sizeof] t = void;
2883             auto a = (cast(ubyte*) &lhs)[0 .. T.sizeof];
2884             auto b = (cast(ubyte*) &rhs)[0 .. T.sizeof];
2885             t[] = a[];
2886             a[] = b[];
2887             b[] = t[];
2888         }
2889     }
2890     else
2891     {
2892         //Avoid assigning overlapping arrays. Dynamic arrays are fine, because
2893         //it's their ptr and length properties which get assigned rather
2894         //than their elements when assigning them, but static arrays are value
2895         //types and therefore all of their elements get copied as part of
2896         //assigning them, which would be assigning overlapping arrays if lhs
2897         //and rhs were the same array.
2898         static if (isStaticArray!T)
2899         {
2900             if (lhs.ptr == rhs.ptr)
2901                 return;
2902         }
2903 
2904         // For non-elaborate-assign types, suffice to do the classic swap
2905         static if (__traits(hasCopyConstructor, T))
2906         {
2907             // don't invoke any elaborate constructors either
2908             T tmp = void;
2909             tmp = lhs;
2910         }
2911         else
2912             auto tmp = lhs;
2913         lhs = rhs;
2914         rhs = tmp;
2915     }
2916 }
2917 
2918 ///
2919 @safe unittest
2920 {
2921     // Swapping POD (plain old data) types:
2922     int a = 42, b = 34;
2923     swap(a, b);
2924     assert(a == 34 && b == 42);
2925 
2926     // Swapping structs with indirection:
2927     static struct S { int x; char c; int[] y; }
2928     S s1 = { 0, 'z', [ 1, 2 ] };
2929     S s2 = { 42, 'a', [ 4, 6 ] };
2930     swap(s1, s2);
2931     assert(s1.x == 42);
2932     assert(s1.c == 'a');
2933     assert(s1.y == [ 4, 6 ]);
2934 
2935     assert(s2.x == 0);
2936     assert(s2.c == 'z');
2937     assert(s2.y == [ 1, 2 ]);
2938 
2939     // Immutables cannot be swapped:
2940     immutable int imm1 = 1, imm2 = 2;
2941     static assert(!__traits(compiles, swap(imm1, imm2)));
2942 
2943     int c = imm1 + 0;
2944     int d = imm2 + 0;
2945     swap(c, d);
2946     assert(c == 2);
2947     assert(d == 1);
2948 }
2949 
2950 ///
2951 @safe unittest
2952 {
2953     // Non-copyable types can still be swapped.
2954     static struct NoCopy
2955     {
2956         this(this) { assert(0); }
2957         int n;
2958         string s;
2959     }
2960     NoCopy nc1, nc2;
2961     nc1.n = 127; nc1.s = "abc";
2962     nc2.n = 513; nc2.s = "uvwxyz";
2963 
2964     swap(nc1, nc2);
2965     assert(nc1.n == 513 && nc1.s == "uvwxyz");
2966     assert(nc2.n == 127 && nc2.s == "abc");
2967 
2968     swap(nc1, nc1);
2969     swap(nc2, nc2);
2970     assert(nc1.n == 513 && nc1.s == "uvwxyz");
2971     assert(nc2.n == 127 && nc2.s == "abc");
2972 
2973     // Types containing non-copyable fields can also be swapped.
2974     static struct NoCopyHolder
2975     {
2976         NoCopy noCopy;
2977     }
2978     NoCopyHolder h1, h2;
2979     h1.noCopy.n = 31; h1.noCopy.s = "abc";
2980     h2.noCopy.n = 65; h2.noCopy.s = null;
2981 
2982     swap(h1, h2);
2983     assert(h1.noCopy.n == 65 && h1.noCopy.s == null);
2984     assert(h2.noCopy.n == 31 && h2.noCopy.s == "abc");
2985 
2986     swap(h1, h1);
2987     swap(h2, h2);
2988     assert(h1.noCopy.n == 65 && h1.noCopy.s == null);
2989     assert(h2.noCopy.n == 31 && h2.noCopy.s == "abc");
2990 
2991     // Const types cannot be swapped.
2992     const NoCopy const1, const2;
2993     assert(const1.n == 0 && const2.n == 0);
2994     static assert(!__traits(compiles, swap(const1, const2)));
2995 }
2996 
2997 // https://issues.dlang.org/show_bug.cgi?id=4789
2998 @safe unittest
2999 {
3000     int[1] s = [1];
3001     swap(s, s);
3002 
3003     int[3] a = [1, 2, 3];
3004     swap(a[1], a[2]);
3005     assert(a == [1, 3, 2]);
3006 }
3007 
3008 @safe unittest
3009 {
3010     static struct NoAssign
3011     {
3012         int i;
3013         void opAssign(NoAssign) @disable;
3014     }
3015     auto s1 = NoAssign(1);
3016     auto s2 = NoAssign(2);
3017     swap(s1, s2);
3018     assert(s1.i == 2);
3019     assert(s2.i == 1);
3020 }
3021 
3022 @safe unittest
3023 {
3024     struct S
3025     {
3026         const int i;
3027         int i2 = 2;
3028         int i3 = 3;
3029     }
3030     S s;
3031     static assert(!__traits(compiles, swap(s, s)));
3032     swap(s.i2, s.i3);
3033     assert(s.i2 == 3);
3034     assert(s.i3 == 2);
3035 }
3036 
3037 // https://issues.dlang.org/show_bug.cgi?id=11853
3038 @safe unittest
3039 {
3040     import std.traits : isAssignable;
3041     alias T = Tuple!(int, double);
3042     static assert(isAssignable!T);
3043 }
3044 
3045 // https://issues.dlang.org/show_bug.cgi?id=12024
3046 @safe unittest
3047 {
3048     import std.datetime;
3049     SysTime a, b;
3050     swap(a, b);
3051 }
3052 
3053 // https://issues.dlang.org/show_bug.cgi?id=9975
3054 @system unittest
3055 {
3056     import std.exception : doesPointTo, mayPointTo;
3057     static struct S2
3058     {
3059         union
3060         {
3061             size_t sz;
3062             string s;
3063         }
3064     }
3065     S2 a , b;
3066     a.sz = -1;
3067     assert(!doesPointTo(a, b));
3068     assert( mayPointTo(a, b));
3069     swap(a, b);
3070 
3071     //Note: we can catch an error here, because there is no RAII in this test
3072     import std.exception : assertThrown;
3073     void* p, pp;
3074     p = &p;
3075     assertThrown!Error(move(p));
3076     assertThrown!Error(move(p, pp));
3077     assertThrown!Error(swap(p, pp));
3078 }
3079 
3080 @system unittest
3081 {
3082     static struct A
3083     {
3084         int* x;
3085         this(this) { x = new int; }
3086     }
3087     A a1, a2;
3088     swap(a1, a2);
3089 
3090     static struct B
3091     {
3092         int* x;
3093         void opAssign(B) { x = new int; }
3094     }
3095     B b1, b2;
3096     swap(b1, b2);
3097 }
3098 
3099 // https://issues.dlang.org/show_bug.cgi?id=20732
3100 @safe unittest
3101 {
3102     static struct A
3103     {
3104         int x;
3105         this(scope ref return const A other)
3106         {
3107             import std.stdio;
3108             x = other.x;
3109             // note, struct functions inside @safe functions infer ALL
3110             // attributes, so the following 3 lines are meant to prevent this.
3111             new int; // prevent @nogc inference
3112             writeln("impure"); // prevent pure inference
3113             throw new Exception(""); // prevent nothrow inference
3114         }
3115     }
3116 
3117     A a1, a2;
3118     swap(a1, a2);
3119 
3120     A[1] a3, a4;
3121     swap(a3, a4);
3122 }
3123 
3124 /// ditto
3125 void swap(T)(ref T lhs, ref T rhs)
3126 if (is(typeof(lhs.proxySwap(rhs))))
3127 {
3128     lhs.proxySwap(rhs);
3129 }
3130 
3131 /**
3132 Swaps two elements in-place of a range `r`,
3133 specified by their indices `i1` and `i2`.
3134 
3135 Params:
3136     r  = a range with swappable elements
3137     i1 = first index
3138     i2 = second index
3139 */
3140 void swapAt(R)(auto ref R r, size_t i1, size_t i2)
3141 {
3142     static if (is(typeof(&r.swapAt)))
3143     {
3144         r.swapAt(i1, i2);
3145     }
3146     else static if (is(typeof(&r[i1])))
3147     {
3148         swap(r[i1], r[i2]);
3149     }
3150     else
3151     {
3152         if (i1 == i2) return;
3153         auto t1 = r.moveAt(i1);
3154         auto t2 = r.moveAt(i2);
3155         r[i2] = t1;
3156         r[i1] = t2;
3157     }
3158 }
3159 
3160 ///
3161 pure @safe nothrow unittest
3162 {
3163     import std.algorithm.comparison : equal;
3164     auto a = [1, 2, 3];
3165     a.swapAt(1, 2);
3166     assert(a.equal([1, 3, 2]));
3167 }
3168 
3169 pure @safe nothrow unittest
3170 {
3171     import std.algorithm.comparison : equal;
3172     auto a = [4, 5, 6];
3173     a.swapAt(1, 1);
3174     assert(a.equal([4, 5, 6]));
3175 }
3176 
3177 pure @safe nothrow unittest
3178 {
3179     // test non random access ranges
3180     import std.algorithm.comparison : equal;
3181     import std.array : array;
3182 
3183     char[] b = ['a', 'b', 'c'];
3184     b.swapAt(1, 2);
3185     assert(b.equal(['a', 'c', 'b']));
3186 
3187     int[3] c = [1, 2, 3];
3188     c.swapAt(1, 2);
3189     assert(c.array.equal([1, 3, 2]));
3190 
3191     // opIndex returns lvalue
3192     struct RandomIndexType(T)
3193     {
3194         T payload;
3195 
3196         @property ref auto opIndex(size_t i)
3197         {
3198            return payload[i];
3199         }
3200 
3201     }
3202     auto d = RandomIndexType!(int[])([4, 5, 6]);
3203     d.swapAt(1, 2);
3204     assert(d.payload.equal([4, 6, 5]));
3205 
3206     // custom moveAt and opIndexAssign
3207     struct RandomMoveAtType(T)
3208     {
3209         T payload;
3210 
3211         ElementType!T moveAt(size_t i)
3212         {
3213            return payload.moveAt(i);
3214         }
3215 
3216         void opIndexAssign(ElementType!T val, size_t idx)
3217         {
3218             payload[idx] = val;
3219         }
3220     }
3221     auto e = RandomMoveAtType!(int[])([7, 8, 9]);
3222     e.swapAt(1, 2);
3223     assert(e.payload.equal([7, 9, 8]));
3224 
3225 
3226     // custom swapAt
3227     struct RandomSwapAtType(T)
3228     {
3229         T payload;
3230 
3231         void swapAt(size_t i)
3232         {
3233            return payload.swapAt(i);
3234         }
3235     }
3236     auto f = RandomMoveAtType!(int[])([10, 11, 12]);
3237     swapAt(f, 1, 2);
3238     assert(f.payload.equal([10, 12, 11]));
3239 }
3240 
3241 private void swapFront(R1, R2)(R1 r1, R2 r2)
3242 if (isInputRange!R1 && isInputRange!R2)
3243 {
3244     static if (is(typeof(swap(r1.front, r2.front))))
3245     {
3246         swap(r1.front, r2.front);
3247     }
3248     else
3249     {
3250         auto t1 = moveFront(r1), t2 = moveFront(r2);
3251         r1.front = move(t2);
3252         r2.front = move(t1);
3253     }
3254 }
3255 
3256 // swapRanges
3257 /**
3258 Swaps all elements of `r1` with successive elements in `r2`.
3259 Returns a tuple containing the remainder portions of `r1` and $(D
3260 r2) that were not swapped (one of them will be empty). The ranges may
3261 be of different types but must have the same element type and support
3262 swapping.
3263 
3264 Params:
3265     r1 = an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
3266          with swappable elements
3267     r2 = an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
3268          with swappable elements
3269 
3270 Returns:
3271     Tuple containing the remainder portions of r1 and r2 that were not swapped
3272 */
3273 Tuple!(InputRange1, InputRange2)
3274 swapRanges(InputRange1, InputRange2)(InputRange1 r1, InputRange2 r2)
3275 if (hasSwappableElements!InputRange1 && hasSwappableElements!InputRange2
3276     && is(ElementType!InputRange1 == ElementType!InputRange2))
3277 {
3278     for (; !r1.empty && !r2.empty; r1.popFront(), r2.popFront())
3279     {
3280         swap(r1.front, r2.front);
3281     }
3282     return tuple(r1, r2);
3283 }
3284 
3285 ///
3286 @safe unittest
3287 {
3288     import std.range : empty;
3289     int[] a = [ 100, 101, 102, 103 ];
3290     int[] b = [ 0, 1, 2, 3 ];
3291     auto c = swapRanges(a[1 .. 3], b[2 .. 4]);
3292     assert(c[0].empty && c[1].empty);
3293     assert(a == [ 100, 2, 3, 103 ]);
3294     assert(b == [ 0, 1, 101, 102 ]);
3295 }
3296 
3297 /**
3298 Initializes each element of `range` with `value`.
3299 Assumes that the elements of the range are uninitialized.
3300 This is of interest for structs that
3301 define copy constructors (for all other types, $(LREF fill) and
3302 uninitializedFill are equivalent).
3303 
3304 Params:
3305         range = An
3306                 $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
3307                 that exposes references to its elements and has assignable
3308                 elements
3309         value = Assigned to each element of range
3310 
3311 See_Also:
3312         $(LREF fill)
3313         $(LREF initializeAll)
3314  */
3315 void uninitializedFill(Range, Value)(Range range, Value value)
3316 if (isInputRange!Range && hasLvalueElements!Range && is(typeof(range.front = value)))
3317 {
3318     import std.traits : hasElaborateAssign;
3319 
3320     alias T = ElementType!Range;
3321     static if (hasElaborateAssign!T)
3322     {
3323         import core.internal.lifetime : emplaceRef;
3324 
3325         // Must construct stuff by the book
3326         for (; !range.empty; range.popFront())
3327             emplaceRef!T(range.front, value);
3328     }
3329     else
3330         // Doesn't matter whether fill is initialized or not
3331         return fill(range, value);
3332 }
3333 
3334 ///
3335 nothrow @system unittest
3336 {
3337     import core.stdc.stdlib : malloc, free;
3338 
3339     auto s = (cast(int*) malloc(5 * int.sizeof))[0 .. 5];
3340     uninitializedFill(s, 42);
3341     assert(s == [ 42, 42, 42, 42, 42 ]);
3342 
3343     scope(exit) free(s.ptr);
3344 }