    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.math.stat.descriptive.summary;
    018
    019    import java.io.Serializable;
    020
    021    import org.apache.commons.math.stat.descriptive.AbstractStorelessUnivariateStatistic;
    022    import org.apache.commons.math.util.FastMath;
    023
    024    /**
    025     * Returns the sum of the natural logs for this collection of values.
    026     * <p>
    027     * Uses {@link java.lang.Math#log(double)} to compute the logs.  Therefore,
    028     * <ul>
    029     * <li>If any of values are < 0, the result is <code>NaN.</code></li>
    030     * <li>If all values are non-negative and less than
    031     * <code>Double.POSITIVE_INFINITY</code>,  but at least one value is 0, the
    032     * result is <code>Double.NEGATIVE_INFINITY.</code></li>
    033     * <li>If both <code>Double.POSITIVE_INFINITY</code> and
    034     * <code>Double.NEGATIVE_INFINITY</code> are among the values, the result is
    035     * <code>NaN.</code></li>
    036     * </ul></p>
    037     * <p>
    038     * <strong>Note that this implementation is not synchronized.</strong> If
    039     * multiple threads access an instance of this class concurrently, and at least
    040     * one of the threads invokes the <code>increment()</code> or
    041     * <code>clear()</code> method, it must be synchronized externally.</p>
    042     *
    043     * @version $Revision: 1006299 $ $Date: 2010-10-10 16:47:17 +0200 (dim. 10 oct. 2010) $
    044     */
    045    public class SumOfLogs extends AbstractStorelessUnivariateStatistic implements Serializable {
    046
    047        /** Serializable version identifier */
    048        private static final long serialVersionUID = -370076995648386763L;
    049
    050        /**Number of values that have been added */
    051        private int n;
    052
    053        /**
    054         * The currently running value
    055         */
    056        private double value;
    057
    058        /**
    059         * Create a SumOfLogs instance
    060         */
    061        public SumOfLogs() {
    062           value = 0d;
    063           n = 0;
    064        }
    065
    066        /**
    067         * Copy constructor, creates a new {@code SumOfLogs} identical
    068         * to the {@code original}
    069         *
    070         * @param original the {@code SumOfLogs} instance to copy
    071         */
    072        public SumOfLogs(SumOfLogs original) {
    073            copy(original, this);
    074        }
    075
    076        /**
    077         * {@inheritDoc}
    078         */
    079        @Override
    080        public void increment(final double d) {
    081            value += FastMath.log(d);
    082            n++;
    083        }
    084
    085        /**
    086         * {@inheritDoc}
    087         */
    088        @Override
    089        public double getResult() {
    090            if (n > 0) {
    091                return value;
    092            } else {
    093                return Double.NaN;
    094            }
    095        }
    096
    097        /**
    098         * {@inheritDoc}
    099         */
    100        public long getN() {
    101            return n;
    102        }
    103
    104        /**
    105         * {@inheritDoc}
    106         */
    107        @Override
    108        public void clear() {
    109            value = 0d;
    110            n = 0;
    111        }
    112
    113        /**
    114         * Returns the sum of the natural logs of the entries in the specified portion of
    115         * the input array, or <code>Double.NaN</code> if the designated subarray
    116         * is empty.
    117         * <p>
    118         * Throws <code>IllegalArgumentException</code> if the array is null.</p>
    119         * <p>
    120         * See {@link SumOfLogs}.</p>
    121         *
    122         * @param values the input array
    123         * @param begin index of the first array element to include
    124         * @param length the number of elements to include
    125         * @return the sum of the natural logs of the values or Double.NaN if
    126         * length = 0
    127         * @throws IllegalArgumentException if the array is null or the array index
    128         *  parameters are not valid
    129         */
    130        @Override
    131        public double evaluate(final double[] values, final int begin, final int length) {
    132            double sumLog = Double.NaN;
    133            if (test(values, begin, length)) {
    134                sumLog = 0.0;
    135                for (int i = begin; i < begin + length; i++) {
    136                    sumLog += FastMath.log(values[i]);
    137                }
    138            }
    139            return sumLog;
    140        }
    141
    142        /**
    143         * {@inheritDoc}
    144         */
    145        @Override
    146        public SumOfLogs copy() {
    147            SumOfLogs result = new SumOfLogs();
    148            copy(this, result);
    149            return result;
    150        }
    151
    152        /**
    153         * Copies source to dest.
    154         * <p>Neither source nor dest can be null.</p>
    155         *
    156         * @param source SumOfLogs to copy
    157         * @param dest SumOfLogs to copy to
    158         * @throws NullPointerException if either source or dest is null
    159         */
    160        public static void copy(SumOfLogs source, SumOfLogs dest) {
    161            dest.setData(source.getDataRef());
    162            dest.n = source.n;
    163            dest.value = source.value;
    164        }
    165    }