reduce ndslice template bloat part 1

This commit is contained in:
Ilya Yaroshenko 2016-09-30 00:49:02 +02:00
parent 81c09ed1c1
commit c39ec4cd43
4 changed files with 106 additions and 261 deletions

View file

@ -334,42 +334,6 @@ enum indexError(size_t pos, size_t N) =
~ " from the range [0 .." ~ N.stringof ~ ")" ~ " from the range [0 .." ~ N.stringof ~ ")"
~ " must be less than corresponding length."; ~ " must be less than corresponding length.";
enum indexStrideCode = q{
static if (_indexes.length)
{
size_t stride = _strides[0] * _indexes[0];
assert(_indexes[0] < _lengths[0], indexError!(0, N));
foreach (i; Iota!(1, N)) //static
{
assert(_indexes[i] < _lengths[i], indexError!(i, N));
stride += _strides[i] * _indexes[i];
}
return stride;
}
else
{
return 0;
}
};
enum mathIndexStrideCode = q{
static if (_indexes.length)
{
size_t stride = _strides[0] * _indexes[N - 1];
assert(_indexes[N - 1] < _lengths[0], indexError!(N - 1, N));
foreach_reverse (i; Iota!(0, N - 1)) //static
{
assert(_indexes[i] < _lengths[N - 1 - i], indexError!(i, N));
stride += _strides[N - 1 - i] * _indexes[i];
}
return stride;
}
else
{
return 0;
}
};
enum string tailErrorMessage( enum string tailErrorMessage(
string fun = __FUNCTION__, string fun = __FUNCTION__,
string pfun = __PRETTY_FUNCTION__) = string pfun = __PRETTY_FUNCTION__) =

View file

@ -329,7 +329,7 @@ Returns:
n-dimensional slice of the same type n-dimensional slice of the same type
See_also: $(LREF swapped), $(LREF transposed) See_also: $(LREF swapped), $(LREF transposed)
+/ +/
Slice!(N, Range) everted(size_t N, Range)(auto ref Slice!(N, Range) slice) Slice!(N, Range) everted(size_t N, Range)(Slice!(N, Range) slice)
{ {
mixin _DefineRet; mixin _DefineRet;
with (slice) with (slice)
@ -378,7 +378,7 @@ private enum _transposedCode = q{
} }
}; };
private size_t[N] completeTranspose(size_t N)(in size_t[] dimensions) private size_t[N] completeTranspose(size_t N)(size_t[] dimensions)
{ {
assert(dimensions.length <= N); assert(dimensions.length <= N);
size_t[N] ctr; size_t[N] ctr;
@ -410,7 +410,7 @@ See_also: $(LREF swapped), $(LREF everted)
template transposed(Dimensions...) template transposed(Dimensions...)
if (Dimensions.length) if (Dimensions.length)
{ {
@fmb Slice!(N, Range) transposed(size_t N, Range)(auto ref Slice!(N, Range) slice) @fmb Slice!(N, Range) transposed(size_t N, Range)(Slice!(N, Range) slice)
{ {
mixin DimensionsCountCTError; mixin DimensionsCountCTError;
foreach (i, dimension; Dimensions) foreach (i, dimension; Dimensions)
@ -425,22 +425,7 @@ template transposed(Dimensions...)
} }
///ditto ///ditto
Slice!(N, Range) transposed(size_t N, Range)(auto ref Slice!(N, Range) slice, size_t dimension) Slice!(N, Range) transposed(size_t N, Range, size_t M)(Slice!(N, Range) slice, size_t[M] dimensions...)
in
{
mixin (DimensionRTError);
}
body
{
size_t[1] permutation = void;
permutation[0] = dimension;
immutable perm = completeTranspose!N(permutation);
assert(perm.isPermutation, __PRETTY_FUNCTION__ ~ ": internal error.");
mixin (_transposedCode);
}
///ditto
Slice!(N, Range) transposed(size_t N, Range)(auto ref Slice!(N, Range) slice, in size_t[] dimensions...)
in in
{ {
mixin (DimensionsCountRTError); mixin (DimensionsCountRTError);
@ -458,7 +443,7 @@ body
} }
///ditto ///ditto
Slice!(2, Range) transposed(Range)(auto ref Slice!(2, Range) slice) Slice!(2, Range) transposed(Range)(Slice!(2, Range) slice)
{ {
return .transposed!(1, 0)(slice); return .transposed!(1, 0)(slice);
} }
@ -564,19 +549,7 @@ template reversed(Dimensions...)
} }
///ditto ///ditto
Slice!(N, Range) reversed(size_t N, Range)(Slice!(N, Range) slice, size_t dimension) Slice!(N, Range) reversed(size_t N, Range, size_t M)(Slice!(N, Range) slice, size_t[M] dimensions...)
in
{
mixin (DimensionRTError);
}
body
{
mixin (_reversedCode);
return slice;
}
///ditto
Slice!(N, Range) reversed(size_t N, Range)(Slice!(N, Range) slice, in size_t[] dimensions...)
in in
{ {
foreach (dimension; dimensions) foreach (dimension; dimensions)
@ -584,8 +557,11 @@ in
} }
body body
{ {
foreach (dimension; dimensions) foreach (i; Iota!(0, M))
{
auto dimension = dimensions[i];
mixin (_reversedCode); mixin (_reversedCode);
}
return slice; return slice;
} }
@ -904,19 +880,7 @@ template dropOne(Dimensions...)
} }
///ditto ///ditto
Slice!(N, Range) dropOne(size_t N, Range)(Slice!(N, Range) slice, size_t dimension) Slice!(N, Range) dropOne(size_t N, Range, size_t M)(Slice!(N, Range) slice, size_t[M] dimensions...)
in
{
mixin (DimensionRTError);
}
body
{
slice.popFront(dimension);
return slice;
}
///ditto
Slice!(N, Range) dropOne(size_t N, Range)(Slice!(N, Range) slice, in size_t[] dimensions...)
in in
{ {
foreach (dimension; dimensions) foreach (dimension; dimensions)
@ -924,8 +888,11 @@ in
} }
body body
{ {
foreach (dimension; dimensions) foreach (i; Iota!(0, M))
{
auto dimension = dimensions[i];
slice.popFront(dimension); slice.popFront(dimension);
}
return slice; return slice;
} }
@ -945,19 +912,7 @@ template dropBackOne(Dimensions...)
} }
///ditto ///ditto
Slice!(N, Range) dropBackOne(size_t N, Range)(Slice!(N, Range) slice, size_t dimension) Slice!(N, Range) dropBackOne(size_t N, Range, size_t M)(Slice!(N, Range) slice, size_t[M] dimensions...)
in
{
mixin (DimensionRTError);
}
body
{
slice.popBack(dimension);
return slice;
}
///ditto
Slice!(N, Range) dropBackOne(size_t N, Range)(Slice!(N, Range) slice, in size_t[] dimensions...)
in in
{ {
foreach (dimension; dimensions) foreach (dimension; dimensions)
@ -965,8 +920,11 @@ in
} }
body body
{ {
foreach (dimension; dimensions) foreach (i; Iota!(0, M))
{
auto dimension = dimensions[i];
slice.popBack(dimension); slice.popBack(dimension);
}
return slice; return slice;
} }

View file

@ -75,7 +75,7 @@ Returns:
+/ +/
template pack(K...) template pack(K...)
{ {
@fmb auto pack(size_t N, Range)(auto ref Slice!(N, Range) slice) @fmb auto pack(size_t N, Range)(Slice!(N, Range) slice)
{ {
template Template(size_t NInner, Range, R...) template Template(size_t NInner, Range, R...)
{ {
@ -174,7 +174,7 @@ Returns:
See_also: $(LREF pack), $(LREF evertPack) See_also: $(LREF pack), $(LREF evertPack)
+/ +/
Slice!(N, Range).PureThis unpack(size_t N, Range)(auto ref Slice!(N, Range) slice) Slice!(N, Range).PureThis unpack(size_t N, Range)(Slice!(N, Range) slice)
{ {
with (slice) return PureThis(_lengths, _strides, _ptr); with (slice) return PureThis(_lengths, _strides, _ptr);
} }
@ -200,7 +200,7 @@ Returns:
See_also: $(LREF pack), $(LREF unpack) See_also: $(LREF pack), $(LREF unpack)
+/ +/
SliceFromSeq!(Slice!(N, Range).PureRange, NSeqEvert!(Slice!(N, Range).NSeq)) SliceFromSeq!(Slice!(N, Range).PureRange, NSeqEvert!(Slice!(N, Range).NSeq))
evertPack(size_t N, Range)(auto ref Slice!(N, Range) slice) evertPack(size_t N, Range)(Slice!(N, Range) slice)
{ {
mixin _DefineRet; mixin _DefineRet;
static assert(Ret.NSeq.length > 0); static assert(Ret.NSeq.length > 0);
@ -294,7 +294,7 @@ Params:
Returns: Returns:
1-dimensional slice composed of diagonal elements 1-dimensional slice composed of diagonal elements
+/ +/
Slice!(1, Range) diagonal(size_t N, Range)(auto ref Slice!(N, Range) slice) Slice!(1, Range) diagonal(size_t N, Range)(Slice!(N, Range) slice)
{ {
auto NewN = slice.PureN - N + 1; auto NewN = slice.PureN - N + 1;
mixin _DefineRet; mixin _DefineRet;
@ -472,8 +472,7 @@ Params:
Returns: Returns:
packed `N`-dimensional slice composed of `N`-dimensional slices packed `N`-dimensional slice composed of `N`-dimensional slices
+/ +/
Slice!(N, Slice!(N+1, Range)) blocks(size_t N, Range, Lengths...)(auto ref Slice!(N, Range) slice, Lengths lengths) Slice!(N, Slice!(N+1, Range)) blocks(size_t N, Range)(Slice!(N, Range) slice, size_t[N] lengths...)
if (allSatisfy!(isIndex, Lengths) && Lengths.length == N)
in in
{ {
foreach (i, length; lengths) foreach (i, length; lengths)
@ -594,8 +593,7 @@ Params:
Returns: Returns:
packed `N`-dimensional slice composed of `N`-dimensional slices packed `N`-dimensional slice composed of `N`-dimensional slices
+/ +/
Slice!(N, Slice!(N+1, Range)) windows(size_t N, Range, Lengths...)(auto ref Slice!(N, Range) slice, Lengths lengths) Slice!(N, Slice!(N+1, Range)) windows(size_t N, Range)(Slice!(N, Range) slice, size_t[N] lengths...)
if (allSatisfy!(isIndex, Lengths) && Lengths.length == N)
in in
{ {
foreach (i, length; lengths) foreach (i, length; lengths)
@ -721,11 +719,10 @@ Returns:
Throws: Throws:
$(LREF ReshapeException) if the slice cannot be reshaped with the input lengths. $(LREF ReshapeException) if the slice cannot be reshaped with the input lengths.
+/ +/
Slice!(Lengths.length, Range) Slice!(M, Range)
reshape reshape
( size_t N, Range , Lengths... ) (size_t N, Range, size_t M)
(auto ref Slice!(N, Range) slice, Lengths lengths) (Slice!(N, Range) slice, size_t[M] lengths...)
if ( allSatisfy!(isIndex, Lengths) && Lengths.length)
{ {
mixin _DefineRet; mixin _DefineRet;
foreach (i; Iota!(0, ret.N)) foreach (i; Iota!(0, ret.N))
@ -821,14 +818,13 @@ pure unittest
import std.experimental.ndslice.iteration : reversed; import std.experimental.ndslice.iteration : reversed;
import std.array : array; import std.array : array;
auto reshape2(S, L...)(S slice, L lengths) auto reshape2(S, size_t M)(S slice, size_t[M] lengths...)
{ {
// Tries to reshape without allocation // Tries to reshape without allocation
try return slice.reshape(lengths); try return slice.reshape(lengths);
catch (ReshapeException e) catch (ReshapeException e)
//allocates the elements and creates a slice // Allocates
//Note: -1 length is not supported by reshape2 return slice.slice.reshape(lengths);
return slice.byElement.array.sliced(lengths);
} }
auto slice = auto slice =
@ -923,7 +919,7 @@ Params:
Returns: Returns:
random access range composed of elements of the `slice` random access range composed of elements of the `slice`
+/ +/
auto byElement(size_t N, Range)(auto ref Slice!(N, Range) slice) auto byElement(size_t N, Range)(Slice!(N, Range) slice)
{ {
with (Slice!(N, Range)) with (Slice!(N, Range))
{ {
@ -1177,7 +1173,7 @@ auto byElement(size_t N, Range)(auto ref Slice!(N, Range) slice)
} }
/// ditto /// ditto
Slice!(1, Range) byElement(size_t N : 1, Range)(auto ref Slice!(N, Range) slice) Slice!(1, Range) byElement(size_t N : 1, Range)(Slice!(N, Range) slice)
{ {
return slice; return slice;
} }
@ -1430,7 +1426,7 @@ Params:
Returns: Returns:
forward range composed of all elements of standard simplex of the `slice` forward range composed of all elements of standard simplex of the `slice`
+/ +/
auto byElementInStandardSimplex(size_t N, Range)(auto ref Slice!(N, Range) slice, size_t maxHypercubeLength = size_t.max) auto byElementInStandardSimplex(size_t N, Range)(Slice!(N, Range) slice, size_t maxHypercubeLength = size_t.max)
{ {
with (Slice!(N, Range)) with (Slice!(N, Range))
{ {
@ -1518,7 +1514,7 @@ auto byElementInStandardSimplex(size_t N, Range)(auto ref Slice!(N, Range) slice
} }
/// ditto /// ditto
Slice!(1, Range) byElementInStandardSimplex(size_t N : 1, Range)(auto ref Slice!(N, Range) slice, size_t maxHypercubeLength = size_t.max) Slice!(1, Range) byElementInStandardSimplex(size_t N : 1, Range)(Slice!(N, Range) slice, size_t maxHypercubeLength = size_t.max)
{ {
if (maxHypercubeLength > slice._lengths[0]) if (maxHypercubeLength > slice._lengths[0])
maxHypercubeLength = slice._lengths[0]; maxHypercubeLength = slice._lengths[0];
@ -1617,14 +1613,7 @@ Returns:
`N`-dimensional slice composed of indexes `N`-dimensional slice composed of indexes
See_also: $(LREF IndexSlice), $(LREF iotaSlice) See_also: $(LREF IndexSlice), $(LREF iotaSlice)
+/ +/
IndexSlice!(Lengths.length) indexSlice(Lengths...)(Lengths lengths) IndexSlice!N indexSlice(size_t N)(size_t[N] lengths...)
if (allSatisfy!(isIndex, Lengths))
{
return .indexSlice!(Lengths.length)([lengths]);
}
///ditto
IndexSlice!N indexSlice(size_t N)(auto ref size_t[N] lengths)
{ {
import std.experimental.ndslice.slice : sliced; import std.experimental.ndslice.slice : sliced;
with (typeof(return)) return Range(lengths[1 .. $]).sliced(lengths); with (typeof(return)) return Range(lengths[1 .. $]).sliced(lengths);
@ -1715,21 +1704,20 @@ Returns:
`N`-dimensional slice composed of indexes `N`-dimensional slice composed of indexes
See_also: $(LREF IotaSlice), $(LREF indexSlice) See_also: $(LREF IotaSlice), $(LREF indexSlice)
+/ +/
IotaSlice!(Lengths.length) iotaSlice(Lengths...)(Lengths lengths) IotaSlice!N iotaSlice(size_t N)(size_t[N] lengths...)
if (allSatisfy!(isIndex, Lengths))
{ {
return .iotaSlice!(Lengths.length)([lengths]); return .iotaSlice(lengths, 0);
} }
///ditto ///ditto
IotaSlice!N iotaSlice(size_t N)(auto ref size_t[N] lengths, size_t shift = 0) IotaSlice!N iotaSlice(size_t N)(size_t[N] lengths, size_t shift)
{ {
import std.experimental.ndslice.slice : sliced; import std.experimental.ndslice.slice : sliced;
return IotaMap!().init.sliced(lengths, shift); return IotaMap!().init.sliced(lengths, shift);
} }
///ditto ///ditto
IotaSlice!N iotaSlice(size_t N)(auto ref size_t[N] lengths, size_t shift, size_t step) IotaSlice!N iotaSlice(size_t N)(size_t[N] lengths, size_t shift, size_t step)
{ {
auto iota = iotaSlice(lengths, shift); auto iota = iotaSlice(lengths, shift);
foreach (i; Iota!(0, N)) foreach (i; Iota!(0, N))
@ -1806,8 +1794,8 @@ Returns:
`n`-dimensional slice composed of identical values, where `n` is dimension count. `n`-dimensional slice composed of identical values, where `n` is dimension count.
See_also: $(REF repeat, std,range) See_also: $(REF repeat, std,range)
+/ +/
RepeatSlice!(Lengths.length, T) repeatSlice(T, Lengths...)(T value, Lengths lengths) RepeatSlice!(M, T) repeatSlice(T, size_t M)(T value, size_t[M] lengths...)
if (allSatisfy!(isIndex, Lengths) && !is(T : Slice!(N, Range), size_t N, Range)) if (!is(T : Slice!(N, Range), size_t N, Range))
{ {
typeof(return) ret; typeof(return) ret;
foreach (i; Iota!(0, ret.N)) foreach (i; Iota!(0, ret.N))
@ -1817,10 +1805,8 @@ RepeatSlice!(Lengths.length, T) repeatSlice(T, Lengths...)(T value, Lengths leng
} }
/// ditto /// ditto
Slice!(Lengths.length, Slice!(N + 1, Range)) repeatSlice(size_t N, Range, Lengths...)(auto ref Slice!(N, Range) slice, Lengths lengths) Slice!(M, Slice!(N + 1, Range)) repeatSlice(size_t N, Range, size_t M)(Slice!(N, Range) slice, size_t[M] lengths...)
if (allSatisfy!(isIndex, Lengths) && Lengths.length)
{ {
enum M = Lengths.length;
typeof(return) ret; typeof(return) ret;
ret._ptr = slice._ptr; ret._ptr = slice._ptr;
foreach (i; Iota!(0, M)) foreach (i; Iota!(0, M))
@ -1975,7 +1961,7 @@ template mapSlice(fun...)
{ {
/// ///
@fmb auto mapSlice(size_t N, Range) @fmb auto mapSlice(size_t N, Range)
(auto ref Slice!(N, Range) tensor) (Slice!(N, Range) tensor)
{ {
// this static if-else block // this static if-else block
// may be unified with std.algorithms.iteration.map // may be unified with std.algorithms.iteration.map

View file

@ -49,18 +49,17 @@ Returns:
auto sliced( auto sliced(
Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer, Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer,
Flag!"allowDownsize" ad = No.allowDownsize, Flag!"allowDownsize" ad = No.allowDownsize,
Range, Lengths...)(Range range, Lengths lengths) Range, size_t N)(Range range, size_t[N] lengths...)
if (!isStaticArray!Range && !isNarrowString!Range if (!isStaticArray!Range && !isNarrowString!Range && N)
&& allSatisfy!(isIndex, Lengths) && Lengths.length)
{ {
return .sliced!(ra, ad, Lengths.length, Range)(range, [lengths]); return .sliced!(ra, ad)(range, lengths, 0);
} }
///ditto ///ditto
auto sliced( auto sliced(
Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer, Flag!"replaceArrayWithPointer" ra = Yes.replaceArrayWithPointer,
Flag!"allowDownsize" ad = No.allowDownsize, Flag!"allowDownsize" ad = No.allowDownsize,
size_t N, Range)(Range range, auto ref in size_t[N] lengths, size_t shift = 0) size_t N, Range)(Range range, size_t[N] lengths, size_t shift = 0)
if (!isStaticArray!Range && !isNarrowString!Range && N) if (!isStaticArray!Range && !isNarrowString!Range && N)
in in
{ {
@ -146,13 +145,12 @@ template sliced(Names...)
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer, Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
Flag!`allowDownsize` ad = No.allowDownsize, Flag!`allowDownsize` ad = No.allowDownsize,
" ~ _Range_Types!Names ~ " " ~ _Range_Types!Names ~ "
Lengths...) size_t N)
(" ~ _Range_DeclarationList!Names ~ (" ~ _Range_DeclarationList!Names ~
"Lengths lengths) "size_t[N] lengths...)
if (allSatisfy!(isIndex, Lengths))
{ {
alias sliced = .sliced!Names; alias sl = .sliced!Names;
return sliced!(ra, ad)(" ~ _Range_Values!Names ~ "[lengths]); return sl!(ra, ad)(" ~ _Range_Values!Names ~ "lengths, 0);
} }
auto sliced( auto sliced(
@ -160,7 +158,7 @@ template sliced(Names...)
Flag!`allowDownsize` ad = No.allowDownsize, Flag!`allowDownsize` ad = No.allowDownsize,
size_t N, " ~ _Range_Types!Names ~ ") size_t N, " ~ _Range_Types!Names ~ ")
(" ~ _Range_DeclarationList!Names ~" (" ~ _Range_DeclarationList!Names ~"
auto ref in size_t[N] lengths, size_t[N] lengths,
size_t shift = 0) size_t shift = 0)
{ {
alias RS = AliasSeq!(" ~ _Range_Types!Names ~ ");" alias RS = AliasSeq!(" ~ _Range_Types!Names ~ ");"
@ -535,20 +533,10 @@ Params:
Returns: Returns:
n-dimensional slice n-dimensional slice
+/ +/
Slice!(Lengths.length, Select!(ra, T*, T[]))
slice(T,
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
Lengths...)(Lengths lengths)
if (allSatisfy!(isIndex, Lengths) && Lengths.length)
{
return .slice!(T, ra)([lengths]);
}
/// ditto
Slice!(N, Select!(ra, T*, T[])) Slice!(N, Select!(ra, T*, T[]))
slice(T, slice(T,
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer, Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
size_t N)(auto ref in size_t[N] lengths) size_t N)(size_t[N] lengths...)
{ {
immutable len = lengthsProduct(lengths); immutable len = lengthsProduct(lengths);
return new T[len].sliced!ra(lengths); return new T[len].sliced!ra(lengths);
@ -557,7 +545,7 @@ slice(T,
/// ditto /// ditto
auto slice(T, auto slice(T,
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer, Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
size_t N)(auto ref in size_t[N] lengths, auto ref T init) size_t N)(size_t[N] lengths, T init)
{ {
immutable len = lengthsProduct(lengths); immutable len = lengthsProduct(lengths);
static if (ra && !hasElaborateAssign!T) static if (ra && !hasElaborateAssign!T)
@ -577,7 +565,7 @@ auto slice(T,
/// ditto /// ditto
auto slice( auto slice(
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer, Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
size_t N, Range)(auto ref Slice!(N, Range) slice) size_t N, Range)(Slice!(N, Range) slice)
{ {
auto ret = .slice!(Unqual!(slice.DeepElemType), ra)(slice.shape); auto ret = .slice!(Unqual!(slice.DeepElemType), ra)(slice.shape);
ret[] = slice; ret[] = slice;
@ -620,19 +608,9 @@ Params:
Returns: Returns:
uninitialized n-dimensional slice 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, auto uninitializedSlice(T,
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer, Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
size_t N)(auto ref in size_t[N] lengths) size_t N)(size_t[N] lengths...)
{ {
immutable len = lengthsProduct(lengths); immutable len = lengthsProduct(lengths);
import std.array : uninitializedArray; import std.array : uninitializedArray;
@ -662,21 +640,10 @@ Returns:
Note: Note:
`makeSlice` always returns slice with mutable elements `makeSlice` always returns slice with mutable elements
+/ +/
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, ra, Allocator)(alloc, [lengths]);
}
/// ditto
auto makeSlice( auto makeSlice(
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer, Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
Allocator, Allocator,
size_t N, Range)(auto ref Allocator alloc, auto ref Slice!(N, Range) slice) size_t N, Range)(auto ref Allocator alloc, Slice!(N, Range) slice)
{ {
alias T = Unqual!(slice.DeepElemType); alias T = Unqual!(slice.DeepElemType);
return makeSlice!(T, ra)(alloc, slice); return makeSlice!(T, ra)(alloc, slice);
@ -687,7 +654,7 @@ SliceAllocationResult!(N, T, ra)
makeSlice(T, makeSlice(T,
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer, Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
Allocator, Allocator,
size_t N)(auto ref Allocator alloc, auto ref in size_t[N] lengths) size_t N)(auto ref Allocator alloc, size_t[N] lengths...)
{ {
import std.experimental.allocator : makeArray; import std.experimental.allocator : makeArray;
immutable len = lengthsProduct(lengths); immutable len = lengthsProduct(lengths);
@ -701,7 +668,7 @@ SliceAllocationResult!(N, T, ra)
makeSlice(T, makeSlice(T,
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer, Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
Allocator, Allocator,
size_t N)(auto ref Allocator alloc, auto ref in size_t[N] lengths, auto ref T init) size_t N)(auto ref Allocator alloc, size_t[N] lengths, T init)
{ {
import std.experimental.allocator : makeArray; import std.experimental.allocator : makeArray;
immutable len = lengthsProduct(lengths); immutable len = lengthsProduct(lengths);
@ -715,7 +682,7 @@ SliceAllocationResult!(N, T, ra)
makeSlice(T, makeSlice(T,
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer, Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
Allocator, Allocator,
size_t N, Range)(auto ref Allocator alloc, auto ref Slice!(N, Range) slice) size_t N, Range)(auto ref Allocator alloc, Slice!(N, Range) slice)
{ {
import std.experimental.allocator : makeArray; import std.experimental.allocator : makeArray;
import std.experimental.ndslice.selection : byElement; import std.experimental.ndslice.selection : byElement;
@ -780,22 +747,11 @@ Params:
Returns: Returns:
a structure with fields `array` and `slice` 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) SliceAllocationResult!(N, T, ra)
makeUninitializedSlice(T, makeUninitializedSlice(T,
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer, Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
Allocator, Allocator,
size_t N)(auto ref Allocator alloc, auto ref in size_t[N] lengths) size_t N)(auto ref Allocator alloc, size_t[N] lengths...)
{ {
immutable len = lengthsProduct(lengths); immutable len = lengthsProduct(lengths);
auto array = cast(T[]) alloc.allocate(len * T.sizeof); auto array = cast(T[]) alloc.allocate(len * T.sizeof);
@ -836,7 +792,7 @@ Params:
Returns: Returns:
multidimensional D array multidimensional D array
+/ +/
auto ndarray(size_t N, Range)(auto ref Slice!(N, Range) slice) auto ndarray(size_t N, Range)(Slice!(N, Range) slice)
{ {
import std.array : array; import std.array : array;
static if (N == 1) static if (N == 1)
@ -1267,25 +1223,42 @@ struct Slice(size_t _N, _Range)
return _strides[dimension] * (_lengths[dimension] - 1); return _strides[dimension] * (_lengths[dimension] - 1);
} }
size_t indexStride(Indexes...)(Indexes _indexes) const size_t indexStride(size_t I)(size_t[I] _indexes...) const
if (allSatisfy!(isIndex, Indexes))
{ {
mixin(indexStrideCode); static if (_indexes.length)
{
size_t stride = _strides[0] * _indexes[0];
assert(_indexes[0] < _lengths[0], indexError!(0, N));
foreach (i; Iota!(1, I)) //static
{
assert(_indexes[i] < _lengths[i], indexError!(i, N));
stride += _strides[i] * _indexes[i];
}
return stride;
}
else
{
return 0;
}
} }
size_t indexStride(size_t[N] _indexes) const size_t mathIndexStride(size_t I)(size_t[I] _indexes...) const
{ {
mixin(indexStrideCode); static if (_indexes.length)
{
size_t stride = _strides[0] * _indexes[N - 1];
assert(_indexes[N - 1] < _lengths[0], indexError!(N - 1, N));
foreach_reverse (i; Iota!(0, I - 1)) //static
{
assert(_indexes[i] < _lengths[N - 1 - i], indexError!(i, N));
stride += _strides[N - 1 - i] * _indexes[i];
} }
return stride;
size_t mathIndexStride(Indexes...)(Indexes _indexes) const
{
mixin(mathIndexStrideCode);
} }
else
size_t mathIndexStride(size_t[N] _indexes) const
{ {
mixin(mathIndexStrideCode); return 0;
}
} }
static if (!hasPtrBehavior!PureRange) static if (!hasPtrBehavior!PureRange)
@ -1829,7 +1802,7 @@ struct Slice(size_t _N, _Range)
/++ /++
Overloading `==` and `!=` Overloading `==` and `!=`
+/ +/
bool opEquals(size_t NR, RangeR)(auto ref Slice!(NR, RangeR) rslice) bool opEquals(size_t NR, RangeR)(Slice!(NR, RangeR) rslice)
if (Slice!(NR, RangeR).PureN == PureN) if (Slice!(NR, RangeR).PureN == PureN)
{ {
foreach (i; Iota!(0, PureN)) foreach (i; Iota!(0, PureN))
@ -2088,34 +2061,20 @@ struct Slice(size_t _N, _Range)
/++ /++
$(BOLD Fully defined index) $(BOLD Fully defined index)
+/ +/
auto ref opIndex(Repeat!(N, size_t) _indexes) auto ref opIndex(size_t I)(size_t[I] _indexes...)
if(I && I <= N)
{ {
static if (PureN == N) static if (I == PureN)
return _ptr[indexStride(_indexes)]; return _ptr[indexStride(_indexes)];
else else
static if (N == I)
return DeepElemType(_lengths[N .. $], _strides[N .. $], _ptr + indexStride(_indexes)); return DeepElemType(_lengths[N .. $], _strides[N .. $], _ptr + indexStride(_indexes));
}
///ditto
auto ref opIndex(size_t[N] _indexes)
{
static if (PureN == N)
return _ptr[indexStride(_indexes)];
else else
return DeepElemType(_lengths[N .. $], _strides[N .. $], _ptr + indexStride(_indexes)); return Slice!(N - I, Range)(_lengths[I .. $], _strides[I .. $], _ptr + indexStride(_indexes));
} }
///ditto ///ditto
auto ref opCall(Repeat!(N, size_t) _indexes) auto ref opCall()(size_t[N] _indexes...)
{
static if (PureN == N)
return _ptr[mathIndexStride(_indexes)];
else
return DeepElemType(_lengths[N .. $], _strides[N .. $], _ptr + mathIndexStride(_indexes));
}
///ditto
auto ref opCall(size_t[N] _indexes)
{ {
static if (PureN == N) static if (PureN == N)
return _ptr[mathIndexStride(_indexes)]; return _ptr[mathIndexStride(_indexes)];
@ -2471,14 +2430,7 @@ struct Slice(size_t _N, _Range)
/++ /++
Assignment of a value (e.g. a number) to a $(B fully defined index). Assignment of a value (e.g. a number) to a $(B fully defined index).
+/ +/
auto ref opIndexAssign(T)(T value, Repeat!(N, size_t) _indexes) auto ref opIndexAssign(T)(T value, size_t[N] _indexes...)
{
return _ptr[indexStride(_indexes)] = value;
}
static if (PureN == N)
/// ditto
auto ref opIndexAssign(T)(T value, size_t[N] _indexes)
{ {
return _ptr[indexStride(_indexes)] = value; return _ptr[indexStride(_indexes)] = value;
} }
@ -2524,14 +2476,7 @@ struct Slice(size_t _N, _Range)
/++ /++
Op Assignment `op=` of a value (e.g. a number) to a $(B fully defined index). Op Assignment `op=` of a value (e.g. a number) to a $(B fully defined index).
+/ +/
auto ref opIndexOpAssign(string op, T)(T value, Repeat!(N, size_t) _indexes) auto ref opIndexOpAssign(string op, T)(T value, size_t[N] _indexes...)
{
mixin (`return _ptr[indexStride(_indexes)] ` ~ op ~ `= value;`);
}
static if (PureN == N)
/// ditto
auto ref opIndexOpAssign(string op, T)(T value, size_t[N] _indexes)
{ {
mixin (`return _ptr[indexStride(_indexes)] ` ~ op ~ `= value;`); mixin (`return _ptr[indexStride(_indexes)] ` ~ op ~ `= value;`);
} }
@ -2781,15 +2726,7 @@ struct Slice(size_t _N, _Range)
/++ /++
Increment `++` and Decrement `--` operators for a $(B fully defined index). Increment `++` and Decrement `--` operators for a $(B fully defined index).
+/ +/
auto ref opIndexUnary(string op)(Repeat!(N, size_t) _indexes) auto ref opIndexUnary(string op)(size_t[N] _indexes...)
if (op == `++` || op == `--`)
{
mixin (`return ` ~ op ~ `_ptr[indexStride(_indexes)];`);
}
static if (PureN == N)
///ditto
auto ref opIndexUnary(string op)(size_t[N] _indexes)
if (op == `++` || op == `--`) if (op == `++` || op == `--`)
{ {
mixin (`return ` ~ op ~ `_ptr[indexStride(_indexes)];`); mixin (`return ` ~ op ~ `_ptr[indexStride(_indexes)];`);