@@ -3544,6 +3544,213 @@ unittest
35443544 assert (minPos! (" a[0] < b[0]" )(b) == [ [2 , 4 ], [4 ], [4 ] ]);
35453545}
35463546
3547+ /**
3548+ Computes the index of the first occurrence of `range`'s minimum element.
3549+
3550+ Params:
3551+ pred = The ordering predicate to use to determine the minimum element.
3552+ range = The input range to search.
3553+
3554+ Complexity: O(n)
3555+ Exactly `n - 1` comparisons are needed.
3556+
3557+ Returns:
3558+ The index of the first encounter of the minimum element in `range`. If the
3559+ `range` is empty, -1 is returned.
3560+
3561+ See_Also:
3562+ $(REF min, std,algorithm,comparison), $(LREF minCount), $(LREF minElement), $(LREF minPos)
3563+ */
3564+ sizediff_t minIndex (alias pred = " a < b" , Range )(Range range)
3565+ if (isForwardRange! Range && ! isInfinite! Range &&
3566+ is (typeof (binaryFun! pred(range.front, range.front))))
3567+ {
3568+ if (range.empty) return - 1 ;
3569+
3570+ sizediff_t minPos = 0 ;
3571+
3572+ static if (isRandomAccessRange! Range && hasLength! Range )
3573+ {
3574+ foreach (i; 1 .. range.length)
3575+ {
3576+ if (binaryFun! pred(range[i], range[minPos]))
3577+ {
3578+ minPos = i;
3579+ }
3580+ }
3581+ }
3582+ else
3583+ {
3584+ sizediff_t curPos = 0 ;
3585+ Unqual! (typeof (range.front)) min = range.front;
3586+ for (range.popFront(); ! range.empty; range.popFront())
3587+ {
3588+ ++ curPos;
3589+ if (binaryFun! pred(range.front, min))
3590+ {
3591+ min = range.front;
3592+ minPos = curPos;
3593+ }
3594+ }
3595+ }
3596+ return minPos;
3597+ }
3598+
3599+ // /
3600+ @safe pure nothrow unittest
3601+ {
3602+ int [] a = [2 , 3 , 4 , 1 , 2 , 4 , 1 , 1 , 2 ];
3603+
3604+ // Minimum is 1 and first occurs in position 3
3605+ assert (a.minIndex == 3 );
3606+ // Get maximum index with minIndex
3607+ assert (a.minIndex! " a > b" == 2 );
3608+
3609+ // Range is empty, so return value is -1
3610+ int [] b;
3611+ assert (b.minIndex == - 1 );
3612+
3613+ // Works with more custom types
3614+ struct Dog { int age; }
3615+ Dog[] dogs = [Dog(10 ), Dog(5 ), Dog(15 )];
3616+ assert (dogs.minIndex! " a.age < b.age" == 1 );
3617+ }
3618+
3619+ @safe pure unittest
3620+ {
3621+ // should work with const
3622+ const (int )[] immArr = [2 , 1 , 3 ];
3623+ assert (immArr.minIndex == 1 );
3624+
3625+ // Works for const ranges too
3626+ const int [] c = [2 , 5 , 4 , 1 , 2 , 3 ];
3627+ assert (c.minIndex == 3 );
3628+
3629+ // should work with immutable
3630+ immutable (int )[] immArr2 = [2 , 1 , 3 ];
3631+ assert (immArr2.minIndex == 1 );
3632+
3633+ // with strings
3634+ assert ([" b" , " a" , " c" ].minIndex == 1 );
3635+
3636+ // infinite range
3637+ import std.range : cycle;
3638+ static assert (! __traits(compiles, cycle([1 ]).minIndex));
3639+
3640+ // with all dummy ranges
3641+ import std.internal.test.dummyrange : AllDummyRanges;
3642+ foreach (DummyType; AllDummyRanges)
3643+ {
3644+ static if (isForwardRange! DummyType && ! isInfinite! DummyType)
3645+ {
3646+ DummyType d;
3647+ d.arr = [5 , 3 , 7 , 2 , 1 , 4 ];
3648+ assert (d.minIndex == 4 );
3649+
3650+ d.arr = [];
3651+ assert (d.minIndex == - 1 );
3652+ }
3653+ }
3654+ }
3655+
3656+ @nogc @safe nothrow pure unittest
3657+ {
3658+ static immutable arr = [7 , 3 , 8 , 2 , 1 , 4 ];
3659+ assert (arr.minIndex == 4 );
3660+
3661+ static immutable arr2d = [[1 , 3 ], [3 , 9 ], [4 , 2 ]];
3662+ assert (arr2d.minIndex! " a[1] < b[1]" == 2 );
3663+ }
3664+
3665+ /**
3666+ Computes the index of the first occurrence of `range`'s maximum element.
3667+
3668+ Complexity: O(n)
3669+ Exactly `n - 1` comparisons are needed.
3670+
3671+ Params:
3672+ pred = The ordering predicate to use to determine the maximum element.
3673+ range = The input range to search.
3674+
3675+ Returns:
3676+ The index of the first encounter of the maximum in `range`. If the
3677+ `range` is empty, -1 is returned.
3678+
3679+ See_Also:
3680+ $(REF max, std,algorithm,comparison), $(LREF maxCount), $(LREF maxElement), $(LREF maxPos)
3681+ */
3682+ sizediff_t maxIndex (alias pred = " a < b" , Range )(Range range)
3683+ if (isInputRange! Range && ! isInfinite! Range &&
3684+ is (typeof (binaryFun! pred(range.front, range.front))))
3685+ {
3686+ return range.minIndex! ((a, b) => binaryFun! pred(b, a));
3687+ }
3688+
3689+ // /
3690+ @safe pure nothrow unittest
3691+ {
3692+ // Maximum is 4 and first occurs in position 2
3693+ int [] a = [2 , 3 , 4 , 1 , 2 , 4 , 1 , 1 , 2 ];
3694+ assert (a.maxIndex == 2 );
3695+
3696+ // Empty range
3697+ int [] b;
3698+ assert (b.maxIndex == - 1 );
3699+
3700+ // Works with more custom types
3701+ struct Dog { int age; }
3702+ Dog[] dogs = [Dog(10 ), Dog(15 ), Dog(5 )];
3703+ assert (dogs.maxIndex! " a.age < b.age" == 1 );
3704+ }
3705+
3706+ @safe pure unittest
3707+ {
3708+ // should work with const
3709+ const (int )[] immArr = [5 , 1 , 3 ];
3710+ assert (immArr.maxIndex == 0 );
3711+
3712+ // Works for const ranges too
3713+ const int [] c = [2 , 5 , 4 , 1 , 2 , 3 ];
3714+ assert (c.maxIndex == 1 );
3715+
3716+
3717+ // should work with immutable
3718+ immutable (int )[] immArr2 = [2 , 1 , 3 ];
3719+ assert (immArr2.maxIndex == 2 );
3720+
3721+ // with strings
3722+ assert ([" b" , " a" , " c" ].maxIndex == 2 );
3723+
3724+ // infinite range
3725+ import std.range : cycle;
3726+ static assert (! __traits(compiles, cycle([1 ]).maxIndex));
3727+
3728+ // with all dummy ranges
3729+ import std.internal.test.dummyrange : AllDummyRanges;
3730+ foreach (DummyType; AllDummyRanges)
3731+ {
3732+ static if (isForwardRange! DummyType && ! isInfinite! DummyType)
3733+ {
3734+ DummyType d;
3735+
3736+ d.arr = [5 , 3 , 7 , 2 , 1 , 4 ];
3737+ assert (d.maxIndex == 2 );
3738+
3739+ d.arr = [];
3740+ assert (d.maxIndex == - 1 );
3741+ }
3742+ }
3743+ }
3744+
3745+ @nogc @safe nothrow pure unittest
3746+ {
3747+ static immutable arr = [7 , 3 , 8 , 2 , 1 , 4 ];
3748+ assert (arr.maxIndex == 2 );
3749+
3750+ static immutable arr2d = [[1 , 3 ], [3 , 9 ], [4 , 2 ]];
3751+ assert (arr2d.maxIndex! " a[1] < b[1]" == 1 );
3752+ }
3753+
35473754/**
35483755Skip over the initial portion of the first given range that matches the second
35493756range, or do nothing if there is no match.
0 commit comments