diff --git a/source/tanya/algorithm/comparison.d b/source/tanya/algorithm/comparison.d deleted file mode 100644 index 7aa7013..0000000 --- a/source/tanya/algorithm/comparison.d +++ /dev/null @@ -1,375 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/** - * Algorithms for comparing values. - * - * Copyright: Eugene Wissner 2018-2020. - * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, - * Mozilla Public License, v. 2.0). - * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) - * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/algorithm/comparison.d, - * tanya/algorithm/comparison.d) - */ -module tanya.algorithm.comparison; - -import std.traits : CommonType; -import tanya.algorithm.mutation; -import tanya.math; -static import tanya.memory.op; -import tanya.meta.metafunction; -import tanya.meta.trait; -import tanya.meta.transform; -import tanya.range.array; -import tanya.range.primitive; - -private ref inout(Args[0]) minMax(alias cmp, Args...)(ref inout Args args) -{ - auto actual = ((ref arg) @trusted => &arg)(args[0]); - - foreach (i, arg; args[1 .. $]) - { - static if (isFloatingPoint!(Args[0])) - { - if (isNaN(arg)) - { - continue; - } - if (isNaN(*actual)) - { - actual = ((ref arg) @trusted => &arg)(args[i + 1]); - continue; - } - } - if (cmp(arg, *actual)) - { - actual = ((ref arg) @trusted => &arg)(args[i + 1]); - } - } - - return *actual; -} - -private T moveIf(T)(ref T arg) -{ - static if (hasElaborateCopyConstructor!T && isMutable!T) - { - return move(arg); - } - else - { - return arg; - } -} - -/** - * Finds the smallest element in the argument list or a range. - * - * If a range is passed, $(D_PSYMBOL min) returns a range of the same type, - * whose front element is the smallest in the range. If more than one element - * fulfills this condition, the front of the returned range points to - * the first one found. - * If $(D_PARAM range) is empty, the original range is returned. - * - * If $(D_PARAM Args) are floating point numbers, $(B NaN) is not considered - * for comparison. $(B NaN) is returned only if all arguments are $(B NaN)s. - * - * Params: - * Args = Types of the arguments. All arguments should have the same type. - * Range = Forward range type. - * args = Argument list. - * range = Forward range. - * - * Returns: The smallest element. - */ -CommonType!Args min(Args...)(Args args) -if (Args.length >= 2 - && isOrderingComparable!(Args[0]) - && allSameType!(Map!(Unqual, Args))) -{ - return moveIf(minMax!((ref a, ref b) => a < b)(args)); -} - -/// ditto -ref inout(Unqual!(Args[0])) min(Args...)(ref inout Args args) -if (Args.length >= 2 - && isOrderingComparable!(Args[0]) - && allSameType!(Map!(Unqual, Args))) -{ - return minMax!((ref a, ref b) => a < b)(args); -} - -/// ditto -Range min(Range)(Range range) -if (isForwardRange!Range && isOrderingComparable!(ElementType!Range)) -{ - if (range.empty) - { - return range; - } - auto actual = range.save; - - range.popFront(); - for (; !range.empty; range.popFront()) - { - if (range.front < actual.front) - { - actual = range.save; - } - } - - return actual; -} - -/// -@nogc nothrow pure @safe unittest -{ - assert(min(1, 2) == 1); - assert(min(3, 2) == 2); - assert(min(3, 1, 2) == 1); - - int[4] range = [3, 1, 1, 2]; - auto minElement = min(range[]); - assert(minElement.front == 1); - assert(minElement.length == 3); -} - -/** - * Finds the largest element in the argument list or a range. - * - * If a range is passed, $(D_PSYMBOL max) returns a range of the same type, - * whose front element is the largest in the range. If more than one element - * fulfills this condition, the front of the returned range points to - * the first one found. - * If $(D_PARAM range) is empty, the original range is returned. - * - * If $(D_PARAM Args) are floating point numbers, $(B NaN) is not considered - * for comparison. $(B NaN) is returned only if all arguments are $(B NaN)s. - * - * Params: - * Args = Types of the arguments. All arguments should have the same type. - * Range = Forward range type. - * args = Argument list. - * range = Forward range. - * - * Returns: The largest element. - */ -CommonType!Args max(Args...)(Args args) -if (Args.length >= 2 - && isOrderingComparable!(Args[0]) - && allSameType!(Map!(Unqual, Args))) -{ - return moveIf(minMax!((ref a, ref b) => a > b)(args)); -} - -/// ditto -ref inout(Unqual!(Args[0])) max(Args...)(ref inout Args args) -if (Args.length >= 2 - && isOrderingComparable!(Args[0]) - && allSameType!(Map!(Unqual, Args))) -{ - return minMax!((ref a, ref b) => a > b)(args); -} - -/// ditto -Range max(Range)(Range range) -if (isForwardRange!Range && isOrderingComparable!(ElementType!Range)) -{ - if (range.empty) - { - return range; - } - auto actual = range.save; - - range.popFront(); - for (; !range.empty; range.popFront()) - { - if (range.front > actual.front) - { - actual = range.save; - } - } - - return actual; -} - -/// -@nogc nothrow pure @safe unittest -{ - assert(max(1, 2) == 2); - assert(max(3, 2) == 3); - assert(max(1, 3, 2) == 3); - - int[4] range = [1, 5, 5, 2]; - auto maxElement = max(range[]); - assert(maxElement.front == 5); - assert(maxElement.length == 3); -} - -/** - * Compares element-wise two ranges for equality. - * - * If the ranges have different lengths, they aren't equal. - * - * Params: - * pred = Predicate used to compare individual element pairs. - * R1 = First range type. - * R2 = Second range type. - * r1 = First range. - * r2 = Second range. - * - * Returns: $(D_KEYWORD true) if both ranges are equal, $(D_KEYWORD false) - * otherwise. - */ -bool equal(alias pred = (auto ref a, auto ref b) => a == b, R1, R2) - (R1 r1, R2 r2) -if (allSatisfy!(isInputRange, R1, R2) - && is(typeof(pred(r1.front, r2.front)) == bool)) -{ - static if (isDynamicArray!R1 - && is(R1 == R2) - && __traits(isPOD, ElementType!R1)) - { - return tanya.memory.op.equal(r1, r2); - } - else - { - static if (hasLength!R1 && hasLength!R2) - { - if (r1.length != r2.length) - { - return false; - } - } - for (; !r1.empty && !r2.empty; r1.popFront(), r2.popFront()) - { - if (!pred(r1.front, r2.front)) - { - return false; - } - } - static if (hasLength!R1 && hasLength!R2) - { - return true; - } - else - { - return r1.empty && r2.empty; - } - } -} - -/// -@nogc nothrow pure @safe unittest -{ - int[2] range1 = [1, 2]; - assert(equal(range1[], range1[])); - - int[3] range2 = [1, 2, 3]; - assert(!equal(range1[], range2[])); -} - -/** - * Compares element-wise two ranges for ordering. - * - * $(D_PSYMBOL compare) returns a negative value if $(D_PARAM r1) is less than - * $(D_PARAM r2), a positive value if $(D_PARAM r2) is less than $(D_PARAM r1), - * or `0` if $(D_PARAM r1) and $(D_PARAM r2) equal. - * - * $(D_PSYMBOL compare) iterates both ranges in lockstep. Whichever of them - * contains an element that is greater than the respective element at the same - * position in the other range is the greater one of the two. - * - * If one of the ranges becomes empty when iterating, but all elements equal so - * far, the range with more elements is the greater one. - * - * If $(D_PARAM pred) is given, it is used for comparison. $(D_PARAM pred) is - * called as $(D_INLINECODE pred(r1.front, r2.front)) and - * $(D_INLINECODE pred(r2.front, r1.front)) to perform three-way comparison. - * $(D_PARAM pred) should return a $(D_KEYWORD bool). - * - * If $(D_PARAM pred) is not given, but the element type of $(D_PARAM R1) - * defines `opCmp()` for the element type of $(D_PARAM R2), `opCmp()` is used. - * - * Otherwise the comparison is perfomed using the basic comparison operators. - * - * Params: - * pred = Predicate used for comparison. - * R1 = First range type. - * R2 = Second range type. - * r1 = First range. - * r2 = Second range. - * - * Returns: A negative value if $(D_PARAM r1) is less than $(D_PARAM r2), a - * positive value if $D(_PARAM r2) is less than $(D_PARAM r1), `0` - * otherwise. - */ -int compare(alias pred, R1, R2)(R1 r1, R2 r2) -if (allSatisfy!(isInputRange, R1, R2) - && is(typeof(pred(r1.front, r2.front)) == bool) - && is(typeof(pred(r2.front, r1.front)) == bool)) -{ - alias predImpl = (ref r1, ref r2) { - return pred(r2.front, r1.front) - pred(r1.front, r2.front); - }; - return compareImpl!(predImpl, R1, R2)(r1, r2); -} - -/// ditto -int compare(R1, R2)(R1 r1, R2 r2) -if (allSatisfy!(isInputRange, R1, R2) - && is(typeof(r1.front < r2.front || r2.front < r1.front))) -{ - static if (is(typeof(r1.front.opCmp(r2.front)) == int)) - { - alias pred = (ref r1, ref r2) => r1.front.opCmp(r2.front); - } - else - { - alias pred = (ref r1, ref r2) { - return (r2.front < r1.front) - (r1.front < r2.front); - }; - } - return compareImpl!(pred, R1, R2)(r1, r2); -} - -/// -@nogc nothrow pure @safe unittest -{ - assert(compare("abc", "abc") == 0); - assert(compare("abcd", "abc") > 0); - assert(compare("ab", "abc") < 0); - assert(compare("abc", "abcd") < 0); - assert(compare("abc", "ab") > 0); - assert(compare("aec", "abc") > 0); - assert(compare("aac", "abc") < 0); - assert(compare("abc", "aec") < 0); - assert(compare("abc", "aab") > 0); - assert(compare("aacd", "abc") < 0); - assert(compare("abc", "aacd") > 0); - - assert(compare!((a, b) => a > b)("aec", "abc") < 0); - assert(compare!((a, b) => a > b)("aac", "abc") > 0); -} - -private int compareImpl(alias pred, R1, R2)(ref R1 r1, ref R2 r2) -{ - for (; !r1.empty || !r2.empty; r1.popFront(), r2.popFront()) - { - if (r1.empty) - { - return -1; - } - else if (r2.empty) - { - return 1; - } - const comparison = pred(r1, r2); - if (comparison != 0) - { - return comparison; - } - } - return 0; -} diff --git a/source/tanya/algorithm/iteration.d b/source/tanya/algorithm/iteration.d index 7526df8..343f3b6 100644 --- a/source/tanya/algorithm/iteration.d +++ b/source/tanya/algorithm/iteration.d @@ -20,7 +20,7 @@ */ module tanya.algorithm.iteration; -import tanya.algorithm.comparison; +import std.algorithm.comparison; import tanya.memory.lifetime; import tanya.meta.trait; import tanya.meta.transform; @@ -558,8 +558,6 @@ if (isBidirectionalRange!Range) /// @nogc nothrow pure @safe unittest { - import tanya.algorithm.comparison : equal; - const int[3] given = [1, 2, 3]; const int[3] expected = [3, 2, 1]; diff --git a/source/tanya/algorithm/mutation.d b/source/tanya/algorithm/mutation.d index 9d9523d..1a51a49 100644 --- a/source/tanya/algorithm/mutation.d +++ b/source/tanya/algorithm/mutation.d @@ -77,7 +77,7 @@ do /// @nogc nothrow pure @safe unittest { - import tanya.algorithm.comparison : equal; + import std.algorithm.comparison : equal; const int[2] source = [1, 2]; int[2] target = [3, 4]; @@ -114,7 +114,7 @@ if (isInputRange!Range && isAssignable!(ElementType!Range, Value)) /// @nogc nothrow pure @safe unittest { - import tanya.algorithm.comparison : equal; + import std.algorithm.comparison : equal; int[6] actual; const int[6] expected = [1, 1, 1, 1, 1, 1]; @@ -154,7 +154,7 @@ if (isInputRange!Range && hasLvalueElements!Range /// @nogc nothrow pure @safe unittest { - import tanya.algorithm.comparison : equal; + import std.algorithm.comparison : equal; int[6] actual = void; const int[6] expected = [1, 1, 1, 1, 1, 1]; @@ -196,7 +196,7 @@ if (isInputRange!Range && hasLvalueElements!Range) /// @nogc nothrow pure @safe unittest { - import tanya.algorithm.comparison : equal; + import std.algorithm.comparison : equal; int[2] actual = void; const int[2] expected = [0, 0]; @@ -287,7 +287,7 @@ if (isForwardRange!Range && hasSwappableElements!Range) /// @nogc nothrow pure @safe unittest { - import tanya.algorithm.comparison : equal; + import std.algorithm.comparison : equal; const int[7] expected = [1, 2, 3, 4, 5, 6, 7]; int[7] actual = [5, 6, 3, 4, 1, 2, 7]; diff --git a/source/tanya/algorithm/package.d b/source/tanya/algorithm/package.d index 5ebe268..1aee863 100644 --- a/source/tanya/algorithm/package.d +++ b/source/tanya/algorithm/package.d @@ -14,7 +14,6 @@ */ module tanya.algorithm; -public import tanya.algorithm.comparison; public import tanya.algorithm.iteration; public import tanya.algorithm.mutation; public import tanya.algorithm.searching; diff --git a/source/tanya/async/event/epoll.d b/source/tanya/async/event/epoll.d index 93ba727..7d3854d 100644 --- a/source/tanya/async/event/epoll.d +++ b/source/tanya/async/event/epoll.d @@ -23,7 +23,7 @@ import core.stdc.errno; public import core.sys.linux.epoll; import core.sys.posix.unistd; import core.time; -import tanya.algorithm.comparison; +import std.algorithm.comparison; import tanya.async.event.selector; import tanya.async.loop; import tanya.async.protocol; diff --git a/source/tanya/container/array.d b/source/tanya/container/array.d index 614020b..dcd2074 100644 --- a/source/tanya/container/array.d +++ b/source/tanya/container/array.d @@ -15,7 +15,7 @@ module tanya.container.array; import core.checkedint; -import tanya.algorithm.comparison; +import std.algorithm.comparison; import tanya.algorithm.iteration; import tanya.algorithm.mutation; import tanya.memory.allocator; diff --git a/source/tanya/container/list.d b/source/tanya/container/list.d index 86b06b1..0d8fc3d 100644 --- a/source/tanya/container/list.d +++ b/source/tanya/container/list.d @@ -15,7 +15,7 @@ */ module tanya.container.list; -import tanya.algorithm.comparison; +import std.algorithm.comparison; import tanya.algorithm.iteration; import tanya.container.entry; import tanya.memory.allocator; diff --git a/source/tanya/container/string.d b/source/tanya/container/string.d index d65c027..6fad9bb 100644 --- a/source/tanya/container/string.d +++ b/source/tanya/container/string.d @@ -26,7 +26,7 @@ */ module tanya.container.string; -import tanya.algorithm.comparison; +import std.algorithm.comparison; import tanya.algorithm.mutation; import tanya.hash.lookup; import tanya.memory.allocator; @@ -1166,29 +1166,29 @@ struct String int opCmp(S)(auto ref S that) const @trusted if (is(Unqual!S == String)) { - return compare(this.data[0 .. length], that.data[0 .. that.length]); + return cmp(this.data[0 .. length], that.data[0 .. that.length]); } /// ditto int opCmp(S)(ByCodeUnit!S that) const @trusted if (is(Unqual!S == char)) { - return compare(this.data[0 .. length], - that.begin[0 .. that.end - that.begin]); + return cmp(this.data[0 .. length], + that.begin[0 .. that.end - that.begin]); } /// ditto int opCmp(S)(ByCodePoint!S that) const @trusted if (is(Unqual!S == char)) { - return compare(this.data[0 .. length], - that.begin[0 .. that.end - that.begin]); + return cmp(this.data[0 .. length], + that.begin[0 .. that.end - that.begin]); } /// ditto int opCmp()(const char[] that) const @trusted { - return compare(this.data[0 .. length], that); + return cmp(this.data[0 .. length], that); } /// diff --git a/source/tanya/format.d b/source/tanya/format.d index b89bbf9..0e349e3 100644 --- a/source/tanya/format.d +++ b/source/tanya/format.d @@ -47,7 +47,7 @@ */ module tanya.format; -import tanya.algorithm.comparison; +import std.algorithm.comparison; import tanya.container.string; import tanya.encoding.ascii; import tanya.math; diff --git a/source/tanya/net/ip.d b/source/tanya/net/ip.d index 294ac95..59d19d9 100644 --- a/source/tanya/net/ip.d +++ b/source/tanya/net/ip.d @@ -14,7 +14,7 @@ */ module tanya.net.ip; -import tanya.algorithm.comparison; +import std.algorithm.comparison; import tanya.algorithm.iteration; import tanya.algorithm.mutation; import tanya.container.string; @@ -465,7 +465,7 @@ struct Address6 */ int opCmp(ref const Address6 that) const @nogc nothrow pure @safe { - const diff = compare(this.address[], that.address[]); + const diff = cmp(this.address[], that.address[]); if (diff == 0) { return (that.scopeID < this.scopeID) - (this.scopeID < that.scopeID); diff --git a/source/tanya/network/socket.d b/source/tanya/network/socket.d index ffe5846..bfd192f 100644 --- a/source/tanya/network/socket.d +++ b/source/tanya/network/socket.d @@ -53,7 +53,6 @@ module tanya.network.socket; import core.stdc.errno; import core.time; public import std.socket : SocketOption, SocketOptionLevel; -import tanya.algorithm.comparison; import tanya.bitmanip; import tanya.memory.allocator; import tanya.meta.trait; diff --git a/source/tanya/range/primitive.d b/source/tanya/range/primitive.d index 1296dad..b4dcb2e 100644 --- a/source/tanya/range/primitive.d +++ b/source/tanya/range/primitive.d @@ -14,7 +14,7 @@ */ module tanya.range.primitive; -import tanya.algorithm.comparison; +import std.algorithm.comparison; import tanya.memory.lifetime; import tanya.meta.trait; import tanya.meta.transform; @@ -305,7 +305,7 @@ private template isDynamicArrayRange(R) private struct Primitive(Candidate, string primitive) { - auto ref returnType(Candidate candidate) + auto ref returnType(ref Candidate candidate) { mixin("return candidate." ~ primitive ~ ";"); } diff --git a/tests/tanya/algorithm/tests/comparison.d b/tests/tanya/algorithm/tests/comparison.d deleted file mode 100644 index 5bd561a..0000000 --- a/tests/tanya/algorithm/tests/comparison.d +++ /dev/null @@ -1,97 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -module tanya.algorithm.tests.comparison; - -import tanya.algorithm.comparison; -import tanya.math; -import tanya.range; - -@nogc nothrow pure @safe unittest -{ - static assert(!is(typeof(min(1, 1UL)))); -} - -@nogc nothrow pure @safe unittest -{ - assert(min(5, 3) == 3); - assert(min(4, 4) == 4); - assert(min(5.2, 3.0) == 3.0); - - assert(min(5.2, double.nan) == 5.2); - assert(min(double.nan, 3.0) == 3.0); - assert(isNaN(min(double.nan, double.nan))); -} - -@nogc nothrow pure @safe unittest -{ - assert(min(cast(ubyte[]) []).empty); -} - -@nogc nothrow pure @safe unittest -{ - static assert(!is(typeof(max(1, 1UL)))); -} - -@nogc nothrow pure @safe unittest -{ - assert(max(5, 3) == 5); - assert(max(4, 4) == 4); - assert(max(5.2, 3.0) == 5.2); - - assert(max(5.2, double.nan) == 5.2); - assert(max(double.nan, 3.0) == 3.0); - assert(isNaN(max(double.nan, double.nan))); -} - -@nogc nothrow pure @safe unittest -{ - assert(max(cast(ubyte[]) []).empty); -} - -// min/max compare const and mutable structs. -@nogc nothrow pure @safe unittest -{ - static struct S - { - int s; - - int opCmp(typeof(this) that) const @nogc nothrow pure @safe - { - return this.s - that.s; - } - } - { - const s1 = S(1); - assert(min(s1, S(2)).s == 1); - assert(max(s1, S(2)).s == 2); - } - { - auto s2 = S(2), s3 = S(3); - assert(min(s2, s3).s == 2); - assert(max(s2, s3).s == 3); - } -} - -@nogc nothrow pure @safe unittest -{ - static struct OpCmp(int value) - { - int opCmp(OpCmp) @nogc nothrow pure @safe - { - return value; - } - } - { - OpCmp!(-1)[1] range; - assert(compare(range[], range[]) < 0); - } - { - OpCmp!1[1] range; - assert(compare(range[], range[]) > 0); - } - { - OpCmp!0[1] range; - assert(compare(range[], range[]) == 0); - } -} diff --git a/tests/tanya/algorithm/tests/mutation.d b/tests/tanya/algorithm/tests/mutation.d index 5d98233..19ab636 100644 --- a/tests/tanya/algorithm/tests/mutation.d +++ b/tests/tanya/algorithm/tests/mutation.d @@ -17,7 +17,7 @@ import tanya.test.stub; // Copies overlapping arrays @nogc nothrow pure @safe unittest { - import tanya.algorithm.comparison : equal; + import std.algorithm.comparison : equal; int[6] actual = [1, 2, 3, 4, 5, 6]; const int[6] expected = [1, 2, 1, 2, 3, 4]; @@ -94,7 +94,7 @@ import tanya.test.stub; @nogc nothrow pure @safe unittest { - import tanya.algorithm.comparison : equal; + import std.algorithm.comparison : equal; const int[5] expected = [1, 2, 3, 4, 5]; int[5] actual = [4, 5, 1, 2, 3]; @@ -106,7 +106,7 @@ import tanya.test.stub; // Doesn't cause an infinite loop if back is shorter than the front @nogc nothrow pure @safe unittest { - import tanya.algorithm.comparison : equal; + import std.algorithm.comparison : equal; const int[5] expected = [1, 2, 3, 4, 5]; int[5] actual = [3, 4, 5, 1, 2]; @@ -118,7 +118,7 @@ import tanya.test.stub; // Doesn't call .front on an empty front @nogc nothrow pure @safe unittest { - import tanya.algorithm.comparison : equal; + import std.algorithm.comparison : equal; const int[2] expected = [2, 8]; int[2] actual = expected; diff --git a/tests/tanya/container/tests/array.d b/tests/tanya/container/tests/array.d index 6dd90b4..2f2eeec 100644 --- a/tests/tanya/container/tests/array.d +++ b/tests/tanya/container/tests/array.d @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ module tanya.container.tests.array; -import tanya.algorithm.comparison; +import std.algorithm.comparison; import tanya.container.array; import tanya.memory.allocator; import tanya.test.stub; @@ -187,10 +187,3 @@ import tanya.test.stub; } func(array); } - -// Can have non-copyable elements -@nogc nothrow pure @safe unittest -{ - static assert(is(Array!NonCopyable)); - static assert(is(typeof({ Array!NonCopyable.init[0] = NonCopyable(); }))); -} diff --git a/tests/tanya/net/tests/iface.d b/tests/tanya/net/tests/iface.d index 4ddb6f0..c77692a 100644 --- a/tests/tanya/net/tests/iface.d +++ b/tests/tanya/net/tests/iface.d @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ module tanya.net.tests.iface; -import tanya.algorithm.comparison; +import std.algorithm.comparison; import tanya.net.iface; @nogc nothrow @safe unittest