001: /*
002: * Copyright 2003-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.math.stat.descriptive.moment;
017:
018: import org.apache.commons.math.stat.descriptive.AbstractStorelessUnivariateStatistic;
019: import org.apache.commons.math.stat.descriptive.summary.SumOfLogs;
020:
021: /**
022: * Returns the <a href="http://www.xycoon.com/geometric_mean.htm">
023: * geometric mean </a> of the available values.
024: * <p>
025: * Uses a {@link SumOfLogs} instance to compute sum of logs and returns
026: * <code> exp( 1/n (sum of logs) ).</code> Therefore,
027: * <ul>
028: * <li>If any of values are < 0, the result is <code>NaN.</code></li>
029: * <li>If all values are non-negative and less than
030: * <code>Double.POSITIVE_INFINITY</code>, but at least one value is 0, the
031: * result is <code>0.</code></li>
032: * <li>If both <code>Double.POSITIVE_INFINITY</code> and
033: * <code>Double.NEGATIVE_INFINITY</code> are among the values, the result is
034: * <code>NaN.</code></li>
035: * </ul>
036: * <p>
037: * <strong>Note that this implementation is not synchronized.</strong> If
038: * multiple threads access an instance of this class concurrently, and at least
039: * one of the threads invokes the <code>increment()</code> or
040: * <code>clear()</code> method, it must be synchronized externally.
041: *
042: *
043: * @version $Revision: 348519 $ $Date: 2005-11-23 12:12:18 -0700 (Wed, 23 Nov 2005) $
044: */
045: public class GeometricMean extends AbstractStorelessUnivariateStatistic {
046:
047: /** Serializable version identifier */
048: private static final long serialVersionUID = -8178734905303459453L;
049:
050: /** Wrapped SumOfLogs instance */
051: private SumOfLogs sumOfLogs;
052:
053: /**
054: * Create a GeometricMean instance
055: */
056: public GeometricMean() {
057: sumOfLogs = new SumOfLogs();
058: }
059:
060: /**
061: * @see org.apache.commons.math.stat.descriptive.StorelessUnivariateStatistic#increment(double)
062: */
063: public void increment(final double d) {
064: sumOfLogs.increment(d);
065: }
066:
067: /**
068: * @see org.apache.commons.math.stat.descriptive.StorelessUnivariateStatistic#getResult()
069: */
070: public double getResult() {
071: if (sumOfLogs.getN() > 0) {
072: return Math.exp(sumOfLogs.getResult()
073: / (double) sumOfLogs.getN());
074: } else {
075: return Double.NaN;
076: }
077: }
078:
079: /**
080: * @see org.apache.commons.math.stat.descriptive.StorelessUnivariateStatistic#clear()
081: */
082: public void clear() {
083: sumOfLogs.clear();
084: }
085:
086: /**
087: * Returns the geometric mean of the entries in the specified portion
088: * of the input array.
089: * <p>
090: * See {@link GeometricMean} for details on the computing algorithm.
091: * <p>
092: * Throws <code>IllegalArgumentException</code> if the array is null.
093: *
094: * @param values input array containing the values
095: * @param begin first array element to include
096: * @param length the number of elements to include
097: * @return the geometric mean or Double.NaN if length = 0 or
098: * any of the values are <= 0.
099: * @throws IllegalArgumentException if the input array is null or the array
100: * index parameters are not valid
101: */
102: public double evaluate(final double[] values, final int begin,
103: final int length) {
104: return Math.exp(sumOfLogs.evaluate(values, begin, length)
105: / (double) length);
106: }
107:
108: /**
109: * @see org.apache.commons.math.stat.descriptive.StorelessUnivariateStatistic#getN()
110: */
111: public long getN() {
112: return sumOfLogs.getN();
113: }
114:
115: }
|