Skip to content

Commit a20263e

Browse files
Merge pull request #942 from benjchristensen/math-module
MathObservable
2 parents 1540f6c + 68d4062 commit a20263e

File tree

10 files changed

+2057
-1
lines changed

10 files changed

+2057
-1
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
apply plugin: 'osgi'
2+
3+
sourceCompatibility = JavaVersion.VERSION_1_6
4+
targetCompatibility = JavaVersion.VERSION_1_6
5+
6+
dependencies {
7+
compile project(':rxjava-core')
8+
testCompile project(":rxjava-core").sourceSets.test.output
9+
provided 'junit:junit-dep:4.10'
10+
provided 'org.mockito:mockito-core:1.8.5'
11+
}
12+
13+
javadoc {
14+
options {
15+
doclet = "org.benjchristensen.doclet.DocletExclude"
16+
docletpath = [rootProject.file('./gradle/doclet-exclude.jar')]
17+
stylesheetFile = rootProject.file('./gradle/javadocStyleSheet.css')
18+
windowTitle = "RxJava Javadoc ${project.version}"
19+
}
20+
options.addStringOption('top').value = '<h2 class="title" style="padding-top:40px">RxJava</h2>'
21+
}
22+
23+
jar {
24+
manifest {
25+
name = 'rxjava-math'
26+
instruction 'Bundle-Vendor', 'Netflix'
27+
instruction 'Bundle-DocURL', 'https://github.com/Netflix/RxJava'
28+
instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*'
29+
instruction 'Fragment-Host', 'com.netflix.rxjava.core'
30+
}
31+
}
Lines changed: 348 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,348 @@
1+
/**
2+
* Copyright 2014 Netflix, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package rx.math.operators;
17+
18+
import rx.Observable;
19+
import rx.Observable.OnSubscribeFunc;
20+
import rx.Observer;
21+
import rx.Subscription;
22+
import rx.functions.Func1;
23+
import rx.functions.Func2;
24+
25+
/**
26+
* A few operators for implementing the averaging operation.
27+
*
28+
* @see <a href="http://msdn.microsoft.com/en-us/library/system.reactive.linq.observable.average%28v=vs.103%29.aspx">MSDN: Observable.Average</a>
29+
*/
30+
public final class OperationAverage {
31+
private static final class Tuple2<T> {
32+
private final T current;
33+
private final Integer count;
34+
35+
private Tuple2(T v1, Integer v2) {
36+
current = v1;
37+
count = v2;
38+
}
39+
}
40+
41+
public static Observable<Integer> average(Observable<Integer> source) {
42+
return source.reduce(new Tuple2<Integer>(0, 0), new Func2<Tuple2<Integer>, Integer, Tuple2<Integer>>() {
43+
@Override
44+
public Tuple2<Integer> call(Tuple2<Integer> accu, Integer next) {
45+
return new Tuple2<Integer>(accu.current + next, accu.count + 1);
46+
}
47+
}).map(new Func1<Tuple2<Integer>, Integer>() {
48+
@Override
49+
public Integer call(Tuple2<Integer> result) {
50+
if (result.count == 0) {
51+
throw new IllegalArgumentException("Sequence contains no elements");
52+
}
53+
return result.current / result.count;
54+
}
55+
});
56+
}
57+
58+
public static Observable<Long> averageLongs(Observable<Long> source) {
59+
return source.reduce(new Tuple2<Long>(0L, 0), new Func2<Tuple2<Long>, Long, Tuple2<Long>>() {
60+
@Override
61+
public Tuple2<Long> call(Tuple2<Long> accu, Long next) {
62+
return new Tuple2<Long>(accu.current + next, accu.count + 1);
63+
}
64+
}).map(new Func1<Tuple2<Long>, Long>() {
65+
@Override
66+
public Long call(Tuple2<Long> result) {
67+
if (result.count == 0) {
68+
throw new IllegalArgumentException("Sequence contains no elements");
69+
}
70+
return result.current / result.count;
71+
}
72+
});
73+
}
74+
75+
public static Observable<Float> averageFloats(Observable<Float> source) {
76+
return source.reduce(new Tuple2<Float>(0.0f, 0), new Func2<Tuple2<Float>, Float, Tuple2<Float>>() {
77+
@Override
78+
public Tuple2<Float> call(Tuple2<Float> accu, Float next) {
79+
return new Tuple2<Float>(accu.current + next, accu.count + 1);
80+
}
81+
}).map(new Func1<Tuple2<Float>, Float>() {
82+
@Override
83+
public Float call(Tuple2<Float> result) {
84+
if (result.count == 0) {
85+
throw new IllegalArgumentException("Sequence contains no elements");
86+
}
87+
return result.current / result.count;
88+
}
89+
});
90+
}
91+
92+
public static Observable<Double> averageDoubles(Observable<Double> source) {
93+
return source.reduce(new Tuple2<Double>(0.0d, 0), new Func2<Tuple2<Double>, Double, Tuple2<Double>>() {
94+
@Override
95+
public Tuple2<Double> call(Tuple2<Double> accu, Double next) {
96+
return new Tuple2<Double>(accu.current + next, accu.count + 1);
97+
}
98+
}).map(new Func1<Tuple2<Double>, Double>() {
99+
@Override
100+
public Double call(Tuple2<Double> result) {
101+
if (result.count == 0) {
102+
throw new IllegalArgumentException("Sequence contains no elements");
103+
}
104+
return result.current / result.count;
105+
}
106+
});
107+
}
108+
109+
/**
110+
* Compute the average by extracting integer values from the source via an
111+
* extractor function.
112+
*
113+
* @param <T>
114+
* the source value type
115+
*/
116+
public static final class AverageIntegerExtractor<T> implements OnSubscribeFunc<Integer> {
117+
final Observable<? extends T> source;
118+
final Func1<? super T, Integer> valueExtractor;
119+
120+
public AverageIntegerExtractor(Observable<? extends T> source, Func1<? super T, Integer> valueExtractor) {
121+
this.source = source;
122+
this.valueExtractor = valueExtractor;
123+
}
124+
125+
@Override
126+
public Subscription onSubscribe(Observer<? super Integer> t1) {
127+
return source.subscribe(new AverageObserver(t1));
128+
}
129+
130+
/** Computes the average. */
131+
private final class AverageObserver implements Observer<T> {
132+
final Observer<? super Integer> observer;
133+
int sum;
134+
int count;
135+
136+
public AverageObserver(Observer<? super Integer> observer) {
137+
this.observer = observer;
138+
}
139+
140+
@Override
141+
public void onNext(T args) {
142+
sum += valueExtractor.call(args);
143+
count++;
144+
}
145+
146+
@Override
147+
public void onError(Throwable e) {
148+
observer.onError(e);
149+
}
150+
151+
@Override
152+
public void onCompleted() {
153+
if (count > 0) {
154+
try {
155+
observer.onNext(sum / count);
156+
} catch (Throwable t) {
157+
observer.onError(t);
158+
return;
159+
}
160+
observer.onCompleted();
161+
} else {
162+
observer.onError(new IllegalArgumentException("Sequence contains no elements"));
163+
}
164+
}
165+
166+
}
167+
}
168+
169+
/**
170+
* Compute the average by extracting long values from the source via an
171+
* extractor function.
172+
*
173+
* @param <T>
174+
* the source value type
175+
*/
176+
public static final class AverageLongExtractor<T> implements OnSubscribeFunc<Long> {
177+
final Observable<? extends T> source;
178+
final Func1<? super T, Long> valueExtractor;
179+
180+
public AverageLongExtractor(Observable<? extends T> source, Func1<? super T, Long> valueExtractor) {
181+
this.source = source;
182+
this.valueExtractor = valueExtractor;
183+
}
184+
185+
@Override
186+
public Subscription onSubscribe(Observer<? super Long> t1) {
187+
return source.subscribe(new AverageObserver(t1));
188+
}
189+
190+
/** Computes the average. */
191+
private final class AverageObserver implements Observer<T> {
192+
final Observer<? super Long> observer;
193+
long sum;
194+
int count;
195+
196+
public AverageObserver(Observer<? super Long> observer) {
197+
this.observer = observer;
198+
}
199+
200+
@Override
201+
public void onNext(T args) {
202+
sum += valueExtractor.call(args);
203+
count++;
204+
}
205+
206+
@Override
207+
public void onError(Throwable e) {
208+
observer.onError(e);
209+
}
210+
211+
@Override
212+
public void onCompleted() {
213+
if (count > 0) {
214+
try {
215+
observer.onNext(sum / count);
216+
} catch (Throwable t) {
217+
observer.onError(t);
218+
return;
219+
}
220+
observer.onCompleted();
221+
} else {
222+
observer.onError(new IllegalArgumentException("Sequence contains no elements"));
223+
}
224+
}
225+
226+
}
227+
}
228+
229+
/**
230+
* Compute the average by extracting float values from the source via an
231+
* extractor function.
232+
*
233+
* @param <T>
234+
* the source value type
235+
*/
236+
public static final class AverageFloatExtractor<T> implements OnSubscribeFunc<Float> {
237+
final Observable<? extends T> source;
238+
final Func1<? super T, Float> valueExtractor;
239+
240+
public AverageFloatExtractor(Observable<? extends T> source, Func1<? super T, Float> valueExtractor) {
241+
this.source = source;
242+
this.valueExtractor = valueExtractor;
243+
}
244+
245+
@Override
246+
public Subscription onSubscribe(Observer<? super Float> t1) {
247+
return source.subscribe(new AverageObserver(t1));
248+
}
249+
250+
/** Computes the average. */
251+
private final class AverageObserver implements Observer<T> {
252+
final Observer<? super Float> observer;
253+
float sum;
254+
int count;
255+
256+
public AverageObserver(Observer<? super Float> observer) {
257+
this.observer = observer;
258+
}
259+
260+
@Override
261+
public void onNext(T args) {
262+
sum += valueExtractor.call(args);
263+
count++;
264+
}
265+
266+
@Override
267+
public void onError(Throwable e) {
268+
observer.onError(e);
269+
}
270+
271+
@Override
272+
public void onCompleted() {
273+
if (count > 0) {
274+
try {
275+
observer.onNext(sum / count);
276+
} catch (Throwable t) {
277+
observer.onError(t);
278+
return;
279+
}
280+
observer.onCompleted();
281+
} else {
282+
observer.onError(new IllegalArgumentException("Sequence contains no elements"));
283+
}
284+
}
285+
286+
}
287+
}
288+
289+
/**
290+
* Compute the average by extracting double values from the source via an
291+
* extractor function.
292+
*
293+
* @param <T>
294+
* the source value type
295+
*/
296+
public static final class AverageDoubleExtractor<T> implements OnSubscribeFunc<Double> {
297+
final Observable<? extends T> source;
298+
final Func1<? super T, Double> valueExtractor;
299+
300+
public AverageDoubleExtractor(Observable<? extends T> source, Func1<? super T, Double> valueExtractor) {
301+
this.source = source;
302+
this.valueExtractor = valueExtractor;
303+
}
304+
305+
@Override
306+
public Subscription onSubscribe(Observer<? super Double> t1) {
307+
return source.subscribe(new AverageObserver(t1));
308+
}
309+
310+
/** Computes the average. */
311+
private final class AverageObserver implements Observer<T> {
312+
final Observer<? super Double> observer;
313+
double sum;
314+
int count;
315+
316+
public AverageObserver(Observer<? super Double> observer) {
317+
this.observer = observer;
318+
}
319+
320+
@Override
321+
public void onNext(T args) {
322+
sum += valueExtractor.call(args);
323+
count++;
324+
}
325+
326+
@Override
327+
public void onError(Throwable e) {
328+
observer.onError(e);
329+
}
330+
331+
@Override
332+
public void onCompleted() {
333+
if (count > 0) {
334+
try {
335+
observer.onNext(sum / count);
336+
} catch (Throwable t) {
337+
observer.onError(t);
338+
return;
339+
}
340+
observer.onCompleted();
341+
} else {
342+
observer.onError(new IllegalArgumentException("Sequence contains no elements"));
343+
}
344+
}
345+
346+
}
347+
}
348+
}

0 commit comments

Comments
 (0)