summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/build.ninja3
-rw-r--r--arch/x64/linux/math/abs.S35
-rw-r--r--dub.json4
-rw-r--r--source/tanya/math/nbtheory.d165
-rw-r--r--source/tanya/math/package.d31
5 files changed, 206 insertions, 32 deletions
diff --git a/arch/build.ninja b/arch/build.ninja
index 42ee8f6..eff2eb9 100644
--- a/arch/build.ninja
+++ b/arch/build.ninja
@@ -4,6 +4,7 @@ rule gas
rule archive
command = ar rcs $out $in
+build abs.o: gas x64/linux/math/abs.S
build syscall.o: gas x64/linux/syscall.S
-build tanya.a: archive syscall.o
+build tanya.a: archive syscall.o abs.o
diff --git a/arch/x64/linux/math/abs.S b/arch/x64/linux/math/abs.S
new file mode 100644
index 0000000..edf8ac9
--- /dev/null
+++ b/arch/x64/linux/math/abs.S
@@ -0,0 +1,35 @@
+ .text
+
+
+// fabsf.
+ .globl _D5tanya4math8nbtheory10__T3absTfZ3absFNaNbNiNffZf
+ .type _D5tanya4math8nbtheory10__T3absTfZ3absFNaNbNiNffZf, @function
+
+_D5tanya4math8nbtheory10__T3absTfZ3absFNaNbNiNffZf:
+ mov $0x7fffffff, %eax
+ movq %rax, %xmm1
+ andpd %xmm1, %xmm0
+ ret
+
+
+// fabs.
+ .globl _D5tanya4math8nbtheory10__T3absTdZ3absFNaNbNiNfdZd
+ .type _D5tanya4math8nbtheory10__T3absTdZ3absFNaNbNiNfdZd, @function
+
+_D5tanya4math8nbtheory10__T3absTdZ3absFNaNbNiNfdZd:
+ mov $0x7fffffffffffffff, %rax
+ movq %rax, %xmm1
+ andpd %xmm1, %xmm0
+ ret
+
+
+// fabsl.
+ .globl _D5tanya4math8nbtheory10__T3absTeZ3absFNaNbNiNfeZe
+ .type _D5tanya4math8nbtheory10__T3absTeZ3absFNaNbNiNfeZe, @function
+
+// Load the parameter from the stack onto FP stack, execute 'fabs' instruction
+// The result is returned in ST0.
+_D5tanya4math8nbtheory10__T3absTeZ3absFNaNbNiNfeZe:
+ fldt 0x8(%rsp)
+ fabs
+ ret
diff --git a/dub.json b/dub.json
index 446d4ce..e6dfaaf 100644
--- a/dub.json
+++ b/dub.json
@@ -18,7 +18,9 @@
{
"name": "native",
"targetType": "library",
- "platforms": ["linux-x86_64"]
+ "platforms": ["linux-x86_64"],
+ "preBuildCommands": ["ninja -C arch"],
+ "lflags": ["arch/tanya.a"]
}
]
}
diff --git a/source/tanya/math/nbtheory.d b/source/tanya/math/nbtheory.d
new file mode 100644
index 0000000..09af9cf
--- /dev/null
+++ b/source/tanya/math/nbtheory.d
@@ -0,0 +1,165 @@
+/* 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/. */
+
+/**
+ * Number theory.
+ *
+ * Copyright: Eugene Wissner 2017.
+ * 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/math/nbtheory.d,
+ * tanya/math/nbtheory.d)
+ */
+module tanya.math.nbtheory;
+
+import tanya.math.mp;
+import tanya.meta.trait;
+
+/**
+ * Floating-point number precisions according to IEEE-754.
+ */
+enum IEEEPrecision : ubyte
+{
+ /// Single precision: 64-bit.
+ single = 4,
+
+ /// Single precision: 64-bit.
+ double_ = 8,
+
+ /// Extended precision: 80-bit.
+ extended = 10,
+}
+
+/**
+ * Tests the precision of floating-point type $(D_PARAM F).
+ *
+ * For $(D_KEYWORD float), $(D_PSYMBOL ieeePrecision) always evaluates to
+ * $(D_INLINECODE IEEEPrecision.single); for $(D_KEYWORD double) - to
+ * $(D_INLINECODE IEEEPrecision.double). It returns different values only
+ * for $(D_KEYWORD real), since $(D_KEYWORD real) is a platform-dependent type.
+ *
+ * If $(D_PARAM F) is a $(D_KEYWORD real) and the target platform isn't
+ * currently supported, static assertion error will be raised (you can use
+ * $(D_INLINECODE is(typeof(ieeePrecision!F))) for testing the platform support
+ * without a compilation error).
+ *
+ * Params:
+ * F = Type to be tested.
+ *
+ * Returns: Precision according to IEEE-754.
+ *
+ * See_Also: $(D_PSYMBOL IEEEPrecision).
+ */
+template ieeePrecision(F)
+if (isFloatingPoint!F)
+{
+ static if (F.sizeof == float.sizeof)
+ {
+ enum IEEEPrecision ieeePrecision = IEEEPrecision.single;
+ }
+ else static if (F.sizeof == double.sizeof)
+ {
+ enum IEEEPrecision ieeePrecision = IEEEPrecision.double_;
+ }
+ else version (X86)
+ {
+ enum IEEEPrecision ieeePrecision = IEEEPrecision.extended;
+ }
+ else version (X86_64)
+ {
+ enum IEEEPrecision ieeePrecision = IEEEPrecision.extended;
+ }
+ else
+ {
+ static assert(false, "Unsupported IEEE 754 precision");
+ }
+}
+
+/**
+ * Calculates the absolute value of a number.
+ *
+ * Params:
+ * I = Value type.
+ * x = Value.
+ *
+ * Returns: Absolute value of $(D_PARAM x).
+ */
+I abs(I)(I x)
+if (isIntegral!I)
+{
+ static if (isSigned!I)
+ {
+ return x >= 0 ? x : -x;
+ }
+ else
+ {
+ return x;
+ }
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ int i = -1;
+ assert(i.abs == 1);
+ static assert(is(typeof(i.abs) == int));
+
+ uint u = 1;
+ assert(u.abs == 1);
+ static assert(is(typeof(u.abs) == uint));
+}
+
+version (D_Ddoc)
+{
+ /// ditto
+ I abs(I)(I x)
+ if (isFloatingPoint!I);
+}
+else version (TanyaPhobos)
+{
+ import core.math;
+
+ I abs(I)(I x)
+ if (isFloatingPoint!I)
+ {
+ return fabs(cast(real) x);
+ }
+}
+else
+{
+ extern I abs(I)(I number) pure nothrow @safe @nogc
+ if (isFloatingPoint!I);
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ float f = -1.64;
+ assert(f.abs == 1.64F);
+ static assert(is(typeof(f.abs) == float));
+
+ double d = -1.64;
+ assert(d.abs == 1.64);
+ static assert(is(typeof(d.abs) == double));
+
+ real r = -1.64;
+ assert(r.abs == 1.64L);
+ static assert(is(typeof(r.abs) == real));
+}
+
+/// ditto
+I abs(I : Integer)(const auto ref I x)
+{
+ auto result = Integer(x, x.allocator);
+ result.sign = Sign.positive;
+ return result;
+}
+
+/// ditto
+I abs(I : Integer)(I x)
+{
+ x.sign = Sign.positive;
+ return x;
+}
diff --git a/source/tanya/math/package.d b/source/tanya/math/package.d
index 0f3e8ea..86f1158 100644
--- a/source/tanya/math/package.d
+++ b/source/tanya/math/package.d
@@ -15,6 +15,7 @@
module tanya.math;
public import tanya.math.mp;
+public import tanya.math.nbtheory;
public import tanya.math.random;
import tanya.meta.trait;
@@ -197,33 +198,3 @@ private pure nothrow @safe @nogc unittest
assert(899809363.isPseudoprime);
assert(982451653.isPseudoprime);
}
-
-/**
- * Calculates the absolute value of a number.
- *
- * Params:
- * I = Value type.
- * x = Value.
- *
- * Returns: Absolute value of $(D_PARAM x).
- */
-I abs(I : Integer)(const auto ref I x)
-{
- auto result = Integer(x, x.allocator);
- result.sign = Sign.positive;
- return result;
-}
-
-/// Ditto.
-I abs(I : Integer)(I x)
-{
- x.sign = Sign.positive;
- return x;
-}
-
-/// Ditto.
-I abs(I)(const I x)
-if (isIntegral!I)
-{
- return x >= 0 ? x : -x;
-}