67 changes: 28 additions & 39 deletions std/experimental/ndslice/selection.d
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ Returns:
+/
template pack(K...)
{
@fmb auto pack(size_t N, Range)(auto ref Slice!(N, Range) slice)
static if (!allSatisfy!(isSize_t, K))
alias pack = .pack!(staticMap!(toSize_t, K));
else
@fmb auto pack(size_t N, Range)(Slice!(N, Range) slice)
{
template Template(size_t NInner, Range, R...)
{
Expand Down Expand Up @@ -174,7 +177,7 @@ Returns:
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);
}
Expand All @@ -200,7 +203,7 @@ Returns:
See_also: $(LREF pack), $(LREF unpack)
+/
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;
static assert(Ret.NSeq.length > 0);
Expand Down Expand Up @@ -294,7 +297,7 @@ Params:
Returns:
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;
mixin _DefineRet;
Expand Down Expand Up @@ -472,8 +475,7 @@ Params:
Returns:
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)
if (allSatisfy!(isIndex, Lengths) && Lengths.length == N)
Slice!(N, Slice!(N+1, Range)) blocks(size_t N, Range)(Slice!(N, Range) slice, size_t[N] lengths...)
in
{
foreach (i, length; lengths)
Expand Down Expand Up @@ -594,8 +596,7 @@ Params:
Returns:
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)
if (allSatisfy!(isIndex, Lengths) && Lengths.length == N)
Slice!(N, Slice!(N+1, Range)) windows(size_t N, Range)(Slice!(N, Range) slice, size_t[N] lengths...)
in
{
foreach (i, length; lengths)
Expand Down Expand Up @@ -721,11 +722,10 @@ Returns:
Throws:
$(LREF ReshapeException) if the slice cannot be reshaped with the input lengths.
+/
Slice!(Lengths.length, Range)
Slice!(M, Range)
reshape
( size_t N, Range , Lengths... )
(auto ref Slice!(N, Range) slice, Lengths lengths)
if ( allSatisfy!(isIndex, Lengths) && Lengths.length)
(size_t N, Range, size_t M)
(Slice!(N, Range) slice, size_t[M] lengths...)
{
mixin _DefineRet;
foreach (i; Iota!(0, ret.N))
Expand Down Expand Up @@ -821,14 +821,13 @@ pure unittest
import std.experimental.ndslice.iteration : reversed;
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
try return slice.reshape(lengths);
catch (ReshapeException e)
//allocates the elements and creates a slice
//Note: -1 length is not supported by reshape2
return slice.byElement.array.sliced(lengths);
// Allocates
return slice.slice.reshape(lengths);
}

auto slice =
Expand Down Expand Up @@ -923,7 +922,7 @@ Params:
Returns:
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))
{
Expand Down Expand Up @@ -1177,7 +1176,7 @@ auto byElement(size_t N, Range)(auto ref Slice!(N, Range) slice)
}

/// 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;
}
Expand Down Expand Up @@ -1430,7 +1429,7 @@ Params:
Returns:
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))
{
Expand Down Expand Up @@ -1518,7 +1517,7 @@ auto byElementInStandardSimplex(size_t N, Range)(auto ref Slice!(N, Range) slice
}

/// 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])
maxHypercubeLength = slice._lengths[0];
Expand Down Expand Up @@ -1617,14 +1616,7 @@ Returns:
`N`-dimensional slice composed of indexes
See_also: $(LREF IndexSlice), $(LREF iotaSlice)
+/
IndexSlice!(Lengths.length) indexSlice(Lengths...)(Lengths lengths)
if (allSatisfy!(isIndex, Lengths))
{
return .indexSlice!(Lengths.length)([lengths]);
}

///ditto
IndexSlice!N indexSlice(size_t N)(auto ref size_t[N] lengths)
IndexSlice!N indexSlice(size_t N)(size_t[N] lengths...)
{
import std.experimental.ndslice.slice : sliced;
with (typeof(return)) return Range(lengths[1 .. $]).sliced(lengths);
Expand Down Expand Up @@ -1715,21 +1707,20 @@ Returns:
`N`-dimensional slice composed of indexes
See_also: $(LREF IotaSlice), $(LREF indexSlice)
+/
IotaSlice!(Lengths.length) iotaSlice(Lengths...)(Lengths lengths)
if (allSatisfy!(isIndex, Lengths))
IotaSlice!N iotaSlice(size_t N)(size_t[N] lengths...)
{
return .iotaSlice!(Lengths.length)([lengths]);
return .iotaSlice(lengths, 0);
}

///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;
return IotaMap!().init.sliced(lengths, shift);
}

///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);
foreach (i; Iota!(0, N))
Expand Down Expand Up @@ -1806,8 +1797,8 @@ Returns:
`n`-dimensional slice composed of identical values, where `n` is dimension count.
See_also: $(REF repeat, std,range)
+/
RepeatSlice!(Lengths.length, T) repeatSlice(T, Lengths...)(T value, Lengths lengths)
if (allSatisfy!(isIndex, Lengths) && !is(T : Slice!(N, Range), size_t N, Range))
RepeatSlice!(M, T) repeatSlice(T, size_t M)(T value, size_t[M] lengths...)
if (!is(T : Slice!(N, Range), size_t N, Range))
{
typeof(return) ret;
foreach (i; Iota!(0, ret.N))
Expand All @@ -1817,10 +1808,8 @@ RepeatSlice!(Lengths.length, T) repeatSlice(T, Lengths...)(T value, Lengths leng
}

/// ditto
Slice!(Lengths.length, Slice!(N + 1, Range)) repeatSlice(size_t N, Range, Lengths...)(auto ref Slice!(N, Range) slice, Lengths lengths)
if (allSatisfy!(isIndex, Lengths) && Lengths.length)
Slice!(M, Slice!(N + 1, Range)) repeatSlice(size_t N, Range, size_t M)(Slice!(N, Range) slice, size_t[M] lengths...)
{
enum M = Lengths.length;
typeof(return) ret;
ret._ptr = slice._ptr;
foreach (i; Iota!(0, M))
Expand Down Expand Up @@ -1975,7 +1964,7 @@ template mapSlice(fun...)
{
///
@fmb auto mapSlice(size_t N, Range)
(auto ref Slice!(N, Range) tensor)
(Slice!(N, Range) tensor)
{
// this static if-else block
// may be unified with std.algorithms.iteration.map
Expand Down
185 changes: 61 additions & 124 deletions std/experimental/ndslice/slice.d
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,17 @@ Returns:
auto sliced(
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)
Range, size_t N)(Range range, size_t[N] lengths...)
if (!isStaticArray!Range && !isNarrowString!Range && N)
{
return .sliced!(ra, ad, Lengths.length, Range)(range, [lengths]);
return .sliced!(ra, ad)(range, lengths, 0);
}

///ditto
auto sliced(
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)
size_t N, Range)(Range range, size_t[N] lengths, size_t shift = 0)
if (!isStaticArray!Range && !isNarrowString!Range && N)
in
{
Expand Down Expand Up @@ -146,21 +145,20 @@ template sliced(Names...)
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
Flag!`allowDownsize` ad = No.allowDownsize,
" ~ _Range_Types!Names ~ "
Lengths...)
size_t N)
(" ~ _Range_DeclarationList!Names ~
"Lengths lengths)
if (allSatisfy!(isIndex, Lengths))
"size_t[N] lengths...)
{
alias sliced = .sliced!Names;
return sliced!(ra, ad)(" ~ _Range_Values!Names ~ "[lengths]);
alias sl = .sliced!Names;
return sl!(ra, ad)(" ~ _Range_Values!Names ~ "lengths, 0);
}
auto sliced(
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,
size_t[N] lengths,
size_t shift = 0)
{
alias RS = AliasSeq!(" ~ _Range_Types!Names ~ ");"
Expand Down Expand Up @@ -535,20 +533,10 @@ Params:
Returns:
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(T,
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);
return new T[len].sliced!ra(lengths);
Expand All @@ -557,7 +545,7 @@ slice(T,
/// ditto
auto slice(T,
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);
static if (ra && !hasElaborateAssign!T)
Expand All @@ -577,7 +565,7 @@ auto slice(T,
/// ditto
auto slice(
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);
ret[] = slice;
Expand Down Expand Up @@ -620,19 +608,9 @@ Params:
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)
size_t N)(size_t[N] lengths...)
{
immutable len = lengthsProduct(lengths);
import std.array : uninitializedArray;
Expand Down Expand Up @@ -662,21 +640,10 @@ Returns:
Note:
`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(
Flag!`replaceArrayWithPointer` ra = Yes.replaceArrayWithPointer,
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);
return makeSlice!(T, ra)(alloc, slice);
Expand All @@ -687,7 +654,7 @@ 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)
size_t N)(auto ref Allocator alloc, size_t[N] lengths...)
{
import std.experimental.allocator : makeArray;
immutable len = lengthsProduct(lengths);
Expand All @@ -701,7 +668,7 @@ 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)
size_t N)(auto ref Allocator alloc, size_t[N] lengths, T init)
{
import std.experimental.allocator : makeArray;
immutable len = lengthsProduct(lengths);
Expand All @@ -715,7 +682,7 @@ 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)
size_t N, Range)(auto ref Allocator alloc, Slice!(N, Range) slice)
{
import std.experimental.allocator : makeArray;
import std.experimental.ndslice.selection : byElement;
Expand Down Expand Up @@ -780,22 +747,11 @@ Params:
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)
size_t N)(auto ref Allocator alloc, size_t[N] lengths...)
{
immutable len = lengthsProduct(lengths);
auto array = cast(T[]) alloc.allocate(len * T.sizeof);
Expand Down Expand Up @@ -836,7 +792,7 @@ Params:
Returns:
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;
static if (N == 1)
Expand Down Expand Up @@ -1267,25 +1223,42 @@ struct Slice(size_t _N, _Range)
return _strides[dimension] * (_lengths[dimension] - 1);
}

size_t indexStride(Indexes...)(Indexes _indexes) const
if (allSatisfy!(isIndex, Indexes))
{
mixin(indexStrideCode);
}

size_t indexStride(size_t[N] _indexes) const
{
mixin(indexStrideCode);
}

size_t mathIndexStride(Indexes...)(Indexes _indexes) const
size_t indexStride(size_t I)(size_t[I] _indexes...) const
{
mixin(mathIndexStrideCode);
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 mathIndexStride(size_t[N] _indexes) const
size_t mathIndexStride(size_t I)(size_t[I] _indexes...) const
{
mixin(mathIndexStrideCode);
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;
}
else
{
return 0;
}
}

static if (!hasPtrBehavior!PureRange)
Expand Down Expand Up @@ -1829,7 +1802,7 @@ struct Slice(size_t _N, _Range)
/++
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)
{
foreach (i; Iota!(0, PureN))
Expand Down Expand Up @@ -2088,34 +2061,20 @@ struct Slice(size_t _N, _Range)
/++
$(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)];
else
static if (N == I)
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
return DeepElemType(_lengths[N .. $], _strides[N .. $], _ptr + indexStride(_indexes));
return Slice!(N - I, Range)(_lengths[I .. $], _strides[I .. $], _ptr + indexStride(_indexes));
}

///ditto
auto ref opCall(Repeat!(N, size_t) _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)
auto ref opCall()(size_t[N] _indexes...)
{
static if (PureN == N)
return _ptr[mathIndexStride(_indexes)];
Expand Down Expand Up @@ -2471,14 +2430,7 @@ struct Slice(size_t _N, _Range)
/++
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)
{
return _ptr[indexStride(_indexes)] = value;
}

static if (PureN == N)
/// ditto
auto ref opIndexAssign(T)(T value, size_t[N] _indexes)
auto ref opIndexAssign(T)(T value, size_t[N] _indexes...)
{
return _ptr[indexStride(_indexes)] = value;
}
Expand Down Expand Up @@ -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).
+/
auto ref opIndexOpAssign(string op, T)(T value, Repeat!(N, size_t) _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)
auto ref opIndexOpAssign(string op, T)(T value, size_t[N] _indexes...)
{
mixin (`return _ptr[indexStride(_indexes)] ` ~ op ~ `= value;`);
}
Expand Down Expand Up @@ -2781,15 +2726,7 @@ struct Slice(size_t _N, _Range)
/++
Increment `++` and Decrement `--` operators for a $(B fully defined index).
+/
auto ref opIndexUnary(string op)(Repeat!(N, size_t) _indexes)
if (op == `++` || op == `--`)
{
mixin (`return ` ~ op ~ `_ptr[indexStride(_indexes)];`);
}

static if (PureN == N)
///ditto
auto ref opIndexUnary(string op)(size_t[N] _indexes)
auto ref opIndexUnary(string op)(size_t[N] _indexes...)
if (op == `++` || op == `--`)
{
mixin (`return ` ~ op ~ `_ptr[indexStride(_indexes)];`);
Expand Down