{"action":"created","issue":{"url":"https://api.github.com/repos/D-Programming-Language/phobos/issues/3397","labels_url":"https://api.github.com/repos/D-Programming-Language/phobos/issues/3397/labels{/name}","comments_url":"https://api.github.com/repos/D-Programming-Language/phobos/issues/3397/comments","events_url":"https://api.github.com/repos/D-Programming-Language/phobos/issues/3397/events","html_url":"https://github.com/D-Programming-Language/phobos/pull/3397","id":86615172,"number":3397,"title":"n-dimensional slice-shell [ready for comments]","user":{"login":"9il","id":845083,"avatar_url":"https://avatars.githubusercontent.com/u/845083?v=3","gravatar_id":"","url":"https://api.github.com/users/9il","html_url":"https://github.com/9il","followers_url":"https://api.github.com/users/9il/followers","following_url":"https://api.github.com/users/9il/following{/other_user}","gists_url":"https://api.github.com/users/9il/gists{/gist_id}","starred_url":"https://api.github.com/users/9il/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/9il/subscriptions","organizations_url":"https://api.github.com/users/9il/orgs","repos_url":"https://api.github.com/users/9il/repos","events_url":"https://api.github.com/users/9il/events{/privacy}","received_events_url":"https://api.github.com/users/9il/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":46,"created_at":"2015-06-09T14:20:31Z","updated_at":"2015-06-15T16:45:31Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/3397","html_url":"https://github.com/D-Programming-Language/phobos/pull/3397","diff_url":"https://github.com/D-Programming-Language/phobos/pull/3397.diff","patch_url":"https://github.com/D-Programming-Language/phobos/pull/3397.patch"},"body":"DUB package at [dip80-ndslice at code.dlang.org](http://code.dlang.org/packages/dip80-ndslice).\r\n\r\n# Requests:\r\n#### `projection` template\r\n#### Remove range properties\r\n#### Iteration over N-1 dimension\r\nImplement `byDim` property\r\n#### `shape` rework\r\n> Alternatively, the existing shape could be renamed structure and shape would just return the lengths, like it does in numpy.\r\n\r\n#### Iterating over elements\r\n_1. `byElement`\r\n```D\r\nforeach(elem; tensor.byElement) {...}\r\nforeach(ref elem; tensor.byElement) {...}\r\n```\r\n\r\n_2. `byIndexedElement`\r\n```D\r\nforeach(i, j, k, elem; tensor3D.byIndexedElement) {...}\r\n```\r\n\r\n_3. `opApply` for indexed  `foreach` with `ref`\r\n```D\r\nforeach(i, j, k, ref elem; tensor3D) {...}\r\n```\r\n#### Lazy functionality like deep `map` and deep `zip`\r\nView from core team is wanted!\r\n\r\n# Implemented requests\r\n1. `shape` property https://github.com/9il/phobos/commit/eacc511398326e28297b9fdf2d69e6adf2af9e7b\r\n2. Numpy like `shape` property, structure property https://github.com/9il/phobos/commit/b5fb8956a4b5c60d3820cf00a4d1f4684bd220e0\r\n\r\n# n-dimensional slices\r\n##### Slicing\r\n```D\r\n    auto a = 1000000.iota.sliced(10, 20, 30, 40);\r\n    auto b = a[0..$, 10, 4..27, 4];\r\n    auto c = b[2..9, 5..10];\r\n    auto d = b[3..$, $-2];\r\n    assert(b[4, 17] == a[4, 10, 21, 4]);\r\n    assert(c[1, 2] == a[3, 10, 11, 4]);\r\n    assert(d[3] == a[6, 10, 25, 4]);\r\n```\r\n##### Operator overloading. # 1\r\n```D\r\n    auto fun(ref int x) { x *= 3; }\r\n\r\n    auto tensor = 1000\r\n        .iota\r\n        .array\r\n        .sliced(8, 9, 10);\r\n\r\n    ++tensor[];\r\n    fun(tensor[0, 0, 0]);\r\n\r\n    assert(tensor[0, 0, 0] == 3);\r\n\r\n    tensor[0, 0, 0] *= 4;\r\n    tensor[0, 0, 0]--;\r\n    assert(tensor[0, 0, 0] == 11);\r\n```\r\n##### Operator overloading. # 2\r\n```D\r\n    auto matrix = 100\r\n        .iota\r\n        .map!(i => BigInt(i))\r\n        .array\r\n        .sliced(8, 9);\r\n\r\n    matrix[3..6, 2] += 100;\r\n    foreach(i; 0..8)\r\n        foreach(j; 0..9)\r\n            if(i >= 3 && i < 6 && j == 2)\r\n                assert(matrix[i, j] >= 100);\r\n            else\r\n                assert(matrix[i, j] < 100);\r\n```\r\n##### Operator overloading. # 3\r\n```D\r\n    auto matrix = 100\r\n        .iota\r\n        .array\r\n        .sliced(8, 9);\r\n    assert(matrix.equal(matrix));\r\n\r\n    matrix[] = matrix;\r\n    matrix[] += matrix;\r\n    assert(matrix[2, 3] == (2 * 9 + 3) * 2);\r\n    \r\n    auto vec = iota(100, 200).sliced(9);\r\n    matrix[] = vec;\r\n    foreach(v; matrix)\r\n        assert(v.equal(vec));\r\n\r\n    matrix[] += vec;\r\n    foreach(vector; matrix)\r\n        foreach(elem; vector)\r\n            assert(elem >= 200);\r\n```\r\n##### Properties and methods\r\n```D\r\n    auto tensor = 100.iota.sliced(3, 4, 5);\r\n    static assert(isRandomAccessRange!(typeof(tensor)));\r\n\r\n    // `save` method\r\n    // Calls `range.save`\r\n    auto a = tensor.save;\r\n    static assert(is(typeof(a) == typeof(tensor)));\r\n\r\n    // `length` property\r\n    assert(tensor.length   == 3);\r\n    assert(tensor.length!0 == 3);\r\n    assert(tensor.length!1 == 4);\r\n    assert(tensor.length!2 == 5);\r\n\r\n    // `front` and `back` properties\r\n    // and `popFront`, `popBack`, \r\n    // `popFrontN` and `popBackN` methods\r\n    auto matrix = tensor.back;\r\n    matrix.popBack!1;\r\n    auto column = matrix.back!1;\r\n    column.popFrontN(3);\r\n    auto elem = column.front!0;\r\n    assert(elem == tensor[$-1, 3, $-2]);\r\n\r\n    // `stride` property\r\n    assert(tensor.stride   == 20);\r\n    assert(tensor.stride!0 == 20);\r\n    assert(tensor.stride!1 ==  5);\r\n    assert(tensor.stride!2 ==  1);\r\n\r\n    assert(matrix.stride   ==  5);\r\n    assert(matrix.stride!1 ==  1);\r\n    \r\n    matrix = tensor.back!2;\r\n    assert(matrix.stride   == 20);\r\n    assert(matrix.stride!1 ==  5);\r\n\r\n    // `structure` property\r\n    auto structure = tensor.structure;\r\n    assert(tensor.length!2 == structure.lengths[2]);\r\n    assert(tensor.stride!1 == structure.strides[1]);\r\n    import std.typecons: Tuple;\r\n    alias Structure = Tuple!(size_t[3], \"lengths\", size_t[3], \"strides\");\r\n    static assert(is(typeof(structure) == Structure));\r\n\r\n    // `shape` property\r\n    assert(tensor.shape == structure.lengths);\r\n\r\n    // `range` method\r\n    // Calls `range.save`.\r\n    auto theIota0 = tensor.range;\r\n    assert(theIota0.front == 0);\r\n    tensor.popFront;\r\n    auto theIota1 = tensor.range;\r\n    assert(theIota1.front == 20);\r\n\r\n    // `ptr` property\r\n    import std.array: array;\r\n    auto ar = 100.iota.array;\r\n    auto ts = ar.sliced(3, 4, 5)[1..$, 2..$, 3..$];\r\n    assert(ts.ptr is ar.ptr + 1*20+2*5+3*1);\r\n```\r\n##### Type conversion\r\n```D\r\n    foreach(T; TypeTuple!(int, const int, immutable int))\r\n        static assert(is(typeof((T[]).init.sliced(3, 4)) == Slice!(2, T*)));\r\n    \r\n    Array!int ar;\r\n    static assert(is(typeof(ar[].sliced(3, 4)) == Slice!(2, typeof(ar[]))));\r\n\r\n    auto      i0 = 100.iota;\r\n    const     i1 = 100.iota; \r\n    immutable i2 = 100.iota;\r\n    alias S = Slice!(3, typeof(iota(0))); //unqualified range\r\n    // const/immutable Iota is implicitly convertable to unqualified type\r\n    foreach(i; TypeTuple!(i0, i1, i2))\r\n        static assert(is(typeof(i.sliced(3, 4, 5)) == S));\r\n```\r\n##### N-dimenstional transpose operator\r\n```D\r\n    auto t0 = 1000.iota.sliced(3, 4, 5);\r\n    auto t1 = t0.transposed!(2, 0, 1); //CTFE - recommended\r\n    auto t2 = t0.transposed (2, 0, 1); //Runtime\r\n    assert(t0[1, 2, 3] == t1[3, 1, 2]);\r\n    assert(t0[1, 2, 3] == t2[3, 1, 2]);\r\n    static assert(is(typeof(t0) == typeof(t1)));\r\n    static assert(is(typeof(t0) == typeof(t2)));\r\n```\r\n##### 2-dimenstional transpose operator\r\n```D\r\n    auto t0 = 1000.iota.sliced(3, 4);\r\n    auto t1 = t0.transposed();      //CTFE\r\n    auto t2 = t0.transposed!(1, 0); //CTFE\r\n    assert(t0[1, 2] == t1[2, 1]);\r\n    assert(t0[1, 2] == t2[2, 1]);\r\n    static assert(is(typeof(t0) == typeof(t1)));\r\n    static assert(is(typeof(t0) == typeof(t2)));\r\n```\r\n##### References: \r\n1. [DIP80 Phobos additions](http://wiki.dlang.org/DIP80) (BLAS support)\r\n2. [Discussion](http://forum.dlang.org/thread/eubhesirsvtnqowbevdm@forum.dlang.org?page=3) about DIP80/BLAS at forum."},"comment":{"url":"https://api.github.com/repos/D-Programming-Language/phobos/issues/comments/112132925","html_url":"https://github.com/D-Programming-Language/phobos/pull/3397#issuecomment-112132925","issue_url":"https://api.github.com/repos/D-Programming-Language/phobos/issues/3397","id":112132925,"user":{"login":"John-Colvin","id":1867189,"avatar_url":"https://avatars.githubusercontent.com/u/1867189?v=3","gravatar_id":"","url":"https://api.github.com/users/John-Colvin","html_url":"https://github.com/John-Colvin","followers_url":"https://api.github.com/users/John-Colvin/followers","following_url":"https://api.github.com/users/John-Colvin/following{/other_user}","gists_url":"https://api.github.com/users/John-Colvin/gists{/gist_id}","starred_url":"https://api.github.com/users/John-Colvin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/John-Colvin/subscriptions","organizations_url":"https://api.github.com/users/John-Colvin/orgs","repos_url":"https://api.github.com/users/John-Colvin/repos","events_url":"https://api.github.com/users/John-Colvin/events{/privacy}","received_events_url":"https://api.github.com/users/John-Colvin/received_events","type":"User","site_admin":false},"created_at":"2015-06-15T16:45:31Z","updated_at":"2015-06-15T16:45:31Z","body":"A not on the lazy range operations: The way I currently see them, they aren't a blocker for getting this done, they're are a totally additive change that would be built on top of map and zip. They could even by added by a wrapper type."}}