001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  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    package org.apache.commons.math3.stat.descriptive;
018    
019    import org.apache.commons.math3.exception.util.LocalizedFormats;
020    import org.apache.commons.math3.exception.MathIllegalArgumentException;
021    import org.apache.commons.math3.exception.NullArgumentException;
022    import org.apache.commons.math3.util.MathUtils;
023    import org.apache.commons.math3.util.Precision;
024    
025    /**
026     *
027     * Abstract implementation of the {@link StorelessUnivariateStatistic} interface.
028     * <p>
029     * Provides default <code>evaluate()</code> and <code>incrementAll(double[])</code>
030     * implementations.</p>
031     * <p>
032     * <strong>Note that these implementations are not synchronized.</strong></p>
033     *
034     * @version $Id: AbstractStorelessUnivariateStatistic.java 1416643 2012-12-03 19:37:14Z tn $
035     */
036    public abstract class AbstractStorelessUnivariateStatistic
037        extends AbstractUnivariateStatistic
038        implements StorelessUnivariateStatistic {
039    
040        /**
041         * This default implementation calls {@link #clear}, then invokes
042         * {@link #increment} in a loop over the the input array, and then uses
043         * {@link #getResult} to compute the return value.
044         * <p>
045         * Note that this implementation changes the internal state of the
046         * statistic.  Its side effects are the same as invoking {@link #clear} and
047         * then {@link #incrementAll(double[])}.</p>
048         * <p>
049         * Implementations may override this method with a more efficient and
050         * possibly more accurate implementation that works directly with the
051         * input array.</p>
052         * <p>
053         * If the array is null, a MathIllegalArgumentException is thrown.</p>
054         * @param values input array
055         * @return the value of the statistic applied to the input array
056         * @throws MathIllegalArgumentException if values is null
057         * @see org.apache.commons.math3.stat.descriptive.UnivariateStatistic#evaluate(double[])
058         */
059        @Override
060        public double evaluate(final double[] values) throws MathIllegalArgumentException {
061            if (values == null) {
062                throw new NullArgumentException(LocalizedFormats.INPUT_ARRAY);
063            }
064            return evaluate(values, 0, values.length);
065        }
066    
067        /**
068         * This default implementation calls {@link #clear}, then invokes
069         * {@link #increment} in a loop over the specified portion of the input
070         * array, and then uses {@link #getResult} to compute the return value.
071         * <p>
072         * Note that this implementation changes the internal state of the
073         * statistic.  Its side effects are the same as invoking {@link #clear} and
074         * then {@link #incrementAll(double[], int, int)}.</p>
075         * <p>
076         * Implementations may override this method with a more efficient and
077         * possibly more accurate implementation that works directly with the
078         * input array.</p>
079         * <p>
080         * If the array is null or the index parameters are not valid, an
081         * MathIllegalArgumentException is thrown.</p>
082         * @param values the input array
083         * @param begin the index of the first element to include
084         * @param length the number of elements to include
085         * @return the value of the statistic applied to the included array entries
086         * @throws MathIllegalArgumentException if the array is null or the indices are not valid
087         * @see org.apache.commons.math3.stat.descriptive.UnivariateStatistic#evaluate(double[], int, int)
088         */
089        @Override
090        public double evaluate(final double[] values, final int begin,
091                final int length) throws MathIllegalArgumentException {
092            if (test(values, begin, length)) {
093                clear();
094                incrementAll(values, begin, length);
095            }
096            return getResult();
097        }
098    
099        /**
100         * {@inheritDoc}
101         */
102        @Override
103        public abstract StorelessUnivariateStatistic copy();
104    
105        /**
106         * {@inheritDoc}
107         */
108        public abstract void clear();
109    
110        /**
111         * {@inheritDoc}
112         */
113        public abstract double getResult();
114    
115        /**
116         * {@inheritDoc}
117         */
118        public abstract void increment(final double d);
119    
120        /**
121         * This default implementation just calls {@link #increment} in a loop over
122         * the input array.
123         * <p>
124         * Throws IllegalArgumentException if the input values array is null.</p>
125         *
126         * @param values values to add
127         * @throws MathIllegalArgumentException if values is null
128         * @see org.apache.commons.math3.stat.descriptive.StorelessUnivariateStatistic#incrementAll(double[])
129         */
130        public void incrementAll(double[] values) throws MathIllegalArgumentException {
131            if (values == null) {
132                throw new NullArgumentException(LocalizedFormats.INPUT_ARRAY);
133            }
134            incrementAll(values, 0, values.length);
135        }
136    
137        /**
138         * This default implementation just calls {@link #increment} in a loop over
139         * the specified portion of the input array.
140         * <p>
141         * Throws IllegalArgumentException if the input values array is null.</p>
142         *
143         * @param values  array holding values to add
144         * @param begin   index of the first array element to add
145         * @param length  number of array elements to add
146         * @throws MathIllegalArgumentException if values is null
147         * @see org.apache.commons.math3.stat.descriptive.StorelessUnivariateStatistic#incrementAll(double[], int, int)
148         */
149        public void incrementAll(double[] values, int begin, int length) throws MathIllegalArgumentException {
150            if (test(values, begin, length)) {
151                int k = begin + length;
152                for (int i = begin; i < k; i++) {
153                    increment(values[i]);
154                }
155            }
156        }
157    
158        /**
159         * Returns true iff <code>object</code> is an
160         * <code>AbstractStorelessUnivariateStatistic</code> returning the same
161         * values as this for <code>getResult()</code> and <code>getN()</code>
162         * @param object object to test equality against.
163         * @return true if object returns the same value as this
164         */
165        @Override
166        public boolean equals(Object object) {
167            if (object == this ) {
168                return true;
169            }
170           if (object instanceof AbstractStorelessUnivariateStatistic == false) {
171                return false;
172            }
173            AbstractStorelessUnivariateStatistic stat = (AbstractStorelessUnivariateStatistic) object;
174            return Precision.equalsIncludingNaN(stat.getResult(), this.getResult()) &&
175                   Precision.equalsIncludingNaN(stat.getN(), this.getN());
176        }
177    
178        /**
179         * Returns hash code based on getResult() and getN()
180         *
181         * @return hash code
182         */
183        @Override
184        public int hashCode() {
185            return 31* (31 + MathUtils.hash(getResult())) + MathUtils.hash(getN());
186        }
187    
188    }