summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-11-02 06:00:11 +0100
committerEugen Wissner <belka@caraus.de>2017-11-02 06:00:11 +0100
commit13407fcf8a45d05a93c285f59fceb8084145e1d5 (patch)
tree9be41ca6e2d87f1e7d83a8f206f147fe45da558d
parente06cc5a071fd5640beec600f7efa2446c6ed1826 (diff)
downloadtanya-13407fcf8a45d05a93c285f59fceb8084145e1d5.tar.gz
math: Add min/max
-rw-r--r--source/tanya/algorithm/mutation.d4
-rw-r--r--source/tanya/math/package.d185
2 files changed, 173 insertions, 16 deletions
diff --git a/source/tanya/algorithm/mutation.d b/source/tanya/algorithm/mutation.d
index 5d09379..55ca003 100644
--- a/source/tanya/algorithm/mutation.d
+++ b/source/tanya/algorithm/mutation.d
@@ -209,10 +209,10 @@ void move(T)(ref T source, ref T target)
}
/// ditto
-T move(T)(ref T source)
+T move(T)(ref T source) @trusted
{
T target = void;
- (() @trusted => moveEmplace(source, target))();
+ moveEmplace(source, target);
return target;
}
diff --git a/source/tanya/math/package.d b/source/tanya/math/package.d
index bb117a2..a78504d 100644
--- a/source/tanya/math/package.d
+++ b/source/tanya/math/package.d
@@ -21,9 +21,11 @@
*/
module tanya.math;
+import tanya.algorithm.mutation;
import tanya.math.mp;
import tanya.math.nbtheory;
import tanya.meta.trait;
+import tanya.meta.transform;
/// Floating-point number precisions according to IEEE-754.
enum IEEEPrecision : ubyte
@@ -79,7 +81,7 @@ if (isFloatingPoint!F)
}
///
-pure nothrow @safe @nogc unittest
+@nogc nothrow pure @safe unittest
{
static assert(ieeePrecision!float == IEEEPrecision.single);
static assert(ieeePrecision!double == IEEEPrecision.double_);
@@ -231,7 +233,7 @@ if (isFloatingPoint!F)
}
///
-pure nothrow @safe @nogc unittest
+@nogc nothrow pure @safe unittest
{
assert(classify(0.0) == FloatingPointClass.zero);
assert(classify(double.nan) == FloatingPointClass.nan);
@@ -253,7 +255,7 @@ pure nothrow @safe @nogc unittest
assert(classify(-real.infinity) == FloatingPointClass.infinite);
}
-private pure nothrow @nogc @safe unittest
+@nogc nothrow pure @safe unittest
{
static if (ieeePrecision!float == IEEEPrecision.doubleExtended)
{
@@ -300,7 +302,7 @@ if (isFloatingPoint!F)
}
///
-pure nothrow @safe @nogc unittest
+@nogc nothrow pure @safe unittest
{
assert(!isFinite(float.infinity));
assert(!isFinite(-double.infinity));
@@ -345,7 +347,7 @@ if (isFloatingPoint!F)
}
///
-pure nothrow @safe @nogc unittest
+@nogc nothrow pure @safe unittest
{
assert(isNaN(float.init));
assert(isNaN(double.init));
@@ -382,7 +384,7 @@ if (isFloatingPoint!F)
}
///
-pure nothrow @safe @nogc unittest
+@nogc nothrow pure @safe unittest
{
assert(isInfinity(float.infinity));
assert(isInfinity(-float.infinity));
@@ -436,7 +438,7 @@ if (isFloatingPoint!F)
}
///
-pure nothrow @safe @nogc unittest
+@nogc nothrow pure @safe unittest
{
assert(!isSubnormal(0.0f));
assert(!isSubnormal(float.nan));
@@ -496,7 +498,7 @@ if (isFloatingPoint!F)
}
///
-pure nothrow @safe @nogc unittest
+@nogc nothrow pure @safe unittest
{
assert(!isNormal(0.0f));
assert(!isNormal(float.nan));
@@ -547,7 +549,7 @@ if (isFloatingPoint!F)
}
///
-pure nothrow @safe @nogc unittest
+@nogc nothrow pure @safe unittest
{
assert(signBit(-1.0f));
assert(!signBit(1.0f));
@@ -659,7 +661,7 @@ body
}
///
-pure nothrow @safe @nogc unittest
+@nogc nothrow pure @safe unittest
{
assert(pow(3, 5, 7) == 5);
assert(pow(2, 2, 1) == 0);
@@ -673,7 +675,7 @@ pure nothrow @safe @nogc unittest
}
///
-nothrow @safe @nogc unittest
+@nogc nothrow pure @safe unittest
{
assert(pow(Integer(3), Integer(5), Integer(7)) == 5);
assert(pow(Integer(2), Integer(2), Integer(1)) == 0);
@@ -695,13 +697,13 @@ nothrow @safe @nogc unittest
* Returns: $(D_KEYWORD true) if $(D_PARAM x) is a prime number,
* $(D_KEYWORD false) otherwise.
*/
-bool isPseudoprime(ulong x) nothrow pure @safe @nogc
+bool isPseudoprime(ulong x) @nogc nothrow pure @safe
{
return pow(2, x - 1, x) == 1;
}
///
-pure nothrow @safe @nogc unittest
+@nogc nothrow pure @safe unittest
{
assert(74623.isPseudoprime);
assert(104729.isPseudoprime);
@@ -709,7 +711,7 @@ pure nothrow @safe @nogc unittest
assert(!15485868.isPseudoprime);
}
-private pure nothrow @safe @nogc unittest
+@nogc nothrow pure @safe unittest
{
assert(74653.isPseudoprime);
assert(74687.isPseudoprime);
@@ -738,3 +740,158 @@ private pure nothrow @safe @nogc unittest
assert(899809363.isPseudoprime);
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).
+ */
+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
+T min(T)(T x, T y)
+if (isFloatingPoint!T && isFloatingPoint!T)
+{
+ if (isNaN(x))
+ {
+ return y;
+ }
+ if (isNaN(y))
+ {
+ return x;
+ }
+ 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
+ref T min(T)(ref T x, ref T y)
+if (is(Unqual!T == Integer))
+{
+ return x < y ? x : y;
+}
+
+/// ditto
+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).
+ */
+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
+T max(T)(T x, T y)
+if (isFloatingPoint!T && isFloatingPoint!T)
+{
+ if (isNaN(x))
+ {
+ return y;
+ }
+ if (isNaN(y))
+ {
+ return x;
+ }
+ 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
+ref T max(T)(ref T x, ref T y)
+if (is(Unqual!T == Integer))
+{
+ return x > y ? x : y;
+}
+
+/// ditto
+T max(T)(T x, T y)
+if (is(T == Integer))
+{
+ return x > y ? move(x) : move(y);
+}
+
+///
+@nogc nothrow pure @safe unittest
+{
+ assert(max(Integer(5), Integer(3)) == 5);
+}
+
+// min/max accept const and mutable references.
+@nogc nothrow pure @safe unittest
+{
+ {
+ Integer i1 = 5, i2 = 3;
+ assert(min(i1, i2) == 3);
+ assert(max(i1, i2) == 5);
+ }
+ {
+ const Integer i1 = 5, i2 = 3;
+ assert(min(i1, i2) == 3);
+ assert(max(i1, i2) == 5);
+ }
+}