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