Skip to content

Commit 3145024

Browse files
committed
add assumeSortedContains & assumeSortedEqualIndex
1 parent cbc3a23 commit 3145024

File tree

1 file changed

+97
-1
lines changed

1 file changed

+97
-1
lines changed

source/mir/ndslice/sorting.d

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,14 +465,108 @@ void medianOf(alias less, Iterator)
465465
}
466466
}
467467

468+
/++
469+
Returns: `true` if a sorted array contains the value.
470+
471+
Params:
472+
test = strict ordering symmetric predicate
473+
474+
For non-symmetric predicates please use a structure with two `opCall`s or an alias of two global functions,
475+
that correponds to `(array[i], value)` and `(value, array[i])` cases.
468476
477+
See_also: $(LREF transitionIndex).
478+
+/
479+
template assumeSortedContains(alias test = "a < b")
480+
{
481+
import mir.functional: naryFun;
482+
static if (__traits(isSame, naryFun!test, test))
483+
{
484+
@optmath:
485+
/++
486+
Params:
487+
slice = sorted one-dimensional slice or array.
488+
v = value to test with. It is passed to second argument.
489+
+/
490+
bool assumeSortedContains(Iterator, SliceKind kind, V)
491+
(auto ref Slice!(Iterator, 1, kind) slice, auto ref scope const V v)
492+
{
493+
auto ti = transitionIndex!test(slice, v);
494+
return ti < slice.length && !test(v, slice[ti]);
495+
}
469496

497+
/// ditto
498+
bool assumeSortedContains(T, V)(scope T[] ar, auto ref scope const V v)
499+
{
500+
return .assumeSortedContains!test(ar.sliced, v);
501+
}
502+
}
503+
else
504+
alias assumeSortedContains = .assumeSortedContains!(naryFun!test);
505+
}
506+
507+
/++
508+
Returns: the smallest index of a sorted array such
509+
that the index corresponds to the arrays element at the index according to the predicate
510+
and array length if the array doesn't contain corresponding element.
511+
512+
Params:
513+
test = strict ordering symmetric predicate.
514+
515+
For non-symmetric predicates please use a structure with two `opCall`s or an alias of two global functions,
516+
that correponds to `(array[i], value)` and `(value, array[i])` cases.
517+
518+
See_also: $(LREF transitionIndex).
519+
+/
520+
template assumeSortedEqualIndex(alias test = "a < b")
521+
{
522+
import mir.functional: naryFun;
523+
static if (__traits(isSame, naryFun!test, test))
524+
{
525+
@optmath:
526+
/++
527+
Params:
528+
slice = sorted one-dimensional slice or array.
529+
v = value to test with. It is passed to second argument.
530+
+/
531+
size_t assumeSortedEqualIndex(Iterator, SliceKind kind, V)
532+
(auto ref Slice!(Iterator, 1, kind) slice, auto ref scope const V v)
533+
{
534+
auto ti = transitionIndex!test(slice, v);
535+
return ti < slice.length && !test(v, slice[ti]) ? ti : slice.length;
536+
}
537+
538+
/// ditto
539+
size_t assumeSortedEqualIndex(T, V)(scope T[] ar, auto ref scope const V v)
540+
{
541+
return .assumeSortedEqualIndex!test(ar.sliced, v);
542+
}
543+
}
544+
else
545+
alias assumeSortedEqualIndex = .assumeSortedEqualIndex!(naryFun!test);
546+
}
547+
548+
///
549+
version(mir_test)
550+
@safe pure unittest
551+
{
552+
// sorted: a < b
553+
auto a = [0, 1, 2, 3, 4, 6];
554+
555+
assert(a.assumeSortedEqualIndex(2) == 2);
556+
assert(a.assumeSortedEqualIndex(5) == a.length);
557+
558+
// <= non strict predicates doesn't work
559+
assert(a.assumeSortedEqualIndex!"a <= b"(2) == a.length);
560+
}
470561

471562
/++
472563
Computes transition index using binary search.
473564
It is low-level API for lower and upper bounds of a sorted array.
474565
475-
See_also: $(SUBREF topology, flattened).
566+
Params:
567+
test = ordering predicate for (`(array[i], value)`) pairs.
568+
569+
See_also: $(SUBREF topology, assumeSortedEqualIndex).
476570
+/
477571
template transitionIndex(alias test = "a < b")
478572
{
@@ -517,6 +611,7 @@ template transitionIndex(alias test = "a < b")
517611
}
518612

519613
///
614+
version(mir_test)
520615
@safe pure unittest
521616
{
522617
// sorted: a < b
@@ -570,6 +665,7 @@ I[] makeIndex(I = size_t, alias less = "a < b", T)(scope T[] r)
570665
}
571666

572667
///
668+
version(mir_test)
573669
@system unittest
574670
{
575671
import mir.algorithm.iteration: all;

0 commit comments

Comments
 (0)