summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-10-02 14:55:30 +0200
committerEugen Wissner <belka@caraus.de>2017-10-02 14:55:30 +0200
commite4cd57a61543833c00b3e6a7254962b385db5ef2 (patch)
treeb09424a4182169072987ade67fa4661794d8b451
parent74b085b88d4e44a6d5b175c6ef954acee8e1619d (diff)
downloadtanya-e4cd57a61543833c00b3e6a7254962b385db5ef2.tar.gz
math.nbtheory: Implement natural logarithm
-rw-r--r--arch/build.ninja3
-rw-r--r--arch/x64/linux/math/log.S48
-rw-r--r--source/tanya/container/string.d49
-rw-r--r--source/tanya/math/nbtheory.d76
4 files changed, 143 insertions, 33 deletions
diff --git a/arch/build.ninja b/arch/build.ninja
index fce2838..824efa4 100644
--- a/arch/build.ninja
+++ b/arch/build.ninja
@@ -5,9 +5,10 @@ rule archive
command = ar rcs $out $in
build abs.o: gas x64/linux/math/abs.S
+build log.o: gas x64/linux/math/log.S
build cmp.o: gas x64/linux/memory/cmp.S
build fill.o: gas x64/linux/memory/fill.S
build copy.o: gas x64/linux/memory/copy.S
build syscall.o: gas x64/linux/syscall.S
-build tanya.a: archive syscall.o copy.o fill.o cmp.o abs.o
+build tanya.a: archive syscall.o copy.o fill.o cmp.o log.o abs.o
diff --git a/arch/x64/linux/math/log.S b/arch/x64/linux/math/log.S
new file mode 100644
index 0000000..7f23703
--- /dev/null
+++ b/arch/x64/linux/math/log.S
@@ -0,0 +1,48 @@
+ .text
+
+
+// logl.
+ .globl _D5tanya4math8nbtheory2lnFNaNbNiNfeZe
+ .type _D5tanya4math8nbtheory2lnFNaNbNiNfeZe, @function
+
+_D5tanya4math8nbtheory2lnFNaNbNiNfeZe:
+ fldln2 // Put lb(e) onto the FPU stack
+ fldt 8(%rsp) // Put the argument onto the FPU stack
+ fyl2x // %st1 * lb(%st0)
+ ret
+
+
+// log.
+ .globl _D5tanya4math8nbtheory2lnFNaNbNiNfdZd
+ .type _D5tanya4math8nbtheory2lnFNaNbNiNfdZd, @function
+
+_D5tanya4math8nbtheory2lnFNaNbNiNfdZd:
+ movsd %xmm0, -8(%rsp) // Put the argument onto the stack
+
+ fldln2 // Put lb(e) onto the FPU stack
+ fldl -8(%rsp) // Put a double onto the FPU stack
+ fyl2x // %st1 * lb(%st0)
+
+ // The result is on the FPU stack, but returned in %xmm0
+ fstpl -8(%rsp)
+ movsd -8(%rsp), %xmm0
+
+ ret
+
+
+// logf.
+ .globl _D5tanya4math8nbtheory2lnFNaNbNiNffZf
+ .type _D5tanya4math8nbtheory2lnFNaNbNiNffZf, @function
+
+_D5tanya4math8nbtheory2lnFNaNbNiNffZf:
+ movss %xmm0, -4(%rsp) // Put the argument onto the stack
+
+ fldln2 // Put lb(e) onto the FPU stack
+ flds -4(%rsp) // Put a float onto the FPU stack
+ fyl2x // %st1 * lb(%st0)
+
+ // The result is on the FPU stack, but returned in %xmm0
+ fstps -4(%rsp)
+ movss -4(%rsp), %xmm0
+
+ ret
diff --git a/source/tanya/container/string.d b/source/tanya/container/string.d
index a89fe0c..b0bbeec 100644
--- a/source/tanya/container/string.d
+++ b/source/tanya/container/string.d
@@ -35,6 +35,7 @@ import tanya.memory;
import tanya.meta.trait;
import tanya.meta.transform;
import tanya.range.array;
+import tanya.range.primitive;
/**
* Thrown on encoding errors.
@@ -352,9 +353,9 @@ struct String
* Precondition: $(D_INLINECODE allocator is null).
*/
this(S)(const S str, shared Allocator allocator = defaultAllocator)
- if (!std.range.isInfinite!S
- && std.range.isInputRange!S
- && isSomeChar!(std.range.ElementEncodingType!S))
+ if (!isInfinite!S
+ && isInputRange!S
+ && isSomeChar!(ElementType!S))
{
this(allocator);
insertBack(str);
@@ -667,12 +668,12 @@ struct String
* Throws: $(D_PSYMBOL UTFException).
*/
size_t insertBack(R)(R str) @trusted
- if (!std.range.isInfinite!R
- && std.range.isInputRange!R
- && is(Unqual!(std.range.ElementEncodingType!R) == char))
+ if (!isInfinite!R
+ && isInputRange!R
+ && is(Unqual!(ElementType!R) == char))
{
size_t size;
- static if (std.range.hasLength!R || isNarrowString!R)
+ static if (hasLength!R || isNarrowString!R)
{
size = str.length + length;
reserve(size);
@@ -731,11 +732,11 @@ struct String
/// ditto
size_t insertBack(R)(R str) @trusted
- if (!std.range.isInfinite!R
- && std.range.isInputRange!R
- && is(Unqual!(std.range.ElementEncodingType!R) == wchar))
+ if (!isInfinite!R
+ && isInputRange!R
+ && is(Unqual!(ElementType!R) == wchar))
{
- static if (std.range.hasLength!R || isNarrowString!R)
+ static if (hasLength!R || isNarrowString!R)
{
reserve(length + str.length * wchar.sizeof);
}
@@ -797,11 +798,11 @@ struct String
/// ditto
size_t insertBack(R)(R str) @trusted
- if (!std.range.isInfinite!R
- && std.range.isInputRange!R
- && is(Unqual!(std.range.ElementEncodingType!R) == dchar))
+ if (!isInfinite!R
+ && isInputRange!R
+ && is(Unqual!(ElementType!R) == dchar))
{
- static if (std.range.hasLength!R || isSomeString!R)
+ static if (hasLength!R || isSomeString!R)
{
reserve(length + str.length * 4);
}
@@ -1268,9 +1269,9 @@ struct String
* Throws: $(D_PSYMBOL UTFException).
*/
ref String opAssign(S)(S that) nothrow
- if (!std.range.isInfinite!S
- && std.range.isInputRange!S
- && isSomeChar!(std.range.ElementEncodingType!S))
+ if (!isInfinite!S
+ && isInputRange!S
+ && isSomeChar!(ElementType!S))
{
this.length_ = 0;
insertBack(that);
@@ -1531,9 +1532,9 @@ struct String
* Precondition: $(D_PARAM r) refers to a region of $(D_KEYWORD this).
*/
size_t insertAfter(T, R)(R r, T el) @trusted
- if ((isSomeChar!T || (!std.range.isInfinite!T
- && std.range.isInputRange!T
- && isSomeChar!(std.range.ElementEncodingType!T)))
+ if ((isSomeChar!T || (!isInfinite!T
+ && isInputRange!T
+ && isSomeChar!(ElementType!T)))
&& (is(R == ByCodeUnit!char) || is(R == ByCodePoint!char)))
in
{
@@ -1564,9 +1565,9 @@ struct String
///
size_t insertBefore(T, R)(R r, T el) @trusted
- if ((isSomeChar!T || (!std.range.isInfinite!T
- && std.range.isInputRange!T
- && isSomeChar!(std.range.ElementEncodingType!T)))
+ if ((isSomeChar!T || (!isInfinite!T
+ && isInputRange!T
+ && isSomeChar!(ElementType!T)))
&& (is(R == ByCodeUnit!char) || is(R == ByCodePoint!char)))
in
{
diff --git a/source/tanya/math/nbtheory.d b/source/tanya/math/nbtheory.d
index 6be04b9..4c94550 100644
--- a/source/tanya/math/nbtheory.d
+++ b/source/tanya/math/nbtheory.d
@@ -17,6 +17,15 @@ module tanya.math.nbtheory;
import tanya.math.mp;
import tanya.meta.trait;
+version (TanyaNative)
+{
+}
+else
+{
+ import core.math : fabs;
+ import std.math : log;
+}
+
/**
* Calculates the absolute value of a number.
*
@@ -57,21 +66,19 @@ version (D_Ddoc)
I abs(I)(I x)
if (isFloatingPoint!I);
}
-else version (TanyaPhobos)
+else version (TanyaNative)
+{
+ extern I abs(I)(I number) pure nothrow @safe @nogc
+ if (isFloatingPoint!I);
+}
+else
{
- 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
@@ -103,3 +110,56 @@ I abs(I : Integer)(I x)
x.sign = Sign.positive;
return x;
}
+
+version (D_Ddoc)
+{
+ /**
+ * Calculates natural logarithm of $(D_PARAM x).
+ *
+ * Params:
+ * x = Argument.
+ *
+ * Returns: Natural logarithm of $(D_PARAM x).
+ */
+ float ln(float x) pure nothrow @safe @nogc;
+ /// ditto
+ double ln(double x) pure nothrow @safe @nogc;
+ /// ditto
+ real ln(real x) pure nothrow @safe @nogc;
+}
+else version (TanyaNative)
+{
+ extern float ln(float x) pure nothrow @safe @nogc;
+ extern double ln(double x) pure nothrow @safe @nogc;
+ extern real ln(real x) pure nothrow @safe @nogc;
+}
+else
+{
+ float ln(float x) pure nothrow @safe @nogc
+ {
+ return log(x);
+ }
+ double ln(double x) pure nothrow @safe @nogc
+ {
+ return log(x);
+ }
+ alias ln = log;
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ import tanya.math;
+
+ assert(isNaN(ln(-7.389f)));
+ assert(isNaN(ln(-7.389)));
+ assert(isNaN(ln(-7.389L)));
+
+ assert(isInfinity(ln(0.0f)));
+ assert(isInfinity(ln(0.0)));
+ assert(isInfinity(ln(0.0L)));
+
+ assert(ln(1.0f) == 0.0f);
+ assert(ln(1.0) == 0.0);
+ assert(ln(1.0L) == 0.0L);
+}