1 // Written in the D programming language.
2 /**
3 This is a submodule of $(MREF std, algorithm).
4 It contains generic comparison algorithms.
5 
6 $(SCRIPT inhibitQuickIndex = 1;)
7 $(BOOKTABLE Cheat Sheet,
8 $(TR $(TH Function Name) $(TH Description))
9 $(T2 among,
10         Checks if a value is among a set of values, e.g.
11         `if (v.among(1, 2, 3)) // `v` is 1, 2 or 3`)
12 $(T2 castSwitch,
13         `(new A()).castSwitch((A a)=>1,(B b)=>2)` returns `1`.)
14 $(T2 clamp,
15         `clamp(1, 3, 6)` returns `3`. `clamp(4, 3, 6)` returns `4`.)
16 $(T2 cmp,
17         `cmp("abc", "abcd")` is `-1`, `cmp("abc", "aba")` is `1`,
18         and `cmp("abc", "abc")` is `0`.)
19 $(T2 either,
20         Return first parameter `p` that passes an `if (p)` test, e.g.
21         `either(0, 42, 43)` returns `42`.)
22 $(T2 equal,
23         Compares ranges for element-by-element equality, e.g.
24         `equal([1, 2, 3], [1.0, 2.0, 3.0])` returns `true`.)
25 $(T2 isPermutation,
26         `isPermutation([1, 2], [2, 1])` returns `true`.)
27 $(T2 isSameLength,
28         `isSameLength([1, 2, 3], [4, 5, 6])` returns `true`.)
29 $(T2 levenshteinDistance,
30         `levenshteinDistance("kitten", "sitting")` returns `3` by using
31         the $(LINK2 https://en.wikipedia.org/wiki/Levenshtein_distance,
32         Levenshtein distance algorithm).)
33 $(T2 levenshteinDistanceAndPath,
34         `levenshteinDistanceAndPath("kitten", "sitting")` returns
35         `tuple(3, "snnnsni")` by using the
36         $(LINK2 https://en.wikipedia.org/wiki/Levenshtein_distance,
37         Levenshtein distance algorithm).)
38 $(T2 max,
39         `max(3, 4, 2)` returns `4`.)
40 $(T2 min,
41         `min(3, 4, 2)` returns `2`.)
42 $(T2 mismatch,
43         `mismatch("oh hi", "ohayo")` returns `tuple(" hi", "ayo")`.)
44 $(T2 predSwitch,
45         `2.predSwitch(1, "one", 2, "two", 3, "three")` returns `"two"`.)
46 )
47 
48 Copyright: Andrei Alexandrescu 2008-.
49 
50 License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
51 
52 Authors: $(HTTP erdani.com, Andrei Alexandrescu)
53 
54 Source: $(PHOBOSSRC std/algorithm/comparison.d)
55 
56 Macros:
57 T2=$(TR $(TDNW $(LREF $1)) $(TD $+))
58  */
59 module std.algorithm.comparison;
60 
61 import std.functional : unaryFun, binaryFun, lessThan, greaterThan;
62 import std.range.primitives;
63 import std.traits;
64 import std.meta : allSatisfy, anySatisfy;
65 import std.typecons : tuple, Tuple, Flag, Yes;
66 
67 import std.internal.attributes : betterC;
68 
69 /**
70 Find `value` _among `values`, returning the 1-based index
71 of the first matching value in `values`, or `0` if `value`
72 is not _among `values`. The predicate `pred` is used to
73 compare values, and uses equality by default.
74 
75 Params:
76     pred = The predicate used to compare the values.
77     value = The value to search for.
78     values = The values to compare the value to.
79 
80 Returns:
81     0 if value was not found among the values, otherwise the index of the
82     found value plus one is returned.
83 
84 See_Also:
85     $(UL
86     $(LI $(REF_SHORT find, std,algorithm,searching) and
87     $(REF_SHORT canFind, std,algorithm,searching) for finding a value in a range.)
88     $(LI $(REF_ALTTEXT `value in iota(start, end)`, iota, std,range) to find a value in
89     a particular interval.)
90     )
91 */
92 uint among(alias pred = (a, b) => a == b, Value, Values...)
93     (Value value, Values values)
94 if (Values.length != 0)
95 {
96     foreach (uint i, ref v; values)
97     {
98         import std.functional : binaryFun;
99         if (binaryFun!pred(value, v)) return i + 1;
100     }
101     return 0;
102 }
103 
104 /// Ditto
105 template among(values...)
106 if (isExpressionTuple!values)
107 {
108     uint among(Value)(Value value)
109     if (!is(CommonType!(Value, values) == void))
110     {
111         switch (value)
112         {
113             foreach (uint i, v; values)
114                 case v:
115                     return i + 1;
116             default:
117                 return 0;
118         }
119     }
120 }
121 
122 ///
123 @safe @nogc @betterC unittest
124 {
125     assert(3.among(1, 42, 24, 3, 2));
126 
127     if (auto pos = "bar".among("foo", "bar", "baz"))
128         assert(pos == 2);
129     else
130         assert(false);
131 
132     // 42 is larger than 24
133     assert(42.among!((lhs, rhs) => lhs > rhs)(43, 24, 100) == 2);
134 }
135 
136 /**
137 Alternatively, `values` can be passed at compile-time, allowing for a more
138 efficient search, but one that only supports matching on equality:
139 */
140 @safe @nogc @betterC unittest
141 {
142     assert(3.among!(2, 3, 4));
143     assert("bar".among!("foo", "bar", "baz") == 2);
144 }
145 
146 @safe unittest
147 {
148     import std.meta : AliasSeq;
149 
150     if (auto pos = 3.among(1, 2, 3))
151         assert(pos == 3);
152     else
153         assert(false);
154     assert(!4.among(1, 2, 3));
155 
156     auto position = "hello".among("hello", "world");
157     assert(position);
158     assert(position == 1);
159 
160     alias values = AliasSeq!("foo", "bar", "baz");
161     auto arr = [values];
162     assert(arr[0 .. "foo".among(values)] == ["foo"]);
163     assert(arr[0 .. "bar".among(values)] == ["foo", "bar"]);
164     assert(arr[0 .. "baz".among(values)] == arr);
165     assert("foobar".among(values) == 0);
166 
167     if (auto pos = 3.among!(1, 2, 3))
168         assert(pos == 3);
169     else
170         assert(false);
171     assert(!4.among!(1, 2, 3));
172 
173     position = "hello".among!("hello", "world");
174     assert(position);
175     assert(position == 1);
176 
177     static assert(!__traits(compiles, "a".among!("a", 42)));
178     static assert(!__traits(compiles, (Object.init).among!(42, "a")));
179 }
180 
181 // Used in castSwitch to find the first choice that overshadows the last choice
182 // in a tuple.
183 private template indexOfFirstOvershadowingChoiceOnLast(choices...)
184 {
185     alias firstParameterTypes = Parameters!(choices[0]);
186     alias lastParameterTypes = Parameters!(choices[$ - 1]);
187 
188     static if (lastParameterTypes.length == 0)
189     {
190         // If the last is null-typed choice, check if the first is null-typed.
191         enum isOvershadowing = firstParameterTypes.length == 0;
192     }
193     else static if (firstParameterTypes.length == 1)
194     {
195         // If the both first and last are not null-typed, check for overshadowing.
196         enum isOvershadowing =
197             is(firstParameterTypes[0] == Object) // Object overshadows all other classes!(this is needed for interfaces)
198             || is(lastParameterTypes[0] : firstParameterTypes[0]);
199     }
200     else
201     {
202         // If the first is null typed and the last is not - the is no overshadowing.
203         enum isOvershadowing = false;
204     }
205 
206     static if (isOvershadowing)
207     {
208         enum indexOfFirstOvershadowingChoiceOnLast = 0;
209     }
210     else
211     {
212         enum indexOfFirstOvershadowingChoiceOnLast =
213             1 + indexOfFirstOvershadowingChoiceOnLast!(choices[1..$]);
214     }
215 }
216 
217 /**
218 Executes and returns one of a collection of handlers based on the type of the
219 switch object.
220 
221 The first choice that `switchObject` can be casted to the type
222 of argument it accepts will be called with `switchObject` casted to that
223 type, and the value it'll return will be returned by `castSwitch`.
224 
225 If a choice's return type is void, the choice must throw an exception, unless
226 all the choices are void. In that case, castSwitch itself will return void.
227 
228 Throws: If none of the choice matches, a `SwitchError` will be thrown.  $(D
229 SwitchError) will also be thrown if not all the choices are void and a void
230 choice was executed without throwing anything.
231 
232 Params:
233     choices = The `choices` needs to be composed of function or delegate
234         handlers that accept one argument. There can also be a choice that
235         accepts zero arguments. That choice will be invoked if the $(D
236         switchObject) is null.
237     switchObject = the object against which the tests are being made.
238 
239 Returns:
240     The value of the selected choice.
241 
242 Note: `castSwitch` can only be used with object types.
243 */
244 auto castSwitch(choices...)(Object switchObject)
245 {
246     import core.exception : SwitchError;
247     import std.format : format;
248 
249     // Check to see if all handlers return void.
250     enum areAllHandlersVoidResult = {
251         bool result = true;
252         foreach (index, choice; choices)
253         {
254             result &= is(ReturnType!choice : void); // void or noreturn
255         }
256         return result;
257     }();
258 
259     if (switchObject !is null)
260     {
261         // Checking for exact matches:
262         const classInfo = typeid(switchObject);
263         foreach (index, choice; choices)
264         {
265             static assert(isCallable!choice,
266                     "A choice handler must be callable");
267 
268             alias choiceParameterTypes = Parameters!choice;
269             static assert(choiceParameterTypes.length <= 1,
270                     "A choice handler can not have more than one argument.");
271 
272             static if (choiceParameterTypes.length == 1)
273             {
274                 alias CastClass = choiceParameterTypes[0];
275                 static assert(is(CastClass == class) || is(CastClass == interface),
276                         "A choice handler can have only class or interface typed argument.");
277 
278                 // Check for overshadowing:
279                 immutable indexOfOvershadowingChoice =
280                     indexOfFirstOvershadowingChoiceOnLast!(choices[0 .. index + 1]);
281                 static assert(indexOfOvershadowingChoice == index,
282                         "choice number %d(type %s) is overshadowed by choice number %d(type %s)".format(
283                             index + 1, CastClass.stringof, indexOfOvershadowingChoice + 1,
284                             Parameters!(choices[indexOfOvershadowingChoice])[0].stringof));
285 
286                 if (classInfo == typeid(CastClass))
287                 {
288                     static if (is(ReturnType!(choice) == void))
289                     {
290                         choice(cast(CastClass) switchObject);
291                         static if (areAllHandlersVoidResult)
292                         {
293                             return;
294                         }
295                         else
296                         {
297                             throw new SwitchError("Handlers that return void should throw");
298                         }
299                     }
300                     else
301                     {
302                         return choice(cast(CastClass) switchObject);
303                     }
304                 }
305             }
306         }
307 
308         // Checking for derived matches:
309         foreach (choice; choices)
310         {
311             alias choiceParameterTypes = Parameters!choice;
312             static if (choiceParameterTypes.length == 1)
313             {
314                 if (auto castedObject = cast(choiceParameterTypes[0]) switchObject)
315                 {
316                     static if (is(ReturnType!(choice) == void))
317                     {
318                         choice(castedObject);
319                         static if (areAllHandlersVoidResult)
320                         {
321                             return;
322                         }
323                         else
324                         {
325                             throw new SwitchError("Handlers that return void should throw");
326                         }
327                     }
328                     else
329                     {
330                         return choice(castedObject);
331                     }
332                 }
333             }
334         }
335     }
336     else // If switchObject is null:
337     {
338         // Checking for null matches:
339         foreach (index, choice; choices)
340         {
341             static if (Parameters!(choice).length == 0)
342             {
343                 immutable indexOfOvershadowingChoice =
344                     indexOfFirstOvershadowingChoiceOnLast!(choices[0 .. index + 1]);
345 
346                 // Check for overshadowing:
347                 static assert(indexOfOvershadowingChoice == index,
348                         "choice number %d(null reference) is overshadowed by choice number %d(null reference)".format(
349                             index + 1, indexOfOvershadowingChoice + 1));
350 
351                 if (switchObject is null)
352                 {
353                     static if (is(ReturnType!(choice) == void))
354                     {
355                         choice();
356                         static if (areAllHandlersVoidResult)
357                         {
358                             return;
359                         }
360                         else
361                         {
362                             throw new SwitchError("Handlers that return void should throw");
363                         }
364                     }
365                     else
366                     {
367                         return choice();
368                     }
369                 }
370             }
371         }
372     }
373 
374     // In case nothing matched:
375     throw new SwitchError("Input not matched by any choice");
376 }
377 
378 ///
379 @system unittest
380 {
381     import std.algorithm.iteration : map;
382     import std.format : format;
383 
384     class A
385     {
386         int a;
387         this(int a) {this.a = a;}
388         @property int i() { return a; }
389     }
390     interface I { }
391     class B : I { }
392 
393     Object[] arr = [new A(1), new B(), null];
394 
395     auto results = arr.map!(castSwitch!(
396                                 (A a) => "A with a value of %d".format(a.a),
397                                 (I i) => "derived from I",
398                                 ()    => "null reference",
399                             ))();
400 
401     // A is handled directly:
402     assert(results[0] == "A with a value of 1");
403     // B has no handler - it is handled by the handler of I:
404     assert(results[1] == "derived from I");
405     // null is handled by the null handler:
406     assert(results[2] == "null reference");
407 }
408 
409 /// Using with void handlers:
410 @system unittest
411 {
412     import std.exception : assertThrown;
413 
414     class A { }
415     class B { }
416     // Void handlers are allowed if they throw:
417     assertThrown!Exception(
418         new B().castSwitch!(
419             (A a) => 1,
420             (B d)    { throw new Exception("B is not allowed!"); }
421         )()
422     );
423 
424     // Void handlers are also allowed if all the handlers are void:
425     new A().castSwitch!(
426         (A a) { },
427         (B b) { assert(false); },
428     )();
429 }
430 
431 @system unittest
432 {
433     import core.exception : SwitchError;
434     import std.exception : assertThrown;
435 
436     interface I { }
437     class A : I { }
438     class B { }
439 
440     // Nothing matches:
441     assertThrown!SwitchError((new A()).castSwitch!(
442                                  (B b) => 1,
443                                  () => 2,
444                              )());
445 
446     // Choices with multiple arguments are not allowed:
447     static assert(!__traits(compiles,
448                             (new A()).castSwitch!(
449                                 (A a, B b) => 0,
450                             )()));
451 
452     // Only callable handlers allowed:
453     static assert(!__traits(compiles,
454                             (new A()).castSwitch!(
455                                 1234,
456                             )()));
457 
458     // Only object arguments allowed:
459     static assert(!__traits(compiles,
460                             (new A()).castSwitch!(
461                                 (int x) => 0,
462                             )()));
463 
464     // Object overshadows regular classes:
465     static assert(!__traits(compiles,
466                             (new A()).castSwitch!(
467                                 (Object o) => 0,
468                                 (A a) => 1,
469                             )()));
470 
471     // Object overshadows interfaces:
472     static assert(!__traits(compiles,
473                             (new A()).castSwitch!(
474                                 (Object o) => 0,
475                                 (I i) => 1,
476                             )()));
477 
478     // No multiple null handlers allowed:
479     static assert(!__traits(compiles,
480                             (new A()).castSwitch!(
481                                 () => 0,
482                                 () => 1,
483                             )()));
484 
485     // No non-throwing void handlers allowed(when there are non-void handlers):
486     assertThrown!SwitchError((new A()).castSwitch!(
487                                  (A a)    {},
488                                  (B b) => 2,
489                              )());
490 
491     // All-void handlers work for the null case:
492     null.castSwitch!(
493         (Object o) { assert(false); },
494         ()         { },
495     )();
496 
497     // Throwing void handlers work for the null case:
498     assertThrown!Exception(null.castSwitch!(
499                                (Object o) => 1,
500                                ()            { throw new Exception("null"); },
501                            )());
502 }
503 
504 @system unittest
505 {
506     interface I { }
507     class B : I { }
508     class C : I { }
509 
510     assert((new B()).castSwitch!(
511             (B b) => "class B",
512             (I i) => "derived from I",
513     ) == "class B");
514 
515     assert((new C()).castSwitch!(
516             (B b) => "class B",
517             (I i) => "derived from I",
518     ) == "derived from I");
519 }
520 
521 // https://issues.dlang.org/show_bug.cgi?id=22384
522 @system unittest
523 {
524     // Use explicit methods to enforce return types
525     static void objectSkip(Object) {}
526     static void defaultSkip() {}
527 
528     static noreturn objectError(Object) { assert(false); }
529     static noreturn defaultError() { assert(false); }
530 
531     {
532         alias test = castSwitch!(objectSkip, defaultError);
533         static assert(is(ReturnType!test == void));
534     }{
535         alias test = castSwitch!(objectError, defaultSkip);
536         static assert(is(ReturnType!test == void));
537     }{
538         alias test = castSwitch!(objectError, defaultError);
539         static assert(is(ReturnType!test == noreturn));
540     }
541 
542     // Also works with non-void handlers
543     static int objectValue(Object) { return 1;}
544     static int defaultValue() { return 2; }
545 
546     {
547         alias test = castSwitch!(objectValue, defaultError);
548         static assert(is(ReturnType!test == int));
549     }{
550         alias test = castSwitch!(objectError, defaultValue);
551         static assert(is(ReturnType!test == int));
552     }
553 
554     // No confusion w.r.t. void callbacks
555     alias FP = void function();
556     static FP objectFunc(Object) { return &defaultSkip; }
557     static FP defaultFunc() { return &defaultSkip; }
558 
559     {
560         alias test = castSwitch!(objectFunc, defaultError);
561         static assert(is(ReturnType!test == FP));
562     }{
563         alias test = castSwitch!(objectError, defaultFunc);
564         static assert(is(ReturnType!test == FP));
565     }
566 }
567 
568 /** Clamps `val` into the given bounds. Result has the same type as `val`.
569 
570 Params:
571     val = The value to _clamp.
572     lower = The _lower bound of the _clamp.
573     upper = The _upper bound of the _clamp.
574 
575 Returns:
576     `lower` if `val` is less than `lower`, `upper` if `val` is greater than
577     `upper`, and `val` in all other cases. Comparisons are made
578     correctly (using $(REF lessThan, std,functional) and the return value
579     is converted to the return type using the standard integer coversion rules
580     $(REF greaterThan, std,functional)) even if the signedness of `T1`, `T2`,
581     and `T3` are different.
582 */
583 T1 clamp(T1, T2, T3)(T1 val, T2 lower, T3 upper)
584 {
585     static assert(is(T2 : T1), "T2 of type '", T2.stringof
586             , "' must be implicitly convertible to type of T1 '"
587             , T1.stringof, "'");
588     static assert(is(T3 : T1), "T3 of type '", T3.stringof
589             , "' must be implicitly convertible to type of T1 '"
590             , T1.stringof, "'");
591 
592     assert(!lower.greaterThan(upper), "Lower can't be greater than upper.");
593 
594     // `if (is(typeof(val.lessThan(lower) ? lower : val.greaterThan(upper) ? upper : val) : T1))
595     // because of https://issues.dlang.org/show_bug.cgi?id=16235.
596     // Once that is fixed, we can simply use the ternary in both the template constraint
597     // and the template body
598     if (val.lessThan(lower))
599         return lower;
600     else if (val.greaterThan(upper))
601         return upper;
602     return val;
603 }
604 
605 ///
606 @safe @nogc @betterC unittest
607 {
608     assert(clamp(2, 1, 3) == 2);
609     assert(clamp(0, 1, 3) == 1);
610     assert(clamp(4, 1, 3) == 3);
611 
612     assert(clamp(1, 1, 1) == 1);
613 
614     assert(clamp(5, -1, 2u) == 2);
615 
616     auto x = clamp(42, uint.max, uint.max);
617     static assert(is(typeof(x) == int));
618     assert(x == -1);
619 }
620 
621 @safe unittest
622 {
623     int a = 1;
624     short b = 6;
625     double c = 2;
626     static assert(is(typeof(clamp(c,a,b)) == double));
627     assert(clamp(c,   a, b) == c);
628     assert(clamp(a-c, a, b) == a);
629     assert(clamp(b+c, a, b) == b);
630     // mixed sign
631     a = -5;
632     uint f = 5;
633     static assert(is(typeof(clamp(f, a, b)) == uint));
634     assert(clamp(f, a, b) == f);
635     // similar type deduction for (u)long
636     static assert(is(typeof(clamp(-1L, -2L, 2UL)) == long));
637 
638     // user-defined types
639     import std.datetime : Date;
640     assert(clamp(Date(1982, 1, 4), Date(1012, 12, 21), Date(2012, 12, 21)) == Date(1982, 1, 4));
641     assert(clamp(Date(1982, 1, 4), Date.min, Date.max) == Date(1982, 1, 4));
642     // UFCS style
643     assert(Date(1982, 1, 4).clamp(Date.min, Date.max) == Date(1982, 1, 4));
644 
645     // Stability
646     struct A {
647         int x, y;
648         int opCmp(ref const A rhs) const { return (x > rhs.x) - (x < rhs.x); }
649     }
650     A x, lo, hi;
651     x.y = 42;
652     assert(x.clamp(lo, hi).y == 42);
653 }
654 
655 // https://issues.dlang.org/show_bug.cgi?id=23268
656 @safe pure nothrow @nogc unittest
657 {
658     static assert(__traits(compiles, clamp(short.init, short.init, cast(const) short.init)));
659 }
660 
661 // cmp
662 /**********************************
663 Performs a lexicographical comparison on two
664 $(REF_ALTTEXT input ranges, isInputRange, std,range,primitives).
665 Iterating `r1` and `r2` in lockstep, `cmp` compares each element
666 `e1` of `r1` with the corresponding element `e2` in `r2`. If one
667 of the ranges has been finished, `cmp` returns a negative value
668 if `r1` has fewer elements than `r2`, a positive value if `r1`
669 has more elements than `r2`, and `0` if the ranges have the same
670 number of elements.
671 
672 If the ranges are strings, `cmp` performs UTF decoding
673 appropriately and compares the ranges one code point at a time.
674 
675 A custom predicate may be specified, in which case `cmp` performs
676 a three-way lexicographical comparison using `pred`. Otherwise
677 the elements are compared using `opCmp`.
678 
679 Params:
680     pred = Predicate used for comparison. Without a predicate
681         specified the ordering implied by `opCmp` is used.
682     r1 = The first range.
683     r2 = The second range.
684 
685 Returns:
686     `0` if the ranges compare equal. A negative value if `r1` is a prefix of `r2` or
687     the first differing element of `r1` is less than the corresponding element of `r2`
688     according to `pred`. A positive value if `r2` is a prefix of `r1` or the first
689     differing element of `r2` is less than the corresponding element of `r1`
690     according to `pred`.
691 
692 Note:
693     An earlier version of the documentation incorrectly stated that `-1` is the
694     only negative value returned and `1` is the only positive value returned.
695     Whether that is true depends on the types being compared.
696 */
697 auto cmp(R1, R2)(R1 r1, R2 r2)
698 if (isInputRange!R1 && isInputRange!R2)
699 {
700     alias E1 = ElementEncodingType!R1;
701     alias E2 = ElementEncodingType!R2;
702 
703     static if (isDynamicArray!R1 && isDynamicArray!R2
704         && __traits(isUnsigned, E1) && __traits(isUnsigned, E2)
705         && E1.sizeof == 1 && E2.sizeof == 1
706         // Both or neither must auto-decode.
707         && (is(immutable E1 == immutable char) == is(immutable E2 == immutable char)))
708     {
709         // dstrcmp algorithm is correct for both ubyte[] and for char[].
710         import core.internal.string : dstrcmp;
711         return dstrcmp(cast(const char[]) r1, cast(const char[]) r2);
712     }
713     else static if (!(isSomeString!R1 && isSomeString!R2))
714     {
715         for (;; r1.popFront(), r2.popFront())
716         {
717             static if (is(typeof(r1.front.opCmp(r2.front)) R))
718                 alias Result = R;
719             else
720                 alias Result = int;
721             if (r2.empty) return Result(!r1.empty);
722             if (r1.empty) return Result(-1);
723             static if (is(typeof(r1.front.opCmp(r2.front))))
724             {
725                 auto c = r1.front.opCmp(r2.front);
726                 if (c != 0) return c;
727             }
728             else
729             {
730                 auto a = r1.front, b = r2.front;
731                 if (auto result = (b < a) - (a < b)) return result;
732             }
733         }
734     }
735     else
736     {
737         static if (typeof(r1[0]).sizeof == typeof(r2[0]).sizeof)
738         {
739             return () @trusted
740             {
741                 auto p1 = r1.ptr, p2 = r2.ptr,
742                     pEnd = p1 + min(r1.length, r2.length);
743                 for (; p1 != pEnd; ++p1, ++p2)
744                 {
745                     if (*p1 != *p2) return cast(int) *p1 - cast(int) *p2;
746                 }
747                 static if (typeof(r1[0]).sizeof >= 2 && size_t.sizeof <= uint.sizeof)
748                     return cast(int) r1.length - cast(int) r2.length;
749                 else
750                     return int(r1.length > r2.length) - int(r1.length < r2.length);
751             }();
752         }
753         else
754         {
755             import std.utf : decode;
756 
757             for (size_t i1, i2;;)
758             {
759                 if (i1 == r1.length) return -int(i2 < r2.length);
760                 if (i2 == r2.length) return int(1);
761                 immutable c1 = decode(r1, i1),
762                     c2 = decode(r2, i2);
763                 if (c1 != c2) return cast(int) c1 - cast(int) c2;
764             }
765         }
766     }
767 }
768 
769 /// ditto
770 int cmp(alias pred, R1, R2)(R1 r1, R2 r2)
771 if (isInputRange!R1 && isInputRange!R2)
772 {
773     static if (!(isSomeString!R1 && isSomeString!R2))
774     {
775         for (;; r1.popFront(), r2.popFront())
776         {
777             if (r2.empty) return !r1.empty;
778             if (r1.empty) return -1;
779             auto a = r1.front, b = r2.front;
780             if (binaryFun!pred(a, b)) return -1;
781             if (binaryFun!pred(b, a)) return 1;
782         }
783     }
784     else
785     {
786         import std.utf : decode;
787 
788         for (size_t i1, i2;;)
789         {
790             if (i1 == r1.length) return -int(i2 < r2.length);
791             if (i2 == r2.length) return 1;
792             immutable c1 = decode(r1, i1),
793                 c2 = decode(r2, i2);
794             if (c1 != c2)
795             {
796                 if (binaryFun!pred(c2, c1)) return 1;
797                 if (binaryFun!pred(c1, c2)) return -1;
798             }
799         }
800     }
801 }
802 
803 ///
804 pure @safe unittest
805 {
806     int result;
807 
808     result = cmp("abc", "abc");
809     assert(result == 0);
810     result = cmp("", "");
811     assert(result == 0);
812     result = cmp("abc", "abcd");
813     assert(result < 0);
814     result = cmp("abcd", "abc");
815     assert(result > 0);
816     result = cmp("abc"d, "abd");
817     assert(result < 0);
818     result = cmp("bbc", "abc"w);
819     assert(result > 0);
820     result = cmp("aaa", "aaaa"d);
821     assert(result < 0);
822     result = cmp("aaaa", "aaa"d);
823     assert(result > 0);
824     result = cmp("aaa", "aaa"d);
825     assert(result == 0);
826     result = cmp("aaa"d, "aaa"d);
827     assert(result == 0);
828     result = cmp(cast(int[])[], cast(int[])[]);
829     assert(result == 0);
830     result = cmp([1, 2, 3], [1, 2, 3]);
831     assert(result == 0);
832     result = cmp([1, 3, 2], [1, 2, 3]);
833     assert(result > 0);
834     result = cmp([1, 2, 3], [1L, 2, 3, 4]);
835     assert(result < 0);
836     result = cmp([1L, 2, 3], [1, 2]);
837     assert(result > 0);
838 }
839 
840 /// Example predicate that compares individual elements in reverse lexical order
841 pure @safe unittest
842 {
843     int result;
844 
845     result = cmp!"a > b"("abc", "abc");
846     assert(result == 0);
847     result = cmp!"a > b"("", "");
848     assert(result == 0);
849     result = cmp!"a > b"("abc", "abcd");
850     assert(result < 0);
851     result = cmp!"a > b"("abcd", "abc");
852     assert(result > 0);
853     result = cmp!"a > b"("abc"d, "abd");
854     assert(result > 0);
855     result = cmp!"a > b"("bbc", "abc"w);
856     assert(result < 0);
857     result = cmp!"a > b"("aaa", "aaaa"d);
858     assert(result < 0);
859     result = cmp!"a > b"("aaaa", "aaa"d);
860     assert(result > 0);
861     result = cmp!"a > b"("aaa", "aaa"d);
862     assert(result == 0);
863     result = cmp("aaa"d, "aaa"d);
864     assert(result == 0);
865     result = cmp!"a > b"(cast(int[])[], cast(int[])[]);
866     assert(result == 0);
867     result = cmp!"a > b"([1, 2, 3], [1, 2, 3]);
868     assert(result == 0);
869     result = cmp!"a > b"([1, 3, 2], [1, 2, 3]);
870     assert(result < 0);
871     result = cmp!"a > b"([1, 2, 3], [1L, 2, 3, 4]);
872     assert(result < 0);
873     result = cmp!"a > b"([1L, 2, 3], [1, 2]);
874     assert(result > 0);
875 }
876 
877 // cmp for string with custom predicate fails if distinct chars can compare equal
878 // https://issues.dlang.org/show_bug.cgi?id=18286
879 @nogc nothrow pure @safe unittest
880 {
881     static bool ltCi(dchar a, dchar b)// less than, case insensitive
882     {
883         import std.ascii : toUpper;
884         return toUpper(a) < toUpper(b);
885     }
886     static assert(cmp!ltCi("apple2", "APPLE1") > 0);
887     static assert(cmp!ltCi("apple1", "APPLE2") < 0);
888     static assert(cmp!ltCi("apple", "APPLE1") < 0);
889     static assert(cmp!ltCi("APPLE", "apple1") < 0);
890     static assert(cmp!ltCi("apple", "APPLE") == 0);
891 }
892 
893 // for non-string ranges check that opCmp is evaluated only once per pair.
894 // https://issues.dlang.org/show_bug.cgi?id=18280
895 @nogc nothrow @safe unittest
896 {
897     static int ctr = 0;
898     struct S
899     {
900         int opCmp(ref const S rhs) const
901         {
902             ++ctr;
903             return 0;
904         }
905         bool opEquals(T)(T o) const { return false; }
906         size_t toHash() const { return 0; }
907     }
908     immutable S[4] a;
909     immutable S[4] b;
910     immutable result = cmp(a[], b[]);
911     assert(result == 0, "neither should compare greater than the other!");
912     assert(ctr == a.length, "opCmp should be called exactly once per pair of items!");
913 }
914 
915 nothrow pure @safe @nogc unittest
916 {
917     import std.array : staticArray;
918     // Test cmp when opCmp returns float.
919     struct F
920     {
921         float value;
922         float opCmp(const ref F rhs) const
923         {
924             return value - rhs.value;
925         }
926         bool opEquals(T)(T o) const { return false; }
927         size_t toHash() const { return 0; }
928     }
929     auto result = cmp([F(1), F(2), F(3)].staticArray[], [F(1), F(2), F(3)].staticArray[]);
930     assert(result == 0);
931     assert(is(typeof(result) == float));
932     result = cmp([F(1), F(3), F(2)].staticArray[], [F(1), F(2), F(3)].staticArray[]);
933     assert(result > 0);
934     result = cmp([F(1), F(2), F(3)].staticArray[], [F(1), F(2), F(3), F(4)].staticArray[]);
935     assert(result < 0);
936     result = cmp([F(1), F(2), F(3)].staticArray[], [F(1), F(2)].staticArray[]);
937     assert(result > 0);
938 }
939 
940 nothrow pure @safe unittest
941 {
942     // Parallelism (was broken by inferred return type "immutable int")
943     import std.parallelism : task;
944     auto t = task!cmp("foo", "bar");
945 }
946 
947 // equal
948 /**
949 Compares two or more ranges for equality, as defined by predicate `pred`
950 (which is `==` by default).
951 */
952 template equal(alias pred = "a == b")
953 {
954     /++
955     Compares two or more ranges for equality. The ranges may have
956     different element types, as long as all are comparable by means of
957     the `pred`.
958     Performs $(BIGOH min(rs[0].length, rs[1].length, ...)) evaluations of `pred`. However, if
959     `equal` is invoked with the default predicate, the implementation may take the liberty
960     to use faster implementations that have the theoretical worst-case
961     $(BIGOH max(rs[0].length, rs[1].length, ...)).
962 
963     At least one of the ranges must be finite. If one range involved is infinite, the result is
964     (statically known to be) `false`.
965 
966     If the ranges have different kinds of UTF code unit (`char`, `wchar`, or
967     `dchar`), then they are compared using UTF decoding to avoid
968     accidentally integer-promoting units.
969 
970     Params:
971         rs = The ranges to be compared.
972 
973     Returns:
974         `true` if and only if all ranges compare _equal element
975         for element, according to binary predicate `pred`.
976     +/
977     bool equal(Ranges...)(Ranges rs)
978     if (rs.length > 1
979         && allSatisfy!(isInputRange, Ranges)
980         && !allSatisfy!(isInfinite, Ranges)
981         && is(typeof(binaryFun!pred(rs[0].front, rs[1].front)))
982         && (rs.length == 2 || is(typeof(equal!pred(rs[1 .. $])) == bool))
983         )
984     {
985         alias ElementEncodingTypes = staticMap!(ElementEncodingType, Ranges);
986         enum differentSize(T) = T.sizeof != ElementEncodingTypes[0].sizeof;
987         enum useCodePoint = allSatisfy!(isSomeChar, ElementEncodingTypes) &&
988             anySatisfy!(differentSize, ElementEncodingTypes);
989         enum bool comparableWithEq(alias r) = is(typeof(rs[0] == r));
990 
991         static if (anySatisfy!(isInfinite, Ranges))
992         {
993             return false;
994         }
995         else static if (useCodePoint)
996         {
997             import std.utf : byDchar;
998             static bool allByDchar(size_t done, Ranges...)(auto ref Ranges rs)
999             {
1000                 static if (done == rs.length)
1001                     return equalLoop(rs);
1002                 else
1003                     return allByDchar!(done + 1)(rs[0 .. done], rs[done].byDchar, rs[done + 1 .. $]);
1004             }
1005             return allByDchar!0(rs);
1006         }
1007         else static if (is(typeof(pred) == string) && pred == "a == b" &&
1008                 allSatisfy!(isArray, Ranges) && allSatisfy!(comparableWithEq, rs))
1009         {
1010             static foreach (r; rs[1 .. $])
1011                 if (rs[0] != r)
1012                     return false;
1013             return true;
1014         }
1015         // if one of the arguments is a string and the other isn't, then auto-decoding
1016         // can be avoided if they have the same ElementEncodingType
1017         // TODO: generalize this
1018         else static if (rs.length == 2 && is(typeof(pred) == string) && pred == "a == b" &&
1019                 isAutodecodableString!(Ranges[0]) != isAutodecodableString!(Ranges[1]) &&
1020                 is(immutable ElementEncodingType!(Ranges[0]) == immutable ElementEncodingType!(Ranges[1])))
1021         {
1022             import std.utf : byCodeUnit;
1023             static if (isAutodecodableString!(Ranges[0]))
1024                 return equal(rs[0].byCodeUnit, rs[1]);
1025             else
1026                 return equal(rs[1].byCodeUnit, rs[0]);
1027         }
1028         else
1029         {
1030             static foreach (i, R; Ranges)
1031             {
1032                 static if (hasLength!R)
1033                 {
1034                     static if (!is(typeof(firstLength)))
1035                     {
1036                         // Found the first range that has length
1037                         auto firstLength = rs[i].length;
1038                     }
1039                     else
1040                     {
1041                         // Compare the length of the current range against the first with length
1042                         if (firstLength != rs[i].length)
1043                             return false;
1044                     }
1045                 }
1046             }
1047             return equalLoop(rs);
1048         }
1049     }
1050 
1051     private bool equalLoop(Rs...)(ref Rs rs)
1052     {
1053         for (; !rs[0].empty; rs[0].popFront)
1054             static foreach (r; rs[1 .. $])
1055                 if (r.empty || !binaryFun!pred(rs[0].front, r.front))
1056                     return false;
1057                 else
1058                     r.popFront;
1059         static foreach (r; rs[1 .. $])
1060             if (!r.empty)
1061                 return false;
1062         return true;
1063     }
1064 }
1065 
1066 ///
1067 @safe @nogc unittest
1068 {
1069     import std.algorithm.comparison : equal;
1070     import std.math.operations : isClose;
1071 
1072     int[4] a = [ 1, 2, 4, 3 ];
1073     assert(!equal(a[], a[1..$]));
1074     assert(equal(a[], a[]));
1075     assert(equal!((a, b) => a == b)(a[], a[]));
1076 
1077     // different types
1078     double[4] b = [ 1.0, 2, 4, 3];
1079     assert(!equal(a[], b[1..$]));
1080     assert(equal(a[], b[]));
1081 
1082     // predicated: ensure that two vectors are approximately equal
1083     double[4] c = [ 1.0000000005, 2, 4, 3];
1084     assert(equal!isClose(b[], c[]));
1085 }
1086 
1087 @safe @nogc unittest
1088 {
1089     import std.algorithm.comparison : equal;
1090     import std.math.operations : isClose;
1091 
1092     auto s1 = "abc", s2 = "abc"w;
1093     assert(equal(s1, s2, s2));
1094     assert(equal(s1, s2, s2, s1));
1095     assert(!equal(s1, s2, s2[1 .. $]));
1096 
1097     int[4] a = [ 1, 2, 4, 3 ];
1098     assert(!equal(a[], a[1..$], a[]));
1099     assert(equal(a[], a[], a[]));
1100     assert(equal!((a, b) => a == b)(a[], a[], a[]));
1101 
1102     // different types
1103     double[4] b = [ 1.0, 2, 4, 3];
1104     assert(!equal(a[], b[1..$], b[]));
1105     assert(equal(a[], b[], a[], b[]));
1106 
1107     // predicated: ensure that two vectors are approximately equal
1108     double[4] c = [ 1.0000000005, 2, 4, 3];
1109     assert(equal!isClose(b[], c[], b[]));
1110 }
1111 
1112 /++
1113 Tip: `equal` can itself be used as a predicate to other functions.
1114 This can be very useful when the element type of a range is itself a
1115 range. In particular, `equal` can be its own predicate, allowing
1116 range of range (of range...) comparisons.
1117  +/
1118 @safe unittest
1119 {
1120     import std.algorithm.comparison : equal;
1121     import std.range : iota, chunks;
1122     assert(equal!(equal!equal)(
1123         [[[0, 1], [2, 3]], [[4, 5], [6, 7]]],
1124         iota(0, 8).chunks(2).chunks(2)
1125     ));
1126 }
1127 
1128 @safe unittest
1129 {
1130     import std.algorithm.iteration : map;
1131     import std.internal.test.dummyrange : ReferenceForwardRange,
1132         ReferenceInputRange, ReferenceInfiniteForwardRange;
1133     import std.math.operations : isClose;
1134 
1135     // various strings
1136     assert(equal("æøå", "æøå")); //UTF8 vs UTF8
1137     assert(!equal("???", "æøå")); //UTF8 vs UTF8
1138     assert(equal("æøå"w, "æøå"d)); //UTF16 vs UTF32
1139     assert(!equal("???"w, "æøå"d));//UTF16 vs UTF32
1140     assert(equal("æøå"d, "æøå"d)); //UTF32 vs UTF32
1141     assert(!equal("???"d, "æøå"d));//UTF32 vs UTF32
1142     assert(!equal("hello", "world"));
1143 
1144     // same strings, but "explicit non default" comparison (to test the non optimized array comparison)
1145     assert( equal!("a == b")("æøå", "æøå")); //UTF8 vs UTF8
1146     assert(!equal!("a == b")("???", "æøå")); //UTF8 vs UTF8
1147     assert( equal!("a == b")("æøå"w, "æøå"d)); //UTF16 vs UTF32
1148     assert(!equal!("a == b")("???"w, "æøå"d));//UTF16 vs UTF32
1149     assert( equal!("a == b")("æøå"d, "æøå"d)); //UTF32 vs UTF32
1150     assert(!equal!("a == b")("???"d, "æøå"d));//UTF32 vs UTF32
1151     assert(!equal!("a == b")("hello", "world"));
1152 
1153     //Array of string
1154     assert(equal(["hello", "world"], ["hello", "world"]));
1155     assert(!equal(["hello", "world"], ["hello"]));
1156     assert(!equal(["hello", "world"], ["hello", "Bob!"]));
1157 
1158     //Should not compile, because "string == dstring" is illegal
1159     static assert(!is(typeof(equal(["hello", "world"], ["hello"d, "world"d]))));
1160     //However, arrays of non-matching string can be compared using equal!equal. Neat-o!
1161     equal!equal(["hello", "world"], ["hello"d, "world"d]);
1162 
1163     //Tests, with more fancy map ranges
1164     int[] a = [ 1, 2, 4, 3 ];
1165     assert(equal([2, 4, 8, 6], map!"a*2"(a)));
1166     double[] b = [ 1.0, 2, 4, 3];
1167     double[] c = [ 1.0000000005, 2, 4, 3];
1168     assert(equal!isClose(map!"a*2"(b), map!"a*2"(c)));
1169     assert(!equal([2, 4, 1, 3], map!"a*2"(a)));
1170     assert(!equal([2, 4, 1], map!"a*2"(a)));
1171     assert(!equal!isClose(map!"a*3"(b), map!"a*2"(c)));
1172 
1173     //Tests with some fancy reference ranges.
1174     ReferenceInputRange!int cir = new ReferenceInputRange!int([1, 2, 4, 3]);
1175     ReferenceForwardRange!int cfr = new ReferenceForwardRange!int([1, 2, 4, 3]);
1176     assert(equal(cir, a));
1177     cir = new ReferenceInputRange!int([1, 2, 4, 3]);
1178     assert(equal(cir, cfr.save));
1179     assert(equal(cfr.save, cfr.save));
1180     cir = new ReferenceInputRange!int([1, 2, 8, 1]);
1181     assert(!equal(cir, cfr));
1182 
1183     //Test with an infinite range
1184     auto ifr = new ReferenceInfiniteForwardRange!int;
1185     assert(!equal(a, ifr));
1186     assert(!equal(ifr, a));
1187     //Test InputRange without length
1188     assert(!equal(ifr, cir));
1189     assert(!equal(cir, ifr));
1190 }
1191 
1192 @safe @nogc pure unittest
1193 {
1194     import std.utf : byChar, byDchar, byWchar;
1195 
1196     assert(equal("æøå".byChar, "æøå"));
1197     assert(equal("æøå".byChar, "æøå"w));
1198     assert(equal("æøå".byChar, "æøå"d));
1199     assert(equal("æøå", "æøå".byChar));
1200     assert(equal("æøå"w, "æøå".byChar));
1201     assert(equal("æøå"d, "æøå".byChar));
1202 
1203     assert(equal("æøå".byWchar, "æøå"));
1204     assert(equal("æøå".byWchar, "æøå"w));
1205     assert(equal("æøå".byWchar, "æøå"d));
1206     assert(equal("æøå", "æøå".byWchar));
1207     assert(equal("æøå"w, "æøå".byWchar));
1208     assert(equal("æøå"d, "æøå".byWchar));
1209 
1210     assert(equal("æøå".byDchar, "æøå"));
1211     assert(equal("æøå".byDchar, "æøå"w));
1212     assert(equal("æøå".byDchar, "æøå"d));
1213     assert(equal("æøå", "æøå".byDchar));
1214     assert(equal("æøå"w, "æøå".byDchar));
1215     assert(equal("æøå"d, "æøå".byDchar));
1216 }
1217 
1218 @safe @nogc pure unittest
1219 {
1220     struct R(bool _empty) {
1221         enum empty = _empty;
1222         @property char front(){assert(0);}
1223         void popFront(){assert(0);}
1224     }
1225     alias I = R!false;
1226     static assert(!__traits(compiles, I().equal(I())));
1227     // strings have fixed length so don't need to compare elements
1228     assert(!I().equal("foo"));
1229     assert(!"bar".equal(I()));
1230 
1231     alias E = R!true;
1232     assert(E().equal(E()));
1233     assert(E().equal(""));
1234     assert("".equal(E()));
1235     assert(!E().equal("foo"));
1236     assert(!"bar".equal(E()));
1237 }
1238 
1239 // levenshteinDistance
1240 /**
1241 Encodes $(HTTP realityinteractive.com/rgrzywinski/archives/000249.html,
1242 edit operations) necessary to transform one sequence into
1243 another. Given sequences `s` (source) and `t` (target), a
1244 sequence of `EditOp` encodes the steps that need to be taken to
1245 convert `s` into `t`. For example, if `s = "cat"` and $(D
1246 "cars"), the minimal sequence that transforms `s` into `t` is:
1247 skip two characters, replace 't' with 'r', and insert an 's'. Working
1248 with edit operations is useful in applications such as spell-checkers
1249 (to find the closest word to a given misspelled word), approximate
1250 searches, diff-style programs that compute the difference between
1251 files, efficient encoding of patches, DNA sequence analysis, and
1252 plagiarism detection.
1253 */
1254 
1255 enum EditOp : char
1256 {
1257     /** Current items are equal; no editing is necessary. */
1258     none = 'n',
1259     /** Substitute current item in target with current item in source. */
1260     substitute = 's',
1261     /** Insert current item from the source into the target. */
1262     insert = 'i',
1263     /** Remove current item from the target. */
1264     remove = 'r'
1265 }
1266 
1267 ///
1268 @safe unittest
1269 {
1270     with(EditOp)
1271     {
1272         assert(levenshteinDistanceAndPath("foo", "foobar")[1] == [none, none, none, insert, insert, insert]);
1273         assert(levenshteinDistanceAndPath("banana", "fazan")[1] == [substitute, none, substitute, none, none, remove]);
1274     }
1275 }
1276 
1277 private struct Levenshtein(Range, alias equals, CostType = size_t)
1278 {
1279     EditOp[] path()
1280     {
1281         import std.algorithm.mutation : reverse;
1282 
1283         EditOp[] result;
1284         size_t i = rows - 1, j = cols - 1;
1285         // restore the path
1286         while (i || j)
1287         {
1288             auto cIns = j == 0 ? CostType.max : matrix(i,j - 1);
1289             auto cDel = i == 0 ? CostType.max : matrix(i - 1,j);
1290             auto cSub = i == 0 || j == 0
1291                 ? CostType.max
1292                 : matrix(i - 1,j - 1);
1293             switch (min_index(cSub, cIns, cDel))
1294             {
1295             case 0:
1296                 result ~= matrix(i - 1,j - 1) == matrix(i,j)
1297                     ? EditOp.none
1298                     : EditOp.substitute;
1299                 --i;
1300                 --j;
1301                 break;
1302             case 1:
1303                 result ~= EditOp.insert;
1304                 --j;
1305                 break;
1306             default:
1307                 result ~= EditOp.remove;
1308                 --i;
1309                 break;
1310             }
1311         }
1312         reverse(result);
1313         return result;
1314     }
1315 
1316     ~this() {
1317         FreeMatrix();
1318     }
1319 
1320 private:
1321     CostType _deletionIncrement = 1,
1322         _insertionIncrement = 1,
1323         _substitutionIncrement = 1;
1324     CostType[] _matrix;
1325     size_t rows, cols;
1326 
1327     // Treat _matrix as a rectangular array
1328     ref CostType matrix(size_t row, size_t col) { return _matrix[row * cols + col]; }
1329 
1330     void AllocMatrix(size_t r, size_t c) @trusted {
1331         import core.checkedint : mulu;
1332         bool overflow;
1333         const rc = mulu(r, c, overflow);
1334         assert(!overflow, "Overflow during multiplication to determine number "
1335                 ~ " of matrix elements");
1336         rows = r;
1337         cols = c;
1338         if (_matrix.length < rc)
1339         {
1340             import core.exception : onOutOfMemoryError;
1341             import core.stdc.stdlib : realloc;
1342             const nbytes = mulu(rc, _matrix[0].sizeof, overflow);
1343             assert(!overflow, "Overflow during multiplication to determine "
1344                 ~ " number of bytes of matrix");
1345             auto m = cast(CostType *) realloc(_matrix.ptr, nbytes);
1346             if (!m)
1347                 onOutOfMemoryError();
1348             _matrix = m[0 .. r * c];
1349             InitMatrix();
1350         }
1351     }
1352 
1353     void FreeMatrix() @trusted {
1354         import core.stdc.stdlib : free;
1355 
1356         free(_matrix.ptr);
1357         _matrix = null;
1358     }
1359 
1360     void InitMatrix() {
1361         foreach (r; 0 .. rows)
1362             matrix(r,0) = r * _deletionIncrement;
1363         foreach (c; 0 .. cols)
1364             matrix(0,c) = c * _insertionIncrement;
1365     }
1366 
1367     static uint min_index(CostType i0, CostType i1, CostType i2)
1368     {
1369         if (i0 <= i1)
1370         {
1371             return i0 <= i2 ? 0 : 2;
1372         }
1373         else
1374         {
1375             return i1 <= i2 ? 1 : 2;
1376         }
1377     }
1378 
1379     CostType distanceWithPath(Range s, Range t)
1380     {
1381         auto slen = walkLength(s.save), tlen = walkLength(t.save);
1382         AllocMatrix(slen + 1, tlen + 1);
1383         foreach (i; 1 .. rows)
1384         {
1385             auto sfront = s.front;
1386             auto tt = t.save;
1387             foreach (j; 1 .. cols)
1388             {
1389                 auto cSub = matrix(i - 1,j - 1)
1390                     + (equals(sfront, tt.front) ? 0 : _substitutionIncrement);
1391                 tt.popFront();
1392                 auto cIns = matrix(i,j - 1) + _insertionIncrement;
1393                 auto cDel = matrix(i - 1,j) + _deletionIncrement;
1394                 switch (min_index(cSub, cIns, cDel))
1395                 {
1396                 case 0:
1397                     matrix(i,j) = cSub;
1398                     break;
1399                 case 1:
1400                     matrix(i,j) = cIns;
1401                     break;
1402                 default:
1403                     matrix(i,j) = cDel;
1404                     break;
1405                 }
1406             }
1407             s.popFront();
1408         }
1409         return matrix(slen,tlen);
1410     }
1411 
1412     CostType distanceLowMem(Range s, Range t, CostType slen, CostType tlen)
1413     {
1414         CostType lastdiag, olddiag;
1415         AllocMatrix(slen + 1, 1);
1416         foreach (y; 1 .. slen + 1)
1417         {
1418             _matrix[y] = y;
1419         }
1420         foreach (x; 1 .. tlen + 1)
1421         {
1422             auto tfront = t.front;
1423             auto ss = s.save;
1424             _matrix[0] = x;
1425             lastdiag = x - 1;
1426             foreach (y; 1 .. rows)
1427             {
1428                 olddiag = _matrix[y];
1429                 auto cSub = lastdiag + (equals(ss.front, tfront) ? 0 : _substitutionIncrement);
1430                 ss.popFront();
1431                 auto cIns = _matrix[y - 1] + _insertionIncrement;
1432                 auto cDel = _matrix[y] + _deletionIncrement;
1433                 switch (min_index(cSub, cIns, cDel))
1434                 {
1435                 case 0:
1436                     _matrix[y] = cSub;
1437                     break;
1438                 case 1:
1439                     _matrix[y] = cIns;
1440                     break;
1441                 default:
1442                     _matrix[y] = cDel;
1443                     break;
1444                 }
1445                 lastdiag = olddiag;
1446             }
1447             t.popFront();
1448         }
1449         return _matrix[slen];
1450     }
1451 }
1452 
1453 /**
1454 Returns the $(HTTP wikipedia.org/wiki/Levenshtein_distance, Levenshtein
1455 distance) between `s` and `t`. The Levenshtein distance computes
1456 the minimal amount of edit operations necessary to transform `s`
1457 into `t`.  Performs $(BIGOH s.length * t.length) evaluations of $(D
1458 equals) and occupies $(BIGOH min(s.length, t.length)) storage.
1459 
1460 Params:
1461     equals = The binary predicate to compare the elements of the two ranges.
1462     s = The original range.
1463     t = The transformation target
1464 
1465 Returns:
1466     The minimal number of edits to transform s into t.
1467 
1468 Does not allocate GC memory.
1469 */
1470 size_t levenshteinDistance(alias equals = (a,b) => a == b, Range1, Range2)
1471     (Range1 s, Range2 t)
1472 if (isForwardRange!(Range1) && isForwardRange!(Range2))
1473 {
1474     alias eq = binaryFun!(equals);
1475 
1476     for (;;)
1477     {
1478         if (s.empty) return t.walkLength;
1479         if (t.empty) return s.walkLength;
1480         if (eq(s.front, t.front))
1481         {
1482             s.popFront();
1483             t.popFront();
1484             continue;
1485         }
1486         static if (isBidirectionalRange!(Range1) && isBidirectionalRange!(Range2))
1487         {
1488             if (eq(s.back, t.back))
1489             {
1490                 s.popBack();
1491                 t.popBack();
1492                 continue;
1493             }
1494         }
1495         break;
1496     }
1497 
1498     auto slen = walkLength(s.save);
1499     auto tlen = walkLength(t.save);
1500 
1501     if (slen == 1 && tlen == 1)
1502     {
1503         return eq(s.front, t.front) ? 0 : 1;
1504     }
1505 
1506     if (slen < tlen)
1507     {
1508         Levenshtein!(Range1, eq, size_t) lev;
1509         return lev.distanceLowMem(s, t, slen, tlen);
1510     }
1511     else
1512     {
1513         Levenshtein!(Range2, eq, size_t) lev;
1514         return lev.distanceLowMem(t, s, tlen, slen);
1515     }
1516 }
1517 
1518 ///
1519 @safe unittest
1520 {
1521     import std.algorithm.iteration : filter;
1522     import std.uni : toUpper;
1523 
1524     assert(levenshteinDistance("cat", "rat") == 1);
1525     assert(levenshteinDistance("parks", "spark") == 2);
1526     assert(levenshteinDistance("abcde", "abcde") == 0);
1527     assert(levenshteinDistance("abcde", "abCde") == 1);
1528     assert(levenshteinDistance("kitten", "sitting") == 3);
1529     assert(levenshteinDistance!((a, b) => toUpper(a) == toUpper(b))
1530         ("parks", "SPARK") == 2);
1531     assert(levenshteinDistance("parks".filter!"true", "spark".filter!"true") == 2);
1532     assert(levenshteinDistance("ID", "I♥D") == 1);
1533 }
1534 
1535 @safe @nogc nothrow unittest
1536 {
1537     assert(levenshteinDistance("cat"d, "rat"d) == 1);
1538 }
1539 
1540 /// ditto
1541 size_t levenshteinDistance(alias equals = (a,b) => a == b, Range1, Range2)
1542     (auto ref Range1 s, auto ref Range2 t)
1543 if (isConvertibleToString!Range1 || isConvertibleToString!Range2)
1544 {
1545     import std.meta : staticMap;
1546     alias Types = staticMap!(convertToString, Range1, Range2);
1547     return levenshteinDistance!(equals, Types)(s, t);
1548 }
1549 
1550 @safe unittest
1551 {
1552     static struct S { string s; alias s this; }
1553     assert(levenshteinDistance(S("cat"), S("rat")) == 1);
1554     assert(levenshteinDistance("cat", S("rat")) == 1);
1555     assert(levenshteinDistance(S("cat"), "rat") == 1);
1556 }
1557 
1558 @safe @nogc nothrow unittest
1559 {
1560     static struct S { dstring s; alias s this; }
1561     assert(levenshteinDistance(S("cat"d), S("rat"d)) == 1);
1562     assert(levenshteinDistance("cat"d, S("rat"d)) == 1);
1563     assert(levenshteinDistance(S("cat"d), "rat"d) == 1);
1564 }
1565 
1566 /**
1567 Returns the Levenshtein distance and the edit path between `s` and
1568 `t`.
1569 
1570 Params:
1571     equals = The binary predicate to compare the elements of the two ranges.
1572     s = The original range.
1573     t = The transformation target
1574 
1575 Returns:
1576     Tuple with the first element being the minimal amount of edits to transform s into t and
1577     the second element being the sequence of edits to effect this transformation.
1578 
1579 Allocates GC memory for the returned EditOp[] array.
1580 */
1581 Tuple!(size_t, EditOp[])
1582 levenshteinDistanceAndPath(alias equals = (a,b) => a == b, Range1, Range2)
1583     (Range1 s, Range2 t)
1584 if (isForwardRange!(Range1) && isForwardRange!(Range2))
1585 {
1586     Levenshtein!(Range1, binaryFun!(equals)) lev;
1587     auto d = lev.distanceWithPath(s, t);
1588     return tuple(d, lev.path());
1589 }
1590 
1591 ///
1592 @safe unittest
1593 {
1594     string a = "Saturday", b = "Sundays";
1595     auto p = levenshteinDistanceAndPath(a, b);
1596     assert(p[0] == 4);
1597     assert(equal(p[1], "nrrnsnnni"));
1598 }
1599 
1600 @safe unittest
1601 {
1602     assert(levenshteinDistance("a", "a") == 0);
1603     assert(levenshteinDistance("a", "b") == 1);
1604     assert(levenshteinDistance("aa", "ab") == 1);
1605     assert(levenshteinDistance("aa", "abc") == 2);
1606     assert(levenshteinDistance("Saturday", "Sunday") == 3);
1607     assert(levenshteinDistance("kitten", "sitting") == 3);
1608 }
1609 
1610 /// ditto
1611 Tuple!(size_t, EditOp[])
1612 levenshteinDistanceAndPath(alias equals = (a,b) => a == b, Range1, Range2)
1613     (auto ref Range1 s, auto ref Range2 t)
1614 if (isConvertibleToString!Range1 || isConvertibleToString!Range2)
1615 {
1616     import std.meta : staticMap;
1617     alias Types = staticMap!(convertToString, Range1, Range2);
1618     return levenshteinDistanceAndPath!(equals, Types)(s, t);
1619 }
1620 
1621 @safe unittest
1622 {
1623     static struct S { string s; alias s this; }
1624     assert(levenshteinDistanceAndPath(S("cat"), S("rat"))[0] == 1);
1625     assert(levenshteinDistanceAndPath("cat", S("rat"))[0] == 1);
1626     assert(levenshteinDistanceAndPath(S("cat"), "rat")[0] == 1);
1627 }
1628 
1629 
1630 // max
1631 /**
1632 Iterates the passed arguments and returns the maximum value.
1633 
1634 Params:
1635     args = The values to select the maximum from. At least two arguments must
1636     be passed, and they must be comparable with `<`.
1637 
1638 Returns:
1639     The maximum of the passed-in values. The type of the returned value is
1640     the type among the passed arguments that is able to store the largest value.
1641     If at least one of the arguments is NaN, the result is an unspecified value.
1642     See $(REF maxElement, std,algorithm,searching) for examples on how to cope
1643     with NaNs.
1644 
1645 See_Also:
1646     $(REF maxElement, std,algorithm,searching)
1647 */
1648 auto max(T...)(T args)
1649 if (T.length >= 2 && !is(CommonType!T == void))
1650 {
1651     // Get left-hand side of the comparison.
1652     static if (T.length == 2)
1653         alias a = args[0];
1654     else
1655         auto a = max(args[0 .. ($ + 1) / 2]);
1656     alias T0 = typeof(a);
1657 
1658     // Get right-hand side.
1659     static if (T.length <= 3)
1660         alias b = args[$ - 1];
1661     else
1662         auto b = max(args[($ + 1) / 2 .. $]);
1663     alias T1 = typeof(b);
1664 
1665     static assert(is(typeof(a < b)),
1666         "Invalid arguments: Cannot compare types " ~ T0.stringof ~
1667         " and " ~ T1.stringof ~ " for ordering.");
1668 
1669     // Compute the returned type.
1670     static if (is(typeof(mostNegative!T0 < mostNegative!T1)))
1671         // Both are numeric (or character or Boolean), so we choose the one with the highest maximum.
1672         // (We use mostNegative for num/bool/char testing purposes even if it's not used otherwise.)
1673         alias Result = Select!(T1.max > T0.max, T1, T0);
1674     else
1675         // At least one is non-numeric, so just go with the common type.
1676         alias Result = CommonType!(T0, T1);
1677 
1678     // Perform the computation.
1679     import std.functional : lessThan;
1680     immutable chooseB = lessThan!(T0, T1)(a, b);
1681     return cast(Result) (chooseB ? b : a);
1682 }
1683 
1684 /// ditto
1685 T max(T, U)(T a, U b)
1686 if (is(T == U) && is(typeof(a < b)))
1687 {
1688    /* Handle the common case without all the template expansions
1689     * of the general case
1690     */
1691     return a < b ? b : a;
1692 }
1693 
1694 ///
1695 @safe @betterC @nogc unittest
1696 {
1697     int a = 5;
1698     short b = 6;
1699     double c = 2;
1700     auto d = max(a, b);
1701     assert(is(typeof(d) == int));
1702     assert(d == 6);
1703     auto e = min(a, b, c);
1704     assert(is(typeof(e) == double));
1705     assert(e == 2);
1706 }
1707 
1708 @safe unittest  // not @nogc due to `Date`
1709 {
1710     int a = 5;
1711     short b = 6;
1712     double c = 2;
1713     auto d = max(a, b);
1714     static assert(is(typeof(d) == int));
1715     assert(d == 6);
1716     auto e = max(a, b, c);
1717     static assert(is(typeof(e) == double));
1718     assert(e == 6);
1719     // mixed sign
1720     a = -5;
1721     uint f = 5;
1722     static assert(is(typeof(max(a, f)) == uint));
1723     assert(max(a, f) == 5);
1724 
1725     //Test user-defined types
1726     import std.datetime : Date;
1727     assert(max(Date(2012, 12, 21), Date(1982, 1, 4)) == Date(2012, 12, 21));
1728     assert(max(Date(1982, 1, 4), Date(2012, 12, 21)) == Date(2012, 12, 21));
1729     assert(max(Date(1982, 1, 4), Date.min) == Date(1982, 1, 4));
1730     assert(max(Date.min, Date(1982, 1, 4)) == Date(1982, 1, 4));
1731     assert(max(Date(1982, 1, 4), Date.max) == Date.max);
1732     assert(max(Date.max, Date(1982, 1, 4)) == Date.max);
1733     assert(max(Date.min, Date.max) == Date.max);
1734     assert(max(Date.max, Date.min) == Date.max);
1735 }
1736 
1737 // min
1738 /**
1739 Iterates the passed arguments and returns the minimum value.
1740 
1741 Params:
1742     args = The values to select the minimum from. At least two arguments must
1743     be passed, and they must be comparable with `<`.
1744 
1745 Returns:
1746     The minimum of the passed-in values. The type of the returned value is
1747     the type among the passed arguments that is able to store the smallest value.
1748     If at least one of the arguments is NaN, the result is an unspecified value.
1749     See $(REF minElement, std,algorithm,searching) for examples on how to cope
1750     with NaNs.
1751 
1752 See_Also:
1753     $(REF minElement, std,algorithm,searching)
1754 */
1755 auto min(T...)(T args)
1756 if (T.length >= 2 && !is(CommonType!T == void))
1757 {
1758     // Get the left-hand side of the comparison.
1759     static if (T.length <= 2)
1760         alias a = args[0];
1761     else
1762         auto a = min(args[0 .. ($ + 1) / 2]);
1763     alias T0 = typeof(a);
1764 
1765     // Get the right-hand side.
1766     static if (T.length <= 3)
1767         alias b = args[$ - 1];
1768     else
1769         auto b = min(args[($ + 1) / 2 .. $]);
1770     alias T1 = typeof(b);
1771 
1772     static assert(is(typeof(a < b)),
1773         "Invalid arguments: Cannot compare types " ~ T0.stringof ~
1774         " and " ~ T1.stringof ~ " for ordering.");
1775 
1776     // Compute the returned type.
1777     static if (is(typeof(mostNegative!T0 < mostNegative!T1)))
1778         // Both are numeric (or character or Boolean), so we choose the one with the lowest minimum.
1779         // If they have the same minimum, choose the one with the smallest size.
1780         // If both mostNegative and sizeof are equal, go for stability: pick the type of the first one.
1781         alias Result = Select!(mostNegative!T1 < mostNegative!T0 ||
1782                 mostNegative!T1 == mostNegative!T0 && T1.sizeof < T0.sizeof,
1783             T1, T0);
1784     else
1785         // At least one is non-numeric, so just go with the common type.
1786         alias Result = CommonType!(T0, T1);
1787 
1788     // Engage!
1789     import std.functional : lessThan;
1790     immutable chooseB = lessThan!(T1, T0)(b, a);
1791     return cast(Result) (chooseB ? b : a);
1792 }
1793 
1794 /// ditto
1795 T min(T, U)(T a, U b)
1796 if (is(T == U) && is(typeof(a < b)))
1797 {
1798    /* Handle the common case without all the template expansions
1799     * of the general case
1800     */
1801     return b < a ? b : a;
1802 }
1803 
1804 
1805 ///
1806 @safe @nogc @betterC unittest
1807 {
1808     int a = 5;
1809     short b = 6;
1810     double c = 2;
1811     auto d = min(a, b);
1812     static assert(is(typeof(d) == int));
1813     assert(d == 5);
1814     auto e = min(a, b, c);
1815     static assert(is(typeof(e) == double));
1816     assert(e == 2);
1817     ulong f = 0xffff_ffff_ffff;
1818     const uint g = min(f, 0xffff_0000);
1819     assert(g == 0xffff_0000);
1820     dchar h = 100;
1821     uint i = 101;
1822     static assert(is(typeof(min(h, i)) == dchar));
1823     static assert(is(typeof(min(i, h)) == uint));
1824     assert(min(h, i) == 100);
1825 }
1826 
1827 /**
1828 With arguments of mixed signedness, the return type is the one that can
1829 store the lowest values.
1830 */
1831 @safe @nogc @betterC unittest
1832 {
1833     int a = -10;
1834     uint f = 10;
1835     static assert(is(typeof(min(a, f)) == int));
1836     assert(min(a, f) == -10);
1837 }
1838 
1839 /// User-defined types that support comparison with < are supported.
1840 @safe unittest  // not @nogc due to `Date`
1841 {
1842     import std.datetime;
1843     assert(min(Date(2012, 12, 21), Date(1982, 1, 4)) == Date(1982, 1, 4));
1844     assert(min(Date(1982, 1, 4), Date(2012, 12, 21)) == Date(1982, 1, 4));
1845     assert(min(Date(1982, 1, 4), Date.min) == Date.min);
1846     assert(min(Date.min, Date(1982, 1, 4)) == Date.min);
1847     assert(min(Date(1982, 1, 4), Date.max) == Date(1982, 1, 4));
1848     assert(min(Date.max, Date(1982, 1, 4)) == Date(1982, 1, 4));
1849     assert(min(Date.min, Date.max) == Date.min);
1850     assert(min(Date.max, Date.min) == Date.min);
1851 }
1852 
1853 // min must be stable: when in doubt, return the first argument.
1854 @safe unittest
1855 {
1856     assert(min(1.0, double.nan) == 1.0);
1857     assert(min(double.nan, 1.0) is double.nan);
1858     static struct A {
1859         int x;
1860         string y;
1861         int opCmp(const A a) const { return int(x > a.x) - int(x < a.x); }
1862     }
1863     assert(min(A(1, "first"), A(1, "second")) == A(1, "first"));
1864 }
1865 
1866 // mismatch
1867 /**
1868 Sequentially compares elements in `rs` in lockstep, and
1869 stops at the first mismatch (according to `pred`, by default
1870 equality). Returns a tuple with the reduced ranges that start with the
1871 two mismatched values. Performs $(BIGOH min(r[0].length, r[1].length, ...))
1872 evaluations of `pred`.
1873 */
1874 Tuple!(Ranges)
1875 mismatch(alias pred = (a, b) => a == b, Ranges...)(Ranges rs)
1876 if (rs.length >= 2 && allSatisfy!(isInputRange, Ranges))
1877 {
1878     loop: for (; !rs[0].empty; rs[0].popFront)
1879     {
1880         static foreach (r; rs[1 .. $])
1881         {
1882             if (r.empty || !binaryFun!pred(rs[0].front, r.front))
1883                 break loop;
1884             r.popFront;
1885         }
1886     }
1887     return tuple(rs);
1888 }
1889 
1890 ///
1891 @safe @nogc unittest
1892 {
1893     int[6] x = [ 1,   5, 2, 7,   4, 3 ];
1894     double[6] y = [ 1.0, 5, 2, 7.3, 4, 8 ];
1895     auto m = mismatch(x[], y[]);
1896     assert(m[0] == x[3 .. $]);
1897     assert(m[1] == y[3 .. $]);
1898 
1899     auto m2 = mismatch(x[], y[], x[], y[]);
1900     assert(m2[0] == x[3 .. $]);
1901     assert(m2[1] == y[3 .. $]);
1902     assert(m2[2] == x[3 .. $]);
1903     assert(m2[3] == y[3 .. $]);
1904 }
1905 
1906 @safe @nogc unittest
1907 {
1908     import std.range : only;
1909 
1910     int[3] a = [ 1, 2, 3 ];
1911     int[4] b = [ 1, 2, 4, 5 ];
1912     auto mm = mismatch(a[], b[]);
1913     assert(equal(mm[0], only(3)));
1914     assert(equal(mm[1], only(4, 5)));
1915 }
1916 
1917 /**
1918 Returns one of a collection of expressions based on the value of the switch
1919 expression.
1920 
1921 `choices` needs to be composed of pairs of test expressions and return
1922 expressions. Each test-expression is compared with `switchExpression` using
1923 `pred`(`switchExpression` is the first argument) and if that yields true -
1924 the return expression is returned.
1925 
1926 Both the test and the return expressions are lazily evaluated.
1927 
1928 Params:
1929 
1930 switchExpression = The first argument for the predicate.
1931 
1932 choices = Pairs of test expressions and return expressions. The test
1933 expressions will be the second argument for the predicate, and the return
1934 expression will be returned if the predicate yields true with $(D
1935 switchExpression) and the test expression as arguments.  May also have a
1936 default return expression, that needs to be the last expression without a test
1937 expression before it. A return expression may be of void type only if it
1938 always throws.
1939 
1940 Returns: The return expression associated with the first test expression that
1941 made the predicate yield true, or the default return expression if no test
1942 expression matched.
1943 
1944 Throws: If there is no default return expression and the predicate does not
1945 yield true with any test expression - `SwitchError` is thrown. $(D
1946 SwitchError) is also thrown if a void return expression was executed without
1947 throwing anything.
1948 */
1949 auto predSwitch(alias pred = "a == b", T, R ...)(T switchExpression, lazy R choices)
1950 {
1951     import core.exception : SwitchError;
1952     alias predicate = binaryFun!(pred);
1953 
1954     foreach (index, ChoiceType; R)
1955     {
1956         //The even places in `choices` are for the predicate.
1957         static if (index % 2 == 1)
1958         {
1959             if (predicate(switchExpression, choices[index - 1]()))
1960             {
1961                 static if (is(typeof(choices[index]()) == void))
1962                 {
1963                     choices[index]();
1964                     throw new SwitchError("Choices that return void should throw");
1965                 }
1966                 else
1967                 {
1968                     return choices[index]();
1969                 }
1970             }
1971         }
1972     }
1973 
1974     //In case nothing matched:
1975     static if (R.length % 2 == 1) //If there is a default return expression:
1976     {
1977         static if (is(typeof(choices[$ - 1]()) == void))
1978         {
1979             choices[$ - 1]();
1980             throw new SwitchError("Choices that return void should throw");
1981         }
1982         else
1983         {
1984             return choices[$ - 1]();
1985         }
1986     }
1987     else //If there is no default return expression:
1988     {
1989         throw new SwitchError("Input not matched by any pattern");
1990     }
1991 }
1992 
1993 ///
1994 @safe unittest
1995 {
1996     string res = 2.predSwitch!"a < b"(
1997         1, "less than 1",
1998         5, "less than 5",
1999         10, "less than 10",
2000         "greater or equal to 10");
2001 
2002     assert(res == "less than 5");
2003 
2004     //The arguments are lazy, which allows us to use predSwitch to create
2005     //recursive functions:
2006     int factorial(int n)
2007     {
2008         return n.predSwitch!"a <= b"(
2009             -1, {throw new Exception("Can not calculate n! for n < 0");}(),
2010             0, 1, // 0! = 1
2011             n * factorial(n - 1) // n! = n * (n - 1)! for n >= 0
2012             );
2013     }
2014     assert(factorial(3) == 6);
2015 
2016     //Void return expressions are allowed if they always throw:
2017     import std.exception : assertThrown;
2018     assertThrown!Exception(factorial(-9));
2019 }
2020 
2021 @system unittest
2022 {
2023     import core.exception : SwitchError;
2024     import std.exception : assertThrown;
2025 
2026     //Nothing matches - with default return expression:
2027     assert(20.predSwitch!"a < b"(
2028         1, "less than 1",
2029         5, "less than 5",
2030         10, "less than 10",
2031         "greater or equal to 10") == "greater or equal to 10");
2032 
2033     //Nothing matches - without default return expression:
2034     assertThrown!SwitchError(20.predSwitch!"a < b"(
2035         1, "less than 1",
2036         5, "less than 5",
2037         10, "less than 10",
2038         ));
2039 
2040     //Using the default predicate:
2041     assert(2.predSwitch(
2042                 1, "one",
2043                 2, "two",
2044                 3, "three",
2045                 ) == "two");
2046 
2047     //Void return expressions must always throw:
2048     assertThrown!SwitchError(1.predSwitch(
2049                 0, "zero",
2050                 1, {}(), //A void return expression that doesn't throw
2051                 2, "two",
2052                 ));
2053 }
2054 
2055 /**
2056 Checks if two or more ranges have the same number of elements. This function is
2057 optimized to always take advantage of the `length` member of either range
2058 if it exists.
2059 
2060 If all ranges have a `length` member or at least one is infinite,
2061 `_isSameLength`'s complexity is $(BIGOH 1). Otherwise, complexity is
2062 $(BIGOH n), where `n` is the smallest of the lengths of ranges with unknown
2063 length.
2064 
2065 Infinite ranges are considered of the same length. An infinite range has never
2066 the same length as a finite range.
2067 
2068 Params:
2069     rs = two or more $(REF_ALTTEXT input ranges, isInputRange, std,range,primitives)
2070 
2071 Returns:
2072     `true` if both ranges have the same length, `false` otherwise.
2073 */
2074 bool isSameLength(Ranges...)(Ranges rs)
2075 if (allSatisfy!(isInputRange, Ranges))
2076 {
2077     static if (anySatisfy!(isInfinite, Ranges))
2078     {
2079         return allSatisfy!(isInfinite, Ranges);
2080     }
2081     else static if (anySatisfy!(hasLength, Ranges))
2082     {
2083         // Compute the O(1) length
2084         auto baselineLength = size_t.max;
2085         static foreach (i, R; Ranges)
2086         {
2087             static if (hasLength!R)
2088             {
2089                 if (baselineLength == size_t.max)
2090                     baselineLength = rs[i].length;
2091                 else if (rs[i].length != baselineLength)
2092                     return false;
2093             }
2094         }
2095         // Iterate all ranges without known length
2096         foreach (_; 0 .. baselineLength)
2097             static foreach (i, R; Ranges)
2098             {
2099                 static if (!hasLength!R)
2100                 {
2101                     // All must be non-empty
2102                     if (rs[i].empty)
2103                         return false;
2104                     rs[i].popFront;
2105                 }
2106             }
2107         static foreach (i, R; Ranges)
2108         {
2109             static if (!hasLength!R)
2110             {
2111                 // All must be now empty
2112                 if (!rs[i].empty)
2113                     return false;
2114             }
2115         }
2116         return true;
2117     }
2118     else
2119     {
2120         // All have unknown length, iterate in lockstep
2121         for (;;)
2122             static foreach (i, r; rs)
2123             {
2124                 if (r.empty)
2125                 {
2126                     // One is empty, so all must be empty
2127                     static if (i != 0)
2128                     {
2129                         return false;
2130                     }
2131                     else
2132                     {
2133                         static foreach (j, r1; rs[1 .. $])
2134                             if (!r1.empty)
2135                                 return false;
2136                         return true;
2137                     }
2138                 }
2139                 r.popFront;
2140             }
2141     }
2142 }
2143 
2144 ///
2145 @safe nothrow pure unittest
2146 {
2147     assert(isSameLength([1, 2, 3], [4, 5, 6]));
2148     assert(isSameLength([1, 2, 3], [4, 5, 6], [7, 8, 9]));
2149     assert(isSameLength([0.3, 90.4, 23.7, 119.2], [42.6, 23.6, 95.5, 6.3]));
2150     assert(isSameLength("abc", "xyz"));
2151     assert(isSameLength("abc", "xyz", [1, 2, 3]));
2152 
2153     int[] a;
2154     int[] b;
2155     assert(isSameLength(a, b));
2156     assert(isSameLength(a, b, a, a, b, b, b));
2157 
2158     assert(!isSameLength([1, 2, 3], [4, 5]));
2159     assert(!isSameLength([1, 2, 3], [4, 5, 6], [7, 8]));
2160     assert(!isSameLength([0.3, 90.4, 23.7], [42.6, 23.6, 95.5, 6.3]));
2161     assert(!isSameLength("abcd", "xyz"));
2162     assert(!isSameLength("abcd", "xyz", "123"));
2163     assert(!isSameLength("abcd", "xyz", "1234"));
2164 }
2165 
2166 // Test CTFE
2167 @safe @nogc pure @betterC unittest
2168 {
2169     static assert(isSameLength([1, 2, 3], [4, 5, 6]));
2170     static assert(isSameLength([1, 2, 3], [4, 5, 6], [7, 8, 9]));
2171     static assert(!isSameLength([0.3, 90.4, 23.7], [42.6, 23.6, 95.5, 6.3]));
2172     static assert(!isSameLength([1], [0.3, 90.4], [42]));
2173 }
2174 
2175 @safe @nogc pure unittest
2176 {
2177     import std.range : only;
2178     assert(isSameLength(only(1, 2, 3), only(4, 5, 6)));
2179     assert(isSameLength(only(1, 2, 3), only(4, 5, 6), only(7, 8, 9)));
2180     assert(isSameLength(only(0.3, 90.4, 23.7, 119.2), only(42.6, 23.6, 95.5, 6.3)));
2181     assert(!isSameLength(only(1, 3, 3), only(4, 5)));
2182     assert(!isSameLength(only(1, 3, 3), only(1, 3, 3), only(4, 5)));
2183     assert(!isSameLength(only(1, 3, 3), only(4, 5), only(1, 3, 3)));
2184 }
2185 
2186 @safe nothrow pure unittest
2187 {
2188     import std.internal.test.dummyrange;
2189 
2190     auto r1 = new ReferenceInputRange!int([1, 2, 3]);
2191     auto r2 = new ReferenceInputRange!int([4, 5, 6]);
2192     assert(isSameLength(r1, r2));
2193 
2194     auto r3 = new ReferenceInputRange!int([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
2195     DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Input) r4;
2196     assert(isSameLength(r3, r4));
2197 
2198     DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Input) r5;
2199     auto r6 = new ReferenceInputRange!int([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
2200     assert(isSameLength(r5, r6));
2201 
2202     auto r7 = new ReferenceInputRange!int([1, 2]);
2203     auto r8 = new ReferenceInputRange!int([4, 5, 6]);
2204     assert(!isSameLength(r7, r8));
2205 
2206     auto r9 = new ReferenceInputRange!int([1, 2, 3, 4, 5, 6, 7, 8]);
2207     DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Input) r10;
2208     assert(!isSameLength(r9, r10));
2209 
2210     DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Input) r11;
2211     auto r12 = new ReferenceInputRange!int([1, 2, 3, 4, 5, 6, 7, 8]);
2212     assert(!isSameLength(r11, r12));
2213 
2214     import std.algorithm.iteration : filter;
2215 
2216     assert(isSameLength(filter!"a >= 1"([1, 2, 3]), [4, 5, 6]));
2217     assert(!isSameLength(filter!"a > 1"([1, 2, 3]), [4, 5, 6]));
2218 
2219     assert(isSameLength(filter!"a > 1"([1, 2, 3]), filter!"a > 4"([4, 5, 6])));
2220     assert(isSameLength(filter!"a > 1"([1, 2, 3]),
2221         filter!"a > 4"([4, 5, 6]), filter!"a >= 5"([4, 5, 6])));
2222 }
2223 
2224 // Still functional but not documented anymore.
2225 alias AllocateGC = Flag!"allocateGC";
2226 
2227 /**
2228 Checks if both ranges are permutations of each other.
2229 
2230 This function can allocate if the `Yes.allocateGC` flag is passed. This has
2231 the benefit of have better complexity than the `Yes.allocateGC` option. However,
2232 this option is only available for ranges whose equality can be determined via each
2233 element's `toHash` method. If customized equality is needed, then the `pred`
2234 template parameter can be passed, and the function will automatically switch to
2235 the non-allocating algorithm. See $(REF binaryFun, std,functional) for more details on
2236 how to define `pred`.
2237 
2238 Non-allocating forward range option: $(BIGOH n^2)
2239 Non-allocating forward range option with custom `pred`: $(BIGOH n^2)
2240 Allocating forward range option: amortized $(BIGOH r1.length) + $(BIGOH r2.length)
2241 
2242 Params:
2243     pred = an optional parameter to change how equality is defined
2244     allocateGC = `Yes.allocateGC`/`No.allocateGC`
2245     r1 = A finite $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
2246     r2 = A finite $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
2247 
2248 Returns:
2249     `true` if all of the elements in `r1` appear the same number of times in `r2`.
2250     Otherwise, returns `false`.
2251 */
2252 
2253 bool isPermutation(Flag!"allocateGC" allocateGC, Range1, Range2)
2254 (Range1 r1, Range2 r2)
2255 if (allocateGC == Yes.allocateGC &&
2256     isForwardRange!Range1 &&
2257     isForwardRange!Range2 &&
2258     !isInfinite!Range1 &&
2259     !isInfinite!Range2)
2260 {
2261     alias E1 = Unqual!(ElementType!Range1);
2262     alias E2 = Unqual!(ElementType!Range2);
2263 
2264     if (!isSameLength(r1.save, r2.save))
2265     {
2266         return false;
2267     }
2268 
2269     // Skip the elements at the beginning where r1.front == r2.front,
2270     // they are in the same order and don't need to be counted.
2271     while (!r1.empty && !r2.empty && r1.front == r2.front)
2272     {
2273         r1.popFront();
2274         r2.popFront();
2275     }
2276 
2277     if (r1.empty && r2.empty)
2278     {
2279         return true;
2280     }
2281 
2282     int[CommonType!(E1, E2)] counts;
2283 
2284     foreach (item; r1)
2285     {
2286         ++counts[item];
2287     }
2288 
2289     foreach (item; r2)
2290     {
2291         if (--counts[item] < 0)
2292         {
2293             return false;
2294         }
2295     }
2296 
2297     return true;
2298 }
2299 
2300 /// ditto
2301 bool isPermutation(alias pred = "a == b", Range1, Range2)
2302 (Range1 r1, Range2 r2)
2303 if (is(typeof(binaryFun!(pred))) &&
2304     isForwardRange!Range1 &&
2305     isForwardRange!Range2 &&
2306     !isInfinite!Range1 &&
2307     !isInfinite!Range2)
2308 {
2309     import std.algorithm.searching : count;
2310 
2311     alias predEquals = binaryFun!(pred);
2312     alias E1 = Unqual!(ElementType!Range1);
2313     alias E2 = Unqual!(ElementType!Range2);
2314 
2315     if (!isSameLength(r1.save, r2.save))
2316     {
2317         return false;
2318     }
2319 
2320     // Skip the elements at the beginning where r1.front == r2.front,
2321     // they are in the same order and don't need to be counted.
2322     while (!r1.empty && !r2.empty && predEquals(r1.front, r2.front))
2323     {
2324         r1.popFront();
2325         r2.popFront();
2326     }
2327 
2328     if (r1.empty && r2.empty)
2329     {
2330         return true;
2331     }
2332 
2333     size_t r1_count;
2334     size_t r2_count;
2335 
2336     // At each element item, when computing the count of item, scan it while
2337     // also keeping track of the scanning index. If the first occurrence
2338     // of item in the scanning loop has an index smaller than the current index,
2339     // then you know that the element has been seen before
2340     size_t index;
2341     outloop: for (auto r1s1 = r1.save; !r1s1.empty; r1s1.popFront, index++)
2342     {
2343         auto item = r1s1.front;
2344         r1_count = 0;
2345         r2_count = 0;
2346 
2347         size_t i;
2348         for (auto r1s2 = r1.save; !r1s2.empty; r1s2.popFront, i++)
2349         {
2350             auto e = r1s2.front;
2351             if (predEquals(e, item) && i < index)
2352             {
2353                  continue outloop;
2354             }
2355             else if (predEquals(e, item))
2356             {
2357                 ++r1_count;
2358             }
2359         }
2360 
2361         r2_count = r2.save.count!pred(item);
2362 
2363         if (r1_count != r2_count)
2364         {
2365             return false;
2366         }
2367     }
2368 
2369     return true;
2370 }
2371 
2372 ///
2373 @safe pure unittest
2374 {
2375     import std.typecons : Yes;
2376 
2377     assert(isPermutation([1, 2, 3], [3, 2, 1]));
2378     assert(isPermutation([1.1, 2.3, 3.5], [2.3, 3.5, 1.1]));
2379     assert(isPermutation("abc", "bca"));
2380 
2381     assert(!isPermutation([1, 2], [3, 4]));
2382     assert(!isPermutation([1, 1, 2, 3], [1, 2, 2, 3]));
2383     assert(!isPermutation([1, 1], [1, 1, 1]));
2384 
2385     // Faster, but allocates GC handled memory
2386     assert(isPermutation!(Yes.allocateGC)([1.1, 2.3, 3.5], [2.3, 3.5, 1.1]));
2387     assert(!isPermutation!(Yes.allocateGC)([1, 2], [3, 4]));
2388 }
2389 
2390 // Test @nogc inference
2391 @safe @nogc pure unittest
2392 {
2393     static immutable arr1 = [1, 2, 3];
2394     static immutable arr2 = [3, 2, 1];
2395     assert(isPermutation(arr1, arr2));
2396 
2397     static immutable arr3 = [1, 1, 2, 3];
2398     static immutable arr4 = [1, 2, 2, 3];
2399     assert(!isPermutation(arr3, arr4));
2400 }
2401 
2402 @safe pure unittest
2403 {
2404     import std.internal.test.dummyrange;
2405 
2406     auto r1 = new ReferenceForwardRange!int([1, 2, 3, 4]);
2407     auto r2 = new ReferenceForwardRange!int([1, 2, 4, 3]);
2408     assert(isPermutation(r1, r2));
2409 
2410     auto r3 = new ReferenceForwardRange!int([1, 2, 3, 4]);
2411     auto r4 = new ReferenceForwardRange!int([4, 2, 1, 3]);
2412     assert(isPermutation!(Yes.allocateGC)(r3, r4));
2413 
2414     auto r5 = new ReferenceForwardRange!int([1, 2, 3]);
2415     auto r6 = new ReferenceForwardRange!int([4, 2, 1, 3]);
2416     assert(!isPermutation(r5, r6));
2417 
2418     auto r7 = new ReferenceForwardRange!int([4, 2, 1, 3]);
2419     auto r8 = new ReferenceForwardRange!int([1, 2, 3]);
2420     assert(!isPermutation!(Yes.allocateGC)(r7, r8));
2421 
2422     DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Random) r9;
2423     DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Random) r10;
2424     assert(isPermutation(r9, r10));
2425 
2426     DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Random) r11;
2427     DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Random) r12;
2428     assert(isPermutation!(Yes.allocateGC)(r11, r12));
2429 
2430     alias mytuple = Tuple!(int, int);
2431 
2432     assert(isPermutation!"a[0] == b[0]"(
2433         [mytuple(1, 4), mytuple(2, 5)],
2434         [mytuple(2, 3), mytuple(1, 2)]
2435     ));
2436 }
2437 
2438 /**
2439 Get the _first argument `a` that passes an `if (unaryFun!pred(a))` test.  If
2440 no argument passes the test, return the last argument.
2441 
2442 Similar to behaviour of the `or` operator in dynamic languages such as Lisp's
2443 `(or ...)` and Python's `a or b or ...` except that the last argument is
2444 returned upon no match.
2445 
2446 Simplifies logic, for instance, in parsing rules where a set of alternative
2447 matchers are tried. The _first one that matches returns it match result,
2448 typically as an abstract syntax tree (AST).
2449 
2450 Bugs:
2451 Lazy parameters are currently, too restrictively, inferred by DMD to
2452 always throw even though they don't need to be. This makes it impossible to
2453 currently mark `either` as `nothrow`. See issue at $(BUGZILLA 12647).
2454 
2455 Returns:
2456     The _first argument that passes the test `pred`.
2457 */
2458 CommonType!(T, Ts) either(alias pred = a => a, T, Ts...)(T first, lazy Ts alternatives)
2459 if (alternatives.length >= 1 &&
2460     !is(CommonType!(T, Ts) == void) &&
2461     allSatisfy!(ifTestable, T, Ts))
2462 {
2463     alias predFun = unaryFun!pred;
2464 
2465     if (predFun(first)) return first;
2466 
2467     foreach (e; alternatives[0 .. $ - 1])
2468         if (predFun(e)) return e;
2469 
2470     return alternatives[$ - 1];
2471 }
2472 
2473 ///
2474 @safe pure @betterC unittest
2475 {
2476     const a = 1;
2477     const b = 2;
2478     auto ab = either(a, b);
2479     static assert(is(typeof(ab) == const(int)));
2480     assert(ab == a);
2481 
2482     auto c = 2;
2483     const d = 3;
2484     auto cd = either!(a => a == 3)(c, d); // use predicate
2485     static assert(is(typeof(cd) == int));
2486     assert(cd == d);
2487 
2488     auto e = 0;
2489     const f = 2;
2490     auto ef = either(e, f);
2491     static assert(is(typeof(ef) == int));
2492     assert(ef == f);
2493 }
2494 
2495 ///
2496 @safe pure unittest
2497 {
2498     immutable p = 1;
2499     immutable q = 2;
2500     auto pq = either(p, q);
2501     static assert(is(typeof(pq) == immutable(int)));
2502     assert(pq == p);
2503 
2504     assert(either(3, 4) == 3);
2505     assert(either(0, 4) == 4);
2506     assert(either(0, 0) == 0);
2507     assert(either("", "a") == "");
2508 }
2509 
2510 ///
2511 @safe pure unittest
2512 {
2513     string r = null;
2514     assert(either(r, "a") == "a");
2515     assert(either("a", "") == "a");
2516 
2517     immutable s = [1, 2];
2518     assert(either(s, s) == s);
2519 
2520     assert(either([0, 1], [1, 2]) == [0, 1]);
2521     assert(either([0, 1], [1]) == [0, 1]);
2522     assert(either("a", "b") == "a");
2523 
2524     static assert(!__traits(compiles, either(1, "a")));
2525     static assert(!__traits(compiles, either(1.0, "a")));
2526     static assert(!__traits(compiles, either('a', "a")));
2527 }