Deprecate math.min/max in favour of tanya.algorithm
This commit is contained in:
parent
c0f9e5be10
commit
6e2852000b
@ -14,6 +14,8 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.algorithm.comparison;
|
module tanya.algorithm.comparison;
|
||||||
|
|
||||||
|
import tanya.algorithm.mutation;
|
||||||
|
import tanya.math : isNaN;
|
||||||
import tanya.meta.metafunction;
|
import tanya.meta.metafunction;
|
||||||
import tanya.meta.trait;
|
import tanya.meta.trait;
|
||||||
import tanya.meta.transform;
|
import tanya.meta.transform;
|
||||||
@ -22,30 +24,55 @@ import tanya.range.primitive;
|
|||||||
|
|
||||||
private ref inout(Args[0]) minMax(alias cmp, Args...)(ref inout Args args)
|
private ref inout(Args[0]) minMax(alias cmp, Args...)(ref inout Args args)
|
||||||
{
|
{
|
||||||
auto actual = ((ref inout arg) @trusted => &arg)(args[0]);
|
auto actual = ((ref arg) @trusted => &arg)(args[0]);
|
||||||
|
|
||||||
foreach (i, arg; args[1 .. $])
|
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))
|
if (cmp(arg, *actual))
|
||||||
{
|
{
|
||||||
actual = ((ref inout arg) @trusted => &arg)(args[i + 1]);
|
actual = ((ref arg) @trusted => &arg)(args[i + 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return *actual;
|
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.
|
* Finds the smallest element in the argument list or a range.
|
||||||
*
|
*
|
||||||
* The function should take at least one argument.
|
|
||||||
*
|
|
||||||
* If a range is passed, $(D_PSYMBOL min) returns a range of the same type,
|
* 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
|
* 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
|
* fulfills this condition, the front of the returned range points to
|
||||||
* the first one found.
|
* the first one found.
|
||||||
* If $(D_PARAM range) is empty, the original range is returned.
|
* 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:
|
* Params:
|
||||||
* Args = Types of the arguments. All arguments should have the same type.
|
* Args = Types of the arguments. All arguments should have the same type.
|
||||||
* Range = Forward range type.
|
* Range = Forward range type.
|
||||||
@ -54,29 +81,39 @@ private ref inout(Args[0]) minMax(alias cmp, Args...)(ref inout Args args)
|
|||||||
*
|
*
|
||||||
* Returns: The smallest element.
|
* Returns: The smallest element.
|
||||||
*/
|
*/
|
||||||
inout(Unqual!(Args[0])) min(Args...)(inout Args args)
|
CommonType!Args min(Args...)(Args args)
|
||||||
if (Args.length > 0
|
if (Args.length >= 2
|
||||||
&& isOrderingComparable!(Args[0])
|
&& isOrderingComparable!(Args[0])
|
||||||
&& allSameType!(Map!(Unqual, Args)))
|
&& allSameType!(Map!(Unqual, Args)))
|
||||||
{
|
{
|
||||||
return minMax!((a, b) => a < b)(args);
|
return moveIf(minMax!((ref a, ref b) => a < b)(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
ref inout(Unqual!(Args[0])) min(Args...)(ref inout Args args)
|
ref inout(Unqual!(Args[0])) min(Args...)(ref inout Args args)
|
||||||
if (Args.length > 0
|
if (Args.length >= 2
|
||||||
&& isOrderingComparable!(Args[0])
|
&& isOrderingComparable!(Args[0])
|
||||||
&& allSameType!(Map!(Unqual, Args)))
|
&& allSameType!(Map!(Unqual, Args)))
|
||||||
{
|
{
|
||||||
return minMax!((a, b) => a < b)(args);
|
return minMax!((ref a, ref b) => a < b)(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
assert(min(1) == 1);
|
|
||||||
static assert(!is(typeof(min(1, 1UL))));
|
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)));
|
||||||
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
Range min(Range)(Range range)
|
Range min(Range)(Range range)
|
||||||
if (isForwardRange!Range && isOrderingComparable!(ElementType!Range))
|
if (isForwardRange!Range && isOrderingComparable!(ElementType!Range))
|
||||||
@ -120,14 +157,15 @@ if (isForwardRange!Range && isOrderingComparable!(ElementType!Range))
|
|||||||
/**
|
/**
|
||||||
* Finds the largest element in the argument list or a range.
|
* Finds the largest element in the argument list or a range.
|
||||||
*
|
*
|
||||||
* The function should take at least one argument.
|
|
||||||
*
|
|
||||||
* If a range is passed, $(D_PSYMBOL max) returns a range of the same type,
|
* 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
|
* 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
|
* fulfills this condition, the front of the returned range points to
|
||||||
* the first one found.
|
* the first one found.
|
||||||
* If $(D_PARAM range) is empty, the original range is returned.
|
* 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:
|
* Params:
|
||||||
* Args = Types of the arguments. All arguments should have the same type.
|
* Args = Types of the arguments. All arguments should have the same type.
|
||||||
* Range = Forward range type.
|
* Range = Forward range type.
|
||||||
@ -136,29 +174,39 @@ if (isForwardRange!Range && isOrderingComparable!(ElementType!Range))
|
|||||||
*
|
*
|
||||||
* Returns: The largest element.
|
* Returns: The largest element.
|
||||||
*/
|
*/
|
||||||
inout(Unqual!(Args[0])) max(Args...)(inout Args args)
|
CommonType!Args max(Args...)(Args args)
|
||||||
if (Args.length > 0
|
if (Args.length >= 2
|
||||||
&& isOrderingComparable!(Args[0])
|
&& isOrderingComparable!(Args[0])
|
||||||
&& allSameType!(Map!(Unqual, Args)))
|
&& allSameType!(Map!(Unqual, Args)))
|
||||||
{
|
{
|
||||||
return minMax!((a, b) => a > b)(args);
|
return moveIf(minMax!((ref a, ref b) => a > b)(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
ref inout(Unqual!(Args[0])) max(Args...)(ref inout Args args)
|
ref inout(Unqual!(Args[0])) max(Args...)(ref inout Args args)
|
||||||
if (Args.length > 0
|
if (Args.length >= 2
|
||||||
&& isOrderingComparable!(Args[0])
|
&& isOrderingComparable!(Args[0])
|
||||||
&& allSameType!(Map!(Unqual, Args)))
|
&& allSameType!(Map!(Unqual, Args)))
|
||||||
{
|
{
|
||||||
return minMax!((a, b) => a > b)(args);
|
return minMax!((ref a, ref b) => a > b)(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
assert(max(1) == 1);
|
|
||||||
static assert(!is(typeof(max(1, 1UL))));
|
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)));
|
||||||
|
}
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
Range max(Range)(Range range)
|
Range max(Range)(Range range)
|
||||||
if (isForwardRange!Range && isOrderingComparable!(ElementType!Range))
|
if (isForwardRange!Range && isOrderingComparable!(ElementType!Range))
|
||||||
@ -211,7 +259,14 @@ if (isForwardRange!Range && isOrderingComparable!(ElementType!Range))
|
|||||||
return this.s - that.s;
|
return this.s - that.s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const s1 = S(1);
|
{
|
||||||
assert(min(s1, S(2)).s == 1);
|
const s1 = S(1);
|
||||||
assert(max(s1, S(2)).s == 2);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ if (isFloatingPoint!F)
|
|||||||
|
|
||||||
private union FloatBits(F)
|
private union FloatBits(F)
|
||||||
{
|
{
|
||||||
F floating;
|
Unqual!F floating;
|
||||||
static if (ieeePrecision!F == IEEEPrecision.single)
|
static if (ieeePrecision!F == IEEEPrecision.single)
|
||||||
{
|
{
|
||||||
uint integral;
|
uint integral;
|
||||||
@ -741,32 +741,14 @@ bool isPseudoprime(ulong x) @nogc nothrow pure @safe
|
|||||||
assert(982451653.isPseudoprime);
|
assert(982451653.isPseudoprime);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
deprecated("Use tanya.algorithm.comparison.min instead")
|
||||||
* Determines minimum of two numbers.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* x = First number.
|
|
||||||
* y = Second number.
|
|
||||||
*
|
|
||||||
* Returns: $(D_PARAM x) if $(D_PARAM x) is smaller than $(D_PSYMBOL y),
|
|
||||||
* $(D_PARAM y) otherwise.
|
|
||||||
*
|
|
||||||
* See_Also: $(D_PSYMBOL max).
|
|
||||||
*/
|
|
||||||
T min(T)(T x, T y)
|
T min(T)(T x, T y)
|
||||||
if (isIntegral!T)
|
if (isIntegral!T)
|
||||||
{
|
{
|
||||||
return x < y ? x : y;
|
return x < y ? x : y;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
deprecated("Use tanya.algorithm.comparison.min instead")
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
assert(min(5, 3) == 3);
|
|
||||||
assert(min(4, 4) == 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ditto
|
|
||||||
T min(T)(T x, T y)
|
T min(T)(T x, T y)
|
||||||
if (isFloatingPoint!T)
|
if (isFloatingPoint!T)
|
||||||
{
|
{
|
||||||
@ -781,62 +763,33 @@ if (isFloatingPoint!T)
|
|||||||
return x < y ? x : y;
|
return x < y ? x : y;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
deprecated("Use tanya.algorithm.comparison.min instead")
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
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)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ditto
|
|
||||||
ref T min(T)(ref T x, ref T y)
|
ref T min(T)(ref T x, ref T y)
|
||||||
if (is(Unqual!T == Integer))
|
if (is(Unqual!T == Integer))
|
||||||
{
|
{
|
||||||
return x < y ? x : y;
|
return x < y ? x : y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
deprecated("Use tanya.algorithm.comparison.min instead")
|
||||||
T min(T)(T x, T y)
|
T min(T)(T x, T y)
|
||||||
if (is(T == Integer))
|
if (is(T == Integer))
|
||||||
{
|
{
|
||||||
return x < y ? move(x) : move(y);
|
return x < y ? move(x) : move(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
@nogc nothrow pure @safe unittest
|
@nogc nothrow pure @safe unittest
|
||||||
{
|
{
|
||||||
assert(min(Integer(5), Integer(3)) == 3);
|
assert(min(Integer(5), Integer(3)) == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
deprecated("Use tanya.algorithm.comparison.max instead")
|
||||||
* Determines maximum of two numbers.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* x = First number.
|
|
||||||
* y = Second number.
|
|
||||||
*
|
|
||||||
* Returns: $(D_PARAM x) if $(D_PARAM x) is larger than $(D_PSYMBOL y),
|
|
||||||
* $(D_PARAM y) otherwise.
|
|
||||||
*
|
|
||||||
* See_Also: $(D_PSYMBOL min).
|
|
||||||
*/
|
|
||||||
T max(T)(T x, T y)
|
T max(T)(T x, T y)
|
||||||
if (isIntegral!T)
|
if (isIntegral!T)
|
||||||
{
|
{
|
||||||
return x > y ? x : y;
|
return x > y ? x : y;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
deprecated("Use tanya.algorithm.comparison.max instead")
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
assert(max(5, 3) == 5);
|
|
||||||
assert(max(4, 4) == 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ditto
|
|
||||||
T max(T)(T x, T y)
|
T max(T)(T x, T y)
|
||||||
if (isFloatingPoint!T)
|
if (isFloatingPoint!T)
|
||||||
{
|
{
|
||||||
@ -851,24 +804,14 @@ if (isFloatingPoint!T)
|
|||||||
return x > y ? x : y;
|
return x > y ? x : y;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
deprecated("Use tanya.algorithm.comparison.max instead")
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
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)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ditto
|
|
||||||
ref T max(T)(ref T x, ref T y)
|
ref T max(T)(ref T x, ref T y)
|
||||||
if (is(Unqual!T == Integer))
|
if (is(Unqual!T == Integer))
|
||||||
{
|
{
|
||||||
return x > y ? x : y;
|
return x > y ? x : y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ditto
|
deprecated("Use tanya.algorithm.comparison.max instead")
|
||||||
T max(T)(T x, T y)
|
T max(T)(T x, T y)
|
||||||
if (is(T == Integer))
|
if (is(T == Integer))
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user