summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2016-12-15 15:00:06 +0100
committerEugen Wissner <belka@caraus.de>2016-12-15 15:00:06 +0100
commitc1fb89af9953738175ca4f28fb1ce2aacc2958e3 (patch)
tree17d106194be893cfc3371566492810ac7fa8a6d9 /source
parent061cd6264b12b13298361f9f0559ad5ce41e483d (diff)
downloadtanya-c1fb89af9953738175ca4f28fb1ce2aacc2958e3.tar.gz
Implement insertion into the vector
Diffstat (limited to 'source')
-rw-r--r--source/tanya/container/vector.d1081
-rw-r--r--source/tanya/math/mp.d21
-rw-r--r--source/tanya/memory/allocator.d16
-rw-r--r--source/tanya/memory/mmappool.d15
4 files changed, 606 insertions, 527 deletions
diff --git a/source/tanya/container/vector.d b/source/tanya/container/vector.d
index daa867c..695fae9 100644
--- a/source/tanya/container/vector.d
+++ b/source/tanya/container/vector.d
@@ -11,6 +11,7 @@
module tanya.container.vector;
import std.algorithm.comparison;
+import std.range.primitives;
import std.traits;
import tanya.memory;
@@ -20,18 +21,18 @@ import tanya.memory;
* Params:
* T = Content type.
*/
-class Vector(T)
+template Vector(T)
{
/**
* Defines the container's primary range.
*/
- struct Range(V)
+ struct Range
{
- private V[1] data;
+ private Vector* data;
- private @property ref inout(V) outer() inout
+ private @property ref inout(Vector) outer() inout return
{
- return data[0];
+ return *data;
}
private size_t start, end;
@@ -39,13 +40,12 @@ class Vector(T)
invariant
{
assert(start <= end);
+ assert(start == 0 || end > 0);
}
- private alias ElementType = typeof(data[0].vector[0]);
-
- protected this(V data, in size_t a, in size_t b)
+ protected this(ref Vector data, in size_t a, in size_t b)
{
- this.data = data;
+ this.data = &data;
start = a;
end = b;
}
@@ -57,7 +57,7 @@ class Vector(T)
@property bool empty() inout const
{
- return start >= end;
+ return start == end;
}
@property size_t length() inout const
@@ -67,7 +67,7 @@ class Vector(T)
alias opDollar = length;
- @property ref inout(ElementType) front() inout
+ @property ref inout(T) front() inout
in
{
assert(!empty);
@@ -77,7 +77,7 @@ class Vector(T)
return outer[start];
}
- @property ref inout(ElementType) back() inout
+ @property ref inout(T) back() inout
in
{
assert(!empty);
@@ -107,7 +107,7 @@ class Vector(T)
--end;
}
- ref inout(ElementType) opIndex(in size_t i) inout
+ ref inout(T) opIndex(in size_t i) inout
in
{
assert(start + i < end);
@@ -133,12 +133,12 @@ class Vector(T)
return typeof(return)(outer, start + i, start + j);
}
- Range!(const(V)) opIndex() const
+ Range opIndex()
{
return typeof(return)(outer, start, end);
}
- Range!(const(V)) opSlice(in size_t i, in size_t j) const
+ Range opSlice(in size_t i, in size_t j)
in
{
assert(i <= j);
@@ -149,9 +149,9 @@ class Vector(T)
return typeof(return)(outer, start + i, start + j);
}
- static if (isMutable!V)
+ static if (isMutable!Vector)
{
- Range opIndexAssign(in ElementType value)
+ Range opIndexAssign(in T value)
in
{
assert(end <= outer.length);
@@ -161,7 +161,7 @@ class Vector(T)
return outer[start .. end] = value;
}
- Range opSliceAssign(in ElementType value, in size_t i, in size_t j)
+ Range opSliceAssign(in T value, in size_t i, in size_t j)
in
{
assert(start + j <= end);
@@ -171,7 +171,7 @@ class Vector(T)
return outer[start + i .. start + j] = value;
}
- Range opSliceAssign(in Range!Vector value, in size_t i, in size_t j)
+ Range opSliceAssign(in Range value, in size_t i, in size_t j)
in
{
assert(length == value.length);
@@ -193,589 +193,676 @@ class Vector(T)
}
}
- /**
- * Creates an empty $(D_PSYMBOL Vector).
- *
- * Params:
- * allocator = The allocator should be used for the element
- * allocations.
- */
- this(shared Allocator allocator = defaultAllocator)
+ struct Vector
{
- this.allocator = allocator;
- }
+ private size_t length_;
- /**
- * Creates a new $(D_PSYMBOL Vector).
- *
- * Params:
- * U = Variadic template for the constructor parameters.
- * params = Values to initialize the array with. The last parameter can
- * be an allocator, if not, $(D_PSYMBOL defaultAllocator) is used.
- */
- this(U...)(U params)
- {
- static if (isImplicitlyConvertible!(typeof(params[$ - 1]), Allocator))
- {
- allocator = params[$ - 1];
- auto values = params[0 .. $ - 1];
- }
- else
+ invariant
{
- allocator = defaultAllocator;
- alias values = params;
+ assert(length_ <= vector.length);
}
- resizeArray!T(allocator, vector, values.length);
- foreach (i, v; values)
- {
- vector[i] = v;
- }
- }
-
- /**
- * Destroys this $(D_PSYMBOL Vector).
- */
- ~this()
- {
- dispose(allocator, vector);
- }
+ /// Internal representation.
+ private T[] vector;
- /**
- * Removes all elements.
- */
- void clear()
- {
- resizeArray!T(allocator, vector, 0);
- }
+ /// The allocator.
+ private shared Allocator allocator;
- ///
- unittest
- {
- auto v = defaultAllocator.make!(Vector!int)(18, 20, 15);
+ /**
+ * Creates an empty $(D_PSYMBOL Vector).
+ *
+ * Params:
+ * allocator = The allocator should be used for the element
+ * allocations.
+ */
+ this(shared Allocator allocator)
+ {
+ this.allocator = allocator;
+ }
- v.clear();
- assert(v.length == 0);
- }
+ /**
+ * Creates a new $(D_PSYMBOL Vector).
+ *
+ * Params:
+ * U = Variadic template for the constructor parameters.
+ * params = Values to initialize the array with. The last parameter can
+ * be an allocator, if not, $(D_PSYMBOL defaultAllocator) is used.
+ */
+ this(U...)(U params)
+ {
+ static if (isImplicitlyConvertible!(typeof(params[$ - 1]), Allocator))
+ {
+ allocator = params[$ - 1];
+ auto values = params[0 .. $ - 1];
+ }
+ else
+ {
+ allocator = defaultAllocator;
+ alias values = params;
+ }
- /**
- * Returns: Vector length.
- */
- @property size_t length() inout const
- {
- return vector.length;
- }
+ resizeArray!T(allocator, vector, values.length);
+ length_ = values.length;
- /// Ditto.
- size_t opDollar() inout const
- {
- return length;
- }
-
- /**
- * Expands/shrinks the vector.
- *
- * Params:
- * length = New length.
- */
- @property void length(in size_t length)
- {
- resizeArray!T(allocator, vector, length);
- }
+ foreach (i, v; values)
+ {
+ vector[i] = v;
+ }
+ }
- ///
- unittest
- {
- auto v = defaultAllocator.make!(Vector!int);
+ /**
+ * Destroys this $(D_PSYMBOL Vector).
+ */
+ ~this()
+ {
+ if (allocator is null)
+ {
+ allocator = defaultAllocator;
+ }
+ dispose(allocator, vector);
+ }
- v.length = 5;
- assert(v.length == 5);
+ /**
+ * Removes all elements.
+ */
+ void clear()
+ {
+ length_ = 0;
+ }
- v.length = 7;
- assert(v.length == 7);
+ ///
+ unittest
+ {
+ auto v = defaultAllocator.make!(Vector!int)(18, 20, 15);
+ v.clear();
+ assert(v.length == 0);
+ }
- v.length = 0;
- assert(v.length == 0);
- }
+ /**
+ * Returns: How many elements the vector can contain without reallocating.
+ */
+ @property size_t capacity() inout const
+ {
+ return vector.length;
+ }
- /**
- * Returns: $(D_KEYWORD true) if the vector is empty.
- */
- @property bool empty() inout const
- {
- return vector.length == 0;
- }
+ /**
+ * Returns: Vector length.
+ */
+ @property size_t length() inout const
+ {
+ return length_;
+ }
- /**
- * Removes $(D_PARAM howMany) elements from the vector.
- *
- * This method doesn't fail if it could not remove $(D_PARAM howMany)
- * elements. Instead, if $(D_PARAM howMany) is greater than the vector
- * length, all elements are removed.
- *
- * Params:
- * howMany = How many elements should be removed.
- *
- * Returns: The number of elements removed
- */
- size_t removeBack(in size_t howMany)
- {
- immutable toRemove = min(howMany, length);
+ /// Ditto.
+ size_t opDollar() inout const
+ {
+ return length;
+ }
- static if (hasElaborateDestructor!T)
+ /**
+ * Reserves space for $(D_PARAM n) elements.
+ */
+ void reserve(in size_t n)
{
- foreach (ref e; vector[$ - toRemove ..$])
+ if (allocator is null)
{
- allocator.dispose(e);
+ allocator = defaultAllocator;
+ }
+ if (vector.length < n)
+ {
+ allocator.resizeArray!T(vector, n);
}
}
- length = length - toRemove;
-
- return toRemove;
- }
- ///
- unittest
- {
- auto v = defaultAllocator.make!(Vector!int)(5, 18, 17);
-
- assert(v.removeBack(0) == 0);
- assert(v.removeBack(2) == 2);
- assert(v.removeBack(3) == 1);
- assert(v.removeBack(3) == 0);
+ ///
+ unittest
+ {
+ Vector!int v;
+ assert(v.capacity == 0);
+ assert(v.length == 0);
- defaultAllocator.dispose(v);
- }
+ v.reserve(3);
+ assert(v.capacity == 3);
+ assert(v.length == 0);
+ }
- /**
- * Assigns a value to the element with the index $(D_PARAM pos).
- *
- * Params:
- * value = Value.
- *
- * Returns: Assigned value.
- *
- * Precondition: $(D_INLINECODE length > pos)
- */
- T opIndexAssign(in T value, in size_t pos)
- in
- {
- assert(length > pos);
- }
- body
- {
- return vector[pos] = value;
- }
+ /**
+ * Expands/shrinks the vector.
+ *
+ * Params:
+ * len = New length.
+ */
+ @property void length(in size_t len)
+ {
+ reserve(len);
+ length_ = len;
+ }
- /// Ditto.
- Range!Vector opIndexAssign(in T value)
- {
- vector[0..$] = value;
- return opIndex();
- }
+ ///
+ unittest
+ {
+ Vector!int v;
- ///
- unittest
- {
- auto v1 = defaultAllocator.make!(Vector!int)(12, 1, 7);
+ v.length = 5;
+ assert(v.length == 5);
+ assert(v.capacity == 5);
- v1[] = 3;
- assert(v1[0] == 3);
- assert(v1[1] == 3);
- assert(v1[2] == 3);
+ v.length = 7;
+ assert(v.length == 7);
+ assert(v.capacity == 7);
- defaultAllocator.dispose(v1);
- }
+ v.length = 0;
+ assert(v.length == 0);
+ assert(v.capacity == 7);
+ }
+ /**
+ * Returns: $(D_KEYWORD true) if the vector is empty.
+ */
+ @property bool empty() inout const
+ {
+ return length == 0;
+ }
- /**
- * Returns: The value on index $(D_PARAM pos).
- *
- * Precondition: $(D_INLINECODE length > pos)
- */
- ref inout(T) opIndex(in size_t pos) inout
- in
- {
- assert(length > pos);
- }
- body
- {
- return vector[pos];
- }
+ /**
+ * Removes $(D_PARAM howMany) elements from the vector.
+ *
+ * This method doesn't fail if it could not remove $(D_PARAM howMany)
+ * elements. Instead, if $(D_PARAM howMany) is greater than the vector
+ * length, all elements are removed.
+ *
+ * Params:
+ * howMany = How many elements should be removed.
+ *
+ * Returns: The number of elements removed
+ */
+ size_t removeBack(in size_t howMany = 1)
+ {
+ immutable toRemove = min(howMany, length);
- ///
- unittest
- {
- auto v = defaultAllocator.make!(Vector!int)(6, 123, 34, 5);
+ static if (hasElaborateDestructor!T)
+ {
+ foreach (ref e; vector[$ - toRemove ..$])
+ {
+ allocator.dispose(e);
+ }
+ }
+ length_ -= toRemove;
- assert(v[0] == 6);
- assert(v[1] == 123);
- assert(v[2] == 34);
- assert(v[3] == 5);
+ return toRemove;
+ }
- defaultAllocator.dispose(v);
- }
+ /// Ditto.
+ alias remove = removeBack;
- /**
- * Comparison for equality.
- *
- * Params:
- * o = The vector to compare with.
- *
- * Returns: $(D_KEYWORD true) if the vectors are equal, $(D_KEYWORD false)
- * otherwise.
- */
- override bool opEquals(Object o)
- {
- auto v = cast(Vector) o;
+ ///
+ unittest
+ {
+ auto v = Vector!int(5, 18, 17);
- return v is null ? super.opEquals(o) : vector == v.vector;
- }
+ assert(v.removeBack(0) == 0);
+ assert(v.removeBack(2) == 2);
+ assert(v.removeBack(3) == 1);
+ assert(v.removeBack(3) == 0);
+ }
- ///
- unittest
- {
- auto v1 = defaultAllocator.make!(Vector!int);
- auto v2 = defaultAllocator.make!(Vector!int);
+ /**
+ * Inserts the $(D_PARAM el) into the vector.
+ *
+ * Returns: The number of elements inserted.
+ */
+ size_t insertBack(in T el)
+ {
+ reserve(length + 1);
+ vector[length] = el;
+ ++length_;
+ return 1;
+ }
- assert(v1 == v2);
+ /// Ditto.
+ size_t insertBack(in Range el)
+ {
+ immutable newLength = length + el.length;
- v1.length = 1;
- v2.length = 2;
- assert(v1 != v2);
+ reserve(newLength);
+ vector[length .. newLength] = el.data.vector[el.start .. el.end];
+ length_ = newLength;
- v1.length = 2;
- v1[0] = v2[0] = 2;
- v1[1] = 3;
- v2[1] = 4;
- assert(v1 != v2);
+ return el.length;
+ }
- v2[1] = 3;
- assert(v1 == v2);
+ /// Ditto.
+ size_t insertBack(R)(R el)
+ if (isInputRange!R && isImplicitlyConvertible!(ElementType!R, T))
+ {
+ immutable rLen = walkLength(el);
- defaultAllocator.dispose(v1);
- defaultAllocator.dispose(v2);
- }
+ reserve(length + rLen);
+ while (!el.empty)
+ {
+ vector[length_] = el.front;
+ el.popFront();
+ length_++;
+ }
+ return rLen;
+ }
- /**
- * $(D_KEYWORD foreach) iteration.
- *
- * Params:
- * dg = $(D_KEYWORD foreach) body.
- */
- int opApply(scope int delegate(ref T) dg)
- {
- int result;
+ /// Ditto.
+ alias insert = insertBack;
- foreach (e; vector)
+ ///
+ unittest
{
- if ((result = dg(e)) != 0)
+ struct TestRange
{
- return result;
+ int counter = 6;
+
+ int front()
+ {
+ return counter;
+ }
+
+ void popFront()
+ {
+ counter -= 2;
+ }
+
+ bool empty()
+ {
+ return counter == 0;
+ }
}
+
+ Vector!int v1;
+
+ assert(v1.insertBack(5) == 1);
+ assert(v1.length == 1);
+ assert(v1.capacity == 1);
+ assert(v1.back == 5);
+
+ assert(v1.insertBack(TestRange()) == 3);
+ assert(v1.length == 4);
+ assert(v1.capacity == 4);
+ assert(v1[0] == 5 && v1[1] == 6 && v1[2] == 4 && v1[3] == 2);
+
+ auto v2 = Vector!int(34, 234);
+ assert(v1.insertBack(v2[]) == 2);
+ assert(v1.length == 6);
+ assert(v1.capacity == 6);
+ assert(v1[4] == 34 && v1[5] == 234);
+ }
+
+ /**
+ * Assigns a value to the element with the index $(D_PARAM pos).
+ *
+ * Params:
+ * value = Value.
+ * pos = Position.
+ *
+ * Returns: Assigned value.
+ *
+ * Precondition: $(D_INLINECODE length > pos)
+ */
+ T opIndexAssign(in T value, in size_t pos)
+ in
+ {
+ assert(length > pos);
+ }
+ body
+ {
+ return vector[pos] = value;
}
- return result;
- }
- /// Ditto.
- int opApply(scope int delegate(ref size_t i, ref T) dg)
- {
- int result;
+ /// Ditto.
+ Range opIndexAssign(in T value)
+ {
+ vector[0 .. $] = value;
+ return opIndex();
+ }
- foreach (i, e; vector)
+ ///
+ unittest
{
- if ((result = dg(i, e)) != 0)
- {
- return result;
- }
+ auto v1 = Vector!int(12, 1, 7);
+
+ v1[] = 3;
+ assert(v1[0] == 3);
+ assert(v1[1] == 3);
+ assert(v1[2] == 3);
}
- return result;
- }
- ///
- unittest
- {
- auto v = defaultAllocator.make!(Vector!int)(5, 15, 8);
+ /**
+ * Returns: The value on index $(D_PARAM pos) or a range that iterates over
+ * elements of the vector, in forward order.
+ *
+ * Precondition: $(D_INLINECODE length > pos)
+ */
+ ref inout(T) opIndex(in size_t pos) inout
+ in
+ {
+ assert(length > pos);
+ }
+ body
+ {
+ return vector[pos];
+ }
- size_t i;
- foreach (j, ref e; v)
+ /// Ditto.
+ Range opIndex()
{
- i = j;
+ return typeof(return)(this, 0, length);
}
- assert(i == 2);
- foreach (j, e; v)
+ ///
+ unittest
{
- assert(j != 0 || e == 5);
- assert(j != 1 || e == 15);
- assert(j != 2 || e == 8);
+ auto v = Vector!int(6, 123, 34, 5);
+
+ assert(v[0] == 6);
+ assert(v[1] == 123);
+ assert(v[2] == 34);
+ assert(v[3] == 5);
}
- defaultAllocator.dispose(v);
- }
- /**
- * $(D_KEYWORD foreach) iteration.
- *
- * Params:
- * dg = $(D_KEYWORD foreach) body.
- */
- int opApplyReverse(scope int delegate(ref T) dg)
- {
- int result;
+ /**
+ * Comparison for equality.
+ *
+ * Params:
+ * o = The vector to compare with.
+ *
+ * Returns: $(D_KEYWORD true) if the vectors are equal, $(D_KEYWORD false)
+ * otherwise.
+ */
+ bool opEquals(typeof(this) v)
+ {
+ return opEquals(v);
+ }
- foreach_reverse (e; vector)
+ /// Ditto.
+ bool opEquals(ref typeof(this) v)
{
- if ((result = dg(e)) != 0)
- {
- return result;
- }
+ return vector == v.vector;
}
- return result;
- }
- /// Ditto.
- int opApplyReverse(scope int delegate(ref size_t i, ref T) dg)
- {
- int result;
+ ///
+ unittest
+ {
+ Vector!int v1, v2;
+ assert(v1 == v2);
+
+ v1.length = 1;
+ v2.length = 2;
+ assert(v1 != v2);
+
+ v1.length = 2;
+ v1[0] = v2[0] = 2;
+ v1[1] = 3;
+ v2[1] = 4;
+ assert(v1 != v2);
- foreach_reverse (i, e; vector)
+ v2[1] = 3;
+ assert(v1 == v2);
+ }
+
+ /**
+ * $(D_KEYWORD foreach) iteration.
+ *
+ * Params:
+ * dg = $(D_KEYWORD foreach) body.
+ */
+ int opApply(scope int delegate(ref T) dg)
{
- if ((result = dg(i, e)) != 0)
+ int result;
+
+ foreach (e; vector)
{
- return result;
+ if ((result = dg(e)) != 0)
+ {
+ return result;
+ }
}
+ return result;
}
- return result;
- }
- ///
- unittest
- {
- auto v = defaultAllocator.make!(Vector!int)(5, 15, 8);
- size_t i;
-
- foreach_reverse (j, ref e; v)
+ /// Ditto.
+ int opApply(scope int delegate(ref size_t i, ref T) dg)
{
- i = j;
+ int result;
+
+ foreach (i, e; vector)
+ {
+ if ((result = dg(i, e)) != 0)
+ {
+ return result;
+ }
+ }
+ return result;
}
- assert(i == 0);
- foreach_reverse (j, e; v)
+ /// Ditto.
+ int opApplyReverse(scope int delegate(ref T) dg)
{
- assert(j != 2 || e == 8);
- assert(j != 1 || e == 15);
- assert(j != 0 || e == 5);
- }
- defaultAllocator.dispose(v);
- }
+ int result;
- /**
- * Returns: The first element.
- *
- * Precondition: $(D_INLINECODE length > 0)
- */
- @property ref inout(T) front() inout
- in
- {
- assert(vector.length > 0);
- }
- body
- {
- return vector[0];
- }
+ foreach_reverse (e; vector)
+ {
+ if ((result = dg(e)) != 0)
+ {
+ return result;
+ }
+ }
+ return result;
+ }
- ///
- unittest
- {
- auto v = defaultAllocator.make!(Vector!int)(5);
+ /// Ditto.
+ int opApplyReverse(scope int delegate(ref size_t i, ref T) dg)
+ {
+ int result;
- assert(v.front == 5);
+ foreach_reverse (i, e; vector)
+ {
+ if ((result = dg(i, e)) != 0)
+ {
+ return result;
+ }
+ }
+ return result;
+ }
- v.length = 2;
- v[1] = 15;
- assert(v.front == 5);
+ ///
+ unittest
+ {
+ auto v = Vector!int(5, 15, 8);
- defaultAllocator.dispose(v);
- }
+ size_t i;
+ foreach (j, ref e; v)
+ {
+ i = j;
+ }
+ assert(i == 2);
- /**
- * Returns: The last element.
- *
- * Precondition: $(D_INLINECODE length > 0)
- */
- @property ref inout(T) back() inout
- in
- {
- assert(vector.length > 0);
- }
- body
- {
- return vector[$ - 1];
- }
+ foreach (j, e; v)
+ {
+ assert(j != 0 || e == 5);
+ assert(j != 1 || e == 15);
+ assert(j != 2 || e == 8);
+ }
+ }
- ///
- unittest
- {
- auto v = defaultAllocator.make!(Vector!int)(5);
+ ///
+ unittest
+ {
+ auto v = Vector!int(5, 15, 8);
+ size_t i;
- assert(v.back == 5);
+ foreach_reverse (j, ref e; v)
+ {
+ i = j;
+ }
+ assert(i == 0);
- v.length = 2;
- v[1] = 15;
- assert(v.back == 15);
+ foreach_reverse (j, e; v)
+ {
+ assert(j != 2 || e == 8);
+ assert(j != 1 || e == 15);
+ assert(j != 0 || e == 5);
+ }
+ }
- defaultAllocator.dispose(v);
- }
+ /**
+ * Returns: The first element.
+ *
+ * Precondition: $(D_INLINECODE length > 0)
+ */
+ @property ref inout(T) front() inout
+ in
+ {
+ assert(!empty);
+ }
+ body
+ {
+ return vector[0];
+ }
- /**
- * Returns: A range that iterates over elements of the container, in
- * forward order.
- */
- Range!Vector opIndex()
- {
- return typeof(return)(this, 0, length);
- }
+ ///
+ unittest
+ {
+ auto v = Vector!int(5);
- /// Ditto.
- Range!(const Vector) opIndex() const
- {
- return typeof(return)(this, 0, length);
- }
+ assert(v.front == 5);
- /// Ditto.
- Range!(immutable Vector) opIndex() immutable
- {
- return typeof(return)(this, 0, length);
- }
+ v.length = 2;
+ v[1] = 15;
+ assert(v.front == 5);
+ }
- /**
- * Params:
- * i = Slice start.
- * j = Slice end.
- *
- * Returns: A range that iterates over elements of the container from
- * index $(D_PARAM i) up to (excluding) index $(D_PARAM j).
- *
- * Precondition: $(D_INLINECODE i <= j && j <= length)
- */
- Range!Vector opSlice(in size_t i, in size_t j)
- in
- {
- assert(i <= j);
- assert(j <= length);
- }
- body
- {
- return typeof(return)(this, i, j);
- }
+ /**
+ * Returns: The last element.
+ *
+ * Precondition: $(D_INLINECODE length > 0)
+ */
+ @property ref inout(T) back() inout
+ in
+ {
+ assert(!empty);
+ }
+ body
+ {
+ return vector[$ - 1];
+ }
- /// Ditto.
- Range!(const Vector) opSlice(in size_t i, in size_t j) const
- in
- {
- assert(i <= j);
- assert(j <= length);
- }
- body
- {
- return typeof(return)(this, i, j);
- }
+ ///
+ unittest
+ {
+ auto v = Vector!int(5);
- /// Ditto.
- Range!(immutable Vector) opSlice(in size_t i, in size_t j) immutable
- in
- {
- assert(i <= j);
- assert(j <= length);
- }
- body
- {
- return typeof(return)(this, i, j);
- }
+ assert(v.back == 5);
- /**
- * Slicing assignment.
- *
- * Params:
- * value = New value.
- * i = Slice start.
- * j = Slice end.
- *
- * Returns: Assigned value.
- *
- * Precondition: $(D_INLINECODE i <= j && j <= length);
- * The lenghts of the ranges and slices match.
- */
- Range!Vector opSliceAssign(in T value, in size_t i, in size_t j)
- in
- {
- assert(i <= j);
- assert(j <= length);
- }
- body
- {
- vector[i .. j] = value;
- return opSlice(i, j);
- }
+ v.length = 2;
+ v[1] = 15;
+ assert(v.back == 15);
+ }
- /// Ditto.
- Range!Vector opSliceAssign(in Range!Vector value, in size_t i, in size_t j)
- in
- {
- assert(j - i == value.length);
- }
- body
- {
- vector[i .. j] = value.outer.vector[value.start .. value.end];
- return opSlice(i, j);
- }
+ /**
+ * Params:
+ * i = Slice start.
+ * j = Slice end.
+ *
+ * Returns: A range that iterates over elements of the container from
+ * index $(D_PARAM i) up to (excluding) index $(D_PARAM j).
+ *
+ * Precondition: $(D_INLINECODE i <= j && j <= length)
+ */
+ Range opSlice(in size_t i, in size_t j)
+ in
+ {
+ assert(i <= j);
+ assert(j <= length);
+ }
+ body
+ {
+ return typeof(return)(this, i, j);
+ }
+
+ /**
+ * Slicing assignment.
+ *
+ * Params:
+ * value = New value.
+ * i = Slice start.
+ * j = Slice end.
+ *
+ * Returns: Assigned value.
+ *
+ * Precondition: $(D_INLINECODE i <= j && j <= length);
+ * The lenghts of the ranges and slices match.
+ */
+ Range opSliceAssign(in T value, in size_t i, in size_t j)
+ in
+ {
+ assert(i <= j);
+ assert(j <= length);
+ }
+ body
+ {
+ vector[i .. j] = value;
+ return opSlice(i, j);
+ }
- /// Ditto.
- Range!Vector opSliceAssign(in T[] value, in size_t i, in size_t j)
- in
- {
- assert(j - i == value.length);
- }
- body
- {
- vector[i .. j] = value;
- return opSlice(i, j);
- }
+ /// Ditto.
+ Range opSliceAssign(in Range value, in size_t i, in size_t j)
+ in
+ {
+ assert(j - i == value.length);
+ }
+ body
+ {
+ vector[i .. j] = value.outer.vector[value.start .. value.end];
+ return opSlice(i, j);
+ }
- ///
- unittest
- {
- auto v1 = defaultAllocator.make!(Vector!int)(3, 3, 3);
- auto v2 = defaultAllocator.make!(Vector!int)(1, 2);
+ /// Ditto.
+ Range opSliceAssign(in T[] value, in size_t i, in size_t j)
+ in
+ {
+ assert(j - i == value.length);
+ }
+ body
+ {
+ vector[i .. j] = value;
+ return opSlice(i, j);
+ }
- v1[0..2] = 286;
- assert(v1[0] == 286);
- assert(v1[1] == 286);
- assert(v1[2] == 3);
+ ///
+ unittest
+ {
+ auto v1 = Vector!int(3, 3, 3);
+ auto v2 = Vector!int(1, 2);
- v2[0..$] = v1[1..3];
- assert(v2[0] == 286);
- assert(v2[1] == 3);
+ v1[0 .. 2] = 286;
+ assert(v1[0] == 286);
+ assert(v1[1] == 286);
+ assert(v1[2] == 3);
- defaultAllocator.dispose(v2);
- defaultAllocator.dispose(v1);
+ v2[0 .. $] = v1[1 .. 3];
+ assert(v2[0] == 286);
+ assert(v2[1] == 3);
+ }
}
-
- /// Internal representation.
- protected T[] vector;
-
- /// The allocator.
- protected shared Allocator allocator;
}
///
unittest
{
- auto v = defaultAllocator.make!(Vector!int)(5, 15, 8);
+ auto v = Vector!int(5, 15, 8);
assert(v.front == 5);
assert(v[1] == 15);
assert(v.back == 8);
+}
- defaultAllocator.dispose(v);
+private unittest
+{
+// const Vector!int v;
}
diff --git a/source/tanya/math/mp.d b/source/tanya/math/mp.d
index 06e9e15..fafe077 100644
--- a/source/tanya/math/mp.d
+++ b/source/tanya/math/mp.d
@@ -10,6 +10,7 @@
*/
module tanya.math.mp;
+import core.exception;
import std.algorithm.iteration;
import std.algorithm.searching;
import std.algorithm.mutation;
@@ -29,7 +30,7 @@ struct Integer
pure nothrow @safe @nogc invariant
{
- assert(!rep.count || rep.length || !sign, "0 should be positive.");
+ assert(rep.length || !sign, "0 should be positive.");
}
/**
@@ -137,16 +138,14 @@ struct Integer
}
--size;
}
- if (rep.count)
- {
- allocator.resizeArray(rep, size);
- }
- else
- {
- rep = () @trusted {
- return cast(ubyte[]) allocator.allocate(size);
- }();
- }
+ rep = () @trusted {
+ void[] rep = this.rep;
+ if (!allocator.reallocate(rep, size))
+ {
+ onOutOfMemoryError();
+ }
+ return cast(ubyte[]) rep;
+ }();
/* Work backward through the int, masking off each byte (up to the
first 0 byte) and copy it into the internal representation in
big-endian format. */
diff --git a/source/tanya/memory/allocator.d b/source/tanya/memory/allocator.d
index c8d0b42..fb86818 100644
--- a/source/tanya/memory/allocator.d
+++ b/source/tanya/memory/allocator.d
@@ -15,8 +15,10 @@ module tanya.memory.allocator;
*/
interface Allocator
{
-@nogc:
- @property uint alignment() const shared pure nothrow @safe;
+ /**
+ * Returns: Alignment.
+ */
+ @property uint alignment() const shared pure nothrow @safe @nogc;
/**
* Allocates $(D_PARAM size) bytes of memory.
@@ -24,9 +26,9 @@ interface Allocator
* Params:
* size = Amount of memory to allocate.
*
- * Returns: The pointer to the new allocated memory.
+ * Returns: Pointer to the new allocated memory.
*/
- void[] allocate(size_t size, TypeInfo ti = null) shared nothrow @safe;
+ void[] allocate(size_t size) shared nothrow @safe @nogc;
/**
* Deallocates a memory block.
@@ -36,7 +38,7 @@ interface Allocator
*
* Returns: Whether the deallocation was successful.
*/
- bool deallocate(void[] p) shared nothrow @safe;
+ bool deallocate(void[] p) shared nothrow @safe @nogc;
/**
* Increases or decreases the size of a memory block.
@@ -45,7 +47,7 @@ interface Allocator
* p = A pointer to the memory block.
* size = Size of the reallocated block.
*
- * Returns: Whether the reallocation was successful.
+ * Returns: Pointer to the allocated memory.
*/
- bool reallocate(ref void[] p, size_t size) shared nothrow @safe;
+ bool reallocate(ref void[] p, size_t size) shared nothrow @safe @nogc;
}
diff --git a/source/tanya/memory/mmappool.d b/source/tanya/memory/mmappool.d
index 9c7da4d..e915659 100644
--- a/source/tanya/memory/mmappool.d
+++ b/source/tanya/memory/mmappool.d
@@ -47,17 +47,8 @@ else version (Windows)
* | N | -----------> next| || N | | |
* | | | | | || | | |
* --------------------------------------------------- ------------------------
- *
- * TODO:
- * $(UL
- * $(LI Thread safety (core.atomic.cas))
- * $(LI If two neighbour blocks are free, they can be merged)
- * $(LI Reallocation shoud check if there is enough free space in the
- * next block instead of always moving the memory)
- * $(LI Make 64 KB regions mininmal region size on Linux)
- * )
*/
-class MmapPool : Allocator
+final class MmapPool : Allocator
{
@nogc:
shared static this()
@@ -80,9 +71,9 @@ class MmapPool : Allocator
* Params:
* size = Amount of memory to allocate.
*
- * Returns: The pointer to the new allocated memory.
+ * Returns: Pointer to the new allocated memory.
*/
- void[] allocate(size_t size, TypeInfo ti = null) shared nothrow @trusted
+ void[] allocate(size_t size) shared nothrow @trusted
{
if (!size)
{