Use auto ref for templated overloaded functions

This commit is contained in:
Eugen Wissner 2016-12-13 10:59:05 +01:00
parent f437dafa6b
commit 061cd6264b
1 changed files with 60 additions and 47 deletions

View File

@ -23,7 +23,7 @@ import tanya.memory;
*/ */
struct Integer struct Integer
{ {
private RefCounted!(ubyte[]) rep; private ubyte[] rep;
private bool sign; private bool sign;
private shared Allocator allocator; private shared Allocator allocator;
@ -42,7 +42,7 @@ struct Integer
* *
* Precondition: $(D_INLINECODE allocator !is null) * Precondition: $(D_INLINECODE allocator !is null)
*/ */
this(T)(in T value, shared Allocator allocator = defaultAllocator) this(T)(in auto ref T value, shared Allocator allocator = defaultAllocator)
nothrow @safe @nogc nothrow @safe @nogc
if (isIntegral!T || is(T == Integer)) if (isIntegral!T || is(T == Integer))
{ {
@ -53,10 +53,10 @@ struct Integer
} }
else else
{ {
rep = RefCounted!(ubyte[])(() @trusted { rep = () @trusted {
return cast(ubyte[]) allocator.allocate(value.length); return cast(ubyte[]) allocator.allocate(value.length);
}(), allocator); }();
value.rep.get.copy(rep.get); value.rep.copy(rep);
sign = value.sign; sign = value.sign;
} }
} }
@ -85,6 +85,24 @@ struct Integer
assert(h2.sign); assert(h2.sign);
} }
~this() nothrow @safe @nogc
in
{
assert(allocator !is null || !rep.length);
}
body
{
if (allocator !is null)
{
allocator.dispose(rep);
}
}
private @nogc unittest
{
Integer h; // allocator isn't set, but the destructor should work
}
/* /*
* Figures out the minimum amount of space this value will take * Figures out the minimum amount of space this value will take
* up in bytes and resizes the internal storage. Sets the sign. * up in bytes and resizes the internal storage. Sets the sign.
@ -121,13 +139,13 @@ struct Integer
} }
if (rep.count) if (rep.count)
{ {
allocator.resizeArray(rep.get, size); allocator.resizeArray(rep, size);
} }
else else
{ {
rep = RefCounted!(ubyte[])(() @trusted { rep = () @trusted {
return cast(ubyte[]) allocator.allocate(size); return cast(ubyte[]) allocator.allocate(size);
}(), allocator); }();
} }
/* Work backward through the int, masking off each byte (up to the /* Work backward through the int, masking off each byte (up to the
first 0 byte) and copy it into the internal representation in first 0 byte) and copy it into the internal representation in
@ -149,33 +167,20 @@ struct Integer
* *
* Returns: $(D_KEYWORD this). * Returns: $(D_KEYWORD this).
*/ */
ref Integer opAssign(T)(in T value) nothrow @safe @nogc ref Integer opAssign(T)(in auto ref T value) nothrow @safe @nogc
if (isIntegral!T || is(T == Integer)) if (isIntegral!T || is(T == Integer))
{ {
if (allocator is null) initialize();
{
allocator = defaultAllocator;
}
static if (isIntegral!T) static if (isIntegral!T)
{ {
assignInt(value); assignInt(value);
} }
else else
{ {
if (rep.count) allocator.resizeArray(rep, value.length);
{ value.rep.copy(rep);
allocator.resizeArray(rep, value.length);
}
else
{
rep = RefCounted!(ubyte[])(() @trusted {
return cast(ubyte[]) allocator.allocate(value.length);
}(), allocator);
}
value.rep.get.copy(rep.get);
sign = value.sign; sign = value.sign;
} }
return this; return this;
} }
@ -202,7 +207,7 @@ struct Integer
*/ */
@property size_t length() const pure nothrow @safe @nogc @property size_t length() const pure nothrow @safe @nogc
{ {
return rep.get.length; return rep.length;
} }
/** /**
@ -216,6 +221,12 @@ struct Integer
return rep == h.rep; return rep == h.rep;
} }
/// Ditto.
bool opEquals(in ref Integer h) const nothrow @safe @nogc
{
return rep == h.rep;
}
/// ///
unittest unittest
{ {
@ -232,7 +243,7 @@ struct Integer
* Returns: A positive number if $(D_INLINECODE this > h), a negative * Returns: A positive number if $(D_INLINECODE this > h), a negative
* number if $(D_INLINECODE this > h), `0` otherwise. * number if $(D_INLINECODE this > h), `0` otherwise.
*/ */
int opCmp(in Integer h) const nothrow @safe @nogc int opCmp(in ref Integer h) const nothrow @safe @nogc
{ {
if (length > h.length) if (length > h.length)
{ {
@ -262,6 +273,12 @@ struct Integer
return 0; return 0;
} }
/// Ditto.
int opCmp(in Integer h) const nothrow @safe @nogc
{
return opCmp(h);
}
/// ///
unittest unittest
{ {
@ -276,7 +293,7 @@ struct Integer
assert(h1 > h2); assert(h1 > h2);
} }
private void add(in ref RefCounted!(ubyte[]) h) nothrow @safe @nogc private void add(in ref ubyte[] h) nothrow @safe @nogc
{ {
uint sum; uint sum;
uint carry = 0; uint carry = 0;
@ -319,7 +336,7 @@ struct Integer
} }
private void subtract(in ref RefCounted!(ubyte[]) h) nothrow @safe @nogc private void subtract(in ref ubyte[] h) nothrow @safe @nogc
{ {
auto i = rep.length; auto i = rep.length;
auto j = h.length; auto j = h.length;
@ -350,7 +367,7 @@ struct Integer
} }
// Go through the representation array and see how many of the // Go through the representation array and see how many of the
// left-most bytes are unused. Remove them and resize the array. // left-most bytes are unused. Remove them and resize the array.
immutable offset = rep.get.countUntil!((const ref a) => a != 0); immutable offset = rep.countUntil!((const ref a) => a != 0);
if (offset > 0) if (offset > 0)
{ {
ubyte[] tmp = allocator.makeArray!ubyte(rep.length - offset); ubyte[] tmp = allocator.makeArray!ubyte(rep.length - offset);
@ -372,7 +389,7 @@ struct Integer
* *
* Returns: $(D_KEYWORD this). * Returns: $(D_KEYWORD this).
*/ */
ref Integer opOpAssign(string op)(in Integer h) nothrow @safe @nogc ref Integer opOpAssign(string op)(in auto ref Integer h) nothrow @safe @nogc
if ((op == "+") || (op == "-")) if ((op == "+") || (op == "-"))
out out
{ {
@ -485,7 +502,7 @@ struct Integer
} }
/// Ditto. /// Ditto.
ref Integer opOpAssign(string op)(in Integer h) nothrow @safe @nogc ref Integer opOpAssign(string op)(in auto ref Integer h) nothrow @safe @nogc
if (op == "*") if (op == "*")
out out
{ {
@ -526,7 +543,7 @@ struct Integer
} }
/// Ditto. /// Ditto.
ref Integer opOpAssign(string op)(in Integer h) nothrow @safe @nogc ref Integer opOpAssign(string op)(in auto ref Integer h) nothrow @safe @nogc
if ((op == "/") || (op == "%")) if ((op == "/") || (op == "%"))
in in
{ {
@ -576,7 +593,8 @@ struct Integer
static if (op == "/") static if (op == "/")
{ {
rep = quotient; swap(rep, quotient);
allocator.dispose(quotient);
sign = sign == h.sign ? false : true; sign = sign == h.sign ? false : true;
} }
return this; return this;
@ -607,7 +625,7 @@ struct Integer
} }
/// Ditto. /// Ditto.
ref Integer opOpAssign(string op)(in Integer exp) nothrow @safe @nogc ref Integer opOpAssign(string op)(in auto ref Integer exp) nothrow @safe @nogc
if (op == "^^") if (op == "^^")
out out
{ {
@ -674,7 +692,7 @@ struct Integer
} }
else static if (op == "~") else static if (op == "~")
{ {
h.rep.get.each!((ref a) => a = ~a); h.rep.each!((ref a) => a = ~a);
} }
return h; return h;
} }
@ -712,7 +730,7 @@ struct Integer
private void decrement() nothrow @safe @nogc private void decrement() nothrow @safe @nogc
{ {
immutable size = rep.get.retro.countUntil!((const ref a) => a != 0); immutable size = rep.retro.countUntil!((const ref a) => a != 0);
if (rep[0] == 1) if (rep[0] == 1)
{ {
allocator.resizeArray(rep, rep.length - 1); allocator.resizeArray(rep, rep.length - 1);
@ -728,13 +746,12 @@ struct Integer
private void increment() nothrow @safe @nogc private void increment() nothrow @safe @nogc
{ {
auto size = rep auto size = rep
.get
.retro .retro
.countUntil!((const ref a) => a != typeof(rep[0]).max); .countUntil!((const ref a) => a != typeof(rep[0]).max);
if (size == -1) if (size == -1)
{ {
size = length; size = length;
allocator.resizeArray(rep.get, rep.length + 1); allocator.resizeArray(rep, rep.length + 1);
rep[0] = 1; rep[0] = 1;
} }
else else
@ -838,10 +855,6 @@ struct Integer
{ {
allocator = defaultAllocator; allocator = defaultAllocator;
} }
if (!rep.count)
{
rep = allocator.refCounted!(ubyte[])(0);
}
} }
/** /**
@ -901,7 +914,7 @@ struct Integer
* *
* Returns: An $(D_PSYMBOL Integer) shifted by $(D_PARAM n) bits. * Returns: An $(D_PSYMBOL Integer) shifted by $(D_PARAM n) bits.
*/ */
ref Integer opOpAssign(string op)(in size_t n) nothrow @safe @nogc ref Integer opOpAssign(string op)(in auto ref size_t n) nothrow @safe @nogc
if (op == ">>") if (op == ">>")
out out
{ {
@ -978,7 +991,7 @@ struct Integer
} }
/// Ditto. /// Ditto.
ref Integer opOpAssign(string op)(in size_t n) nothrow @safe @nogc ref Integer opOpAssign(string op)(in auto ref size_t n) nothrow @safe @nogc
if (op == "<<") if (op == "<<")
out out
{ {
@ -1027,7 +1040,7 @@ struct Integer
} }
/// Ditto. /// Ditto.
Integer opBinary(string op)(in size_t n) nothrow @safe @nogc Integer opBinary(string op)(in auto ref size_t n) nothrow @safe @nogc
if (op == "<<" || op == ">>" || op == "+" || op == "-" || op == "/" if (op == "<<" || op == ">>" || op == "+" || op == "-" || op == "/"
|| op == "*" || op == "^^" || op == "%") || op == "*" || op == "^^" || op == "%")
{ {
@ -1049,7 +1062,7 @@ struct Integer
} }
/// Ditto. /// Ditto.
Integer opBinary(string op)(in Integer h) nothrow @safe @nogc Integer opBinary(string op)(in auto ref Integer h) nothrow @safe @nogc
if (op == "+" || op == "-" || op == "/" if (op == "+" || op == "-" || op == "/"
|| op == "*" || op == "^^" || op == "%") || op == "*" || op == "^^" || op == "%")
{ {