Skip to content

Commit 29ee9df

Browse files
committed
more const/immutable powers for timeseries
1 parent 780ecbb commit 29ee9df

File tree

2 files changed

+118
-4
lines changed

2 files changed

+118
-4
lines changed

source/mir/ndslice/slice.d

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,6 +1518,13 @@ struct Slice(SliceKind kind, size_t[] packs, Iterator)
15181518
return this[index];
15191519
}
15201520

1521+
auto ref backward()(size_t[packs[0]] index) @safe const
1522+
{
1523+
foreach (i; Iota!(packs[0]))
1524+
index[i] = _lengths[i] - index[i];
1525+
return this[index];
1526+
}
1527+
15211528
static if (doUnittest)
15221529
///
15231530
@safe @nogc pure nothrow version(mir_test) unittest
@@ -1784,6 +1791,20 @@ struct Slice(SliceKind kind, size_t[] packs, Iterator)
17841791
}
17851792
}
17861793

1794+
/// ditto
1795+
auto ref opIndex(size_t I)(size_t[I] _indexes) @trusted const
1796+
if (I && I <= packs[0])
1797+
{
1798+
return this[][_indexes];
1799+
}
1800+
1801+
/// ditto
1802+
auto ref opIndex(size_t I)(size_t[I] _indexes) @trusted immutable
1803+
if (I && I <= packs[0])
1804+
{
1805+
return this[][_indexes];
1806+
}
1807+
17871808
/++
17881809
$(BOLD Partially or fully defined slice.)
17891810
+/

source/mir/timeseries.d

Lines changed: 97 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ T2=$(TR $(TDNW $(LREF $1)) $(TD $+))
1616
module mir.timeseries;
1717

1818
public import mir.ndslice.slice;
19+
import std.traits;
1920

2021
///
2122
version(mir_test) unittest
@@ -111,7 +112,7 @@ struct Series(TimeIterator, SliceKind kind, size_t[] packs, Iterator)
111112
}
112113

113114
///
114-
bool opEquals()(typeof(this) rhs)
115+
bool opEquals()(const typeof(this) rhs) const
115116
{
116117
return this.time == rhs.time && this.data == rhs.data;
117118
}
@@ -122,7 +123,19 @@ struct Series(TimeIterator, SliceKind kind, size_t[] packs, Iterator)
122123
`TimeIterator` is an iterator on top of date, date-time, time, or integer types.
123124
For example, `Date*`, `DateTime*`, `immutable(long)*`, `mir.ndslice.iterator.IotaIterator`.
124125
+/
125-
Slice!(Contiguous, [1], TimeIterator) time() @property @trusted
126+
auto time()() @property @trusted
127+
{
128+
return _time.sliced(_data._lengths[0]);
129+
}
130+
131+
/// ditto
132+
auto time()() @property @trusted const
133+
{
134+
return _time.sliced(_data._lengths[0]);
135+
}
136+
137+
/// ditto
138+
auto time()() @property @trusted immutable
126139
{
127140
return _time.sliced(_data._lengths[0]);
128141
}
@@ -131,11 +144,23 @@ struct Series(TimeIterator, SliceKind kind, size_t[] packs, Iterator)
131144
Data is any ndslice with only one constraints,
132145
`data` and `time` lengths should be equal.
133146
+/
134-
Slice!(kind, packs, Iterator) data() @property @trusted
147+
auto data()() @property @trusted
135148
{
136149
return _data;
137150
}
138151

152+
/// ditto
153+
auto data()() @property @trusted const
154+
{
155+
return _data[];
156+
}
157+
158+
/// ditto
159+
auto data()() @property @trusted immutable
160+
{
161+
return _data[];
162+
}
163+
139164
/++
140165
Special `[] =` index-assign operator for time-series.
141166
Assigns data from `r` with time intersection.
@@ -205,7 +230,7 @@ struct Series(TimeIterator, SliceKind kind, size_t[] packs, Iterator)
205230
if (lf == rf)
206231
{
207232
E:
208-
static if (isSlice!(typeof(l.data.front)))
233+
static if (packs != [1])
209234
mixin("l.data.front[] " ~ op ~ "= r.data.front;");
210235
else
211236
mixin("l.data.front " ~ op ~ "= r.data.front;");
@@ -253,6 +278,13 @@ struct Series(TimeIterator, SliceKind kind, size_t[] packs, Iterator)
253278
return this[0 .. time.assumeSorted.lowerBound!sp(moment).length];
254279
}
255280

281+
/// ditto
282+
auto lowerBound(SearchPolicy sp = SearchPolicy.binarySearch, Time)(Time moment) const
283+
{
284+
return this[0 .. time.assumeSorted.lowerBound!sp(moment).length];
285+
}
286+
287+
256288
/++
257289
This function uses a search with policy sp to find the largest left subrange on which
258290
`t > moment` is true for all `t`.
@@ -263,6 +295,12 @@ struct Series(TimeIterator, SliceKind kind, size_t[] packs, Iterator)
263295
return this[$ - time.assumeSorted.upperBound!sp(moment).length .. $];
264296
}
265297

298+
/// ditto
299+
auto upperBound(SearchPolicy sp = SearchPolicy.binarySearch, Time)(Time moment) const
300+
{
301+
return this[$ - time.assumeSorted.upperBound!sp(moment).length .. $];
302+
}
303+
266304
///
267305
bool contains(Time)(Time moment)
268306
{
@@ -412,6 +450,49 @@ struct Series(TimeIterator, SliceKind kind, size_t[] packs, Iterator)
412450
auto opIndex(Slices...)(Slices slices)
413451
if (allSatisfy!(templateOr!(is_Slice, isIndex), Slices))
414452
{
453+
static if (Slices.length == 0)
454+
{
455+
return this;
456+
}
457+
else
458+
static if (is_Slice!(Slices[0]))
459+
{
460+
return time[slices[0]].series(data[slices]);
461+
}
462+
else
463+
{
464+
return time[slices[0]].observation(data[slices]);
465+
}
466+
}
467+
468+
/// ditto
469+
auto opIndex(Slices...)(Slices slices) const
470+
if (allSatisfy!(templateOr!(is_Slice, isIndex), Slices))
471+
{
472+
static if (Slices.length == 0)
473+
{
474+
return time.series(_data[]);
475+
}
476+
else
477+
static if (is_Slice!(Slices[0]))
478+
{
479+
return time[slices[0]].series(data[slices]);
480+
}
481+
else
482+
{
483+
return time[slices[0]].observation(data[slices]);
484+
}
485+
}
486+
487+
/// ditto
488+
auto opIndex(Slices...)(Slices slices) immutable
489+
if (allSatisfy!(templateOr!(is_Slice, isIndex), Slices))
490+
{
491+
static if (Slices.length == 0)
492+
{
493+
return time.series(_data[]);
494+
}
495+
else
415496
static if (is_Slice!(Slices[0]))
416497
{
417498
return time[slices[0]].series(data[slices]);
@@ -435,6 +516,7 @@ struct Series(TimeIterator, SliceKind kind, size_t[] packs, Iterator)
435516
auto time = [1, 2, 3, 4].sliced;
436517
auto data = [2.1, 3.4, 5.6, 7.8].sliced;
437518
auto series = time.series(data);
519+
const cseries = series;
438520

439521
assert(series.contains(2));
440522
assert( ()@trusted{ return (2 in series) is &data[1]; }() );
@@ -445,6 +527,17 @@ struct Series(TimeIterator, SliceKind kind, size_t[] packs, Iterator)
445527
assert(series.lowerBound(2) == series[0 .. 1]);
446528
assert(series.upperBound(2) == series[2 .. $]);
447529

530+
assert(cseries.lowerBound(2) == cseries[0 .. 1]);
531+
assert(cseries.upperBound(2) == cseries[2 .. $]);
532+
533+
// slicing type deduction for const / immutable series
534+
static assert(is(typeof(series[]) ==
535+
Series!(int*, cast(SliceKind)2, [1LU], double*)));
536+
static assert(is(typeof(cseries[]) ==
537+
Series!(const(int)*, cast(SliceKind)2, [1LU], const(double)*)));
538+
static assert(is(typeof((cast(immutable) series)[]) ==
539+
Series!(immutable(int)*, cast(SliceKind)2, [1LU], immutable(double)*)));
540+
448541
/// slicing
449542
auto seriesSlice = series[1 .. $ - 1];
450543
assert(seriesSlice.time == time[1 .. $ - 1]);

0 commit comments

Comments
 (0)