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 }