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