1 /* 2 * Copyright 2003-2004 The Apache Software Foundation. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package org.apache.commons.math.stat.descriptive.moment; 17 18 import org.apache.commons.math.stat.descriptive.AbstractStorelessUnivariateStatistic; 19 import org.apache.commons.math.stat.descriptive.summary.SumOfLogs; 20 21 /** 22 * Returns the <a href="http://www.xycoon.com/geometric_mean.htm"> 23 * geometric mean </a> of the available values. 24 * <p> 25 * Uses a {@link SumOfLogs} instance to compute sum of logs and returns 26 * <code> exp( 1/n (sum of logs) ).</code> Therefore, 27 * <ul> 28 * <li>If any of values are < 0, the result is <code>NaN.</code></li> 29 * <li>If all values are non-negative and less than 30 * <code>Double.POSITIVE_INFINITY</code>, but at least one value is 0, the 31 * result is <code>0.</code></li> 32 * <li>If both <code>Double.POSITIVE_INFINITY</code> and 33 * <code>Double.NEGATIVE_INFINITY</code> are among the values, the result is 34 * <code>NaN.</code></li> 35 * </ul> 36 * <p> 37 * <strong>Note that this implementation is not synchronized.</strong> If 38 * multiple threads access an instance of this class concurrently, and at least 39 * one of the threads invokes the <code>increment()</code> or 40 * <code>clear()</code> method, it must be synchronized externally. 41 * 42 * 43 * @version $Revision: 348519 $ $Date: 2005-11-23 12:12:18 -0700 (Wed, 23 Nov 2005) $ 44 */ 45 public class GeometricMean extends AbstractStorelessUnivariateStatistic { 46 47 /** Serializable version identifier */ 48 private static final long serialVersionUID = -8178734905303459453L; 49 50 /** Wrapped SumOfLogs instance */ 51 private SumOfLogs sumOfLogs; 52 53 /** 54 * Create a GeometricMean instance 55 */ 56 public GeometricMean() { 57 sumOfLogs = new SumOfLogs(); 58 } 59 60 /** 61 * @see org.apache.commons.math.stat.descriptive.StorelessUnivariateStatistic#increment(double) 62 */ 63 public void increment(final double d) { 64 sumOfLogs.increment(d); 65 } 66 67 /** 68 * @see org.apache.commons.math.stat.descriptive.StorelessUnivariateStatistic#getResult() 69 */ 70 public double getResult() { 71 if (sumOfLogs.getN() > 0) { 72 return Math.exp(sumOfLogs.getResult() / (double) sumOfLogs.getN()); 73 } else { 74 return Double.NaN; 75 } 76 } 77 78 /** 79 * @see org.apache.commons.math.stat.descriptive.StorelessUnivariateStatistic#clear() 80 */ 81 public void clear() { 82 sumOfLogs.clear(); 83 } 84 85 /** 86 * Returns the geometric mean of the entries in the specified portion 87 * of the input array. 88 * <p> 89 * See {@link GeometricMean} for details on the computing algorithm. 90 * <p> 91 * Throws <code>IllegalArgumentException</code> if the array is null. 92 * 93 * @param values input array containing the values 94 * @param begin first array element to include 95 * @param length the number of elements to include 96 * @return the geometric mean or Double.NaN if length = 0 or 97 * any of the values are <= 0. 98 * @throws IllegalArgumentException if the input array is null or the array 99 * index parameters are not valid 100 */ 101 public double evaluate( 102 final double[] values, final int begin, final int length) { 103 return Math.exp( 104 sumOfLogs.evaluate(values, begin, length) / (double) length); 105 } 106 107 /** 108 * @see org.apache.commons.math.stat.descriptive.StorelessUnivariateStatistic#getN() 109 */ 110 public long getN() { 111 return sumOfLogs.getN(); 112 } 113 114 }