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

root/trunk/phobos/std/algorithm.d

Revision 2373, 218.3 kB (checked in by andrei, 14 years ago)

findSplit, findSplitBefore, findSplitAfter

  • Property svn:eol-style set to native
Line 
1 // Written in the D programming language.
2
3 /**
4 Implements algorithms oriented mainly towards processing of
5 sequences. Some functions are semantic equivalents or supersets of
6 those found in the $(D $(LESS)_algorithm$(GREATER)) header in $(WEB
7 sgi.com/tech/stl/, Alexander Stepanov's Standard Template Library) for
8 C++.
9
10 Note:
11
12 Many functions in this module are parameterized with a function or a
13 $(GLOSSARY predicate). The predicate may be passed either as a
14 function name, a delegate name, a $(GLOSSARY functor) name, or a
15 compile-time string. The string may consist of $(B any) legal D
16 expression that uses the symbol $(D a) (for unary functions) or the
17 symbols $(D a) and $(D b) (for binary functions). These names will NOT
18 interfere with other homonym symbols in user code because they are
19 evaluated in a different context. The default for all binary
20 comparison predicates is $(D "a == b") for unordered operations and
21 $(D "a < b") for ordered operations.
22
23 Example:
24
25 ----
26 int[] a = ...;
27 static bool greater(int a, int b)
28 {
29     return a > b;
30 }
31 sort!(greater)(a);  // predicate as alias
32 sort!("a > b")(a);  // predicate as string
33                     // (no ambiguity with array name)
34 sort(a);            // no predicate, "a < b" is implicit
35 ----
36
37 Macros:
38 WIKI = Phobos/StdAlgorithm
39
40 Copyright: Andrei Alexandrescu 2008-.
41
42 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
43
44 Authors:   $(WEB erdani.com, Andrei Alexandrescu)
45  */
46 module std.algorithm;
47 //debug = std_algorithm;
48
49 import std.c.string;
50 import std.array, std.container, std.conv, std.exception,
51     std.functional, std.math, std.metastrings, std.range, std.string,
52     std.traits, std.typecons, std.typetuple, std.stdio;
53
54 version(unittest)
55 {
56     import std.random, std.stdio, std.string;
57     mixin(dummyRanges);
58 }
59
60 /**
61 Implements the homonym function (also known as $(D transform)) present
62 in many languages of functional flavor. The call $(D map!(fun)(range))
63 returns a range of which elements are obtained by applying $(D fun(x))
64 left to right for all $(D x) in $(D range). The original ranges are
65 not changed. Evaluation is done lazily. The range returned by $(D map)
66 caches the last value such that evaluating $(D front) multiple times
67 does not result in multiple calls to $(D fun).
68
69 Example:
70 ----
71 int[] arr1 = [ 1, 2, 3, 4 ];
72 int[] arr2 = [ 5, 6 ];
73 auto squares = map!("a * a")(chain(arr1, arr2));
74 assert(equal(squares, [ 1, 4, 9, 16, 25, 36 ]));
75 ----
76
77 Multiple functions can be passed to $(D map). In that case, the
78 element type of $(D map) is a tuple containing one element for each
79 function.
80
81 Example:
82
83 ----
84 auto arr1 = [ 1, 2, 3, 4 ];
85 foreach (e; map!("a + a", "a * a")(arr1))
86 {
87     writeln(e[0], " ", e[1]);
88 }
89 ----
90
91 You may alias $(D map) with some function(s) to a symbol and use it
92 separately:
93
94 ----
95 alias map!(to!string) stringize;
96 assert(equal(stringize([ 1, 2, 3, 4 ]), [ "1", "2", "3", "4" ]));
97 ----
98  */
99 template map(fun...)
100 {
101     auto map(Range)(Range r)
102     {
103         static if (fun.length > 1)
104         {
105             return Map!(adjoin!(staticMap!(unaryFun, fun)), Range)(r);
106         }
107         else
108         {
109             return Map!(unaryFun!fun, Range)(r);
110         }
111     }
112 }
113
114 struct Map(alias fun, Range) if (isInputRange!(Unqual!Range))
115 {
116     alias Unqual!Range R;
117     alias fun _fun;
118     // Uncomment this to reveal a @@@BUG@@@ in the compiler
119     //alias typeof(fun(.ElementType!R.init)) ElementType;
120     alias typeof({ return fun(.ElementType!R.init); }()) ElementType;
121     R _input;
122
123     static if (isBidirectionalRange!(R))
124     {
125         @property ElementType back()
126         {
127             return _fun(_input.back);
128         }
129
130         void popBack()
131         {
132             _input.popBack();
133         }
134     }
135
136     this(R input)
137     {
138         _input = input;
139     }
140
141     static if (isInfinite!R)
142     {
143         // Propagate infinite-ness.
144         enum bool empty = false;
145     }
146     else
147     {
148         @property bool empty()
149         {
150             return _input.empty;
151         }
152     }
153
154     void popFront()
155     {
156         _input.popFront();
157     }
158
159     @property ElementType front()
160     {
161         return _fun(_input.front);
162     }
163
164     static if (isRandomAccessRange!R)
165     {
166         ElementType opIndex(size_t index)
167         {
168             return _fun(_input[index]);
169         }
170     }
171
172     // hasLength is busted, Bug 2873
173     static if (is(typeof(_input.length) : size_t)
174         || is(typeof(_input.length()) : size_t))
175     {
176         @property size_t length()
177         {
178             return _input.length;
179         }
180     }
181
182     static if (hasSlicing!(R))
183     {
184         typeof(this) opSlice(size_t lowerBound, size_t upperBound)
185         {
186             return typeof(this)(_input[lowerBound..upperBound]);
187         }
188     }
189
190     static if (isForwardRange!R)
191     @property Map save()
192     {
193         auto result = this;
194         result._input = result._input.save;
195         return result;
196     }
197 }
198
199 unittest
200 {
201     debug(std_algorithm) scope(success)
202         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
203     alias map!(to!string) stringize;
204     assert(equal(stringize([ 1, 2, 3, 4 ]), [ "1", "2", "3", "4" ]));
205     uint counter;
206     alias map!((a) { return counter++; }) count;
207     assert(equal(count([ 10, 2, 30, 4 ]), [ 0, 1, 2, 3 ]));
208     counter = 0;
209     adjoin!((a) { return counter++; }, (a) { return counter++; })(1);
210     alias map!((a) { return counter++; }, (a) { return counter++; }) countAndSquare;
211     //assert(equal(countAndSquare([ 10, 2 ]), [ tuple(0u, 100), tuple(1u, 4) ]));
212 }
213
214 unittest
215 {
216     debug(std_algorithm) scope(success)
217         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
218     int[] arr1 = [ 1, 2, 3, 4 ];
219     const int[] arr1Const = arr1;
220     int[] arr2 = [ 5, 6 ];
221     auto squares = map!("a * a")(arr1Const);
222     assert(equal(squares, [ 1, 4, 9, 16 ][]));
223     assert(equal(map!("a * a")(chain(arr1, arr2)), [ 1, 4, 9, 16, 25, 36 ][]));
224
225     // Test the caching stuff.
226     assert(squares.back == 16);
227     auto squares2 = squares.save;
228     assert(squares2.back == 16);
229
230     assert(squares2.front == 1);
231     squares2.popFront;
232     assert(squares2.front == 4);
233     squares2.popBack;
234     assert(squares2.front == 4);
235     assert(squares2.back == 9);
236
237     assert(equal(map!("a * a")(chain(arr1, arr2)), [ 1, 4, 9, 16, 25, 36 ][]));
238
239     uint i;
240     foreach (e; map!("a", "a * a")(arr1))
241     {
242         assert(e[0] == ++i);
243         assert(e[1] == i * i);
244     }
245
246     // Test length.
247     assert(squares.length == 4);
248     assert(map!"a * a"(chain(arr1, arr2)).length == 6);
249
250     // Test indexing.
251     assert(squares[0] == 1);
252     assert(squares[1] == 4);
253     assert(squares[2] == 9);
254     assert(squares[3] == 16);
255
256     // Test slicing.
257     auto squareSlice = squares[1..squares.length - 1];
258     assert(equal(squareSlice, [4, 9][]));
259     assert(squareSlice.back == 9);
260     assert(squareSlice[1] == 9);
261
262     // Test on a forward range to make sure it compiles when all the fancy
263     // stuff is disabled.
264     auto fibsSquares = map!"a * a"(recurrence!("a[n-1] + a[n-2]")(1, 1));
265     assert(fibsSquares.front == 1);
266     fibsSquares.popFront;
267     fibsSquares.popFront;
268     assert(fibsSquares.front == 4);
269     fibsSquares.popFront;
270     assert(fibsSquares.front == 9);
271
272     auto repeatMap = map!"a"(repeat(1));
273     static assert(isInfinite!(typeof(repeatMap)));
274    
275     auto intRange = map!"a"([1,2,3]);
276     static assert(isRandomAccessRange!(typeof(intRange)));
277    
278     foreach(DummyType; AllDummyRanges)
279     {
280         DummyType d;
281         auto m = map!"a * a"(d);
282
283         static assert(propagatesRangeType!(typeof(m), DummyType));
284         assert(equal(m, [1,4,9,16,25,36,49,64,81,100]));
285     }
286 }
287
288 // reduce
289 /**
290 Implements the homonym function (also known as $(D accumulate), $(D
291 compress), $(D inject), or $(D foldl)) present in various programming
292 languages of functional flavor. The call $(D reduce!(fun)(seed,
293 range)) first assigns $(D seed) to an internal variable $(D result),
294 also called the accumulator. Then, for each element $(D x) in $(D
295 range), $(D result = fun(result, x)) gets evaluated. Finally, $(D
296 result) is returned. The one-argument version $(D reduce!(fun)(range))
297 works similarly, but it uses the first element of the range as the
298 seed (the range must be non-empty).
299
300 Many aggregate range operations turn out to be solved with $(D reduce)
301 quickly and easily. The example below illustrates $(D reduce)'s
302 remarkable power and flexibility.
303
304 Example:
305 ----
306 int[] arr = [ 1, 2, 3, 4, 5 ];
307 // Sum all elements
308 auto sum = reduce!("a + b")(0, arr);
309 assert(sum == 15);
310
311 // Compute the maximum of all elements
312 auto largest = reduce!(max)(arr);
313 assert(largest == 5);
314
315 // Compute the number of odd elements
316 auto odds = reduce!("a + (b & 1)")(0, arr);
317 assert(odds == 3);
318
319 // Compute the sum of squares
320 auto ssquares = reduce!("a + b * b")(0, arr);
321 assert(ssquares == 55);
322
323 // Chain multiple ranges into seed
324 int[] a = [ 3, 4 ];
325 int[] b = [ 100 ];
326 auto r = reduce!("a + b")(chain(a, b));
327 assert(r == 107);
328
329 // Mixing convertible types is fair game, too
330 double[] c = [ 2.5, 3.0 ];
331 auto r1 = reduce!("a + b")(chain(a, b, c));
332 assert(r1 == 112.5);
333 ----
334
335 $(DDOC_SECTION_H Multiple functions:) Sometimes it is very useful to
336 compute multiple aggregates in one pass. One advantage is that the
337 computation is faster because the looping overhead is shared. That's
338 why $(D reduce) accepts multiple functions. If two or more functions
339 are passed, $(D reduce) returns a $(XREF typecons, Tuple) object with
340 one member per passed-in function. The number of seeds must be
341 correspondingly increased.
342
343 Example:
344 ----
345 double[] a = [ 3.0, 4, 7, 11, 3, 2, 5 ];
346 // Compute minimum and maximum in one pass
347 auto r = reduce!(min, max)(a);
348 // The type of r is Tuple!(double, double)
349 assert(r[0] == 2);  // minimum
350 assert(r[1] == 11); // maximum
351
352 // Compute sum and sum of squares in one pass
353 r = reduce!("a + b", "a + b * b")(tuple(0.0, 0.0), a);
354 assert(r[0] == 35);  // sum
355 assert(r[1] == 233); // sum of squares
356 // Compute average and standard deviation from the above
357 auto avg = r[0] / a.length;
358 auto stdev = sqrt(r[1] / a.length - avg * avg);
359 ----
360  */
361
362 template reduce(fun...)
363 {
364     auto reduce(Args...)(Args args)
365     if (Args.length > 0 && Args.length <= 2 && isIterable!(Args[$ - 1]))
366     {
367         static if(isInputRange!(Args[$ - 1]))
368         {
369             static if (Args.length == 2)
370             {
371                 alias args[0] seed;
372                 alias args[1] r;
373                 Unqual!(Args[0]) result = seed;
374                 for (; !r.empty; r.popFront)
375                 {
376                     static if (fun.length == 1)
377                     {
378                         result = binaryFun!(fun[0])(result, r.front);
379                     }
380                     else
381                     {
382                         foreach (i, Unused; Args[0].Types)
383                         {
384                             result[i] = binaryFun!(fun[i])(result[i], r.front);
385                         }
386                     }
387                 }
388                 return result;
389             }
390             else
391             {
392                 enforce(!args[$ - 1].empty,
393                     "Cannot reduce an empty range w/o an explicit seed value.");
394                 alias args[0] r;
395                 static if (fun.length == 1)
396                 {
397                     return reduce(r.front, (r.popFront(), r));
398                 }
399                 else
400                 {
401                     static assert(fun.length > 1);
402                     typeof(adjoin!(staticMap!(binaryFun, fun))(r.front, r.front))
403                         result = void;
404                     foreach (i, T; result.Types)
405                     {
406                         auto p = (cast(void*) &result[i])[0 .. result[i].sizeof];
407                         emplace!T(p, r.front);
408                     }
409                     r.popFront();
410                     return reduce(result, r);
411                 }
412             }
413         }
414         else
415         {   // opApply case.  Coded as a separate case because efficiently
416             // handling all of the small details like avoiding unnecessary
417             // copying, iterating by dchar over strings, and dealing with the
418             // no explicit start value case would become an unreadable mess
419             // if these were merged.
420             alias args[$ - 1] r;
421             alias Args[$ - 1] R;
422             alias ForeachType!R E;
423
424             static if(args.length == 2)
425             {
426                 static if(fun.length == 1)
427                 {
428                     auto result = Tuple!(Unqual!(Args[0]))(args[0]);
429                 }
430                 else
431                 {
432                     Unqual!(Args[0]) result = args[0];
433                 }
434
435                 enum bool initialized = true;
436             }
437             else static if(fun.length == 1)
438             {
439                 Tuple!(typeof(binaryFun!fun(E.init, E.init))) result = void;
440                 bool initialized = false;
441             }
442             else
443             {
444                 typeof(adjoin!(staticMap!(binaryFun, fun))(E.init, E.init))
445                     result = void;
446                 bool initialized = false;
447             }
448
449             // For now, just iterate using ref to avoid unnecessary copying.
450             // When Bug 2443 is fixed, this may need to change.
451             foreach(ref elem; r)
452             {
453                 if(initialized)
454                 {
455                     foreach(i, T; result.Types)
456                     {
457                         result[i] = binaryFun!(fun[i])(result[i], elem);
458                     }
459                 }
460                 else
461                 {
462                     static if(is(typeof(&initialized)))
463                     {
464                         initialized = true;
465                     }
466
467                     foreach (i, T; result.Types)
468                     {
469                         auto p = (cast(void*) &result[i])
470                             [0 .. result[i].sizeof];
471                         emplace!T(p, elem);
472                     }
473                 }
474             }
475
476             enforce(initialized,
477                 "Cannot reduce an empty iterable w/o an explicit seed value.");
478
479             static if(fun.length == 1)
480             {
481                 return result[0];
482             }
483             else
484             {
485                 return result;
486             }
487         }
488     }
489 }
490
491 unittest
492 {
493     debug(std_algorithm) scope(success)
494         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
495     double[] a = [ 3, 4 ];
496     auto r = reduce!("a + b")(0.0, a);
497     assert(r == 7);
498     r = reduce!("a + b")(a);
499     assert(r == 7);
500     r = reduce!(min)(a);
501     assert(r == 3);
502     double[] b = [ 100 ];
503     auto r1 = reduce!("a + b")(chain(a, b));
504     assert(r1 == 107);
505
506     // two funs
507     auto r2 = reduce!("a + b", "a - b")(tuple(0., 0.), a);
508     assert(r2[0] == 7 && r2[1] == -7);
509     auto r3 = reduce!("a + b", "a - b")(a);
510     assert(r3[0] == 7 && r3[1] == -1);
511
512     a = [ 1, 2, 3, 4, 5 ];
513     // Stringize with commas
514     string rep = reduce!("a ~ `, ` ~ to!(string)(b)")("", a);
515     assert(rep[2 .. $] == "1, 2, 3, 4, 5", "["~rep[2 .. $]~"]");
516
517     // Test the opApply case.
518     struct OpApply
519     {
520         bool actEmpty;
521
522         int opApply(int delegate(ref int) dg)
523         {
524             int res;
525             if(actEmpty) return res;
526
527             foreach(i; 0..100)
528             {
529                 res = dg(i);
530                 if(res) break;
531             }
532             return res;
533         }
534     }
535
536     OpApply oa;
537     auto hundredSum = reduce!"a + b"(iota(100));
538     assert(reduce!"a + b"(5, oa) == hundredSum + 5);
539     assert(reduce!"a + b"(oa) == hundredSum);
540     assert(reduce!("a + b", max)(oa) == tuple(hundredSum, 99));
541     assert(reduce!("a + b", max)(tuple(5, 0), oa) == tuple(hundredSum + 5, 99));
542
543     // Test for throwing on empty range plus no seed.
544     try {
545         reduce!"a + b"([1, 2][0..0]);
546         assert(0);
547     } catch(Exception) {}
548
549     oa.actEmpty = true;
550     try {
551         reduce!"a + b"(oa);
552         assert(0);
553     } catch(Exception) {}
554 }
555
556 unittest
557 {
558     debug(std_algorithm) scope(success)
559         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
560     const float a = 0.0;
561     const float[] b = [ 1.2, 3, 3.3 ];
562     float[] c = [ 1.2, 3, 3.3 ];
563     auto r = reduce!"a + b"(a, b);
564     r = reduce!"a + b"(a, c);
565 }
566
567 /**
568 Fills a range with a value.
569
570 Example:
571 ----
572 int[] a = [ 1, 2, 3, 4 ];
573 fill(a, 5);
574 assert(a == [ 5, 5, 5, 5 ]);
575 ----
576  */
577 void fill(Range, Value)(Range range, Value filler)
578 if (isForwardRange!Range && is(typeof(range.front = filler)))
579 {
580     alias ElementType!Range T;
581     static if (hasElaborateCopyConstructor!T || !isDynamicArray!Range)
582     {
583         for (; !range.empty; range.popFront)
584         {
585             range.front = filler;
586         }
587     }
588     else
589     {
590         if (range.empty) return;
591         // Range is a dynamic array of bald values, just fill memory
592         // Can't use memcpy or memmove coz ranges overlap
593         range.front = filler;
594         auto bytesToFill = T.sizeof * (range.length - 1);
595         auto bytesFilled = T.sizeof;
596         while (bytesToFill)
597         {
598             auto fillNow = min(bytesToFill, bytesFilled);
599             memcpy(cast(void*) range.ptr + bytesFilled,
600                     cast(void*) range.ptr,
601                   fillNow);
602             bytesToFill -= fillNow;
603             bytesFilled += fillNow;
604         }
605     }
606 }
607
608 unittest
609 {
610     debug(std_algorithm) scope(success)
611         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
612     int[] a = [ 1, 2, 3 ];
613     fill(a, 6);
614     assert(a == [ 6, 6, 6 ], text(a));
615     void fun0()
616     {
617         foreach (i; 0 .. 1000)
618         {
619             foreach (ref e; a) e = 6;
620         }
621     }
622     void fun1() { foreach (i; 0 .. 1000) fill(a, 6); }
623     //void fun2() { foreach (i; 0 .. 1000) fill2(a, 6); }
624     //writeln(benchmark!(fun0, fun1, fun2)(10000));
625 }
626
627 /**
628 Fills $(D range) with a pattern copied from $(D filler). The length of
629 $(D range) does not have to be a multiple of the length of $(D
630 filler). If $(D filler) is empty, an exception is thrown.
631
632 Example:
633 ----
634 int[] a = [ 1, 2, 3, 4, 5 ];
635 int[] b = [ 8, 9 ];
636 fill(a, b);
637 assert(a == [ 8, 9, 8, 9, 8 ]);
638 ----
639  */
640
641 void fill(Range1, Range2)(Range1 range, Range2 filler)
642 if (isForwardRange!Range1 && isForwardRange!Range2
643         && is(typeof(Range1.init.front = Range2.init.front)))
644 {
645     enforce(!filler.empty);
646     auto t = filler.save;
647     for (; !range.empty; range.popFront, t.popFront)
648     {
649         if (t.empty) t = filler;
650         range.front = t.front;
651     }
652 }
653
654 unittest
655 {
656     debug(std_algorithm) scope(success)
657         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
658     int[] a = [ 1, 2, 3, 4, 5 ];
659     int[] b = [1, 2];
660     fill(a, b);
661     assert(a == [ 1, 2, 1, 2, 1 ]);
662 }
663
664 /**
665 Fills a range with a value. Assumes that the range does not currently
666 contain meaningful content. This is of interest for structs that
667 define copy constructors (for all other types, fill and
668 uninitializedFill are equivalent).
669
670 Example:
671 ----
672 struct S { ... }
673 S[] s = (cast(S*) malloc(5 * S.sizeof))[0 .. 5];
674 uninitializedFill(s, 42);
675 assert(s == [ 42, 42, 42, 42, 42 ]);
676 ----
677  */
678 void uninitializedFill(Range, Value)(Range range, Value filler)
679 if (isForwardRange!Range && is(typeof(range.front = filler)))
680 {
681     alias ElementType!Range T;
682     static if (hasElaborateCopyConstructor!T)
683     {
684         // Must construct stuff by the book
685         for (; !range.empty; range.popFront)
686         {
687             emplace!T((cast(void*) &range.front)[0 .. T.sizeof], filler);
688         }
689     }
690     else
691     {
692         // Doesn't matter whether fill is initialized or not
693         return fill(range, filler);
694     }
695 }
696
697 unittest
698 {
699     debug(std_algorithm) scope(success)
700         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
701     int[] a = [ 1, 2, 3 ];
702     uninitializedFill(a, 6);
703     assert(a == [ 6, 6, 6 ]);
704     void fun0()
705     {
706         foreach (i; 0 .. 1000)
707         {
708             foreach (ref e; a) e = 6;
709         }
710     }
711     void fun1() { foreach (i; 0 .. 1000) fill(a, 6); }
712     //void fun2() { foreach (i; 0 .. 1000) fill2(a, 6); }
713     //writeln(benchmark!(fun0, fun1, fun2)(10000));
714 }
715
716 /**
717 Initializes all elements of a range with their $(D .init)
718 value. Assumes that the range does not currently contain meaningful
719 content.
720
721 Example:
722 ----
723 struct S { ... }
724 S[] s = (cast(S*) malloc(5 * S.sizeof))[0 .. 5];
725 initialize(s);
726 assert(s == [ 0, 0, 0, 0, 0 ]);
727 ----
728  */
729 void initializeAll(Range)(Range range)
730 if (isForwardRange!Range && is(typeof(range.front = range.front)))
731 {
732     alias ElementType!Range T;
733     static assert(is(typeof(&(range.front()))) || !hasElaborateAssign!T,
734             "Cannot initialize a range that does not expose"
735             " references to its elements");
736     static if (!isDynamicArray!Range)
737     {
738         static if (is(typeof(&(range.front()))))
739         {
740             // Range exposes references
741             for (; !range.empty; range.popFront)
742             {
743                 memcpy(&(range.front()), &T.init, T.sizeof);
744             }
745         }
746         else
747         {
748             // Go the slow route
749             for (; !range.empty; range.popFront)
750             {
751                 range.front = filler;
752             }
753         }
754     }
755     else
756     {
757         fill(range, T.init);
758     }
759 }
760
761 unittest
762 {
763     debug(std_algorithm) scope(success)
764         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
765     int[] a = [ 1, 2, 3 ];
766     uninitializedFill(a, 6);
767     assert(a == [ 6, 6, 6 ]);
768     initializeAll(a);
769     assert(a == [ 0, 0, 0 ]);
770     void fun0()
771     {
772         foreach (i; 0 .. 1000)
773         {
774             foreach (ref e; a) e = 6;
775         }
776     }
777     void fun1() { foreach (i; 0 .. 1000) fill(a, 6); }
778     //void fun2() { foreach (i; 0 .. 1000) fill2(a, 6); }
779     //writeln(benchmark!(fun0, fun1, fun2)(10000));
780 }
781
782 // filter
783 /**
784 Implements the homonym function present in various programming
785 languages of functional flavor. The call $(D filter!(fun)(range))
786 returns a new range only containing elements $(D x) in $(D r) for
787 which $(D predicate(x)) is $(D true).
788
789 Example:
790 ----
791 int[] arr = [ 1, 2, 3, 4, 5 ];
792 // Sum all elements
793 auto small = filter!("a < 3")(arr);
794 assert(small == [ 1, 2 ]);
795 // In combination with chain() to span multiple ranges
796 int[] a = [ 3, -2, 400 ];
797 int[] b = [ 100, -101, 102 ];
798 auto r = filter!("a > 0")(chain(a, b));
799 assert(equal(r, [ 3, 400, 100, 102 ]));
800 // Mixing convertible types is fair game, too
801 double[] c = [ 2.5, 3.0 ];
802 auto r1 = filter!("cast(int) a != a")(chain(c, a, b));
803 assert(r1 == [ 2.5 ]);
804 ----
805  */
806 template filter(alias pred)
807 {
808     auto filter(Range)(Range rs)
809     {
810         return Filter!(unaryFun!(pred), Range)(rs);
811     }
812 }
813
814 struct Filter(alias pred, Range) if (isInputRange!(Unqual!Range))
815 {
816     alias Unqual!Range R;
817     R _input;
818
819     this(R r)
820     {
821         _input = r;
822         while (!_input.empty && !pred(_input.front)) _input.popFront;
823     }
824
825     ref Filter opSlice()
826     {
827         return this;
828     }
829
830     static if (isInfinite!Range)
831     {
832         enum bool empty = false;
833     }
834     else
835     {
836         @property bool empty() { return _input.empty; }
837     }
838
839     void popFront()
840     {
841         do
842         {
843             _input.popFront;
844         } while (!_input.empty && !pred(_input.front));
845     }
846
847     @property auto ref front()
848     {
849         return _input.front;
850     }
851
852     static if(isForwardRange!R)
853     {
854         @property typeof(this) save()
855         {
856             return typeof(this)(_input);
857         }
858     }
859 }
860
861 unittest
862 {
863     debug(std_algorithm) scope(success)
864         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
865     int[] a = [ 3, 4, 2 ];
866     auto r = filter!("a > 3")(a);
867     static assert(isForwardRange!(typeof(r)));
868     assert(equal(r, [ 4 ][]));
869
870     a = [ 1, 22, 3, 42, 5 ];
871     auto under10 = filter!("a < 10")(a);
872     assert(equal(under10, [1, 3, 5][]));
873     static assert(isForwardRange!(typeof(under10)));
874     under10.front() = 4;
875     assert(equal(under10, [4, 3, 5][]));
876     under10.front() = 40;
877     assert(equal(under10, [40, 3, 5][]));
878     under10.front() = 1;
879
880     auto infinite = filter!"a > 2"(repeat(3));
881     static assert(isInfinite!(typeof(infinite)));
882     static assert(isForwardRange!(typeof(infinite)));
883    
884     foreach(DummyType; AllDummyRanges) {
885         DummyType d;
886         auto f = filter!"a & 1"(d);
887         assert(equal(f, [1,3,5,7,9]));
888        
889         static if (isForwardRange!DummyType) {
890             static assert(isForwardRange!(typeof(f)));
891         }
892     }
893    
894     // With delegates
895     int x = 10;
896     int overX(int a) { return a > x; }
897     typeof(filter!overX(a)) getFilter()
898     {
899         return filter!overX(a);
900     }
901     auto r1 = getFilter();
902     assert(equal(r1, [22, 42]));
903    
904     // With chain
905     auto nums = [0,1,2,3,4];
906     assert(equal(filter!overX(chain(a, nums)), [22, 42]));
907    
908     // With copying of inner struct Filter to Map
909     auto arr = [1,2,3,4,5];
910     auto m = map!"a + 1"(filter!"a < 4"(arr));
911 }
912
913 unittest
914 {
915     int[] a = [ 3, 4 ];
916     const aConst = a;
917     auto r = filter!("a > 3")(aConst);
918     assert(equal(r, [ 4 ][]));
919
920     a = [ 1, 22, 3, 42, 5 ];
921     auto under10 = filter!("a < 10")(a);
922     assert(equal(under10, [1, 3, 5][]));
923     assert(under10.save == under10);
924
925     // With copying of inner struct Filter to Map
926     auto arr = [1,2,3,4,5];
927     auto m = map!"a + 1"(filter!"a < 4"(arr));
928 }
929
930 unittest
931 {
932     assert(equal(compose!(map!"2 * a", filter!"a & 1")([1,2,3,4,5]),
933                     [2,6,10]));
934     assert(equal(pipe!(filter!"a & 1", map!"2 * a")([1,2,3,4,5]),
935             [2,6,10]));
936 }
937
938 unittest
939 {
940     int x = 10;
941     int underX(int a) { return a < x; }
942     const(int)[] list = [ 1, 2, 10, 11, 3, 4 ];
943     assert(equal(filter!underX(list), [ 1, 2, 3, 4 ]));
944 }
945
946 // filterBidirectional
947 /**
948  * Similar to $(D filter), except it defines a bidirectional
949  * range. There is a speed disadvantage - the constructor spends time
950  * finding the last element in the range that satisfies the filtering
951  * condition (in addition to finding the first one). The advantage is
952  * that the filtered range can be spanned from both directions. Also,
953  * $(XREF range, retro) can be applied against the filtered range.
954  *
955 Example:
956 ----
957 int[] arr = [ 1, 2, 3, 4, 5 ];
958 auto small = filterBidirectional!("a < 3")(arr);
959 assert(small.back == 2);
960 assert(equal(small, [ 1, 2 ]));
961 assert(equal(retro(small), [ 2, 1 ]));
962 // In combination with chain() to span multiple ranges
963 int[] a = [ 3, -2, 400 ];
964 int[] b = [ 100, -101, 102 ];
965 auto r = filterBidirectional!("a > 0")(chain(a, b));
966 assert(r.back == 102);
967 ----
968  */
969 template filterBidirectional(alias pred)
970 {
971     FilterBidirectional!(unaryFun!(pred), Range)
972     filterBidirectional(Range)(Range rs)
973     {
974         return typeof(return)(rs);
975     }
976 }
977
978 struct FilterBidirectional(alias pred, Range) if (isBidirectionalRange!(Unqual!Range))
979 {
980     alias Unqual!Range R;
981     R _input;
982
983     this(R r)
984     {
985         _input = r;
986         while (!_input.empty && !pred(_input.front)) _input.popFront();
987         while (!_input.empty && !pred(_input.back)) _input.popBack();
988     }
989
990     @property bool empty() { return _input.empty; }
991
992     void popFront()
993     {
994         do
995         {
996             _input.popFront;
997         } while (!_input.empty && !pred(_input.front));
998     }
999
1000     @property auto ref front()
1001     {
1002         return _input.front;
1003     }
1004
1005     void popBack()
1006     {
1007         do
1008         {
1009             _input.popBack;
1010         } while (!_input.empty && !pred(_input.back));
1011     }
1012
1013     @property auto ref back()
1014     {
1015         return _input.back;
1016     }
1017
1018     @property typeof(this) save()
1019     {
1020         return typeof(this)(_input);
1021     }
1022 }
1023
1024 unittest
1025 {
1026     int[] arr = [ 1, 2, 3, 4, 5 ];
1027     auto small = filterBidirectional!("a < 3")(arr);
1028     static assert(isBidirectionalRange!(typeof(small)));
1029     assert(small.back == 2);
1030     assert(equal(small, [ 1, 2 ]));
1031     assert(equal(retro(small), [ 2, 1 ]));
1032     // In combination with chain() to span multiple ranges
1033     int[] a = [ 3, -2, 400 ];
1034     int[] b = [ 100, -101, 102 ];
1035     auto r = filterBidirectional!("a > 0")(chain(a, b));
1036     assert(r.back == 102);
1037 }
1038
1039 // move
1040 /**
1041 Moves $(D source) into $(D target) via a destructive
1042 copy. Specifically: $(UL $(LI If $(D hasAliasing!T) is true (see
1043 $(XREF traits, hasAliasing)), then the representation of $(D source)
1044 is bitwise copied into $(D target) and then $(D source = T.init) is
1045 evaluated.)  $(LI Otherwise, $(D target = source) is evaluated.)) See
1046 also $(XREF contracts, pointsTo).
1047
1048 Preconditions:
1049 $(D &source == &target || !pointsTo(source, source))
1050 */
1051 void move(T)(ref T source, ref T target)
1052 {
1053     if (&source == &target) return;
1054     assert(!pointsTo(source, source));
1055     static if (is(T == struct))
1056     {
1057         // Most complicated case. Destroy whatever target had in it
1058         // and bitblast source over it
1059         static if (is(typeof(target.__dtor()))) target.__dtor();
1060         memcpy(&target, &source, T.sizeof);
1061         // If the source defines a destructor or a postblit hook, we must obliterate the
1062         // object in order to avoid double freeing and undue aliasing
1063         static if (is(typeof(source.__dtor())) || is(typeof(source.__postblit())))
1064         {
1065             static T empty;
1066             memcpy(&source, &empty, T.sizeof);
1067         }
1068     }
1069     else
1070     {
1071         // Primitive data (including pointers and arrays) or class -
1072         // assignment works great
1073         target = source;
1074         // static if (is(typeof(source = null)))
1075         // {
1076         //     // Nullify the source to help the garbage collector
1077         //     source = null;
1078         // }
1079     }
1080 }
1081
1082 unittest
1083 {
1084     debug(std_algorithm) scope(success)
1085         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
1086     Object obj1 = new Object;
1087     Object obj2 = obj1;
1088     Object obj3;
1089     move(obj2, obj3);
1090     assert(obj3 is obj1);
1091
1092     struct S1 { int a = 1, b = 2; }
1093     S1 s11 = { 10, 11 };
1094     S1 s12;
1095     move(s11, s12);
1096     assert(s11.a == 10 && s11.b == 11 && s12.a == 10 && s12.b == 11);
1097
1098     struct S2 { int a = 1; int * b; }
1099     S2 s21 = { 10, new int };
1100     S2 s22;
1101     move(s21, s22);
1102     assert(s21 == s22);
1103 }
1104
1105 /// Ditto
1106 T move(T)(ref T src)
1107 {
1108     T result;
1109     move(src, result);
1110     return result;
1111 }
1112
1113 // moveAll
1114 /**
1115 For each element $(D a) in $(D src) and each element $(D b) in $(D
1116 tgt) in lockstep in increasing order, calls $(D move(a, b)). Returns
1117 the leftover portion of $(D tgt). Throws an exeption if there is not
1118 enough room in $(D tgt) to acommodate all of $(D src).
1119
1120 Preconditions:
1121 $(D walkLength(src) >= walkLength(tgt))
1122  */
1123 Range2 moveAll(Range1, Range2)(Range1 src, Range2 tgt)
1124 {
1125     for (; !src.empty; src.popFront, tgt.popFront)
1126     {
1127         enforce(!tgt.empty);
1128         move(src.front, tgt.front);
1129     }
1130     return tgt;
1131 }
1132
1133 unittest
1134 {
1135     debug(std_algorithm) scope(success)
1136         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
1137     int[] a = [ 1, 2, 3 ];
1138     int[] b = new int[5];
1139     assert(moveAll(a, b) is b[3 .. $]);
1140     assert(a == b[0 .. 3]);
1141     assert(a == [ 1, 2, 3 ]);
1142 }
1143
1144 // moveSome
1145 /**
1146 For each element $(D a) in $(D src) and each element $(D b) in $(D
1147 tgt) in lockstep in increasing order, calls $(D move(a, b)). Stops
1148 when either $(D src) or $(D tgt) have been exhausted. Returns the
1149 leftover portions of the two ranges.
1150  */
1151 Tuple!(Range1, Range2) moveSome(Range1, Range2)(Range1 src, Range2 tgt)
1152 {
1153     for (; !src.empty && !tgt.empty; src.popFront, tgt.popFront)
1154     {
1155         enforce(!tgt.empty);
1156         move(src.front, tgt.front);
1157     }
1158     return tuple(src, tgt);
1159 }
1160
1161 unittest
1162 {
1163     debug(std_algorithm) scope(success)
1164         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
1165     int[] a = [ 1, 2, 3, 4, 5 ];
1166     int[] b = new int[3];
1167     assert(moveSome(a, b)[0] is a[3 .. $]);
1168     assert(a[0 .. 3] == b);
1169     assert(a == [ 1, 2, 3, 4, 5 ]);
1170 }
1171
1172 // swap
1173 /**
1174 Swaps $(D lhs) and $(D rhs). See also $(XREF exception, pointsTo).
1175
1176 Preconditions:
1177
1178 $(D !pointsTo(lhs, lhs) && !pointsTo(lhs, rhs) && !pointsTo(rhs, lhs)
1179 && !pointsTo(rhs, rhs))
1180  */
1181 void swap(T)(ref T lhs, ref T rhs) @trusted pure nothrow
1182 if (isMutable!T && !is(typeof(T.init.proxySwap(T.init))))
1183 {
1184     static if (hasElaborateAssign!T)
1185     {
1186         // For structs with non-trivial assignment, move memory directly
1187         // First check for undue aliasing
1188         assert(!pointsTo(lhs, rhs) && !pointsTo(rhs, lhs)
1189             && !pointsTo(lhs, lhs) && !pointsTo(rhs, rhs));
1190         // Swap bits
1191         ubyte[T.sizeof] t = void;
1192         auto a = (cast(ubyte*) &lhs)[0 .. T.sizeof];
1193         auto b = (cast(ubyte*) &rhs)[0 .. T.sizeof];
1194         t[] = a[];
1195         a[] = b[];
1196         b[] = t[];
1197     }
1198     else
1199     {
1200         // Temporary fix Bug 4789.  Wor around the fact that assigning a static
1201         // array to itself doesn't work properly.
1202         static if(isStaticArray!T) {
1203             if(lhs.ptr is rhs.ptr) {
1204                 return;
1205             }
1206         }
1207
1208         // For non-struct types, suffice to do the classic swap
1209         auto tmp = lhs;
1210         lhs = rhs;
1211         rhs = tmp;
1212     }
1213 }
1214
1215 // Not yet documented
1216 void swap(T)(T lhs, T rhs) if (is(typeof(T.init.proxySwap(T.init))))
1217 {
1218     lhs.proxySwap(rhs);
1219 }
1220
1221 unittest
1222 {
1223     debug(std_algorithm) scope(success)
1224         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
1225     int a = 42, b = 34;
1226     swap(a, b);
1227     assert(a == 34 && b == 42);
1228
1229     struct S { int x; char c; int[] y; }
1230     S s1 = { 0, 'z', [ 1, 2 ] };
1231     S s2 = { 42, 'a', [ 4, 6 ] };
1232     //writeln(s2.tupleof.stringof);
1233     swap(s1, s2);
1234     assert(s1.x == 42);
1235     assert(s1.c == 'a');
1236     assert(s1.y == [ 4, 6 ]);
1237
1238     assert(s2.x == 0);
1239     assert(s2.c == 'z');
1240     assert(s2.y == [ 1, 2 ]);
1241
1242     immutable int imm1, imm2;
1243     static assert(!__traits(compiles, swap(imm1, imm2)));
1244 }
1245
1246 unittest
1247 {
1248     struct NoCopy
1249     {
1250         this(this) { assert(0); }
1251         int n;
1252         string s;
1253     }
1254     NoCopy nc1, nc2;
1255     nc1.n = 127; nc1.s = "abc";
1256     nc2.n = 513; nc2.s = "uvwxyz";
1257     swap(nc1, nc2);
1258     assert(nc1.n == 513 && nc1.s == "uvwxyz");
1259     assert(nc2.n == 127 && nc2.s == "abc");
1260
1261     struct NoCopyHolder
1262     {
1263         NoCopy noCopy;
1264     }
1265     NoCopyHolder h1, h2;
1266     h1.noCopy.n = 31; h1.noCopy.s = "abc";
1267     h2.noCopy.n = 65; h2.noCopy.s = null;
1268     swap(h1, h2);
1269     assert(h1.noCopy.n == 65 && h1.noCopy.s == null);
1270     assert(h2.noCopy.n == 31 && h2.noCopy.s == "abc");
1271
1272     const NoCopy const1, const2;
1273     static assert(!__traits(compiles, swap(const1, const2)));
1274 }
1275
1276 void swapFront(R1, R2)(R1 r1, R2 r2)
1277     if (isInputRange!R1 && isInputRange!R2)
1278 {
1279     static if (is(typeof(swap(r1.front, r2.front))))
1280     {
1281         swap(r1.front, r2.front);
1282     }
1283     else
1284     {
1285         auto t1 = moveFront(r1), t2 = moveFront(r2);
1286         r1.front = move(t2);
1287         r2.front = move(t1);
1288     }
1289 }
1290
1291 // splitter
1292 /**
1293 Splits a range using an element as a separator. This can be used with
1294 any range type, but is most popular with string types.
1295
1296 Two adjacent separators are considered to surround an empty element in
1297 the split range.
1298
1299 If the empty range is given, the result is a range with one empty
1300 element. If a range with one separator is given, the result is a range
1301 with two empty elements.
1302
1303 Example:
1304 ---
1305 assert(equal(splitter("hello  world", ' '), [ "hello", "", "world" ]));
1306 int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
1307 int[][] w = [ [1, 2], [], [3], [4, 5] ];
1308 assert(equal(splitter(a, 0), w));
1309 a = null;
1310 assert(equal(splitter(a, 0), [ (int[]).init ]));
1311 a = [ 0 ];
1312 assert(equal(splitter(a, 0), [ (int[]).init, (int[]).init ]));
1313 a = [ 0, 1 ];
1314 assert(equal(splitter(a, 0), [ [], [1] ]));
1315 ----
1316 */
1317 struct Splitter(Range, Separator)
1318     if (is(typeof(ElementType!Range.init == Separator.init)) && hasSlicing!Range)
1319 {
1320 private:
1321     Range _input;
1322     Separator _separator;
1323     enum size_t _unComputed = size_t.max - 1, _atEnd = size_t.max;
1324     size_t _frontLength = _unComputed;
1325     size_t _backLength = _unComputed;
1326
1327     static if(isBidirectionalRange!Range)
1328     {
1329         static sizediff_t lastIndexOf(Range haystack, Separator needle)
1330         {
1331             immutable index = countUntil(retro(haystack), needle);
1332             return (index == -1) ? -1 : haystack.length - 1 - index;
1333         }
1334     }
1335
1336 public:
1337     this(Range input, Separator separator)
1338     {
1339         _input = input;
1340         _separator = separator;
1341         // computeFront();
1342         // computeBack();
1343     }
1344
1345     static if (isInfinite!Range)
1346     {
1347         enum bool empty = false;
1348     }
1349     else
1350     {
1351         @property bool empty()
1352         {
1353             return _frontLength == _atEnd;
1354         }
1355     }
1356
1357     @property Range front()
1358     {
1359         assert(!empty);
1360         if (_frontLength == _unComputed)
1361         {
1362             _frontLength = countUntil(_input, _separator);
1363             if (_frontLength == -1) _frontLength = _input.length;
1364         }
1365         return _input[0 .. _frontLength];
1366     }
1367
1368     void popFront()
1369     {
1370         assert(!empty);
1371         if (_frontLength == _unComputed)
1372         {
1373             front;
1374         }
1375         assert(_frontLength <= _input.length);
1376         if (_frontLength == _input.length)
1377         {
1378             // no more input and need to fetch => done
1379             _frontLength = _atEnd;
1380
1381             // Probably don't need this, but just for consistency:
1382             _backLength = _atEnd;
1383         }
1384         else
1385         {
1386             _input = _input[_frontLength .. _input.length];
1387             skipOver(_input, _separator) || assert(false);
1388             _frontLength = _unComputed;
1389         }
1390     }
1391
1392     static if(isForwardRange!Range)
1393     {
1394         @property typeof(this) save()
1395         {
1396             auto ret = this;
1397             ret._input = _input.save;
1398             return ret;
1399         }
1400     }
1401
1402     static if(isBidirectionalRange!Range)
1403     {
1404         @property Range back()
1405         {
1406             assert(!empty);
1407             if (_backLength == _unComputed)
1408             {
1409                 immutable lastIndex = lastIndexOf(_input, _separator);
1410                 if(lastIndex == -1)
1411                 {
1412                     _backLength = _input.length;
1413                 }
1414                 else
1415                 {
1416                     _backLength = _input.length - lastIndex - 1;
1417                 }
1418             }
1419             return _input[_input.length - _backLength .. _input.length];
1420         }
1421
1422         void popBack()
1423         {
1424             assert(!empty);
1425             if (_backLength == _unComputed)
1426             {
1427                 back;
1428             }
1429             assert(_backLength <= _input.length);
1430             if (_backLength == _input.length)
1431             {
1432                 // no more input and need to fetch => done
1433                 _frontLength = _atEnd;
1434                 _backLength = _atEnd;
1435             }
1436             else
1437             {
1438                 _input = _input[0 .. _input.length - _backLength];
1439                 if(!_input.empty && _input.back == _separator)
1440                 {
1441                     _input.popBack();
1442                 }
1443                 else
1444                 {
1445                     assert(false);
1446                 }
1447                 _backLength = _unComputed;
1448             }
1449         }
1450     }
1451 }
1452
1453 /// Ditto
1454 Splitter!(Range, Separator)
1455 splitter(Range, Separator)(Range r, Separator s)
1456 if (is(typeof(ElementType!Range.init == ElementType!Separator.init))
1457        ||
1458     is(typeof(ElementType!Range.init == Separator.init))
1459     )
1460 {
1461     return typeof(return)(r, s);
1462 }
1463
1464 unittest
1465 {
1466     debug(std_algorithm) scope(success)
1467         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
1468     assert(equal(splitter("hello  world", ' '), [ "hello", "", "world" ]));
1469     int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
1470     int[][] w = [ [1, 2], [], [3], [4, 5], [] ];
1471     static assert(isForwardRange!(typeof(splitter(a, 0))));
1472
1473     // foreach (x; splitter(a, 0)) {
1474     //     writeln("[", x, "]");
1475     // }
1476     assert(equal(splitter(a, 0), w));
1477     a = null;
1478     assert(equal(splitter(a, 0), [ (int[]).init ][]));
1479     a = [ 0 ];
1480     assert(equal(splitter(a, 0), [ (int[]).init, (int[]).init ][]));
1481     a = [ 0, 1 ];
1482     assert(equal(splitter(a, 0), [ [], [1] ][]));
1483
1484     // Thoroughly exercise the bidirectional stuff.
1485     auto str = "abc abcd abcde ab abcdefg abcdefghij ab ac ar an at ada";
1486     assert(equal(
1487         retro(splitter(str, 'a')),
1488         retro(array(splitter(str, 'a')))
1489     ));
1490
1491     // Test interleaving front and back.
1492     auto split = splitter(str, 'a');
1493     assert(split.front == "");
1494     assert(split.back == "");
1495     split.popBack();
1496     assert(split.back == "d");
1497     split.popFront();
1498     assert(split.front == "bc ");
1499     assert(split.back == "d");
1500     split.popFront();
1501     split.popBack();
1502     assert(split.back == "t ");
1503     split.popBack();
1504     split.popBack();
1505     split.popFront();
1506     split.popFront();
1507     assert(split.front == "b ");
1508     assert(split.back == "r ");
1509
1510     foreach(DummyType; AllDummyRanges) {  // Bug 4408
1511         static if(isRandomAccessRange!DummyType) {
1512             static assert(isBidirectionalRange!DummyType);
1513             DummyType d;
1514             auto s = splitter(d, 5);
1515             assert(equal(s.front, [1,2,3,4]));
1516             assert(equal(s.back, [6,7,8,9,10]));
1517
1518
1519             auto s2 = splitter(d, [4, 5]);
1520             assert(equal(s2.front, [1,2,3]));
1521             assert(equal(s2.back, [6,7,8,9,10]));
1522         }
1523     }
1524 }
1525
1526 /**
1527 Splits a range using another range as a separator. This can be used
1528 with any range type, but is most popular with string types.
1529  */
1530 struct Splitter(Range, Separator)
1531 if (is(typeof(Range.init.front == Separator.init.front) : bool))
1532 {
1533 private:
1534     Range _input;
1535     Separator _separator;
1536     // _frontLength == size_t.max means empty
1537     size_t _frontLength = size_t.max;
1538     static if (isBidirectionalRange!Range)
1539         size_t _backLength = size_t.max;
1540
1541     size_t separatorLength() { return _separator.length; }
1542
1543     void ensureFrontLength()
1544     {
1545         if (_frontLength != _frontLength.max) return;
1546         assert(!_input.empty);
1547         // compute front length
1548         _frontLength = _input.length - find(_input, _separator).length;
1549         static if (isBidirectionalRange!Range)
1550             if (_frontLength == _input.length) _backLength = _frontLength;
1551     }
1552
1553     void ensureBackLength()
1554     {
1555         static if (isBidirectionalRange!Range)
1556             if (_backLength != _backLength.max) return;
1557         assert(!_input.empty);
1558         // compute back length
1559         static if (isBidirectionalRange!Range)
1560         {
1561             _backLength = _input.length -
1562                 find(retro(_input), retro(_separator)).length;
1563         }
1564     }
1565
1566 public:
1567     this(Range input, Separator separator)
1568     {
1569         _input = input;
1570         _separator = separator;
1571     }
1572
1573     @property Range front()
1574     {
1575         assert(!empty);
1576         ensureFrontLength();
1577         return _input[0 .. _frontLength];
1578     }
1579
1580     static if (isInfinite!Range)
1581     {
1582         enum bool empty = false;  // Propagate infiniteness
1583     }
1584     else
1585     {
1586         @property bool empty()
1587         {
1588             return _frontLength == size_t.max && _input.empty;
1589         }
1590     }
1591
1592     void popFront()
1593     {
1594         assert(!empty);
1595         ensureFrontLength;
1596         if (_frontLength == _input.length)
1597         {
1598             // done, there's no separator in sight
1599             _input = _input[_frontLength .. _frontLength];
1600             _frontLength = _frontLength.max;
1601             static if (isBidirectionalRange!Range)
1602                 _backLength = _backLength.max;
1603             return;
1604         }
1605         if (_frontLength + separatorLength == _input.length)
1606         {
1607             // Special case: popping the first-to-last item; there is
1608             // an empty item right after this.
1609             _input = _input[_input.length .. _input.length];
1610             _frontLength = 0;
1611             static if (isBidirectionalRange!Range)
1612                 _backLength = 0;
1613             return;
1614         }
1615         // Normal case, pop one item and the separator, get ready for
1616         // reading the next item
1617         _input = _input[_frontLength + separatorLength .. _input.length];
1618         // mark _frontLength as uninitialized
1619         _frontLength = _frontLength.max;
1620     }
1621
1622     static if(isForwardRange!Range)
1623     {
1624         @property typeof(this) save()
1625         {
1626             auto ret = this;
1627             ret._input = _input.save;
1628             return ret;
1629         }
1630     }
1631
1632 // Bidirectional functionality as suggested by Brad Roberts.
1633     static if (isBidirectionalRange!Range)
1634     {
1635         @property Range back()
1636         {
1637             ensureBackLength;
1638             return _input[_input.length - _backLength .. _input.length];
1639         }
1640
1641         void popBack()
1642         {
1643             ensureBackLength;
1644             if (_backLength == _input.length)
1645             {
1646                 // done
1647                 _input = _input[0 .. 0];
1648                 _frontLength = _frontLength.max;
1649                 _backLength = _backLength.max;
1650                 return;
1651             }
1652             if (_backLength + separatorLength == _input.length)
1653             {
1654                 // Special case: popping the first-to-first item; there is
1655                 // an empty item right before this. Leave the separator in.
1656                 _input = _input[0 .. 0];
1657                 _frontLength = 0;
1658                 _backLength = 0;
1659                 return;
1660             }
1661             // Normal case
1662             _input = _input[0 .. _input.length - _backLength - separatorLength];
1663             _backLength = _backLength.max;
1664         }
1665     }
1666 }
1667
1668 unittest
1669 {
1670     debug(std_algorithm) scope(success)
1671         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
1672     auto s = ",abc, de, fg,hi,";
1673     auto sp0 = splitter(s, ',');
1674     // //foreach (e; sp0) writeln("[", e, "]");
1675     assert(equal(sp0, ["", "abc", " de", " fg", "hi", ""][]));
1676
1677     auto s1 = ", abc, de,  fg, hi, ";
1678     auto sp1 = splitter(s1, ", ");
1679     //foreach (e; sp1) writeln("[", e, "]");
1680     assert(equal(sp1, ["", "abc", "de", " fg", "hi", ""][]));
1681     static assert(isForwardRange!(typeof(sp1)));
1682
1683     int[] a = [ 1, 2, 0, 3, 0, 4, 5, 0 ];
1684     int[][] w = [ [1, 2], [3], [4, 5], [] ];
1685     uint i;
1686     foreach (e; splitter(a, 0))
1687     {
1688         assert(i < w.length);
1689         assert(e == w[i++]);
1690     }
1691     assert(i == w.length);
1692     // // Now go back
1693     // auto s2 = splitter(a, 0);
1694
1695     // foreach (e; retro(s2))
1696     // {
1697     //     assert(i > 0);
1698     //     assert(equal(e, w[--i]), text(e));
1699     // }
1700     // assert(i == 0);
1701
1702     wstring names = ",peter,paul,jerry,";
1703     auto words = split(names, ",");
1704     assert(walkLength(words) == 5, text(walkLength(words)));
1705 }
1706
1707 unittest
1708 {
1709     debug(std_algorithm) scope(success)
1710         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
1711     auto s6 = ",";
1712     auto sp6 = splitter(s6, ',');
1713     foreach (e; sp6)
1714     {
1715         //writeln("{", e, "}");
1716     }
1717     assert(equal(sp6, ["", ""][]));
1718 }
1719
1720 struct Splitter(alias isTerminator, Range,
1721         Slice = Select!(is(typeof(Range.init[0 .. 1])),
1722                 Range,
1723                 ElementType!(Range)[]))
1724 if(!is(isTerminator))
1725 {
1726     private Range _input;
1727     private size_t _end;
1728     private alias unaryFun!isTerminator _isTerminator;
1729
1730     this(Range input)
1731     {
1732         _input = input;
1733         if (_input.empty)
1734         {
1735             _end = _end.max;
1736         }
1737         else
1738         {
1739             // Chase first terminator
1740             while (_end < _input.length && !_isTerminator(_input[_end]))
1741             {
1742                 ++_end;
1743             }
1744         }
1745     }
1746
1747     static if (isInfinite!Range)
1748     {
1749         enum bool empty = false;  // Propagate infiniteness.
1750     }
1751     else
1752     {
1753         @property bool empty()
1754         {
1755             return _end == _end.max;
1756         }
1757     }
1758
1759     @property Range front()
1760     {
1761         assert(!empty);
1762         return _input[0 .. _end];
1763     }
1764
1765     void popFront()
1766     {
1767         assert(!empty);
1768         if (_input.empty)
1769         {
1770             _end = _end.max;
1771             return;
1772         }
1773         // Skip over existing word
1774         _input = _input[_end .. _input.length];
1775         // Skip terminator
1776         for (;;)
1777         {
1778             if (_input.empty)
1779             {
1780                 // Nothing following the terminator - done
1781                 _end = _end.max;
1782                 return;
1783             }
1784             if (!_isTerminator(_input.front))
1785             {
1786                 // Found a legit next field
1787                 break;
1788             }
1789             _input.popFront();
1790         }
1791         assert(!_input.empty && !_isTerminator(_input.front));
1792         // Prepare _end
1793         _end = 1;
1794         while (_end < _input.length && !_isTerminator(_input[_end]))
1795         {
1796             ++_end;
1797         }
1798     }
1799
1800     static if(isForwardRange!Range)
1801     {
1802         @property typeof(this) save()
1803         {
1804             auto ret = this;
1805             ret._input = _input.save;
1806             return ret;
1807         }
1808     }
1809 }
1810
1811 Splitter!(isTerminator, Range)
1812 splitter(alias isTerminator, Range)(Range input)
1813 if (is(typeof(unaryFun!(isTerminator)(ElementType!(Range).init))))
1814 {
1815     return typeof(return)(input);
1816 }
1817
1818 unittest
1819 {
1820     debug(std_algorithm) scope(success)
1821         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
1822     void compare(string sentence, string[] witness)
1823     {
1824         foreach (word; splitter!"a == ' '"(sentence))
1825         {
1826             assert(word == witness.front, word);
1827             witness.popFront();
1828         }
1829         assert(witness.empty, witness[0]);
1830     }
1831
1832     compare(" Mary    has a little lamb.   ",
1833             ["", "Mary", "has", "a", "little", "lamb."]);
1834     compare("Mary    has a little lamb.   ",
1835             ["Mary", "has", "a", "little", "lamb."]);
1836     compare("Mary    has a little lamb.",
1837             ["Mary", "has", "a", "little", "lamb."]);
1838     compare("", []);
1839     compare(" ", [""]);
1840
1841     static assert(isForwardRange!(typeof(splitter!"a == ' '"("ABC"))));
1842
1843     foreach(DummyType; AllDummyRanges)
1844     {
1845         static if(isRandomAccessRange!DummyType)
1846         {
1847             auto rangeSplit = splitter!"a == 5"(DummyType.init);
1848             assert(equal(rangeSplit.front, [1,2,3,4]));
1849             rangeSplit.popFront();
1850             assert(equal(rangeSplit.front, [6,7,8,9,10]));
1851         }
1852     }
1853 }
1854
1855 // joiner
1856 /**
1857 Lazily joins a range of ranges with a separator. The separator itself
1858 is a range.
1859
1860 Example:
1861 ----
1862 assert(equal(joiner([""], "xyz"), ""));
1863 assert(equal(joiner(["", ""], "xyz"), "xyz"));
1864 assert(equal(joiner(["", "abc"], "xyz"), "xyzabc"));
1865 assert(equal(joiner(["abc", ""], "xyz"), "abcxyz"));
1866 assert(equal(joiner(["abc", "def"], "xyz"), "abcxyzdef"));
1867 assert(equal(joiner(["Mary", "has", "a", "little", "lamb"], "..."),
1868   "Mary...has...a...little...lamb"));
1869 ----
1870  */
1871 auto joiner(RoR, Separator)(RoR r, Separator sep)
1872 if (isForwardRange!RoR && isInputRange!(ElementType!RoR)
1873         && isForwardRange!Separator
1874         && is(ElementType!Separator : ElementType!(ElementType!RoR)))
1875 {
1876     static struct Result
1877     {
1878         private RoR _items;
1879         private ElementType!RoR _current;
1880         private Separator _sep, _currentSep;
1881
1882         private void useSeparator()
1883         {
1884             assert(_currentSep.empty && _current.empty,
1885                     "joiner: internal error");
1886             if (_sep.empty)
1887             {
1888                 // Advance to the next range in the
1889                 // input
1890                 //_items.popFront();
1891                 for (;; _items.popFront())
1892                 {
1893                     if (_items.empty) return;
1894                     if (!_items.front.empty) break;
1895                 }
1896                 _current = _items.front;
1897                 _items.popFront();
1898             }
1899             else
1900             {
1901                 // Must make sure something is coming after the
1902                 // separator - it's a separator, not a terminator!
1903                 if (_items.empty) return;
1904                 _currentSep = _sep.save;
1905                 assert(!_currentSep.empty);
1906             }
1907         }
1908
1909         private void useItem()
1910         {
1911             assert(_currentSep.empty && _current.empty,
1912                     "joiner: internal error");
1913             // Use the input
1914             if (_items.empty) return;
1915             _current = _items.front;
1916             _items.popFront();
1917             if (!_current.empty)
1918             {
1919                 return;
1920             }
1921             // No data in the current item - toggle to use the
1922             // separator
1923             useSeparator();
1924         }
1925        
1926         this(RoR items, Separator sep)
1927         {
1928             _items = items;
1929             _sep = sep;
1930             useItem();
1931             // We need the separator if the input has at least two
1932             // elements
1933             if (_current.empty && _items.empty)
1934             {
1935                 // Vacate the whole thing
1936                 _currentSep = _currentSep.init;
1937             }
1938         }
1939
1940         @property auto empty()
1941         {
1942             return _current.empty && _currentSep.empty;
1943         }
1944        
1945         @property ElementType!(ElementType!RoR) front()
1946         {
1947             if (!_currentSep.empty) return _currentSep.front;
1948             assert(!_current.empty);
1949             return _current.front;
1950         }
1951        
1952         void popFront()
1953         {
1954             assert(!empty);
1955             // Using separator?
1956             if (!_currentSep.empty)
1957             {
1958                 _currentSep.popFront();
1959                 if (!_currentSep.empty) return;
1960                 useItem();
1961             }
1962             else
1963             {
1964                 // we're using the range
1965                 _current.popFront();
1966                 if (!_current.empty) return;
1967                 useSeparator();
1968             }
1969         }
1970
1971         static if (isForwardRange!RoR && isForwardRange!(ElementType!RoR))
1972         {
1973             @property auto save()
1974             {
1975                 Result copy;
1976                 copy._items = _items.save;
1977                 copy._current = _current.save;
1978                 copy._sep = _sep.save;
1979                 copy._currentSep = _currentSep.save;
1980                 return copy;
1981             }
1982         }
1983     }
1984     return Result(r, sep);
1985 }
1986
1987 unittest
1988 {
1989     debug(std_algorithm) scope(success)
1990         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
1991     static assert(isInputRange!(typeof(joiner([""], ""))));
1992     static assert(isForwardRange!(typeof(joiner([""], ""))));
1993     assert(equal(joiner([""], "xyz"), ""), text(joiner([""], "xyz")));
1994     assert(equal(joiner(["", ""], "xyz"), "xyz"), text(joiner(["", ""], "xyz")));
1995     assert(equal(joiner(["", "abc"], "xyz"), "xyzabc"));
1996     assert(equal(joiner(["abc", ""], "xyz"), "abcxyz"));
1997     assert(equal(joiner(["abc", "def"], "xyz"), "abcxyzdef"));
1998     assert(equal(joiner(["Mary", "has", "a", "little", "lamb"], "..."),
1999                     "Mary...has...a...little...lamb"));
2000 }
2001
2002 auto joiner(RoR)(RoR r)
2003 if (isInputRange!RoR && isInputRange!(ElementType!RoR))
2004 {
2005     static struct Result
2006     {
2007     private:
2008         RoR _items;
2009         ElementType!RoR _current;
2010         void prepare()
2011         {
2012             for (;; _items.popFront())
2013             {
2014                 if (_items.empty) return;
2015                 if (!_items.front.empty) break;
2016             }
2017             _current = _items.front;
2018             _items.popFront();
2019         }
2020     public:
2021         this(RoR r)
2022         {
2023             _items = r;
2024             prepare();
2025         }
2026         static if (isInfinite!(ElementType!RoR))
2027         {
2028             enum bool empty = false;
2029         }
2030         else
2031         {
2032             @property auto empty()
2033             {
2034                 return _current.empty;
2035             }
2036         }
2037         @property auto ref front()
2038         {
2039             assert(!empty);
2040             return _current.front;
2041         }
2042         void popFront()
2043         {
2044             assert(!_current.empty);
2045             _current.popFront();
2046             if (_current.empty) prepare();
2047         }
2048         static if (isForwardRange!RoR && isForwardRange!(ElementType!RoR))
2049         {
2050             @property auto save()
2051             {
2052                 Result copy;
2053                 copy._items = _items.save;
2054                 copy._current = _current.save;
2055                 return copy;
2056             }
2057         }
2058     }
2059     return Result(r);
2060 }
2061
2062 unittest
2063 {
2064     debug(std_algorithm) scope(success)
2065         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
2066     static assert(isInputRange!(typeof(joiner([""]))));
2067     static assert(isForwardRange!(typeof(joiner([""]))));
2068     assert(equal(joiner([""]), ""));
2069     assert(equal(joiner(["", ""]), ""));
2070     assert(equal(joiner(["", "abc"]), "abc"));
2071     assert(equal(joiner(["abc", ""]), "abc"));
2072     assert(equal(joiner(["abc", "def"]), "abcdef"));
2073     assert(equal(joiner(["Mary", "has", "a", "little", "lamb"]),
2074                     "Maryhasalittlelamb"));
2075     assert(equal(joiner(std.range.repeat("abc", 3)), "abcabcabc"));
2076
2077     // joiner allows in-place mutation!
2078     auto a = [ [1, 2, 3], [42, 43] ];
2079     auto j = joiner(a);
2080     j.front() = 44;
2081     assert(a == [ [44, 2, 3], [42, 43] ]);
2082 }
2083
2084 // uniq
2085 /**
2086 Iterates unique consecutive elements of the given range (functionality
2087 akin to the $(WEB wikipedia.org/wiki/_Uniq, _uniq) system
2088 utility). Equivalence of elements is assessed by using the predicate
2089 $(D pred), by default $(D "a == b"). If the given range is
2090 bidirectional, $(D uniq) also yields a bidirectional range.
2091
2092 Example:
2093 ----
2094 int[] arr = [ 1, 2, 2, 2, 2, 3, 4, 4, 4, 5 ];
2095 assert(equal(uniq(arr), [ 1, 2, 3, 4, 5 ][]));
2096 ----
2097 */
2098 struct Uniq(alias pred, R)
2099 {
2100     R _input;
2101
2102     this(R input)
2103     {
2104         _input = input;
2105     }
2106
2107     ref Uniq opSlice()
2108     {
2109         return this;
2110     }
2111
2112     void popFront()
2113     {
2114         auto last = _input.front;
2115         do
2116         {
2117             _input.popFront;
2118         }
2119         while (!_input.empty && binaryFun!(pred)(last, _input.front));
2120     }
2121
2122     @property ElementType!(R) front() { return _input.front; }
2123
2124     static if (isBidirectionalRange!R)
2125     {
2126         void popBack()
2127         {
2128             auto last = _input.back;
2129             do
2130             {
2131                 _input.popBack;
2132             }
2133             while (!_input.empty && binaryFun!(pred)(last, _input.back));
2134         }
2135
2136         @property ElementType!(R) back() { return _input.back; }
2137     }
2138
2139     static if (isInfinite!R)
2140     {
2141         enum bool empty = false;  // Propagate infiniteness.
2142     }
2143     else
2144     {
2145         @property bool empty() { return _input.empty; }
2146     }
2147
2148
2149     static if (isForwardRange!R) {
2150         @property typeof(this) save() {
2151             return typeof(this)(_input.save);
2152         }
2153     }
2154 }
2155
2156 /// Ditto
2157 Uniq!(pred, Range) uniq(alias pred = "a == b", Range)(Range r)
2158 {
2159     return typeof(return)(r);
2160 }
2161
2162 unittest
2163 {
2164     debug(std_algorithm) scope(success)
2165         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
2166     int[] arr = [ 1, 2, 2, 2, 2, 3, 4, 4, 4, 5 ];
2167     auto r = uniq(arr);
2168     static assert(isForwardRange!(typeof(r)));
2169
2170     assert(equal(r, [ 1, 2, 3, 4, 5 ][]));
2171     assert(equal(retro(r), retro([ 1, 2, 3, 4, 5 ][])));
2172
2173     foreach(DummyType; AllDummyRanges) {
2174         DummyType d;
2175         auto u = uniq(d);
2176         assert(equal(u, [1,2,3,4,5,6,7,8,9,10]));
2177
2178         static assert(d.rt == RangeType.Input || isForwardRange!(typeof(u)));
2179
2180         static if (d.rt >= RangeType.Bidirectional) {
2181             assert(equal(retro(u), [10,9,8,7,6,5,4,3,2,1]));
2182         }
2183     }
2184 }
2185
2186 // group
2187 /**
2188 Similarly to $(D uniq), $(D group) iterates unique consecutive
2189 elements of the given range. The element type is $(D
2190 Tuple!(ElementType!R, uint)) because it includes the count of
2191 equivalent elements seen. Equivalence of elements is assessed by using
2192 the predicate $(D pred), by default $(D "a == b").
2193
2194 $(D Group) is an input range if $(D R) is an input range, and a
2195 forward range in all other cases.
2196
2197 Example:
2198 ----
2199 int[] arr = [ 1, 2, 2, 2, 2, 3, 4, 4, 4, 5 ];
2200 assert(equal(group(arr), [ tuple(1, 1u), tuple(2, 4u), tuple(3, 1u),
2201     tuple(4, 3u), tuple(5, 1u) ][]));
2202 ----
2203 */
2204 struct Group(alias pred, R) if (isInputRange!R)
2205 {
2206     private R _input;
2207     private Tuple!(ElementType!R, uint) _current;
2208     private alias binaryFun!pred comp;
2209
2210     this(R input)
2211     {
2212         _input = input;
2213         if (!_input.empty) popFront;
2214     }
2215
2216     void popFront()
2217     {
2218         if (_input.empty)
2219         {
2220             _current[1] = 0;
2221         }
2222         else
2223         {
2224             _current = tuple(_input.front, 1u);
2225             _input.popFront;
2226             while (!_input.empty && comp(_current[0], _input.front))
2227             {
2228                 ++_current[1];
2229                 _input.popFront;
2230             }
2231         }
2232     }
2233
2234     static if (isInfinite!R)
2235     {
2236         enum bool empty = false;  // Propagate infiniteness.
2237     }
2238     else
2239     {
2240         @property bool empty()
2241         {
2242             return _current[1] == 0;
2243         }
2244     }
2245
2246     @property ref Tuple!(ElementType!R, uint) front()
2247     {
2248         assert(!empty);
2249         return _current;
2250     }
2251
2252     static if (isForwardRange!R) {
2253         @property typeof(this) save() {
2254             typeof(this) ret;
2255             ret._input = this._input.save;
2256             ret._current = this._current;
2257
2258             return ret;
2259         }
2260     }
2261 }
2262
2263 /// Ditto
2264 Group!(pred, Range) group(alias pred = "a == b", Range)(Range r)
2265 {
2266     return typeof(return)(r);
2267 }
2268
2269 unittest
2270 {
2271     debug(std_algorithm) scope(success)
2272         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
2273     int[] arr = [ 1, 2, 2, 2, 2, 3, 4, 4, 4, 5 ];
2274     assert(equal(group(arr), [ tuple(1, 1u), tuple(2, 4u), tuple(3, 1u),
2275                             tuple(4, 3u), tuple(5, 1u) ][]));
2276     static assert(isForwardRange!(typeof(group(arr))));
2277
2278     foreach(DummyType; AllDummyRanges) {
2279         DummyType d;
2280         auto g = group(d);
2281
2282         static assert(d.rt == RangeType.Input || isForwardRange!(typeof(g)));
2283
2284         assert(equal(g, [tuple(1, 1u), tuple(2, 1u), tuple(3, 1u), tuple(4, 1u),
2285             tuple(5, 1u), tuple(6, 1u), tuple(7, 1u), tuple(8, 1u),
2286             tuple(9, 1u), tuple(10, 1u)]));
2287     }
2288 }
2289
2290 // overwriteAdjacent
2291 /*
2292 Reduces $(D r) by shifting it to the left until no adjacent elements
2293 $(D a), $(D b) remain in $(D r) such that $(D pred(a, b)). Shifting is
2294 performed by evaluating $(D move(source, target)) as a primitive. The
2295 algorithm is stable and runs in $(BIGOH r.length) time. Returns the
2296 reduced range.
2297
2298 The default $(XREF _algorithm, move) performs a potentially
2299 destructive assignment of $(D source) to $(D target), so the objects
2300 beyond the returned range should be considered "empty". By default $(D
2301 pred) compares for equality, in which case $(D overwriteAdjacent)
2302 collapses adjacent duplicate elements to one (functionality akin to
2303 the $(WEB wikipedia.org/wiki/Uniq, uniq) system utility).
2304
2305 Example:
2306 ----
2307 int[] arr = [ 1, 2, 2, 2, 2, 3, 4, 4, 4, 5 ];
2308 auto r = overwriteAdjacent(arr);
2309 assert(r == [ 1, 2, 3, 4, 5 ]);
2310 ----
2311 */
2312 // Range overwriteAdjacent(alias pred, alias move, Range)(Range r)
2313 // {
2314 //     if (r.empty) return r;
2315 //     //auto target = begin(r), e = end(r);
2316 //     auto target = r;
2317 //     auto source = r;
2318 //     source.popFront;
2319 //     while (!source.empty)
2320 //     {
2321 //         if (!pred(target.front, source.front))
2322 //         {
2323 //             target.popFront;
2324 //             continue;
2325 //         }
2326 //         // found an equal *source and *target
2327 //         for (;;)
2328 //         {
2329 //             //@@@
2330 //             //move(source.front, target.front);
2331 //             target[0] = source[0];
2332 //             source.popFront;
2333 //             if (source.empty) break;
2334 //             if (!pred(target.front, source.front)) target.popFront;
2335 //         }
2336 //         break;
2337 //     }
2338 //     return range(begin(r), target + 1);
2339 // }
2340
2341 // /// Ditto
2342 // Range overwriteAdjacent(
2343 //     string fun = "a == b",
2344 //     alias move = .move,
2345 //     Range)(Range r)
2346 // {
2347 //     return .overwriteAdjacent!(binaryFun!(fun), move, Range)(r);
2348 // }
2349
2350 // unittest
2351 // {
2352 //     int[] arr = [ 1, 2, 2, 2, 2, 3, 4, 4, 4, 5 ];
2353 //     auto r = overwriteAdjacent(arr);
2354 //     assert(r == [ 1, 2, 3, 4, 5 ]);
2355 //     assert(arr == [ 1, 2, 3, 4, 5, 3, 4, 4, 4, 5 ]);
2356
2357 // }
2358
2359 // find
2360 /**
2361 Finds an individual element in an input range. Elements of $(D
2362 haystack) are compared with $(D needle) by using predicate $(D
2363 pred). Performs $(BIGOH walkLength(haystack)) evaluations of $(D
2364 pred). See also $(WEB sgi.com/tech/stl/_find.html, STL's _find).
2365
2366 To _find the last occurence of $(D needle) in $(D haystack), call $(D
2367 find(retro(haystack), needle)). See also $(XREF range, retro).
2368
2369 Params:
2370
2371 haystack = The range searched in.
2372
2373 needle = The element searched for.
2374
2375 Constraints:
2376
2377 $(D isInputRange!R && is(typeof(binaryFun!pred(haystack.front, needle)
2378 : bool)))
2379
2380 Returns:
2381
2382 $(D haystack) advanced such that $(D binaryFun!pred(haystack.front,
2383 needle)) is $(D true) (if no such position exists, returns $(D
2384 haystack) after exhaustion).
2385
2386 Example:
2387
2388 ----
2389 assert(find("hello, world", ',') == ", world");
2390 assert(find([1, 2, 3, 5], 4) == []);
2391 assert(find(SList!int(1, 2, 3, 4, 5)[], 4) == SList!int(4, 5)[]);
2392 assert(find!"a > b"([1, 2, 3, 5], 2) == [3, 5]);
2393
2394 auto a = [ 1, 2, 3 ];
2395 assert(find(a, 5).empty);       // not found
2396 assert(!find(a, 2).empty);      // found
2397
2398 // Case-insensitive find of a string
2399 string[] s = [ "Hello", "world", "!" ];
2400 assert(!find!("tolower(a) == b")(s, "hello").empty);
2401 ----
2402  */
2403 R find(alias pred = "a == b", R, E)(R haystack, E needle)
2404 if (isInputRange!R &&
2405         is(typeof(binaryFun!pred(haystack.front, needle)) : bool))
2406 {
2407     for (; !haystack.empty; haystack.popFront())
2408     {
2409         if (binaryFun!pred(haystack.front, needle)) break;
2410     }
2411     return haystack;
2412 }
2413
2414 unittest
2415 {
2416     debug(std_algorithm) scope(success)
2417         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
2418     auto lst = SList!int(1, 2, 5, 7, 3);
2419     assert(lst.front == 1);
2420     auto r = find(lst[], 5);
2421     assert(equal(r, SList!int(5, 7, 3)[]));
2422     assert(find([1, 2, 3, 5], 4).empty);
2423 }
2424
2425 /**
2426 Finds a forward range in another. Elements are compared for
2427 equality. Performs $(BIGOH walkLength(haystack) * walkLength(needle))
2428 comparisons in the worst case. Specializations taking advantage of
2429 bidirectional or random access (where present) may accelerate search
2430 depending on the statistics of the two ranges' content.
2431
2432 Params:
2433
2434 haystack = The range searched in.
2435
2436 needle = The range searched for.
2437
2438 Constraints:
2439
2440 $(D isForwardRange!R1 && isForwardRange!R2 &&
2441 is(typeof(binaryFun!pred(haystack.front, needle.front) : bool)))
2442
2443 Returns:
2444
2445 $(D haystack) advanced such that $(D needle) is a prefix of it (if no
2446 such position exists, returns $(D haystack) advanced to termination).
2447
2448 ----
2449 assert(find("hello, world", "World").empty);
2450 assert(find("hello, world", "wo") == "world");
2451 assert(find([1, 2, 3, 4], SList!(2, 3)[]) == [2, 3, 4]);
2452 ----
2453  */
2454 R1 find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
2455 if (isForwardRange!R1 && isForwardRange!R2
2456         && is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool)
2457         && !isRandomAccessRange!R1)
2458 {
2459     static if (is(typeof(pred == "a == b")) && pred == "a == b" && isSomeString!R1 && isSomeString!R2
2460             && haystack[0].sizeof == needle[0].sizeof)
2461     {
2462         //return cast(R1) find(representation(haystack), representation(needle));
2463         // Specialization for simple string search
2464         alias Select!(haystack[0].sizeof == 1, ubyte[],
2465                 Select!(haystack[0].sizeof == 2, ushort[], uint[]))
2466             Representation;
2467         // Will use the array specialization
2468         return cast(R1) .find!(pred, Representation, Representation)
2469             (cast(Representation) haystack, cast(Representation) needle);
2470     }
2471     else
2472     {
2473         return simpleMindedFind!pred(haystack, needle);
2474     }
2475 }
2476
2477 unittest
2478 {
2479     debug(std_algorithm) scope(success)
2480         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
2481     auto lst = SList!int(1, 2, 5, 7, 3);
2482     static assert(isForwardRange!(int[]));
2483     static assert(isForwardRange!(typeof(lst[])));
2484     auto r = find(lst[], [2, 5]);
2485     assert(equal(r, SList!int(2, 5, 7, 3)[]));
2486 }
2487
2488 // Specialization for searching a random-access range for a
2489 // bidirectional range
2490 R1 find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
2491 if (isRandomAccessRange!R1 && isBidirectionalRange!R2
2492         && is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool))
2493 {
2494     if (needle.empty) return haystack;
2495     const needleLength = walkLength(needle);
2496     if (needleLength > haystack.length)
2497     {
2498         // @@@BUG@@@
2499         //return haystack[$ .. $];
2500         return haystack[haystack.length .. haystack.length];
2501     }
2502     // @@@BUG@@@
2503     // auto needleBack = moveBack(needle);
2504     // Stage 1: find the step
2505     size_t step = 1;
2506     auto needleBack = needle.back;
2507     needle.popBack();
2508     for (auto i = needle.save; !i.empty && !binaryFun!pred(i.back, needleBack);
2509          i.popBack(), ++step)
2510     {
2511     }
2512     // Stage 2: linear find
2513     size_t scout = needleLength - 1;
2514     for (;;)
2515     {
2516         if (scout >= haystack.length)
2517         {
2518             return haystack[haystack.length .. haystack.length];
2519         }
2520         if (!binaryFun!pred(haystack[scout], needleBack))
2521         {
2522             ++scout;
2523             continue;
2524         }
2525         // Found a match with the last element in the needle
2526         auto cand = haystack[scout + 1 - needleLength .. haystack.length];
2527         if (startsWith!pred(cand, needle))
2528         {
2529             // found
2530             return cand;
2531         }
2532         // Continue with the stride
2533         scout += step;
2534     }
2535 }
2536
2537 unittest
2538 {
2539     //scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done.");
2540     // @@@BUG@@@ removing static below makes unittest fail
2541     static struct BiRange
2542     {
2543         int[] payload;
2544         @property bool empty() { return payload.empty; }
2545         @property BiRange save() { return this; }
2546         @property ref int front() { return payload[0]; }
2547         @property ref int back() { return payload[$ - 1]; }
2548         void popFront() { return payload.popFront(); }
2549         void popBack() { return payload.popBack(); }
2550     }
2551     //static assert(isBidirectionalRange!BiRange);
2552     auto r = BiRange([1, 2, 3, 10, 11, 4]);
2553     //assert(equal(find(r, [3, 10]), BiRange([3, 10, 11, 4])));
2554     //assert(find("abc", "bc").length == 2);
2555     debug(std_algorithm) scope(success)
2556         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
2557     //assert(find!"a == b"("abc", "bc").length == 2);
2558 }
2559
2560 // Leftover specialization: searching a random-access range for a
2561 // non-bidirectional forward range
2562 R1 find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
2563 if (isRandomAccessRange!R1 && isForwardRange!R2 && !isBidirectionalRange!R2
2564         && is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool))
2565 {
2566     static if (!is(ElementType!R1 == ElementType!R2))
2567     {
2568         return simpleMindedFind!pred(haystack, needle);
2569     }
2570     else
2571     {
2572         // Prepare the search with needle's first element
2573         if (needle.empty) return haystack;
2574         haystack = .find!pred(haystack, needle.front);
2575         if (haystack.empty) return haystack;
2576         needle.popFront();
2577         size_t matchLen = 1;
2578         // Loop invariant: haystack[0 .. matchLen] matches everything in
2579         // the initial needle that was popped out of needle.
2580         for (;;)
2581         {
2582             // Extend matchLength as much as possible
2583             for (;;)
2584             {
2585                 if (needle.empty || haystack.empty) return haystack;
2586                 if (!binaryFun!pred(haystack[matchLen], needle.front)) break;
2587                 ++matchLen;
2588                 needle.popFront();
2589             }
2590             auto bestMatch = haystack[0 .. matchLen];
2591             haystack.popFront();
2592             haystack = .find!pred(haystack, bestMatch);
2593         }
2594     }
2595 }
2596
2597 unittest
2598 {
2599     assert(find([ 1, 2, 3 ], SList!int(2, 3)[]) == [ 2, 3 ]);
2600     assert(find([ 1, 2, 1, 2, 3, 3 ], SList!int(2, 3)[]) == [ 2, 3, 3 ]);
2601 }
2602
2603 // Internally used by some find() overloads above. Can't make it
2604 // private due to bugs in the compiler.
2605 /*private*/ R1 simpleMindedFind(alias pred, R1, R2)(R1 haystack, R2 needle)
2606 {
2607     enum estimateNeedleLength = hasLength!R1 && !hasLength!R2;
2608
2609     static if (hasLength!R1)
2610     {
2611         static if (hasLength!R2)
2612             size_t estimatedNeedleLength = 0;
2613         else
2614             immutable size_t estimatedNeedleLength = needle.length;
2615     }
2616
2617     bool haystackTooShort()
2618     {
2619         static if (hasLength!R1)
2620         {
2621             return haystack.length < estimatedNeedleLength;
2622         }
2623         else
2624         {
2625             return haystack.empty;
2626         }
2627     }
2628
2629   searching:
2630     for (;; haystack.popFront())
2631     {
2632         if (haystackTooShort())
2633         {
2634             // Failed search
2635             static if (hasLength!R1)
2636             {
2637                 static if (is(typeof(haystack[haystack.length ..
2638                                                 haystack.length]) : R1))
2639                     return haystack[haystack.length .. haystack.length];
2640                 else
2641                     return R1.init;
2642             }
2643             else
2644             {
2645                 assert(haystack.empty);
2646                 return haystack;
2647             }
2648         }
2649         static if (estimateNeedleLength)
2650             size_t matchLength = 0;
2651         for (auto h = haystack.save, n = needle.save;
2652              !n.empty;
2653              h.popFront(), n.popFront())
2654         {
2655             if (h.empty || !binaryFun!pred(h.front, n.front))
2656             {
2657                 // Failed searching n in h
2658                 static if (estimateNeedleLength)
2659                 {
2660                     if (estimatedNeedleLength < matchLength)
2661                         estimatedNeedleLength = matchLength;
2662                 }
2663                 continue searching;
2664             }
2665             static if (estimateNeedleLength)
2666                 ++matchLength;
2667         }
2668         break;
2669     }
2670     return haystack;
2671 }
2672
2673 /**
2674 Finds two or more $(D needles) into a $(D haystack). The predicate $(D
2675 pred) is used throughout to compare elements. By default, elements are
2676 compared for equality.
2677
2678 Params:
2679
2680 haystack = The target of the search. Must be an $(GLOSSARY input
2681 range). If any of $(D needles) is a range with elements comparable to
2682 elements in $(D haystack), then $(D haystack) must be a $(GLOSSARY
2683 forward range) such that the search can backtrack.
2684
2685 needles = One or more items to search for. Each of $(D needles) must
2686 be either comparable to one element in $(D haystack), or be itself a
2687 $(GLOSSARY forward range) with elements comparable with elements in
2688 $(D haystack).
2689
2690 Returns:
2691
2692 A tuple containing $(D haystack) positioned to match one of the
2693 needles and also the 1-based index of the matching element in $(D
2694 needles) (0 if none of $(D needles) matched, 1 if $(D needles[0])
2695 matched, 2 if $(D needles[1]) matched...).
2696
2697 The relationship between $(D haystack) and $(D needles) simply means
2698 that one can e.g. search for individual $(D int)s or arrays of $(D
2699 int)s in an array of $(D int)s. In addition, if elements are
2700 individually comparable, searches of heterogeneous types are allowed
2701 as well: a $(D double[]) can be searched for an $(D int) or a $(D
2702 short[]), and conversely a $(D long) can be searched for a $(D float)
2703 or a $(D double[]). This makes for efficient searches without the need
2704 to coerce one side of the comparison into the other's side type.
2705
2706 Example:
2707 ----
2708 int[] a = [ 1, 4, 2, 3 ];
2709 assert(find(a, 4) == [ 4, 2, 3 ]);
2710 assert(find(a, [ 1, 4 ]) == [ 1, 4, 2, 3 ]);
2711 assert(find(a, [ 1, 3 ], 4) == tuple([ 4, 2, 3 ], 2));
2712 // Mixed types allowed if comparable
2713 assert(find(a, 5, [ 1.2, 3.5 ], 2.0, [ 1 ]) == tuple([ 2, 3 ], 3));
2714 ----
2715
2716 The complexity of the search is $(BIGOH haystack.length *
2717 max(needles.length)). (For needles that are individual items, length
2718 is considered to be 1.) The strategy used in searching several
2719 subranges at once maximizes cache usage by moving in $(D haystack) as
2720 few times as possible.
2721  */
2722 Tuple!(Range, size_t) find(alias pred = "a == b", Range, Ranges...)
2723 (Range haystack, Ranges needles)
2724 if (Ranges.length > 1 && allSatisfy!(isForwardRange, Ranges))
2725 {
2726     for (;; haystack.popFront)
2727     {
2728         size_t r = startsWith!pred(haystack, needles);
2729         if (r || haystack.empty)
2730         {
2731             return tuple(haystack, r);
2732         }
2733     }
2734 }
2735
2736 unittest
2737 {
2738     debug(std_algorithm) scope(success)
2739         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
2740     auto s1 = "Mary has a little lamb";
2741     //writeln(find(s1, "has a", "has an"));
2742     assert(find(s1, "has a", "has an") == tuple("has a little lamb", 1));
2743     assert(find("abc", "bc").length == 2);
2744 }
2745
2746 unittest
2747 {
2748     debug(std_algorithm) scope(success)
2749         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
2750     int[] a = [ 1, 2, 3 ];
2751     assert(find(a, 5).empty);
2752     assert(find(a, 2) == [2, 3]);
2753
2754     foreach (T; TypeTuple!(int, double))
2755     {
2756         auto b = rndstuff!(T)();
2757         if (!b.length) continue;
2758         b[$ / 2] = 200;
2759         b[$ / 4] = 200;
2760         assert(find(b, 200).length == b.length - b.length / 4);
2761     }
2762
2763 // Case-insensitive find of a string
2764     string[] s = [ "Hello", "world", "!" ];
2765     //writeln(find!("toupper(a) == toupper(b)")(s, "hello"));
2766     assert(find!("toupper(a) == toupper(b)")(s, "hello").length == 3);
2767
2768     static bool f(string a, string b) { return toupper(a) == toupper(b); }
2769     assert(find!(f)(s, "hello").length == 3);
2770 }
2771
2772 unittest
2773 {
2774     debug(std_algorithm) scope(success)
2775         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
2776     int[] a = [ 1, 2, 3, 2, 6 ];
2777     assert(find(std.range.retro(a), 5).empty);
2778     assert(equal(find(std.range.retro(a), 2), [ 2, 3, 2, 1 ][]));
2779
2780     foreach (T; TypeTuple!(int, double))
2781     {
2782         auto b = rndstuff!(T)();
2783         if (!b.length) continue;
2784         b[$ / 2] = 200;
2785         b[$ / 4] = 200;
2786         assert(find(std.range.retro(b), 200).length ==
2787                 b.length - (b.length - 1) / 2);
2788     }
2789 }
2790
2791 unittest
2792 {
2793     debug(std_algorithm) scope(success)
2794         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
2795     int[] a = [ -1, 0, 1, 2, 3, 4, 5 ];
2796     int[] b = [ 1, 2, 3 ];
2797     assert(find(a, b) == [ 1, 2, 3, 4, 5 ]);
2798     assert(find(b, a).empty);
2799
2800     foreach(DummyType; AllDummyRanges) {
2801         DummyType d;
2802         auto findRes = find(d, 5);
2803         assert(equal(findRes, [5,6,7,8,9,10]));
2804     }
2805 }
2806
2807 /// Ditto
2808 struct BoyerMooreFinder(alias pred, Range)
2809 {
2810 private:
2811     size_t skip[];
2812     sizediff_t[ElementType!(Range)] occ;
2813     Range needle;
2814
2815     sizediff_t occurrence(ElementType!(Range) c)
2816     {
2817         auto p = c in occ;
2818         return p ? *p : -1;
2819     }
2820
2821 /*
2822 This helper function checks whether the last "portion" bytes of
2823 "needle" (which is "nlen" bytes long) exist within the "needle" at
2824 offset "offset" (counted from the end of the string), and whether the
2825 character preceding "offset" is not a match.  Notice that the range
2826 being checked may reach beyond the beginning of the string. Such range
2827 is ignored.
2828  */
2829     static bool needlematch(R)(R needle,
2830                               size_t portion, size_t offset)
2831     {
2832         sizediff_t virtual_begin = needle.length - offset - portion;
2833         sizediff_t ignore = 0;
2834         if (virtual_begin < 0) {
2835             ignore = -virtual_begin;
2836             virtual_begin = 0;
2837         }
2838         if (virtual_begin > 0
2839             && needle[virtual_begin - 1] == needle[$ - portion - 1])
2840             return 0;
2841
2842         immutable delta = portion - ignore;
2843         return equal(needle[needle.length - delta .. needle.length],
2844                 needle[virtual_begin .. virtual_begin + delta]);
2845     }
2846
2847 public:
2848     this(Range needle)
2849     {
2850         if (!needle.length) return;
2851         this.needle = needle;
2852         /* Populate table with the analysis of the needle */
2853         /* But ignoring the last letter */
2854         foreach (i, n ; needle[0 .. $ - 1])
2855         {
2856             this.occ[n] = i;
2857         }
2858         /* Preprocess #2: init skip[] */
2859         /* Note: This step could be made a lot faster.
2860          * A simple implementation is shown here. */
2861         this.skip = new size_t[needle.length];
2862         foreach (a; 0 .. needle.length)
2863         {
2864             size_t value = 0;
2865             while (value < needle.length
2866                    && !needlematch(needle, a, value))
2867             {
2868                 ++value;
2869             }
2870             this.skip[needle.length - a - 1] = value;
2871         }
2872     }
2873
2874     Range beFound(Range haystack)
2875     {
2876         if (!needle.length) return haystack;
2877         if (needle.length > haystack.length) return haystack[$ .. $];
2878         /* Search: */
2879         auto limit = haystack.length - needle.length;
2880         for (size_t hpos = 0; hpos <= limit; )
2881         {
2882             size_t npos = needle.length - 1;
2883             while (pred(needle[npos], haystack[npos+hpos]))
2884             {
2885                 if (npos == 0) return haystack[hpos .. $];
2886                 --npos;
2887             }
2888             hpos += max(skip[npos], npos - occurrence(haystack[npos+hpos]));
2889         }
2890         return haystack[$ .. $];
2891     }
2892
2893     @property size_t length()
2894     {
2895         return needle.length;
2896     }
2897 }
2898
2899 /// Ditto
2900 BoyerMooreFinder!(binaryFun!(pred), Range) boyerMooreFinder
2901 (alias pred = "a == b", Range)
2902 (Range needle) if (isRandomAccessRange!(Range) || isSomeString!Range)
2903 {
2904     return typeof(return)(needle);
2905 }
2906
2907 // Oddly this is not disabled by bug 4759
2908 Range1 find(Range1, alias pred, Range2)(
2909     Range1 haystack, BoyerMooreFinder!(pred, Range2) needle)
2910 {
2911     return needle.beFound(haystack);
2912 }
2913
2914 unittest
2915 {
2916     debug(std_algorithm) scope(success)
2917         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
2918     string h = "/homes/aalexand/d/dmd/bin/../lib/libphobos.a(dmain2.o)"
2919         "(.gnu.linkonce.tmain+0x74): In function `main' undefined reference"
2920         " to `_Dmain':";
2921     string[] ns = ["libphobos", "function", " undefined", "`", ":"];
2922     foreach (n ; ns) {
2923         auto p = find(h, boyerMooreFinder(n));
2924         assert(!p.empty);
2925     }
2926
2927     int[] a = [ -1, 0, 1, 2, 3, 4, 5 ];
2928     int[] b = [ 1, 2, 3 ];
2929     //writeln(find(a, boyerMooreFinder(b)));
2930     assert(find(a, boyerMooreFinder(b)) == [ 1, 2, 3, 4, 5 ]);
2931     assert(find(b, boyerMooreFinder(a)).empty);
2932 }
2933
2934 /**
2935 Advances the input range $(D haystack) by calling $(D haystack.popFront)
2936 until either $(D pred(haystack.front)), or $(D
2937 haystack.empty). Performs $(BIGOH haystack.length) evaluations of $(D
2938 pred). See also $(WEB sgi.com/tech/stl/find_if.html, STL's find_if).
2939
2940 To find the last element of a bidirectional $(D haystack) satisfying
2941 $(D pred), call $(D find!(pred)(retro(haystack))). See also $(XREF
2942 range, retro).
2943
2944 Example:
2945 ----
2946 auto arr = [ 1, 2, 3, 4, 1 ];
2947 assert(find!("a > 2")(arr) == [ 3, 4, 1 ]);
2948
2949 // with predicate alias
2950 bool pred(int x) { return x + 1 > 1.5; }
2951 assert(find!(pred)(arr) == arr);
2952 ----
2953 */
2954 Range find(alias pred, Range)(Range haystack) if (isInputRange!(Range))
2955 {
2956     alias unaryFun!(pred) predFun;
2957     for (; !haystack.empty && !predFun(haystack.front); haystack.popFront)
2958     {
2959     }
2960     return haystack;
2961 }
2962
2963 unittest
2964 {
2965     //scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done.");
2966     int[] a = [ 1, 2, 3 ];
2967     assert(find!("a > 2")(a) == [3]);
2968     bool pred(int x) { return x + 1 > 1.5; }
2969     assert(find!(pred)(a) == a);
2970 }
2971
2972 // findSkip
2973 /**
2974  * If $(D needle) occurs in $(D haystack), positions $(D haystack)
2975  * right after the first occurrence of $(D needle) and returns $(D
2976  * true). Otherwise, leaves $(D haystack) as is and returns $(D
2977  * false).
2978  *
2979  * Example:
2980 ----
2981 string s = "abcdef";
2982 assert(findSkip("abcdef", "cd") && s == "ef");
2983 s = "abcdef";
2984 assert(!findSkip("abcdef", "cxd") && s == "abcdef");
2985 assert(findSkip("abcdef", "def") && s.empty);
2986 ----
2987  */
2988 bool findSkip(alias pred = "a == b", R1, R2)(ref R1 haystack, R2 needle)
2989 if (isForwardRange!R1 && isForwardRange!R2
2990         && is(typeof(binaryFun!pred(haystack.front, needle.front))))
2991 {
2992     auto parts = findSplit!pred(haystack, needle);
2993     if (parts[1].empty) return false;
2994     // found
2995     haystack = parts[2];
2996     return true;
2997 }
2998
2999 unittest
3000 {
3001     string s = "abcdef";
3002     assert(findSkip(s, "cd") && s == "ef");
3003     s = "abcdef";
3004     assert(!findSkip(s, "cxd") && s == "abcdef");
3005     s = "abcdef";
3006     assert(findSkip(s, "def") && s.empty);
3007 }
3008
3009 /**
3010 These functions find the first occurrence of $(D needle) in $(D
3011 haystack) and then split $(D haystack) as follows.
3012
3013 $(D findSplit) returns a tuple $(D result) containing $(I three)
3014 ranges. $(D result[0]) is the portion of $(D haystack) before $(D
3015 needle), $(D result[1]) is the portion of $(D haystack) that matches
3016 $(D needle), and $(D result[2]) is the portion of $(D haystack) after
3017 the match.
3018  
3019 $(D findSplitBefore) returns a tuple $(D result) containing two
3020 ranges. $(D result[0]) is the portion of $(D haystack) before $(D
3021 needle), and $(D result[1]) is the balance of $(D haystack) starting
3022 with the match. If $(D needle) was not found, $(D result[0])
3023 comprehends $(D haystack) entirely and $(D result[1]) is empty.
3024
3025 $(D findSplitAfter) returns a tuple $(D result) containing two ranges.
3026 $(D result[0]) is the portion of $(D haystack) up to and including the
3027 match, and $(D result[1]) is the balance of $(D haystack) starting
3028 after the match. If $(D needle) was not found, $(D result[0]) is empty
3029 and $(D result[1]) is $(D haystack).
3030
3031 In all cases, the concatenation of the returned ranges spans the
3032 entire $(D haystack).
3033
3034 If $(D haystack) is a random-access range, all three components of the
3035 tuple have the same type as $(D haystack). Otherwise, $(D haystack)
3036 must be a forward range and the type of $(D result[0]) and $(D
3037 result[1]) is the same as $(XREF range,takeExactly).
3038
3039 Example:
3040 ----
3041 auto a = [ 1, 2, 3, 4, 5, 6, 7, 8 ];
3042 auto r = findSplit(a, [9, 1]);
3043 assert(r[0] == a);
3044 assert(r[1].empty);
3045 assert(r[2].empty);
3046 r = findSplit(a, [ 3, 4 ]);
3047 assert(r[0] == a[0 .. 2]);
3048 assert(r[1] == a[2 .. 4]);
3049 assert(r[2] == a[4 .. $]);
3050 auto r1 = findSplitBefore(a, [ 7, 8 ]);
3051 assert(r1[0] == a[0 .. 6]);
3052 assert(r1[1] == a[6 .. $]);
3053 auto r1 = findSplitAfter(a, [ 7, 8 ]);
3054 assert(r1[0] == a);
3055 assert(r1[1].empty);
3056 ----
3057  */
3058 auto findSplit(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
3059 if (isForwardRange!R1 && isForwardRange!R2)
3060 {
3061     static if (isSomeString!R1 && isSomeString!R2
3062             || isRandomAccessRange!R1 && hasLength!R2)
3063     {
3064         auto balance = find!pred(haystack, needle);
3065         immutable pos1 = haystack.length - balance.length;
3066         immutable pos2 = balance.empty ? pos1 : pos1 + needle.length;
3067         return tuple(haystack[0 .. pos1],
3068                 haystack[pos1 .. pos2],
3069                 haystack[pos2 .. haystack.length]);
3070     }
3071     else
3072     {
3073         auto original = haystack.save;
3074         auto h = haystack.save;
3075         auto n = needle.save;
3076         size_t pos1, pos2;
3077         while (!n.empty && !h.empty)
3078         {
3079             if (binaryFun!pred(h.front, n.front))
3080             {
3081                 h.popFront();
3082                 n.popFront();
3083                 ++pos2;
3084             }
3085             else
3086             {
3087                 haystack.popFront();
3088                 n = needle.save;
3089                 h = haystack.save;
3090                 pos2 = ++pos1;
3091             }
3092         }
3093         return tuple(takeExactly(original, pos1),
3094                 takeExactly(haystack, pos2 - pos1),
3095                 h);
3096     }
3097 }
3098
3099 /// Ditto
3100 auto findSplitBefore(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
3101 if (isForwardRange!R1 && isForwardRange!R2)
3102 {
3103     static if (isSomeString!R1 && isSomeString!R2
3104             || isRandomAccessRange!R1 && hasLength!R2)
3105     {
3106         auto balance = find!pred(haystack, needle);
3107         immutable pos = haystack.length - balance.length;
3108         return tuple(haystack[0 .. pos], haystack[pos .. haystack.length]);
3109     }
3110     else
3111     {
3112         auto original = haystack.save;
3113         auto h = haystack.save;
3114         auto n = needle.save;
3115         size_t pos;
3116         while (!n.empty && !h.empty)
3117         {
3118             if (binaryFun!pred(h.front, n.front))
3119             {
3120                 h.popFront();
3121                 n.popFront();
3122             }
3123             else
3124             {
3125                 haystack.popFront();
3126                 n = needle.save;
3127                 h = haystack.save;
3128                 ++pos;
3129             }
3130         }
3131         return tuple(takeExactly(original, pos), haystack);
3132     }
3133 }
3134
3135 /// Ditto
3136 auto findSplitAfter(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
3137 if (isForwardRange!R1 && isForwardRange!R2)
3138 {
3139     static if (isSomeString!R1 && isSomeString!R2
3140             || isRandomAccessRange!R1 && hasLength!R2)
3141     {
3142         auto balance = find!pred(haystack, needle);
3143         immutable pos = balance.empty ? 0 : haystack.length - balance.length + needle.length;
3144         return tuple(haystack[0 .. pos], haystack[pos .. haystack.length]);
3145     }
3146     else
3147     {
3148         auto original = haystack.save;
3149         auto h = haystack.save;
3150         auto n = needle.save;
3151         size_t pos1, pos2;
3152         while (!n.empty)
3153         {
3154             if (h.empty)
3155             {
3156                 // Failed search
3157                 return tuple(takeExactly(original, 0), original);
3158             }
3159             if (binaryFun!pred(h.front, n.front))
3160             {
3161                 h.popFront();
3162                 n.popFront();
3163                 ++pos2;
3164             }
3165             else
3166             {
3167                 haystack.popFront();
3168                 n = needle.save;
3169                 h = haystack.save;
3170                 pos2 = ++pos1;
3171             }
3172         }
3173         return tuple(takeExactly(original, pos2), h);
3174     }
3175 }
3176
3177 unittest
3178 {
3179     auto a = [ 1, 2, 3, 4, 5, 6, 7, 8 ];
3180     auto r = findSplit(a, [9, 1]);
3181     assert(r[0] == a);
3182     assert(r[1].empty);
3183     assert(r[2].empty);
3184     r = findSplit(a, [3]);
3185     assert(r[0] == a[0 .. 2]);
3186     assert(r[1] == a[2 .. 3]);
3187     assert(r[2] == a[3 .. $]);
3188
3189     auto r1 = findSplitBefore(a, [9, 1]);
3190     assert(r1[0] == a);
3191     assert(r1[1].empty);
3192     r1 = findSplitBefore(a, [3, 4]);
3193     assert(r1[0] == a[0 .. 2]);
3194     assert(r1[1] == a[2 .. $]);
3195
3196     r1 = findSplitAfter(a, [9, 1]);
3197     assert(r1[0].empty);
3198     assert(r1[1] == a);
3199     r1 = findSplitAfter(a, [3, 4]);
3200     assert(r1[0] == a[0 .. 4]);
3201     assert(r1[1] == a[4 .. $]);
3202 }
3203
3204 unittest
3205 {
3206     auto a = [ 1, 2, 3, 4, 5, 6, 7, 8 ];
3207     auto fwd = filter!"a > 0"(a);
3208     auto r = findSplit(fwd, [9, 1]);
3209     assert(equal(r[0], a));
3210     assert(r[1].empty);
3211     assert(r[2].empty);
3212     r = findSplit(fwd, [3]);
3213     assert(equal(r[0],  a[0 .. 2]));
3214     assert(equal(r[1], a[2 .. 3]));
3215     assert(equal(r[2], a[3 .. $]));
3216    
3217     auto r1 = findSplitBefore(fwd, [9, 1]);
3218     assert(equal(r1[0], a));
3219     assert(r1[1].empty);
3220     r1 = findSplitBefore(fwd, [3, 4]);
3221     assert(equal(r1[0], a[0 .. 2]));
3222     assert(equal(r1[1], a[2 .. $]));
3223
3224     r1 = findSplitAfter(fwd, [9, 1]);
3225     assert(r1[0].empty);
3226     assert(equal(r1[1], a));
3227     r1 = findSplitAfter(fwd, [3, 4]);
3228     assert(equal(r1[0], a[0 .. 4]));
3229     assert(equal(r1[1], a[4 .. $]));
3230 }
3231
3232 /**
3233 If $(D haystack) supports slicing, returns the smallest number $(D n)
3234 such that $(D haystack[n .. $].startsWith!pred(needle)). Oherwise,
3235 returns the smallest $(D n) such that after $(D n) calls to $(D
3236 haystack.popFront), $(D haystack.startsWith!pred(needle)). If no such
3237 number could be found, return $(D -1).
3238  */
3239 sizediff_t countUntil(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
3240 if (is(typeof(startsWith!pred(haystack, needle))))
3241 {
3242     static if (isNarrowString!R1)
3243     {
3244         // Narrow strings are handled a bit differently
3245         auto length = haystack.length;
3246         for (; !haystack.empty; haystack.popFront)
3247         {
3248             if (startsWith!pred(haystack, needle))
3249             {
3250                 return length - haystack.length;
3251             }
3252         }
3253     }
3254     else
3255     {
3256         typeof(return) result;
3257         for (; !haystack.empty; ++result, haystack.popFront())
3258         {
3259             if (startsWith!pred(haystack, needle)) return result;
3260         }
3261     }
3262     return -1;
3263 }
3264
3265 /**
3266  * Same as $(D countUntil). This symbol has been scheduled for
3267  * deprecation because it is easily confused with the homonym function
3268  * in $(D std.string).
3269  */
3270 sizediff_t indexOf(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
3271 if (is(typeof(startsWith!pred(haystack, needle))))
3272 {
3273     pragma(msg, "std.algorithm.indexOf has been scheduled for deprecation."
3274             " You may want to use std.algorithm.countUntil instead.");
3275     return countUntil!pred(haystack, needle);
3276 }
3277
3278 /**
3279 Interval option specifier for $(D until) (below) and others.
3280  */
3281 enum OpenRight
3282 {
3283     no, /// Interval is closed to the right (last element included)
3284     yes /// Interval is open to the right (last element is not included)
3285 }
3286
3287 /**
3288 Lazily iterates $(D range) until value $(D sentinel) is found, at
3289 which point it stops.
3290
3291 Example:
3292 ----
3293 int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5];
3294 assert(equal(a.until(7), [1, 2, 4][]));
3295 assert(equal(a.until(7, OpenRight.no), [1, 2, 4, 7][]));
3296 ----
3297  */
3298 struct Until(alias pred, Range, Sentinel) if (isInputRange!Range)
3299 {
3300     private Range _input;
3301     static if (!is(Sentinel == void))
3302         private Sentinel _sentinel;
3303     // mixin(bitfields!(
3304     //             OpenRight, "_openRight", 1,
3305     //             bool,  "_done", 1,
3306     //             uint, "", 6));
3307     //             OpenRight, "_openRight", 1,
3308     //             bool,  "_done", 1,
3309     OpenRight _openRight;
3310     bool _done;
3311
3312     static if (!is(Sentinel == void))
3313         this(Range input, Sentinel sentinel,
3314                 OpenRight openRight = OpenRight.yes)
3315         {
3316             _input = input;
3317             _sentinel = sentinel;
3318             _openRight = openRight;
3319             _done = _input.empty || openRight && predSatisfied();
3320         }
3321     else
3322         this(Range input, OpenRight openRight = OpenRight.yes)
3323         {
3324             _input = input;
3325             _openRight = openRight;
3326             _done = _input.empty || openRight && predSatisfied();
3327         }
3328
3329     @property bool empty()
3330     {
3331         return _done;
3332     }
3333
3334     @property ElementType!Range front()
3335     {
3336         assert(!empty);
3337         return _input.front;
3338     }
3339
3340     bool predSatisfied()
3341     {
3342         static if (is(Sentinel == void))
3343             return unaryFun!pred(_input.front);
3344         else
3345             return startsWith!pred(_input, _sentinel);
3346     }
3347
3348     void popFront()
3349     {
3350         assert(!empty);
3351         if (!_openRight)
3352         {
3353             if (predSatisfied())
3354             {
3355                 _done = true;
3356                 return;
3357             }
3358             _input.popFront;
3359             _done = _input.empty;
3360         }
3361         else
3362         {
3363             _input.popFront;
3364             _done = _input.empty || predSatisfied;
3365         }
3366     }
3367
3368     static if (!is(Sentinel == void))
3369         @property Until save()
3370         {
3371             Until result;
3372
3373             result._input     = _input.save;
3374             result._sentinel  = _sentinel;
3375             result._openRight = _openRight;
3376             result._done      = _done;
3377
3378             return result;
3379         }
3380     else
3381         @property Until save()
3382         {
3383             Until result;
3384
3385             result._input     = _input.save;
3386             result._openRight = _openRight;
3387             result._done      = _done;
3388
3389             return result;
3390         }
3391 }
3392
3393 /// Ditto
3394 Until!(pred, Range, Sentinel)
3395 until(alias pred = "a == b", Range, Sentinel)
3396 (Range range, Sentinel sentinel, OpenRight openRight = OpenRight.yes)
3397 if (!is(Sentinel == OpenRight))
3398 {
3399     return typeof(return)(range, sentinel, openRight);
3400 }
3401
3402 /// Ditto
3403 Until!(pred, Range, void)
3404 until(alias pred, Range)
3405 (Range range, OpenRight openRight = OpenRight.yes)
3406 {
3407     return typeof(return)(range, openRight);
3408 }
3409
3410 unittest
3411 {
3412     //scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done.");
3413     int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5];
3414
3415     static assert(isForwardRange!(typeof(a.until(7))));
3416     static assert(isForwardRange!(typeof(until!"a == 2"(a, OpenRight.no))));
3417
3418     assert(equal(a.until(7), [1, 2, 4][]));
3419     assert(equal(a.until([7, 2]), [1, 2, 4, 7][]));
3420     assert(equal(a.until(7, OpenRight.no), [1, 2, 4, 7][]));
3421     assert(equal(until!"a == 2"(a, OpenRight.no), [1, 2][]));
3422 }
3423
3424 /**
3425 If the range $(D doesThisStart) starts with $(I any) of the $(D
3426 withOneOfThese) ranges or elements, returns 1 if it starts with $(D
3427 withOneOfThese[0]), 2 if it starts with $(D withOneOfThese[1]), and so
3428 on. If no match, returns 0.
3429
3430 Example:
3431 ----
3432 assert(startsWith("abc", ""));
3433 assert(startsWith("abc", "a"));
3434 assert(!startsWith("abc", "b"));
3435 assert(startsWith("abc", 'a', "b") == 1);
3436 assert(startsWith("abc", "b", "a") == 2);
3437 assert(startsWith("abc", "a", "a") == 1);
3438 assert(startsWith("abc", "x", "a", "b") == 2);
3439 assert(startsWith("abc", "x", "aa", "ab") == 3);
3440 assert(startsWith("abc", "x", "aaa", "sab") == 0);
3441 assert(startsWith("abc", "x", "aaa", "a", "sab") == 3);
3442 ----
3443  */
3444 uint startsWith(alias pred = "a == b", Range, Ranges...)
3445 (Range doesThisStart, Ranges withOneOfThese)
3446 if (Ranges.length > 1 && isInputRange!Range
3447         && is(typeof(.startsWith!pred(doesThisStart, withOneOfThese[0]))
3448                 : bool)
3449         && is(typeof(.startsWith!pred(doesThisStart, withOneOfThese[1 .. $]))
3450                 : uint))
3451 {
3452     alias doesThisStart lhs;
3453     alias withOneOfThese rhs;
3454
3455     // Make one pass looking for empty ranges
3456     foreach (i, Unused; Ranges)
3457     {
3458         // Empty range matches everything
3459         static if (!is(typeof(binaryFun!pred(lhs.front, rhs[i])) : bool))
3460         {
3461             if (rhs[i].empty) return i + 1;
3462         }
3463     }
3464
3465     for (; !lhs.empty; lhs.popFront())
3466     {
3467         foreach (i, Unused; Ranges)
3468         {
3469             static if (is(typeof(binaryFun!pred(lhs.front, rhs[i])) : bool))
3470             {
3471                 // Single-element
3472                 if (binaryFun!pred(lhs.front, rhs[i]))
3473                 {
3474                     // found, but continue to account for one-element
3475                     // range matches (consider startsWith("ab", "a",
3476                     // 'a') should return 1, not 2).
3477                     continue;
3478                 }
3479             }
3480             else
3481             {
3482                 if (binaryFun!pred(lhs.front, rhs[i].front))
3483                 {
3484                     continue;
3485                 }
3486             }
3487             // This code executed on failure to match
3488             // Out with this guy, check for the others
3489             uint result = startsWith!pred(lhs, rhs[0 .. i], rhs[i + 1 .. $]);
3490             if (result > i) ++result;
3491             return result;
3492         }
3493
3494         // If execution reaches this point, then the front matches for all
3495         // rhs ranges. What we need to do now is to lop off the front of
3496         // all ranges involved and recurse.
3497         foreach (i, Unused; Ranges)
3498         {
3499             static if (is(typeof(binaryFun!pred(lhs.front, rhs[i])) : bool))
3500             {
3501                 // Test has passed in the previous loop
3502                 return i + 1;
3503             }
3504             else
3505             {
3506                 rhs[i].popFront();
3507                 if (rhs[i].empty) return i + 1;
3508             }
3509         }
3510     }
3511     return 0;
3512 }
3513
3514
3515 /// Ditto
3516 bool startsWith(alias pred = "a == b", R1, R2)
3517 (R1 doesThisStart, R2 withThis)
3518 if (isInputRange!R1 && isInputRange!R2
3519         && is(typeof(binaryFun!pred(doesThisStart.front, withThis.front))
3520                 : bool))
3521 {
3522     // Special  case for two arrays
3523     static if (isArray!R1 && isArray!R2)
3524     {
3525         alias doesThisStart haystack;
3526         alias withThis needle;
3527         //writeln("Matching: ", haystack, " with ", needle);
3528         if (haystack.length < needle.length) return 0;
3529         foreach (j; 0 .. needle.length)
3530         {
3531             if (!binaryFun!pred(needle[j], haystack[j]))
3532                 // not found
3533                 return false;
3534         }
3535         // found!
3536         return true;
3537     }
3538     else
3539     {
3540         static if (hasLength!R1 && hasLength!R2)
3541         {
3542             if (doesThisStart.length < withThis.length) return false;
3543         }
3544         if (withThis.empty) return true;
3545         for (; !doesThisStart.empty; doesThisStart.popFront())
3546         {
3547             if (!binaryFun!pred(doesThisStart.front, withThis.front))
3548                 break;
3549             withThis.popFront();
3550             if (withThis.empty) return true;
3551         }
3552         return false;
3553     }
3554 }
3555
3556 /// Ditto
3557 bool startsWith(alias pred = "a == b", R, E)
3558 (R doesThisStart, E withThis)
3559 if (isInputRange!R && is(typeof(binaryFun!pred(doesThisStart.front, withThis))
3560                 : bool))
3561 {
3562     return doesThisStart.empty
3563         ? false
3564         : binaryFun!pred(doesThisStart.front, withThis);
3565 }
3566
3567 unittest
3568 {
3569     debug(std_algorithm) scope(success)
3570         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
3571     bool x = startsWith("ab", "a");
3572     assert(startsWith("abc", ""));
3573     assert(startsWith("abc", "a"));
3574     assert(!startsWith("abc", "b"));
3575     assert(!startsWith("abc", "b", "bc", "abcd", "xyz"));
3576     assert(startsWith("abc", "a", "b") == 1);
3577     assert(startsWith("abc", "b", "a") == 2);
3578     assert(startsWith("abc", "a", 'a') == 1);
3579     assert(startsWith("abc", 'a', "a") == 1);
3580     assert(startsWith("abc", "x", "a", "b") == 2);
3581     assert(startsWith("abc", "x", "aa", "ab") == 3);
3582     assert(startsWith("abc", "x", "aaa", "sab") == 0);
3583     assert(startsWith("abc", 'a'));
3584     assert(!startsWith("abc", "sab"));
3585     assert(startsWith("abc", 'x', "aaa", 'a', "sab") == 3);
3586 }
3587
3588 unittest
3589 {
3590     debug(std_algorithm) scope(success)
3591         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
3592     assert(!startsWith("abc", 'x', 'n', 'b'));
3593     assert(startsWith("abc", 'x', 'n', 'a') == 3);
3594 }
3595
3596 /**
3597 If $(D startsWith(r1, r2)), consume the corresponding elements off $(D
3598 r1) and return $(D true). Otherwise, leave $(D r1) unchanged and
3599 return $(D false).
3600  */
3601 bool skipOver(alias pred = "a == b", R1, R2)(ref R1 r1, R2 r2)
3602 if (is(typeof(binaryFun!pred(r1.front, r2.front))))
3603 {
3604     auto r = r1.save;
3605     while (!r2.empty && !r.empty && binaryFun!pred(r.front, r2.front))
3606     {
3607         r.popFront();
3608         r2.popFront();
3609     }
3610     return r2.empty ? (r1 = r, true) : false;
3611 }
3612
3613 unittest
3614 {
3615     //scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done.");
3616     auto s1 = "Hello world";
3617     assert(!skipOver(s1, "Ha"));
3618     assert(s1 == "Hello world");
3619     assert(skipOver(s1, "Hell") && s1 == "o world");
3620 }
3621
3622 /**
3623 Checks whether a range starts with an element, and if so, consume that
3624 element off $(D r) and return $(D true). Otherwise, leave $(D r)
3625 unchanged and return $(D false).
3626  */
3627 bool skipOver(alias pred = "a == b", R, E)(ref R r, E e)
3628 if (is(typeof(binaryFun!pred(r.front, e))))
3629 {
3630     return binaryFun!pred(r.front, e)
3631         ? (r.popFront(), true)
3632         : false;
3633 }
3634
3635 unittest {
3636     auto s1 = "Hello world";
3637     assert(!skipOver(s1, "Ha"));
3638     assert(s1 == "Hello world");
3639     assert(skipOver(s1, "Hell") && s1 == "o world");
3640 }
3641
3642 /* (Not yet documented.)
3643 Consume all elements from $(D r) that are equal to one of the elements
3644 $(D es).
3645  */
3646 void skipAll(alias pred = "a == b", R, Es...)(ref R r, Es es)
3647 //if (is(typeof(binaryFun!pred(r1.front, es[0]))))
3648 {
3649   loop:
3650     for (; !r.empty; r.popFront())
3651     {
3652         foreach (i, E; Es)
3653         {
3654             if (binaryFun!pred(r.front, es[i]))
3655             {
3656                 continue loop;
3657             }
3658         }
3659         break;
3660     }
3661 }
3662
3663 unittest
3664 {
3665     //scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done.");
3666     auto s1 = "Hello world";
3667     skipAll(s1, 'H', 'e');
3668     assert(s1 == "llo world");
3669 }
3670
3671 /**
3672 The reciprocal of $(D startsWith).
3673
3674 Example:
3675 ----
3676 assert(endsWith("abc", ""));
3677 assert(!endsWith("abc", "b"));
3678 assert(endsWith("abc", "a", 'c') == 2);
3679 assert(endsWith("abc", "c", "a") == 1);
3680 assert(endsWith("abc", "c", "c") == 1);
3681 assert(endsWith("abc", "x", "c", "b") == 2);
3682 assert(endsWith("abc", "x", "aa", "bc") == 3);
3683 assert(endsWith("abc", "x", "aaa", "sab") == 0);
3684 assert(endsWith("abc", "x", "aaa", 'c', "sab") == 3);
3685 ----
3686  */
3687 uint
3688 endsWith(alias pred = "a == b", Range, Ranges...)
3689 (Range doesThisEnd, Ranges withOneOfThese)
3690 if (isInputRange!(Range) && Ranges.length > 0
3691         && is(typeof(binaryFun!pred(doesThisEnd.back, withOneOfThese[0].back))))
3692 {
3693     alias doesThisEnd lhs;
3694     alias withOneOfThese rhs;
3695     // Special  case for two arrays
3696     static if (Ranges.length == 1 && isArray!Range && isArray!(Ranges[0])
3697             && is(typeof(binaryFun!(pred)(lhs[0], rhs[0][0]))))
3698     {
3699         if (lhs.length < rhs[0].length) return 0;
3700         auto k = lhs.length - rhs[0].length;
3701         foreach (j; 0 .. rhs[0].length)
3702         {
3703             if (!binaryFun!(pred)(rhs[0][j], lhs[j + k]))
3704                 // not found
3705                 return 0u;
3706         }
3707         // found!
3708         return 1u;
3709     }
3710     else
3711     {
3712         // Make one pass looking for empty ranges
3713         foreach (i, Unused; Ranges)
3714         {
3715             // Empty range matches everything
3716             if (rhs[i].empty) return i + 1;
3717         }
3718         bool mismatch[Ranges.length];
3719         for (; !lhs.empty; lhs.popBack)
3720         {
3721             foreach (i, Unused; Ranges)
3722             {
3723                 if (mismatch[i]) continue;
3724                 if (binaryFun!pred(lhs.back, rhs[i].back))
3725                 {
3726                     // Stay in the game
3727                     rhs[i].popBack();
3728                     // Done with success if exhausted
3729                     if (rhs[i].empty) return i + 1;
3730                 }
3731                 else
3732                 {
3733                     // Out
3734                     mismatch[i] = true;
3735                 }
3736             }
3737         }
3738         return 0;
3739     }
3740 }
3741
3742 unittest
3743 {
3744     debug(std_algorithm) scope(success)
3745         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
3746     assert(endsWith("abc", ""));
3747     assert(!endsWith("abc", "a"));
3748     assert(!endsWith("abc", 'a'));
3749     assert(!endsWith("abc", "b"));
3750     assert(endsWith("abc", "a", "c") == 2);
3751     assert(endsWith("abc", 'a', 'c') == 2);
3752     assert(endsWith("abc", "c", "a") == 1);
3753     assert(endsWith("abc", "c", "c") == 1);
3754     assert(endsWith("abc", "x", "c", "b") == 2);
3755     assert(endsWith("abc", "x", "aa", "bc") == 3);
3756     assert(endsWith("abc", "x", "aaa", "sab") == 0);
3757     assert(endsWith("abc", "x", "aaa", "c", "sab") == 3);
3758     // string a = "abc";
3759     // immutable(char[1]) b = "c";
3760     // assert(wyda(a, b));
3761 }
3762
3763 /**
3764 Checks whether $(D doesThisEnd) starts with one of the individual
3765 elements $(D withOneOfThese) according to $(D pred).
3766
3767 Example:
3768 ----
3769 assert(endsWith("abc", 'x', 'c', 'a') == 2);
3770 ----
3771  */
3772 uint endsWith(alias pred = "a == b", Range, Elements...)
3773 (Range doesThisEnd, Elements withOneOfThese)
3774 if (isInputRange!Range && Elements.length > 0
3775         && is(typeof(binaryFun!pred(doesThisEnd.front, withOneOfThese[0]))))
3776 {
3777     if (doesThisEnd.empty) return 0;
3778     auto back = doesThisEnd.back;
3779     foreach (i, Unused; Elements)
3780     {
3781         if (binaryFun!pred(back, withOneOfThese[i])) return i + 1;
3782     }
3783     return 0;
3784 }
3785
3786 unittest
3787 {
3788     debug(std_algorithm) scope(success)
3789         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
3790     assert(!startsWith("abc", 'x', 'n', 'b'));
3791     assert(startsWith("abc", 'x', 'n', 'a') == 3);
3792 }
3793
3794 // findAdjacent
3795 /**
3796 Advances $(D r) until it finds the first two adjacent elements $(D a),
3797 $(D b) that satisfy $(D pred(a, b)). Performs $(BIGOH r.length)
3798 evaluations of $(D pred). See also $(WEB
3799 sgi.com/tech/stl/adjacent_find.html, STL's adjacent_find).
3800
3801 Example:
3802 ----
3803 int[] a = [ 11, 10, 10, 9, 8, 8, 7, 8, 9 ];
3804 auto r = findAdjacent(a);
3805 assert(r == [ 10, 10, 9, 8, 8, 7, 8, 9 ]);
3806 p = findAdjacent!("a < b")(a);
3807 assert(p == [ 7, 8, 9 ]);
3808 ----
3809 */
3810 Range findAdjacent(alias pred = "a == b", Range)(Range r)
3811     if (isForwardRange!(Range))
3812 {
3813     auto ahead = r;
3814     if (!ahead.empty)
3815     {
3816         for (ahead.popFront; !ahead.empty; r.popFront, ahead.popFront)
3817         {
3818             if (binaryFun!(pred)(r.front, ahead.front)) return r;
3819         }
3820     }
3821     return ahead;
3822 }
3823
3824 unittest
3825 {
3826     //scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done.");
3827     int[] a = [ 11, 10, 10, 9, 8, 8, 7, 8, 9 ];
3828     auto p = findAdjacent(a);
3829     assert(p == [10, 10, 9, 8, 8, 7, 8, 9 ]);
3830     p = findAdjacent!("a < b")(a);
3831     assert(p == [7, 8, 9]);
3832     // empty
3833     a = [];
3834     p = findAdjacent(a);
3835     assert(p.empty);
3836     // not found
3837     a = [ 1, 2, 3, 4, 5 ];
3838     p = findAdjacent(a);
3839     assert(p.empty);
3840     p = findAdjacent!"a > b"(a);
3841     assert(p.empty);
3842 }
3843
3844 // findAmong
3845 /**
3846 Advances $(D seq) by calling $(D seq.popFront) until either $(D
3847 find!(pred)(choices, seq.front)) is $(D true), or $(D seq) becomes
3848 empty. Performs $(BIGOH seq.length * choices.length) evaluations of
3849 $(D pred). See also $(WEB sgi.com/tech/stl/find_first_of.html, STL's
3850 find_first_of).
3851
3852 Example:
3853 ----
3854 int[] a = [ -1, 0, 1, 2, 3, 4, 5 ];
3855 int[] b = [ 3, 1, 2 ];
3856 assert(findAmong(a, b) == a[2 .. $]);
3857 ----
3858 */
3859 Range1 findAmong(alias pred = "a == b", Range1, Range2)(
3860     Range1 seq, Range2 choices)
3861     if (isInputRange!Range1 && isForwardRange!Range2)
3862 {
3863     for (; !seq.empty && find!pred(choices, seq.front).empty; seq.popFront)
3864     {
3865     }
3866     return seq;
3867 }
3868
3869 unittest
3870 {
3871     //scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done.");
3872     int[] a = [ -1, 0, 2, 1, 2, 3, 4, 5 ];
3873     int[] b = [ 1, 2, 3 ];
3874     assert(findAmong(a, b) == [2, 1, 2, 3, 4, 5 ]);
3875     assert(findAmong(b, [ 4, 6, 7 ][]).empty);
3876     assert(findAmong!("a==b")(a, b).length == a.length - 2);
3877     assert(findAmong!("a==b")(b, [ 4, 6, 7 ][]).empty);
3878 }
3879
3880 // count
3881 /**
3882 The first version counts the number of elements $(D x) in $(D r) for
3883 which $(D pred(x, value)) is $(D true). $(D pred) defaults to
3884 equality. Performs $(BIGOH r.length) evaluations of $(D pred).
3885
3886 The second version returns the number of times $(D needle) occurs in
3887 $(D haystack). Throws an exception if $(D needle.empty), as the _count
3888 of the empty range in any range would be infinite. Overlapped counts
3889 are not considered, for example $(D count("aaa", "aa")) is $(D 1), not
3890 $(D 2).
3891
3892 The third version counts the elements for which $(D pred(x)) is $(D
3893 true). Performs $(BIGOH r.length) evaluations of $(D pred).
3894
3895 Example:
3896 ----
3897 // count elements in range
3898 int[] a = [ 1, 2, 4, 3, 2, 5, 3, 2, 4 ];
3899 assert(count(a, 2) == 3);
3900 assert(count!("a > b")(a, 2) == 5);
3901 // count range in range
3902 assert(count("abcadfabf", "ab") == 2);
3903 assert(count("ababab", "abab") == 1);
3904 assert(count("ababab", "abx") == 0);
3905 // count predicate in range
3906 assert(count!("a > 1")(a) == 8);
3907 ----
3908 */
3909 size_t count(alias pred = "a == b", Range, E)(Range r, E value)
3910 if (isInputRange!Range && is(typeof(binaryFun!pred(r.front, value)) == bool))
3911 {
3912     bool pred2(ElementType!(Range) a) { return binaryFun!pred(a, value); }
3913     return count!(pred2)(r);
3914 }
3915
3916 unittest
3917 {
3918     debug(std_algorithm) scope(success)
3919         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
3920     int[] a = [ 1, 2, 4, 3, 2, 5, 3, 2, 4 ];
3921     assert(count(a, 2) == 3, text(count(a, 2)));
3922     assert(count!("a > b")(a, 2) == 5, text(count!("a > b")(a, 2)));
3923
3924     // check strings
3925     assert(count("日本語")  == 3);
3926     assert(count("日本語"w) == 3);
3927     assert(count("日本語"d) == 3);
3928
3929     assert(count!("a == '日'")("日本語")  == 1);
3930     assert(count!("a == '本'")("日本語"w) == 1);
3931     assert(count!("a == '語'")("日本語"d) == 1);
3932 }
3933
3934 unittest
3935 {
3936     debug(std_algorithm) printf("algorithm.count.unittest\n");
3937     string s = "This is a fofofof list";
3938     string sub = "fof";
3939     assert(count(s, sub) == 2);
3940 }
3941
3942 /// Ditto
3943 size_t count(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
3944 if (isInputRange!R1 && isForwardRange!R2 && is(typeof(binaryFun!pred(haystack, needle)) == bool))
3945 {
3946     enforce(!needle.empty, "Cannot count occurrences of an empty range");
3947     size_t result;
3948     for (; findSkip!pred(haystack, needle); ++result)
3949     {
3950     }
3951     return result;
3952 }
3953
3954 unittest
3955 {
3956     assert(count("abcadfabf", "ab") == 2);
3957     assert(count("ababab", "abab") == 1);
3958     assert(count("ababab", "abx") == 0);
3959 }
3960
3961 /// Ditto
3962 size_t count(alias pred = "true", Range)(Range r) if (isInputRange!(Range))
3963 {
3964     size_t result;
3965     for (; !r.empty; r.popFront())
3966     {
3967         if (unaryFun!pred(r.front)) ++result;
3968     }
3969     return result;
3970 }
3971
3972 unittest
3973 {
3974     debug(std_algorithm) scope(success)
3975         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
3976     int[] a = [ 1, 2, 4, 3, 2, 5, 3, 2, 4 ];
3977     assert(count!("a == 3")(a) == 2);
3978 }
3979
3980 // balancedParens
3981 /**
3982 Checks whether $(D r) has "balanced parentheses", i.e. all instances
3983 of $(D lPar) are closed by corresponding instances of $(D rPar). The
3984 parameter $(D maxNestingLevel) controls the nesting level allowed. The
3985 most common uses are the default or $(D 0). In the latter case, no
3986 nesting is allowed.
3987
3988 Example:
3989 ----
3990 auto s = "1 + (2 * (3 + 1 / 2)";
3991 assert(!balancedParens(s, '(', ')'));
3992 s = "1 + (2 * (3 + 1) / 2)";
3993 assert(balancedParens(s, '(', ')'));
3994 s = "1 + (2 * (3 + 1) / 2)";
3995 assert(!balancedParens(s, '(', ')', 1));
3996 s = "1 + (2 * 3 + 1) / (2 - 5)";
3997 assert(balancedParens(s, '(', ')', 1));
3998 ----
3999 */
4000
4001 bool balancedParens(Range, E)(Range r, E lPar, E rPar,
4002         size_t maxNestingLevel = size_t.max)
4003 if (isInputRange!(Range) && is(typeof(r.front == lPar)))
4004 {
4005     size_t count;
4006     for (; !r.empty; r.popFront())
4007     {
4008         if (r.front == lPar)
4009         {
4010             if (count > maxNestingLevel) return false;
4011             ++count;
4012         }
4013         else if (r.front == rPar)
4014         {
4015             if (!count) return false;
4016             --count;
4017         }
4018     }
4019     return count == 0;
4020 }
4021
4022 unittest
4023 {
4024     auto s = "1 + (2 * (3 + 1 / 2)";
4025     assert(!balancedParens(s, '(', ')'));
4026     s = "1 + (2 * (3 + 1) / 2)";
4027     assert(balancedParens(s, '(', ')'));
4028     s = "1 + (2 * (3 + 1) / 2)";
4029     assert(!balancedParens(s, '(', ')', 0));
4030     s = "1 + (2 * 3 + 1) / (2 - 5)";
4031     assert(balancedParens(s, '(', ')', 0));
4032 }
4033
4034 // equal
4035 /**
4036 Returns $(D true) if and only if the two ranges compare equal element
4037 for element, according to binary predicate $(D pred). The ranges may
4038 have different element types, as long as $(D pred(a, b)) evaluates to
4039 $(D bool) for $(D a) in $(D r1) and $(D b) in $(D r2). Performs
4040 $(BIGOH min(r1.length, r2.length)) evaluations of $(D pred). See also
4041 $(WEB sgi.com/tech/stl/_equal.html, STL's equal).
4042
4043 Example:
4044 ----
4045 int[] a = [ 1, 2, 4, 3 ];
4046 assert(!equal(a, a[1..$]));
4047 assert(equal(a, a));
4048
4049 // different types
4050 double[] b = [ 1., 2, 4, 3];
4051 assert(!equal(a, b[1..$]));
4052 assert(equal(a, b));
4053
4054 // predicated: ensure that two vectors are approximately equal
4055 double[] c = [ 1.005, 2, 4, 3];
4056 assert(equal!(approxEqual)(b, c));
4057 ----
4058 */
4059 bool equal(alias pred = "a == b", Range1, Range2)(Range1 r1, Range2 r2)
4060 if (isInputRange!(Range1) && isInputRange!(Range2)
4061         && is(typeof(binaryFun!pred(r1.front, r2.front))))
4062 {
4063     foreach (e1; r1)
4064     {
4065         if (r2.empty) return false;
4066         if (!binaryFun!(pred)(e1, r2.front)) return false;
4067         r2.popFront;
4068     }
4069     return r2.empty;
4070 }
4071
4072 unittest
4073 {
4074     debug(std_algorithm) scope(success)
4075         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
4076     int[] a = [ 1, 2, 4, 3];
4077     assert(!equal(a, a[1..$]));
4078     assert(equal(a, a));
4079     // test with different types
4080     double[] b = [ 1., 2, 4, 3];
4081     assert(!equal(a, b[1..$]));
4082     assert(equal(a, b));
4083
4084     // predicated
4085     double[] c = [ 1.005, 2, 4, 3];
4086     assert(equal!(approxEqual)(b, c));
4087 }
4088
4089 // cmp
4090 /**********************************
4091 Performs three-way lexicographical comparison on two input ranges
4092 according to predicate $(D pred). Iterating $(D r1) and $(D r2) in
4093 lockstep, $(D cmp) compares each element $(D e1) of $(D r1) with the
4094 corresponding element $(D e2) in $(D r2). If $(D binaryFun!pred(e1,
4095 e2)), $(D cmp) returns a negative value. If $(D binaryFun!pred(e2,
4096 e1)), $(D cmp) returns a positive value. If one of the ranges has been
4097 finished, $(D cmp) returns a negative value if $(D r1) has fewer
4098 elements than $(D r2), a positive value if $(D r1) has more elements
4099 than $(D r2), and $(D 0) if the ranges have the same number of
4100 elements.
4101
4102 If the ranges are strings, $(D cmp) performs UTF decoding
4103 appropriately and compares the ranges one code point at a time.
4104 */
4105
4106 int cmp(alias pred = "a < b", R1, R2)(R1 r1, R2 r2)
4107 if (isInputRange!R1 && isInputRange!R2 && !(isSomeString!R1 && isSomeString!R2))
4108 {
4109     for (;; r1.popFront(), r2.popFront())
4110     {
4111         if (r1.empty) return -r2.empty;
4112         if (r2.empty) return r1.empty;
4113         auto a = r1.front, b = r2.front;
4114         if (binaryFun!pred(a, b)) return -1;
4115         if (binaryFun!pred(b, a)) return 1;
4116     }
4117 }
4118
4119 // Specialization for strings (for speed purposes)
4120 int cmp(alias pred = "a < b", R1, R2)(R1 r1, R2 r2) if (isSomeString!R1 && isSomeString!R2)
4121 {
4122     enum isLessThan = is(pred : string) && pred == "a < b";
4123     // For speed only
4124     static int threeWay(size_t a, size_t b)
4125     {
4126         static if (size_t.sizeof == int.sizeof && isLessThan)
4127             return a - b;
4128         else
4129             return binaryFun!pred(b, a) ? 1 : binaryFun!pred(a, b) ? -1 : 0;
4130     }
4131     // For speed only
4132     // @@@BUG@@@ overloading should be allowed for nested functions
4133     static int threeWayInt(int a, int b)
4134     {
4135         static if (isLessThan)
4136             return a - b;
4137         else
4138             return binaryFun!pred(b, a) ? 1 : binaryFun!pred(a, b) ? -1 : 0;
4139     }
4140    
4141     static if (typeof(r1[0]).sizeof == typeof(r2[0]).sizeof && isLessThan)
4142     {
4143         static if (typeof(r1[0]).sizeof == 1)
4144         {
4145             immutable len = min(r1.length, r2.length);
4146             immutable result = std.c.string.memcmp(r1.ptr, r2.ptr, len);
4147             if (result) return result;
4148         }
4149         else
4150         {
4151             auto p1 = r1.ptr, p2 = r2.ptr,
4152                 pEnd = p1 + min(r1.length, r2.length);
4153             for (; p1 != pEnd; ++p1, ++p2)
4154             {
4155                 if (*p1 != *p2) return threeWayInt(cast(int) *p1, cast(int) *p2);
4156             }
4157         }
4158         return threeWay(r1.length, r2.length);
4159     }
4160     else
4161     {
4162         for (size_t i1, i2;;)
4163         {
4164             if (i1 == r1.length) return threeWay(i2, r2.length);
4165             if (i2 == r2.length) return threeWay(r1.length, i1);
4166             immutable c1 = std.utf.decode(r1, i1),
4167                 c2 = std.utf.decode(r2, i2);
4168             if (c1 != c2) return threeWayInt(cast(int) c1, cast(int) c2);
4169         }
4170     }
4171 }
4172
4173 unittest
4174 {
4175     int result;
4176
4177     debug(string) printf("string.cmp.unittest\n");
4178     result = cmp("abc", "abc");
4179     assert(result == 0);
4180     //    result = cmp(null, null);
4181     //    assert(result == 0);
4182     result = cmp("", "");
4183     assert(result == 0);
4184     result = cmp("abc", "abcd");
4185     assert(result < 0);
4186     result = cmp("abcd", "abc");
4187     assert(result > 0);
4188     result = cmp("abc"d, "abd");
4189     assert(result < 0);
4190     result = cmp("bbc", "abc"w);
4191     assert(result > 0);
4192     result = cmp("aaa", "aaaa"d);
4193     assert(result < 0);
4194     result = cmp("aaaa", "aaa"d);
4195     assert(result > 0);
4196     result = cmp("aaa", "aaa"d);
4197     assert(result == 0);
4198 }
4199
4200 // MinType
4201 template MinType(T...)
4202 {
4203     static assert(T.length >= 2);
4204     static if (T.length == 2)
4205     {
4206         static if (!is(typeof(T[0].min)))
4207             alias CommonType!(T[0 .. 2]) MinType;
4208         else static if (mostNegative!(T[1]) < mostNegative!(T[0]))
4209             alias T[1] MinType;
4210         else static if (mostNegative!(T[1]) > mostNegative!(T[0]))
4211             alias T[0] MinType;
4212         else static if (T[1].max < T[0].max)
4213             alias T[1] MinType;
4214         else
4215             alias T[0] MinType;
4216     }
4217     else
4218     {
4219         alias MinType!(MinType!(T[0 .. 2]), T[2 .. $]) MinType;
4220     }
4221 }
4222
4223 // min
4224 /**
4225 Returns the minimum of the passed-in values. The type of the result is
4226 computed by using $(XREF traits, CommonType).
4227 */
4228 MinType!(T1, T2, T) min(T1, T2, T...)(T1 a, T2 b, T xs)
4229 {
4230     static if (T.length == 0)
4231     {
4232         static if (isIntegral!(T1) && isIntegral!(T2)
4233                    && (mostNegative!(T1) < 0) != (mostNegative!(T2) < 0))
4234             static if (mostNegative!(T1) < 0)
4235                 immutable chooseB = b < a && a > 0;
4236             else
4237                 immutable chooseB = b < a || b < 0;
4238         else
4239                 immutable chooseB = b < a;
4240         return cast(typeof(return)) (chooseB ? b : a);
4241     }
4242     else
4243     {
4244         return min(min(a, b), xs);
4245     }
4246 }
4247
4248 unittest
4249 {
4250     debug(std_algorithm) scope(success)
4251         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
4252     int a = 5;
4253     short b = 6;
4254     double c = 2;
4255     auto d = min(a, b);
4256     assert(is(typeof(d) == int));
4257     assert(d == 5);
4258     auto e = min(a, b, c);
4259     assert(is(typeof(e) == double));
4260     assert(e == 2);
4261     // mixed signedness test
4262     a = -10;
4263     uint f = 10;
4264     static assert(is(typeof(min(a, f)) == int));
4265     assert(min(a, f) == -10);
4266 }
4267
4268 // MaxType
4269 template MaxType(T...)
4270 {
4271     static assert(T.length >= 2);
4272     static if (T.length == 2)
4273     {
4274         static if (!is(typeof(T[0].min)))
4275             alias CommonType!(T[0 .. 2]) MaxType;
4276         else static if (T[1].max > T[0].max)
4277             alias T[1] MaxType;
4278         else
4279             alias T[0] MaxType;
4280     }
4281     else
4282     {
4283         alias MaxType!(MaxType!(T[0], T[1]), T[2 .. $]) MaxType;
4284     }
4285 }
4286
4287 // max
4288 /**
4289 Returns the maximum of the passed-in values. The type of the result is
4290 computed by using $(XREF traits, CommonType).
4291
4292 Example:
4293 ----
4294 int a = 5;
4295 short b = 6;
4296 double c = 2;
4297 auto d = max(a, b);
4298 assert(is(typeof(d) == int));
4299 assert(d == 6);
4300 auto e = min(a, b, c);
4301 assert(is(typeof(e) == double));
4302 assert(e == 2);
4303 ----
4304 */
4305 MaxType!(T1, T2, T) max(T1, T2, T...)(T1 a, T2 b, T xs)
4306 {
4307     static if (T.length == 0)
4308     {
4309         static if (isIntegral!(T1) && isIntegral!(T2)
4310                    && (mostNegative!(T1) < 0) != (mostNegative!(T2) < 0))
4311             static if (mostNegative!(T1) < 0)
4312                 immutable chooseB = b > a || a < 0;
4313             else
4314                 immutable chooseB = b > a && b > 0;
4315         else
4316             immutable chooseB = b > a;
4317         return cast(typeof(return)) (chooseB ? b : a);
4318     }
4319     else
4320     {
4321         return max(max(a, b), xs);
4322     }
4323 }
4324
4325 unittest
4326 {
4327     debug(std_algorithm) scope(success)
4328         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
4329     int a = 5;
4330     short b = 6;
4331     double c = 2;
4332     auto d = max(a, b);
4333     assert(is(typeof(d) == int));
4334     assert(d == 6);
4335     auto e = max(a, b, c);
4336     assert(is(typeof(e) == double));
4337     assert(e == 6);
4338     // mixed sign
4339     a = -5;
4340     uint f = 5;
4341     static assert(is(typeof(max(a, f)) == uint));
4342     assert(max(a, f) == 5);
4343 }
4344
4345 /**
4346 Returns the minimum element of a range together with the number of
4347 occurrences. The function can actually be used for counting the
4348 maximum or any other ordering predicate (that's why $(D maxCount) is
4349 not provided).
4350
4351 Example:
4352 ----
4353 int[] a = [ 2, 3, 4, 1, 2, 4, 1, 1, 2 ];
4354 // Minimum is 1 and occurs 3 times
4355 assert(minCount(a) == tuple(1, 3));
4356 // Maximum is 4 and occurs 2 times
4357 assert(minCount!("a > b")(a) == tuple(4, 2));
4358 ----
4359  */
4360 Tuple!(ElementType!(Range), size_t)
4361 minCount(alias pred = "a < b", Range)(Range range)
4362 {
4363     if (range.empty) return typeof(return)();
4364     auto p = &(range.front());
4365     size_t occurrences = 1;
4366     for (range.popFront; !range.empty; range.popFront)
4367     {
4368         if (binaryFun!(pred)(*p, range.front)) continue;
4369         if (binaryFun!(pred)(range.front, *p))
4370         {
4371             // change the min
4372             p = &(range.front());
4373             occurrences = 1;
4374         }
4375         else
4376         {
4377             ++occurrences;
4378         }
4379     }
4380     return tuple(*p, occurrences);
4381 }
4382
4383 unittest
4384 {
4385     debug(std_algorithm) scope(success)
4386         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
4387     int[] a = [ 2, 3, 4, 1, 2, 4, 1, 1, 2 ];
4388     assert(minCount(a) == tuple(1, 3));
4389     assert(minCount!("a > b")(a) == tuple(4, 2));
4390     int[][] b = [ [4], [2, 4], [4], [4] ];
4391     auto c = minCount!("a[0] < b[0]")(b);
4392     assert(c == tuple([2, 4], 1), text(c[0]));
4393 }
4394
4395 // minPos
4396 /**
4397 Returns the position of the minimum element of forward range $(D
4398 range), i.e. a subrange of $(D range) starting at the position of its
4399 smallest element and with the same ending as $(D range). The function
4400 can actually be used for counting the maximum or any other ordering
4401 predicate (that's why $(D maxPos) is not provided).
4402
4403 Example:
4404 ----
4405 int[] a = [ 2, 3, 4, 1, 2, 4, 1, 1, 2 ];
4406 // Minimum is 1 and first occurs in position 3
4407 assert(minPos(a) == [ 1, 2, 4, 1, 1, 2 ]);
4408 // Maximum is 4 and first occurs in position 2
4409 assert(minPos!("a > b")(a) == [ 4, 1, 2, 4, 1, 1, 2 ]);
4410 ----
4411  */
4412 Range minPos(alias pred = "a < b", Range)(Range range)
4413 {
4414     if (range.empty) return range;
4415     auto result = range;
4416     for (range.popFront; !range.empty; range.popFront)
4417     {
4418         if (binaryFun!(pred)(result.front, range.front)
4419                 || !binaryFun!(pred)(range.front, result.front)) continue;
4420         // change the min
4421         result = range;
4422     }
4423     return result;
4424 }
4425
4426 unittest
4427 {
4428     debug(std_algorithm) scope(success)
4429         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
4430     int[] a = [ 2, 3, 4, 1, 2, 4, 1, 1, 2 ];
4431 // Minimum is 1 and first occurs in position 3
4432     assert(minPos(a) == [ 1, 2, 4, 1, 1, 2 ]);
4433 // Maximum is 4 and first occurs in position 5
4434     assert(minPos!("a > b")(a) == [ 4, 1, 2, 4, 1, 1, 2 ]);
4435 }
4436
4437 // mismatch
4438 /**
4439 Sequentially compares elements in $(D r1) and $(D r2) in lockstep, and
4440 stops at the first mismatch (according to $(D pred), by default
4441 equality). Returns a tuple with the reduced ranges that start with the
4442 two mismatched values. Performs $(BIGOH min(r1.length, r2.length))
4443 evaluations of $(D pred). See also $(WEB
4444 sgi.com/tech/stl/_mismatch.html, STL's mismatch).
4445
4446 Example:
4447 ----
4448 int[]    x = [ 1,  5, 2, 7,   4, 3 ];
4449 double[] y = [ 1., 5, 2, 7.3, 4, 8 ];
4450 auto m = mismatch(x, y);
4451 assert(m[0] == x[3 .. $]);
4452 assert(m[1] == y[3 .. $]);
4453 ----
4454 */
4455
4456 Tuple!(Range1, Range2)
4457 mismatch(alias pred = "a == b", Range1, Range2)(Range1 r1, Range2 r2)
4458     if (isInputRange!(Range1) && isInputRange!(Range2))
4459 {
4460     for (; !r1.empty && !r2.empty; r1.popFront(), r2.popFront())
4461     {
4462         if (!binaryFun!(pred)(r1.front, r2.front)) break;
4463     }
4464     return tuple(r1, r2);
4465 }
4466
4467 unittest
4468 {
4469     debug(std_algorithm) scope(success)
4470         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
4471     // doc example
4472     int[]    x = [ 1,  5, 2, 7,   4, 3 ];
4473     double[] y = [ 1., 5, 2, 7.3, 4, 8 ];
4474     auto m = mismatch(x, y);
4475     assert(m[0] == [ 7, 4, 3 ]);
4476     assert(m[1] == [ 7.3, 4, 8 ]);
4477
4478     int[] a = [ 1, 2, 3 ];
4479     int[] b = [ 1, 2, 4, 5 ];
4480     auto mm = mismatch(a, b);
4481     assert(mm[0] == [3]);
4482     assert(mm[1] == [4, 5]);
4483 }
4484
4485 // levenshteinDistance
4486 /**
4487 Encodes $(WEB realityinteractive.com/rgrzywinski/archives/000249.html,
4488 edit operations) necessary to transform one sequence into
4489 another. Given sequences $(D s) (source) and $(D t) (target), a
4490 sequence of $(D EditOp) encodes the steps that need to be taken to
4491 convert $(D s) into $(D t). For example, if $(D s = "cat") and $(D
4492 "cars"), the minimal sequence that transforms $(D s) into $(D t) is:
4493 skip two characters, replace 't' with 'r', and insert an 's'. Working
4494 with edit operations is useful in applications such as spell-checkers
4495 (to find the closest word to a given misspelled word), approximate
4496 searches, diff-style programs that compute the difference between
4497 files, efficient encoding of patches, DNA sequence analysis, and
4498 plagiarism detection.
4499 */
4500
4501 enum EditOp : char
4502 {
4503     /** Current items are equal; no editing is necessary. */
4504     none = 'n',
4505     /** Substitute current item in target with current item in source. */
4506     substitute = 's',
4507     /** Insert current item from the source into the target. */
4508     insert = 'i',
4509     /** Remove current item from the target. */
4510     remove = 'r'
4511 }
4512
4513 struct Levenshtein(Range, alias equals, CostType = size_t)
4514 {
4515     void deletionIncrement(CostType n)
4516     {
4517         _deletionIncrement = n;
4518         InitMatrix();
4519     }
4520
4521     void insertionIncrement(CostType n)
4522     {
4523         _insertionIncrement = n;
4524         InitMatrix();
4525     }
4526
4527     CostType distance(Range s, Range t)
4528     {
4529         auto slen = walkLength(s), tlen = walkLength(t);
4530         AllocMatrix(slen + 1, tlen + 1);
4531         foreach (i; 1 .. rows)
4532         {
4533             auto sfront = s.front;
4534             s.popFront();
4535             auto tt = t;
4536             foreach (j; 1 .. cols)
4537             {
4538                 auto cSub = _matrix[i - 1][j - 1]
4539                     + (equals(sfront, tt.front) ? 0 : _substitutionIncrement);
4540                 tt.popFront();
4541                 auto cIns = _matrix[i][j - 1] + _insertionIncrement;
4542                 auto cDel = _matrix[i - 1][j] + _deletionIncrement;
4543                 switch (min_index(cSub, cIns, cDel)) {
4544                 case 0:
4545                     _matrix[i][j] = cSub;
4546                     break;
4547                 case 1:
4548                     _matrix[i][j] = cIns;
4549                     break;
4550                 default:
4551                     _matrix[i][j] = cDel;
4552                     break;
4553                 }
4554             }
4555         }
4556         return _matrix[slen][tlen];
4557     }
4558
4559     EditOp[] path(Range s, Range t)
4560     {
4561         distance(s, t);
4562         return path();
4563     }
4564
4565     EditOp[] path()
4566     {
4567         EditOp[] result;
4568         size_t i = rows - 1, j = cols - 1;
4569         // restore the path
4570         while (i || j) {
4571             auto cIns = j == 0 ? CostType.max : _matrix[i][j - 1];
4572             auto cDel = i == 0 ? CostType.max : _matrix[i - 1][j];
4573             auto cSub = i == 0 || j == 0
4574                 ? CostType.max
4575                 : _matrix[i - 1][j - 1];
4576             switch (min_index(cSub, cIns, cDel)) {
4577             case 0:
4578                 result ~= _matrix[i - 1][j - 1] == _matrix[i][j]
4579                     ? EditOp.none
4580                     : EditOp.substitute;
4581                 --i;
4582                 --j;
4583                 break;
4584             case 1:
4585                 result ~= EditOp.insert;
4586                 --j;
4587                 break;
4588             default:
4589                 result ~= EditOp.remove;
4590                 --i;
4591                 break;
4592             }
4593         }
4594         reverse(result);
4595         return result;
4596     }
4597
4598 private:
4599     CostType _deletionIncrement = 1,
4600         _insertionIncrement = 1,
4601         _substitutionIncrement = 1;
4602     CostType[][] _matrix;
4603     size_t rows, cols;
4604
4605     void AllocMatrix(size_t r, size_t c) {
4606         rows = r;
4607         cols = c;
4608         if (!_matrix || _matrix.length < r || _matrix[0].length < c) {
4609             delete _matrix;
4610             _matrix = new CostType[][](r, c);
4611             InitMatrix();
4612         }
4613     }
4614
4615     void InitMatrix() {
4616         foreach (i, row; _matrix) {
4617             row[0] = i * _deletionIncrement;
4618         }
4619         if (!_matrix) return;
4620         for (auto i = 0u; i != _matrix[0].length; ++i) {
4621             _matrix[0][i] = i * _insertionIncrement;
4622         }
4623     }
4624
4625     static uint min_index(CostType i0, CostType i1, CostType i2)
4626     {
4627         if (i0 <= i1)
4628         {
4629             return i0 <= i2 ? 0 : 2;
4630         }
4631         else
4632         {
4633             return i1 <= i2 ? 1 : 2;
4634         }
4635     }
4636 }
4637
4638 /**
4639 Returns the $(WEB wikipedia.org/wiki/Levenshtein_distance, Levenshtein
4640 distance) between $(D s) and $(D t). The Levenshtein distance computes
4641 the minimal amount of edit operations necessary to transform $(D s)
4642 into $(D t).  Performs $(BIGOH s.length * t.length) evaluations of $(D
4643 equals) and occupies $(BIGOH s.length * t.length) storage.
4644
4645 Example:
4646 ----
4647 assert(levenshteinDistance("cat", "rat") == 1);
4648 assert(levenshteinDistance("parks", "spark") == 2);
4649 assert(levenshteinDistance("kitten", "sitting") == 3);
4650 // ignore case
4651 assert(levenshteinDistance!("toupper(a) == toupper(b)")
4652     ("parks", "SPARK") == 2);
4653 ----
4654 */
4655 size_t levenshteinDistance(alias equals = "a == b", Range1, Range2)
4656     (Range1 s, Range2 t)
4657     if (isForwardRange!(Range1) && isForwardRange!(Range2))
4658 {
4659     Levenshtein!(Range1, binaryFun!(equals), size_t) lev;
4660     return lev.distance(s, t);
4661 }
4662
4663 /**
4664 Returns the Levenshtein distance and the edit path between $(D s) and
4665 $(D t).
4666
4667 Example:
4668 ---
4669 string a = "Saturday", b = "Sunday";
4670 auto p = levenshteinDistanceAndPath(a, b);
4671 assert(p[0] == 3);
4672 assert(equal(p[1], "nrrnsnnn"));
4673 ---
4674 */
4675 Tuple!(size_t, EditOp[])
4676 levenshteinDistanceAndPath(alias equals = "a == b", Range1, Range2)
4677     (Range1 s, Range2 t)
4678     if (isForwardRange!(Range1) && isForwardRange!(Range2))
4679 {
4680     Levenshtein!(Range1, binaryFun!(equals)) lev;
4681     auto d = lev.distance(s, t);
4682     return tuple(d, lev.path);
4683 }
4684
4685 unittest
4686 {
4687     debug(std_algorithm) scope(success)
4688         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
4689     assert(levenshteinDistance("a", "a") == 0);
4690     assert(levenshteinDistance("a", "b") == 1);
4691     assert(levenshteinDistance("aa", "ab") == 1);
4692     assert(levenshteinDistance("aa", "abc") == 2);
4693     assert(levenshteinDistance("Saturday", "Sunday") == 3);
4694     assert(levenshteinDistance("kitten", "sitting") == 3);
4695     //lev.deletionIncrement = 2;
4696     //lev.insertionIncrement = 100;
4697     string a = "Saturday", b = "Sunday";
4698     auto p = levenshteinDistanceAndPath(a, b);
4699     assert(cast(string) p[1] == "nrrnsnnn");
4700 }
4701
4702 // copy
4703 /**
4704 Copies the content of $(D source) into $(D target) and returns the
4705 remaining (unfilled) part of $(D target). See also $(WEB
4706 sgi.com/tech/stl/_copy.html, STL's copy). If a behavior similar to
4707 $(WEB sgi.com/tech/stl/copy_backward.html, STL's copy_backward) is
4708 needed, use $(D copy(retro(source), retro(target))). See also $(XREF
4709 range, retro).
4710
4711 Example:
4712 ----
4713 int[] a = [ 1, 5 ];
4714 int[] b = [ 9, 8 ];
4715 int[] c = new int[a.length + b.length + 10];
4716 auto d = copy(b, copy(a, c));
4717 assert(c[0 .. a.length + b.length] == a ~ b);
4718 assert(d.length == 10);
4719 ----
4720
4721 As long as the target range elements support assignment from source
4722 range elements, different types of ranges are accepted.
4723
4724 Example:
4725 ----
4726 float[] a = [ 1.0f, 5 ];
4727 double[] b = new double[a.length];
4728 auto d = copy(a, b);
4729 ----
4730
4731 To copy at most $(D n) elements from range $(D a) to range $(D b), you
4732 may want to use $(D copy(take(a, n), b)). To copy those elements from
4733 range $(D a) that satisfy predicate $(D pred) to range $(D b), you may
4734 want to use $(D copy(filter!(pred)(a), b)).
4735
4736 Example:
4737 ----
4738 int[] a = [ 1, 5, 8, 9, 10, 1, 2, 0 ];
4739 auto b = new int[a.length];
4740 auto c = copy(filter!("(a & 1) == 1")(a), b);
4741 assert(b[0 .. $ - c.length] == [ 1, 5, 9, 1 ]);
4742 ----
4743
4744  */
4745 Range2 copy(Range1, Range2)(Range1 source, Range2 target)
4746 if (isInputRange!Range1 && isOutputRange!(Range2, ElementType!Range1))
4747 {
4748     for (; !source.empty; source.popFront())
4749     {
4750         put(target, source.front);
4751     }
4752     return target;
4753 }
4754
4755 unittest
4756 {
4757     debug(std_algorithm) scope(success)
4758         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
4759     {
4760         int[] a = [ 1, 5 ];
4761         int[] b = [ 9, 8 ];
4762         int[] c = new int[a.length + b.length + 10];
4763         auto d = copy(b, copy(a, c));
4764         assert(c[0 .. a.length + b.length] == a ~ b);
4765         assert(d.length == 10);
4766     }
4767     {
4768         int[] a = [ 1, 5 ];
4769         int[] b = [ 9, 8 ];
4770         auto e = copy(filter!("a > 1")(a), b);
4771         assert(b[0] == 5 && e.length == 1);
4772     }
4773 }
4774
4775 // swapRanges
4776 /**
4777 Swaps all elements of $(D r1) with successive elements in $(D r2).
4778 Returns a tuple containing the remainder portions of $(D r1) and $(D
4779 r2) that were not swapped (one of them will be empty). The ranges may
4780 be of different types but must have the same element type and support
4781 swapping.
4782
4783 Example:
4784 ----
4785 int[] a = [ 100, 101, 102, 103 ];
4786 int[] b = [ 0, 1, 2, 3 ];
4787 auto c = swapRanges(a[1 .. 3], b[2 .. 4]);
4788 assert(c[0].empty && c[1].empty);
4789 assert(a == [ 100, 2, 3, 103 ]);
4790 assert(b == [ 0, 1, 101, 102 ]);
4791 ----
4792 */
4793 Tuple!(Range1, Range2)
4794 swapRanges(Range1, Range2)(Range1 r1, Range2 r2)
4795     if (isInputRange!(Range1) && isInputRange!(Range2)
4796             && hasSwappableElements!(Range1) && hasSwappableElements!(Range2)
4797             && is(ElementType!(Range1) == ElementType!(Range2)))
4798 {
4799     for (; !r1.empty && !r2.empty; r1.popFront, r2.popFront)
4800     {
4801         swap(r1.front, r2.front);
4802     }
4803     return tuple(r1, r2);
4804 }
4805
4806 unittest
4807 {
4808     debug(std_algorithm) scope(success)
4809         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
4810     int[] a = [ 100, 101, 102, 103 ];
4811     int[] b = [ 0, 1, 2, 3 ];
4812     auto c = swapRanges(a[1 .. 3], b[2 .. 4]);
4813     assert(c[0].empty && c[1].empty);
4814     assert(a == [ 100, 2, 3, 103 ]);
4815     assert(b == [ 0, 1, 101, 102 ]);
4816 }
4817
4818 // reverse
4819 /**
4820 Reverses $(D r) in-place.  Performs $(D r.length) evaluations of $(D
4821 swap). See also $(WEB sgi.com/tech/stl/_reverse.html, STL's reverse).
4822
4823 Example:
4824 ----
4825 int[] arr = [ 1, 2, 3 ];
4826 reverse(arr);
4827 assert(arr == [ 3, 2, 1 ]);
4828 ----
4829 */
4830 void reverse(Range)(Range r)
4831 if (isBidirectionalRange!(Range) && hasSwappableElements!(Range))
4832 {
4833     while (!r.empty)
4834     {
4835         swap(r.front, r.back);
4836         r.popFront;
4837         if (r.empty) break;
4838         r.popBack;
4839     }
4840 }
4841
4842 unittest
4843 {
4844     debug(std_algorithm) scope(success)
4845         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
4846     int[] range = null;
4847     reverse(range);
4848     range = [ 1 ];
4849     reverse(range);
4850     assert(range == [1]);
4851     range = [1, 2];
4852     reverse(range);
4853     assert(range == [2, 1]);
4854     range = [1, 2, 3];
4855     reverse(range);
4856     assert(range == [3, 2, 1]);
4857 }
4858
4859 // bringToFront
4860 /**
4861 The $(D bringToFront) function has considerable flexibility and
4862 usefulness. It can rotate elements in one buffer left or right, swap
4863 buffers of equal length, and even move elements across disjoint
4864 buffers of different types and different lengths.
4865
4866 $(D bringToFront) takes two ranges $(D front) and $(D back), which may
4867 be of different types. Considering the concatenation of $(D front) and
4868 $(D back) one unified range, $(D bringToFront) rotates that unified
4869 range such that all elements in $(D back) are brought to the beginning
4870 of the unified range. The relative ordering of elements in $(D front)
4871 and $(D back), respectively, remains unchanged.
4872
4873 The simplest use of $(D bringToFront) is for rotating elements in a
4874 buffer. For example:
4875
4876 ----
4877 auto arr = [4, 5, 6, 7, 1, 2, 3];
4878 bringToFront(arr[0 .. 4], arr[4 .. $]);
4879 assert(arr == [ 1, 2, 3, 4, 5, 6, 7 ]);
4880 ----
4881
4882 The $(D front) range may actually "step over" the $(D back)
4883 range. This is very useful with forward ranges that cannot compute
4884 comfortably right-bounded subranges like $(D arr[0 .. 4]) above. In
4885 the example below, $(D r2) is a right subrange of $(D r1).
4886
4887 ----
4888 auto list = SList!(int)(4, 5, 6, 7, 1, 2, 3);
4889 auto r1 = list[];
4890 auto r2 = list[]; popFrontN(r2, 4);
4891 assert(equal(r2, [ 1, 2, 3 ]));
4892 bringToFront(r1, r2);
4893 assert(equal(list[], [ 1, 2, 3, 4, 5, 6, 7 ]));
4894 ----
4895
4896 Elements can be swapped across ranges of different types:
4897
4898 ----
4899 auto list = SList!(int)(4, 5, 6, 7);
4900 auto vec = [ 1, 2, 3 ];
4901 bringToFront(list[], vec);
4902 assert(equal(list[], [ 1, 2, 3, 4 ]));
4903 assert(equal(vec, [ 5, 6, 7 ]));
4904 ----
4905
4906 Performs $(BIGOH max(front.length, back.length)) evaluations of $(D
4907 swap). See also $(WEB sgi.com/tech/stl/_rotate.html, STL's rotate).
4908
4909 Preconditions:
4910
4911 Either $(D front) and $(D back) are disjoint, or $(D back) is
4912 reachable from $(D front) and $(D front) is not reachable from $(D
4913 back).
4914
4915 Returns:
4916
4917 The number of elements brought to the front, i.e., the length of $(D
4918 back).
4919 */
4920 size_t bringToFront(Range1, Range2)(Range1 front, Range2 back)
4921     if (isInputRange!Range1 && isForwardRange!Range2)
4922 {
4923     enum bool sameHeadExists = is(typeof(front.sameHead(back)));
4924     size_t result;
4925     for (bool semidone; !front.empty && !back.empty; )
4926     {
4927         static if (sameHeadExists)
4928         {
4929             if (front.sameHead(back)) break; // shortcut
4930         }
4931         // Swap elements until front and/or back ends.
4932         auto back0 = back.save;
4933         size_t nswaps;
4934         do
4935         {
4936             static if (sameHeadExists)
4937             {
4938                 // Detect the stepping-over condition.
4939                 if (front.sameHead(back0)) back0 = back.save;
4940             }
4941             swapFront(front, back);
4942             ++nswaps;
4943             front.popFront();
4944             back.popFront();
4945         }
4946         while (!front.empty && !back.empty);
4947
4948         if (!semidone) result += nswaps;
4949
4950         // Now deal with the remaining elements.
4951         if (back.empty)
4952         {
4953             if (front.empty) break;
4954             // Right side was shorter, which means that we've brought
4955             // all the back elements to the front.
4956             semidone = true;
4957             // Next pass: bringToFront(front, back0) to adjust the rest.
4958             back = back0;
4959         }
4960         else
4961         {
4962             assert(front.empty);
4963             // Left side was shorter. Let's step into the back.
4964             static if (is(Range1 == Take!Range2))
4965             {
4966                 front = take(back0, nswaps);
4967             }
4968             else
4969             {
4970                 immutable subresult = bringToFront(take(back0, nswaps),
4971                                                    back);
4972                 if (!semidone) result += subresult;
4973                 break; // done
4974             }
4975         }
4976     }
4977     return result;
4978 }
4979
4980 unittest
4981 {
4982     debug(std_algorithm) scope(success)
4983         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
4984     // doc example
4985     {
4986         int[] arr = [4, 5, 6, 7, 1, 2, 3];
4987         auto p = bringToFront(arr[0 .. 4], arr[4 .. $]);
4988         assert(p == arr.length - 4);
4989         assert(arr == [ 1, 2, 3, 4, 5, 6, 7 ], text(arr));
4990     }
4991     {
4992         auto list = SList!(int)(4, 5, 6, 7, 1, 2, 3);
4993         auto r1 = list[];
4994         auto r2 = list[]; popFrontN(r2, 4);
4995         assert(equal(r2, [ 1, 2, 3 ]));
4996         bringToFront(r1, r2);
4997         assert(equal(list[], [ 1, 2, 3, 4, 5, 6, 7 ]));
4998     }
4999     {
5000         auto list = SList!(int)(4, 5, 6, 7);
5001         auto vec = [ 1, 2, 3 ];
5002         bringToFront(list[], vec);
5003         assert(equal(list[], [ 1, 2, 3, 4 ]));
5004         assert(equal(vec, [ 5, 6, 7 ]));
5005     }
5006     // a more elaborate test
5007     {
5008         auto rnd = Random(unpredictableSeed);
5009         int[] a = new int[uniform(100, 200, rnd)];
5010         int[] b = new int[uniform(100, 200, rnd)];
5011         foreach (ref e; a) e = uniform(-100, 100, rnd);
5012         foreach (ref e; b) e = uniform(-100, 100, rnd);
5013         int[] c = a ~ b;
5014         // writeln("a= ", a);
5015         // writeln("b= ", b);
5016         auto n = bringToFront(c[0 .. a.length], c[a.length .. $]);
5017         //writeln("c= ", c);
5018         assert(n == b.length);
5019         assert(c == b ~ a, text(c, "\n", a, "\n", b));
5020     }
5021     // different types, moveFront, no sameHead
5022     {
5023         static struct R(T)
5024         {
5025             T[] data;
5026             size_t i;
5027             @property
5028             {
5029                 R save() { return this; }
5030                 bool empty() { return i >= data.length; }
5031                 T front() { return data[i]; }
5032                 T front(real e) { return data[i] = cast(T) e; }
5033                 alias front moveFront;
5034             }
5035             void popFront() { ++i; }
5036         }
5037         auto a = R!int([1, 2, 3, 4, 5]);
5038         auto b = R!real([6, 7, 8, 9]);
5039         auto n = bringToFront(a, b);
5040         assert(n == 4);
5041         assert(a.data == [6, 7, 8, 9, 1]);
5042         assert(b.data == [2, 3, 4, 5]);
5043     }
5044     // front steps over back
5045     {
5046         int[] arr, r1, r2;
5047
5048         // back is shorter
5049         arr = [4, 5, 6, 7, 1, 2, 3];
5050         r1 = arr;
5051         r2 = arr[4 .. $];
5052         bringToFront(r1, r2) == 3 || assert(0);
5053         assert(equal(arr, [1, 2, 3, 4, 5, 6, 7]));
5054
5055         // front is shorter
5056         arr = [5, 6, 7, 1, 2, 3, 4];
5057         r1 = arr;
5058         r2 = arr[3 .. $];
5059         bringToFront(r1, r2) == 4 || assert(0);
5060         assert(equal(arr, [1, 2, 3, 4, 5, 6, 7]));
5061     }
5062 }
5063
5064 // SwapStrategy
5065 /**
5066 Defines the swapping strategy for algorithms that need to swap
5067 elements in a range (such as partition and sort). The strategy
5068 concerns the swapping of elements that are not the core concern of the
5069 algorithm. For example, consider an algorithm that sorts $(D [ "abc",
5070 "b", "aBc" ]) according to $(D toupper(a) < toupper(b)). That
5071 algorithm might choose to swap the two equivalent strings $(D "abc")
5072 and $(D "aBc"). That does not affect the sorting since both $(D [
5073 "abc", "aBc", "b" ]) and $(D [ "aBc", "abc", "b" ]) are valid
5074 outcomes.
5075
5076 Some situations require that the algorithm must NOT ever change the
5077 relative ordering of equivalent elements (in the example above, only
5078 $(D [ "abc", "aBc", "b" ]) would be the correct result). Such
5079 algorithms are called $(B stable). If the ordering algorithm may swap
5080 equivalent elements discretionarily, the ordering is called $(B
5081 unstable).
5082
5083 Yet another class of algorithms may choose an intermediate tradeoff by
5084 being stable only on a well-defined subrange of the range. There is no
5085 established terminology for such behavior; this library calls it $(B
5086 semistable).
5087
5088 Generally, the $(D stable) ordering strategy may be more costly in
5089 time and/or space than the other two because it imposes additional
5090 constraints. Similarly, $(D semistable) may be costlier than $(D
5091 unstable). As (semi-)stability is not needed very often, the ordering
5092 algorithms in this module parameterized by $(D SwapStrategy) all
5093 choose $(D SwapStrategy.unstable) as the default.
5094 */
5095
5096 enum SwapStrategy
5097 {
5098     /**
5099        Allows freely swapping of elements as long as the output
5100        satisfies the algorithm's requirements.
5101     */
5102     unstable,
5103     /**
5104        In algorithms partitioning ranges in two, preserve relative
5105        ordering of elements only to the left of the partition point.
5106     */
5107     semistable,
5108     /**
5109        Preserve the relative ordering of elements to the largest
5110        extent allowed by the algorithm's requirements.
5111     */
5112     stable,
5113 }
5114
5115 /**
5116 Eliminates elements at given offsets from $(D range) and returns the
5117 shortened range. In the simplest call, one element is removed.
5118
5119 ----
5120 int[] a = [ 3, 5, 7, 8 ];
5121 assert(remove(a, 1) == [ 3, 7, 8 ]);
5122 assert(a == [ 3, 7, 8, 8 ]);
5123 ----
5124
5125 In the case above the element at offset $(D 1) is removed and $(D
5126 remove) returns the range smaller by one element. The original array
5127 has remained of the same length because all functions in $(D
5128 std.algorithm) only change $(I content), not $(I topology). The value
5129 $(D 8) is repeated because $(XREF algorithm, move) was invoked to move
5130 elements around and on integers $(D move) simply copies the source to
5131 the destination. To replace $(D a) with the effect of the removal,
5132 simply assign $(D a = remove(a, 1)). The slice will be rebound to the
5133 shorter array and the operation completes with maximal efficiency.
5134
5135 Multiple indices can be passed into $(D remove). In that case,
5136 elements at the respective indices are all removed. The indices must
5137 be passed in increasing order, otherwise an exception occurs.
5138
5139 ----
5140 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
5141 assert(remove(a, 1, 3, 5) ==
5142     [ 0, 2, 4, 6, 7, 8, 9, 10 ]);
5143 ----
5144
5145 (Note how all indices refer to slots in the $(I original) array, not
5146 in the array as it is being progressively shortened.) Finally, any
5147 combination of integral offsets and tuples composed of two integral
5148 offsets can be passed in.
5149
5150 ----
5151 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
5152 assert(remove(a, 1, tuple(3, 5), 9) == [ 0, 2, 6, 7, 8, 10 ]);
5153 ----
5154
5155 In this case, the slots at positions 1, 3, 4, and 9 are removed from
5156 the array. The tuple passes in a range closed to the left and open to
5157 the right (consistent with built-in slices), e.g. $(D tuple(3, 5))
5158 means indices $(D 3) and $(D 4) but not $(D 5).
5159
5160 If the need is to remove some elements in the range but the order of
5161 the remaining elements does not have to be preserved, you may want to
5162 pass $(D SwapStrategy.unstable) to $(D remove).
5163
5164 ----
5165 int[] a = [ 0, 1, 2, 3 ];
5166 assert(remove!(SwapStrategy.unstable)(a, 1) == [ 0, 3, 2 ]);
5167 ----
5168
5169 In the case above, the element at slot $(D 1) is removed, but replaced
5170 with the last element of the range. Taking advantage of the relaxation
5171 of the stability requirement, $(D remove) moved elements from the end
5172 of the array over the slots to be removed. This way there is less data
5173 movement to be done which improves the execution time of the function.
5174
5175 The function $(D remove) works on any forward range. The moving
5176 strategy is (listed from fastest to slowest): $(UL $(LI If $(D s ==
5177 SwapStrategy.unstable && isRandomAccessRange!Range &&
5178 hasLength!Range), then elements are moved from the end of the range
5179 into the slots to be filled. In this case, the absolute minimum of
5180 moves is performed.)  $(LI Otherwise, if $(D s ==
5181 SwapStrategy.unstable && isBidirectionalRange!Range &&
5182 hasLength!Range), then elements are still moved from the end of the
5183 range, but time is spent on advancing between slots by repeated calls
5184 to $(D range.popFront).)  $(LI Otherwise, elements are moved incrementally
5185 towards the front of $(D range); a given element is never moved
5186 several times, but more elements are moved than in the previous
5187 cases.))
5188  */
5189 Range remove
5190 (SwapStrategy s = SwapStrategy.stable, Range, Offset...)
5191 (Range range, Offset offset)
5192 if (isBidirectionalRange!Range && hasLength!Range && s != SwapStrategy.stable
5193     && Offset.length >= 1)
5194 {
5195     enum bool tupleLeft = is(typeof(offset[0][0]))
5196         && is(typeof(offset[0][1]));
5197     enum bool tupleRight = is(typeof(offset[$ - 1][0]))
5198         && is(typeof(offset[$ - 1][1]));
5199     static if (!tupleLeft)
5200     {
5201         alias offset[0] lStart;
5202         auto lEnd = lStart + 1;
5203     }
5204     else
5205     {
5206         auto lStart = offset[0][0];
5207         auto lEnd = offset[0][1];
5208     }
5209     static if (!tupleRight)
5210     {
5211         alias offset[$ - 1] rStart;
5212         auto rEnd = rStart + 1;
5213     }
5214     else
5215     {
5216         auto rStart = offset[$ - 1][0];
5217         auto rEnd = offset[$ - 1][1];
5218     }
5219     // Begin. Test first to see if we need to remove the rightmost
5220     // element(s) in the range. In that case, life is simple - chop
5221     // and recurse.
5222     if (rEnd == range.length)
5223     {
5224         // must remove the last elements of the range
5225         range.popBackN(rEnd - rStart);
5226         static if (Offset.length > 1)
5227         {
5228             return .remove!(s, Range, Offset[0 .. $ - 1])
5229                 (range, offset[0 .. $ - 1]);
5230         }
5231         else
5232         {
5233             return range;
5234         }
5235     }
5236
5237     // Ok, there are "live" elements at the end of the range
5238     auto t = range;
5239     auto lDelta = lEnd - lStart, rDelta = rEnd - rStart;
5240     auto rid = min(lDelta, rDelta);
5241     foreach (i; 0 .. rid)
5242     {
5243         move(range.back, t.front);
5244         range.popBack;
5245         t.popFront;
5246     }
5247     if (rEnd - rStart == lEnd - lStart)
5248     {
5249         // We got rid of both left and right
5250         static if (Offset.length > 2)
5251         {
5252             return .remove!(s, Range, Offset[1 .. $ - 1])
5253                 (range, offset[1 .. $ - 1]);
5254         }
5255         else
5256         {
5257             return range;
5258         }
5259     }
5260     else if (rEnd - rStart < lEnd - lStart)
5261     {
5262         // We got rid of the entire right subrange
5263         static if (Offset.length > 2)
5264         {
5265             return .remove!(s, Range)
5266                 (range, tuple(lStart + rid, lEnd),
5267                         offset[1 .. $ - 1]);
5268         }
5269         else
5270         {
5271             auto tmp = tuple(lStart + rid, lEnd);
5272             return .remove!(s, Range, typeof(tmp))
5273                 (range, tmp);
5274         }
5275     }
5276     else
5277     {
5278         // We got rid of the entire left subrange
5279         static if (Offset.length > 2)
5280         {
5281             return .remove!(s, Range)
5282                 (range, offset[1 .. $ - 1],
5283                         tuple(rStart, lEnd - rid));
5284         }
5285         else
5286         {
5287             auto tmp = tuple(rStart, lEnd - rid);
5288             return .remove!(s, Range, typeof(tmp))
5289                 (range, tmp);
5290         }
5291     }
5292 }
5293
5294 // Ditto
5295 Range remove
5296 (SwapStrategy s = SwapStrategy.stable, Range, Offset...)
5297 (Range range, Offset offset)
5298 if ((isForwardRange!Range && !isBidirectionalRange!Range
5299                 || !hasLength!Range || s == SwapStrategy.stable)
5300         && Offset.length >= 1)
5301 {
5302     auto result = range;
5303     auto src = range, tgt = range;
5304     size_t pos;
5305     foreach (i; offset)
5306     {
5307         static if (is(typeof(i[0])) && is(typeof(i[1])))
5308         {
5309             auto from = i[0], delta = i[1] - i[0];
5310         }
5311         else
5312         {
5313             auto from = i;
5314             enum delta = 1;
5315         }
5316         assert(pos <= from);
5317         for (; pos < from; ++pos, src.popFront, tgt.popFront)
5318         {
5319             move(src.front, tgt.front);
5320         }
5321         // now skip source to the "to" position
5322         src.popFrontN(delta);
5323         pos += delta;
5324         foreach (j; 0 .. delta) result.popBack;
5325     }
5326     // leftover move
5327     moveAll(src, tgt);
5328     return result;
5329 }
5330
5331 unittest
5332 {
5333     debug(std_algorithm) scope(success)
5334         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
5335     int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
5336     //writeln(remove!(SwapStrategy.stable)(a, 1));
5337     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
5338     assert(remove!(SwapStrategy.stable)(a, 1) ==
5339         [ 0, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]);
5340
5341     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
5342     assert(remove!(SwapStrategy.unstable)(a, 0, 10) ==
5343             [ 9, 1, 2, 3, 4, 5, 6, 7, 8 ]);
5344
5345     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
5346     assert(remove!(SwapStrategy.unstable)(a, 0, tuple(9, 11)) ==
5347             [ 8, 1, 2, 3, 4, 5, 6, 7 ]);
5348
5349     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
5350     //writeln(remove!(SwapStrategy.stable)(a, 1, 5));
5351     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
5352     assert(remove!(SwapStrategy.stable)(a, 1, 5) ==
5353         [ 0, 2, 3, 4, 6, 7, 8, 9, 10 ]);
5354
5355     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
5356     //writeln(remove!(SwapStrategy.stable)(a, 1, 3, 5));
5357     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
5358     assert(remove!(SwapStrategy.stable)(a, 1, 3, 5)
5359             == [ 0, 2, 4, 6, 7, 8, 9, 10]);
5360     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
5361     //writeln(remove!(SwapStrategy.stable)(a, 1, tuple(3, 5)));
5362     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
5363     assert(remove!(SwapStrategy.stable)(a, 1, tuple(3, 5))
5364             == [ 0, 2, 5, 6, 7, 8, 9, 10]);
5365 }
5366
5367 /**
5368 Reduces the length of the bidirectional range $(D range) by only
5369 keeping elements that satisfy $(D pred). If $(s =
5370 SwapStrategy.unstable), elements are moved from the right end of the
5371 range over the elements to eliminate. If $(D s = SwapStrategy.stable)
5372 (the default), elements are moved progressively to front such that
5373 their relative order is preserved. Returns the tail portion of the
5374 range that was moved.
5375
5376 Example:
5377 ----
5378 int[] a = [ 1, 2, 3, 2, 3, 4, 5, 2, 5, 6 ];
5379 assert(a[0 .. $ - remove!("a == 2")(a).length] == [ 1, 3, 3, 4, 5, 5, 6 ]);
5380 ----
5381  */
5382 Range remove(alias pred, SwapStrategy s = SwapStrategy.stable, Range)
5383 (Range range)
5384 if (isBidirectionalRange!Range)
5385 {
5386     auto result = range;
5387     static if (s != SwapStrategy.stable)
5388     {
5389         for (;!range.empty;)
5390         {
5391             if (!unaryFun!(pred)(range.front))
5392             {
5393                 range.popFront;
5394                 continue;
5395             }
5396             move(range.back, range.front);
5397             range.popBack;
5398             result.popBack;
5399         }
5400     }
5401     else
5402     {
5403         auto tgt = range;
5404         for (; !range.empty; range.popFront)
5405         {
5406             if (unaryFun!(pred)(range.front))
5407             {
5408                 // yank this guy
5409                 result.popBack;
5410                 continue;
5411             }
5412             // keep this guy
5413             move(range.front, tgt.front);
5414             tgt.popFront;
5415         }
5416     }
5417     return result;
5418 }
5419
5420 unittest
5421 {
5422     debug(std_algorithm) scope(success)
5423         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
5424     int[] a = [ 1, 2, 3, 2, 3, 4, 5, 2, 5, 6 ];
5425     assert(remove!("a == 2", SwapStrategy.unstable)(a) ==
5426             [ 1, 6, 3, 5, 3, 4, 5 ]);
5427     a = [ 1, 2, 3, 2, 3, 4, 5, 2, 5, 6 ];
5428     //writeln(remove!("a != 2", SwapStrategy.stable)(a));
5429     assert(remove!("a == 2", SwapStrategy.stable)(a) ==
5430             [ 1, 3, 3, 4, 5, 5, 6 ]);
5431 }
5432
5433 // eliminate
5434 /* *
5435 Reduces $(D r) by overwriting all elements $(D x) that satisfy $(D
5436 pred(x)). Returns the reduced range.
5437
5438 Example:
5439 ----
5440 int[] arr = [ 1, 2, 3, 4, 5 ];
5441 // eliminate even elements
5442 auto r = eliminate!("(a & 1) == 0")(arr);
5443 assert(r == [ 1, 3, 5 ]);
5444 assert(arr == [ 1, 3, 5, 4, 5 ]);
5445 ----
5446 */
5447 // Range eliminate(alias pred,
5448 //                 SwapStrategy ss = SwapStrategy.unstable,
5449 //                 alias move = .move,
5450 //                 Range)(Range r)
5451 // {
5452 //     alias Iterator!(Range) It;
5453 //     static void assignIter(It a, It b) { move(*b, *a); }
5454 //     return range(begin(r), partitionold!(not!(pred), ss, assignIter, Range)(r));
5455 // }
5456
5457 // unittest
5458 // {
5459 //     int[] arr = [ 1, 2, 3, 4, 5 ];
5460 // // eliminate even elements
5461 //     auto r = eliminate!("(a & 1) == 0")(arr);
5462 //     assert(find!("(a & 1) == 0")(r).empty);
5463 // }
5464
5465 /* *
5466 Reduces $(D r) by overwriting all elements $(D x) that satisfy $(D
5467 pred(x, v)). Returns the reduced range.
5468
5469 Example:
5470 ----
5471 int[] arr = [ 1, 2, 3, 2, 4, 5, 2 ];
5472 // keep elements different from 2
5473 auto r = eliminate(arr, 2);
5474 assert(r == [ 1, 3, 4, 5 ]);
5475 assert(arr == [ 1, 3, 4, 5, 4, 5, 2  ]);
5476 ----
5477 */
5478 // Range eliminate(alias pred = "a == b",
5479 //                 SwapStrategy ss = SwapStrategy.semistable,
5480 //                 Range, Value)(Range r, Value v)
5481 // {
5482 //     alias Iterator!(Range) It;
5483 //     bool comp(typeof(*It) a) { return !binaryFun!(pred)(a, v); }
5484 //     static void assignIterB(It a, It b) { *a = *b; }
5485 //     return range(begin(r),
5486 //             partitionold!(comp,
5487 //                     ss, assignIterB, Range)(r));
5488 // }
5489
5490 // unittest
5491 // {
5492 //     int[] arr = [ 1, 2, 3, 2, 4, 5, 2 ];
5493 // // keep elements different from 2
5494 //     auto r = eliminate(arr, 2);
5495 //     assert(r == [ 1, 3, 4, 5 ]);
5496 //     assert(arr == [ 1, 3, 4, 5, 4, 5, 2  ]);
5497 // }
5498
5499 // partition
5500 /**
5501 Partitions a range in two using $(D pred) as a
5502 predicate. Specifically, reorders the range $(D r = [left,
5503 right$(RPAREN)) using $(D swap) such that all elements $(D i) for
5504 which $(D pred(i)) is $(D true) come before all elements $(D j) for
5505 which $(D pred(j)) returns $(D false).
5506
5507 Performs $(BIGOH r.length) (if unstable or semistable) or $(BIGOH
5508 r.length * log(r.length)) (if stable) evaluations of $(D less) and $(D
5509 swap). The unstable version computes the minimum possible evaluations
5510 of $(D swap) (roughly half of those performed by the semistable
5511 version).
5512
5513 See also STL's $(WEB sgi.com/tech/stl/_partition.html, partition) and
5514 $(WEB sgi.com/tech/stl/stable_partition.html, stable_partition).
5515
5516 Returns:
5517
5518 The right part of $(D r) after partitioning.
5519
5520 If $(D ss == SwapStrategy.stable), $(D partition) preserves the
5521 relative ordering of all elements $(D a), $(D b) in $(D r) for which
5522 $(D pred(a) == pred(b)). If $(D ss == SwapStrategy.semistable), $(D
5523 partition) preserves the relative ordering of all elements $(D a), $(D
5524 b) in the left part of $(D r) for which $(D pred(a) == pred(b)).
5525
5526 Example:
5527
5528 ----
5529 auto Arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
5530 auto arr = Arr.dup;
5531 static bool even(int a) { return (a & 1) == 0; }
5532 // Partition arr such that even numbers come first
5533 auto r = partition!(even)(arr);
5534 // Now arr is separated in evens and odds.
5535 // Numbers may have become shuffled due to instability
5536 assert(r == arr[5 .. $]);
5537 assert(count!(even)(arr[0 .. 5]) == 5);
5538 assert(find!(even)(r).empty);
5539
5540 // Can also specify the predicate as a string.
5541 // Use 'a' as the predicate argument name
5542 arr[] = Arr[];
5543 r = partition!(q{(a & 1) == 0})(arr);
5544 assert(r == arr[5 .. $]);
5545
5546 // Now for a stable partition:
5547 arr[] = Arr[];
5548 r = partition!(q{(a & 1) == 0}, SwapStrategy.stable)(arr);
5549 // Now arr is [2 4 6 8 10 1 3 5 7 9], and r points to 1
5550 assert(arr == [2, 4, 6, 8, 10, 1, 3, 5, 7, 9] && r == arr[5 .. $]);
5551
5552 // In case the predicate needs to hold its own state, use a delegate:
5553 arr[] = Arr[];
5554 int x = 3;
5555 // Put stuff greater than 3 on the left
5556 bool fun(int a) { return a > x; }
5557 r = partition!(fun, SwapStrategy.semistable)(arr);
5558 // Now arr is [4 5 6 7 8 9 10 2 3 1] and r points to 2
5559 assert(arr == [4, 5, 6, 7, 8, 9, 10, 2, 3, 1] && r == arr[7 .. $]);
5560 ----
5561 */
5562 Range partition(alias predicate,
5563         SwapStrategy ss = SwapStrategy.unstable, Range)(Range r)
5564     if ((ss == SwapStrategy.stable && isRandomAccessRange!(Range))
5565             || (ss != SwapStrategy.stable && isForwardRange!(Range)))
5566 {
5567     alias unaryFun!(predicate) pred;
5568     if (r.empty) return r;
5569     static if (ss == SwapStrategy.stable)
5570     {
5571         if (r.length == 1)
5572         {
5573             if (pred(r.front)) r.popFront;
5574             return r;
5575         }
5576         const middle = r.length / 2;
5577         alias .partition!(pred, ss, Range) recurse;
5578         auto lower = recurse(r[0 .. middle]);
5579         auto upper = recurse(r[middle .. $]);
5580         bringToFront(lower, r[middle .. r.length - upper.length]);
5581         return r[r.length - lower.length - upper.length .. r.length];
5582     }
5583     else static if (ss == SwapStrategy.semistable)
5584     {
5585         for (; !r.empty; r.popFront)
5586         {
5587             // skip the initial portion of "correct" elements
5588             if (pred(r.front)) continue;
5589             // hit the first "bad" element
5590             auto result = r;
5591             for (r.popFront; !r.empty; r.popFront)
5592             {
5593                 if (!pred(r.front)) continue;
5594                 swap(result.front, r.front);
5595                 result.popFront;
5596             }
5597             return result;
5598         }
5599         return r;
5600     }
5601     else // ss == SwapStrategy.unstable
5602     {
5603         // Inspired from www.stepanovpapers.com/PAM3-partition_notes.pdf,
5604         // section "Bidirectional Partition Algorithm (Hoare)"
5605         auto result = r;
5606         for (;;)
5607         {
5608             for (;;)
5609             {
5610                 if (r.empty) return result;
5611                 if (!pred(r.front)) break;
5612                 r.popFront;
5613                 result.popFront;
5614             }
5615             // found the left bound
5616             assert(!r.empty);
5617             for (;;)
5618             {
5619                 if (pred(r.back)) break;
5620                 r.popBack;
5621                 if (r.empty) return result;
5622             }
5623             // found the right bound, swap & make progress
5624             static if (is(typeof(swap(r.front, r.back))))
5625             {
5626                 swap(r.front, r.back);
5627             }
5628             else
5629             {
5630                 auto t1 = moveFront(r), t2 = moveBack(r);
5631                 r.front = t2;
5632                 r.back = t1;
5633             }
5634             r.popFront;
5635             result.popFront;
5636             r.popBack;
5637         }
5638     }
5639 }
5640
5641 unittest // partition
5642 {
5643     auto Arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
5644     auto arr = Arr.dup;
5645     static bool even(int a) { return (a & 1) == 0; }
5646 // Partition a such that even numbers come first
5647     auto p1 = partition!(even)(arr);
5648 // Now arr is separated in evens and odds.
5649     assert(p1 == arr[5 .. $], text(p1));
5650     assert(count!(even)(arr[0 .. $ - p1.length]) == p1.length);
5651     assert(find!(even)(p1).empty);
5652 // Notice that numbers have become shuffled due to instability
5653     arr[] = Arr[];
5654 // Can also specify the predicate as a string.
5655 // Use 'a' as the predicate argument name
5656     p1 = partition!(q{(a & 1) == 0})(arr);
5657     assert(p1 == arr[5 .. $]);
5658 // Same result as above. Now for a stable partition:
5659     arr[] = Arr[];
5660     p1 = partition!(q{(a & 1) == 0}, SwapStrategy.stable)(arr);
5661 // Now arr is [2 4 6 8 10 1 3 5 7 9], and p points to 1
5662     assert(arr == [2, 4, 6, 8, 10, 1, 3, 5, 7, 9], text(arr));
5663     assert(p1 == arr[5 .. $], text(p1));
5664 // In case the predicate needs to hold its own state, use a delegate:
5665     arr[] = Arr[];
5666     int x = 3;
5667 // Put stuff greater than 3 on the left
5668     bool fun(int a) { return a > x; }
5669     p1 = partition!(fun, SwapStrategy.semistable)(arr);
5670 // Now arr is [4 5 6 7 8 9 10 2 3 1] and p points to 2
5671     assert(arr == [4, 5, 6, 7, 8, 9, 10, 2, 3, 1] && p1 == arr[7 .. $]);
5672
5673     // test with random data
5674     auto a = rndstuff!(int)();
5675     partition!(even)(a);
5676     assert(isPartitioned!(even)(a));
5677     auto b = rndstuff!(string);
5678     partition!(`a.length < 5`)(b);
5679     assert(isPartitioned!(`a.length < 5`)(b));
5680 }
5681
5682 /**
5683 Returns $(D true) if $(D r) is partitioned according to predicate $(D
5684 pred).
5685
5686 Example:
5687 ----
5688 int[] r = [ 1, 3, 5, 7, 8, 2, 4, ];
5689 assert(isPartitioned!("a & 1")(r));
5690 ----
5691  */
5692 bool isPartitioned(alias pred, Range)(Range r)
5693     if (isForwardRange!(Range))
5694 {
5695     for (; !r.empty; r.popFront)
5696     {
5697         if (unaryFun!(pred)(r.front)) continue;
5698         for (r.popFront; !r.empty; r.popFront)
5699         {
5700             if (unaryFun!(pred)(r.front)) return false;
5701         }
5702         break;
5703     }
5704     return true;
5705 }
5706
5707 unittest
5708 {
5709     debug(std_algorithm) scope(success)
5710         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
5711     int[] r = [ 1, 3, 5, 7, 8, 2, 4, ];
5712     assert(isPartitioned!("a & 1")(r));
5713 }
5714
5715 // topN
5716 /**
5717 Reorders the range $(D r) using $(D swap) such that $(D r[nth]) refers
5718 to the element that would fall there if the range were fully
5719 sorted. In addition, it also partitions $(D r) such that all elements
5720 $(D e1) from $(D r[0]) to $(D r[nth]) satisfy $(D !less(r[nth], e1)),
5721 and all elements $(D e2) from $(D r[nth]) to $(D r[r.length]) satisfy
5722 $(D !less(e2, r[nth])). Effectively, it finds the nth smallest
5723 (according to $(D less)) elements in $(D r). Performs $(BIGOH
5724 r.length) (if unstable) or $(BIGOH r.length * log(r.length)) (if
5725 stable) evaluations of $(D less) and $(D swap). See also $(WEB
5726 sgi.com/tech/stl/nth_element.html, STL's nth_element).
5727
5728 Example:
5729
5730 ----
5731 int[] v = [ 25, 7, 9, 2, 0, 5, 21 ];
5732 auto n = 4;
5733 topN!(less)(v, n);
5734 assert(v[n] == 9);
5735 // Equivalent form:
5736 topN!("a < b")(v, n);
5737 assert(v[n] == 9);
5738 ----
5739
5740 BUGS:
5741
5742 Stable topN has not been implemented yet.
5743 */
5744 void topN(alias less = "a < b",
5745         SwapStrategy ss = SwapStrategy.unstable,
5746         Range)(Range r, size_t nth)
5747     if (isRandomAccessRange!(Range) && hasLength!Range)
5748 {
5749     static assert(ss == SwapStrategy.unstable,
5750             "Stable topN not yet implemented");
5751     while (r.length > nth)
5752     {
5753         auto pivot = r.length / 2;
5754         swap(r[pivot], r.back);
5755         assert(!binaryFun!(less)(r.back, r.back));
5756         bool pred(ElementType!(Range) a)
5757         {
5758             return binaryFun!(less)(a, r.back);
5759         }
5760         auto right = partition!(pred, ss)(r);
5761         assert(right.length >= 1);
5762         swap(right.front, r.back);
5763         pivot = r.length - right.length;
5764         if (pivot == nth)
5765         {
5766             return;
5767         }
5768         if (pivot < nth)
5769         {
5770             ++pivot;
5771             r = r[pivot .. $];
5772             nth -= pivot;
5773         }
5774         else
5775         {
5776             assert(pivot < r.length);
5777             r = r[0 .. pivot];
5778         }
5779     }
5780 }
5781
5782 unittest
5783 {
5784     debug(std_algorithm) scope(success)
5785         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
5786     //scope(failure) writeln(stderr, "Failure testing algorithm");
5787     //auto v = ([ 25, 7, 9, 2, 0, 5, 21 ]).dup;
5788     int[] v = [ 7, 6, 5, 4, 3, 2, 1, 0 ];
5789     sizediff_t n = 3;
5790     topN!("a < b")(v, n);
5791     assert(reduce!max(v[0 .. n]) <= v[n]);
5792     assert(reduce!min(v[n + 1 .. $]) >= v[n]);
5793     //
5794     v = ([3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5]).dup;
5795     n = 3;
5796     topN(v, n);
5797     assert(reduce!max(v[0 .. n]) <= v[n]);
5798     assert(reduce!min(v[n + 1 .. $]) >= v[n]);
5799     //
5800     v = ([3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5]).dup;
5801     n = 1;
5802     topN(v, n);
5803     assert(reduce!max(v[0 .. n]) <= v[n]);
5804     assert(reduce!min(v[n + 1 .. $]) >= v[n]);
5805     //
5806     v = ([3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5]).dup;
5807     n = v.length - 1;
5808     topN(v, n);
5809     assert(v[n] == 7);
5810     //
5811     v = ([3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5]).dup;
5812     n = 0;
5813     topN(v, n);
5814     assert(v[n] == 1);
5815
5816     double[][] v1 = [[-10, -5], [-10, -3], [-10, -5], [-10, -4],
5817             [-10, -5], [-9, -5], [-9, -3], [-9, -5],];
5818
5819     // double[][] v1 = [ [-10, -5], [-10, -4], [-9, -5], [-9, -5],
5820     //         [-10, -5], [-10, -3], [-10, -5], [-9, -3],];
5821     double[]*[] idx = [ &v1[0], &v1[1], &v1[2], &v1[3], &v1[4], &v1[5], &v1[6],
5822             &v1[7], ];
5823
5824     auto mid = v1.length / 2;
5825     topN!((a, b){ return (*a)[1] < (*b)[1]; })(idx, mid);
5826     foreach (e; idx[0 .. mid]) assert((*e)[1] <= (*idx[mid])[1]);
5827     foreach (e; idx[mid .. $]) assert((*e)[1] >= (*idx[mid])[1]);
5828 }
5829
5830 unittest
5831 {
5832     debug(std_algorithm) scope(success)
5833         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
5834     int[] a = new int[uniform(1, 10000)];
5835         foreach (ref e; a) e = uniform(-1000, 1000);
5836     auto k = uniform(0, a.length);
5837     topN(a, k);
5838     if (k > 0)
5839     {
5840         auto left = reduce!max(a[0 .. k]);
5841         assert(left <= a[k]);
5842     }
5843     if (k + 1 < a.length)
5844     {
5845         auto right = reduce!min(a[k + 1 .. $]);
5846         assert(right >= a[k]);
5847     }
5848 }
5849
5850 /**
5851 Stores the smallest elements of the two ranges in the left-hand range.
5852  */
5853 void topN(alias less = "a < b",
5854         SwapStrategy ss = SwapStrategy.unstable,
5855         Range1, Range2)(Range1 r1, Range2 r2)
5856     if (isRandomAccessRange!(Range1) && hasLength!Range1 &&
5857             isInputRange!Range2 && is(ElementType!Range1 == ElementType!Range2))
5858 {
5859     static assert(ss == SwapStrategy.unstable,
5860             "Stable topN not yet implemented");
5861     auto heap = BinaryHeap!Range1(r1);
5862     for (; !r2.empty; r2.popFront)
5863     {
5864         heap.conditionalInsert(r2.front);
5865     }
5866 }
5867
5868 unittest
5869 {
5870     debug(std_algorithm) scope(success)
5871         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
5872     int[] a = [ 5, 7, 2, 6, 7 ];
5873     int[] b = [ 2, 1, 5, 6, 7, 3, 0 ];
5874     topN(a, b);
5875     sort(a);
5876     sort(b);
5877     assert(a == [0, 1, 2, 2, 3]);
5878 }
5879
5880 // sort
5881 /**
5882 Sorts a random-access range according to predicate $(D less). Performs
5883 $(BIGOH r.length * log(r.length)) (if unstable) or $(BIGOH r.length *
5884 log(r.length) * log(r.length)) (if stable) evaluations of $(D less)
5885 and $(D swap). See also STL's $(WEB sgi.com/tech/stl/_sort.html, sort)
5886 and $(WEB sgi.com/tech/stl/stable_sort.html, stable_sort).
5887
5888 Example:
5889
5890 ----
5891 int[] array = [ 1, 2, 3, 4 ];
5892 // sort in descending order
5893 sort!("a > b")(array);
5894 assert(array == [ 4, 3, 2, 1 ]);
5895 // sort in ascending order
5896 sort(array);
5897 assert(array == [ 1, 2, 3, 4 ]);
5898 // sort with a delegate
5899 bool myComp(int x, int y) { return x > y; }
5900 sort!(myComp)(array);
5901 assert(array == [ 4, 3, 2, 1 ]);
5902 // Showcase stable sorting
5903 string[] words = [ "aBc", "a", "abc", "b", "ABC", "c" ];
5904 sort!("toupper(a) < toupper(b)", SwapStrategy.stable)(words);
5905 assert(words == [ "a", "aBc", "abc", "ABC", "b", "c" ]);
5906 ----
5907 */
5908
5909 SortedRange!(Range, less)
5910 sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable,
5911         Range)(Range r)
5912 {
5913     alias binaryFun!(less) lessFun;
5914     static if (is(typeof(lessFun(r.front, r.front)) == bool))
5915     {
5916         sortImpl!(lessFun, ss)(r);
5917         static if(is(typeof(text(r))))
5918             assert(isSorted!lessFun(r), text(Range.stringof, ": ", r));
5919         else
5920             assert(isSorted!lessFun(r), text(Range.stringof, ": <unable to print elements>"));
5921     }
5922     else
5923     {
5924         static assert(false, "Invalid predicate passed to sort: "~less);
5925     }
5926     return assumeSorted!less(r);
5927 }
5928
5929 unittest
5930 {
5931     debug(std_algorithm) scope(success)
5932         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
5933     // sort using delegate
5934     int a[] = new int[100];
5935     auto rnd = Random(unpredictableSeed);
5936     foreach (ref e; a) {
5937         e = uniform(-100, 100, rnd);
5938     }
5939
5940     int i = 0;
5941     bool greater2(int a, int b) { return a + i > b + i; }
5942     bool delegate(int, int) greater = &greater2;
5943     sort!(greater)(a);
5944     assert(isSorted!(greater)(a));
5945
5946     // sort using string
5947     sort!("a < b")(a);
5948     assert(isSorted!("a < b")(a));
5949
5950     // sort using function; all elements equal
5951     foreach (ref e; a) {
5952         e = 5;
5953     }
5954     static bool less(int a, int b) { return a < b; }
5955     sort!(less)(a);
5956     assert(isSorted!(less)(a));
5957
5958     string[] words = [ "aBc", "a", "abc", "b", "ABC", "c" ];
5959     bool lessi(string a, string b) { return toupper(a) < toupper(b); }
5960     sort!(lessi, SwapStrategy.stable)(words);
5961     assert(words == [ "a", "aBc", "abc", "ABC", "b", "c" ]);
5962
5963     // sort using ternary predicate
5964     //sort!("b - a")(a);
5965     //assert(isSorted!(less)(a));
5966
5967     a = rndstuff!(int);
5968     sort(a);
5969     assert(isSorted(a));
5970     auto b = rndstuff!(string);
5971     sort!("tolower(a) < tolower(b)")(b);
5972     assert(isSorted!("toupper(a) < toupper(b)")(b));
5973 }
5974
5975 // @@@BUG1904
5976 /*private*/
5977 size_t getPivot(alias less, Range)(Range r)
5978 {
5979     return r.length / 2;
5980 }
5981
5982 // @@@BUG1904
5983 /*private*/
5984 void optimisticInsertionSort(alias less, Range)(Range r)
5985 {
5986     if (r.length <= 1) return;
5987     for (auto i = 1; i != r.length; )
5988     {
5989         // move to the left to find the insertion point
5990         auto p = i - 1;
5991         for (;;)
5992         {
5993             if (!less(r[i], r[p]))
5994             {
5995                 ++p;
5996                 break;
5997             }
5998             if (p == 0) break;
5999             --p;
6000         }
6001         if (i == p)
6002         {
6003             // already in place
6004             ++i;
6005             continue;
6006         }
6007         assert(less(r[i], r[p]));
6008         // move up to see how many we can insert
6009         auto iOld = i, iPrev = i;
6010         ++i;
6011         // The code commented below has a darn bug in it.
6012         // while (i != r.length && less(r[i], r[p]) && !less(r[i], r[iPrev]))
6013         // {
6014         //     ++i;
6015         //     ++iPrev;
6016         // }
6017         // do the insertion
6018         //assert(isSorted!(less)(r[0 .. iOld]));
6019         //assert(isSorted!(less)(r[iOld .. i]));
6020         //assert(less(r[i - 1], r[p]));
6021         //assert(p == 0 || !less(r[i - 1], r[p - 1]));
6022         bringToFront(r[p .. iOld], r[iOld .. i]);
6023         //assert(isSorted!(less)(r[0 .. i]));
6024     }
6025 }
6026
6027 unittest
6028 {
6029     debug(std_algorithm) scope(success)
6030         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
6031     auto rnd = Random(1);
6032     int a[] = new int[uniform(100, 200, rnd)];
6033     foreach (ref e; a) {
6034         e = uniform(-100, 100, rnd);
6035     }
6036
6037     optimisticInsertionSort!(binaryFun!("a < b"), int[])(a);
6038     assert(isSorted(a));
6039 }
6040
6041 // private
6042 void swapAt(R)(R r, size_t i1, size_t i2)
6043 {
6044     static if (is(typeof(&r[i1])))
6045     {
6046         swap(r[i1], r[i2]);
6047     }
6048     else
6049     {
6050         if (i1 == i2) return;
6051         auto t1 = moveAt(r, i1);
6052         auto t2 = moveAt(r, i2);
6053         r[i2] = t1;
6054         r[i1] = t2;
6055     }
6056 }
6057
6058 // @@@BUG1904
6059 /*private*/
6060 void sortImpl(alias less, SwapStrategy ss, Range)(Range r)
6061 {
6062     alias ElementType!(Range) Elem;
6063     enum uint optimisticInsertionSortGetsBetter = 1;
6064     static assert(optimisticInsertionSortGetsBetter >= 1);
6065
6066     while (r.length > optimisticInsertionSortGetsBetter)
6067     {
6068         const pivotIdx = getPivot!(less)(r);
6069         // partition
6070         static if (ss == SwapStrategy.unstable)
6071         {
6072             // partition
6073             swapAt(r, pivotIdx, r.length - 1);
6074             bool pred(ElementType!(Range) a)
6075             {
6076                 return less(a, r.back);
6077             }
6078             auto right = partition!(pred, ss)(r);
6079             swapAt(r, r.length - right.length, r.length - 1);
6080             // done with partitioning
6081             if (r.length == right.length)
6082             {
6083                 // worst case: *b <= everything (also pivot <= everything)
6084                 // avoid quadratic behavior
6085                 do r.popFront; while (!r.empty && !less(right.front, r.front));
6086             }
6087             else
6088             {
6089                 auto left = r[0 .. r.length - right.length];
6090                 right.popFront; // no need to consider right.front,
6091                                 // it's in the proper place already
6092                 if (right.length > left.length)
6093                 {
6094                     swap(left, right);
6095                 }
6096                 .sortImpl!(less, ss, Range)(right);
6097                 r = left;
6098             }
6099         }
6100         else // handle semistable and stable the same
6101         {
6102             auto pivot = r[pivotIdx];
6103             static assert(ss != SwapStrategy.semistable);
6104             bool pred(Elem a) { return less(a, pivot); }
6105             auto right = partition!(pred, ss)(r);
6106             if (r.length == right.length)
6107             {
6108                 // bad, bad pivot. pivot <= everything
6109                 // find the first occurrence of the pivot
6110                 bool pred1(Elem a) { return !less(pivot, a); }
6111                 //auto firstPivotPos = find!(pred1)(r).ptr;
6112                 auto pivotSpan = find!(pred1)(r);
6113                 assert(!pivotSpan.empty);
6114                 assert(!less(pivotSpan.front, pivot)
6115                        && !less(pivot, pivotSpan.front));
6116                 // find the last occurrence of the pivot
6117                 bool pred2(Elem a) { return less(pivot, a); }
6118                 //auto lastPivotPos = find!(pred2)(pivotsRight[1 .. $]).ptr;
6119                 auto pivotRunLen = find!(pred2)(pivotSpan[1 .. $]).length;
6120                 pivotSpan = pivotSpan[0 .. pivotRunLen + 1];
6121                 // now rotate firstPivotPos..lastPivotPos to the front
6122                 bringToFront(r, pivotSpan);
6123                 r = r[pivotSpan.length .. $];
6124             }
6125             else
6126             {
6127                 .sortImpl!(less, ss, Range)(r[0 .. r.length - right.length]);
6128                 r = right;
6129             }
6130         }
6131     }
6132     // residual sort
6133     static if (optimisticInsertionSortGetsBetter > 1)
6134     {
6135         optimisticInsertionSort!(less, Range)(r);
6136     }
6137 }
6138
6139 // schwartzSort
6140 /**
6141 Sorts a range using an algorithm akin to the $(WEB
6142 wikipedia.org/wiki/Schwartzian_transform, Schwartzian transform), also
6143 known as the decorate-sort-undecorate pattern in Python and Lisp. (Not
6144 to be confused with $(WEB youtube.com/watch?v=S25Zf8svHZQ, the other
6145 Schwartz).) This function is helpful when the sort comparison includes
6146 an expensive computation. The complexity is the same as that of the
6147 corresponding $(D sort), but $(D schwartzSort) evaluates $(D
6148 transform) only $(D r.length) times (less than half when compared to
6149 regular sorting). The usage can be best illustrated with an example.
6150
6151 Example:
6152
6153 ----
6154 uint hashFun(string) { ... expensive computation ... }
6155 string[] array = ...;
6156 // Sort strings by hash, slow
6157 sort!("hashFun(a) < hashFun(b)")(array);
6158 // Sort strings by hash, fast (only computes arr.length hashes):
6159 schwartzSort!(hashFun, "a < b")(array);
6160 ----
6161
6162 The $(D schwartzSort) function might require less temporary data and
6163 be faster than the Perl idiom or the decorate-sort-undecorate idiom
6164 present in Python and Lisp. This is because sorting is done in-place
6165 and only minimal extra data (one array of transformed elements) is
6166 created.
6167
6168 To check whether an array was sorted and benefit of the speedup of
6169 Schwartz sorting, a function $(D schwartzIsSorted) is not provided
6170 because the effect can be achieved by calling $(D
6171 isSorted!(less)(map!(transform)(r))).
6172  */
6173 void schwartzSort(alias transform, alias less = "a < b",
6174         SwapStrategy ss = SwapStrategy.unstable, Range)(Range r)
6175     if (isRandomAccessRange!(Range) && hasLength!(Range))
6176 {
6177     alias typeof(transform(r.front)) XformType;
6178     auto xform = new XformType[r.length];
6179     foreach (i, e; r)
6180     {
6181         xform[i] = transform(e);
6182     }
6183     auto z = zip(xform, r);
6184     alias typeof(z.front()) ProxyType;
6185     bool myLess(ProxyType a, ProxyType b)
6186     {
6187         return binaryFun!less(a[0], b[0]);
6188     }
6189     sort!(myLess, ss)(z);
6190 }
6191
6192 unittest
6193 {
6194     debug(std_algorithm) scope(success)
6195         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
6196     static double entropy(double[] probs) {
6197         double result = 0;
6198         foreach (p; probs) {
6199             if (!p) continue;
6200             //enforce(p > 0 && p <= 1, "Wrong probability passed to entropy");
6201             result -= p * log2(p);
6202         }
6203         return result;
6204     }
6205
6206     auto lowEnt = ([ 1.0, 0, 0 ]).dup,
6207         midEnt = ([ 0.1, 0.1, 0.8 ]).dup,
6208         highEnt = ([ 0.31, 0.29, 0.4 ]).dup;
6209     double arr[][] = new double[][3];
6210     arr[0] = midEnt;
6211     arr[1] = lowEnt;
6212     arr[2] = highEnt;
6213
6214     schwartzSort!(entropy, q{a > b})(arr);
6215     assert(arr[0] == highEnt);
6216     assert(arr[1] == midEnt);
6217     assert(arr[2] == lowEnt);
6218     assert(isSorted!("a > b")(map!(entropy)(arr)));
6219 }
6220
6221 unittest
6222 {
6223     debug(std_algorithm) scope(success)
6224         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
6225     static double entropy(double[] probs) {
6226         double result = 0;
6227         foreach (p; probs) {
6228             if (!p) continue;
6229             //enforce(p > 0 && p <= 1, "Wrong probability passed to entropy");
6230             result -= p * log2(p);
6231         }
6232         return result;
6233     }
6234
6235     auto lowEnt = ([ 1.0, 0, 0 ]).dup,
6236         midEnt = ([ 0.1, 0.1, 0.8 ]).dup,
6237         highEnt = ([ 0.31, 0.29, 0.4 ]).dup;
6238     double arr[][] = new double[][3];
6239     arr[0] = midEnt;
6240     arr[1] = lowEnt;
6241     arr[2] = highEnt;
6242
6243     schwartzSort!(entropy, q{a < b})(arr);
6244     assert(arr[0] == lowEnt);
6245     assert(arr[1] == midEnt);
6246     assert(arr[2] == highEnt);
6247     assert(isSorted!("a < b")(map!(entropy)(arr)));
6248 }
6249
6250 // partialSort
6251 /**
6252 Reorders the random-access range $(D r) such that the range $(D r[0
6253 .. mid]) is the same as if the entire $(D r) were sorted, and leaves
6254 the range $(D r[mid .. r.length]) in no particular order. Performs
6255 $(BIGOH r.length * log(mid)) evaluations of $(D pred). The
6256 implementation simply calls $(D topN!(less, ss)(r, n)) and then $(D
6257 sort!(less, ss)(r[0 .. n])).
6258
6259 Example:
6260 ----
6261 int[] a = [ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 ];
6262 partialSort(a, 5);
6263 assert(a[0 .. 5] == [ 0, 1, 2, 3, 4 ]);
6264 ----
6265 */
6266 void partialSort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable,
6267     Range)(Range r, size_t n)
6268     if (isRandomAccessRange!(Range) && hasLength!(Range) && hasSlicing!(Range))
6269 {
6270     topN!(less, ss)(r, n);
6271     sort!(less, ss)(r[0 .. n]);
6272 }
6273
6274 unittest
6275 {
6276     debug(std_algorithm) scope(success)
6277         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
6278     int[] a = [ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 ];
6279     partialSort(a, 5);
6280     assert(a[0 .. 5] == [ 0, 1, 2, 3, 4 ]);
6281 }
6282
6283 // completeSort
6284 /**
6285 Sorts the random-access range $(D chain(lhs, rhs)) according to
6286 predicate $(D less). The left-hand side of the range $(D lhs) is
6287 assumed to be already sorted; $(D rhs) is assumed to be unsorted. The
6288 exact strategy chosen depends on the relative sizes of $(D lhs) and
6289 $(D rhs).  Performs $(BIGOH lhs.length + rhs.length * log(rhs.length))
6290 (best case) to $(BIGOH (lhs.length + rhs.length) * log(lhs.length +
6291 rhs.length)) (worst-case) evaluations of $(D swap).
6292
6293 Example:
6294 ----
6295 int[] a = [ 1, 2, 3 ];
6296 int[] b = [ 4, 0, 6, 5 ];
6297 completeSort(assumeSorted(a), b);
6298 assert(a == [ 0, 1, 2 ]);
6299 assert(b == [ 3, 4, 5, 6 ]);
6300 ----
6301 */
6302 void completeSort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable,
6303         Range1, Range2)(SortedRange!(Range1, less) lhs, Range2 rhs)
6304 if (hasLength!(Range2) && hasSlicing!(Range2))
6305 {
6306     // Probably this algorithm can be optimized by using in-place
6307     // merge
6308     auto lhsOriginal = lhs.release();
6309     foreach (i; 0 .. rhs.length)
6310     {
6311         auto sortedSoFar = chain(lhsOriginal, rhs[0 .. i]);
6312         auto ub = assumeSorted!less(sortedSoFar).upperBound(rhs[i]);
6313         if (!ub.length) continue;
6314         bringToFront(ub.release(), rhs[i .. i + 1]);
6315     }
6316 }
6317
6318 unittest
6319 {
6320     debug(std_algorithm) scope(success)
6321        writeln("unittest @", __FILE__, ":", __LINE__, " done.");
6322     int[] a = [ 1, 2, 3 ];
6323     int[] b = [ 4, 0, 6, 5 ];
6324     // @@@BUG@@@ The call below should work
6325     // completeSort(assumeSorted(a), b);
6326     completeSort!("a < b", SwapStrategy.unstable, int[], int[])(
6327         assumeSorted(a), b);
6328     assert(a == [ 0, 1, 2 ]);
6329     assert(b == [ 3, 4, 5, 6 ]);
6330 }
6331
6332 // isSorted
6333 /**
6334 Checks whether a forward range is sorted according to the comparison
6335 operation $(D less). Performs $(BIGOH r.length) evaluations of $(D
6336 less).
6337
6338 Example:
6339 ----
6340 int[] arr = [4, 3, 2, 1];
6341 assert(!isSorted(arr));
6342 sort(arr);
6343 assert(isSorted(arr));
6344 sort!("a > b")(arr);
6345 assert(isSorted!("a > b")(arr));
6346 ----
6347 */
6348 bool isSorted(alias less = "a < b", Range)(Range r) if (isForwardRange!(Range))
6349 {
6350     // @@@BUG@@@ Should work with inlined predicate
6351     bool pred(ElementType!Range a, ElementType!Range b)
6352     {
6353         return binaryFun!less(b, a);
6354     }
6355     return findAdjacent!pred(r).empty;
6356 }
6357
6358 // makeIndex
6359 /**
6360 Computes an index for $(D r) based on the comparison $(D less). The
6361 index is a sorted array of pointers or indices into the original
6362 range. This technique is similar to sorting, but it is more flexible
6363 because (1) it allows "sorting" of immutable collections, (2) allows
6364 binary search even if the original collection does not offer random
6365 access, (3) allows multiple indexes, each on a different predicate,
6366 and (4) may be faster when dealing with large objects. However, using
6367 an index may also be slower under certain circumstances due to the
6368 extra indirection, and is always larger than a sorting-based solution
6369 because it needs space for the index in addition to the original
6370 collection. The complexity is the same as $(D sort)'s.
6371
6372 $(D makeIndex) overwrites its second argument with the result, but
6373 never reallocates it. If the second argument's length is less than
6374 that of the range indexed, an exception is thrown.
6375
6376 The first overload of $(D makeIndex) writes to a range containing
6377 pointers, and the second writes to a range containing offsets. The
6378 first overload requires $(D Range) to be a forward range, and the
6379 latter requires it to be a random-access range.
6380
6381 Example:
6382 ----
6383 immutable(int[]) arr = [ 2, 3, 1, 5, 0 ];
6384 // index using pointers
6385 auto index1 = new immutable(int)*[arr.length];
6386 makeIndex!("a < b")(arr, index1);
6387 assert(isSorted!("*a < *b")(index1));
6388 // index using offsets
6389 auto index2 = new size_t[arr.length];
6390 makeIndex!("a < b")(arr, index2);
6391 assert(isSorted!
6392     ((size_t a, size_t b){ return arr[a] < arr[b];})
6393     (index2));
6394 ----
6395 */
6396 void makeIndex(
6397     alias less = "a < b",
6398     SwapStrategy ss = SwapStrategy.unstable,
6399     Range,
6400     RangeIndex)
6401 (Range r, RangeIndex index)
6402     if (isForwardRange!(Range) && isRandomAccessRange!(RangeIndex)
6403             && is(ElementType!(RangeIndex) : ElementType!(Range)*))
6404 {
6405     // assume collection already ordered
6406     size_t i;
6407     for (; !r.empty; r.popFront, ++i)
6408         index[i] = &(r.front);
6409     enforce(index.length == i);
6410     // sort the index
6411     static bool indirectLess(ElementType!(RangeIndex) a,
6412             ElementType!(RangeIndex) b)
6413     {
6414         return binaryFun!(less)(*a, *b);
6415     }
6416     sort!(indirectLess, ss)(index);
6417 }
6418
6419 /// Ditto
6420 void makeIndex(
6421     alias less = "a < b",
6422     SwapStrategy ss = SwapStrategy.unstable,
6423     Range,
6424     RangeIndex)
6425 (Range r, RangeIndex index)
6426     if (isRandomAccessRange!(Range) && isRandomAccessRange!(RangeIndex)
6427             && isIntegral!(ElementType!(RangeIndex)))
6428 {
6429     // assume collection already ordered
6430     size_t i;
6431     auto r1 = r;
6432     for (; !r1.empty; r1.popFront, ++i)
6433         index[i] = i;
6434     enforce(index.length == i);
6435     // sort the index
6436     bool indirectLess(ElementType!(RangeIndex) a, ElementType!(RangeIndex) b)
6437     {
6438         return binaryFun!(less)(r[a], r[b]);
6439     }
6440     sort!(indirectLess, ss)(index);
6441 }
6442
6443 unittest
6444 {
6445     debug(std_algorithm) scope(success)
6446         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
6447     immutable(int)[] arr = [ 2, 3, 1, 5, 0 ];
6448     // index using pointers
6449     auto index1 = new immutable(int)*[arr.length];
6450     alias typeof(arr) ImmRange;
6451     alias typeof(index1) ImmIndex;
6452     static assert(isForwardRange!(ImmRange));
6453     static assert(isRandomAccessRange!(ImmIndex));
6454     static assert(!isIntegral!(ElementType!(ImmIndex)));
6455     static assert(is(ElementType!(ImmIndex) : ElementType!(ImmRange)*));
6456     makeIndex!("a < b")(arr, index1);
6457     assert(isSorted!("*a < *b")(index1));
6458
6459     // index using offsets
6460     auto index2 = new size_t[arr.length];
6461     makeIndex(arr, index2);
6462     assert(isSorted!
6463             ((size_t a, size_t b){ return arr[a] < arr[b];})
6464             (index2));
6465
6466     // index strings using offsets
6467     string[] arr1 = ["I", "have", "no", "chocolate"];
6468     auto index3 = new size_t[arr1.length];
6469     makeIndex(arr1, index3);
6470     assert(isSorted!
6471             ((size_t a, size_t b){ return arr1[a] < arr1[b];})
6472             (index3));
6473 }
6474
6475 /**
6476 Specifies whether the output of certain algorithm is desired in sorted
6477 format.
6478  */
6479 enum SortOutput {
6480     no,  /// Don't sort output
6481     yes, /// Sort output
6482 }
6483
6484 void topNIndex(
6485     alias less = "a < b",
6486     SwapStrategy ss = SwapStrategy.unstable,
6487     Range, RangeIndex)(Range r, RangeIndex index, SortOutput sorted = SortOutput.no)
6488 if (isIntegral!(ElementType!(RangeIndex)))
6489 {
6490     if (index.empty) return;
6491     enforce(ElementType!(RangeIndex).max >= index.length,
6492             "Index type too small");
6493     bool indirectLess(ElementType!(RangeIndex) a, ElementType!(RangeIndex) b)
6494     {
6495         return binaryFun!(less)(r[a], r[b]);
6496     }
6497     auto heap = BinaryHeap!(RangeIndex, indirectLess)(index, 0);
6498     foreach (i; 0 .. r.length)
6499     {
6500         heap.conditionalInsert(cast(ElementType!RangeIndex) i);
6501     }
6502     if (sorted == SortOutput.yes)
6503     {
6504         while (!heap.empty) heap.removeFront();
6505     }
6506 }
6507
6508 void topNIndex(
6509     alias less = "a < b",
6510     SwapStrategy ss = SwapStrategy.unstable,
6511     Range, RangeIndex)(Range r, RangeIndex index,
6512             SortOutput sorted = SortOutput.no)
6513 if (is(ElementType!(RangeIndex) == ElementType!(Range)*))
6514 {
6515     if (index.empty) return;
6516     static bool indirectLess(const ElementType!(RangeIndex) a,
6517             const ElementType!(RangeIndex) b)
6518     {
6519         return binaryFun!less(*a, *b);
6520     }
6521     auto heap = BinaryHeap!(RangeIndex, indirectLess)(index, 0);
6522     foreach (i; 0 .. r.length)
6523     {
6524         heap.conditionalInsert(&r[i]);
6525     }
6526     if (sorted == SortOutput.yes)
6527     {
6528         while (!heap.empty) heap.removeFront();
6529     }
6530 }
6531
6532 unittest
6533 {
6534     debug(std_algorithm) scope(success)
6535         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
6536     {
6537         int[] a = [ 10, 8, 9, 2, 4, 6, 7, 1, 3, 5 ];
6538         int*[] b = new int*[5];
6539         topNIndex!("a > b")(a, b, SortOutput.yes);
6540         //foreach (e; b) writeln(*e);
6541         assert(b == [ &a[0], &a[2], &a[1], &a[6], &a[5]]);
6542     }
6543     {
6544         int[] a = [ 10, 8, 9, 2, 4, 6, 7, 1, 3, 5 ];
6545         auto b = new ubyte[5];
6546         topNIndex!("a > b")(a, b, SortOutput.yes);
6547         //foreach (e; b) writeln(e, ":", a[e]);
6548         assert(b == [ cast(ubyte) 0, cast(ubyte)2, cast(ubyte)1, cast(ubyte)6, cast(ubyte)5], text(b));
6549     }
6550 }
6551 /+
6552
6553 // topNIndexImpl
6554 // @@@BUG1904
6555 /*private*/ void topNIndexImpl(
6556     alias less,
6557     bool sortAfter,
6558     SwapStrategy ss,
6559     SRange, TRange)(SRange source, TRange target)
6560 {
6561     alias binaryFun!(less) lessFun;
6562     static assert(ss == SwapStrategy.unstable,
6563             "Stable indexing not yet implemented");
6564     alias Iterator!(SRange) SIter;
6565     alias std.iterator.ElementType!(TRange) TElem;
6566     enum usingInt = isIntegral!(TElem);
6567
6568     static if (usingInt)
6569     {
6570         enforce(source.length <= TElem.max,
6571                 "Numeric overflow at risk in computing topNIndexImpl");
6572     }
6573
6574     // types and functions used within
6575     SIter index2iter(TElem a)
6576     {
6577         static if (!usingInt)
6578             return a;
6579         else
6580             return begin(source) + a;
6581     }
6582     bool indirectLess(TElem a, TElem b)
6583     {
6584         return lessFun(*index2iter(a), *index2iter(b));
6585     }
6586     void indirectCopy(SIter from, ref TElem to)
6587     {
6588         static if (!usingInt)
6589             to = from;
6590         else
6591             to = cast(TElem)(from - begin(source));
6592     }
6593
6594     // copy beginning of collection into the target
6595     auto sb = begin(source), se = end(source),
6596         tb = begin(target), te = end(target);
6597     for (; sb != se; ++sb, ++tb)
6598     {
6599         if (tb == te) break;
6600         indirectCopy(sb, *tb);
6601     }
6602
6603     // if the index's size is same as the source size, just quicksort it
6604     // otherwise, heap-insert stuff in it.
6605     if (sb == se)
6606     {
6607         // everything in source is now in target... just sort the thing
6608         static if (sortAfter) sort!(indirectLess, ss)(target);
6609     }
6610     else
6611     {
6612         // heap-insert
6613         te = tb;
6614         tb = begin(target);
6615         target = range(tb, te);
6616         makeHeap!(indirectLess)(target);
6617         // add stuff to heap
6618         for (; sb != se; ++sb)
6619         {
6620             if (!lessFun(*sb, *index2iter(*tb))) continue;
6621             // copy the source over the smallest
6622             indirectCopy(sb, *tb);
6623             heapify!(indirectLess)(target, tb);
6624         }
6625         static if (sortAfter) sortHeap!(indirectLess)(target);
6626     }
6627 }
6628
6629 /**
6630 topNIndex
6631 */
6632 void topNIndex(
6633     alias less,
6634     SwapStrategy ss = SwapStrategy.unstable,
6635     SRange, TRange)(SRange source, TRange target)
6636 {
6637     return .topNIndexImpl!(less, false, ss)(source, target);
6638 }
6639
6640 /// Ditto
6641 void topNIndex(
6642     string less,
6643     SwapStrategy ss = SwapStrategy.unstable,
6644     SRange, TRange)(SRange source, TRange target)
6645 {
6646     return .topNIndexImpl!(binaryFun!(less), false, ss)(source, target);
6647 }
6648
6649 // partialIndex
6650 /**
6651 Computes an index for $(D source) based on the comparison $(D less)
6652 and deposits the result in $(D target). It is acceptable that $(D
6653 target.length < source.length), in which case only the smallest $(D
6654 target.length) elements in $(D source) get indexed. The target
6655 provides a sorted "view" into $(D source). This technique is similar
6656 to sorting and partial sorting, but it is more flexible because (1) it
6657 allows "sorting" of immutable collections, (2) allows binary search
6658 even if the original collection does not offer random access, (3)
6659 allows multiple indexes, each on a different comparison criterion, (4)
6660 may be faster when dealing with large objects. However, using an index
6661 may also be slower under certain circumstances due to the extra
6662 indirection, and is always larger than a sorting-based solution
6663 because it needs space for the index in addition to the original
6664 collection. The complexity is $(BIGOH source.length *
6665 log(target.length)).
6666
6667 Two types of indexes are accepted. They are selected by simply passing
6668 the appropriate $(D target) argument: $(OL $(LI Indexes of type $(D
6669 Iterator!(Source)), in which case the index will be sorted with the
6670 predicate $(D less(*a, *b));) $(LI Indexes of an integral type
6671 (e.g. $(D size_t)), in which case the index will be sorted with the
6672 predicate $(D less(source[a], source[b])).))
6673
6674 Example:
6675
6676 ----
6677 immutable arr = [ 2, 3, 1 ];
6678 int* index[3];
6679 partialIndex(arr, index);
6680 assert(*index[0] == 1 && *index[1] == 2 && *index[2] == 3);
6681 assert(isSorted!("*a < *b")(index));
6682 ----
6683 */
6684 void partialIndex(
6685     alias less,
6686     SwapStrategy ss = SwapStrategy.unstable,
6687     SRange, TRange)(SRange source, TRange target)
6688 {
6689     return .topNIndexImpl!(less, true, ss)(source, target);
6690 }
6691
6692 unittest
6693 {
6694     debug(std_algorithm) scope(success)
6695         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
6696     immutable arr = [ 2, 3, 1 ];
6697     auto index = new immutable(int)*[3];
6698     partialIndex!(binaryFun!("a < b"))(arr, index);
6699     assert(*index[0] == 1 && *index[1] == 2 && *index[2] == 3);
6700     assert(isSorted!("*a < *b")(index));
6701 }
6702
6703 unittest
6704 {
6705     debug(std_algorithm) scope(success)
6706         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
6707     static bool less(int a, int b) { return a < b; }
6708     {
6709         string[] x = ([ "c", "a", "b", "d" ]).dup;
6710         // test with integrals
6711         auto index1 = new size_t[x.length];
6712         partialIndex!(q{a < b})(x, index1);
6713         assert(index1[0] == 1 && index1[1] == 2 && index1[2] == 0
6714                && index1[3] == 3);
6715         // half-sized
6716         index1 = new size_t[x.length / 2];
6717         partialIndex!(q{a < b})(x, index1);
6718         assert(index1[0] == 1 && index1[1] == 2);
6719
6720         // and with iterators
6721         auto index = new string*[x.length];
6722         partialIndex!(q{a < b})(x, index);
6723         assert(isSorted!(q{*a < *b})(index));
6724         assert(*index[0] == "a" && *index[1] == "b" && *index[2] == "c"
6725                && *index[3] == "d");
6726     }
6727
6728     {
6729         immutable arr = [ 2, 3, 1 ];
6730         auto index = new immutable(int)*[arr.length];
6731         partialIndex!(less)(arr, index);
6732         assert(*index[0] == 1 && *index[1] == 2 && *index[2] == 3);
6733         assert(isSorted!(q{*a < *b})(index));
6734     }
6735
6736     // random data
6737     auto b = rndstuff!(string);
6738     auto index = new string*[b.length];
6739     partialIndex!("toupper(a) < toupper(b)")(b, index);
6740     assert(isSorted!("toupper(*a) < toupper(*b)")(index));
6741
6742     // random data with indexes
6743     auto index1 = new size_t[b.length];
6744     bool cmp(string x, string y) { return toupper(x) < toupper(y); }
6745     partialIndex!(cmp)(b, index1);
6746     bool check(size_t x, size_t y) { return toupper(b[x]) < toupper(b[y]); }
6747     assert(isSorted!(check)(index1));
6748 }
6749
6750 // Commented out for now, needs reimplementation
6751
6752 // // schwartzMakeIndex
6753 // /**
6754 // Similar to $(D makeIndex) but using $(D schwartzSort) to sort the
6755 // index.
6756
6757 // Example:
6758
6759 // ----
6760 // string[] arr = [ "ab", "c", "Ab", "C" ];
6761 // auto index = schwartzMakeIndex!(toupper, less, SwapStrategy.stable)(arr);
6762 // assert(*index[0] == "ab" && *index[1] == "Ab"
6763 //     && *index[2] == "c" && *index[2] == "C");
6764 // assert(isSorted!("toupper(*a) < toupper(*b)")(index));
6765 // ----
6766 // */
6767 // Iterator!(Range)[] schwartzMakeIndex(
6768 //     alias transform,
6769 //     alias less,
6770 //     SwapStrategy ss = SwapStrategy.unstable,
6771 //     Range)(Range r)
6772 // {
6773 //     alias Iterator!(Range) Iter;
6774 //     auto result = new Iter[r.length];
6775 //     // assume collection already ordered
6776 //     size_t i = 0;
6777 //     foreach (it; begin(r) .. end(r))
6778 //     {
6779 //         result[i++] = it;
6780 //     }
6781 //     // sort the index
6782 //     alias typeof(transform(*result[0])) Transformed;
6783 //     static bool indirectLess(Transformed a, Transformed b)
6784 //     {
6785 //         return less(a, b);
6786 //     }
6787 //     static Transformed indirectTransform(Iter a)
6788 //     {
6789 //         return transform(*a);
6790 //     }
6791 //     schwartzSort!(indirectTransform, less, ss)(result);
6792 //     return result;
6793 // }
6794
6795 // /// Ditto
6796 // Iterator!(Range)[] schwartzMakeIndex(
6797 //     alias transform,
6798 //     string less = q{a < b},
6799 //     SwapStrategy ss = SwapStrategy.unstable,
6800 //     Range)(Range r)
6801 // {
6802 //     return .schwartzMakeIndex!(
6803 //         transform, binaryFun!(less), ss, Range)(r);
6804 // }
6805
6806 // version (wyda) unittest
6807 // {
6808 //     string[] arr = [ "D", "ab", "c", "Ab", "C" ];
6809 //     auto index = schwartzMakeIndex!(toupper, "a < b",
6810 //                                     SwapStrategy.stable)(arr);
6811 //     assert(isSorted!(q{toupper(*a) < toupper(*b)})(index));
6812 //     assert(*index[0] == "ab" && *index[1] == "Ab"
6813 //            && *index[2] == "c" && *index[3] == "C");
6814
6815 //     // random data
6816 //     auto b = rndstuff!(string);
6817 //     auto index1 = schwartzMakeIndex!(toupper)(b);
6818 //     assert(isSorted!("toupper(*a) < toupper(*b)")(index1));
6819 // }
6820
6821 +/
6822
6823 // canFind
6824 /**
6825 Returns $(D true) if and only if $(D value) can be found in $(D
6826 range). Performs $(BIGOH r.length) evaluations of $(D pred). */
6827
6828 bool canFind(alias pred = "a == b", Range, V)(Range range, V value)
6829 if (is(typeof(find!pred(range, value))))
6830 {
6831     return !find!pred(range, value).empty;
6832 }
6833
6834 unittest
6835 {
6836     debug(std_algorithm) scope(success)
6837         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
6838     auto a = rndstuff!(int);
6839     if (a.length)
6840     {
6841         auto b = a[a.length / 2];
6842         assert(canFind(a, b));
6843     }
6844 }
6845
6846 // canFind
6847 /**
6848 Returns $(D true) if and only if a value $(D v) satisfying the
6849 predicate $(D pred) can be found in the forward range $(D
6850 range). Performs $(BIGOH r.length) evaluations of $(D pred).
6851  */
6852
6853 bool canFind(alias pred, Range)(Range range)
6854 if (is(typeof(find!pred(range))))
6855 {
6856     return !find!pred(range).empty;
6857 }
6858
6859 unittest
6860 {
6861     debug(std_algorithm) scope(success)
6862         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
6863     auto a = [ 1, 2, 0, 4 ];
6864     assert(canFind!"a == 2"(a));
6865 }
6866
6867 // Scheduled for deprecation.  Use std.range.SortedRange.canFind.
6868 bool canFindSorted(alias pred = "a < b", Range, V)(Range range, V value) {
6869     pragma(msg, "std.algorithm.canFindSorted is scheduled for " ~
6870         "deprecation.  Use std.range.SortedRange.canFind instead.");
6871     return assumeSorted!pred(range).canFind!V(value);
6872 }
6873
6874 // Scheduled for deprecation.  Use std.range.SortedRange.lowerBound.
6875 Range lowerBound(alias pred = "a < b", Range, V)(Range range, V value) {
6876     pragma(msg, "std.algorithm.lowerBound is scheduled for " ~
6877         "deprecation.  Use std.range.SortedRange.lowerBound instead.");
6878     return assumeSorted!pred(range).lowerBound!V(value).release;
6879 }
6880
6881 // Scheduled for deprecation.  Use std.range.SortedRange.upperBound.
6882 Range upperBound(alias pred = "a < b", Range, V)(Range range, V value) {
6883     pragma(msg, "std.algorithm.upperBound is scheduled for " ~
6884         "deprecation.  Use std.range.SortedRange.upperBound instead.");
6885     return assumeSorted!pred(range).upperBound!V(value).release;
6886 }
6887
6888 // Scheduled for deprecation.  Use std.range.SortedRange.equalRange.
6889 Range equalRange(alias pred = "a < b", Range, V)(Range range, V value) {
6890     pragma(msg, "std.algorithm.equalRange is scheduled for " ~
6891         "deprecation.  Use std.range.SortedRange.equalRange instead.");
6892     return assumeSorted!pred(range).equalRange!V(value).release;
6893 }
6894
6895 /**
6896 Copies the top $(D n) elements of the input range $(D source) into the
6897 random-access range $(D target), where $(D n =
6898 target.length). Elements of $(D source) are not touched. If $(D
6899 sorted) is $(D true), the target is sorted. Otherwise, the target
6900 respects the $(WEB en.wikipedia.org/wiki/Binary_heap, heap property).
6901
6902 Example:
6903 ----
6904 int[] a = [ 10, 16, 2, 3, 1, 5, 0 ];
6905 int[] b = new int[3];
6906 topNCopy(a, b, true);
6907 assert(b == [ 0, 1, 2 ]);
6908 ----
6909  */
6910 TRange topNCopy(alias less = "a < b", SRange, TRange)
6911     (SRange source, TRange target, SortOutput sorted = SortOutput.no)
6912     if (isInputRange!(SRange) && isRandomAccessRange!(TRange)
6913             && hasLength!(TRange) && hasSlicing!(TRange))
6914 {
6915     if (target.empty) return target;
6916     auto heap = BinaryHeap!(TRange, less)(target, 0);
6917     foreach (e; source) heap.conditionalInsert(e);
6918     auto result = target[0 .. heap.length];
6919     if (sorted == SortOutput.yes)
6920     {
6921         while (!heap.empty) heap.removeFront();
6922     }
6923     return result;
6924 }
6925
6926 unittest
6927 {
6928     debug(std_algorithm) scope(success)
6929         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
6930     int[] a = [ 10, 16, 2, 3, 1, 5, 0 ];
6931     int[] b = new int[3];
6932     topNCopy(a, b, SortOutput.yes);
6933     assert(b == [ 0, 1, 2 ]);
6934 }
6935
6936 unittest
6937 {
6938     debug(std_algorithm) scope(success)
6939         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
6940     auto r = Random(unpredictableSeed);
6941     sizediff_t[] a = new sizediff_t[uniform(1, 1000, r)];
6942     foreach (i, ref e; a) e = i;
6943     randomShuffle(a, r);
6944     auto n = uniform(0, a.length, r);
6945     sizediff_t[] b = new sizediff_t[n];
6946     topNCopy!(binaryFun!("a < b"))(a, b, SortOutput.yes);
6947     assert(isSorted!(binaryFun!("a < b"))(b));
6948 }
6949
6950 /**
6951 Lazily computes the union of two or more ranges $(D rs). The ranges
6952 are assumed to be sorted by $(D less). Elements in the output are not
6953 unique; the length of the output is the sum of the lengths of the
6954 inputs. (The $(D length) member is offered if all ranges also have
6955 length.) The element types of all ranges must have a common type.
6956
6957 Example:
6958 ----
6959 int[] a = [ 1, 2, 4, 5, 7, 9 ];
6960 int[] b = [ 0, 1, 2, 4, 7, 8 ];
6961 int[] c = [ 10 ];
6962 assert(setUnion(a, b).length == a.length + b.length);
6963 assert(equal(setUnion(a, b), [0, 1, 1, 2, 2, 4, 4, 5, 7, 7, 8, 9][]));
6964 assert(equal(setUnion(a, c, b),
6965     [0, 1, 1, 2, 2, 4, 4, 5, 7, 7, 8, 9, 10][]));
6966 ----
6967  */
6968 struct SetUnion(alias less = "a < b", Rs...) if (allSatisfy!(isInputRange, Rs))
6969 {
6970 private:
6971     Rs _r;
6972     alias binaryFun!(less) comp;
6973     uint _crt;
6974
6975     void adjustPosition(uint candidate = 0)()
6976     {
6977         static if (candidate == Rs.length)
6978         {
6979             _crt = _crt.max;
6980         }
6981         else
6982         {
6983             if (_r[candidate].empty)
6984             {
6985                 adjustPosition!(candidate + 1)();
6986                 return;
6987             }
6988             foreach (i, U; Rs[candidate + 1 .. $])
6989             {
6990                 enum j = candidate + i + 1;
6991                 if (_r[j].empty) continue;
6992                 if (comp(_r[j].front, _r[candidate].front))
6993                 {
6994                     // a new candidate was found
6995                     adjustPosition!(j)();
6996                     return;
6997                 }
6998             }
6999             // Found a successful candidate
7000             _crt = candidate;
7001         }
7002     }
7003
7004 public:
7005     alias CommonType!(staticMap!(.ElementType, Rs)) ElementType;
7006
7007     this(Rs rs)
7008     {
7009         this._r = rs;
7010         adjustPosition();
7011     }
7012
7013     @property bool empty()
7014     {
7015         return _crt == _crt.max;
7016     }
7017
7018     void popFront()
7019     {
7020         // Assumes _crt is correct
7021         assert(!empty);
7022         foreach (i, U; Rs)
7023         {
7024             if (i < _crt) continue;
7025             // found _crt
7026             assert(!_r[i].empty);
7027             _r[i].popFront;
7028             adjustPosition();
7029             return;
7030         }
7031         assert(false);
7032     }
7033
7034     @property ElementType front()
7035     {
7036         assert(!empty);
7037         // Assume _crt is correct
7038         foreach (i, U; Rs)
7039         {
7040             if (i < _crt) continue;
7041             assert(!_r[i].empty);
7042             return _r[i].front;
7043         }
7044         assert(false);
7045     }
7046
7047     static if(allSatisfy!(isForwardRange, Rs))
7048     {
7049         @property typeof(this) save()
7050         {
7051             auto ret = this;
7052             foreach(ti, elem; _r)
7053             {
7054                 ret._r[ti] = elem.save;
7055             }
7056
7057             return ret;
7058         }
7059     }
7060
7061     static if (allSatisfy!(hasLength, Rs))
7062     {
7063         @property size_t length()
7064         {
7065             size_t result;
7066             foreach (i, U; Rs)
7067             {
7068                 result += _r[i].length;
7069             }
7070             return result;
7071         }
7072     }
7073 }
7074
7075 /// Ditto
7076 SetUnion!(less, Rs) setUnion(alias less = "a < b", Rs...)
7077 (Rs rs)
7078 {
7079     return typeof(return)(rs);
7080 }
7081
7082 unittest
7083 {
7084     debug(std_algorithm) scope(success)
7085         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
7086     int[] a = [ 1, 2, 4, 5, 7, 9 ];
7087     int[] b = [ 0, 1, 2, 4, 7, 8 ];
7088     int[] c = [ 10 ];
7089     //foreach (e; setUnion(a, b)) writeln(e);
7090     assert(setUnion(a, b).length == a.length + b.length);
7091     assert(equal(setUnion(a, b), [0, 1, 1, 2, 2, 4, 4, 5, 7, 7, 8, 9][]));
7092     assert(equal(setUnion(a, c, b),
7093                     [0, 1, 1, 2, 2, 4, 4, 5, 7, 7, 8, 9, 10][]));
7094
7095     static assert(isForwardRange!(typeof(setUnion(a, b))));
7096 }
7097
7098 /**
7099 Lazily computes the intersection of two or more input ranges $(D
7100 rs). The ranges are assumed to be sorted by $(D less). The element
7101 types of all ranges must have a common type.
7102
7103 Example:
7104 ----
7105 int[] a = [ 1, 2, 4, 5, 7, 9 ];
7106 int[] b = [ 0, 1, 2, 4, 7, 8 ];
7107 int[] c = [ 0, 1, 4, 5, 7, 8 ];
7108 assert(equal(setIntersection(a, a), a));
7109 assert(equal(setIntersection(a, b), [1, 2, 4, 7][]));
7110 assert(equal(setIntersection(a, b, c), [1, 4, 7][]));
7111 ----
7112  */
7113 struct SetIntersection(alias less = "a < b", Rs...)
7114 if (allSatisfy!(isInputRange, Rs))
7115 {
7116     static assert(Rs.length == 2);
7117 private:
7118     Rs _input;
7119     alias binaryFun!(less) comp;
7120     alias CommonType!(staticMap!(.ElementType, Rs)) ElementType;
7121
7122     void adjustPosition()
7123     {
7124         // Positions to the first two elements that are equal
7125         while (!empty)
7126         {
7127             if (comp(_input[0].front, _input[1].front))
7128             {
7129                 _input[0].popFront;
7130             }
7131             else if (comp(_input[1].front, _input[0].front))
7132             {
7133                 _input[1].popFront;
7134             }
7135             else
7136             {
7137                 break;
7138             }
7139         }
7140     }
7141
7142 public:
7143     this(Rs input)
7144     {
7145         this._input = input;
7146         // position to the first element
7147         adjustPosition;
7148     }
7149
7150     @property bool empty()
7151     {
7152         foreach (i, U; Rs)
7153         {
7154             if (_input[i].empty) return true;
7155         }
7156         return false;
7157     }
7158
7159     void popFront()
7160     {
7161         assert(!empty);
7162         assert(!comp(_input[0].front, _input[1].front)
7163                 && !comp(_input[1].front, _input[0].front));
7164         _input[0].popFront;
7165         _input[1].popFront;
7166         adjustPosition;
7167     }
7168
7169     @property ElementType front()
7170     {
7171         assert(!empty);
7172         return _input[0].front;
7173     }
7174
7175     static if(allSatisfy!(isForwardRange, Rs))
7176     {
7177         @property typeof(this) save()
7178         {
7179             auto ret = this;
7180             foreach(ti, elem; _input)
7181             {
7182                 ret._input[ti] = elem.save;
7183             }
7184
7185             return ret;
7186         }
7187     }
7188 }
7189
7190 /// Ditto
7191 SetIntersection!(less, Rs) setIntersection(alias less = "a < b", Rs...)
7192 (Rs ranges)
7193 if (allSatisfy!(isInputRange, Rs))
7194 {
7195     return typeof(return)(ranges);
7196 }
7197
7198 unittest
7199 {
7200     debug(std_algorithm) scope(success)
7201         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
7202     int[] a = [ 1, 2, 4, 5, 7, 9 ];
7203     int[] b = [ 0, 1, 2, 4, 7, 8 ];
7204     int[] c = [ 0, 1, 4, 5, 7, 8 ];
7205     //foreach (e; setIntersection(a, b, c)) writeln(e);
7206     assert(equal(setIntersection(a, b), [1, 2, 4, 7][]));
7207     assert(equal(setIntersection(a, a), a));
7208
7209     static assert(isForwardRange!(typeof(setIntersection(a, a))));
7210     // assert(equal(setIntersection(a, b, b, a), [1, 2, 4, 7][]));
7211     // assert(equal(setIntersection(a, b, c), [1, 4, 7][]));
7212     // assert(equal(setIntersection(a, c, b), [1, 4, 7][]));
7213     // assert(equal(setIntersection(b, a, c), [1, 4, 7][]));
7214     // assert(equal(setIntersection(b, c, a), [1, 4, 7][]));
7215     // assert(equal(setIntersection(c, a, b), [1, 4, 7][]));
7216     // assert(equal(setIntersection(c, b, a), [1, 4, 7][]));
7217 }
7218
7219 /**
7220 Lazily computes the difference of $(D r1) and $(D r2). The two ranges
7221 are assumed to be sorted by $(D less). The element types of the two
7222 ranges must have a common type.
7223
7224 Example:
7225 ----
7226 int[] a = [ 1, 2, 4, 5, 7, 9 ];
7227 int[] b = [ 0, 1, 2, 4, 7, 8 ];
7228 assert(equal(setDifference(a, b), [5, 9][]));
7229 ----
7230  */
7231 struct SetDifference(alias less = "a < b", R1, R2)
7232     if (isInputRange!(R1) && isInputRange!(R2))
7233 {
7234 private:
7235     R1 r1;
7236     R2 r2;
7237     alias binaryFun!(less) comp;
7238
7239     void adjustPosition()
7240     {
7241         while (!r1.empty)
7242         {
7243             if (r2.empty || comp(r1.front, r2.front)) break;
7244             if (comp(r2.front, r1.front))
7245             {
7246                 r2.popFront;
7247             }
7248             else
7249             {
7250                 // both are equal
7251                 r1.popFront;
7252                 r2.popFront;
7253             }
7254         }
7255     }
7256
7257 public:
7258     this(R1 r1, R2 r2)
7259     {
7260         this.r1 = r1;
7261         this.r2 = r2;
7262         // position to the first element
7263         adjustPosition;
7264     }
7265
7266     void popFront()
7267     {
7268         r1.popFront;
7269         adjustPosition;
7270     }
7271
7272     @property ElementType!(R1) front()
7273     {
7274         assert(!empty);
7275         return r1.front;
7276     }
7277
7278     static if(isForwardRange!R1 && isForwardRange!R2)
7279     {
7280         @property typeof(this) save()
7281         {
7282             auto ret = this;
7283             ret.r1 = r1.save;
7284             ret.r2 = r2.save;
7285             return ret;
7286         }
7287     }
7288
7289     bool empty() { return r1.empty; }
7290 }
7291
7292 /// Ditto
7293 SetDifference!(less, R1, R2) setDifference(alias less = "a < b", R1, R2)
7294 (R1 r1, R2 r2)
7295 {
7296     return typeof(return)(r1, r2);
7297 }
7298
7299 unittest
7300 {
7301     debug(std_algorithm) scope(success)
7302         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
7303     int[] a = [ 1, 2, 4, 5, 7, 9 ];
7304     int[] b = [ 0, 1, 2, 4, 7, 8 ];
7305     //foreach (e; setDifference(a, b)) writeln(e);
7306     assert(equal(setDifference(a, b), [5, 9][]));
7307     static assert(isForwardRange!(typeof(setDifference(a, b))));
7308 }
7309
7310 /**
7311 Lazily computes the symmetric difference of $(D r1) and $(D r2),
7312 i.e. the elements that are present in exactly one of $(D r1) and $(D
7313 r2). The two ranges are assumed to be sorted by $(D less), and the
7314 output is also sorted by $(D less). The element types of the two
7315 ranges must have a common type.
7316
7317 Example:
7318 ----
7319 int[] a = [ 1, 2, 4, 5, 7, 9 ];
7320 int[] b = [ 0, 1, 2, 4, 7, 8 ];
7321 assert(equal(setSymmetricDifference(a, b), [0, 5, 8, 9][]));
7322 ----
7323  */
7324 struct SetSymmetricDifference(alias less = "a < b", R1, R2)
7325     if (isInputRange!(R1) && isInputRange!(R2))
7326 {
7327 private:
7328     R1 r1;
7329     R2 r2;
7330     //bool usingR2;
7331     alias binaryFun!(less) comp;
7332
7333     void adjustPosition()
7334     {
7335         while (!r1.empty && !r2.empty)
7336         {
7337             if (comp(r1.front, r2.front) || comp(r2.front, r1.front))
7338             {
7339                 break;
7340             }
7341             // equal, pop both
7342             r1.popFront;
7343             r2.popFront;
7344         }
7345     }
7346
7347 public:
7348     this(R1 r1, R2 r2)
7349     {
7350         this.r1 = r1;
7351         this.r2 = r2;
7352         // position to the first element
7353         adjustPosition;
7354     }
7355
7356     void popFront()
7357     {
7358         assert(!empty);
7359         if (r1.empty) r2.popFront;
7360         else if (r2.empty) r1.popFront;
7361         else
7362         {
7363             // neither is empty
7364             if (comp(r1.front, r2.front))
7365             {
7366                 r1.popFront;
7367             }
7368             else
7369             {
7370                 assert(comp(r2.front, r1.front));
7371                 r2.popFront;
7372             }
7373         }
7374         adjustPosition;
7375     }
7376
7377     @property ElementType!(R1) front()
7378     {
7379         assert(!empty);
7380         if (r2.empty || !r1.empty && comp(r1.front, r2.front))
7381         {
7382             return r1.front;
7383         }
7384         assert(r1.empty || comp(r2.front, r1.front));
7385         return r2.front;
7386     }
7387
7388     static if(isForwardRange!R1 && isForwardRange!R2)
7389     {
7390         @property typeof(this) save()
7391         {
7392             auto ret = this;
7393             ret.r1 = r1.save;
7394             ret.r2 = r2.save;
7395             return ret;
7396         }
7397     }
7398
7399     ref auto opSlice() { return this; }
7400
7401     @property bool empty() { return r1.empty && r2.empty; }
7402 }
7403
7404 /// Ditto
7405 SetSymmetricDifference!(less, R1, R2)
7406 setSymmetricDifference(alias less = "a < b", R1, R2)
7407 (R1 r1, R2 r2)
7408 {
7409     return typeof(return)(r1, r2);
7410 }
7411
7412 unittest
7413 {
7414     debug(std_algorithm) scope(success)
7415         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
7416     int[] a = [ 1, 2, 4, 5, 7, 9 ];
7417     int[] b = [ 0, 1, 2, 4, 7, 8 ];
7418     //foreach (e; setSymmetricDifference(a, b)) writeln(e);
7419     assert(equal(setSymmetricDifference(a, b), [0, 5, 8, 9][]));
7420
7421     static assert(isForwardRange!(typeof(setSymmetricDifference(a, b))));
7422 }
7423
7424 // Internal random array generators
7425
7426 version(unittest)
7427 {
7428     private enum size_t maxArraySize = 50;
7429     private enum size_t minArraySize = maxArraySize - 1;
7430
7431     private string[] rndstuff(T : string)()
7432     {
7433         static Random rnd;
7434         static bool first = true;
7435         if (first)
7436         {
7437             rnd = Random(unpredictableSeed);
7438             first = false;
7439         }
7440         string[] result =
7441             new string[uniform(minArraySize, maxArraySize, rnd)];
7442         string alpha = "abcdefghijABCDEFGHIJ";
7443         foreach (ref s; result)
7444         {
7445             foreach (i; 0 .. uniform(0u, 20u, rnd))
7446             {
7447                 auto j = uniform(0, alpha.length - 1, rnd);
7448                 s ~= alpha[j];
7449             }
7450         }
7451         return result;
7452     }
7453
7454     private int[] rndstuff(T : int)()
7455     {
7456         static Random rnd;
7457         static bool first = true;
7458         if (first)
7459         {
7460             rnd = Random(unpredictableSeed);
7461             first = false;
7462         }
7463         int[] result = new int[uniform(minArraySize, maxArraySize, rnd)];
7464         foreach (ref i; result)
7465         {
7466             i = uniform(-100, 100, rnd);
7467         }
7468         return result;
7469     }
7470
7471     private double[] rndstuff(T : double)()
7472     {
7473         double[] result;
7474         foreach (i; rndstuff!(int)())
7475         {
7476             result ~= i / 50.;
7477         }
7478         return result;
7479     }
7480 }
7481
7482 // NWayUnion
7483 /**
7484 Computes the union of multiple sets. The input sets are passed as a
7485 range of ranges and each is assumed to be sorted by $(D
7486 less). Computation is done lazily, one union element at a time. The
7487 complexity of one $(D popFront) operation is $(BIGOH
7488 log(ror.length)). However, the length of $(D ror) decreases as ranges
7489 in it are exhausted, so the complexity of a full pass through $(D
7490 NWayUnion) is dependent on the distribution of the lengths of ranges
7491 contained within $(D ror). If all ranges have the same length $(D n)
7492 (worst case scenario), the complexity of a full pass through $(D
7493 NWayUnion) is $(BIGOH n * ror.length * log(ror.length)), i.e., $(D
7494 log(ror.length)) times worse than just spanning all ranges in
7495 turn. The output comes sorted (unstably) by $(D less).
7496
7497 Warning: Because $(D NWayUnion) does not allocate extra memory, it
7498 will leave $(D ror) modified. Namely, $(D NWayUnion) assumes ownership
7499 of $(D ror) and discretionarily swaps and advances elements of it. If
7500 you want $(D ror) to preserve its contents after the call, you may
7501 want to pass a duplicate to $(D NWayUnion) (and perhaps cache the
7502 duplicate in between calls).
7503
7504 Example:
7505 ----
7506 double[][] a =
7507 [
7508     [ 1, 4, 7, 8 ],
7509     [ 1, 7 ],
7510     [ 1, 7, 8],
7511     [ 4 ],
7512     [ 7 ],
7513 ];
7514 auto witness = [
7515     1, 1, 1, 4, 4, 7, 7, 7, 7, 8, 8
7516 ];
7517 assert(equal(nWayUnion(a), witness[]));
7518 ----
7519  */
7520 struct NWayUnion(alias less, RangeOfRanges)
7521 {
7522     private alias .ElementType!(.ElementType!RangeOfRanges) ElementType;
7523     private alias binaryFun!less comp;
7524     private RangeOfRanges _ror;
7525     static bool compFront(.ElementType!RangeOfRanges a,
7526             .ElementType!RangeOfRanges b)
7527     {
7528         // revert comparison order so we get the smallest elements first
7529         return comp(b.front, a.front);
7530     }
7531     BinaryHeap!(RangeOfRanges, compFront) _heap;
7532
7533     this(RangeOfRanges ror)
7534     {
7535         // Preemptively get rid of all empty ranges in the input
7536         // No need for stability either
7537         _ror = remove!("a.empty", SwapStrategy.unstable)(ror);
7538         //Build the heap across the range
7539         _heap.acquire(_ror);
7540     }
7541
7542     @property bool empty() { return _ror.empty; }
7543
7544     @property ref ElementType front()
7545     {
7546         return _heap.front.front;
7547     }
7548
7549     void popFront()
7550     {
7551         _heap.removeFront();
7552         // let's look at the guy just popped
7553         _ror.back.popFront;
7554         if (_ror.back.empty)
7555         {
7556             _ror.popBack;
7557             // nothing else to do: the empty range is not in the
7558             // heap and not in _ror
7559             return;
7560         }
7561         // Put the popped range back in the heap
7562         _heap.conditionalInsert(_ror.back) || assert(false);
7563     }
7564 }
7565
7566 /// Ditto
7567 NWayUnion!(less, RangeOfRanges) nWayUnion
7568 (alias less = "a < b", RangeOfRanges)
7569 (RangeOfRanges ror)
7570 {
7571     return typeof(return)(ror);
7572 }
7573
7574 unittest
7575 {
7576     debug(std_algorithm) scope(success)
7577         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
7578     double[][] a =
7579     [
7580         [ 1, 4, 7, 8 ],
7581         [ 1, 7 ],
7582         [ 1, 7, 8],
7583         [ 4 ],
7584         [ 7 ],
7585     ];
7586     auto witness = [
7587         1, 1, 1, 4, 4, 7, 7, 7, 7, 8, 8
7588     ];
7589     //foreach (e; nWayUnion(a)) writeln(e);
7590     assert(equal(nWayUnion(a), witness[]));
7591 }
7592
7593 // largestPartialIntersection
7594 /**
7595 Given a range of sorted forward ranges $(D ror), copies to $(D tgt)
7596 the elements that are common to most ranges, along with their number
7597 of occurrences. All ranges in $(D ror) are assumed to be sorted by $(D
7598 less). Only the most frequent $(D tgt.length) elements are returned.
7599
7600 Example:
7601 ----
7602 // Figure which number can be found in most arrays of the set of
7603 // arrays below.
7604 double[][] a =
7605 [
7606     [ 1, 4, 7, 8 ],
7607     [ 1, 7 ],
7608     [ 1, 7, 8],
7609     [ 4 ],
7610     [ 7 ],
7611 ];
7612 auto b = new Tuple!(double, uint)[1];
7613 largestPartialIntersection(a, b);
7614 // First member is the item, second is the occurrence count
7615 assert(b[0] == tuple(7.0, 4u));
7616 ----
7617
7618 $(D 7.0) is the correct answer because it occurs in $(D 4) out of the
7619 $(D 5) inputs, more than any other number. The second member of the
7620 resulting tuple is indeed $(D 4) (recording the number of occurrences
7621 of $(D 7.0)). If more of the top-frequent numbers are needed, just
7622 create a larger $(D tgt) range. In the axample above, creating $(D b)
7623 with length $(D 2) yields $(D tuple(1.0, 3u)) in the second position.
7624
7625 The function $(D largestPartialIntersection) is useful for
7626 e.g. searching an $(LUCKY inverted index) for the documents most
7627 likely to contain some terms of interest. The complexity of the search
7628 is $(BIGOH n * log(tgt.length)), where $(D n) is the sum of lengths of
7629 all input ranges. This approach is faster than keeping an associative
7630 array of the occurrences and then selecting its top items, and also
7631 requires less memory ($(D largestPartialIntersection) builds its
7632 result directly in $(D tgt) and requires no extra memory).
7633
7634 Warning: Because $(D largestPartialIntersection) does not allocate
7635 extra memory, it will leave $(D ror) modified. Namely, $(D
7636 largestPartialIntersection) assumes ownership of $(D ror) and
7637 discretionarily swaps and advances elements of it. If you want $(D
7638 ror) to preserve its contents after the call, you may want to pass a
7639 duplicate to $(D largestPartialIntersection) (and perhaps cache the
7640 duplicate in between calls).
7641  */
7642 void largestPartialIntersection
7643 (alias less = "a < b", RangeOfRanges, Range)
7644 (RangeOfRanges ror, Range tgt, SortOutput sorted = SortOutput.no)
7645 {
7646     struct UnitWeights
7647     {
7648         static int opIndex(ElementType!(ElementType!RangeOfRanges)) { return 1; }
7649     }
7650     return largestPartialIntersectionWeighted!less(ror, tgt, UnitWeights(),
7651             sorted);
7652 }
7653
7654 // largestPartialIntersectionWeighted
7655 /**
7656 Similar to $(D largestPartialIntersection), but associates a weight
7657 with each distinct element in the intersection.
7658
7659 Example:
7660 ----
7661 // Figure which number can be found in most arrays of the set of
7662 // arrays below, with specific per-element weights
7663 double[][] a =
7664 [
7665     [ 1, 4, 7, 8 ],
7666     [ 1, 7 ],
7667     [ 1, 7, 8],
7668     [ 4 ],
7669     [ 7 ],
7670 ];
7671 auto b = new Tuple!(double, uint)[1];
7672 double[double] weights = [ 1:1.2, 4:2.3, 7:1.1, 8:1.1 ];
7673 largestPartialIntersectionWeighted(a, b, weights);
7674 // First member is the item, second is the occurrence count
7675 assert(b[0] == tuple(4.0, 2u));
7676 ----
7677
7678 The correct answer in this case is $(D 4.0), which, although only
7679 appears two times, has a total weight $(D 4.6) (three times its weight
7680 $(D 2.3)). The value $(D 7) is weighted with $(D 1.1) and occurs four
7681 times for a total weight $(D 4.4).
7682  */
7683 void largestPartialIntersectionWeighted
7684 (alias less = "a < b", RangeOfRanges, Range, WeightsAA)
7685 (RangeOfRanges ror, Range tgt, WeightsAA weights, SortOutput sorted = SortOutput.no)
7686 {
7687     if (tgt.empty) return;
7688     alias ElementType!Range InfoType;
7689     bool heapComp(InfoType a, InfoType b)
7690     {
7691         return weights[a[0]] * a[1] > weights[b[0]] * b[1];
7692     }
7693     topNCopy!heapComp(group(nWayUnion!less(ror)), tgt, sorted);
7694 }
7695
7696 unittest
7697 {
7698     debug(std_algorithm) scope(success)
7699         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
7700     double[][] a =
7701         [
7702             [ 1, 4, 7, 8 ],
7703             [ 1, 7 ],
7704             [ 1, 7, 8],
7705             [ 4 ],
7706             [ 7 ],
7707         ];
7708     auto b = new Tuple!(double, uint)[2];
7709     largestPartialIntersection(a, b, SortOutput.yes);
7710     //sort(b);
7711     //writeln(b);
7712     assert(b == [ tuple(7., 4u), tuple(1., 3u) ][], text(b));
7713     assert(a[0].empty);
7714 }
7715
7716 unittest
7717 {
7718     debug(std_algorithm) scope(success)
7719         writeln("unittest @", __FILE__, ":", __LINE__, " done.");
7720     string[][] a =
7721         [
7722             [ "1", "4", "7", "8" ],
7723             [ "1", "7" ],
7724             [ "1", "7", "8"],
7725             [ "4" ],
7726             [ "7" ],
7727         ];
7728     auto b = new Tuple!(string, uint)[2];
7729     largestPartialIntersection(a, b, SortOutput.yes);
7730     //writeln(b);
7731     assert(b == [ tuple("7", 4u), tuple("1", 3u) ][], text(b));
7732 }
7733
7734 unittest
7735 {
7736     //scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done.");
7737 // Figure which number can be found in most arrays of the set of
7738 // arrays below, with specific per-element weights
7739     double[][] a =
7740         [
7741             [ 1, 4, 7, 8 ],
7742             [ 1, 7 ],
7743             [ 1, 7, 8],
7744             [ 4 ],
7745             [ 7 ],
7746             ];
7747     auto b = new Tuple!(double, uint)[1];
7748     double[double] weights = [ 1:1.2, 4:2.3, 7:1.1, 8:1.1 ];
7749     largestPartialIntersectionWeighted(a, b, weights);
7750 // First member is the item, second is the occurrence count
7751     //writeln(b[0]);
7752     assert(b[0] == tuple(4.0, 2u));
7753 }
Note: See TracBrowser for help on using the browser.