mirror of
https://github.com/dlang/phobos.git
synced 2025-05-04 17:11:26 +03:00
add uninitialised slice allocation
This commit is contained in:
parent
00c1cc3b0d
commit
4f871af02f
1 changed files with 151 additions and 55 deletions
|
@ -28,7 +28,7 @@ Params:
|
|||
range = a random access range or an array; only index operator
|
||||
`auto opIndex(size_t index)` is required for ranges. The length of the
|
||||
range should be equal to the sum of shift and the product of
|
||||
lengths. If `allowDownsize`, the length of the
|
||||
lengths. If `ad`, the length of the
|
||||
range should be greater than or equal to the sum of shift and the product of
|
||||
lengths.
|
||||
lengths = list of lengths for each dimension
|
||||
|
@ -37,34 +37,36 @@ Params:
|
|||
Names = names of elements in a slice tuple.
|
||||
Slice tuple is a slice, which holds single set of lengths and strides
|
||||
for a number of ranges.
|
||||
replaceArrayWithPointer = If `yes`, the array will be replaced with
|
||||
ra = If `yes`, the array will be replaced with
|
||||
its pointer to improve performance.
|
||||
Use `no` for compile time function evaluation.
|
||||
|
||||
ad = If `yes`, no assert error will be thrown for range, which
|
||||
has a length and its length is greater then the sum of shift and the product of
|
||||
lengths.
|
||||
Returns:
|
||||
n-dimensional slice
|
||||
+/
|
||||
auto sliced(
|
||||
Flag!"replaceArrayWithPointer" replaceArrayWithPointer = Yes.replaceArrayWithPointer,
|
||||
Flag!"allowDownsize" allowDownsize = No.allowDownsize,
|
||||
Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer,
|
||||
Flag!"allowDownsize" ad = No.allowDownsize,
|
||||
Range, Lengths...)(Range range, Lengths lengths)
|
||||
if (!isStaticArray!Range && !isNarrowString!Range
|
||||
&& allSatisfy!(isIndex, Lengths) && Lengths.length)
|
||||
{
|
||||
return .sliced!(replaceArrayWithPointer, allowDownsize, Lengths.length, Range)(range, [lengths]);
|
||||
return .sliced!(ra, ad, Lengths.length, Range)(range, [lengths]);
|
||||
}
|
||||
|
||||
///ditto
|
||||
auto sliced(
|
||||
Flag!"replaceArrayWithPointer" replaceArrayWithPointer = Yes.replaceArrayWithPointer,
|
||||
Flag!"allowDownsize" allowDownsize = No.allowDownsize,
|
||||
Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer,
|
||||
Flag!"allowDownsize" ad = No.allowDownsize,
|
||||
size_t N, Range)(Range range, auto ref in size_t[N] lengths, size_t shift = 0)
|
||||
if (!isStaticArray!Range && !isNarrowString!Range && N)
|
||||
in
|
||||
{
|
||||
static if (hasLength!Range)
|
||||
{
|
||||
static if (allowDownsize)
|
||||
static if (ad)
|
||||
{
|
||||
assert(lengthsProduct!N(lengths) + shift <= range.length,
|
||||
"Range length must be greater than or equal to the sum of shift and the product of lengths."
|
||||
|
@ -80,7 +82,7 @@ in
|
|||
}
|
||||
body
|
||||
{
|
||||
static if (isDynamicArray!Range && replaceArrayWithPointer)
|
||||
static if (isDynamicArray!Range && ra)
|
||||
{
|
||||
Slice!(N, typeof(range.ptr)) ret = void;
|
||||
ret._ptr = range.ptr + shift;
|
||||
|
@ -141,8 +143,8 @@ template sliced(Names...)
|
|||
mixin (
|
||||
"
|
||||
auto sliced(
|
||||
Flag!`replaceArrayWithPointer` replaceArrayWithPointer = Yes.replaceArrayWithPointer,
|
||||
Flag!`allowDownsize` allowDownsize = No.allowDownsize,
|
||||
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
|
||||
Flag!`allowDownsize` ad = No.allowDownsize,
|
||||
" ~ _Range_Types!Names ~ "
|
||||
Lengths...)
|
||||
(" ~ _Range_DeclarationList!Names ~
|
||||
|
@ -150,12 +152,12 @@ template sliced(Names...)
|
|||
if (allSatisfy!(isIndex, Lengths))
|
||||
{
|
||||
alias sliced = .sliced!Names;
|
||||
return sliced!(replaceArrayWithPointer, allowDownsize)(" ~ _Range_Values!Names ~ "[lengths]);
|
||||
return sliced!(ra, ad)(" ~ _Range_Values!Names ~ "[lengths]);
|
||||
}
|
||||
|
||||
auto sliced(
|
||||
Flag!`replaceArrayWithPointer` replaceArrayWithPointer = Yes.replaceArrayWithPointer,
|
||||
Flag!`allowDownsize` allowDownsize = No.allowDownsize,
|
||||
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
|
||||
Flag!`allowDownsize` ad = No.allowDownsize,
|
||||
size_t N, " ~ _Range_Types!Names ~ ")
|
||||
(" ~ _Range_DeclarationList!Names ~"
|
||||
auto ref in size_t[N] lengths,
|
||||
|
@ -183,7 +185,7 @@ template sliced(Names...)
|
|||
mixin (`alias r = range_` ~ name ~`;`);
|
||||
static if (hasLength!R)
|
||||
{
|
||||
static if (allowDownsize)
|
||||
static if (ad)
|
||||
{
|
||||
assert(minLength <= r.length,
|
||||
`length of range '` ~ name ~`' must be greater than or equal `
|
||||
|
@ -198,24 +200,24 @@ template sliced(Names...)
|
|||
~ tailErrorMessage!());
|
||||
}
|
||||
}
|
||||
static if (isDynamicArray!T && replaceArrayWithPointer)
|
||||
static if (isDynamicArray!T && ra)
|
||||
range.ptrs[i] = r.ptr;
|
||||
else
|
||||
range.ptrs[i] = T(0, r);
|
||||
}
|
||||
return .sliced!(replaceArrayWithPointer, allowDownsize, N, SPT)(range, lengths, shift);
|
||||
return .sliced!(ra, ad, N, SPT)(range, lengths, shift);
|
||||
}
|
||||
~ "}");
|
||||
}
|
||||
|
||||
/// ditto
|
||||
auto sliced(
|
||||
Flag!"replaceArrayWithPointer" replaceArrayWithPointer = Yes.replaceArrayWithPointer,
|
||||
Flag!"allowDownsize" allowDownsize = No.allowDownsize,
|
||||
Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer,
|
||||
Flag!"allowDownsize" ad = No.allowDownsize,
|
||||
Range)(Range range)
|
||||
if (!isStaticArray!Range && !isNarrowString!Range && hasLength!Range)
|
||||
{
|
||||
return .sliced!(replaceArrayWithPointer, allowDownsize, 1, Range)(range, [range.length]);
|
||||
return .sliced!(ra, ad, 1, Range)(range, [range.length]);
|
||||
}
|
||||
|
||||
/// Creates a slice from an array.
|
||||
|
@ -533,28 +535,28 @@ Params:
|
|||
Returns:
|
||||
n-dimensional slice
|
||||
+/
|
||||
Slice!(Lengths.length, Select!(replaceArrayWithPointer, T*, T[]))
|
||||
Slice!(Lengths.length, Select!(ra, T*, T[]))
|
||||
slice(T,
|
||||
Flag!`replaceArrayWithPointer` replaceArrayWithPointer = Yes.replaceArrayWithPointer,
|
||||
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
|
||||
Lengths...)(Lengths lengths)
|
||||
if (allSatisfy!(isIndex, Lengths) && Lengths.length)
|
||||
{
|
||||
return .slice!(T, replaceArrayWithPointer)([lengths]);
|
||||
return .slice!(T, ra)([lengths]);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
Slice!(N, Select!(replaceArrayWithPointer, T*, T[]))
|
||||
Slice!(N, Select!(ra, T*, T[]))
|
||||
slice(T,
|
||||
Flag!`replaceArrayWithPointer` replaceArrayWithPointer = Yes.replaceArrayWithPointer,
|
||||
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
|
||||
size_t N)(auto ref in size_t[N] lengths)
|
||||
{
|
||||
immutable len = lengthsProduct(lengths);
|
||||
return new T[len].sliced!replaceArrayWithPointer(lengths);
|
||||
return new T[len].sliced!ra(lengths);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
auto slice(T,
|
||||
Flag!`replaceArrayWithPointer` replaceArrayWithPointer = Yes.replaceArrayWithPointer,
|
||||
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
|
||||
size_t N)(auto ref in size_t[N] lengths, auto ref T init)
|
||||
{
|
||||
immutable len = lengthsProduct(lengths);
|
||||
|
@ -568,16 +570,16 @@ auto slice(T,
|
|||
auto arr = new T[len];
|
||||
}
|
||||
arr[] = init;
|
||||
auto ret = arr.sliced!replaceArrayWithPointer(lengths);
|
||||
auto ret = arr.sliced!ra(lengths);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// ditto
|
||||
auto slice(
|
||||
Flag!`replaceArrayWithPointer` replaceArrayWithPointer = Yes.replaceArrayWithPointer,
|
||||
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
|
||||
size_t N, Range)(auto ref Slice!(N, Range) slice)
|
||||
{
|
||||
auto ret = .slice!(Unqual!(slice.DeepElemType), replaceArrayWithPointer)(slice.shape);
|
||||
auto ret = .slice!(Unqual!(slice.DeepElemType), ra)(slice.shape);
|
||||
ret[] = slice;
|
||||
return ret;
|
||||
}
|
||||
|
@ -610,6 +612,43 @@ pure nothrow unittest
|
|||
assert(tensor == [[0, 1, 2], [3, 4, 5]]);
|
||||
}
|
||||
|
||||
/++
|
||||
Creates an uninitialized array and an n-dimensional slice over it.
|
||||
Params:
|
||||
lengths = list of lengths for each dimension
|
||||
slice = slice to copy shape and data from
|
||||
Returns:
|
||||
uninitialized n-dimensional slice
|
||||
+/
|
||||
Slice!(Lengths.length, Select!(ra, T*, T[]))
|
||||
uninitializedSlice(T,
|
||||
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
|
||||
Lengths...)(Lengths lengths)
|
||||
if (allSatisfy!(isIndex, Lengths) && Lengths.length)
|
||||
{
|
||||
return .uninitializedSlice!(T, ra)([lengths]);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
auto uninitializedSlice(T,
|
||||
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
|
||||
size_t N)(auto ref in size_t[N] lengths)
|
||||
{
|
||||
immutable len = lengthsProduct(lengths);
|
||||
import std.array : uninitializedArray;
|
||||
auto arr = uninitializedArray!(T[])(len);
|
||||
return arr.sliced!ra(lengths);
|
||||
}
|
||||
|
||||
///
|
||||
pure nothrow unittest
|
||||
{
|
||||
auto tensor = uninitializedSlice!int(5, 6, 7);
|
||||
assert(tensor.length == 5);
|
||||
assert(tensor.elementsCount == 5 * 6 * 7);
|
||||
static assert(is(typeof(tensor) == Slice!(3, int*)));
|
||||
}
|
||||
|
||||
/++
|
||||
Allocates an array through a specified allocator and creates an n-dimensional slice over it.
|
||||
See also $(MREF std, experimental, allocator).
|
||||
|
@ -621,65 +660,66 @@ Params:
|
|||
Returns:
|
||||
a structure with fields `array` and `slice`
|
||||
+/
|
||||
auto makeSlice(T,
|
||||
Flag!`replaceArrayWithPointer` replaceArrayWithPointer = Yes.replaceArrayWithPointer,
|
||||
SliceAllocationResult!(Lengths.length, T, ra)
|
||||
makeSlice(T,
|
||||
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
|
||||
Allocator,
|
||||
Lengths...)(auto ref Allocator alloc, Lengths lengths)
|
||||
if (allSatisfy!(isIndex, Lengths) && Lengths.length)
|
||||
{
|
||||
return .makeSlice!(T, replaceArrayWithPointer, Allocator)(alloc, [lengths]);
|
||||
return .makeSlice!(T, ra, Allocator)(alloc, [lengths]);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
auto makeSlice(
|
||||
Flag!`replaceArrayWithPointer` replaceArrayWithPointer = Yes.replaceArrayWithPointer,
|
||||
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
|
||||
Allocator,
|
||||
size_t N, Range)(auto ref Allocator alloc, auto ref Slice!(N, Range) slice)
|
||||
{
|
||||
alias T = Unqual!(slice.DeepElemType);
|
||||
return makeSlice!(T, replaceArrayWithPointer)(alloc, slice);
|
||||
return makeSlice!(T, ra)(alloc, slice);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
auto makeSlice(T,
|
||||
Flag!`replaceArrayWithPointer` replaceArrayWithPointer = Yes.replaceArrayWithPointer,
|
||||
SliceAllocationResult!(N, T, ra)
|
||||
makeSlice(T,
|
||||
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
|
||||
Allocator,
|
||||
size_t N)(auto ref Allocator alloc, auto ref in size_t[N] lengths)
|
||||
{
|
||||
import std.experimental.allocator : makeArray;
|
||||
static struct Result { T[] array; Slice!(N, Select!(replaceArrayWithPointer, T*, T[])) slice; }
|
||||
immutable len = lengthsProduct(lengths);
|
||||
auto array = alloc.makeArray!T(len);
|
||||
auto slice = array.sliced!replaceArrayWithPointer(lengths);
|
||||
return Result(array, slice);
|
||||
auto slice = array.sliced!ra(lengths);
|
||||
return typeof(return)(array, slice);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
auto makeSlice(T,
|
||||
Flag!`replaceArrayWithPointer` replaceArrayWithPointer = Yes.replaceArrayWithPointer,
|
||||
SliceAllocationResult!(N, T, ra)
|
||||
makeSlice(T,
|
||||
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
|
||||
Allocator,
|
||||
size_t N)(auto ref Allocator alloc, auto ref in size_t[N] lengths, auto ref T init)
|
||||
{
|
||||
import std.experimental.allocator : makeArray;
|
||||
static struct Result { T[] array; Slice!(N, Select!(replaceArrayWithPointer, T*, T[])) slice; }
|
||||
immutable len = lengthsProduct(lengths);
|
||||
auto array = alloc.makeArray!T(len, init);
|
||||
auto slice = array.sliced!replaceArrayWithPointer(lengths);
|
||||
return Result(array, slice);
|
||||
auto slice = array.sliced!ra(lengths);
|
||||
return typeof(return)(array, slice);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
auto makeSlice(T,
|
||||
Flag!`replaceArrayWithPointer` replaceArrayWithPointer = Yes.replaceArrayWithPointer,
|
||||
SliceAllocationResult!(N, T, ra)
|
||||
makeSlice(T,
|
||||
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
|
||||
Allocator,
|
||||
size_t N, Range)(auto ref Allocator alloc, auto ref Slice!(N, Range) slice)
|
||||
{
|
||||
import std.experimental.allocator : makeArray;
|
||||
import std.experimental.ndslice.selection : byElement;
|
||||
static struct Result { T[] array; Slice!(N, Select!(replaceArrayWithPointer, T*, T[])) slice; }
|
||||
auto array = alloc.makeArray!T(slice.byElement);
|
||||
auto _slice = array.sliced!replaceArrayWithPointer(slice.shape);
|
||||
return Result(array, _slice);
|
||||
auto _slice = array.sliced!ra(slice.shape);
|
||||
return typeof(return)(array, _slice);
|
||||
}
|
||||
|
||||
///
|
||||
|
@ -690,9 +730,6 @@ auto makeSlice(T,
|
|||
|
||||
auto tup = makeSlice!int(Mallocator.instance, 2, 3, 4);
|
||||
|
||||
static assert(is(typeof(tup.array) == int[]));
|
||||
static assert(is(typeof(tup.slice) == Slice!(3, int*)));
|
||||
|
||||
assert(tup.array.length == 24);
|
||||
assert(tup.slice.elementsCount == 24);
|
||||
assert(tup.array.ptr == &tup.slice[0, 0, 0]);
|
||||
|
@ -718,7 +755,6 @@ auto makeSlice(T,
|
|||
Mallocator.instance.dispose(tup.array);
|
||||
}
|
||||
|
||||
|
||||
@nogc unittest
|
||||
{
|
||||
import std.experimental.allocator;
|
||||
|
@ -731,6 +767,66 @@ auto makeSlice(T,
|
|||
Mallocator.instance.dispose(tup.array);
|
||||
}
|
||||
|
||||
/++
|
||||
Allocates an uninitialized array through a specified allocator and creates an n-dimensional slice over it.
|
||||
See also $(MREF std, experimental, allocator).
|
||||
Params:
|
||||
alloc = allocator
|
||||
lengths = list of lengths for each dimension
|
||||
init = default value for array initialization
|
||||
slice = slice to copy shape and data from
|
||||
Returns:
|
||||
a structure with fields `array` and `slice`
|
||||
+/
|
||||
SliceAllocationResult!(Lengths.length, T, ra)
|
||||
makeUninitializedSlice(T,
|
||||
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
|
||||
Allocator,
|
||||
Lengths...)(auto ref Allocator alloc, Lengths lengths)
|
||||
if (allSatisfy!(isIndex, Lengths) && Lengths.length)
|
||||
{
|
||||
return .makeUninitializedSlice!(T, ra, Allocator)(alloc, [lengths]);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
SliceAllocationResult!(N, T, ra)
|
||||
makeUninitializedSlice(T,
|
||||
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
|
||||
Allocator,
|
||||
size_t N)(auto ref Allocator alloc, auto ref in size_t[N] lengths)
|
||||
{
|
||||
immutable len = lengthsProduct(lengths);
|
||||
auto array = cast(T[]) alloc.allocate(len * T.sizeof);
|
||||
auto slice = array.sliced!ra(lengths);
|
||||
return typeof(return)(array, slice);
|
||||
}
|
||||
|
||||
///
|
||||
@nogc unittest
|
||||
{
|
||||
import std.experimental.allocator;
|
||||
import std.experimental.allocator.mallocator;
|
||||
|
||||
auto tup = makeUninitializedSlice!int(Mallocator.instance, 2, 3, 4);
|
||||
|
||||
assert(tup.array.length == 24);
|
||||
assert(tup.slice.elementsCount == 24);
|
||||
assert(tup.array.ptr == &tup.slice[0, 0, 0]);
|
||||
|
||||
Mallocator.instance.dispose(tup.array);
|
||||
}
|
||||
|
||||
/++
|
||||
Structure used by $(LREF makeSlice) and $(LREF makeUninitializedSlice).
|
||||
+/
|
||||
struct SliceAllocationResult(size_t N, T, Flag!`replaceArrayWithPointer` ra)
|
||||
{
|
||||
///
|
||||
T[] array;
|
||||
///
|
||||
Slice!(N, Select!(ra, T*, T[])) slice;
|
||||
}
|
||||
|
||||
/++
|
||||
Creates a common n-dimensional array from a slice.
|
||||
Params:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue