Home | History | Annotate | Download | only in descriptive
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 package org.apache.commons.math.stat.descriptive;
     18 
     19 import org.apache.commons.math.MathRuntimeException;
     20 import org.apache.commons.math.exception.DimensionMismatchException;
     21 import org.apache.commons.math.exception.NotPositiveException;
     22 import org.apache.commons.math.exception.NullArgumentException;
     23 import org.apache.commons.math.exception.util.LocalizedFormats;
     24 
     25 /**
     26  * Abstract base class for all implementations of the
     27  * {@link UnivariateStatistic} interface.
     28  * <p>
     29  * Provides a default implementation of <code>evaluate(double[]),</code>
     30  * delegating to <code>evaluate(double[], int, int)</code> in the natural way.
     31  * </p>
     32  * <p>
     33  * Also includes a <code>test</code> method that performs generic parameter
     34  * validation for the <code>evaluate</code> methods.</p>
     35  *
     36  * @version $Revision: 1006299 $ $Date: 2010-10-10 16:47:17 +0200 (dim. 10 oct. 2010) $
     37  */
     38 public abstract class AbstractUnivariateStatistic
     39     implements UnivariateStatistic {
     40 
     41     /** Stored data. */
     42     private double[] storedData;
     43 
     44     /**
     45      * Set the data array.
     46      * <p>
     47      * The stored value is a copy of the parameter array, not the array itself
     48      * </p>
     49      * @param values data array to store (may be null to remove stored data)
     50      * @see #evaluate()
     51      */
     52     public void setData(final double[] values) {
     53         storedData = (values == null) ? null : values.clone();
     54     }
     55 
     56     /**
     57      * Get a copy of the stored data array.
     58      * @return copy of the stored data array (may be null)
     59      */
     60     public double[] getData() {
     61         return (storedData == null) ? null : storedData.clone();
     62     }
     63 
     64     /**
     65      * Get a reference to the stored data array.
     66      * @return reference to the stored data array (may be null)
     67      */
     68     protected double[] getDataRef() {
     69         return storedData;
     70     }
     71 
     72     /**
     73      * Set the data array.
     74      * @param values data array to store
     75      * @param begin the index of the first element to include
     76      * @param length the number of elements to include
     77      * @see #evaluate()
     78      */
     79     public void setData(final double[] values, final int begin, final int length) {
     80         storedData = new double[length];
     81         System.arraycopy(values, begin, storedData, 0, length);
     82     }
     83 
     84     /**
     85      * Returns the result of evaluating the statistic over the stored data.
     86      * <p>
     87      * The stored array is the one which was set by previous calls to
     88      * </p>
     89      * @return the value of the statistic applied to the stored data
     90      */
     91     public double evaluate() {
     92         return evaluate(storedData);
     93     }
     94 
     95     /**
     96      * {@inheritDoc}
     97      */
     98     public double evaluate(final double[] values) {
     99         test(values, 0, 0);
    100         return evaluate(values, 0, values.length);
    101     }
    102 
    103     /**
    104      * {@inheritDoc}
    105      */
    106     public abstract double evaluate(final double[] values, final int begin, final int length);
    107 
    108     /**
    109      * {@inheritDoc}
    110      */
    111     public abstract UnivariateStatistic copy();
    112 
    113     /**
    114      * This method is used by <code>evaluate(double[], int, int)</code> methods
    115      * to verify that the input parameters designate a subarray of positive length.
    116      * <p>
    117      * <ul>
    118      * <li>returns <code>true</code> iff the parameters designate a subarray of
    119      * positive length</li>
    120      * <li>throws <code>IllegalArgumentException</code> if the array is null or
    121      * or the indices are invalid</li>
    122      * <li>returns <code>false</li> if the array is non-null, but
    123      * <code>length</code> is 0.
    124      * </ul></p>
    125      *
    126      * @param values the input array
    127      * @param begin index of the first array element to include
    128      * @param length the number of elements to include
    129      * @return true if the parameters are valid and designate a subarray of positive length
    130      * @throws IllegalArgumentException if the indices are invalid or the array is null
    131      */
    132     protected boolean test(
    133         final double[] values,
    134         final int begin,
    135         final int length) {
    136 
    137         if (values == null) {
    138             throw new NullArgumentException(LocalizedFormats.INPUT_ARRAY);
    139         }
    140 
    141         if (begin < 0) {
    142             throw new NotPositiveException(LocalizedFormats.START_POSITION, begin);
    143         }
    144 
    145         if (length < 0) {
    146             throw new NotPositiveException(LocalizedFormats.LENGTH, length);
    147         }
    148 
    149         if (begin + length > values.length) {
    150             throw MathRuntimeException.createIllegalArgumentException(
    151                   LocalizedFormats.SUBARRAY_ENDS_AFTER_ARRAY_END);
    152         }
    153 
    154         if (length == 0) {
    155             return false;
    156         }
    157 
    158         return true;
    159 
    160     }
    161 
    162     /**
    163      * This method is used by <code>evaluate(double[], double[], int, int)</code> methods
    164      * to verify that the begin and length parameters designate a subarray of positive length
    165      * and the weights are all non-negative, non-NaN, finite, and not all zero.
    166      * <p>
    167      * <ul>
    168      * <li>returns <code>true</code> iff the parameters designate a subarray of
    169      * positive length and the weights array contains legitimate values.</li>
    170      * <li>throws <code>IllegalArgumentException</code> if any of the following are true:
    171      * <ul><li>the values array is null</li>
    172      *     <li>the weights array is null</li>
    173      *     <li>the weights array does not have the same length as the values array</li>
    174      *     <li>the weights array contains one or more infinite values</li>
    175      *     <li>the weights array contains one or more NaN values</li>
    176      *     <li>the weights array contains negative values</li>
    177      *     <li>the start and length arguments do not determine a valid array</li></ul>
    178      * </li>
    179      * <li>returns <code>false</li> if the array is non-null, but
    180      * <code>length</code> is 0.
    181      * </ul></p>
    182      *
    183      * @param values the input array
    184      * @param weights the weights array
    185      * @param begin index of the first array element to include
    186      * @param length the number of elements to include
    187      * @return true if the parameters are valid and designate a subarray of positive length
    188      * @throws IllegalArgumentException if the indices are invalid or the array is null
    189      * @since 2.1
    190      */
    191     protected boolean test(
    192         final double[] values,
    193         final double[] weights,
    194         final int begin,
    195         final int length) {
    196 
    197         if (weights == null) {
    198             throw new NullArgumentException(LocalizedFormats.INPUT_ARRAY);
    199         }
    200 
    201         if (weights.length != values.length) {
    202             throw new DimensionMismatchException(weights.length, values.length);
    203         }
    204 
    205         boolean containsPositiveWeight = false;
    206         for (int i = begin; i < begin + length; i++) {
    207             if (Double.isNaN(weights[i])) {
    208                 throw MathRuntimeException.createIllegalArgumentException(
    209                         LocalizedFormats.NAN_ELEMENT_AT_INDEX, i);
    210             }
    211             if (Double.isInfinite(weights[i])) {
    212                 throw MathRuntimeException.createIllegalArgumentException(
    213                         LocalizedFormats.INFINITE_ARRAY_ELEMENT, weights[i], i);
    214             }
    215             if (weights[i] < 0) {
    216                 throw MathRuntimeException.createIllegalArgumentException(
    217                       LocalizedFormats.NEGATIVE_ELEMENT_AT_INDEX, i, weights[i]);
    218             }
    219             if (!containsPositiveWeight && weights[i] > 0.0) {
    220                 containsPositiveWeight = true;
    221             }
    222         }
    223 
    224         if (!containsPositiveWeight) {
    225             throw MathRuntimeException.createIllegalArgumentException(
    226                     LocalizedFormats.WEIGHT_AT_LEAST_ONE_NON_ZERO);
    227         }
    228 
    229         return test(values, begin, length);
    230     }
    231 }
    232 
    233