math.nbtheory: Implement natural logarithm

This commit is contained in:
Eugen Wissner 2017-10-02 14:55:30 +02:00
parent 74b085b88d
commit e4cd57a615
4 changed files with 143 additions and 33 deletions

View File

@ -5,9 +5,10 @@ rule archive
command = ar rcs $out $in command = ar rcs $out $in
build abs.o: gas x64/linux/math/abs.S 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 cmp.o: gas x64/linux/memory/cmp.S
build fill.o: gas x64/linux/memory/fill.S build fill.o: gas x64/linux/memory/fill.S
build copy.o: gas x64/linux/memory/copy.S build copy.o: gas x64/linux/memory/copy.S
build syscall.o: gas x64/linux/syscall.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

48
arch/x64/linux/math/log.S Normal file
View File

@ -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

View File

@ -35,6 +35,7 @@ import tanya.memory;
import tanya.meta.trait; import tanya.meta.trait;
import tanya.meta.transform; import tanya.meta.transform;
import tanya.range.array; import tanya.range.array;
import tanya.range.primitive;
/** /**
* Thrown on encoding errors. * Thrown on encoding errors.
@ -352,9 +353,9 @@ struct String
* Precondition: $(D_INLINECODE allocator is null). * Precondition: $(D_INLINECODE allocator is null).
*/ */
this(S)(const S str, shared Allocator allocator = defaultAllocator) this(S)(const S str, shared Allocator allocator = defaultAllocator)
if (!std.range.isInfinite!S if (!isInfinite!S
&& std.range.isInputRange!S && isInputRange!S
&& isSomeChar!(std.range.ElementEncodingType!S)) && isSomeChar!(ElementType!S))
{ {
this(allocator); this(allocator);
insertBack(str); insertBack(str);
@ -667,12 +668,12 @@ struct String
* Throws: $(D_PSYMBOL UTFException). * Throws: $(D_PSYMBOL UTFException).
*/ */
size_t insertBack(R)(R str) @trusted size_t insertBack(R)(R str) @trusted
if (!std.range.isInfinite!R if (!isInfinite!R
&& std.range.isInputRange!R && isInputRange!R
&& is(Unqual!(std.range.ElementEncodingType!R) == char)) && is(Unqual!(ElementType!R) == char))
{ {
size_t size; size_t size;
static if (std.range.hasLength!R || isNarrowString!R) static if (hasLength!R || isNarrowString!R)
{ {
size = str.length + length; size = str.length + length;
reserve(size); reserve(size);
@ -731,11 +732,11 @@ struct String
/// ditto /// ditto
size_t insertBack(R)(R str) @trusted size_t insertBack(R)(R str) @trusted
if (!std.range.isInfinite!R if (!isInfinite!R
&& std.range.isInputRange!R && isInputRange!R
&& is(Unqual!(std.range.ElementEncodingType!R) == wchar)) && 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); reserve(length + str.length * wchar.sizeof);
} }
@ -797,11 +798,11 @@ struct String
/// ditto /// ditto
size_t insertBack(R)(R str) @trusted size_t insertBack(R)(R str) @trusted
if (!std.range.isInfinite!R if (!isInfinite!R
&& std.range.isInputRange!R && isInputRange!R
&& is(Unqual!(std.range.ElementEncodingType!R) == dchar)) && is(Unqual!(ElementType!R) == dchar))
{ {
static if (std.range.hasLength!R || isSomeString!R) static if (hasLength!R || isSomeString!R)
{ {
reserve(length + str.length * 4); reserve(length + str.length * 4);
} }
@ -1268,9 +1269,9 @@ struct String
* Throws: $(D_PSYMBOL UTFException). * Throws: $(D_PSYMBOL UTFException).
*/ */
ref String opAssign(S)(S that) nothrow ref String opAssign(S)(S that) nothrow
if (!std.range.isInfinite!S if (!isInfinite!S
&& std.range.isInputRange!S && isInputRange!S
&& isSomeChar!(std.range.ElementEncodingType!S)) && isSomeChar!(ElementType!S))
{ {
this.length_ = 0; this.length_ = 0;
insertBack(that); insertBack(that);
@ -1531,9 +1532,9 @@ struct String
* Precondition: $(D_PARAM r) refers to a region of $(D_KEYWORD this). * Precondition: $(D_PARAM r) refers to a region of $(D_KEYWORD this).
*/ */
size_t insertAfter(T, R)(R r, T el) @trusted size_t insertAfter(T, R)(R r, T el) @trusted
if ((isSomeChar!T || (!std.range.isInfinite!T if ((isSomeChar!T || (!isInfinite!T
&& std.range.isInputRange!T && isInputRange!T
&& isSomeChar!(std.range.ElementEncodingType!T))) && isSomeChar!(ElementType!T)))
&& (is(R == ByCodeUnit!char) || is(R == ByCodePoint!char))) && (is(R == ByCodeUnit!char) || is(R == ByCodePoint!char)))
in in
{ {
@ -1564,9 +1565,9 @@ struct String
/// ///
size_t insertBefore(T, R)(R r, T el) @trusted size_t insertBefore(T, R)(R r, T el) @trusted
if ((isSomeChar!T || (!std.range.isInfinite!T if ((isSomeChar!T || (!isInfinite!T
&& std.range.isInputRange!T && isInputRange!T
&& isSomeChar!(std.range.ElementEncodingType!T))) && isSomeChar!(ElementType!T)))
&& (is(R == ByCodeUnit!char) || is(R == ByCodePoint!char))) && (is(R == ByCodeUnit!char) || is(R == ByCodePoint!char)))
in in
{ {

View File

@ -17,6 +17,15 @@ module tanya.math.nbtheory;
import tanya.math.mp; import tanya.math.mp;
import tanya.meta.trait; import tanya.meta.trait;
version (TanyaNative)
{
}
else
{
import core.math : fabs;
import std.math : log;
}
/** /**
* Calculates the absolute value of a number. * Calculates the absolute value of a number.
* *
@ -57,21 +66,19 @@ version (D_Ddoc)
I abs(I)(I x) I abs(I)(I x)
if (isFloatingPoint!I); 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) I abs(I)(I x)
if (isFloatingPoint!I) if (isFloatingPoint!I)
{ {
return fabs(cast(real) x); return fabs(cast(real) x);
} }
} }
else
{
extern I abs(I)(I number) pure nothrow @safe @nogc
if (isFloatingPoint!I);
}
/// ///
pure nothrow @safe @nogc unittest pure nothrow @safe @nogc unittest
@ -103,3 +110,56 @@ I abs(I : Integer)(I x)
x.sign = Sign.positive; x.sign = Sign.positive;
return x; 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);
}