@@ -7,7 +7,7 @@ at expense of precision, one can use $(REF_ALTTEXT $(TT Summation.fast), Summati
77
88License: $(LINK2 http://boost.org/LICENSE_1_0.txt, Boost License 1.0).
99
10- Authors: Ilya Yaroshenko
10+ Authors: Ilya Yaroshenko, John Michael Hall
1111
1212Copyright: 2019 Symmetry Investments Group and Kaleidic Associates Advisory Limited.
1313
@@ -23,41 +23,116 @@ import mir.math.common: fmamath;
2323import mir.math.sum;
2424import mir.primitives;
2525import std.range.primitives : isInputRange;
26- import std.traits : isArray, isFloatingPoint;
26+ import std.traits : isArray, isFloatingPoint, isMutable, isIterable ;
2727
2828/+ +
29- Computes the average of `r`, which must be a finite iterable.
30-
31- Returns:
32- The average of all the elements in the range r.
29+ Output range for mean.
3330+/
34- template mean (Summation summation = Summation.appropriate)
31+ struct MeanAccumulator (T, Summation summation)
32+ if (isMutable! T)
3533{
3634 // /
37- @safe @fmamath sumType ! Range
38- mean( Range )( Range r)
39- if (hasLength ! Range
40- || summation == Summation.appropriate
41- || summation == Summation.fast
42- || summation == Summation.naive)
35+ size_t count;
36+ // /
37+ Summator ! (T, summation) sumAccumulator;
38+
39+ // /
40+ F mean (F = T)() @property
4341 {
44- static if (hasLength! Range )
42+ return cast (F) sumAccumulator.sum / cast (F) count;
43+ }
44+
45+ // /
46+ void put (Range )(Range r)
47+ if (isIterable! Range )
48+ {
49+ static if (hasShape! Range )
4550 {
46- auto n = r.length ;
47- return sum ! summation(r.move) / cast (sumType ! Range ) n ;
51+ count + = r.elementCount ;
52+ sumAccumulator.put(r) ;
4853 }
4954 else
5055 {
51- auto s = cast (typeof (return )) 0 ;
52- size_t length;
53- foreach (e; r)
56+ foreach (x; r)
5457 {
55- length ++ ;
56- s += e ;
58+ count ++ ;
59+ sumAccumulator.put(x) ;
5760 }
58- return s / cast (sumType! Range ) length;
5961 }
6062 }
63+
64+ // /
65+ void put ()(T x)
66+ {
67+ count++ ;
68+ sumAccumulator.put(x);
69+ }
70+ }
71+
72+ // /
73+ version (mir_test)
74+ @safe pure nothrow unittest
75+ {
76+ import mir.ndslice.slice : sliced;
77+
78+ MeanAccumulator! (double , Summation.pairwise) x;
79+ x.put([0.0 , 1 , 2 , 3 , 4 ].sliced);
80+ assert (x.mean == 2 );
81+ x.put(5 );
82+ assert (x.mean == 2.5 );
83+ }
84+
85+ version (mir_test)
86+ @safe pure nothrow unittest
87+ {
88+ import mir.ndslice.slice : sliced;
89+
90+ MeanAccumulator! (float , Summation.pairwise) x;
91+ x.put([0 , 1 , 2 , 3 , 4 ].sliced);
92+ assert (x.mean == 2 );
93+ x.put(5 );
94+ assert (x.mean == 2.5 );
95+ }
96+
97+ /+ +
98+ Computes the average of `r`, which must be a finite iterable.
99+
100+ Returns:
101+ The average of all the elements in the range r.
102+ +/
103+ template mean (F, Summation summation = Summation.appropriate)
104+ {
105+ /+ +
106+ Params:
107+ r = range
108+ +/
109+ F mean (Range )(Range r)
110+ if (isIterable! Range )
111+ {
112+ MeanAccumulator! (F, ResolveSummationType! (summation, Range , sumType! Range )) mean;
113+ mean.put(r.move);
114+ return mean.mean;
115+ }
116+ }
117+
118+ // / ditto
119+ template mean (Summation summation = Summation.appropriate)
120+ {
121+ /+ +
122+ Params:
123+ r = range
124+ +/
125+ sumType! Range mean (Range )(Range r)
126+ if (isIterable! Range )
127+ {
128+ return .mean! (sumType! Range , summation)(r.move);
129+ }
130+ }
131+
132+ // /ditto
133+ template mean (F, string summation)
134+ {
135+ mixin (" alias mean = .mean!(F, Summation." ~ summation ~ " );" );
61136}
62137
63138// /ditto
@@ -67,10 +142,23 @@ template mean(string summation)
67142}
68143
69144// /
70- version (mir_test) @safe pure nothrow unittest
145+ version (mir_test)
146+ @safe pure nothrow unittest
71147{
148+ import mir.ndslice.slice : sliced;
149+
72150 assert (mean([1.0 , 2 , 3 ]) == 2 );
73151 assert (mean([1.0 + 3i, 2 , 3 ]) == 2 + 1i);
152+
153+ assert (mean! float ([0 , 1 , 2 , 3 , 4 , 5 ].sliced(3 , 2 )) == 2.5 );
154+
155+ assert (is (typeof (mean! float ([1 , 2 , 3 ])) == float ));
156+ }
157+
158+ version (mir_test)
159+ @safe pure nothrow unittest
160+ {
161+ assert ([1.0 , 2 , 3 , 4 ].mean == 2.5 );
74162}
75163
76164/+ +
@@ -157,7 +245,8 @@ template simpleLinearRegression(string summation)
157245}
158246
159247// /
160- version (mir_test) @safe pure nothrow @nogc unittest
248+ version (mir_test)
249+ @safe pure nothrow @nogc unittest
161250{
162251 import mir.math.common: approxEqual;
163252 static immutable x = [0 , 1 , 2 , 3 ];
0 commit comments