001/*
002 * Java Genetic Algorithm Library (jenetics-1.5.0).
003 * Copyright (c) 2007-2013 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019 */
020package org.jenetics.util;
021
022import static java.lang.String.format;
023import static java.util.Objects.requireNonNull;
024import static org.jenetics.util.object.eq;
025import static org.jenetics.util.object.hashCodeOf;
026
027import java.util.Iterator;
028
029import org.jscience.mathematics.structure.GroupAdditive;
030
031
032/**
033 * Collection of some general purpose Accumulators and some static helper classes
034 * for accumulating.
035 *
036 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
037 * @since 1.0
038 * @version 1.0 &mdash; <em>$Date: 2013-11-22 $</em>
039 */
040public final class accumulators extends StaticObject {
041        private accumulators() {}
042
043        public static final Accumulator<Object> NULL = new Accumulator<Object>() {
044                @Override
045                public void accumulate(final Object value) {
046                }
047        };
048
049        /**
050         * Calculates min value.
051         *
052         * <p/>
053         * <strong>Note that this implementation is not synchronized.</strong> If
054         * multiple threads access this object concurrently, and at least one of the
055         * threads modifies it, it must be synchronized externally.
056         *
057         * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
058         * @since 1.0
059         * @version 1.0 &ndash; <em>$Revision$</em>
060         */
061        public static final class Min<C extends Comparable<? super C>>
062                extends MappedAccumulator<C>
063        {
064                private C _min;
065
066                /**
067                 * Create a new Min accumulator.
068                 */
069                public Min() {
070                }
071
072                /**
073                 * Copy constructor.
074                 *
075                 * @param min the accumulator to copy.
076                 * @throws NullPointerException if {@code min} is {@code null}.
077                 */
078                public Min(final Min<C> min) {
079                        requireNonNull(min, "Min");
080                        _samples = min._samples;
081                        _min = min._min;
082                }
083
084                /**
085                 * Return the min value, accumulated so far.
086                 *
087                 * @return the min value, accumulated so far.
088                 */
089                public C getMin() {
090                        return _min;
091                }
092
093                /**
094                 * @throws NullPointerException if the given {@code value} is {@code null}.
095                 */
096                @Override
097                public void accumulate(final C value) {
098                        if (_min == null) {
099                                _min = value;
100                        } else {
101                                if (value.compareTo(_min) < 0) {
102                                        _min = value;
103                                }
104                        }
105
106                        ++_samples;
107                }
108
109                @Override
110                public int hashCode() {
111                        return hashCodeOf(getClass()).and(super.hashCode()).and(_min).value();
112                }
113
114                @Override
115                public boolean equals(final Object obj) {
116                        if (obj == this) {
117                                return true;
118                        }
119                        if (obj == null || obj.getClass() != getClass()) {
120                                return false;
121                        }
122
123                        final Min<?> min = (Min<?>)obj;
124                        return super.equals(obj) && eq(_min, min._min);
125                }
126
127                @Override
128                public String toString() {
129                        return format(
130                                        "%s[samples=%d, min=%s]",
131                                        getClass().getSimpleName(), getSamples(), getMin()
132                                );
133                }
134
135                @Override
136                public Min<C> clone() {
137                        return (Min<C>)super.clone();
138                }
139        }
140
141
142        /**
143         * Calculates max value.
144         *
145         * <p/>
146         * <strong>Note that this implementation is not synchronized.</strong> If
147         * multiple threads access this object concurrently, and at least one of the
148         * threads modifies it, it must be synchronized externally.
149         *
150         * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
151         * @since 1.0
152         * @version 1.0 &ndash; <em>$Revision$</em>
153         */
154        public static final class Max<C extends Comparable<? super C>>
155                extends MappedAccumulator<C>
156        {
157                private C _max;
158
159                /**
160                 * Create a new Max accumulator.
161                 */
162                public Max() {
163                }
164
165                /**
166                 * Copy constructor.
167                 *
168                 * @param max the accumulator to copy.
169                 * @throws NullPointerException if {@code max} is {@code null}.
170                 */
171                public Max(final Max<C> max) {
172                        requireNonNull(max, "Max");
173                        _samples = max._samples;
174                        _max = max._max;
175                }
176
177                /**
178                 * Return the max value, accumulated so far.
179                 *
180                 * @return the max value, accumulated so far.
181                 */
182                public C getMax() {
183                        return _max;
184                }
185
186                /**
187                 * @throws NullPointerException if the given {@code value} is {@code null}.
188                 */
189                @Override
190                public void accumulate(final C value) {
191                        if (_max == null) {
192                                _max = value;
193                        } else {
194                                if (value.compareTo(_max) > 0) {
195                                        _max = value;
196                                }
197                        }
198
199                        ++_samples;
200                }
201
202                @Override
203                public int hashCode() {
204                        return hashCodeOf(getClass()).and(super.hashCode()).and(_max).value();
205                }
206
207                @Override
208                public boolean equals(final Object obj) {
209                        if (obj == this) {
210                                return true;
211                        }
212                        if (obj == null || obj.getClass() != getClass()) {
213                                return false;
214                        }
215
216                        final Max<?> max = (Max<?>)obj;
217                        return super.equals(obj) && eq(_max, max._max);
218                }
219
220                @Override
221                public String toString() {
222                        return format(
223                                        "%s[samples=%d, max=%s]",
224                                        getClass().getSimpleName(), getSamples(), getMax()
225                                );
226                }
227
228                @Override
229                public Max<C> clone() {
230                        return (Max<C>)super.clone();
231                }
232        }
233
234
235        /**
236         * Calculates min and max values.
237         *
238         * <p/>
239         * <strong>Note that this implementation is not synchronized.</strong> If
240         * multiple threads access this object concurrently, and at least one of the
241         * threads modifies it, it must be synchronized externally.
242         *
243         * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
244         * @since 1.0
245         * @version 1.0 &ndash; <em>$Revision$</em>
246         */
247        public static final class MinMax<C extends Comparable<? super C>>
248                extends MappedAccumulator<C>
249        {
250                private C _min;
251                private C _max;
252
253                /**
254                 * Create a new min-max accumulator.
255                 */
256                public MinMax() {
257                }
258
259                /**
260                 * Copy constructor.
261                 *
262                 * @param mm the accumulator to copy.
263                 * @throws NullPointerException if {@code mm} is {@code null}.
264                 */
265                public MinMax(final MinMax<C> mm) {
266                        requireNonNull(mm, "MinMax");
267                        _samples = mm._samples;
268                        _min = mm._min;
269                        _max = mm._max;
270                }
271
272                /**
273                 * Return the min value, accumulated so far.
274                 *
275                 * @return the min value, accumulated so far.
276                 */
277                public C getMin() {
278                        return _min;
279                }
280
281                /**
282                 * Return the max value, accumulated so far.
283                 *
284                 * @return the max value, accumulated so far.
285                 */
286                public C getMax() {
287                        return _max;
288                }
289
290                /**
291                 * @throws NullPointerException if the given {@code value} is {@code null}.
292                 */
293                @Override
294                public void accumulate(final C value) {
295                        if (_min == null) {
296                                _min = value;
297                                _max = value;
298                        } else {
299                                if (value.compareTo(_min) < 0) {
300                                        _min = value;
301                                } else if (value.compareTo(_max) > 0) {
302                                        _max = value;
303                                }
304                        }
305
306                        ++_samples;
307                }
308
309                @Override
310                public int hashCode() {
311                        return hashCodeOf(getClass()).
312                                        and(super.hashCode()).
313                                        and(_min).
314                                        and(_max).value();
315                }
316
317                @Override
318                public boolean equals(final Object obj) {
319                        if (obj == this) {
320                                return true;
321                        }
322                        if (obj == null || obj.getClass() != getClass()) {
323                                return false;
324                        }
325
326                        final MinMax<?> mm = (MinMax<?>)obj;
327                        return super.equals(obj) && eq(_min, mm._min) && eq(_max, mm._max);
328                }
329
330                @Override
331                public String toString() {
332                        return format(
333                                        "%s[samples=%d, min=%s, max=%s]",
334                                        getClass().getSimpleName(), getSamples(), getMin(), getMax()
335                                );
336                }
337
338                @Override
339                public MinMax<C> clone() {
340                        return (MinMax<C>)super.clone();
341                }
342        }
343
344        /**
345         * Calculates the sum of the accumulated values.
346         *
347         * <p/>
348         * <strong>Note that this implementation is not synchronized.</strong> If
349         * multiple threads access this object concurrently, and at least one of the
350         * threads modifies it, it must be synchronized externally.
351         *
352         * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
353         * @since 1.0
354         * @version 1.0 &ndash; <em>$Revision$</em>
355         */
356        public static class Sum<G extends GroupAdditive<G>>
357                extends MappedAccumulator<G>
358        {
359
360                private G _sum = null;
361
362                public Sum() {
363                }
364
365                public Sum(final G start) {
366                        _sum = start;
367                }
368
369                @Override
370                public void accumulate(final G value) {
371                        if (_sum == null) {
372                                _sum = value;
373                        } else {
374                                _sum = _sum.plus(value);
375                        }
376
377                        ++_samples;
378                }
379
380                public G getSum() {
381                        return _sum;
382                }
383
384        }
385
386        /**
387         * Calls the {@link Accumulator#accumulate(Object)} method of all given
388         * {@code accumulators} with each value of the given {@code values}. The
389         * accumulation is done in parallel.
390         *
391         * @param <T> the value type.
392         * @param values the values to accumulate.
393         * @param accus the accumulators to apply.
394         * @throws NullPointerException if one of the given arguments is {@code null}.
395         */
396        public static <T> void accumulate(
397                final Iterable<? extends T> values,
398                final Seq<? extends Accumulator<? super T>> accus
399        ) {
400                switch (accus.length()) {
401                case 1:
402                        accumulators.<T>accumulate(
403                                values,
404                                accus.get(0)
405                        );
406                        break;
407                case 2:
408                        accumulators.<T>accumulate(
409                                values,
410                                accus.get(0),
411                                accus.get(1)
412                        );
413                        break;
414                case 3:
415                        accumulators.<T>accumulate(
416                                values,
417                                accus.get(0),
418                                accus.get(1),
419                                accus.get(2)
420                        );
421                        break;
422                case 4:
423                        accumulators.<T>accumulate(
424                                values,
425                                accus.get(0),
426                                accus.get(1),
427                                accus.get(2),
428                                accus.get(3)
429                        );
430                        break;
431                case 5:
432                        accumulators.<T>accumulate(
433                                values,
434                                accus.get(0),
435                                accus.get(1),
436                                accus.get(2),
437                                accus.get(3),
438                                accus.get(4)
439                        );
440                        break;
441                default:
442                        try (Concurrency c = Concurrency.start()) {
443                                for (final Accumulator<? super T> accumulator : accus) {
444                                        c.execute(new Acc<>(values, accumulator));
445                                }
446                        }
447                }
448        }
449
450        /**
451         * Calls the {@link Accumulator#accumulate(Object)} method of all given
452         * {@code accumulators} with each value of the given {@code values}. The
453         * accumulation is done in parallel.
454         *
455         * @param <T> the value type.
456         * @param values the values to accumulate.
457         * @param accus the accumulators to apply.
458         * @throws NullPointerException if one of the given arguments is {@code null}.
459         */
460        @SafeVarargs
461        public static <T> void accumulate(
462                final Iterable<? extends T> values,
463                final Accumulator<? super T>... accus
464        ) {
465                accumulate(values, Array.valueOf(accus));
466        }
467
468        /**
469         * Calls the {@link Accumulator#accumulate(Object)} method of the given
470         * {@code accumulator} with each value of the given {@code values}.
471         *
472         * @param <T> the value type.
473         * @param values the values to accumulate.
474         * @param a the accumulator.
475         * @throws NullPointerException if one of the given arguments is {@code null}.
476         */
477        public static <T> void accumulate(
478                final Iterator<? extends T> values,
479                final Accumulator<? super T> a
480        ) {
481                while (values.hasNext()) {
482                        a.accumulate(values.next());
483                }
484        }
485
486        /**
487         * Calls the {@link Accumulator#accumulate(Object)} method of the given
488         * {@code accumulator} with each value of the given {@code values}.
489         *
490         * @param <T> the value type.
491         * @param values the values to accumulate.
492         * @param a the accumulator.
493         * @throws NullPointerException if one of the given arguments is {@code null}.
494         */
495        public static <T> void accumulate(
496                final Iterable<? extends T> values,
497                final Accumulator<? super T> a
498        ) {
499                for (final T value : values) {
500                        a.accumulate(value);
501                }
502        }
503
504        /**
505         * Calls the {@link Accumulator#accumulate(Object)} method of all given
506         * {@code accumulators} with each value of the given {@code values}. The
507         * accumulation is done in parallel.
508         *
509         * @param <T> the value type.
510         * @param values the values to accumulate.
511         * @param a1 the first accumulator.
512         * @param a2 the second accumulator.
513         * @throws NullPointerException if one of the given arguments is {@code null}.
514         */
515        public static <T> void accumulate(
516                final Iterable<? extends T> values,
517                final Accumulator<? super T> a1,
518                final Accumulator<? super T> a2
519        ) {
520                try (Concurrency c = Concurrency.start()) {
521                        c.execute(new Acc<>(values, a1));
522                        c.execute(new Acc<>(values, a2));;
523                }
524        }
525
526        /**
527         * Calls the {@link Accumulator#accumulate(Object)} method of all given
528         * {@code accumulators} with each value of the given {@code values}. The
529         * accumulation is done in parallel.
530         *
531         * @param <T> the value type.
532         * @param values the values to accumulate.
533         * @param a1 the first accumulator.
534         * @param a2 the second accumulator.
535         * @param a3 the third accumulator
536         * @throws NullPointerException if one of the given arguments is {@code null}.
537         */
538        public static <T> void accumulate(
539                final Iterable<? extends T> values,
540                final Accumulator<? super T> a1,
541                final Accumulator<? super T> a2,
542                final Accumulator<? super T> a3
543        ) {
544                try (Concurrency c = Concurrency.start()) {
545                        c.execute(new Acc<>(values, a1));
546                        c.execute(new Acc<>(values, a2));
547                        c.execute(new Acc<>(values, a3));
548                }
549        }
550
551        /**
552         * Calls the {@link Accumulator#accumulate(Object)} method of all given
553         * {@code accumulators} with each value of the given {@code values}. The
554         * accumulation is done in parallel.
555         *
556         * @param <T> the value type.
557         * @param values the values to accumulate.
558         * @param a1 the first accumulator.
559         * @param a2 the second accumulator.
560         * @param a3 the third accumulator.
561         * @param a4 the fourth accumulator.
562         * @throws NullPointerException if one of the given arguments is {@code null}.
563         */
564        public static <T> void accumulate(
565                final Iterable<? extends T> values,
566                final Accumulator<? super T> a1,
567                final Accumulator<? super T> a2,
568                final Accumulator<? super T> a3,
569                final Accumulator<? super T> a4
570        ) {
571                try (Concurrency c = Concurrency.start()) {
572                        c.execute(new Acc<>(values, a1));
573                        c.execute(new Acc<>(values, a2));
574                        c.execute(new Acc<>(values, a3));
575                        c.execute(new Acc<>(values, a4));
576                }
577        }
578
579        /**
580         * Calls the {@link Accumulator#accumulate(Object)} method of all given
581         * {@code accumulators} with each value of the given {@code values}. The
582         * accumulation is done in parallel.
583         *
584         * @param <T> the value type.
585         * @param values the values to accumulate.
586         * @param a1 the first accumulator.
587         * @param a2 the second accumulator.
588         * @param a3 the third accumulator.
589         * @param a4 the fourth accumulator.
590         * @param a5 the fifth accumulator.
591         * @throws NullPointerException if one of the given arguments is {@code null}.
592         */
593        public static <T> void accumulate(
594                final Iterable<? extends T> values,
595                final Accumulator<? super T> a1,
596                final Accumulator<? super T> a2,
597                final Accumulator<? super T> a3,
598                final Accumulator<? super T> a4,
599                final Accumulator<? super T> a5
600        ) {
601                try (Concurrency c = Concurrency.start()) {
602                        c.execute(new Acc<>(values, a1));
603                        c.execute(new Acc<>(values, a2));
604                        c.execute(new Acc<>(values, a3));
605                        c.execute(new Acc<>(values, a4));
606                        c.execute(new Acc<>(values, a5));
607                }
608        }
609
610        private static final class Acc<T> implements Runnable {
611                private final Iterable<? extends T> _values;
612                private final Accumulator<? super T> _accumulator;
613
614                public Acc(
615                        final Iterable<? extends T> values,
616                        final Accumulator<? super T> accumulator
617                ) {
618                        _values = values;
619                        _accumulator = accumulator;
620                }
621
622                @Override
623                public void run() {
624                        for (final T value : _values) {
625                                _accumulator.accumulate(value);
626                        }
627                }
628        }
629
630}
631
632