Skip to content

Commit 69d8366

Browse files
authored
optimise iteratino algorithms for rc types and fix issue 202 (#203)
1 parent 2d4c600 commit 69d8366

File tree

4 files changed

+112
-49
lines changed

4 files changed

+112
-49
lines changed

source/mir/algorithm/iteration.d

Lines changed: 62 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ Macros:
4545
*/
4646
module mir.algorithm.iteration;
4747

48-
import mir.primitives;
4948
import mir.functional: naryFun;
5049
import mir.internal.utility;
5150
import mir.math.common: optmath;
@@ -54,6 +53,7 @@ import mir.ndslice.internal;
5453
import mir.ndslice.iterator: FieldIterator, RetroIterator;
5554
import mir.ndslice.slice;
5655
import mir.primitives;
56+
import mir.qualifier;
5757
import std.meta;
5858
import std.range.primitives: isInputRange, isBidirectionalRange, isInfinite, isForwardRange, ElementType;
5959
import std.traits;
@@ -567,14 +567,20 @@ template frontOf(size_t N)
567567
}
568568
}
569569

570-
template allFlattened(size_t N)
571-
if (N)
570+
package(mir) template allFlattened(args...)
572571
{
573-
enum i = N - 1;
574-
static if (i)
575-
enum allFlattened = .allFlattened!i ~ ("slices[" ~ i.stringof ~ "].flattened, ");
572+
static if (args.length)
573+
{
574+
alias arg = args[0];
575+
@optmath @property ls()()
576+
{
577+
import mir.ndslice.topology: flattened;
578+
return flattened(arg);
579+
}
580+
alias allFlattened = AliasSeq!(ls, allFlattened!(args[1..$]));
581+
}
576582
else
577-
enum allFlattened = "slices[" ~ i.stringof ~ "].flattened, ";
583+
alias allFlattened = AliasSeq!();
578584
}
579585

580586
private template areAllContiguousSlices(Slices...)
@@ -707,7 +713,7 @@ template reduce(alias fun)
707713
static if (areAllContiguousSlices!Slices)
708714
{
709715
import mir.ndslice.topology: flattened;
710-
return mixin(`.reduce!fun(seed, ` ~ allFlattened!(Slices.length) ~`)`);
716+
return .reduce!fun(seed, allFlattened!(allLightScope!slices));
711717
}
712718
else
713719
{
@@ -717,7 +723,7 @@ template reduce(alias fun)
717723
alias UT = Unqual!S;
718724
else
719725
alias UT = S;
720-
return reduceImpl!(fun, UT, Slices)(seed, slices);
726+
return reduceImpl!(fun, UT, Slices)(seed, allLightScope!slices);
721727
}
722728
}
723729
else version(Mir_disable_inlining_in_reduce)
@@ -730,7 +736,7 @@ template reduce(alias fun)
730736
static if (areAllContiguousSlices!Slices)
731737
{
732738
import mir.ndslice.topology: flattened;
733-
return mixin(`.reduce!fun(seed, ` ~ allFlattened!(Slices.length) ~`)`);
739+
return .reduce!fun(seed, allFlattened!(allLightScope!slices));
734740
}
735741
else
736742
{
@@ -740,7 +746,7 @@ template reduce(alias fun)
740746
alias UT = Unqual!S;
741747
else
742748
alias UT = S;
743-
return reduceImpl!(nonInlinedNaryFun!fun, UT, Slices)(seed, slices);
749+
return reduceImpl!(nonInlinedNaryFun!fun, UT, Slices)(seed, allLightScope!slices);
744750
}
745751
}
746752
else
@@ -953,13 +959,13 @@ template each(alias fun)
953959
static if (areAllContiguousSlices!Slices)
954960
{
955961
import mir.ndslice.topology: flattened;
956-
mixin(`.each!fun(` ~ allFlattened!(Slices.length) ~`);`);
962+
.each!fun(allFlattened!(allLightScope!slices));
957963
}
958964
else
959965
{
960966
if (slices[0].anyEmpty)
961967
return;
962-
eachImpl!fun(slices);
968+
eachImpl!fun(allLightScope!slices);
963969
}
964970
}
965971
else
@@ -1083,7 +1089,7 @@ template eachUploPair(alias fun, bool includeDiagonal = false)
10831089
{
10841090
if (matrix.length) do
10851091
{
1086-
eachImpl!fun(matrix.front!0, matrix.front!1);
1092+
eachImpl!fun(matrix.lightScope.front!0, matrix.lightScope.front!1);
10871093
matrix.popFront!1;
10881094
matrix.popFront!0;
10891095
// hint for optimizer
@@ -1097,8 +1103,8 @@ template eachUploPair(alias fun, bool includeDiagonal = false)
10971103
{
10981104
assert(!matrix.empty!0);
10991105
assert(!matrix.empty!1);
1100-
auto l = matrix.front!1;
1101-
auto u = matrix.front!0;
1106+
auto l = matrix.lightScope.front!1;
1107+
auto u = matrix.lightScope.front!0;
11021108
matrix.popFront!1;
11031109
matrix.popFront!0;
11041110
l.popFront;
@@ -1236,7 +1242,7 @@ template isSymmetric(alias fun = "a == b")
12361242
return false;
12371243
if (matrix.length) do
12381244
{
1239-
if (!allImpl!fun(matrix.front!0, matrix.front!1))
1245+
if (!allImpl!fun(matrix.lightScope.front!0, matrix.lightScope.front!1))
12401246
{
12411247
return false;
12421248
}
@@ -1280,7 +1286,7 @@ bool minPosImpl(alias fun, Iterator, size_t N, SliceKind kind)(scope ref size_t[
12801286
}
12811287
else
12821288
{
1283-
if (minPosImpl!(fun, Iterator, N - 1, kind)(backwardIndex[1 .. $], iterator, slice.front))
1289+
if (minPosImpl!(fun, LightScopeOf!Iterator, N - 1, kind)(backwardIndex[1 .. $], iterator, lightScope(slice).front))
12841290
{
12851291
backwardIndex[0] = slice.length;
12861292
found = true;
@@ -1315,7 +1321,7 @@ bool[2] minmaxPosImpl(alias fun, Iterator, size_t N, SliceKind kind)(scope ref s
13151321
}
13161322
else
13171323
{
1318-
auto r = minmaxPosImpl!(fun, Iterator, N - 1, kind)(backwardIndex[1 .. $], iterator, slice.front);
1324+
auto r = minmaxPosImpl!(fun, LightScopeOf!Iterator, N - 1, kind)(backwardIndex[1 .. $], iterator, lightScope(slice).front);
13191325
if (r[0])
13201326
{
13211327
backwardIndex[0][0] = slice.length;
@@ -1365,7 +1371,7 @@ template minmaxPos(alias pred = "a < b")
13651371
size_t[2][N] ret;
13661372
auto it = slice._iterator;
13671373
Iterator[2] iterator = [it, it];
1368-
minmaxPosImpl!(pred, Iterator, N, kind)(ret, iterator, slice);
1374+
minmaxPosImpl!(pred, Iterator, N, kind)(ret, iterator, lightScope(slice));
13691375
foreach (i; Iota!N)
13701376
{
13711377
pret[0]._lengths[i] = ret[i][0];
@@ -1443,7 +1449,7 @@ template minmaxIndex(alias pred = "a < b")
14431449
}
14441450
auto it = slice._iterator;
14451451
Iterator[2] iterator = [it, it];
1446-
minmaxPosImpl!(pred, Iterator, N, kind)(ret, iterator, slice);
1452+
minmaxPosImpl!(pred, LightScopeOf!Iterator, N, kind)(ret, iterator, lightScope(slice));
14471453
foreach (i; Iota!N)
14481454
{
14491455
pret[0][i] = slice._lengths[i] - ret[i][0];
@@ -1503,7 +1509,7 @@ template minPos(alias pred = "a < b")
15031509
typeof(return) ret = { _iterator : slice._iterator };
15041510
if (!slice.anyEmpty)
15051511
{
1506-
minPosImpl!(pred, Iterator, N, kind)(ret._lengths, ret._iterator, slice);
1512+
minPosImpl!(pred, LightScopeOf!Iterator, N, kind)(ret._lengths, ret._iterator, lightScope(slice));
15071513
}
15081514
auto strides = slice.strides;
15091515
foreach(i; Iota!(0, ret.S))
@@ -1575,7 +1581,7 @@ template minIndex(alias pred = "a < b")
15751581
if (!slice.anyEmpty)
15761582
{
15771583
ret = slice.shape;
1578-
minPosImpl!(pred, Iterator, N, kind)(ret, slice._iterator, slice);
1584+
minPosImpl!(pred, LightScopeOf!Iterator, N, kind)(ret, slice._iterator, lightScope(slice));
15791585
foreach (i; Iota!N)
15801586
ret[i] = slice._lengths[i] - ret[i];
15811587
}
@@ -1727,7 +1733,7 @@ template findIndex(alias pred)
17271733
slices.checkShapesMatch;
17281734
size_t[DimensionCount!(Slices[0])] ret = -1;
17291735
auto lengths = slices[0].shape;
1730-
if (!slices[0].anyEmpty && findImpl!pred(ret, slices))
1736+
if (!slices[0].anyEmpty && findImpl!pred(ret, allLightScope!slices))
17311737
foreach (i; Iota!(DimensionCount!(Slices[0])))
17321738
ret[i] = lengths[i] - ret[i];
17331739
static if (DimensionCount!(Slices[0]) > 1)
@@ -1824,7 +1830,7 @@ template find(alias pred)
18241830
slices.checkShapesMatch;
18251831
size_t[DimensionCount!(Slices[0])] ret;
18261832
if (!slices[0].anyEmpty)
1827-
findImpl!pred(ret, slices);
1833+
findImpl!pred(ret, allLightScope!slices);
18281834
static if (DimensionCount!(Slices[0]) > 1)
18291835
return ret;
18301836
else
@@ -1951,7 +1957,7 @@ size_t anyImpl(alias fun, Slices...)(scope Slices slices)
19511957
{
19521958
// pragma(msg, S);
19531959
import mir.ndslice.topology: retro;
1954-
return .anyImpl!fun(slices[0].retro);
1960+
return .anyImpl!fun(lightScope(slices[0]).retro);
19551961
}
19561962
else
19571963
{
@@ -2003,11 +2009,11 @@ template any(alias pred = "a")
20032009
static if (areAllContiguousSlices!Slices)
20042010
{
20052011
import mir.ndslice.topology: flattened;
2006-
return mixin(`.any!pred(` ~ allFlattened!(Slices.length) ~`)`);
2012+
return .any!pred(allFlattened!(allLightScope!slices));
20072013
}
20082014
else
20092015
{
2010-
return !slices[0].anyEmpty && anyImpl!pred(slices);
2016+
return !slices[0].anyEmpty && anyImpl!pred(allLightScope!slices);
20112017
}
20122018
}
20132019
else
@@ -2104,14 +2110,14 @@ size_t allImpl(alias fun, Slices...)(scope Slices slices)
21042110
{
21052111
static if (__traits(isSame, fun, naryFun!"a") && is(S : Slice!(FieldIterator!(BitField!(Field, I))), Field, I))
21062112
{
2107-
return BitSliceAccelerator!(Field, I)(slices[0]).all;
2113+
return BitSliceAccelerator!(LightScopeOf!Field, I)(lightScope(slices[0])).all;
21082114
}
21092115
else
21102116
static if (__traits(isSame, fun, naryFun!"a") && is(S : Slice!(RetroIterator!(FieldIterator!(BitField!(Field, I)))), Field, I))
21112117
{
21122118
// pragma(msg, S);
21132119
import mir.ndslice.topology: retro;
2114-
return .allImpl!fun(slices[0].retro);
2120+
return .allImpl!fun(lightScope(slices[0]).retro);
21152121
}
21162122
else
21172123
{
@@ -2163,11 +2169,11 @@ template all(alias pred = "a")
21632169
static if (areAllContiguousSlices!Slices)
21642170
{
21652171
import mir.ndslice.topology: flattened;
2166-
return mixin(`.all!pred(` ~ allFlattened!(Slices.length) ~`)`);
2172+
return .all!pred(allFlattened!(allLightScope!slices));
21672173
}
21682174
else
21692175
{
2170-
return slices[0].anyEmpty || allImpl!pred(slices);
2176+
return slices[0].anyEmpty || allImpl!pred(allLightScope!slices);
21712177
}
21722178
}
21732179
else
@@ -2298,13 +2304,13 @@ template count(alias fun)
22982304
static if (areAllContiguousSlices!Slices)
22992305
{
23002306
import mir.ndslice.topology: flattened;
2301-
return mixin(`.count!fun(` ~ allFlattened!(Slices.length) ~`)`);
2307+
return .count!fun(allFlattened!(allLightScope!slices));
23022308
}
23032309
else
23042310
{
23052311
if (slices[0].anyEmpty)
23062312
return 0;
2307-
return countImpl!(fun, Slices)(slices);
2313+
return countImpl!(fun)(allLightScope!slices);
23082314
}
23092315
}
23102316
else
@@ -2421,7 +2427,7 @@ template equal(alias pred = "a == b")
24212427
goto False;
24222428
}
24232429
}
2424-
return all!pred(slices);
2430+
return all!pred(allLightScope!slices);
24252431
False: return false;
24262432
}
24272433
else
@@ -2461,6 +2467,21 @@ version(mir_test) unittest
24612467
assert(!equal(sl1[0 .. $, 0 .. $ - 1], sl1));
24622468
}
24632469

2470+
@safe pure nothrow @nogc
2471+
version(mir_test) unittest
2472+
{
2473+
import mir.algorithm.iteration: equal;
2474+
import mir.math.common: approxEqual;
2475+
import mir.ndslice.allocation: rcslice;
2476+
import mir.ndslice.topology: as, iota;
2477+
2478+
auto x = 5.iota.as!double.rcslice;
2479+
auto y = x.rcslice;
2480+
2481+
assert(equal(x, y));
2482+
assert(equal!approxEqual(x, y));
2483+
}
2484+
24642485
ptrdiff_t cmpImpl(alias pred, A, B)
24652486
(scope A sl1, scope B sl2)
24662487
if (DimensionCount!A == DimensionCount!B)
@@ -2534,7 +2555,7 @@ template cmp(alias pred = "a < b")
25342555
}
25352556
if (b)
25362557
return 1;
2537-
return cmpImpl!pred(sl1, sl2);
2558+
return cmpImpl!pred(lightScope(sl1), lightScope(sl2));
25382559
}
25392560
else
25402561
alias cmp = .cmp!(naryFun!pred);
@@ -2608,7 +2629,7 @@ size_t countImpl(alias fun, Slices...)(scope Slices slices)
26082629
{
26092630
// pragma(msg, S);
26102631
import mir.ndslice.topology: retro;
2611-
ret = .countImpl!fun(slices[0].retro);
2632+
ret = .countImpl!fun(lightScope(slices[0]).retro);
26122633
}
26132634
else
26142635
do
@@ -2635,7 +2656,7 @@ private template selectBackOf(size_t N, string input)
26352656
{
26362657
enum i = N - 1;
26372658
enum selectBackOf = selectBackOf!(i, input) ~
2638-
"slices[" ~ i.stringof ~ "].selectBack!0(" ~ input ~ "), ";
2659+
"lightScope(slices[" ~ i.stringof ~ "]).selectBack!0(" ~ input ~ "), ";
26392660
}
26402661
}
26412662

@@ -2647,7 +2668,7 @@ private template frontSelectFrontOf(size_t N, string input)
26472668
{
26482669
enum i = N - 1;
26492670
enum frontSelectFrontOf = frontSelectFrontOf!(i, input) ~
2650-
"slices[" ~ i.stringof ~ "].front!0.selectFront!0(" ~ input ~ "), ";
2671+
"lightScope(slices[" ~ i.stringof ~ "]).front!0.selectFront!0(" ~ input ~ "), ";
26512672
}
26522673
}
26532674

@@ -3114,7 +3135,7 @@ private template frontSelectBackOf(size_t N, string input)
31143135
{
31153136
enum i = N - 1;
31163137
enum frontSelectBackOf = frontSelectBackOf!(i, input) ~
3117-
"slices[" ~ i.stringof ~ "].front.selectBack!0(" ~ input ~ "), ";
3138+
"lightScope(slices[" ~ i.stringof ~ "]).front.selectBack!0(" ~ input ~ "), ";
31183139
}
31193140
}
31203141

@@ -3126,7 +3147,7 @@ private template selectFrontOf(size_t N, string input)
31263147
{
31273148
enum i = N - 1;
31283149
enum selectFrontOf = selectFrontOf!(i, input) ~
3129-
"slices[" ~ i.stringof ~ "].selectFront!0(" ~ input ~ "), ";
3150+
"lightScope(slices[" ~ i.stringof ~ "]).selectFront!0(" ~ input ~ "), ";
31303151
}
31313152
}
31323153

source/mir/combinatorics/package.d

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ License: $(LINK2 http://boost.org/LICENSE_1_0.txt, Boost License 1.0).
77
*/
88
module mir.combinatorics;
99

10-
import std.traits;
1110
import mir.primitives: hasLength;
11+
import mir.qualifier;
12+
import std.traits;
1213

1314
///
1415
version(mir_test) unittest
@@ -223,6 +224,24 @@ struct IndexedRoR(Collection, Range)
223224
this.r = range;
224225
}
225226

227+
///
228+
auto lightScope()()
229+
{
230+
return IndexedRoR!(LightScopeOf!Collection, LightScopeOf!Range)(.lightScope(c), .lightScope(r));
231+
}
232+
233+
///
234+
auto lightScope()() const
235+
{
236+
return IndexedRoR!(LightConstOf!(LightScopeOf!Collection), LightConstOf!(LightScopeOf!Range))(.lightScope(c), .lightScope(r));
237+
}
238+
239+
///
240+
auto lightConst()() const
241+
{
242+
return IndexedRoR!(LightConstOf!Collection, LightConstOf!Range)(.lightConst(c), .lightConst(r));
243+
}
244+
226245
/// Input range primitives
227246
auto ref front()() @property
228247
{

0 commit comments

Comments
 (0)