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    }