aboutsummaryrefslogtreecommitdiff
path: root/libphobos/src/std/algorithm
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2025-01-09 23:56:49 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2025-01-12 23:18:25 +0100
commita2e540bf0150b1a2f05924ce6d5210dc0048471d (patch)
treeb46d2d634704cfea7200180a0d03ddc5303aab0b /libphobos/src/std/algorithm
parentf4fa0b7d493a4ba217d989d3df75bbe3730874fc (diff)
downloadgcc-a2e540bf0150b1a2f05924ce6d5210dc0048471d.zip
gcc-a2e540bf0150b1a2f05924ce6d5210dc0048471d.tar.gz
gcc-a2e540bf0150b1a2f05924ce6d5210dc0048471d.tar.bz2
d: Merge dmd, druntime c7902293d7, phobos 03aeafd20
D front-end changes: - Import dmd v2.110.0-rc.1. - An error is now given for subtracting pointers of different types. D runtime changes: - Import druntime v2.110.0-rc.1. Phobos changes: - Import phobos v2.110.0-rc.1. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd c7902293d7. * dmd/VERSION: Bump version to v2.110.0-rc.1. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime c7902293d7. * libdruntime/Makefile.am (DRUNTIME_DSOURCES): Rename core/thread/fiber.d to core/thread/fiber/package.d. Add core/thread/fiber/base.d. * libdruntime/Makefile.in: Regenerate. * src/MERGE: Merge upstream phobos 63fdb282f. gcc/testsuite/ChangeLog: * gdc.dg/asm3.d: Adjust test. * gdc.dg/torture/pr96435.d: Adjust test.
Diffstat (limited to 'libphobos/src/std/algorithm')
-rw-r--r--libphobos/src/std/algorithm/searching.d131
1 files changed, 129 insertions, 2 deletions
diff --git a/libphobos/src/std/algorithm/searching.d b/libphobos/src/std/algorithm/searching.d
index e0d2435..924ea1c 100644
--- a/libphobos/src/std/algorithm/searching.d
+++ b/libphobos/src/std/algorithm/searching.d
@@ -34,6 +34,7 @@ $(T2 commonPrefix,
`commonPrefix("parakeet", "parachute")` returns `"para"`.)
$(T2 endsWith,
`endsWith("rocks", "ks")` returns `true`.)
+$(T2 extrema, `extrema([2, 1, 3, 5, 4])` returns `[1, 5]`.)
$(T2 find,
`find("hello world", "or")` returns `"orld"` using linear search.
(For binary search refer to $(REF SortedRange, std,range).))
@@ -3684,7 +3685,7 @@ Note:
See_Also:
- $(LREF maxElement), $(REF min, std,algorithm,comparison), $(LREF minCount),
+ $(LREF extrema), $(LREF maxElement), $(REF min, std,algorithm,comparison), $(LREF minCount),
$(LREF minIndex), $(LREF minPos)
*/
auto minElement(alias map = (a => a), Range)(Range r)
@@ -3865,7 +3866,7 @@ Note:
See_Also:
- $(LREF minElement), $(REF max, std,algorithm,comparison), $(LREF maxCount),
+ $(LREF extrema), $(LREF minElement), $(REF max, std,algorithm,comparison), $(LREF maxCount),
$(LREF maxIndex), $(LREF maxPos)
*/
auto maxElement(alias map = (a => a), Range)(Range r)
@@ -4035,6 +4036,132 @@ if (isInputRange!Range && !isInfinite!Range &&
assert(maxElement(arr) == S(145));
}
+/** Returns an array of the minimum and maximum element in `r`.
+ * Performs `< 3n/2` comparisons, unlike the naive `< 2n`.
+ * Params:
+ * r = The range to traverse.
+ */
+// TODO alias map = a => a
+ElementType!Range[2] extrema(Range)(Range r)
+if (isInputRange!Range && !isInfinite!Range)
+in (!r.empty)
+{
+ static if (isRandomAccessRange!Range && hasLength!Range)
+ {
+ if (r.length == 1)
+ return [r[0], r[0]];
+
+ typeof(return) result;
+ size_t i;
+ if (r.length & 1) // odd
+ {
+ result = [r[0], r[0]];
+ i = 1;
+ }
+ else
+ {
+ result = (r[0] < r[1]) ? [r[0], r[1]] : [r[1], r[0]];
+ i = 2;
+ }
+ // iterate pairs
+ const imax = r.length;
+ for (; i != imax; i += 2)
+ {
+ // save work
+ if (r[i] < r[i+1])
+ {
+ if (r[i] < result[0])
+ result[0] = r[i];
+ if (r[i+1] > result[1])
+ result[1] = r[i+1];
+ }
+ else
+ {
+ if (r[i+1] < result[0])
+ result[0] = r[i+1];
+ if (r[i] > result[1])
+ result[1] = r[i];
+ }
+ }
+ return result;
+ }
+ else
+ {
+ auto first = r.front;
+ r.popFront;
+ if (r.empty)
+ return [first, first];
+
+ typeof(return) result = (first < r.front) ? [first, r.front] : [r.front, first];
+ // iterate pairs
+ while (true)
+ {
+ r.popFront;
+ if (r.empty)
+ return result;
+ first = r.front;
+ r.popFront;
+ if (r.empty)
+ {
+ if (first < result[0])
+ result[0] = first;
+ else if (first > result[1])
+ result[1] = first;
+ return result;
+ }
+ // save work
+ if (first < r.front)
+ {
+ if (first < result[0])
+ result[0] = first;
+ if (r.front > result[1])
+ result[1] = r.front;
+ }
+ else
+ {
+ if (r.front < result[0])
+ result[0] = r.front;
+ if (first > result[1])
+ result[1] = first;
+ }
+ }
+ }
+}
+
+///
+@safe unittest
+{
+ assert(extrema([5,2,9,4,1]) == [1, 9]);
+}
+
+@safe unittest
+{
+ assert(extrema([8,3,7,4,9]) == [3, 9]);
+ assert(extrema([1,5,3,2]) == [1, 5]);
+ assert(extrema([2,3,3,2]) == [2, 3]);
+
+ import std.range;
+ assert(iota(2, 5).extrema == [2, 4]);
+ assert(iota(3, 7).retro.extrema == [3, 6]);
+
+ import std.internal.test.dummyrange;
+ foreach (DummyType; AllDummyRanges)
+ {
+ DummyType d;
+ assert(d.extrema == [1, 10]);
+ }
+
+ version (StdRandomTests)
+ foreach (i; 0 .. 1000)
+ {
+ import std.random;
+ auto arr = generate!(() => uniform(0, 100)).takeExactly(uniform(1, 10)).array;
+ auto result = arr.extrema;
+ assert(result[0] == arr.minElement);
+ assert(result[1] == arr.maxElement);
+ }
+}
+
// minPos
/**
Computes a subrange of `range` starting at the first occurrence of `range`'s