Implement insertion into the vector
This commit is contained in:
parent
061cd6264b
commit
c1fb89af99
@ -11,6 +11,7 @@
|
|||||||
module tanya.container.vector;
|
module tanya.container.vector;
|
||||||
|
|
||||||
import std.algorithm.comparison;
|
import std.algorithm.comparison;
|
||||||
|
import std.range.primitives;
|
||||||
import std.traits;
|
import std.traits;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
|
|
||||||
@ -20,18 +21,18 @@ import tanya.memory;
|
|||||||
* Params:
|
* Params:
|
||||||
* T = Content type.
|
* T = Content type.
|
||||||
*/
|
*/
|
||||||
class Vector(T)
|
template Vector(T)
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Defines the container's primary range.
|
* 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;
|
private size_t start, end;
|
||||||
@ -39,13 +40,12 @@ class Vector(T)
|
|||||||
invariant
|
invariant
|
||||||
{
|
{
|
||||||
assert(start <= end);
|
assert(start <= end);
|
||||||
|
assert(start == 0 || end > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private alias ElementType = typeof(data[0].vector[0]);
|
protected this(ref Vector data, in size_t a, in size_t b)
|
||||||
|
|
||||||
protected this(V data, in size_t a, in size_t b)
|
|
||||||
{
|
{
|
||||||
this.data = data;
|
this.data = &data;
|
||||||
start = a;
|
start = a;
|
||||||
end = b;
|
end = b;
|
||||||
}
|
}
|
||||||
@ -57,7 +57,7 @@ class Vector(T)
|
|||||||
|
|
||||||
@property bool empty() inout const
|
@property bool empty() inout const
|
||||||
{
|
{
|
||||||
return start >= end;
|
return start == end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property size_t length() inout const
|
@property size_t length() inout const
|
||||||
@ -67,7 +67,7 @@ class Vector(T)
|
|||||||
|
|
||||||
alias opDollar = length;
|
alias opDollar = length;
|
||||||
|
|
||||||
@property ref inout(ElementType) front() inout
|
@property ref inout(T) front() inout
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(!empty);
|
assert(!empty);
|
||||||
@ -77,7 +77,7 @@ class Vector(T)
|
|||||||
return outer[start];
|
return outer[start];
|
||||||
}
|
}
|
||||||
|
|
||||||
@property ref inout(ElementType) back() inout
|
@property ref inout(T) back() inout
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(!empty);
|
assert(!empty);
|
||||||
@ -107,7 +107,7 @@ class Vector(T)
|
|||||||
--end;
|
--end;
|
||||||
}
|
}
|
||||||
|
|
||||||
ref inout(ElementType) opIndex(in size_t i) inout
|
ref inout(T) opIndex(in size_t i) inout
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(start + i < end);
|
assert(start + i < end);
|
||||||
@ -133,12 +133,12 @@ class Vector(T)
|
|||||||
return typeof(return)(outer, start + i, start + j);
|
return typeof(return)(outer, start + i, start + j);
|
||||||
}
|
}
|
||||||
|
|
||||||
Range!(const(V)) opIndex() const
|
Range opIndex()
|
||||||
{
|
{
|
||||||
return typeof(return)(outer, start, end);
|
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
|
in
|
||||||
{
|
{
|
||||||
assert(i <= j);
|
assert(i <= j);
|
||||||
@ -149,9 +149,9 @@ class Vector(T)
|
|||||||
return typeof(return)(outer, start + i, start + j);
|
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
|
in
|
||||||
{
|
{
|
||||||
assert(end <= outer.length);
|
assert(end <= outer.length);
|
||||||
@ -161,7 +161,7 @@ class Vector(T)
|
|||||||
return outer[start .. end] = value;
|
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
|
in
|
||||||
{
|
{
|
||||||
assert(start + j <= end);
|
assert(start + j <= end);
|
||||||
@ -171,7 +171,7 @@ class Vector(T)
|
|||||||
return outer[start + i .. start + j] = value;
|
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
|
in
|
||||||
{
|
{
|
||||||
assert(length == value.length);
|
assert(length == value.length);
|
||||||
@ -193,6 +193,21 @@ class Vector(T)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Vector
|
||||||
|
{
|
||||||
|
private size_t length_;
|
||||||
|
|
||||||
|
invariant
|
||||||
|
{
|
||||||
|
assert(length_ <= vector.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Internal representation.
|
||||||
|
private T[] vector;
|
||||||
|
|
||||||
|
/// The allocator.
|
||||||
|
private shared Allocator allocator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an empty $(D_PSYMBOL Vector).
|
* Creates an empty $(D_PSYMBOL Vector).
|
||||||
*
|
*
|
||||||
@ -200,7 +215,7 @@ class Vector(T)
|
|||||||
* allocator = The allocator should be used for the element
|
* allocator = The allocator should be used for the element
|
||||||
* allocations.
|
* allocations.
|
||||||
*/
|
*/
|
||||||
this(shared Allocator allocator = defaultAllocator)
|
this(shared Allocator allocator)
|
||||||
{
|
{
|
||||||
this.allocator = allocator;
|
this.allocator = allocator;
|
||||||
}
|
}
|
||||||
@ -227,6 +242,8 @@ class Vector(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
resizeArray!T(allocator, vector, values.length);
|
resizeArray!T(allocator, vector, values.length);
|
||||||
|
length_ = values.length;
|
||||||
|
|
||||||
foreach (i, v; values)
|
foreach (i, v; values)
|
||||||
{
|
{
|
||||||
vector[i] = v;
|
vector[i] = v;
|
||||||
@ -238,6 +255,10 @@ class Vector(T)
|
|||||||
*/
|
*/
|
||||||
~this()
|
~this()
|
||||||
{
|
{
|
||||||
|
if (allocator is null)
|
||||||
|
{
|
||||||
|
allocator = defaultAllocator;
|
||||||
|
}
|
||||||
dispose(allocator, vector);
|
dispose(allocator, vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,24 +267,31 @@ class Vector(T)
|
|||||||
*/
|
*/
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
resizeArray!T(allocator, vector, 0);
|
length_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v = defaultAllocator.make!(Vector!int)(18, 20, 15);
|
auto v = defaultAllocator.make!(Vector!int)(18, 20, 15);
|
||||||
|
|
||||||
v.clear();
|
v.clear();
|
||||||
assert(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: Vector length.
|
* Returns: Vector length.
|
||||||
*/
|
*/
|
||||||
@property size_t length() inout const
|
@property size_t length() inout const
|
||||||
{
|
{
|
||||||
return vector.length;
|
return length_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
@ -273,29 +301,60 @@ class Vector(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expands/shrinks the vector.
|
* Reserves space for $(D_PARAM n) elements.
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* length = New length.
|
|
||||||
*/
|
*/
|
||||||
@property void length(in size_t length)
|
void reserve(in size_t n)
|
||||||
{
|
{
|
||||||
resizeArray!T(allocator, vector, length);
|
if (allocator is null)
|
||||||
|
{
|
||||||
|
allocator = defaultAllocator;
|
||||||
|
}
|
||||||
|
if (vector.length < n)
|
||||||
|
{
|
||||||
|
allocator.resizeArray!T(vector, n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v = defaultAllocator.make!(Vector!int);
|
Vector!int v;
|
||||||
|
assert(v.capacity == 0);
|
||||||
|
assert(v.length == 0);
|
||||||
|
|
||||||
|
v.reserve(3);
|
||||||
|
assert(v.capacity == 3);
|
||||||
|
assert(v.length == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expands/shrinks the vector.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* len = New length.
|
||||||
|
*/
|
||||||
|
@property void length(in size_t len)
|
||||||
|
{
|
||||||
|
reserve(len);
|
||||||
|
length_ = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
Vector!int v;
|
||||||
|
|
||||||
v.length = 5;
|
v.length = 5;
|
||||||
assert(v.length == 5);
|
assert(v.length == 5);
|
||||||
|
assert(v.capacity == 5);
|
||||||
|
|
||||||
v.length = 7;
|
v.length = 7;
|
||||||
assert(v.length == 7);
|
assert(v.length == 7);
|
||||||
|
assert(v.capacity == 7);
|
||||||
|
|
||||||
v.length = 0;
|
v.length = 0;
|
||||||
assert(v.length == 0);
|
assert(v.length == 0);
|
||||||
|
assert(v.capacity == 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -303,7 +362,7 @@ class Vector(T)
|
|||||||
*/
|
*/
|
||||||
@property bool empty() inout const
|
@property bool empty() inout const
|
||||||
{
|
{
|
||||||
return vector.length == 0;
|
return length == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -318,7 +377,7 @@ class Vector(T)
|
|||||||
*
|
*
|
||||||
* Returns: The number of elements removed
|
* Returns: The number of elements removed
|
||||||
*/
|
*/
|
||||||
size_t removeBack(in size_t howMany)
|
size_t removeBack(in size_t howMany = 1)
|
||||||
{
|
{
|
||||||
immutable toRemove = min(howMany, length);
|
immutable toRemove = min(howMany, length);
|
||||||
|
|
||||||
@ -329,22 +388,109 @@ class Vector(T)
|
|||||||
allocator.dispose(e);
|
allocator.dispose(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
length = length - toRemove;
|
length_ -= toRemove;
|
||||||
|
|
||||||
return toRemove;
|
return toRemove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ditto.
|
||||||
|
alias remove = removeBack;
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v = defaultAllocator.make!(Vector!int)(5, 18, 17);
|
auto v = Vector!int(5, 18, 17);
|
||||||
|
|
||||||
assert(v.removeBack(0) == 0);
|
assert(v.removeBack(0) == 0);
|
||||||
assert(v.removeBack(2) == 2);
|
assert(v.removeBack(2) == 2);
|
||||||
assert(v.removeBack(3) == 1);
|
assert(v.removeBack(3) == 1);
|
||||||
assert(v.removeBack(3) == 0);
|
assert(v.removeBack(3) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
defaultAllocator.dispose(v);
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ditto.
|
||||||
|
size_t insertBack(in Range el)
|
||||||
|
{
|
||||||
|
immutable newLength = length + el.length;
|
||||||
|
|
||||||
|
reserve(newLength);
|
||||||
|
vector[length .. newLength] = el.data.vector[el.start .. el.end];
|
||||||
|
length_ = newLength;
|
||||||
|
|
||||||
|
return el.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ditto.
|
||||||
|
size_t insertBack(R)(R el)
|
||||||
|
if (isInputRange!R && isImplicitlyConvertible!(ElementType!R, T))
|
||||||
|
{
|
||||||
|
immutable rLen = walkLength(el);
|
||||||
|
|
||||||
|
reserve(length + rLen);
|
||||||
|
while (!el.empty)
|
||||||
|
{
|
||||||
|
vector[length_] = el.front;
|
||||||
|
el.popFront();
|
||||||
|
length_++;
|
||||||
|
}
|
||||||
|
return rLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ditto.
|
||||||
|
alias insert = insertBack;
|
||||||
|
|
||||||
|
///
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
struct TestRange
|
||||||
|
{
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -352,6 +498,7 @@ class Vector(T)
|
|||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* value = Value.
|
* value = Value.
|
||||||
|
* pos = Position.
|
||||||
*
|
*
|
||||||
* Returns: Assigned value.
|
* Returns: Assigned value.
|
||||||
*
|
*
|
||||||
@ -368,28 +515,26 @@ class Vector(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
Range!Vector opIndexAssign(in T value)
|
Range opIndexAssign(in T value)
|
||||||
{
|
{
|
||||||
vector[0..$] = value;
|
vector[0 .. $] = value;
|
||||||
return opIndex();
|
return opIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v1 = defaultAllocator.make!(Vector!int)(12, 1, 7);
|
auto v1 = Vector!int(12, 1, 7);
|
||||||
|
|
||||||
v1[] = 3;
|
v1[] = 3;
|
||||||
assert(v1[0] == 3);
|
assert(v1[0] == 3);
|
||||||
assert(v1[1] == 3);
|
assert(v1[1] == 3);
|
||||||
assert(v1[2] == 3);
|
assert(v1[2] == 3);
|
||||||
|
|
||||||
defaultAllocator.dispose(v1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns: The value on index $(D_PARAM pos).
|
* 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)
|
* Precondition: $(D_INLINECODE length > pos)
|
||||||
*/
|
*/
|
||||||
@ -403,17 +548,21 @@ class Vector(T)
|
|||||||
return vector[pos];
|
return vector[pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ditto.
|
||||||
|
Range opIndex()
|
||||||
|
{
|
||||||
|
return typeof(return)(this, 0, length);
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v = defaultAllocator.make!(Vector!int)(6, 123, 34, 5);
|
auto v = Vector!int(6, 123, 34, 5);
|
||||||
|
|
||||||
assert(v[0] == 6);
|
assert(v[0] == 6);
|
||||||
assert(v[1] == 123);
|
assert(v[1] == 123);
|
||||||
assert(v[2] == 34);
|
assert(v[2] == 34);
|
||||||
assert(v[3] == 5);
|
assert(v[3] == 5);
|
||||||
|
|
||||||
defaultAllocator.dispose(v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -425,19 +574,21 @@ class Vector(T)
|
|||||||
* Returns: $(D_KEYWORD true) if the vectors are equal, $(D_KEYWORD false)
|
* Returns: $(D_KEYWORD true) if the vectors are equal, $(D_KEYWORD false)
|
||||||
* otherwise.
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
override bool opEquals(Object o)
|
bool opEquals(typeof(this) v)
|
||||||
{
|
{
|
||||||
auto v = cast(Vector) o;
|
return opEquals(v);
|
||||||
|
}
|
||||||
|
|
||||||
return v is null ? super.opEquals(o) : vector == v.vector;
|
/// Ditto.
|
||||||
|
bool opEquals(ref typeof(this) v)
|
||||||
|
{
|
||||||
|
return vector == v.vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v1 = defaultAllocator.make!(Vector!int);
|
Vector!int v1, v2;
|
||||||
auto v2 = defaultAllocator.make!(Vector!int);
|
|
||||||
|
|
||||||
assert(v1 == v2);
|
assert(v1 == v2);
|
||||||
|
|
||||||
v1.length = 1;
|
v1.length = 1;
|
||||||
@ -452,9 +603,6 @@ class Vector(T)
|
|||||||
|
|
||||||
v2[1] = 3;
|
v2[1] = 3;
|
||||||
assert(v1 == v2);
|
assert(v1 == v2);
|
||||||
|
|
||||||
defaultAllocator.dispose(v1);
|
|
||||||
defaultAllocator.dispose(v2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -492,33 +640,7 @@ class Vector(T)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
/// Ditto.
|
||||||
unittest
|
|
||||||
{
|
|
||||||
auto v = defaultAllocator.make!(Vector!int)(5, 15, 8);
|
|
||||||
|
|
||||||
size_t i;
|
|
||||||
foreach (j, ref e; v)
|
|
||||||
{
|
|
||||||
i = j;
|
|
||||||
}
|
|
||||||
assert(i == 2);
|
|
||||||
|
|
||||||
foreach (j, e; v)
|
|
||||||
{
|
|
||||||
assert(j != 0 || e == 5);
|
|
||||||
assert(j != 1 || e == 15);
|
|
||||||
assert(j != 2 || e == 8);
|
|
||||||
}
|
|
||||||
defaultAllocator.dispose(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* $(D_KEYWORD foreach) iteration.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* dg = $(D_KEYWORD foreach) body.
|
|
||||||
*/
|
|
||||||
int opApplyReverse(scope int delegate(ref T) dg)
|
int opApplyReverse(scope int delegate(ref T) dg)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
@ -551,7 +673,27 @@ class Vector(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v = defaultAllocator.make!(Vector!int)(5, 15, 8);
|
auto v = Vector!int(5, 15, 8);
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
foreach (j, ref e; v)
|
||||||
|
{
|
||||||
|
i = j;
|
||||||
|
}
|
||||||
|
assert(i == 2);
|
||||||
|
|
||||||
|
foreach (j, e; v)
|
||||||
|
{
|
||||||
|
assert(j != 0 || e == 5);
|
||||||
|
assert(j != 1 || e == 15);
|
||||||
|
assert(j != 2 || e == 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
auto v = Vector!int(5, 15, 8);
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
foreach_reverse (j, ref e; v)
|
foreach_reverse (j, ref e; v)
|
||||||
@ -566,7 +708,6 @@ class Vector(T)
|
|||||||
assert(j != 1 || e == 15);
|
assert(j != 1 || e == 15);
|
||||||
assert(j != 0 || e == 5);
|
assert(j != 0 || e == 5);
|
||||||
}
|
}
|
||||||
defaultAllocator.dispose(v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -577,7 +718,7 @@ class Vector(T)
|
|||||||
@property ref inout(T) front() inout
|
@property ref inout(T) front() inout
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(vector.length > 0);
|
assert(!empty);
|
||||||
}
|
}
|
||||||
body
|
body
|
||||||
{
|
{
|
||||||
@ -587,15 +728,13 @@ class Vector(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v = defaultAllocator.make!(Vector!int)(5);
|
auto v = Vector!int(5);
|
||||||
|
|
||||||
assert(v.front == 5);
|
assert(v.front == 5);
|
||||||
|
|
||||||
v.length = 2;
|
v.length = 2;
|
||||||
v[1] = 15;
|
v[1] = 15;
|
||||||
assert(v.front == 5);
|
assert(v.front == 5);
|
||||||
|
|
||||||
defaultAllocator.dispose(v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -606,7 +745,7 @@ class Vector(T)
|
|||||||
@property ref inout(T) back() inout
|
@property ref inout(T) back() inout
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(vector.length > 0);
|
assert(!empty);
|
||||||
}
|
}
|
||||||
body
|
body
|
||||||
{
|
{
|
||||||
@ -616,36 +755,13 @@ class Vector(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v = defaultAllocator.make!(Vector!int)(5);
|
auto v = Vector!int(5);
|
||||||
|
|
||||||
assert(v.back == 5);
|
assert(v.back == 5);
|
||||||
|
|
||||||
v.length = 2;
|
v.length = 2;
|
||||||
v[1] = 15;
|
v[1] = 15;
|
||||||
assert(v.back == 15);
|
assert(v.back == 15);
|
||||||
|
|
||||||
defaultAllocator.dispose(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns: A range that iterates over elements of the container, in
|
|
||||||
* forward order.
|
|
||||||
*/
|
|
||||||
Range!Vector opIndex()
|
|
||||||
{
|
|
||||||
return typeof(return)(this, 0, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Ditto.
|
|
||||||
Range!(const Vector) opIndex() const
|
|
||||||
{
|
|
||||||
return typeof(return)(this, 0, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Ditto.
|
|
||||||
Range!(immutable Vector) opIndex() immutable
|
|
||||||
{
|
|
||||||
return typeof(return)(this, 0, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -658,31 +774,7 @@ class Vector(T)
|
|||||||
*
|
*
|
||||||
* Precondition: $(D_INLINECODE i <= j && j <= length)
|
* Precondition: $(D_INLINECODE i <= j && j <= length)
|
||||||
*/
|
*/
|
||||||
Range!Vector opSlice(in size_t i, in size_t j)
|
Range opSlice(in size_t i, in size_t j)
|
||||||
in
|
|
||||||
{
|
|
||||||
assert(i <= j);
|
|
||||||
assert(j <= length);
|
|
||||||
}
|
|
||||||
body
|
|
||||||
{
|
|
||||||
return typeof(return)(this, i, j);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Ditto.
|
|
||||||
Range!(immutable Vector) opSlice(in size_t i, in size_t j) immutable
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(i <= j);
|
assert(i <= j);
|
||||||
@ -706,7 +798,7 @@ class Vector(T)
|
|||||||
* Precondition: $(D_INLINECODE i <= j && j <= length);
|
* Precondition: $(D_INLINECODE i <= j && j <= length);
|
||||||
* The lenghts of the ranges and slices match.
|
* The lenghts of the ranges and slices match.
|
||||||
*/
|
*/
|
||||||
Range!Vector opSliceAssign(in T value, in size_t i, in size_t j)
|
Range opSliceAssign(in T value, in size_t i, in size_t j)
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(i <= j);
|
assert(i <= j);
|
||||||
@ -719,7 +811,7 @@ class Vector(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
Range!Vector 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
|
in
|
||||||
{
|
{
|
||||||
assert(j - i == value.length);
|
assert(j - i == value.length);
|
||||||
@ -731,7 +823,7 @@ class Vector(T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
Range!Vector opSliceAssign(in T[] value, in size_t i, in size_t j)
|
Range opSliceAssign(in T[] value, in size_t i, in size_t j)
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(j - i == value.length);
|
assert(j - i == value.length);
|
||||||
@ -745,37 +837,32 @@ class Vector(T)
|
|||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v1 = defaultAllocator.make!(Vector!int)(3, 3, 3);
|
auto v1 = Vector!int(3, 3, 3);
|
||||||
auto v2 = defaultAllocator.make!(Vector!int)(1, 2);
|
auto v2 = Vector!int(1, 2);
|
||||||
|
|
||||||
v1[0..2] = 286;
|
v1[0 .. 2] = 286;
|
||||||
assert(v1[0] == 286);
|
assert(v1[0] == 286);
|
||||||
assert(v1[1] == 286);
|
assert(v1[1] == 286);
|
||||||
assert(v1[2] == 3);
|
assert(v1[2] == 3);
|
||||||
|
|
||||||
v2[0..$] = v1[1..3];
|
v2[0 .. $] = v1[1 .. 3];
|
||||||
assert(v2[0] == 286);
|
assert(v2[0] == 286);
|
||||||
assert(v2[1] == 3);
|
assert(v2[1] == 3);
|
||||||
|
|
||||||
defaultAllocator.dispose(v2);
|
|
||||||
defaultAllocator.dispose(v1);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/// Internal representation.
|
|
||||||
protected T[] vector;
|
|
||||||
|
|
||||||
/// The allocator.
|
|
||||||
protected shared Allocator allocator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto v = defaultAllocator.make!(Vector!int)(5, 15, 8);
|
auto v = Vector!int(5, 15, 8);
|
||||||
|
|
||||||
assert(v.front == 5);
|
assert(v.front == 5);
|
||||||
assert(v[1] == 15);
|
assert(v[1] == 15);
|
||||||
assert(v.back == 8);
|
assert(v.back == 8);
|
||||||
|
}
|
||||||
defaultAllocator.dispose(v);
|
|
||||||
|
private unittest
|
||||||
|
{
|
||||||
|
// const Vector!int v;
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.math.mp;
|
module tanya.math.mp;
|
||||||
|
|
||||||
|
import core.exception;
|
||||||
import std.algorithm.iteration;
|
import std.algorithm.iteration;
|
||||||
import std.algorithm.searching;
|
import std.algorithm.searching;
|
||||||
import std.algorithm.mutation;
|
import std.algorithm.mutation;
|
||||||
@ -29,7 +30,7 @@ struct Integer
|
|||||||
|
|
||||||
pure nothrow @safe @nogc invariant
|
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;
|
--size;
|
||||||
}
|
}
|
||||||
if (rep.count)
|
|
||||||
{
|
|
||||||
allocator.resizeArray(rep, size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rep = () @trusted {
|
rep = () @trusted {
|
||||||
return cast(ubyte[]) allocator.allocate(size);
|
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
|
/* 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
|
||||||
big-endian format. */
|
big-endian format. */
|
||||||
|
@ -15,8 +15,10 @@ module tanya.memory.allocator;
|
|||||||
*/
|
*/
|
||||||
interface 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.
|
* Allocates $(D_PARAM size) bytes of memory.
|
||||||
@ -24,9 +26,9 @@ interface Allocator
|
|||||||
* Params:
|
* Params:
|
||||||
* size = Amount of memory to allocate.
|
* 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.
|
* Deallocates a memory block.
|
||||||
@ -36,7 +38,7 @@ interface Allocator
|
|||||||
*
|
*
|
||||||
* Returns: Whether the deallocation was successful.
|
* 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.
|
* Increases or decreases the size of a memory block.
|
||||||
@ -45,7 +47,7 @@ interface Allocator
|
|||||||
* p = A pointer to the memory block.
|
* p = A pointer to the memory block.
|
||||||
* size = Size of the reallocated 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;
|
||||||
}
|
}
|
||||||
|
@ -47,17 +47,8 @@ else version (Windows)
|
|||||||
* | N | -----------> next| || N | | |
|
* | 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:
|
@nogc:
|
||||||
shared static this()
|
shared static this()
|
||||||
@ -80,9 +71,9 @@ class MmapPool : Allocator
|
|||||||
* Params:
|
* Params:
|
||||||
* size = Amount of memory to allocate.
|
* 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)
|
if (!size)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user