summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Wissner <belka@caraus.de>2018-04-27 11:32:22 +0200
committerEugene Wissner <belka@caraus.de>2018-04-27 11:32:22 +0200
commit6e2852000b4e34c3381a044007e08d05fd82d0ee (patch)
tree326bec6a09ceef94d298794c3f27fab9905da026
parentc0f9e5be106fdea277b9bb47caea8f3fcd487def (diff)
downloadtanya-6e2852000b4e34c3381a044007e08d05fd82d0ee.tar.gz
Deprecate math.min/max in favour of tanya.algorithm
-rw-r--r--source/tanya/algorithm/comparison.d97
-rw-r--r--source/tanya/math/package.d75
2 files changed, 85 insertions, 87 deletions
diff --git a/source/tanya/algorithm/comparison.d b/source/tanya/algorithm/comparison.d
index 43e9ffb..f8e1c60 100644
--- a/source/tanya/algorithm/comparison.d
+++ b/source/tanya/algorithm/comparison.d
@@ -14,6 +14,8 @@
*/
module tanya.algorithm.comparison;
+import tanya.algorithm.mutation;
+import tanya.math : isNaN;
import tanya.meta.metafunction;
import tanya.meta.trait;
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)
{
- auto actual = ((ref inout arg) @trusted => &arg)(args[0]);
+ 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 inout arg) @trusted => &arg)(args[i + 1]);
+ 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.
*
- * The function should take at least one argument.
- *
* 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.
@@ -54,29 +81,39 @@ private ref inout(Args[0]) minMax(alias cmp, Args...)(ref inout Args args)
*
* Returns: The smallest element.
*/
-inout(Unqual!(Args[0])) min(Args...)(inout Args args)
-if (Args.length > 0
+CommonType!Args min(Args...)(Args args)
+if (Args.length >= 2
&& isOrderingComparable!(Args[0])
&& allSameType!(Map!(Unqual, Args)))
{
- return minMax!((a, b) => a < b)(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 > 0
+if (Args.length >= 2
&& isOrderingComparable!(Args[0])
&& 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
{
- assert(min(1) == 1);
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
Range min(Range)(Range 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.
*
- * The function should take at least one argument.
- *
* 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.
@@ -136,29 +174,39 @@ if (isForwardRange!Range && isOrderingComparable!(ElementType!Range))
*
* Returns: The largest element.
*/
-inout(Unqual!(Args[0])) max(Args...)(inout Args args)
-if (Args.length > 0
+CommonType!Args max(Args...)(Args args)
+if (Args.length >= 2
&& isOrderingComparable!(Args[0])
&& allSameType!(Map!(Unqual, Args)))
{
- return minMax!((a, b) => a > b)(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 > 0
+if (Args.length >= 2
&& isOrderingComparable!(Args[0])
&& 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
{
- assert(max(1) == 1);
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
Range max(Range)(Range range)
if (isForwardRange!Range && isOrderingComparable!(ElementType!Range))
@@ -211,7 +259,14 @@ if (isForwardRange!Range && isOrderingComparable!(ElementType!Range))
return this.s - that.s;
}
}
- const s1 = S(1);
- assert(min(s1, S(2)).s == 1);
- assert(max(s1, S(2)).s == 2);
+ {
+ 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);
+ }
}
diff --git a/source/tanya/math/package.d b/source/tanya/math/package.d
index dc0ad3c..73b254c 100644
--- a/source/tanya/math/package.d
+++ b/source/tanya/math/package.d
@@ -89,7 +89,7 @@ if (isFloatingPoint!F)
private union FloatBits(F)
{
- F floating;
+ Unqual!F floating;
static if (ieeePrecision!F == IEEEPrecision.single)
{
uint integral;
@@ -741,32 +741,14 @@ bool isPseudoprime(ulong x) @nogc nothrow pure @safe
assert(982451653.isPseudoprime);
}
-/**
- * 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).
- */
+deprecated("Use tanya.algorithm.comparison.min instead")
T min(T)(T x, T y)
if (isIntegral!T)
{
return x < y ? x : y;
}
-///
-@nogc nothrow pure @safe unittest
-{
- assert(min(5, 3) == 3);
- assert(min(4, 4) == 4);
-}
-
-/// ditto
+deprecated("Use tanya.algorithm.comparison.min instead")
T min(T)(T x, T y)
if (isFloatingPoint!T)
{
@@ -781,62 +763,33 @@ if (isFloatingPoint!T)
return x < y ? x : y;
}
-///
-@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
+deprecated("Use tanya.algorithm.comparison.min instead")
ref T min(T)(ref T x, ref T y)
if (is(Unqual!T == Integer))
{
return x < y ? x : y;
}
-/// ditto
+deprecated("Use tanya.algorithm.comparison.min instead")
T min(T)(T x, T y)
if (is(T == Integer))
{
return x < y ? move(x) : move(y);
}
-///
@nogc nothrow pure @safe unittest
{
assert(min(Integer(5), Integer(3)) == 3);
}
-/**
- * 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).
- */
+deprecated("Use tanya.algorithm.comparison.max instead")
T max(T)(T x, T y)
if (isIntegral!T)
{
return x > y ? x : y;
}
-///
-@nogc nothrow pure @safe unittest
-{
- assert(max(5, 3) == 5);
- assert(max(4, 4) == 4);
-}
-
-/// ditto
+deprecated("Use tanya.algorithm.comparison.max instead")
T max(T)(T x, T y)
if (isFloatingPoint!T)
{
@@ -851,24 +804,14 @@ if (isFloatingPoint!T)
return x > y ? x : y;
}
-///
-@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
+deprecated("Use tanya.algorithm.comparison.max instead")
ref T max(T)(ref T x, ref T y)
if (is(Unqual!T == Integer))
{
return x > y ? x : y;
}
-/// ditto
+deprecated("Use tanya.algorithm.comparison.max instead")
T max(T)(T x, T y)
if (is(T == Integer))
{