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 }