@@ -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+ }
0 commit comments