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.stat.descriptive.WeightedEvaluation;
023 import org.apache.commons.math.util.FastMath;
024
025 /**
026 * Returns the product of the available values.
027 * <p>
028 * If there are no values in the dataset, or any of the values are
029 * <code>NaN</code>, then <code>NaN</code> is returned.</p>
030 * <p>
031 * <strong>Note that this implementation is not synchronized.</strong> If
032 * multiple threads access an instance of this class concurrently, and at least
033 * one of the threads invokes the <code>increment()</code> or
034 * <code>clear()</code> method, it must be synchronized externally.</p>
035 *
036 * @version $Revision: 1006299 $ $Date: 2010-10-10 16:47:17 +0200 (dim. 10 oct. 2010) $
037 */
038 public class Product extends AbstractStorelessUnivariateStatistic implements Serializable, WeightedEvaluation {
039
040 /** Serializable version identifier */
041 private static final long serialVersionUID = 2824226005990582538L;
042
043 /**The number of values that have been added */
044 private long n;
045
046 /**
047 * The current Running Product.
048 */
049 private double value;
050
051 /**
052 * Create a Product instance
053 */
054 public Product() {
055 n = 0;
056 value = Double.NaN;
057 }
058
059 /**
060 * Copy constructor, creates a new {@code Product} identical
061 * to the {@code original}
062 *
063 * @param original the {@code Product} instance to copy
064 */
065 public Product(Product original) {
066 copy(original, this);
067 }
068
069 /**
070 * {@inheritDoc}
071 */
072 @Override
073 public void increment(final double d) {
074 if (n == 0) {
075 value = d;
076 } else {
077 value *= d;
078 }
079 n++;
080 }
081
082 /**
083 * {@inheritDoc}
084 */
085 @Override
086 public double getResult() {
087 return value;
088 }
089
090 /**
091 * {@inheritDoc}
092 */
093 public long getN() {
094 return n;
095 }
096
097 /**
098 * {@inheritDoc}
099 */
100 @Override
101 public void clear() {
102 value = Double.NaN;
103 n = 0;
104 }
105
106 /**
107 * Returns the product of the entries in the specified portion of
108 * the input array, or <code>Double.NaN</code> if the designated subarray
109 * is empty.
110 * <p>
111 * Throws <code>IllegalArgumentException</code> if the array is null.</p>
112 *
113 * @param values the input array
114 * @param begin index of the first array element to include
115 * @param length the number of elements to include
116 * @return the product of the values or Double.NaN if length = 0
117 * @throws IllegalArgumentException if the array is null or the array index
118 * parameters are not valid
119 */
120 @Override
121 public double evaluate(final double[] values, final int begin, final int length) {
122 double product = Double.NaN;
123 if (test(values, begin, length)) {
124 product = 1.0;
125 for (int i = begin; i < begin + length; i++) {
126 product *= values[i];
127 }
128 }
129 return product;
130 }
131
132 /**
133 * <p>Returns the weighted product of the entries in the specified portion of
134 * the input array, or <code>Double.NaN</code> if the designated subarray
135 * is empty.</p>
136 *
137 * <p>Throws <code>IllegalArgumentException</code> if any of the following are true:
138 * <ul><li>the values array is null</li>
139 * <li>the weights array is null</li>
140 * <li>the weights array does not have the same length as the values array</li>
141 * <li>the weights array contains one or more infinite values</li>
142 * <li>the weights array contains one or more NaN values</li>
143 * <li>the weights array contains negative values</li>
144 * <li>the start and length arguments do not determine a valid array</li>
145 * </ul></p>
146 *
147 * <p>Uses the formula, <pre>
148 * weighted product = ∏values[i]<sup>weights[i]</sup>
149 * </pre>
150 * that is, the weights are applied as exponents when computing the weighted product.</p>
151 *
152 * @param values the input array
153 * @param weights the weights array
154 * @param begin index of the first array element to include
155 * @param length the number of elements to include
156 * @return the product of the values or Double.NaN if length = 0
157 * @throws IllegalArgumentException if the parameters are not valid
158 * @since 2.1
159 */
160 public double evaluate(final double[] values, final double[] weights,
161 final int begin, final int length) {
162 double product = Double.NaN;
163 if (test(values, weights, begin, length)) {
164 product = 1.0;
165 for (int i = begin; i < begin + length; i++) {
166 product *= FastMath.pow(values[i], weights[i]);
167 }
168 }
169 return product;
170 }
171
172 /**
173 * <p>Returns the weighted product of the entries in the input array.</p>
174 *
175 * <p>Throws <code>IllegalArgumentException</code> if any of the following are true:
176 * <ul><li>the values array is null</li>
177 * <li>the weights array is null</li>
178 * <li>the weights array does not have the same length as the values array</li>
179 * <li>the weights array contains one or more infinite values</li>
180 * <li>the weights array contains one or more NaN values</li>
181 * <li>the weights array contains negative values</li>
182 * </ul></p>
183 *
184 * <p>Uses the formula, <pre>
185 * weighted product = ∏values[i]<sup>weights[i]</sup>
186 * </pre>
187 * that is, the weights are applied as exponents when computing the weighted product.</p>
188 *
189 * @param values the input array
190 * @param weights the weights array
191 * @return the product of the values or Double.NaN if length = 0
192 * @throws IllegalArgumentException if the parameters are not valid
193 * @since 2.1
194 */
195 public double evaluate(final double[] values, final double[] weights) {
196 return evaluate(values, weights, 0, values.length);
197 }
198
199
200 /**
201 * {@inheritDoc}
202 */
203 @Override
204 public Product copy() {
205 Product result = new Product();
206 copy(this, result);
207 return result;
208 }
209
210 /**
211 * Copies source to dest.
212 * <p>Neither source nor dest can be null.</p>
213 *
214 * @param source Product to copy
215 * @param dest Product to copy to
216 * @throws NullPointerException if either source or dest is null
217 */
218 public static void copy(Product source, Product dest) {
219 dest.setData(source.getDataRef());
220 dest.n = source.n;
221 dest.value = source.value;
222 }
223
224 }