1 /* 2 * Copyright 2005 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 17 package org.apache.commons.math.distribution; 18 19 import java.io.Serializable; 20 21 /** 22 * Default implementation of 23 * {@link org.apache.commons.math.distribution.CauchyDistribution}. 24 * 25 * @since 1.1 26 * @version $Revision: 348519 $ $Date: 2005-11-23 12:12:18 -0700 (Wed, 23 Nov 2005) $ 27 */ 28 public class CauchyDistributionImpl extends AbstractContinuousDistribution 29 implements CauchyDistribution, Serializable { 30 31 /** Serializable version identifier */ 32 private static final long serialVersionUID = 8589540077390120676L; 33 34 /** The median of this distribution. */ 35 private double median = 0; 36 37 /** The scale of this distribution. */ 38 private double scale = 1; 39 40 /** 41 * Creates cauchy distribution with the medain equal to zero and scale 42 * equal to one. 43 */ 44 public CauchyDistributionImpl(){ 45 this(0.0, 1.0); 46 } 47 48 /** 49 * Create a cauchy distribution using the given median and scale. 50 * @param median median for this distribution 51 * @param s scale parameter for this distribution 52 */ 53 public CauchyDistributionImpl(double median, double s){ 54 super(); 55 setMedian(median); 56 setScale(s); 57 } 58 59 /** 60 * For this disbution, X, this method returns P(X < <code>x</code>). 61 * @param x the value at which the CDF is evaluated. 62 * @return CDF evaluted at <code>x</code>. 63 */ 64 public double cumulativeProbability(double x) { 65 return 0.5 + (Math.atan((x - median) / scale) / Math.PI); 66 } 67 68 /** 69 * Access the median. 70 * @return median for this distribution 71 */ 72 public double getMedian() { 73 return median; 74 } 75 76 /** 77 * Access the scale parameter. 78 * @return scale parameter for this distribution 79 */ 80 public double getScale() { 81 return scale; 82 } 83 84 /** 85 * For this distribution, X, this method returns the critical point x, such 86 * that P(X < x) = <code>p</code>. 87 * <p> 88 * Returns <code>Double.NEGATIVE_INFINITY</code> for p=0 and 89 * <code>Double.POSITIVE_INFINITY</code> for p=1. 90 * 91 * @param p the desired probability 92 * @return x, such that P(X < x) = <code>p</code> 93 * @throws IllegalArgumentException if <code>p</code> is not a valid 94 * probability. 95 */ 96 public double inverseCumulativeProbability(double p) { 97 double ret; 98 if (p < 0.0 || p > 1.0) { 99 throw new IllegalArgumentException 100 ("probability argument must be between 0 and 1 (inclusive)"); 101 } else if (p == 0) { 102 ret = Double.NEGATIVE_INFINITY; 103 } else if (p == 1) { 104 ret = Double.POSITIVE_INFINITY; 105 } else { 106 ret = median + scale * Math.tan(Math.PI * (p - .5)); 107 } 108 return ret; 109 } 110 111 /** 112 * Modify the median. 113 * @param median for this distribution 114 */ 115 public void setMedian(double median) { 116 this.median = median; 117 } 118 119 /** 120 * Modify the scale parameter. 121 * @param s scale parameter for this distribution 122 * @throws IllegalArgumentException if <code>sd</code> is not positive. 123 */ 124 public void setScale(double s) { 125 if (s <= 0.0) { 126 throw new IllegalArgumentException( 127 "Scale must be positive."); 128 } 129 scale = s; 130 } 131 132 /** 133 * Access the domain value lower bound, based on <code>p</code>, used to 134 * bracket a CDF root. This method is used by 135 * {@link #inverseCumulativeProbability(double)} to find critical values. 136 * 137 * @param p the desired probability for the critical value 138 * @return domain value lower bound, i.e. 139 * P(X < <i>lower bound</i>) < <code>p</code> 140 */ 141 protected double getDomainLowerBound(double p) { 142 double ret; 143 144 if (p < .5) { 145 ret = -Double.MAX_VALUE; 146 } else { 147 ret = getMedian(); 148 } 149 150 return ret; 151 } 152 153 /** 154 * Access the domain value upper bound, based on <code>p</code>, used to 155 * bracket a CDF root. This method is used by 156 * {@link #inverseCumulativeProbability(double)} to find critical values. 157 * 158 * @param p the desired probability for the critical value 159 * @return domain value upper bound, i.e. 160 * P(X < <i>upper bound</i>) > <code>p</code> 161 */ 162 protected double getDomainUpperBound(double p) { 163 double ret; 164 165 if (p < .5) { 166 ret = getMedian(); 167 } else { 168 ret = Double.MAX_VALUE; 169 } 170 171 return ret; 172 } 173 174 /** 175 * Access the initial domain value, based on <code>p</code>, used to 176 * bracket a CDF root. This method is used by 177 * {@link #inverseCumulativeProbability(double)} to find critical values. 178 * 179 * @param p the desired probability for the critical value 180 * @return initial domain value 181 */ 182 protected double getInitialDomain(double p) { 183 double ret; 184 185 if (p < .5) { 186 ret = getMedian() - getScale(); 187 } else if (p > .5) { 188 ret = getMedian() + getScale(); 189 } else { 190 ret = getMedian(); 191 } 192 193 return ret; 194 } 195 }