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    *      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  
19  import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
20  import org.apache.commons.math4.legacy.exception.NullArgumentException;
21  import org.apache.commons.math4.legacy.stat.descriptive.AbstractStorelessUnivariateStatistic;
22  import org.apache.commons.math4.core.jdkmath.JdkMath;
23  import org.apache.commons.math4.legacy.core.MathArrays;
24  
25  /**
26   * Returns the sum of the natural logs for this collection of values.
27   * <p>
28   * Uses {@link org.apache.commons.math4.core.jdkmath.JdkMath#log(double)} to compute the logs.
29   * Therefore,
30   * <ul>
31   * <li>If any of values are &lt; 0, the result is <code>NaN.</code></li>
32   * <li>If all values are non-negative and less than
33   * <code>Double.POSITIVE_INFINITY</code>,  but at least one value is 0, the
34   * result is <code>Double.NEGATIVE_INFINITY.</code></li>
35   * <li>If both <code>Double.POSITIVE_INFINITY</code> and
36   * <code>Double.NEGATIVE_INFINITY</code> are among the values, the result is
37   * <code>NaN.</code></li>
38   * </ul>
39   * <p>
40   * <strong>Note that this implementation is not synchronized.</strong> If
41   * multiple threads access an instance of this class concurrently, and at least
42   * one of the threads invokes the <code>increment()</code> or
43   * <code>clear()</code> method, it must be synchronized externally.</p>
44   */
45  public class SumOfLogs extends AbstractStorelessUnivariateStatistic {
46      /** Number of values that have been added. */
47      private int n;
48  
49      /**
50       * The currently running value.
51       */
52      private double value;
53  
54      /**
55       * Create a SumOfLogs instance.
56       */
57      public SumOfLogs() {
58         value = 0d;
59         n = 0;
60      }
61  
62      /**
63       * Copy constructor, creates a new {@code SumOfLogs} identical
64       * to the {@code original}.
65       *
66       * @param original the {@code SumOfLogs} instance to copy
67       * @throws NullArgumentException if original is null
68       */
69      public SumOfLogs(SumOfLogs original) throws NullArgumentException {
70          copy(original, this);
71      }
72  
73      /**
74       * {@inheritDoc}
75       */
76      @Override
77      public void increment(final double d) {
78          value += JdkMath.log(d);
79          n++;
80      }
81  
82      /**
83       * {@inheritDoc}
84       */
85      @Override
86      public double getResult() {
87          return value;
88      }
89  
90      /**
91       * {@inheritDoc}
92       */
93      @Override
94      public long getN() {
95          return n;
96      }
97  
98      /**
99       * {@inheritDoc}
100      */
101     @Override
102     public void clear() {
103         value = 0d;
104         n = 0;
105     }
106 
107     /**
108      * Returns the sum of the natural logs of the entries in the specified portion of
109      * the input array, or <code>Double.NaN</code> if the designated subarray
110      * is empty.
111      * <p>
112      * Throws <code>MathIllegalArgumentException</code> if the array is null.</p>
113      * <p>
114      * See {@link SumOfLogs}.</p>
115      *
116      * @param values the input array
117      * @param begin index of the first array element to include
118      * @param length the number of elements to include
119      * @return the sum of the natural logs of the values or 0 if
120      * length = 0
121      * @throws MathIllegalArgumentException if the array is null or the array index
122      *  parameters are not valid
123      */
124     @Override
125     public double evaluate(final double[] values, final int begin, final int length)
126         throws MathIllegalArgumentException {
127 
128         double sumLog = Double.NaN;
129         if (MathArrays.verifyValues(values, begin, length, true)) {
130             sumLog = 0.0;
131             for (int i = begin; i < begin + length; i++) {
132                 sumLog += JdkMath.log(values[i]);
133             }
134         }
135         return sumLog;
136     }
137 
138     /**
139      * {@inheritDoc}
140      */
141     @Override
142     public SumOfLogs copy() {
143         SumOfLogs result = new SumOfLogs();
144         // No try-catch or advertised exception here because args are valid
145         copy(this, result);
146         return result;
147     }
148 
149     /**
150      * Copies source to dest.
151      * <p>Neither source nor dest can be null.</p>
152      *
153      * @param source SumOfLogs to copy
154      * @param dest SumOfLogs to copy to
155      * @throws NullArgumentException if either source or dest is null
156      */
157     public static void copy(SumOfLogs source, SumOfLogs dest)
158         throws NullArgumentException {
159         NullArgumentException.check(source);
160         NullArgumentException.check(dest);
161         dest.n = source.n;
162         dest.value = source.value;
163     }
164 }