blob: c7d1d76ea563670eca7097e83b1da48db880c690 [file] [log] [blame]
Raymonddee08492015-04-02 10:43:13 -07001/*
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 */
17package org.apache.commons.math.stat.descriptive.summary;
18
19import java.io.Serializable;
20
21import org.apache.commons.math.stat.descriptive.AbstractStorelessUnivariateStatistic;
22import org.apache.commons.math.stat.descriptive.WeightedEvaluation;
23import org.apache.commons.math.util.FastMath;
24
25/**
26 * Returns the product of the available values.
27 * <p>
28 * If there are no values in the dataset, or any of the values are
29 * <code>NaN</code>, then <code>NaN</code> is returned.</p>
30 * <p>
31 * <strong>Note that this implementation is not synchronized.</strong> If
32 * multiple threads access an instance of this class concurrently, and at least
33 * one of the threads invokes the <code>increment()</code> or
34 * <code>clear()</code> method, it must be synchronized externally.</p>
35 *
36 * @version $Revision: 1006299 $ $Date: 2010-10-10 16:47:17 +0200 (dim. 10 oct. 2010) $
37 */
38public class Product extends AbstractStorelessUnivariateStatistic implements Serializable, WeightedEvaluation {
39
40 /** Serializable version identifier */
41 private static final long serialVersionUID = 2824226005990582538L;
42
43 /**The number of values that have been added */
44 private long n;
45
46 /**
47 * The current Running Product.
48 */
49 private double value;
50
51 /**
52 * Create a Product instance
53 */
54 public Product() {
55 n = 0;
56 value = Double.NaN;
57 }
58
59 /**
60 * Copy constructor, creates a new {@code Product} identical
61 * to the {@code original}
62 *
63 * @param original the {@code Product} instance to copy
64 */
65 public Product(Product original) {
66 copy(original, this);
67 }
68
69 /**
70 * {@inheritDoc}
71 */
72 @Override
73 public void increment(final double d) {
74 if (n == 0) {
75 value = d;
76 } else {
77 value *= d;
78 }
79 n++;
80 }
81
82 /**
83 * {@inheritDoc}
84 */
85 @Override
86 public double getResult() {
87 return value;
88 }
89
90 /**
91 * {@inheritDoc}
92 */
93 public long getN() {
94 return n;
95 }
96
97 /**
98 * {@inheritDoc}
99 */
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 = &prod;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 = &prod;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}