Skip to content

Commit f4cf3ba

Browse files
committed
add diff and slide to topology module
1 parent 36a31f9 commit f4cf3ba

File tree

2 files changed

+81
-8
lines changed

2 files changed

+81
-8
lines changed

source/mir/ndslice/iterator.d

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ $(T2 IotaIterator, $(SUBREF topology, iota))
1313
$(T2 MapIterator, $(SUBREF topology, map))
1414
$(T2 RetroIterator, $(SUBREF topology, retro))
1515
$(T2 SliceIterator, $(SUBREF topology, map) in composition with $(LREF MapIterator) for packed slices.)
16+
$(T2 SlideIterator, $(SUBREF topology, diff) and $(SUBREF topology, slide).)
1617
$(T2 StrideIterator, $(SUBREF topology, stride))
1718
$(T2 ZipIterator, $(SUBREF topology, zip))
1819
)
@@ -612,15 +613,15 @@ auto mapIterator(alias fun, Iterator)(Iterator iterator)
612613
return MapIterator!(Iterator, fun)(iterator);
613614
}
614615

615-
auto ConvolutionIterator__map(Iterator, size_t params, alias fun0, alias fun)(ref ConvolutionIterator!(Iterator, params, fun0) it)
616+
auto SlideIterator__map(Iterator, size_t params, alias fun0, alias fun)(ref SlideIterator!(Iterator, params, fun0) it)
616617
{
617-
return ConvolutionIterator!(Iterator, params, fun)(it._iterator);
618+
return SlideIterator!(Iterator, params, fun)(it._iterator);
618619
}
619620

620621
/++
621-
`ConvolutionIterator` is used by $(SUBREF topology, map).
622+
`SlideIterator` is used by $(SUBREF topology, diff) and $(SUBREF topology, slide).
622623
+/
623-
struct ConvolutionIterator(Iterator, size_t params, alias fun)
624+
struct SlideIterator(Iterator, size_t params, alias fun)
624625
if (params > 1)
625626
{
626627
@fastmath:
@@ -629,7 +630,7 @@ struct ConvolutionIterator(Iterator, size_t params, alias fun)
629630

630631
import mir.functional: pipe;
631632
///
632-
static alias __map(alias fun1) = ConvolutionIterator__map!(Iterator, params, fun, pipe!(fun, fun1));
633+
static alias __map(alias fun1) = SlideIterator__map!(Iterator, params, fun, pipe!(fun, fun1));
633634

634635
auto ref opUnary(string op : "*")()
635636
{
@@ -649,7 +650,7 @@ unittest
649650
{
650651
import mir.functional: naryFun;
651652
auto data = [1, 3, 8, 18];
652-
auto diff = ConvolutionIterator!(int*, 2, naryFun!"b - a")(data.ptr);
653+
auto diff = SlideIterator!(int*, 2, naryFun!"b - a")(data.ptr);
653654
assert(*diff == 2);
654655
assert(diff[1] == 5);
655656
assert(diff[2] == 10);

source/mir/ndslice/topology.d

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ $(T2 repeat, Slice with identical values)
1818
$(T2 iota, Contiguous Slice with initial flattened (contiguous) index.)
1919
$(T2 ndiota, Contiguous Slice with initial multidimensional index.)
2020
$(T2 linspace, Evenly spaced numbers over a specified interval.)
21-
2221
)
2322
2423
$(BOOKTABLE $(H2 Products),
@@ -36,12 +35,14 @@ $(T2 as, Convenience function that creates a lazy view,
3635
where each element of the original slice is converted to a type `T`.)
3736
$(T2 bitpack, Bitpack slice over an unsigned integral slice.)
3837
$(T2 bitwise, Bitwise slice over an unsigned integral slice.)
38+
$(T2 diff, Differences between vector elements.)
3939
$(T2 flattened, Contiguous 1-dimensional slice of all elements of a slice.)
4040
$(T2 map, Multidimensional functional map.)
4141
$(T2 retro, Reverses order of iteration for all dimensions)
42+
$(T2 slide, Sliding map for vectors.)
4243
$(T2 stride, Strides 1-dimensional slice)
43-
$(T2 zip, Zips slices into a slice of tuples.)
4444
$(T2 unzip, Selects a slice from a zipped slice.)
45+
$(T2 zip, Zips slices into a slice of tuples.)
4546
4647
)
4748
@@ -2542,6 +2543,77 @@ pure nothrow unittest
25422543

25432544
private enum TotalDim(NdFields...) = [staticMap!(DimensionCount, NdFields)].sum;
25442545

2546+
/++
2547+
Sliding map for vectors.
2548+
2549+
Suitable for simple convolution algorithms.
2550+
2551+
Params:
2552+
params = windows length.
2553+
fun = map functions with `params` arity.
2554+
See_also: $(LREF diff).
2555+
+/
2556+
template slide(size_t params, alias fun)
2557+
if (params <= 'z' - 'a' + 1)
2558+
{
2559+
import mir.functional: naryFun;
2560+
static if (params == 1)
2561+
{
2562+
alias slide = .map!(naryFun!fun);
2563+
}
2564+
else
2565+
static if (__traits(isSame, naryFun!fun, fun))
2566+
{
2567+
/++
2568+
Params:
2569+
slice = An 1-dimensional input slice.
2570+
Returns:
2571+
1d-slice composed of `fun(slice[i], ..., slice[i + params - 1])`.
2572+
+/
2573+
@fastmath auto slide(SliceKind kind, Iterator)
2574+
(Slice!(kind, [1], Iterator) slice)
2575+
{
2576+
auto s = slice.flattened;
2577+
s._lengths[0] -= params - 1;
2578+
if (cast(sizediff_t)s._lengths[0] < 0)
2579+
s._lengths[0] = 0;
2580+
alias I = SlideIterator!(_IteratorOf!(typeof(s)), params, fun);
2581+
return Slice!(Contiguous, [1], I)(
2582+
s._lengths,
2583+
s._strides,
2584+
I(s._iterator));
2585+
}
2586+
}
2587+
else alias slide = .slide!(params, naryFun!fun);
2588+
}
2589+
2590+
///
2591+
unittest
2592+
{
2593+
auto data = 10.iota;
2594+
auto sw = data.slide!(3, "a + 2 * b + c");
2595+
2596+
import mir.utility: max;
2597+
assert(sw.length == max(0, cast(ptrdiff_t)data.length - 3 + 1));
2598+
assert(sw == sw.length.iota.map!"(a + 1) * 4");
2599+
}
2600+
2601+
/++
2602+
Differences between vector elements.
2603+
Params:
2604+
lag = an integer indicating which lag to use
2605+
Returns: lazy difference 1d-slice.
2606+
2607+
See_also: $(LREF slide).
2608+
+/
2609+
alias diff(size_t lag = 1) = slide!(lag + 1, ('a' + lag) ~ " - a");
2610+
2611+
///
2612+
unittest
2613+
{
2614+
assert([2, 4, 3, -1].sliced.diff == [2, -1, -4]);
2615+
}
2616+
25452617
/++
25462618
Cartesian product.
25472619

0 commit comments

Comments
 (0)