View Javadoc
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    *      https://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  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.stat.descriptive.summary;
23  
24  import java.io.Serializable;
25  
26  import org.hipparchus.exception.MathIllegalArgumentException;
27  import org.hipparchus.exception.NullArgumentException;
28  import org.hipparchus.stat.descriptive.AbstractStorelessUnivariateStatistic;
29  import org.hipparchus.stat.descriptive.AggregatableStatistic;
30  import org.hipparchus.stat.descriptive.WeightedEvaluation;
31  import org.hipparchus.util.FastMath;
32  import org.hipparchus.util.MathArrays;
33  import org.hipparchus.util.MathUtils;
34  
35  /**
36   * Returns the product of the available values.
37   * <p>
38   * If there are no values in the dataset, then 1 is returned.
39   * If any of the values are
40   * <code>NaN</code>, then <code>NaN</code> is returned.
41   * <p>
42   * <strong>Note that this implementation is not synchronized.</strong> If
43   * multiple threads access an instance of this class concurrently, and at least
44   * one of the threads invokes the <code>increment()</code> or
45   * <code>clear()</code> method, it must be synchronized externally.
46   */
47  public class Product extends AbstractStorelessUnivariateStatistic
48      implements AggregatableStatistic<Product>, WeightedEvaluation, Serializable {
49  
50      /** Serializable version identifier */
51      private static final long serialVersionUID = 20150412L;
52  
53      /** The number of values that have been added */
54      private long n;
55  
56      /** The current Running Product */
57      private double value;
58  
59      /**
60       * Create a Product instance.
61       */
62      public Product() {
63          n = 0;
64          value = 1;
65      }
66  
67      /**
68       * Copy constructor, creates a new {@code Product} identical
69       * to the {@code original}.
70       *
71       * @param original the {@code Product} instance to copy
72       * @throws NullArgumentException  if original is null
73       */
74      public Product(Product original) throws NullArgumentException {
75          MathUtils.checkNotNull(original);
76          this.n     = original.n;
77          this.value = original.value;
78      }
79  
80      /** {@inheritDoc} */
81      @Override
82      public void increment(final double d) {
83          value *= d;
84          n++;
85      }
86  
87      /** {@inheritDoc} */
88      @Override
89      public double getResult() {
90          return value;
91      }
92  
93      /** {@inheritDoc} */
94      @Override
95      public long getN() {
96          return n;
97      }
98  
99      /** {@inheritDoc} */
100     @Override
101     public void clear() {
102         value = 1;
103         n = 0;
104     }
105 
106     /** {@inheritDoc} */
107     @Override
108     public void aggregate(Product other) {
109         MathUtils.checkNotNull(other);
110         if (other.n > 0) {
111             this.n     += other.n;
112             this.value *= other.value;
113         }
114     }
115 
116     /**
117      * Returns the product of the entries in the specified portion of
118      * the input array, or <code>Double.NaN</code> if the designated subarray
119      * is empty.
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 product of the values or 1 if length = 0
125      * @throws MathIllegalArgumentException if the array is null or the array index
126      *  parameters are not valid
127      */
128     @Override
129     public double evaluate(final double[] values, final int begin, final int length)
130         throws MathIllegalArgumentException {
131         double product = Double.NaN;
132         if (MathArrays.verifyValues(values, begin, length, true)) {
133             product = 1.0;
134             for (int i = begin; i < begin + length; i++) {
135                 product *= values[i];
136             }
137         }
138         return product;
139     }
140 
141     /**
142      * Returns the weighted product of the entries in the specified portion of
143      * the input array, or <code>Double.NaN</code> if the designated subarray
144      * is empty.
145      * <p>
146      * Throws <code>MathIllegalArgumentException</code> if any of the following are true:
147      * <ul><li>the values array is null</li>
148      *     <li>the weights array is null</li>
149      *     <li>the weights array does not have the same length as the values array</li>
150      *     <li>the weights array contains one or more infinite values</li>
151      *     <li>the weights array contains one or more NaN values</li>
152      *     <li>the weights array contains negative values</li>
153      *     <li>the start and length arguments do not determine a valid array</li>
154      * </ul>
155      * <p>
156      * Uses the formula \(\mathrm{weighted product} = \prod \mathrm{values}_i^{\mathrm{weights}_i}\)
157      * <p>
158      * that is, the weights are applied as exponents when computing the weighted product.
159      *
160      * @param values the input array
161      * @param weights the weights array
162      * @param begin index of the first array element to include
163      * @param length the number of elements to include
164      * @return the product of the values or 1 if length = 0
165      * @throws MathIllegalArgumentException if the parameters are not valid
166      */
167     @Override
168     public double evaluate(final double[] values, final double[] weights,
169                            final int begin, final int length) throws MathIllegalArgumentException {
170         double product = Double.NaN;
171         if (MathArrays.verifyValues(values, weights, begin, length, true)) {
172             product = 1.0;
173             for (int i = begin; i < begin + length; i++) {
174                 product *= FastMath.pow(values[i], weights[i]);
175             }
176         }
177         return product;
178     }
179 
180     /** {@inheritDoc} */
181     @Override
182     public Product copy() {
183         return new Product(this);
184     }
185 
186 }