Skip to content

Commit 83609c9

Browse files
committed
rework stairs iterator
1 parent 581c0ca commit 83609c9

File tree

2 files changed

+77
-28
lines changed

2 files changed

+77
-28
lines changed

source/mir/ndslice/iterator.d

Lines changed: 70 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,24 +1621,25 @@ version(mir_test) unittest
16211621
/++
16221622
`StairsIterator` is used by $(SUBREF topology, stairs).
16231623
+/
1624-
struct StairsIterator(Iterator)
1624+
struct StairsIterator(Iterator, string direction)
1625+
if (direction == "+" || direction == "-")
16251626
{
16261627
///
1627-
size_t _length = 1;
1628+
size_t _length;
16281629

16291630
///
16301631
Iterator _iterator;
16311632

16321633
///
16331634
auto lightConst()() const @property
16341635
{
1635-
return StairsIterator!(LightConstOf!Iterator)(_length, _iterator.lightConst);
1636+
return StairsIterator!(LightConstOf!Iterator, direction)(_length, _iterator.lightConst);
16361637
}
16371638

16381639
///
16391640
auto lightImmutable()() immutable @property
16401641
{
1641-
return StairsIterator!(LightImmutableOf!Iterator)(_length, _iterator.lightImmutable);
1642+
return StairsIterator!(LightImmutableOf!Iterator, direction)(_length, _iterator.lightImmutable);
16421643
}
16431644

16441645
@optmath:
@@ -1654,9 +1655,17 @@ struct StairsIterator(Iterator)
16541655
Slice!Iterator opIndex()(ptrdiff_t index)
16551656
{
16561657
import mir.ndslice.slice: sliced;
1657-
auto newLength = _length + index;
1658+
static if (direction == "+")
1659+
{
1660+
auto newLength = _length + index;
1661+
auto shift = ptrdiff_t(_length + newLength - 1) * index / 2;
1662+
}
1663+
else
1664+
{
1665+
auto newLength = _length - index;
1666+
auto shift = ptrdiff_t(_length + newLength + 1) * index / 2;
1667+
}
16581668
assert(ptrdiff_t(newLength) >= 0);
1659-
auto shift = ptrdiff_t(_length + newLength - 1) * index / 2;
16601669
return (_iterator + shift).sliced(newLength);
16611670
}
16621671

@@ -1666,24 +1675,39 @@ struct StairsIterator(Iterator)
16661675
static if (op == "++")
16671676
{
16681677
_iterator += _length;
1669-
++_length;
1678+
static if (direction == "+")
1679+
++_length;
1680+
else
1681+
--_length;
16701682
}
16711683
else
16721684
{
16731685
assert(_length);
1674-
--_length;
1686+
static if (direction == "+")
1687+
--_length;
1688+
else
1689+
++_length;
16751690
_iterator -= _length;
16761691
}
16771692
}
16781693

16791694
void opOpAssign(string op)(ptrdiff_t index)
16801695
if (op == "-" || op == "+")
16811696
{
1682-
auto newLength = mixin("_length " ~ op ~ " index");
1697+
static if (op == direction)
1698+
auto newLength = _length + index;
1699+
else
1700+
auto newLength = _length - index;
1701+
static if (direction == "+")
1702+
auto shift = ptrdiff_t(_length + newLength - 1) * index / 2;
1703+
else
1704+
auto shift = ptrdiff_t(_length + newLength + 1) * index / 2;
16831705
assert(ptrdiff_t(newLength) >= 0);
1684-
auto shift = ptrdiff_t(_length + newLength - 1) * index / 2;
16851706
_length = newLength;
1686-
mixin("_iterator " ~ op ~ "= shift;");
1707+
static if (op == "+")
1708+
_iterator += shift;
1709+
else
1710+
_iterator -= shift;
16871711
}
16881712

16891713
auto opBinary(string op)(ptrdiff_t index)
@@ -1695,13 +1719,18 @@ struct StairsIterator(Iterator)
16951719
}
16961720

16971721
ptrdiff_t opBinary(string op : "-")(auto ref const typeof(this) right) const
1698-
{ return this._length - right._length; }
1722+
{
1723+
static if (direction == "+")
1724+
return this._length - right._length;
1725+
else
1726+
return right._length - this._length;
1727+
}
16991728

17001729
bool opEquals()(ref const typeof(this) right) const
17011730
{ return this._length == right._length; }
17021731

17031732
ptrdiff_t opCmp()(ref const typeof(this) right) const
1704-
{ return this._length - right._length; }
1733+
{ return this - right; }
17051734
}
17061735

17071736
///
@@ -1712,7 +1741,7 @@ version(mir_test) unittest
17121741
// 3 4 5
17131742
// 6 7 8 9
17141743
// 10 11 12 13 14
1715-
auto it = StairsIterator!(IotaIterator!size_t)(1, IotaIterator!size_t());
1744+
auto it = StairsIterator!(IotaIterator!size_t, "+")(1, IotaIterator!size_t());
17161745
assert(*it == [0]);
17171746
assert(it[4] == [10, 11, 12, 13, 14]);
17181747
assert(*(it + 4) == [10, 11, 12, 13, 14]);
@@ -1724,7 +1753,33 @@ version(mir_test) unittest
17241753
assert(*(it - 3) == [1, 2]);
17251754
assert(it + 1 > it);
17261755
assert(it + 1 - 1 == it);
1727-
assert(it + 3 - it == 3);
1756+
assert(it - 3 - it == -3);
17281757
--it;
17291758
assert(*it == [6, 7, 8, 9]);
17301759
}
1760+
1761+
///
1762+
version(mir_test) unittest
1763+
{
1764+
// [0, 1, 2, 3, 4],
1765+
// [5, 6, 7, 8],
1766+
// [9, 10, 11],
1767+
// [12, 13],
1768+
// [14]]);
1769+
1770+
auto it = StairsIterator!(IotaIterator!size_t, "-")(5, IotaIterator!size_t());
1771+
assert(*it == [0, 1, 2, 3, 4]);
1772+
assert(it[4] == [14]);
1773+
assert(*(it + 4) == [14]);
1774+
++it;
1775+
assert(*it == [5, 6, 7, 8]);
1776+
it += 3;
1777+
assert(*it == [14]);
1778+
assert(it[-3] == [5, 6, 7, 8]);
1779+
assert(*(it - 3) == [5, 6, 7, 8]);
1780+
assert(it + 1 > it);
1781+
assert(it + 1 - 1 == it);
1782+
assert(it - 3 - it == -3);
1783+
--it;
1784+
assert(*it == [12, 13]);
1785+
}

source/mir/ndslice/topology.d

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3532,27 +3532,19 @@ Returns:
35323532
35333533
See_also: $(LREF ._stairs.2)
35343534
+/
3535-
auto stairs(string type, Iterator)(Slice!Iterator slice, size_t n)
3535+
Slice!(StairsIterator!(Iterator, type)) stairs(string type, Iterator)(Slice!Iterator slice, size_t n)
35363536
if (type == "+" || type == "-")
35373537
{
35383538
assert(slice.length == (n + 1) * n / 2, "stairs: slice length must be equal to n * (n + 1) / 2, where n is stairs count.");
35393539
static if (type == "+")
3540-
{
3541-
return StairsIterator!Iterator(1, slice._iterator)
3542-
.sliced(n);
3543-
}
3540+
size_t length = 1;
35443541
else
3545-
{
3546-
auto it = slice.retro._iterator;
3547-
return StairsIterator!(typeof(it))(1, it)
3548-
.sliced(n)
3549-
.map!retro
3550-
.retro;
3551-
}
3542+
size_t length = n;
3543+
return StairsIterator!(Iterator, type)(length, slice._iterator).sliced(n);
35523544
}
35533545

35543546
/// ditto
3555-
auto stairs(string type, S)(S[] slice, size_t n)
3547+
Slice!(StairsIterator!(S*, type)) stairs(string type, S)(S[] slice, size_t n)
35563548
if (type == "+" || type == "-")
35573549
{
35583550
return stairs!type(slice.sliced, n);
@@ -3580,13 +3572,15 @@ version(mir_test) unittest
35803572
[3, 4, 5],
35813573
[6, 7, 8, 9],
35823574
[10, 11, 12, 13, 14]]);
3575+
assert(inc[1 .. $][2] == [6, 7, 8, 9]);
35833576

35843577
assert(dec == [
35853578
[0, 1, 2, 3, 4],
35863579
[5, 6, 7, 8],
35873580
[9, 10, 11],
35883581
[12, 13],
35893582
[14]]);
3583+
assert(dec[1 .. $][2] == [12, 13]);
35903584

35913585
static assert(is(typeof(inc.front) == typeof(pck)));
35923586
static assert(is(typeof(dec.front) == typeof(pck)));

0 commit comments

Comments
 (0)