Product.java

  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.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */
  21. package org.hipparchus.stat.descriptive.summary;

  22. import java.io.Serializable;

  23. import org.hipparchus.exception.MathIllegalArgumentException;
  24. import org.hipparchus.exception.NullArgumentException;
  25. import org.hipparchus.stat.descriptive.AbstractStorelessUnivariateStatistic;
  26. import org.hipparchus.stat.descriptive.AggregatableStatistic;
  27. import org.hipparchus.stat.descriptive.WeightedEvaluation;
  28. import org.hipparchus.util.FastMath;
  29. import org.hipparchus.util.MathArrays;
  30. import org.hipparchus.util.MathUtils;

  31. /**
  32.  * Returns the product of the available values.
  33.  * <p>
  34.  * If there are no values in the dataset, then 1 is returned.
  35.  * If any of the values are
  36.  * <code>NaN</code>, then <code>NaN</code> is returned.
  37.  * <p>
  38.  * <strong>Note that this implementation is not synchronized.</strong> If
  39.  * multiple threads access an instance of this class concurrently, and at least
  40.  * one of the threads invokes the <code>increment()</code> or
  41.  * <code>clear()</code> method, it must be synchronized externally.
  42.  */
  43. public class Product extends AbstractStorelessUnivariateStatistic
  44.     implements AggregatableStatistic<Product>, WeightedEvaluation, Serializable {

  45.     /** Serializable version identifier */
  46.     private static final long serialVersionUID = 20150412L;

  47.     /** The number of values that have been added */
  48.     private long n;

  49.     /** The current Running Product */
  50.     private double value;

  51.     /**
  52.      * Create a Product instance.
  53.      */
  54.     public Product() {
  55.         n = 0;
  56.         value = 1;
  57.     }

  58.     /**
  59.      * Copy constructor, creates a new {@code Product} identical
  60.      * to the {@code original}.
  61.      *
  62.      * @param original the {@code Product} instance to copy
  63.      * @throws NullArgumentException  if original is null
  64.      */
  65.     public Product(Product original) throws NullArgumentException {
  66.         MathUtils.checkNotNull(original);
  67.         this.n     = original.n;
  68.         this.value = original.value;
  69.     }

  70.     /** {@inheritDoc} */
  71.     @Override
  72.     public void increment(final double d) {
  73.         value *= d;
  74.         n++;
  75.     }

  76.     /** {@inheritDoc} */
  77.     @Override
  78.     public double getResult() {
  79.         return value;
  80.     }

  81.     /** {@inheritDoc} */
  82.     @Override
  83.     public long getN() {
  84.         return n;
  85.     }

  86.     /** {@inheritDoc} */
  87.     @Override
  88.     public void clear() {
  89.         value = 1;
  90.         n = 0;
  91.     }

  92.     /** {@inheritDoc} */
  93.     @Override
  94.     public void aggregate(Product other) {
  95.         MathUtils.checkNotNull(other);
  96.         if (other.n > 0) {
  97.             this.n     += other.n;
  98.             this.value *= other.value;
  99.         }
  100.     }

  101.     /**
  102.      * Returns the product of the entries in the specified portion of
  103.      * the input array, or <code>Double.NaN</code> if the designated subarray
  104.      * is empty.
  105.      *
  106.      * @param values the input array
  107.      * @param begin index of the first array element to include
  108.      * @param length the number of elements to include
  109.      * @return the product of the values or 1 if length = 0
  110.      * @throws MathIllegalArgumentException if the array is null or the array index
  111.      *  parameters are not valid
  112.      */
  113.     @Override
  114.     public double evaluate(final double[] values, final int begin, final int length)
  115.         throws MathIllegalArgumentException {
  116.         double product = Double.NaN;
  117.         if (MathArrays.verifyValues(values, begin, length, true)) {
  118.             product = 1.0;
  119.             for (int i = begin; i < begin + length; i++) {
  120.                 product *= values[i];
  121.             }
  122.         }
  123.         return product;
  124.     }

  125.     /**
  126.      * Returns the weighted product of the entries in the specified portion of
  127.      * the input array, or <code>Double.NaN</code> if the designated subarray
  128.      * is empty.
  129.      * <p>
  130.      * Throws <code>MathIllegalArgumentException</code> if any of the following are true:
  131.      * <ul><li>the values array is null</li>
  132.      *     <li>the weights array is null</li>
  133.      *     <li>the weights array does not have the same length as the values array</li>
  134.      *     <li>the weights array contains one or more infinite values</li>
  135.      *     <li>the weights array contains one or more NaN values</li>
  136.      *     <li>the weights array contains negative values</li>
  137.      *     <li>the start and length arguments do not determine a valid array</li>
  138.      * </ul>
  139.      * <p>
  140.      * Uses the formula \(\mathrm{weighted product} = \prod \mathrm{values}_i^{\mathrm{weights}_i}\)
  141.      * <p>
  142.      * that is, the weights are applied as exponents when computing the weighted product.
  143.      *
  144.      * @param values the input array
  145.      * @param weights the weights array
  146.      * @param begin index of the first array element to include
  147.      * @param length the number of elements to include
  148.      * @return the product of the values or 1 if length = 0
  149.      * @throws MathIllegalArgumentException if the parameters are not valid
  150.      */
  151.     @Override
  152.     public double evaluate(final double[] values, final double[] weights,
  153.                            final int begin, final int length) throws MathIllegalArgumentException {
  154.         double product = Double.NaN;
  155.         if (MathArrays.verifyValues(values, weights, begin, length, true)) {
  156.             product = 1.0;
  157.             for (int i = begin; i < begin + length; i++) {
  158.                 product *= FastMath.pow(values[i], weights[i]);
  159.             }
  160.         }
  161.         return product;
  162.     }

  163.     /** {@inheritDoc} */
  164.     @Override
  165.     public Product copy() {
  166.         return new Product(this);
  167.     }

  168. }