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.exception.NullArgumentException;
022 import org.apache.commons.math.stat.descriptive.AbstractStorelessUnivariateStatistic;
023 import org.apache.commons.math.util.FastMath;
024 import org.apache.commons.math.util.MathUtils;
025
026 /**
027 * Returns the sum of the natural logs for this collection of values.
028 * <p>
029 * Uses {@link org.apache.commons.math.util.FastMath#log(double)} to compute the logs.
030 * Therefore,
031 * <ul>
032 * <li>If any of values are < 0, the result is <code>NaN.</code></li>
033 * <li>If all values are non-negative and less than
034 * <code>Double.POSITIVE_INFINITY</code>, but at least one value is 0, the
035 * result is <code>Double.NEGATIVE_INFINITY.</code></li>
036 * <li>If both <code>Double.POSITIVE_INFINITY</code> and
037 * <code>Double.NEGATIVE_INFINITY</code> are among the values, the result is
038 * <code>NaN.</code></li>
039 * </ul></p>
040 * <p>
041 * <strong>Note that this implementation is not synchronized.</strong> If
042 * multiple threads access an instance of this class concurrently, and at least
043 * one of the threads invokes the <code>increment()</code> or
044 * <code>clear()</code> method, it must be synchronized externally.</p>
045 *
046 * @version $Id: SumOfLogs.java 1132432 2011-06-05 14:59:29Z luc $
047 */
048 public class SumOfLogs extends AbstractStorelessUnivariateStatistic implements Serializable {
049
050 /** Serializable version identifier */
051 private static final long serialVersionUID = -370076995648386763L;
052
053 /**Number of values that have been added */
054 private int n;
055
056 /**
057 * The currently running value
058 */
059 private double value;
060
061 /**
062 * Create a SumOfLogs instance
063 */
064 public SumOfLogs() {
065 value = 0d;
066 n = 0;
067 }
068
069 /**
070 * Copy constructor, creates a new {@code SumOfLogs} identical
071 * to the {@code original}
072 *
073 * @param original the {@code SumOfLogs} instance to copy
074 */
075 public SumOfLogs(SumOfLogs original) {
076 copy(original, this);
077 }
078
079 /**
080 * {@inheritDoc}
081 */
082 @Override
083 public void increment(final double d) {
084 value += FastMath.log(d);
085 n++;
086 }
087
088 /**
089 * {@inheritDoc}
090 */
091 @Override
092 public double getResult() {
093 return value;
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 0 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, true)) {
133 sumLog = 0.0;
134 for (int i = begin; i < begin + length; i++) {
135 sumLog += FastMath.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 NullArgumentException if either source or dest is null
158 */
159 public static void copy(SumOfLogs source, SumOfLogs dest)
160 throws NullArgumentException {
161 MathUtils.checkNotNull(source);
162 MathUtils.checkNotNull(dest);
163 dest.setData(source.getDataRef());
164 dest.n = source.n;
165 dest.value = source.value;
166 }
167 }