Skip to content

Commit 39957b5

Browse files
authored
Merge pull request #4782 from 9il/repeatSlice
add repeatSlice
2 parents 8170aac + 1ea8b7a commit 39957b5

File tree

4 files changed

+154
-3
lines changed

4 files changed

+154
-3
lines changed

std/experimental/ndslice/internal.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module std.experimental.ndslice.internal;
33
import std.traits;
44
import std.meta; //: AliasSeq, anySatisfy, Filter, Reverse;
55

6-
package:
6+
struct LikePtr {}
77

88
alias isMemory = isPointer;
99

std/experimental/ndslice/package.d

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ $(TR $(TDNW Advanced Level $(BR)
122122
$(SUBREF selection, byElementInStandardSimplex)
123123
$(SUBREF selection, indexSlice)
124124
$(SUBREF selection, iotaSlice)
125+
$(SUBREF selection, repeatSlice)
125126
$(SUBREF selection, pack)
126127
$(SUBREF selection, evertPack)
127128
$(SUBREF selection, unpack)

std/experimental/ndslice/selection.d

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ $(T2 byElementInStandardSimplex, an input range of all elements in standard simp
3232
If the slice has two dimensions, it is a range of all elements of upper left triangular matrix.)
3333
$(T2 indexSlice, lazy slice with initial multidimensional index)
3434
$(T2 iotaSlice, lazy slice with initial flattened (continuous) index)
35+
$(T2 repeatSlice, slice with identical values)
3536
$(T2 reshape, new slice with changed dimensions for the same data)
3637
$(T2 diagonal, 1-dimensional slice composed of diagonal elements)
3738
$(T2 blocks, n-dimensional slice composed of n-dimensional non-overlapping blocks.
@@ -1791,3 +1792,154 @@ struct IotaMap()
17911792
return index;
17921793
}
17931794
}
1795+
1796+
/++
1797+
Returns a slice with identical elements.
1798+
`RepeatSlice` stores only single value.
1799+
Params:
1800+
lengths = list of dimension lengths
1801+
Returns:
1802+
`n`-dimensional slice composed of identical values, where `n` is dimension count.
1803+
See_also: $(REF repeat, std,range)
1804+
+/
1805+
RepeatSlice!(Lengths.length, T) repeatSlice(T, Lengths...)(T value, Lengths lengths)
1806+
if (allSatisfy!(isIndex, Lengths) && !is(T : Slice!(N, Range), size_t N, Range))
1807+
{
1808+
typeof(return) ret;
1809+
foreach (i; Iota!(0, ret.N))
1810+
ret._lengths[i] = lengths[i];
1811+
ret._ptr = RepeatPtr!T(value);
1812+
return ret;
1813+
}
1814+
1815+
/// ditto
1816+
Slice!(Lengths.length, Slice!(N + 1, Range)) repeatSlice(size_t N, Range, Lengths...)(auto ref Slice!(N, Range) slice, Lengths lengths)
1817+
if (allSatisfy!(isIndex, Lengths) && Lengths.length)
1818+
{
1819+
enum M = Lengths.length;
1820+
typeof(return) ret;
1821+
ret._ptr = slice._ptr;
1822+
foreach (i; Iota!(0, M))
1823+
ret._lengths[i] = lengths[i];
1824+
foreach (i; Iota!(0, N))
1825+
{
1826+
ret._lengths[M + i] = slice._lengths[i];
1827+
ret._strides[M + i] = slice._strides[i];
1828+
}
1829+
return ret;
1830+
}
1831+
1832+
///
1833+
@safe pure nothrow unittest
1834+
{
1835+
auto sl = iotaSlice(3)
1836+
.repeatSlice(4);
1837+
assert(sl == [[0, 1, 2],
1838+
[0, 1, 2],
1839+
[0, 1, 2],
1840+
[0, 1, 2]]);
1841+
}
1842+
1843+
///
1844+
@safe pure nothrow unittest
1845+
{
1846+
import std.experimental.ndslice.iteration : transposed;
1847+
1848+
auto sl = iotaSlice(3)
1849+
.repeatSlice(4)
1850+
.unpack
1851+
.transposed;
1852+
1853+
assert(sl == [[0, 0, 0, 0],
1854+
[1, 1, 1, 1],
1855+
[2, 2, 2, 2]]);
1856+
}
1857+
1858+
///
1859+
pure nothrow unittest
1860+
{
1861+
import std.experimental.ndslice.slice : slice;
1862+
1863+
auto sl = iotaSlice([3], 6).slice;
1864+
auto slC = sl.repeatSlice(2, 3);
1865+
sl[1] = 4;
1866+
assert(slC == [[[6, 4, 8],
1867+
[6, 4, 8],
1868+
[6, 4, 8]],
1869+
[[6, 4, 8],
1870+
[6, 4, 8],
1871+
[6, 4, 8]]]);
1872+
}
1873+
1874+
///
1875+
@safe pure nothrow unittest
1876+
{
1877+
auto sl = repeatSlice(4.0, 2, 3);
1878+
assert(sl == [[4.0, 4.0, 4.0],
1879+
[4.0, 4.0, 4.0]]);
1880+
1881+
static assert(is(DeepElementType!(typeof(sl)) == double));
1882+
1883+
sl[1, 1] = 3;
1884+
assert(sl == [[3.0, 3.0, 3.0],
1885+
[3.0, 3.0, 3.0]]);
1886+
}
1887+
1888+
/++
1889+
Slice composed of identical values.
1890+
+/
1891+
template RepeatSlice(size_t N, T)
1892+
if (N)
1893+
{
1894+
alias RepeatSlice = Slice!(N, RepeatPtr!T);
1895+
}
1896+
1897+
// undocumented
1898+
// zero cost variant of `std.range.repeat`
1899+
// in addition, the internal value is mutable
1900+
@LikePtr struct RepeatPtr(T)
1901+
{
1902+
// UT definition is from std.range
1903+
// Store a non-qualified T when possible: This is to make RepeatPtr assignable
1904+
static if ((is(T == class) || is(T == interface)) && (is(T == const) || is(T == immutable)))
1905+
{
1906+
import std.typecons : Rebindable;
1907+
private alias UT = Rebindable!T;
1908+
}
1909+
else static if (is(T : Unqual!T) && is(Unqual!T : T))
1910+
private alias UT = Unqual!T;
1911+
else
1912+
private alias UT = T;
1913+
private UT _value;
1914+
1915+
ref T opIndex(sizediff_t)
1916+
{
1917+
return _value;
1918+
}
1919+
1920+
void opOpAssign(string op)(sizediff_t)
1921+
if (op == `+` || op == `-`)
1922+
{
1923+
}
1924+
1925+
auto opBinary(string op)(sizediff_t)
1926+
if (op == `+` || op == `-`)
1927+
{
1928+
return this;
1929+
}
1930+
1931+
auto ref opUnary(string op)()
1932+
if (op == `++` || op == `--`)
1933+
{
1934+
return this;
1935+
}
1936+
}
1937+
1938+
@safe pure nothrow @nogc unittest
1939+
{
1940+
RepeatPtr!double val;
1941+
val._value = 3;
1942+
assert((++val)._value == 3);
1943+
val += 2;
1944+
assert((val + 3)._value == 3);
1945+
}

std/experimental/ndslice/slice.d

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3301,8 +3301,6 @@ unittest
33013301

33023302
private enum isSlicePointer(T) = isPointer!T || is(T : PtrShell!R, R);
33033303

3304-
private struct LikePtr {}
3305-
33063304
package template hasPtrBehavior(T)
33073305
{
33083306
static if (isPointer!T)

0 commit comments

Comments
 (0)