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