From c39ec4cd43ee4ea58aa3d3b6747024c7c9979732 Mon Sep 17 00:00:00 2001 From: Ilya Yaroshenko Date: Fri, 30 Sep 2016 00:49:02 +0200 Subject: [PATCH] reduce ndslice template bloat part 1 --- std/experimental/ndslice/internal.d | 36 ------ std/experimental/ndslice/iteration.d | 82 +++--------- std/experimental/ndslice/selection.d | 64 ++++----- std/experimental/ndslice/slice.d | 185 +++++++++------------------ 4 files changed, 106 insertions(+), 261 deletions(-) diff --git a/std/experimental/ndslice/internal.d b/std/experimental/ndslice/internal.d index 170776651..2bb8c299b 100644 --- a/std/experimental/ndslice/internal.d +++ b/std/experimental/ndslice/internal.d @@ -334,42 +334,6 @@ enum indexError(size_t pos, size_t N) = ~ " from the range [0 .." ~ N.stringof ~ ")" ~ " 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( string fun = __FUNCTION__, string pfun = __PRETTY_FUNCTION__) = diff --git a/std/experimental/ndslice/iteration.d b/std/experimental/ndslice/iteration.d index 0b11f86bc..b5190bc9f 100644 --- a/std/experimental/ndslice/iteration.d +++ b/std/experimental/ndslice/iteration.d @@ -329,7 +329,7 @@ Returns: n-dimensional slice of the same type 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; 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); size_t[N] ctr; @@ -410,7 +410,7 @@ See_also: $(LREF swapped), $(LREF everted) template transposed(Dimensions...) 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; foreach (i, dimension; Dimensions) @@ -425,22 +425,7 @@ template transposed(Dimensions...) } ///ditto -Slice!(N, Range) transposed(size_t N, Range)(auto ref Slice!(N, Range) slice, size_t dimension) -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...) +Slice!(N, Range) transposed(size_t N, Range, size_t M)(Slice!(N, Range) slice, size_t[M] dimensions...) in { mixin (DimensionsCountRTError); @@ -458,7 +443,7 @@ body } ///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); } @@ -564,19 +549,7 @@ template reversed(Dimensions...) } ///ditto -Slice!(N, Range) reversed(size_t N, Range)(Slice!(N, Range) slice, size_t dimension) -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...) +Slice!(N, Range) reversed(size_t N, Range, size_t M)(Slice!(N, Range) slice, size_t[M] dimensions...) in { foreach (dimension; dimensions) @@ -584,8 +557,11 @@ in } body { - foreach (dimension; dimensions) + foreach (i; Iota!(0, M)) + { + auto dimension = dimensions[i]; mixin (_reversedCode); + } return slice; } @@ -904,19 +880,7 @@ template dropOne(Dimensions...) } ///ditto -Slice!(N, Range) dropOne(size_t N, Range)(Slice!(N, Range) slice, size_t dimension) -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...) +Slice!(N, Range) dropOne(size_t N, Range, size_t M)(Slice!(N, Range) slice, size_t[M] dimensions...) in { foreach (dimension; dimensions) @@ -924,8 +888,11 @@ in } body { - foreach (dimension; dimensions) + foreach (i; Iota!(0, M)) + { + auto dimension = dimensions[i]; slice.popFront(dimension); + } return slice; } @@ -945,19 +912,7 @@ template dropBackOne(Dimensions...) } ///ditto -Slice!(N, Range) dropBackOne(size_t N, Range)(Slice!(N, Range) slice, size_t dimension) -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...) +Slice!(N, Range) dropBackOne(size_t N, Range, size_t M)(Slice!(N, Range) slice, size_t[M] dimensions...) in { foreach (dimension; dimensions) @@ -965,8 +920,11 @@ in } body { - foreach (dimension; dimensions) + foreach (i; Iota!(0, M)) + { + auto dimension = dimensions[i]; slice.popBack(dimension); + } return slice; } diff --git a/std/experimental/ndslice/selection.d b/std/experimental/ndslice/selection.d index b525d7598..e64f0fc6a 100644 --- a/std/experimental/ndslice/selection.d +++ b/std/experimental/ndslice/selection.d @@ -75,7 +75,7 @@ Returns: +/ 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...) { @@ -174,7 +174,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); } @@ -200,7 +200,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); @@ -294,7 +294,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; @@ -472,8 +472,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) @@ -594,8 +593,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) @@ -721,11 +719,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)) @@ -821,14 +818,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 = @@ -923,7 +919,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)) { @@ -1177,7 +1173,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; } @@ -1430,7 +1426,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)) { @@ -1518,7 +1514,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]; @@ -1617,14 +1613,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); @@ -1715,21 +1704,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)) @@ -1806,8 +1794,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)) @@ -1817,10 +1805,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)) @@ -1975,7 +1961,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 diff --git a/std/experimental/ndslice/slice.d b/std/experimental/ndslice/slice.d index ceb90956c..1c8a310cc 100644 --- a/std/experimental/ndslice/slice.d +++ b/std/experimental/ndslice/slice.d @@ -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 { @@ -146,13 +145,12 @@ 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( @@ -160,7 +158,7 @@ template sliced(Names...) 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 ~ ");" @@ -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); @@ -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) @@ -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; @@ -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; @@ -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); @@ -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); @@ -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); @@ -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; @@ -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); @@ -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) @@ -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)) + size_t indexStride(size_t I)(size_t[I] _indexes...) const { - 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); - } - - size_t mathIndexStride(Indexes...)(Indexes _indexes) const - { - mixin(mathIndexStrideCode); - } - - size_t mathIndexStride(size_t[N] _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) @@ -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)) @@ -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)]; @@ -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; } @@ -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;`); } @@ -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)];`);