mirror of
https://github.com/dlang/phobos.git
synced 2025-05-03 16:40:48 +03:00
Remove std.experimental.ndslice (#5187)
Remove std.experimental.ndslice merged-on-behalf-of: Sebastian Wilzbach <sebi.wilzbach@gmail.com>
This commit is contained in:
parent
023f525b83
commit
d6d6831d3b
10 changed files with 10 additions and 8287 deletions
5
changelog/std-expertimental-ndslice-removed.dd
Normal file
5
changelog/std-expertimental-ndslice-removed.dd
Normal file
|
@ -0,0 +1,5 @@
|
|||
`std.experimental.ndslice` has been removed
|
||||
|
||||
The synchronization between Phobos and Mir turned out to be a high amount of work with litte gain.
|
||||
Users of `std.experimental.ndslice` are advised to switch to the upstream
|
||||
$(LINK2 https://github.com/libmir/mir-algorithm, mir package).
|
8
index.d
8
index.d
|
@ -32,10 +32,6 @@ $(BOOKTABLE ,
|
|||
comparison, iteration, sorting, set operations, and mutation.
|
||||
)
|
||||
)
|
||||
$(TR
|
||||
$(TDNW $(LINK2 std_experimental_ndslice.html, std.experimental.ndslice))
|
||||
$(TD Multidimensional random access ranges and arrays.)
|
||||
)
|
||||
$(LEADINGROW Array manipulation)
|
||||
$(TR
|
||||
$(TDNW
|
||||
|
@ -326,10 +322,6 @@ $(BOOKTABLE ,
|
|||
$(TDNW $(LINK2 std_mathspecial.html, std.mathspecial))
|
||||
$(TD Families of transcendental functions.)
|
||||
)
|
||||
$(TR
|
||||
$(TDNW $(LINK2 std_experimental_ndslice.html, std.experimental.ndslice))
|
||||
$(TD Multidimensional random access ranges and arrays.)
|
||||
)
|
||||
$(TR
|
||||
$(TDNW $(LINK2 std_numeric.html, std.numeric))
|
||||
$(TD Floating point numerics functions.)
|
||||
|
|
|
@ -163,7 +163,6 @@ P2MODULES=$(foreach P,$1,$(addprefix $P/,$(PACKAGE_$(subst /,_,$P))))
|
|||
STD_PACKAGES = std $(addprefix std/,\
|
||||
algorithm container digest experimental/allocator \
|
||||
experimental/allocator/building_blocks experimental/logger \
|
||||
experimental/ndslice \
|
||||
net \
|
||||
experimental range regex)
|
||||
|
||||
|
@ -189,7 +188,6 @@ PACKAGE_std_experimental_allocator_building_blocks = \
|
|||
fallback_allocator free_list free_tree bitmapped_block \
|
||||
kernighan_ritchie null_allocator package quantizer \
|
||||
region scoped_allocator segregator stats_collector
|
||||
PACKAGE_std_experimental_ndslice = package iteration selection slice
|
||||
PACKAGE_std_net = curl isemail
|
||||
PACKAGE_std_range = interfaces package primitives
|
||||
PACKAGE_std_regex = package $(addprefix internal/,generator ir parser \
|
||||
|
@ -214,7 +212,6 @@ EXTRA_DOCUMENTABLES := $(EXTRA_MODULES_LINUX) $(EXTRA_MODULES_WIN32) $(EXTRA_MOD
|
|||
|
||||
EXTRA_MODULES_INTERNAL := $(addprefix std/, \
|
||||
algorithm/internal concurrencybase \
|
||||
experimental/ndslice/internal \
|
||||
$(addprefix internal/, \
|
||||
cstring digest/sha_SSSE3 encodinginit \
|
||||
$(addprefix math/, biguintcore biguintnoasm biguintx86 \
|
||||
|
@ -538,7 +535,7 @@ style: ../dscanner/dsc $(LIB) has_public_example publictests
|
|||
done
|
||||
|
||||
@echo "Check that Ddoc runs without errors"
|
||||
$(DMD) $(DFLAGS) -defaultlib= -debuglib= $(LIB) -w -D -main -c -o- $$(find etc std -type f -name '*.d' | grep -vE 'std/experimental/ndslice/iteration.d') 2>&1 | grep -v "Deprecation:"; test $$? -eq 1
|
||||
$(DMD) $(DFLAGS) -defaultlib= -debuglib= $(LIB) -w -D -main -c -o- $$(find etc std -type f -name '*.d') 2>&1 | grep -v "Deprecation:"; test $$? -eq 1
|
||||
|
||||
# at the moment libdparse has problems to parse some modules (->excludes)
|
||||
@echo "Running DScanner"
|
||||
|
@ -547,14 +544,14 @@ style: ../dscanner/dsc $(LIB) has_public_example publictests
|
|||
publictests: $(LIB)
|
||||
# parse all public unittests from Phobos and runs them (for now some modules are excluded)
|
||||
rm -rf ./out
|
||||
DFLAGS="$(DFLAGS) $(LIB) -defaultlib= -debuglib= $(LINKDL)" $(DUB) --compiler=$${PWD}/$(DMD) --root=../tools/styles -c tests_extractor -- --inputdir . --ignore "base64.d,building_blocks/free_list,building_blocks/quantizer,digest/hmac.d,file.d,index.d,math.d,ndslice/selection.d,stdio.d,traits.d,typecons.d,uuid.d" --outputdir ./out
|
||||
DFLAGS="$(DFLAGS) $(LIB) -defaultlib= -debuglib= $(LINKDL)" $(DUB) --compiler=$${PWD}/$(DMD) --root=../tools/styles -c tests_extractor -- --inputdir . --ignore "base64.d,building_blocks/free_list,building_blocks/quantizer,digest/hmac.d,file.d,index.d,math.d,stdio.d,traits.d,typecons.d,uuid.d" --outputdir ./out
|
||||
# execute all parsed tests
|
||||
for file in $$(find out -name '*.d'); do echo "executing $${file}" && $(DMD) $(DFLAGS) -defaultlib= -debuglib= $(LIB) -main -unittest -run $$file || exit 1 ; done
|
||||
|
||||
has_public_example: $(LIB)
|
||||
# checks whether public function have public examples (for now some modules are excluded)
|
||||
rm -rf ./out
|
||||
DFLAGS="$(DFLAGS) $(LIB) -defaultlib= -debuglib= $(LINKDL)" $(DUB) --compiler=$${PWD}/$(DMD) --root=../tools/styles -c has_public_example -- --inputdir . --ignore "etc,array.d,allocator,base64.d,bitmanip.d,concurrency.d,conv.d,csv.d,datetime.d,demangle.d,digest/hmac.d,digest/sha.d,encoding.d,exception.d,file.d,format.d,getopt.d,index.d,internal,isemail.d,json.d,logger/core.d,logger/nulllogger.d,math.d,mathspecial.d,net/curl.d,ndslice/selection.d,ndslice/slice.d,numeric.d,parallelism.d,path.d,process.d,random.d,range,regex/package.d,socket.d,stdio.d,string.d,traits.d,typecons.d,uni.d,unittest.d,uri.d,utf.d,uuid.d,xml.d,zlib.d"
|
||||
DFLAGS="$(DFLAGS) $(LIB) -defaultlib= -debuglib= $(LINKDL)" $(DUB) --compiler=$${PWD}/$(DMD) --root=../tools/styles -c has_public_example -- --inputdir . --ignore "etc,array.d,allocator,base64.d,bitmanip.d,concurrency.d,conv.d,csv.d,datetime.d,demangle.d,digest/hmac.d,digest/sha.d,encoding.d,exception.d,file.d,format.d,getopt.d,index.d,internal,isemail.d,json.d,logger/core.d,logger/nulllogger.d,math.d,mathspecial.d,net/curl.d,numeric.d,parallelism.d,path.d,process.d,random.d,range,regex/package.d,socket.d,stdio.d,string.d,traits.d,typecons.d,uni.d,unittest.d,uri.d,utf.d,uuid.d,xml.d,zlib.d"
|
||||
|
||||
.PHONY : auto-tester-build
|
||||
auto-tester-build: all checkwhitespace
|
||||
|
|
|
@ -1,521 +0,0 @@
|
|||
/// @@@DEPRECATED_2017-04@@@
|
||||
deprecated("Please use mir-algorithm DUB package: http://github.com/libmir/mir-algorithm")
|
||||
module std.experimental.ndslice.internal;
|
||||
|
||||
import std.range.primitives;
|
||||
import std.traits;
|
||||
import std.meta;
|
||||
import std.experimental.ndslice.slice;
|
||||
|
||||
/+
|
||||
fastmath do nothing here,
|
||||
but remove constraint for LDC that operations for pointer's computations
|
||||
maybe mixed up with callers computations if both computations has fastmath attribute.
|
||||
So, it is just a bridge between two fastmath functions.
|
||||
fmb alias is used to relax users.
|
||||
+/
|
||||
package alias fmb = fastmath;
|
||||
|
||||
version(LDC)
|
||||
{
|
||||
static import ldc.attributes;
|
||||
alias fastmath = ldc.attributes.fastmath;
|
||||
}
|
||||
else
|
||||
{
|
||||
alias fastmath = fastmathDummy;
|
||||
}
|
||||
|
||||
enum FastmathDummy { init }
|
||||
FastmathDummy fastmathDummy() { return FastmathDummy.init; }
|
||||
|
||||
template PtrTuple(Names...)
|
||||
{
|
||||
@LikePtr struct PtrTuple(Ptrs...)
|
||||
if (allSatisfy!(isSlicePointer, Ptrs) && Ptrs.length == Names.length)
|
||||
{
|
||||
@fmb:
|
||||
|
||||
Ptrs ptrs;
|
||||
|
||||
void opOpAssign(string op)(sizediff_t shift)
|
||||
if (op == `+` || op == `-`)
|
||||
{
|
||||
foreach (ref ptr; ptrs)
|
||||
mixin (`ptr ` ~ op ~ `= shift;`);
|
||||
}
|
||||
|
||||
auto opBinary(string op)(sizediff_t shift)
|
||||
if (op == `+` || op == `-`)
|
||||
{
|
||||
auto ret = this;
|
||||
ret.opOpAssign!op(shift);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public struct Index
|
||||
{
|
||||
Ptrs _ptrs__;
|
||||
mixin (PtrTupleFrontMembers!Names);
|
||||
}
|
||||
|
||||
auto opIndex(sizediff_t index)
|
||||
{
|
||||
auto p = ptrs;
|
||||
foreach (ref ptr; p)
|
||||
ptr += index;
|
||||
return Index(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ISSUE 16501
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.ndslice;
|
||||
alias sab = sliced!("a", "b");
|
||||
auto sl = sab(new double[12], new double[12], 3, 4);
|
||||
auto psl = sl.pack!1;
|
||||
}
|
||||
|
||||
|
||||
struct PtrShell(Range)
|
||||
{
|
||||
sizediff_t _shift;
|
||||
Range _range;
|
||||
@fmb:
|
||||
|
||||
enum hasAccessByRef = isPointer!Range ||
|
||||
__traits(compiles, &_range[0]);
|
||||
|
||||
void opOpAssign(string op)(sizediff_t shift)
|
||||
if (op == `+` || op == `-`)
|
||||
{
|
||||
mixin (`_shift ` ~ op ~ `= shift;`);
|
||||
}
|
||||
|
||||
auto opBinary(string op)(sizediff_t shift)
|
||||
if (op == `+` || op == `-`)
|
||||
{
|
||||
mixin (`return typeof(this)(_shift ` ~ op ~ ` shift, _range);`);
|
||||
}
|
||||
|
||||
auto opUnary(string op)()
|
||||
if (op == `++` || op == `--`)
|
||||
{
|
||||
mixin(op ~ `_shift;`);
|
||||
return this;
|
||||
}
|
||||
|
||||
auto ref opIndex(sizediff_t index)
|
||||
in
|
||||
{
|
||||
assert(_shift + index >= 0);
|
||||
static if (hasLength!Range)
|
||||
assert(_shift + index <= _range.length);
|
||||
}
|
||||
body
|
||||
{
|
||||
return _range[_shift + index];
|
||||
}
|
||||
|
||||
static if (!hasAccessByRef)
|
||||
{
|
||||
auto ref opIndexAssign(T)(T value, sizediff_t index)
|
||||
in
|
||||
{
|
||||
assert(_shift + index >= 0);
|
||||
static if (hasLength!Range)
|
||||
assert(_shift + index <= _range.length);
|
||||
}
|
||||
body
|
||||
{
|
||||
return _range[_shift + index] = value;
|
||||
}
|
||||
|
||||
auto ref opIndexOpAssign(string op, T)(T value, sizediff_t index)
|
||||
in
|
||||
{
|
||||
assert(_shift + index >= 0);
|
||||
static if (hasLength!Range)
|
||||
assert(_shift + index <= _range.length);
|
||||
}
|
||||
body
|
||||
{
|
||||
mixin (`return _range[_shift + index] ` ~ op ~ `= value;`);
|
||||
}
|
||||
|
||||
auto ref opIndexUnary(string op)(sizediff_t index)
|
||||
in
|
||||
{
|
||||
assert(_shift + index >= 0);
|
||||
static if (hasLength!Range)
|
||||
assert(_shift + index <= _range.length);
|
||||
}
|
||||
body
|
||||
{
|
||||
mixin (`return ` ~ op ~ `_range[_shift + index];`);
|
||||
}
|
||||
}
|
||||
|
||||
auto save() @property
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
auto ptrShell(Range)(Range range, sizediff_t shift = 0)
|
||||
{
|
||||
return PtrShell!Range(shift, range);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.internal.test.dummyrange;
|
||||
foreach (RB; AliasSeq!(ReturnBy.Reference, ReturnBy.Value))
|
||||
{
|
||||
DummyRange!(RB, Length.Yes, RangeType.Random) range;
|
||||
range.reinit;
|
||||
assert(range.length >= 10);
|
||||
auto ptr = range.ptrShell;
|
||||
assert(ptr[0] == range[0]);
|
||||
auto save0 = range[0];
|
||||
ptr[0] += 10;
|
||||
++ptr[0];
|
||||
assert(ptr[0] == save0 + 11);
|
||||
(ptr + 5)[2] = 333;
|
||||
assert(range[7] == 333);
|
||||
|
||||
auto ptrCopy = ptr.save;
|
||||
ptrCopy._range.popFront;
|
||||
ptr[1] = 2;
|
||||
assert(ptr[0] == save0 + 11);
|
||||
assert(ptrCopy[0] == 2);
|
||||
}
|
||||
}
|
||||
|
||||
private template PtrTupleFrontMembers(Names...)
|
||||
if (Names.length <= 32)
|
||||
{
|
||||
static if (Names.length)
|
||||
{
|
||||
alias Top = Names[0..$-1];
|
||||
enum int m = Top.length;
|
||||
/+
|
||||
fastmath do nothing here,
|
||||
but remove constraint for LDC that operations for pointer's computations
|
||||
maybe mixed up with callers computations if both computations has fastmath attribute.
|
||||
So, it is just a bridge between two fastmath functions.
|
||||
+/
|
||||
enum PtrTupleFrontMembers = PtrTupleFrontMembers!Top
|
||||
~ "
|
||||
@fmb @property auto ref " ~ Names[$-1] ~ "() {
|
||||
return _ptrs__[" ~ m.stringof ~ "][0];
|
||||
}
|
||||
static if (!__traits(compiles, &(_ptrs__[" ~ m.stringof ~ "][0])))
|
||||
@fmb @property auto ref " ~ Names[$-1] ~ "(T)(auto ref T value) {
|
||||
return _ptrs__[" ~ m.stringof ~ "][0] = value;
|
||||
}
|
||||
";
|
||||
}
|
||||
else
|
||||
{
|
||||
enum PtrTupleFrontMembers = "";
|
||||
}
|
||||
}
|
||||
|
||||
@LikePtr struct Pack(size_t N, Range)
|
||||
{
|
||||
@fmb:
|
||||
alias Elem = Slice!(N, Range);
|
||||
alias PureN = Elem.PureN;
|
||||
alias PureRange = Elem.PureRange;
|
||||
|
||||
size_t[PureN] _lengths;
|
||||
sizediff_t[PureN] _strides;
|
||||
|
||||
SlicePtr!PureRange _ptr;
|
||||
mixin PropagatePtr;
|
||||
|
||||
Elem opIndex(size_t index)
|
||||
{
|
||||
return Elem(_lengths, _strides, _ptr + index);
|
||||
}
|
||||
}
|
||||
|
||||
@LikePtr struct Map(Range, alias fun)
|
||||
{
|
||||
Range _ptr;
|
||||
// can not use @fmb here because fun maybe an LLVM function.
|
||||
auto ref opIndex(size_t index)
|
||||
{
|
||||
return fun(_ptr[index]);
|
||||
}
|
||||
mixin PropagatePtr;
|
||||
}
|
||||
|
||||
private mixin template PropagatePtr()
|
||||
{
|
||||
@fmb void opOpAssign(string op)(sizediff_t shift)
|
||||
if (op == `+` || op == `-`)
|
||||
{
|
||||
mixin (`_ptr ` ~ op ~ `= shift;`);
|
||||
}
|
||||
|
||||
@fmb auto opBinary(string op)(sizediff_t shift)
|
||||
if (op == `+` || op == `-`)
|
||||
{
|
||||
auto ret = this;
|
||||
ret.opOpAssign!op(shift);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@fmb auto opUnary(string op)()
|
||||
if (op == `++` || op == `--`)
|
||||
{
|
||||
mixin(op ~ `_ptr;`);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
struct LikePtr {}
|
||||
|
||||
template SlicePtr(Range)
|
||||
{
|
||||
static if (hasPtrBehavior!Range)
|
||||
alias SlicePtr = Range;
|
||||
else
|
||||
alias SlicePtr = PtrShell!Range;
|
||||
}
|
||||
|
||||
enum isSlicePointer(T) = isPointer!T || is(T : PtrShell!R, R);
|
||||
|
||||
template hasPtrBehavior(T)
|
||||
{
|
||||
static if (isPointer!T)
|
||||
enum hasPtrBehavior = true;
|
||||
else
|
||||
static if (!isAggregateType!T)
|
||||
enum hasPtrBehavior = false;
|
||||
else
|
||||
enum hasPtrBehavior = hasUDA!(T, LikePtr);
|
||||
}
|
||||
|
||||
alias RangeOf(T : Slice!(N, Range), size_t N, Range) = Range;
|
||||
|
||||
template isMemory(T)
|
||||
{
|
||||
static if (isPointer!T)
|
||||
enum isMemory = true;
|
||||
else
|
||||
static if (is(T : Map!(Range, fun), Range, alias fun))
|
||||
enum isMemory = .isMemory!Range;
|
||||
else
|
||||
static if (__traits(compiles, __traits(isSame, PtrTuple, TemplateOf!(TemplateOf!T))))
|
||||
static if (__traits(isSame, PtrTuple, TemplateOf!(TemplateOf!T)))
|
||||
enum isMemory = allSatisfy!(.isMemory, TemplateArgsOf!T);
|
||||
else
|
||||
enum isMemory = false;
|
||||
else
|
||||
enum isMemory = false;
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.ndslice.slice : PtrTuple;
|
||||
import std.experimental.ndslice.selection : Map;
|
||||
static assert(isMemory!(int*));
|
||||
alias R = PtrTuple!("a", "b");
|
||||
alias F = R!(double*, double*);
|
||||
static assert(isMemory!F);
|
||||
static assert(isMemory!(Map!(F, a => a)));
|
||||
}
|
||||
|
||||
enum indexError(size_t pos, size_t N) =
|
||||
"index at position " ~ pos.stringof
|
||||
~ " from the range [0 .." ~ N.stringof ~ ")"
|
||||
~ " must be less than corresponding length.";
|
||||
|
||||
enum string tailErrorMessage(
|
||||
string fun = __FUNCTION__,
|
||||
string pfun = __PRETTY_FUNCTION__) =
|
||||
"
|
||||
- - -
|
||||
Error in function
|
||||
" ~ fun ~ "
|
||||
- - -
|
||||
Function prototype
|
||||
" ~ pfun ~ "
|
||||
_____";
|
||||
|
||||
mixin template _DefineRet()
|
||||
{
|
||||
alias Ret = typeof(return);
|
||||
static if (hasElaborateAssign!(Ret.PureRange))
|
||||
Ret ret;
|
||||
else
|
||||
Ret ret = void;
|
||||
}
|
||||
|
||||
mixin template DimensionsCountCTError()
|
||||
{
|
||||
static assert(Dimensions.length <= N,
|
||||
"Dimensions list length = " ~ Dimensions.length.stringof
|
||||
~ " should be less than or equal to N = " ~ N.stringof
|
||||
~ tailErrorMessage!());
|
||||
}
|
||||
|
||||
enum DimensionsCountRTError = q{
|
||||
assert(dimensions.length <= N,
|
||||
"Dimensions list length should be less than or equal to N = " ~ N.stringof
|
||||
~ tailErrorMessage!());
|
||||
};
|
||||
|
||||
mixin template DimensionCTError()
|
||||
{
|
||||
static assert(dimension >= 0,
|
||||
"dimension = " ~ dimension.stringof ~ " at position "
|
||||
~ i.stringof ~ " should be greater than or equal to 0"
|
||||
~ tailErrorMessage!());
|
||||
static assert(dimension < N,
|
||||
"dimension = " ~ dimension.stringof ~ " at position "
|
||||
~ i.stringof ~ " should be less than N = " ~ N.stringof
|
||||
~ tailErrorMessage!());
|
||||
}
|
||||
|
||||
enum DimensionRTError = q{
|
||||
static if (isSigned!(typeof(dimension)))
|
||||
assert(dimension >= 0, "dimension should be greater than or equal to 0"
|
||||
~ tailErrorMessage!());
|
||||
assert(dimension < N, "dimension should be less than N = " ~ N.stringof
|
||||
~ tailErrorMessage!());
|
||||
};
|
||||
|
||||
private alias IncFront(Seq...) = AliasSeq!(Seq[0] + 1, Seq[1 .. $]);
|
||||
|
||||
private alias DecFront(Seq...) = AliasSeq!(Seq[0] - 1, Seq[1 .. $]);
|
||||
|
||||
private enum bool isNotZero(alias t) = t != 0;
|
||||
|
||||
alias NSeqEvert(Seq...) = Filter!(isNotZero, DecFront!(Reverse!(IncFront!Seq)));
|
||||
|
||||
alias Parts(Seq...) = DecAll!(IncFront!Seq);
|
||||
|
||||
alias Snowball(Seq...) = AliasSeq!(size_t.init, SnowballImpl!(size_t.init, Seq));
|
||||
|
||||
private template SnowballImpl(size_t val, Seq...)
|
||||
{
|
||||
static if (Seq.length == 0)
|
||||
alias SnowballImpl = AliasSeq!();
|
||||
else
|
||||
alias SnowballImpl = AliasSeq!(Seq[0] + val, SnowballImpl!(Seq[0] + val, Seq[1 .. $]));
|
||||
}
|
||||
|
||||
private template DecAll(Seq...)
|
||||
{
|
||||
static if (Seq.length == 0)
|
||||
alias DecAll = AliasSeq!();
|
||||
else
|
||||
alias DecAll = AliasSeq!(Seq[0] - 1, DecAll!(Seq[1 .. $]));
|
||||
}
|
||||
|
||||
template SliceFromSeq(Range, Seq...)
|
||||
{
|
||||
static if (Seq.length == 0)
|
||||
alias SliceFromSeq = Range;
|
||||
else
|
||||
{
|
||||
import std.experimental.ndslice.slice : Slice;
|
||||
alias SliceFromSeq = SliceFromSeq!(Slice!(Seq[$ - 1], Range), Seq[0 .. $ - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
template DynamicArrayDimensionsCount(T)
|
||||
{
|
||||
static if (isDynamicArray!T)
|
||||
enum size_t DynamicArrayDimensionsCount = 1 + DynamicArrayDimensionsCount!(typeof(T.init[0]));
|
||||
else
|
||||
enum size_t DynamicArrayDimensionsCount = 0;
|
||||
}
|
||||
|
||||
bool isPermutation(size_t N)(auto ref in size_t[N] perm)
|
||||
{
|
||||
int[N] mask;
|
||||
return isValidPartialPermutationImpl(perm, mask);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
assert(isPermutation([0, 1]));
|
||||
// all numbers 0 .. N-1 need to be part of the permutation
|
||||
assert(!isPermutation([1, 2]));
|
||||
assert(!isPermutation([0, 2]));
|
||||
// duplicates are not allowed
|
||||
assert(!isPermutation([0, 1, 1]));
|
||||
|
||||
size_t[0] emptyArr;
|
||||
// empty permutations are not allowed either
|
||||
assert(!isPermutation(emptyArr));
|
||||
}
|
||||
|
||||
bool isValidPartialPermutation(size_t N)(in size_t[] perm)
|
||||
{
|
||||
int[N] mask;
|
||||
return isValidPartialPermutationImpl(perm, mask);
|
||||
}
|
||||
|
||||
private bool isValidPartialPermutationImpl(size_t N)(in size_t[] perm, ref int[N] mask)
|
||||
{
|
||||
if (perm.length == 0)
|
||||
return false;
|
||||
foreach (j; perm)
|
||||
{
|
||||
if (j >= N)
|
||||
return false;
|
||||
if (mask[j]) //duplicate
|
||||
return false;
|
||||
mask[j] = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
enum toSize_t(size_t i) = i;
|
||||
enum isSize_t(alias i) = is(typeof(i) == size_t);
|
||||
enum isIndex(I) = is(I : size_t);
|
||||
enum is_Slice(S) = is(S : _Slice);
|
||||
|
||||
private enum isReference(P) =
|
||||
hasIndirections!P
|
||||
|| isFunctionPointer!P
|
||||
|| is(P == interface);
|
||||
|
||||
enum hasReference(T) = anySatisfy!(isReference, RepresentationTypeTuple!T);
|
||||
|
||||
alias ImplicitlyUnqual(T) = Select!(isImplicitlyConvertible!(T, Unqual!T), Unqual!T, T);
|
||||
|
||||
//TODO: replace with `static foreach`
|
||||
template Iota(size_t i, size_t j)
|
||||
{
|
||||
static assert(i <= j, "Iota: i should be less than or equal to j");
|
||||
static if (i == j)
|
||||
alias Iota = AliasSeq!();
|
||||
else
|
||||
alias Iota = AliasSeq!(i, Iota!(i + 1, j));
|
||||
}
|
||||
|
||||
size_t lengthsProduct(size_t N)(auto ref in size_t[N] lengths)
|
||||
{
|
||||
size_t length = lengths[0];
|
||||
foreach (i; Iota!(1, N))
|
||||
length *= lengths[i];
|
||||
return length;
|
||||
}
|
||||
|
||||
pure nothrow @system unittest
|
||||
{
|
||||
const size_t[3] lengths = [3, 4, 5];
|
||||
assert(lengthsProduct(lengths) == 60);
|
||||
assert(lengthsProduct([3, 4, 5]) == 60);
|
||||
}
|
||||
|
||||
struct _Slice { size_t i, j; }
|
File diff suppressed because it is too large
Load diff
|
@ -1,581 +0,0 @@
|
|||
/+
|
||||
## Guide for Slice/BLAS contributors
|
||||
|
||||
1. Make sure functions are
|
||||
a. inlined(!),
|
||||
b. `@nogc`,
|
||||
c. `nothrow`,
|
||||
d. `pure`.
|
||||
For this reason, it is preferable to use _simple_ `assert`s with messages
|
||||
that can be computed at compile time.
|
||||
The goals are:
|
||||
1. to reduce executable size for _any_ compilation mode
|
||||
2. to reduce template bloat in object files
|
||||
3. to reduce compilation time
|
||||
4. to allow users to write extern C bindings for code libraries on `Slice` type.
|
||||
|
||||
2. `std.format`, `std.string`, and `std.conv` should not be used in error
|
||||
message formatting.`"Use" ~ Concatenation.stringof`.
|
||||
|
||||
3. `mixin template`s may be used for pretty error message formatting.
|
||||
|
||||
4. `Exception`s/`enforce`s should no be used to check indexes and lengths.
|
||||
Exceptions are only allowed for algorithms where validation of input data is
|
||||
too complicated for the user. `reshape` function is a good example of a case
|
||||
where Exceptions are required.
|
||||
If a function might throw an exception, an example with exception handing should be added.
|
||||
|
||||
5. For simple checks like matrix transposition, compile time flags should not be used.
|
||||
It is much better to opt for runtime matrix transposition.
|
||||
Furthermore, Slice type provides runtime matrix transposition out of the box.
|
||||
|
||||
6. _Fortran_VS_C_ flags should not be used. They are about notation,
|
||||
but not about the algorithm itself. For math world users,
|
||||
a corresponding code example might be included in the documentation.
|
||||
`transposed` / `everted` can be used in cache-friendly codes.
|
||||
|
||||
7. Compile time evaluation should not be used to produce dummy types like `IdentityMatrix`.
|
||||
|
||||
8. Memory allocation and algorithm logic should be separated whenever possible.
|
||||
|
||||
9. CTFE unittests should be added to new functions.
|
||||
+/
|
||||
|
||||
/**
|
||||
$(H1 Multidimensional Random Access Ranges)
|
||||
|
||||
The package provides a multidimensional array implementation.
|
||||
It would be well suited to creating machine learning and image
|
||||
processing algorithms, but should also be general enough for use anywhere with
|
||||
homogeneously-typed multidimensional data.
|
||||
In addition, it includes various functions for iteration, accessing, and manipulation.
|
||||
|
||||
Advanced and fast iteration algorithms, matrix multiplication, and BLAS-like functions
|
||||
can be found in the $(LINK2 http://mir.dlang.io, Mir
|
||||
LLVM-Accelerated Generic Numerical Library for Science and Machine Learning).
|
||||
|
||||
Quick_Start:
|
||||
$(SUBREF slice, sliced) is a function designed to create
|
||||
a multidimensional view over a range.
|
||||
Multidimensional view is presented by $(SUBREF slice, Slice) type.
|
||||
|
||||
------
|
||||
auto matrix = slice!double(3, 4);
|
||||
matrix[] = 0;
|
||||
matrix.diagonal[] = 1;
|
||||
|
||||
auto row = matrix[2];
|
||||
row[3] = 6;
|
||||
assert(matrix[2, 3] == 6); // D & C index order
|
||||
------
|
||||
|
||||
Note:
|
||||
In many examples $(SUBREF selection, iotaSlice) is used
|
||||
instead of a regular array, which makes it
|
||||
possible to carry out tests without memory allocation.
|
||||
|
||||
$(SCRIPT inhibitQuickIndex = 1;)
|
||||
|
||||
$(DIVC quickindex,
|
||||
$(BOOKTABLE ,
|
||||
|
||||
$(TR $(TH Submodule) $(TH Declarations))
|
||||
|
||||
$(TR $(TDNW $(SUBMODULE slice)
|
||||
$(BR) $(SMALL $(SUBREF slice, Slice), its properties, operator overloading))
|
||||
$(TD
|
||||
$(SUBREF slice, as)
|
||||
$(SUBREF slice, assumeSameStructure)
|
||||
$(SUBREF slice, DeepElementType)
|
||||
$(SUBREF slice, makeNdarray)
|
||||
$(SUBREF slice, makeSlice)
|
||||
$(SUBREF slice, makeUninitializedSlice)
|
||||
$(SUBREF slice, ndarray)
|
||||
$(SUBREF slice, ReplaceArrayWithPointer)
|
||||
$(SUBREF slice, shape)
|
||||
$(SUBREF slice, Slice)
|
||||
$(SUBREF slice, slice)
|
||||
$(SUBREF slice, sliced)
|
||||
$(SUBREF slice, SliceException)
|
||||
$(SUBREF slice, uninitializedSlice)
|
||||
)
|
||||
)
|
||||
$(TR $(TDNW $(SUBMODULE iteration)
|
||||
$(BR) $(SMALL Basic iteration operators))
|
||||
$(TD
|
||||
$(SUBREF iteration, allReversed)
|
||||
$(SUBREF iteration, everted)
|
||||
$(SUBREF iteration, reversed)
|
||||
$(SUBREF iteration, rotated)
|
||||
$(SUBREF iteration, strided)
|
||||
$(SUBREF iteration, swapped)
|
||||
$(SUBREF iteration, transposed)
|
||||
$(SUBREF iteration, dropToHypercube) and other `drop` primitives
|
||||
)
|
||||
)
|
||||
|
||||
$(TR $(TDNW $(SUBMODULE selection)
|
||||
$(BR) $(SMALL Subspace manipulations $(BR) Operators for loop free programming))
|
||||
$(TD
|
||||
$(SUBREF selection, blocks)
|
||||
$(SUBREF selection, byElement)
|
||||
$(SUBREF selection, byElementInStandardSimplex)
|
||||
$(SUBREF selection, diagonal)
|
||||
$(SUBREF selection, evertPack)
|
||||
$(SUBREF selection, indexSlice)
|
||||
$(SUBREF selection, iotaSlice)
|
||||
$(SUBREF selection, mapSlice)
|
||||
$(SUBREF selection, pack)
|
||||
$(SUBREF selection, repeatSlice)
|
||||
$(SUBREF selection, reshape)
|
||||
$(SUBREF selection, ReshapeException)
|
||||
$(SUBREF selection, unpack)
|
||||
$(SUBREF selection, windows)
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
$(H2 Example: Image Processing)
|
||||
|
||||
A median filter is implemented as an example. The function
|
||||
`movingWindowByChannel` can also be used with other filters that use a sliding
|
||||
window as the argument, in particular with convolution matrices such as the
|
||||
$(LINK2 https://en.wikipedia.org/wiki/Sobel_operator, Sobel operator).
|
||||
|
||||
`movingWindowByChannel` iterates over an image in sliding window mode.
|
||||
Each window is transferred to a `filter`, which calculates the value of the
|
||||
pixel that corresponds to the given window.
|
||||
|
||||
This function does not calculate border cases in which a window overlaps
|
||||
the image partially. However, the function can still be used to carry out such
|
||||
calculations. That can be done by creating an amplified image, with the edges
|
||||
reflected from the original image, and then applying the given function to the
|
||||
new file.
|
||||
|
||||
Note: You can find the example at
|
||||
$(LINK2 https://github.com/libmir/mir/blob/master/examples/median_filter.d, GitHub).
|
||||
|
||||
-------
|
||||
/++
|
||||
Params:
|
||||
filter = unary function. Dimension window 2D is the argument.
|
||||
image = image dimensions `(h, w, c)`,
|
||||
where с is the number of channels in the image
|
||||
nr = number of rows in the window
|
||||
nс = number of columns in the window
|
||||
|
||||
Returns:
|
||||
image dimensions `(h - nr + 1, w - nc + 1, c)`,
|
||||
where с is the number of channels in the image.
|
||||
Dense data layout is guaranteed.
|
||||
+/
|
||||
|
||||
Slice!(3, C*) movingWindowByChannel(alias filter, C)
|
||||
(Slice!(3, C*) image, size_t nr, size_t nc)
|
||||
{
|
||||
// 0. 3D
|
||||
// The last dimension represents the color channel.
|
||||
return image
|
||||
// 1. 2D composed of 1D
|
||||
// Packs the last dimension.
|
||||
.pack!1
|
||||
// 2. 2D composed of 2D composed of 1D
|
||||
// Splits image into overlapping windows.
|
||||
.windows(nr, nc)
|
||||
// 3. 5D
|
||||
// Unpacks the windows.
|
||||
.unpack
|
||||
// 4. 5D
|
||||
// Brings the color channel dimension to the third position.
|
||||
.transposed!(0, 1, 4)
|
||||
// 5. 3D Composed of 2D
|
||||
// Packs the last two dimensions.
|
||||
.pack!2
|
||||
// 2D to pixel lazy conversion.
|
||||
.mapSlice!filter
|
||||
// Creates the new image. The only memory allocation in this function.
|
||||
.slice;
|
||||
}
|
||||
-------
|
||||
|
||||
A function that calculates the value of iterator median is also necessary.
|
||||
|
||||
-------
|
||||
/++
|
||||
|
||||
Params:
|
||||
r = input range
|
||||
buf = buffer with length no less than the number of elements in `r`
|
||||
Returns:
|
||||
median value over the range `r`
|
||||
+/
|
||||
T median(Range, T)(Slice!(2, Range) sl, T[] buf)
|
||||
{
|
||||
import std.algorithm.sorting : topN;
|
||||
// copy sl to the buffer
|
||||
size_t n;
|
||||
foreach (r; sl)
|
||||
foreach (e; r)
|
||||
buf[n++] = e;
|
||||
buf[0 .. n].topN(n / 2);
|
||||
return buf[n / 2];
|
||||
}
|
||||
-------
|
||||
|
||||
The `main` function:
|
||||
|
||||
-------
|
||||
void main(string[] args)
|
||||
{
|
||||
import std.conv : to;
|
||||
import std.getopt : getopt, defaultGetoptPrinter;
|
||||
import std.path : stripExtension;
|
||||
|
||||
uint nr, nc, def = 3;
|
||||
auto helpInformation = args.getopt(
|
||||
"nr", "number of rows in window, default value is " ~ def.to!string, &nr,
|
||||
"nc", "number of columns in window, default value is equal to nr", &nc);
|
||||
if (helpInformation.helpWanted)
|
||||
{
|
||||
defaultGetoptPrinter(
|
||||
"Usage: median-filter [<options...>] [<file_names...>]\noptions:",
|
||||
helpInformation.options);
|
||||
return;
|
||||
}
|
||||
if (!nr) nr = def;
|
||||
if (!nc) nc = nr;
|
||||
|
||||
auto buf = new ubyte[nr * nc];
|
||||
|
||||
foreach (name; args[1 .. $])
|
||||
{
|
||||
import imageformats; // can be found at code.dlang.org
|
||||
|
||||
IFImage image = read_image(name);
|
||||
|
||||
auto ret = image.pixels
|
||||
.sliced(cast(size_t) image.h, cast(size_t) image.w, cast(size_t) image.c)
|
||||
.movingWindowByChannel
|
||||
!(window => median(window, buf))
|
||||
(nr, nc);
|
||||
|
||||
write_image(
|
||||
name.stripExtension ~ "_filtered.png",
|
||||
ret.length!1,
|
||||
ret.length!0,
|
||||
(&ret[0, 0, 0])[0 .. ret.elementsCount]);
|
||||
}
|
||||
}
|
||||
-------
|
||||
|
||||
This program works both with color and grayscale images.
|
||||
|
||||
-------
|
||||
$ median-filter --help
|
||||
Usage: median-filter [<options...>] [<file_names...>]
|
||||
options:
|
||||
--nr number of rows in window, default value is 3
|
||||
--nc number of columns in window default value equals to nr
|
||||
-h --help This help information.
|
||||
-------
|
||||
|
||||
$(H2 Compared with `numpy.ndarray`)
|
||||
|
||||
numpy is undoubtedly one of the most effective software packages that has
|
||||
facilitated the work of many engineers and scientists. However, due to the
|
||||
specifics of implementation of Python, a programmer who wishes to use the
|
||||
functions not represented in numpy may find that the built-in functions
|
||||
implemented specifically for numpy are not enough, and their Python
|
||||
implementations work at a very low speed. Extending numpy can be done, but
|
||||
is somewhat laborious as even the most basic numpy functions that refer
|
||||
directly to `ndarray` data must be implemented in C for reasonable performance.
|
||||
|
||||
At the same time, while working with `ndslice`, an engineer has access to the
|
||||
whole set of standard D library, so the functions he creates will be as
|
||||
efficient as if they were written in C.
|
||||
|
||||
License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
|
||||
|
||||
Authors: Ilya Yaroshenko
|
||||
|
||||
Acknowledgements: John Loughran Colvin
|
||||
|
||||
Source: $(PHOBOSSRC std/_experimental/_ndslice/_package.d)
|
||||
|
||||
Macros:
|
||||
SUBMODULE = $(MREF_ALTTEXT $1, std,experimental, ndslice, $1)
|
||||
SUBREF = $(REF_ALTTEXT $(TT $2), $2, std,experimental, ndslice, $1)$(NBSP)
|
||||
T2=$(TR $(TDNW $(LREF $1)) $(TD $+))
|
||||
TDNW2 = <td class="donthyphenate nobr" rowspan="2">$0</td>
|
||||
*/
|
||||
/// @@@DEPRECATED_2017-04@@@
|
||||
deprecated("Please use mir-algorithm DUB package: http://github.com/libmir/mir-algorithm")
|
||||
module std.experimental.ndslice;
|
||||
|
||||
public import std.experimental.ndslice.slice;
|
||||
public import std.experimental.ndslice.iteration;
|
||||
public import std.experimental.ndslice.selection;
|
||||
|
||||
@system unittest
|
||||
{
|
||||
auto matrix = new double[12].sliced(3, 4);
|
||||
matrix[] = 0;
|
||||
matrix.diagonal[] = 1;
|
||||
|
||||
auto row = matrix[2];
|
||||
row[3] = 6;
|
||||
assert(matrix[2, 3] == 6); // D & C index order
|
||||
assert(matrix(3, 2) == 6); // Math & Fortran index order
|
||||
}
|
||||
|
||||
// relaxed example
|
||||
@system unittest
|
||||
{
|
||||
static Slice!(3, ubyte*) movingWindowByChannel
|
||||
(Slice!(3, ubyte*) image, size_t nr, size_t nc, ubyte delegate(Slice!(2, ubyte*)) filter)
|
||||
{
|
||||
return image
|
||||
.pack!1
|
||||
.windows(nr, nc)
|
||||
.unpack
|
||||
.transposed!(0, 1, 4)
|
||||
.pack!2
|
||||
.mapSlice!filter
|
||||
.slice;
|
||||
}
|
||||
|
||||
static T median(Range, T)(Slice!(2, Range) sl, T[] buf)
|
||||
{
|
||||
import std.algorithm.sorting : topN;
|
||||
// copy sl to the buffer
|
||||
size_t n;
|
||||
foreach (r; sl)
|
||||
foreach (e; r)
|
||||
buf[n++] = e;
|
||||
buf[0 .. n].topN(n / 2);
|
||||
return buf[n / 2];
|
||||
}
|
||||
|
||||
import std.conv : to;
|
||||
import std.getopt : getopt, defaultGetoptPrinter;
|
||||
import std.path : stripExtension;
|
||||
|
||||
auto args = ["bin", "image"];
|
||||
uint nr, nc, def = 3;
|
||||
auto helpInformation = args.getopt(
|
||||
"nr", "number of rows in window, default value is " ~ def.to!string, &nr,
|
||||
"nc", "number of columns in window default value equals to nr", &nc);
|
||||
if (helpInformation.helpWanted)
|
||||
{
|
||||
defaultGetoptPrinter(
|
||||
"Usage: median-filter [<options...>] [<file_names...>]\noptions:",
|
||||
helpInformation.options);
|
||||
return;
|
||||
}
|
||||
if (!nr) nr = def;
|
||||
if (!nc) nc = nr;
|
||||
|
||||
auto buf = new ubyte[nr * nc];
|
||||
|
||||
foreach (name; args[1 .. $])
|
||||
{
|
||||
auto ret =
|
||||
movingWindowByChannel
|
||||
(new ubyte[300].sliced(10, 10, 3), nr, nc, window => median(window, buf));
|
||||
}
|
||||
}
|
||||
|
||||
@safe @nogc pure nothrow unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range : iota;
|
||||
immutable r = 1000.iota;
|
||||
|
||||
auto t0 = r.sliced(1000);
|
||||
assert(t0.front == 0);
|
||||
assert(t0.back == 999);
|
||||
assert(t0[9] == 9);
|
||||
|
||||
auto t1 = t0[10 .. 20];
|
||||
assert(t1.front == 10);
|
||||
assert(t1.back == 19);
|
||||
assert(t1[9] == 19);
|
||||
|
||||
t1.popFront();
|
||||
assert(t1.front == 11);
|
||||
t1.popFront();
|
||||
assert(t1.front == 12);
|
||||
|
||||
t1.popBack();
|
||||
assert(t1.back == 18);
|
||||
t1.popBack();
|
||||
assert(t1.back == 17);
|
||||
|
||||
assert(t1.equal(iota(12, 18)));
|
||||
}
|
||||
|
||||
pure nothrow @system unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.array : array;
|
||||
import std.range : iota;
|
||||
auto r = 1000.iota.array;
|
||||
|
||||
auto t0 = r.sliced(1000);
|
||||
assert(t0.length == 1000);
|
||||
assert(t0.front == 0);
|
||||
assert(t0.back == 999);
|
||||
assert(t0[9] == 9);
|
||||
|
||||
auto t1 = t0[10 .. 20];
|
||||
assert(t1.front == 10);
|
||||
assert(t1.back == 19);
|
||||
assert(t1[9] == 19);
|
||||
|
||||
t1.popFront();
|
||||
assert(t1.front == 11);
|
||||
t1.popFront();
|
||||
assert(t1.front == 12);
|
||||
|
||||
t1.popBack();
|
||||
assert(t1.back == 18);
|
||||
t1.popBack();
|
||||
assert(t1.back == 17);
|
||||
|
||||
assert(t1.equal(iota(12, 18)));
|
||||
|
||||
t1.front = 13;
|
||||
assert(t1.front == 13);
|
||||
t1.front++;
|
||||
assert(t1.front == 14);
|
||||
t1.front += 2;
|
||||
assert(t1.front == 16);
|
||||
t1.front = 12;
|
||||
assert((t1.front = 12) == 12);
|
||||
|
||||
t1.back = 13;
|
||||
assert(t1.back == 13);
|
||||
t1.back++;
|
||||
assert(t1.back == 14);
|
||||
t1.back += 2;
|
||||
assert(t1.back == 16);
|
||||
t1.back = 12;
|
||||
assert((t1.back = 12) == 12);
|
||||
|
||||
t1[3] = 13;
|
||||
assert(t1[3] == 13);
|
||||
t1[3]++;
|
||||
assert(t1[3] == 14);
|
||||
t1[3] += 2;
|
||||
assert(t1[3] == 16);
|
||||
t1[3] = 12;
|
||||
assert((t1[3] = 12) == 12);
|
||||
|
||||
t1[3 .. 5] = 100;
|
||||
assert(t1[2] != 100);
|
||||
assert(t1[3] == 100);
|
||||
assert(t1[4] == 100);
|
||||
assert(t1[5] != 100);
|
||||
|
||||
t1[3 .. 5] += 100;
|
||||
assert(t1[2] < 100);
|
||||
assert(t1[3] == 200);
|
||||
assert(t1[4] == 200);
|
||||
assert(t1[5] < 100);
|
||||
|
||||
--t1[3 .. 5];
|
||||
|
||||
assert(t1[2] < 100);
|
||||
assert(t1[3] == 199);
|
||||
assert(t1[4] == 199);
|
||||
assert(t1[5] < 100);
|
||||
|
||||
--t1[];
|
||||
assert(t1[3] == 198);
|
||||
assert(t1[4] == 198);
|
||||
|
||||
t1[] += 2;
|
||||
assert(t1[3] == 200);
|
||||
assert(t1[4] == 200);
|
||||
|
||||
t1[] *= t1[];
|
||||
assert(t1[3] == 40000);
|
||||
assert(t1[4] == 40000);
|
||||
|
||||
|
||||
assert(&t1[$ - 1] is &(t1.back()));
|
||||
}
|
||||
|
||||
@safe @nogc pure nothrow unittest
|
||||
{
|
||||
import std.range : iota;
|
||||
auto r = (10_000L * 2 * 3 * 4).iota;
|
||||
|
||||
auto t0 = r.sliced(10, 20, 30, 40);
|
||||
assert(t0.length == 10);
|
||||
assert(t0.length!0 == 10);
|
||||
assert(t0.length!1 == 20);
|
||||
assert(t0.length!2 == 30);
|
||||
assert(t0.length!3 == 40);
|
||||
}
|
||||
|
||||
pure nothrow @system unittest
|
||||
{
|
||||
import std.experimental.ndslice.internal : Iota;
|
||||
import std.meta : AliasSeq;
|
||||
import std.range;
|
||||
import std.typecons : Tuple;
|
||||
foreach (R; AliasSeq!(
|
||||
int*, int[], typeof(1.iota),
|
||||
const(int)*, const(int)[],
|
||||
immutable(int)*, immutable(int)[],
|
||||
double*, double[], typeof(10.0.iota),
|
||||
Tuple!(double, int[string])*, Tuple!(double, int[string])[]))
|
||||
foreach (n; Iota!(1, 4))
|
||||
{
|
||||
alias S = Slice!(n, R);
|
||||
static assert(isRandomAccessRange!S);
|
||||
static assert(hasSlicing!S);
|
||||
static assert(hasLength!S);
|
||||
}
|
||||
|
||||
immutable int[] im = [1,2,3,4,5,6];
|
||||
auto slice = im.sliced(2, 3);
|
||||
}
|
||||
|
||||
pure nothrow @system unittest
|
||||
{
|
||||
auto tensor = new int[3 * 4 * 8].sliced(3, 4, 8);
|
||||
assert(&(tensor.back.back.back()) is &tensor[2, 3, 7]);
|
||||
assert(&(tensor.front.front.front()) is &tensor[0, 0, 0]);
|
||||
}
|
||||
|
||||
pure nothrow @system unittest
|
||||
{
|
||||
import std.experimental.ndslice.selection : pack;
|
||||
auto slice = new int[24].sliced(2, 3, 4);
|
||||
auto r0 = slice.pack!1[1, 2];
|
||||
slice.pack!1[1, 2][] = 4;
|
||||
auto r1 = slice[1, 2];
|
||||
assert(slice[1, 2, 3] == 4);
|
||||
}
|
||||
|
||||
pure nothrow @system unittest
|
||||
{
|
||||
auto ar = new int[3 * 8 * 9];
|
||||
|
||||
auto tensor = ar.sliced(3, 8, 9);
|
||||
tensor[0, 1, 2] = 4;
|
||||
tensor[0, 1, 2]++;
|
||||
assert(tensor[0, 1, 2] == 5);
|
||||
tensor[0, 1, 2]--;
|
||||
assert(tensor[0, 1, 2] == 4);
|
||||
tensor[0, 1, 2] += 2;
|
||||
assert(tensor[0, 1, 2] == 6);
|
||||
|
||||
auto matrix = tensor[0 .. $, 1, 0 .. $];
|
||||
matrix[] = 10;
|
||||
assert(tensor[0, 1, 2] == 10);
|
||||
assert(matrix[0, 2] == tensor[0, 1, 2]);
|
||||
assert(&matrix[0, 2] is &tensor[0, 1, 2]);
|
||||
}
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
28
win32.mak
28
win32.mak
|
@ -327,13 +327,6 @@ SRC_STD_EXP_LOGGER= \
|
|||
std\experimental\logger\nulllogger.d \
|
||||
std\experimental\logger\package.d
|
||||
|
||||
SRC_STD_EXP_NDSLICE= \
|
||||
std\experimental\ndslice\package.d \
|
||||
std\experimental\ndslice\iteration.d \
|
||||
std\experimental\ndslice\selection.d \
|
||||
std\experimental\ndslice\slice.d \
|
||||
std\experimental\ndslice\internal.d
|
||||
|
||||
SRC_ETC=
|
||||
|
||||
SRC_ETC_C= \
|
||||
|
@ -363,7 +356,6 @@ SRC_TO_COMPILE= \
|
|||
$(SRC_STD_EXP) \
|
||||
$(SRC_STD_EXP_ALLOC) \
|
||||
$(SRC_STD_EXP_LOGGER) \
|
||||
$(SRC_STD_EXP_NDSLICE) \
|
||||
$(SRC_ETC) \
|
||||
$(SRC_ETC_C)
|
||||
|
||||
|
@ -523,10 +515,6 @@ DOCS= \
|
|||
$(DOC)\std_experimental_allocator_showcase.html \
|
||||
$(DOC)\std_experimental_allocator_typed.html \
|
||||
$(DOC)\std_experimental_allocator.html \
|
||||
$(DOC)\std_experimental_ndslice_iteration.html \
|
||||
$(DOC)\std_experimental_ndslice_selection.html \
|
||||
$(DOC)\std_experimental_ndslice_slice.html \
|
||||
$(DOC)\std_experimental_ndslice.html \
|
||||
$(DOC)\std_experimental_typecons.html \
|
||||
$(DOC)\std_windows_charset.html \
|
||||
$(DOC)\std_windows_registry.html \
|
||||
|
@ -571,8 +559,7 @@ UNITTEST_OBJS= \
|
|||
unittest8c.obj \
|
||||
unittest8d.obj \
|
||||
unittest8e.obj \
|
||||
unittest8f.obj \
|
||||
unittest9a.obj
|
||||
unittest8f.obj
|
||||
|
||||
unittest : $(LIB)
|
||||
$(DMD) $(UDFLAGS) -L/co -c -unittest -ofunittest1.obj $(SRC_STD_1)
|
||||
|
@ -591,7 +578,6 @@ unittest : $(LIB)
|
|||
$(DMD) $(UDFLAGS) -L/co -c -unittest -ofunittest8d.obj $(SRC_STD_INTERNAL) $(SRC_STD_INTERNAL_DIGEST) $(SRC_STD_INTERNAL_MATH) $(SRC_STD_INTERNAL_WINDOWS)
|
||||
$(DMD) $(UDFLAGS) -L/co -c -unittest -ofunittest8e.obj $(SRC_ETC) $(SRC_ETC_C)
|
||||
$(DMD) $(UDFLAGS) -L/co -c -unittest -ofunittest8f.obj $(SRC_STD_EXP)
|
||||
$(DMD) $(UDFLAGS) -L/co -c -unittest -ofunittest9a.obj $(SRC_STD_EXP_NDSLICE)
|
||||
$(DMD) $(UDFLAGS) -L/co -unittest unittest.d $(UNITTEST_OBJS) \
|
||||
$(ZLIB) $(DRUNTIMELIB)
|
||||
.\unittest.exe
|
||||
|
@ -1056,18 +1042,6 @@ $(DOC)\std_experimental_allocator.html : $(STDDOC) std\experimental\allocator\pa
|
|||
$(DOC)\std_experimental_typecons.html : $(STDDOC) std\experimental\typecons.d
|
||||
$(DMD) -c -o- $(DDOCFLAGS) -Df$(DOC)\std_experimental_typecons.html $(STDDOC) std\experimental\typecons.d
|
||||
|
||||
$(DOC)\std_experimental_ndslice_iteration.html : $(STDDOC) std\experimental\ndslice\iteration.d
|
||||
$(DMD) -c -o- $(DDOCFLAGS) -Df$(DOC)\std_experimental_ndslice_iteration.html $(STDDOC) std\experimental\ndslice\iteration.d
|
||||
|
||||
$(DOC)\std_experimental_ndslice_selection.html : $(STDDOC) std\experimental\ndslice\selection.d
|
||||
$(DMD) -c -o- $(DDOCFLAGS) -Df$(DOC)\std_experimental_ndslice_selection.html $(STDDOC) std\experimental\ndslice\selection.d
|
||||
|
||||
$(DOC)\std_experimental_ndslice_slice.html : $(STDDOC) std\experimental\ndslice\slice.d
|
||||
$(DMD) -c -o- $(DDOCFLAGS) -Df$(DOC)\std_experimental_ndslice_slice.html $(STDDOC) std\experimental\ndslice\slice.d
|
||||
|
||||
$(DOC)\std_experimental_ndslice.html : $(STDDOC) std\experimental\ndslice\package.d
|
||||
$(DMD) -c -o- $(DDOCFLAGS) -Df$(DOC)\std_experimental_ndslice.html $(STDDOC) std\experimental\ndslice\package.d
|
||||
|
||||
$(DOC)\std_digest_crc.html : $(STDDOC) std\digest\crc.d
|
||||
$(DMD) -c -o- $(DDOCFLAGS) -Df$(DOC)\std_digest_crc.html $(STDDOC) std\digest\crc.d
|
||||
|
||||
|
|
28
win64.mak
28
win64.mak
|
@ -346,13 +346,6 @@ SRC_STD_EXP_LOGGER= \
|
|||
std\experimental\logger\nulllogger.d \
|
||||
std\experimental\logger\package.d
|
||||
|
||||
SRC_STD_EXP_NDSLICE= \
|
||||
std\experimental\ndslice\package.d \
|
||||
std\experimental\ndslice\iteration.d \
|
||||
std\experimental\ndslice\selection.d \
|
||||
std\experimental\ndslice\slice.d \
|
||||
std\experimental\ndslice\internal.d
|
||||
|
||||
SRC_ETC=
|
||||
|
||||
SRC_ETC_C= \
|
||||
|
@ -382,7 +375,6 @@ SRC_TO_COMPILE= \
|
|||
$(SRC_STD_EXP) \
|
||||
$(SRC_STD_EXP_ALLOC) \
|
||||
$(SRC_STD_EXP_LOGGER) \
|
||||
$(SRC_STD_EXP_NDSLICE) \
|
||||
$(SRC_ETC) \
|
||||
$(SRC_ETC_C)
|
||||
|
||||
|
@ -542,10 +534,6 @@ DOCS= \
|
|||
$(DOC)\std_experimental_allocator_showcase.html \
|
||||
$(DOC)\std_experimental_allocator_typed.html \
|
||||
$(DOC)\std_experimental_allocator.html \
|
||||
$(DOC)\std_experimental_ndslice_iteration.html \
|
||||
$(DOC)\std_experimental_ndslice_selection.html \
|
||||
$(DOC)\std_experimental_ndslice_slice.html \
|
||||
$(DOC)\std_experimental_ndslice.html \
|
||||
$(DOC)\std_experimental_typecons.html \
|
||||
$(DOC)\std_windows_charset.html \
|
||||
$(DOC)\std_windows_registry.html \
|
||||
|
@ -599,8 +587,7 @@ UNITTEST_OBJS= \
|
|||
unittest8d.obj \
|
||||
unittest8e.obj \
|
||||
unittest8f.obj \
|
||||
unittest9.obj \
|
||||
unittest9a.obj
|
||||
unittest9.obj
|
||||
|
||||
unittest : $(LIB)
|
||||
$(DMD) $(UDFLAGS) -c -unittest -ofunittest1.obj $(SRC_STD_1)
|
||||
|
@ -628,7 +615,6 @@ unittest : $(LIB)
|
|||
$(DMD) $(UDFLAGS) -c -unittest -ofunittest8e.obj $(SRC_ETC) $(SRC_ETC_C)
|
||||
$(DMD) $(UDFLAGS) -c -unittest -ofunittest8f.obj $(SRC_STD_EXP)
|
||||
$(DMD) $(UDFLAGS) -c -unittest -ofunittest9.obj $(SRC_STD_EXP_ALLOC)
|
||||
$(DMD) $(UDFLAGS) -c -unittest -ofunittest9a.obj $(SRC_STD_EXP_NDSLICE)
|
||||
$(DMD) $(UDFLAGS) -L/OPT:NOICF -unittest unittest.d $(UNITTEST_OBJS) \
|
||||
$(ZLIB) $(DRUNTIMELIB)
|
||||
.\unittest.exe
|
||||
|
@ -1028,18 +1014,6 @@ $(DOC)\std_experimental_allocator.html : $(STDDOC) std\experimental\allocator\pa
|
|||
$(DOC)\std_experimental_typecons.html : $(STDDOC) std\experimental\typecons.d
|
||||
$(DMD) -c -o- $(DDOCFLAGS) -Df$(DOC)\std_experimental_typecons.html $(STDDOC) std\experimental\typecons.d
|
||||
|
||||
$(DOC)\std_experimental_ndslice_iteration.html : $(STDDOC) std\experimental\ndslice\iteration.d
|
||||
$(DMD) -c -o- $(DDOCFLAGS) -Df$(DOC)\std_experimental_ndslice_iteration.html $(STDDOC) std\experimental\ndslice\iteration.d
|
||||
|
||||
$(DOC)\std_experimental_ndslice_selection.html : $(STDDOC) std\experimental\ndslice\selection.d
|
||||
$(DMD) -c -o- $(DDOCFLAGS) -Df$(DOC)\std_experimental_ndslice_selection.html $(STDDOC) std\experimental\ndslice\selection.d
|
||||
|
||||
$(DOC)\std_experimental_ndslice_slice.html : $(STDDOC) std\experimental\ndslice\slice.d
|
||||
$(DMD) -c -o- $(DDOCFLAGS) -Df$(DOC)\std_experimental_ndslice_slice.html $(STDDOC) std\experimental\ndslice\slice.d
|
||||
|
||||
$(DOC)\std_experimental_ndslice.html : $(STDDOC) std\experimental\ndslice\package.d
|
||||
$(DMD) -c -o- $(DDOCFLAGS) -Df$(DOC)\std_experimental_ndslice.html $(STDDOC) std\experimental\ndslice\package.d
|
||||
|
||||
$(DOC)\std_digest_crc.html : $(STDDOC) std\digest\crc.d
|
||||
$(DMD) -c -o- $(DDOCFLAGS) -Df$(DOC)\std_digest_crc.html $(STDDOC) std\digest\crc.d
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue