1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.math.stat.descriptive.summary;
18
19 import java.io.Serializable;
20
21 import org.apache.commons.math.stat.descriptive.AbstractStorelessUnivariateStatistic;
22
23 /**
24 * Returns the sum of the natural logs for this collection of values.
25 * <p>
26 * Uses {@link java.lang.Math#log(double)} to compute the logs. Therefore,
27 * <ul>
28 * <li>If any of values are < 0, the result is <code>NaN.</code></li>
29 * <li>If all values are non-negative and less than
30 * <code>Double.POSITIVE_INFINITY</code>, but at least one value is 0, the
31 * result is <code>Double.NEGATIVE_INFINITY.</code></li>
32 * <li>If both <code>Double.POSITIVE_INFINITY</code> and
33 * <code>Double.NEGATIVE_INFINITY</code> are among the values, the result is
34 * <code>NaN.</code></li>
35 * </ul></p>
36 * <p>
37 * <strong>Note that this implementation is not synchronized.</strong> If
38 * multiple threads access an instance of this class concurrently, and at least
39 * one of the threads invokes the <code>increment()</code> or
40 * <code>clear()</code> method, it must be synchronized externally.</p>
41 *
42 * @version $Revision: 762087 $ $Date: 2009-04-05 10:20:18 -0400 (Sun, 05 Apr 2009) $
43 */
44 public class SumOfLogs extends AbstractStorelessUnivariateStatistic implements Serializable {
45
46 /** Serializable version identifier */
47 private static final long serialVersionUID = -370076995648386763L;
48
49 /**Number of values that have been added */
50 private int n;
51
52 /**
53 * The currently running value
54 */
55 private double value;
56
57 /**
58 * Create a SumOfLogs instance
59 */
60 public SumOfLogs() {
61 value = 0d;
62 n = 0;
63 }
64
65 /**
66 * Copy constructor, creates a new {@code SumOfLogs} identical
67 * to the {@code original}
68 *
69 * @param original the {@code SumOfLogs} instance to copy
70 */
71 public SumOfLogs(SumOfLogs original) {
72 copy(original, this);
73 }
74
75 /**
76 * {@inheritDoc}
77 */
78 @Override
79 public void increment(final double d) {
80 value += Math.log(d);
81 n++;
82 }
83
84 /**
85 * {@inheritDoc}
86 */
87 @Override
88 public double getResult() {
89 if (n > 0) {
90 return value;
91 } else {
92 return Double.NaN;
93 }
94 }
95
96 /**
97 * {@inheritDoc}
98 */
99 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 }