SumOfLogs.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.core.jdkmath.JdkMath;
  22. import org.apache.commons.math4.legacy.core.MathArrays;

  23. /**
  24.  * Returns the sum of the natural logs for this collection of values.
  25.  * <p>
  26.  * Uses {@link org.apache.commons.math4.core.jdkmath.JdkMath#log(double)} to compute the logs.
  27.  * Therefore,
  28.  * <ul>
  29.  * <li>If any of values are &lt; 0, the result is <code>NaN.</code></li>
  30.  * <li>If all values are non-negative and less than
  31.  * <code>Double.POSITIVE_INFINITY</code>,  but at least one value is 0, the
  32.  * result is <code>Double.NEGATIVE_INFINITY.</code></li>
  33.  * <li>If both <code>Double.POSITIVE_INFINITY</code> and
  34.  * <code>Double.NEGATIVE_INFINITY</code> are among the values, the result is
  35.  * <code>NaN.</code></li>
  36.  * </ul>
  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.</p>
  42.  */
  43. public class SumOfLogs extends AbstractStorelessUnivariateStatistic {
  44.     /** Number of values that have been added. */
  45.     private int n;

  46.     /**
  47.      * The currently running value.
  48.      */
  49.     private double value;

  50.     /**
  51.      * Create a SumOfLogs instance.
  52.      */
  53.     public SumOfLogs() {
  54.        value = 0d;
  55.        n = 0;
  56.     }

  57.     /**
  58.      * Copy constructor, creates a new {@code SumOfLogs} identical
  59.      * to the {@code original}.
  60.      *
  61.      * @param original the {@code SumOfLogs} instance to copy
  62.      * @throws NullArgumentException if original is null
  63.      */
  64.     public SumOfLogs(SumOfLogs original) throws NullArgumentException {
  65.         copy(original, this);
  66.     }

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

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

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

  89.     /**
  90.      * {@inheritDoc}
  91.      */
  92.     @Override
  93.     public void clear() {
  94.         value = 0d;
  95.         n = 0;
  96.     }

  97.     /**
  98.      * Returns the sum of the natural logs of the entries in the specified portion of
  99.      * the input array, or <code>Double.NaN</code> if the designated subarray
  100.      * is empty.
  101.      * <p>
  102.      * Throws <code>MathIllegalArgumentException</code> if the array is null.</p>
  103.      * <p>
  104.      * See {@link SumOfLogs}.</p>
  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 sum of the natural logs of the values or 0 if
  110.      * length = 0
  111.      * @throws MathIllegalArgumentException if the array is null or the array index
  112.      *  parameters are not valid
  113.      */
  114.     @Override
  115.     public double evaluate(final double[] values, final int begin, final int length)
  116.         throws MathIllegalArgumentException {

  117.         double sumLog = Double.NaN;
  118.         if (MathArrays.verifyValues(values, begin, length, true)) {
  119.             sumLog = 0.0;
  120.             for (int i = begin; i < begin + length; i++) {
  121.                 sumLog += JdkMath.log(values[i]);
  122.             }
  123.         }
  124.         return sumLog;
  125.     }

  126.     /**
  127.      * {@inheritDoc}
  128.      */
  129.     @Override
  130.     public SumOfLogs copy() {
  131.         SumOfLogs result = new SumOfLogs();
  132.         // No try-catch or advertised exception here because args are valid
  133.         copy(this, result);
  134.         return result;
  135.     }

  136.     /**
  137.      * Copies source to dest.
  138.      * <p>Neither source nor dest can be null.</p>
  139.      *
  140.      * @param source SumOfLogs to copy
  141.      * @param dest SumOfLogs to copy to
  142.      * @throws NullArgumentException if either source or dest is null
  143.      */
  144.     public static void copy(SumOfLogs source, SumOfLogs dest)
  145.         throws NullArgumentException {
  146.         NullArgumentException.check(source);
  147.         NullArgumentException.check(dest);
  148.         dest.n = source.n;
  149.         dest.value = source.value;
  150.     }
  151. }