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.  *      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.math4.legacy.stat.descriptive.summary;

  18. import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
  19. import org.apache.commons.math4.legacy.exception.NullArgumentException;
  20. import org.apache.commons.math4.legacy.stat.descriptive.AbstractStorelessUnivariateStatistic;
  21. import org.apache.commons.math4.legacy.stat.descriptive.WeightedEvaluation;
  22. import org.apache.commons.math4.core.jdkmath.JdkMath;
  23. import org.apache.commons.math4.legacy.core.MathArrays;

  24. /**
  25.  * Returns the product of the available values.
  26.  * <p>
  27.  * If there are no values in the dataset, then 1 is returned.
  28.  *  If 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. public class Product extends AbstractStorelessUnivariateStatistic implements WeightedEvaluation {
  37.     /**The number of values that have been added. */
  38.     private long n;

  39.     /**
  40.      * The current Running Product.
  41.      */
  42.     private double value;

  43.     /**
  44.      * Create a Product instance.
  45.      */
  46.     public Product() {
  47.         n = 0;
  48.         value = 1;
  49.     }

  50.     /**
  51.      * Copy constructor, creates a new {@code Product} identical
  52.      * to the {@code original}.
  53.      *
  54.      * @param original the {@code Product} instance to copy
  55.      * @throws NullArgumentException  if original is null
  56.      */
  57.     public Product(Product original) throws NullArgumentException {
  58.         copy(original, this);
  59.     }

  60.     /**
  61.      * {@inheritDoc}
  62.      */
  63.     @Override
  64.     public void increment(final double d) {
  65.         value *= d;
  66.         n++;
  67.     }

  68.     /**
  69.      * {@inheritDoc}
  70.      */
  71.     @Override
  72.     public double getResult() {
  73.         return value;
  74.     }

  75.     /**
  76.      * {@inheritDoc}
  77.      */
  78.     @Override
  79.     public long getN() {
  80.         return n;
  81.     }

  82.     /**
  83.      * {@inheritDoc}
  84.      */
  85.     @Override
  86.     public void clear() {
  87.         value = 1;
  88.         n = 0;
  89.     }

  90.     /**
  91.      * Returns the product of the entries in the specified portion of
  92.      * the input array, or <code>Double.NaN</code> if the designated subarray
  93.      * is empty.
  94.      * <p>
  95.      * Throws <code>MathIllegalArgumentException</code> if the array is null.</p>
  96.      *
  97.      * @param values the input array
  98.      * @param begin index of the first array element to include
  99.      * @param length the number of elements to include
  100.      * @return the product of the values or 1 if length = 0
  101.      * @throws MathIllegalArgumentException if the array is null or the array index
  102.      *  parameters are not valid
  103.      */
  104.     @Override
  105.     public double evaluate(final double[] values, final int begin, final int length)
  106.         throws MathIllegalArgumentException {
  107.         double product = Double.NaN;
  108.         if (MathArrays.verifyValues(values, begin, length, true)) {
  109.             product = 1.0;
  110.             for (int i = begin; i < begin + length; i++) {
  111.                 product *= values[i];
  112.             }
  113.         }
  114.         return product;
  115.     }

  116.     /**
  117.      * <p>Returns the weighted 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.</p>
  120.      *
  121.      * <p>Throws <code>MathIllegalArgumentException</code> if any of the following are true:
  122.      * <ul><li>the values array is null</li>
  123.      *     <li>the weights array is null</li>
  124.      *     <li>the weights array does not have the same length as the values array</li>
  125.      *     <li>the weights array contains one or more infinite values</li>
  126.      *     <li>the weights array contains one or more NaN values</li>
  127.      *     <li>the weights array contains negative values</li>
  128.      *     <li>the start and length arguments do not determine a valid array</li>
  129.      * </ul>
  130.      *
  131.      * <p>Uses the formula, <div style="white-space: pre"><code>
  132.      *    weighted product = &prod;values[i]<sup>weights[i]</sup>
  133.      * </code></div>
  134.      * that is, the weights are applied as exponents when computing the weighted product.
  135.      *
  136.      * @param values the input array
  137.      * @param weights the weights array
  138.      * @param begin index of the first array element to include
  139.      * @param length the number of elements to include
  140.      * @return the product of the values or 1 if length = 0
  141.      * @throws MathIllegalArgumentException if the parameters are not valid
  142.      * @since 2.1
  143.      */
  144.     @Override
  145.     public double evaluate(final double[] values, final double[] weights,
  146.                            final int begin, final int length) throws MathIllegalArgumentException {
  147.         double product = Double.NaN;
  148.         if (MathArrays.verifyValues(values, weights, begin, length, true)) {
  149.             product = 1.0;
  150.             for (int i = begin; i < begin + length; i++) {
  151.                 product *= JdkMath.pow(values[i], weights[i]);
  152.             }
  153.         }
  154.         return product;
  155.     }

  156.     /**
  157.      * <p>Returns the weighted product of the entries in the input array.</p>
  158.      *
  159.      * <p>Throws <code>MathIllegalArgumentException</code> if any of the following are true:
  160.      * <ul><li>the values array is null</li>
  161.      *     <li>the weights array is null</li>
  162.      *     <li>the weights array does not have the same length as the values array</li>
  163.      *     <li>the weights array contains one or more infinite values</li>
  164.      *     <li>the weights array contains one or more NaN values</li>
  165.      *     <li>the weights array contains negative values</li>
  166.      * </ul>
  167.      *
  168.      * <p>Uses the formula,
  169.      * <div style="white-space: pre"><code>
  170.      *    weighted product = &prod;values[i]<sup>weights[i]</sup>
  171.      * </code></div>
  172.      * that is, the weights are applied as exponents when computing the weighted product.
  173.      *
  174.      * @param values the input array
  175.      * @param weights the weights array
  176.      * @return the product of the values or Double.NaN if length = 0
  177.      * @throws MathIllegalArgumentException if the parameters are not valid
  178.      * @since 2.1
  179.      */
  180.     @Override
  181.     public double evaluate(final double[] values, final double[] weights) throws MathIllegalArgumentException {
  182.         return evaluate(values, weights, 0, values.length);
  183.     }

  184.     /**
  185.      * {@inheritDoc}
  186.      */
  187.     @Override
  188.     public Product copy() {
  189.         Product result = new Product();
  190.         // No try-catch or advertised exception because args are valid
  191.         copy(this, result);
  192.         return result;
  193.     }

  194.     /**
  195.      * Copies source to dest.
  196.      * <p>Neither source nor dest can be null.</p>
  197.      *
  198.      * @param source Product to copy
  199.      * @param dest Product to copy to
  200.      * @throws NullArgumentException if either source or dest is null
  201.      */
  202.     public static void copy(Product source, Product dest)
  203.         throws NullArgumentException {
  204.         NullArgumentException.check(source);
  205.         NullArgumentException.check(dest);
  206.         dest.n = source.n;
  207.         dest.value = source.value;
  208.     }
  209. }