STK++ 1.0
STK_Law_Cauchy.cpp
Go to the documentation of this file.
00001 /*--------------------------------------------------------------------*/
00002 /*     Copyright (C) 2004-2008  Serge Iovleff
00003 
00004     This program is free software; you can redistribute it and/or modify
00005     it under the terms of the GNU Lesser General Public License as
00006     published by the Free Software Foundation; either version 2 of the
00007     License, or (at your option) any later version.
00008 
00009     This program is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012     GNU Lesser General Public License for more details.
00013 
00014     You should have received a copy of the GNU Lesser General Public
00015     License along with this program; if not, write to the
00016     Free Software Foundation, Inc.,
00017     59 Temple Place,
00018     Suite 330,
00019     Boston, MA 02111-1307
00020     USA
00021 
00022     Contact : Serge.Iovleff@stkpp.org
00023 */
00024 
00025 /*
00026  * Project: STatistiK
00027  * Purpose: Implementation of the Cauchy Distribution
00028  * Author:  Serge Iovleff, serge.iovleff@stkpp.org
00029  **/
00030 
00035 #include "../include/STK_Law_Cauchy.h"
00036 
00037 namespace STK
00038 {
00039 
00040 namespace Law
00041 {
00042 
00043 /* constructor */
00044 Cauchy::Cauchy( Real const& location, Real const& scale)
00045               : ITUnivariate<Real>(String(_T("Cauchy")))
00046               , location_(location)
00047               , scale_(scale)
00048 {
00049   // check parameters
00050   if (  !Arithmetic<Real>::isFinite(location)
00051      || !Arithmetic<Real>::isFinite(scale)
00052      || scale <= 0
00053      )
00054     throw domain_error("Cauchy::Cauchy(location, scale) "
00055                             "argument error");
00056 }
00057 
00058 /* destructor */
00059 Cauchy::~Cauchy()
00060 { ;}
00061 
00062 /*  Generate a pseudo Cauchy random variate. */
00063 Real Cauchy::rand() const
00064 {
00065   return location_ + scale_ * tan((double)(Const::_PI_ * generator.randUnif()));
00066 }
00067 
00068 /*
00069  *  Generate a pseudo Cauchy random variate with the specified parameters.
00070  *  (static)
00071  */
00072 Real Cauchy::rand( Real const& location, Real const& scale)
00073 {
00074   // check parameters
00075   if (  !Arithmetic<Real>::isFinite(location)
00076      || !Arithmetic<Real>::isFinite(scale)
00077      || scale <= 0
00078      )
00079     throw domain_error("Cauchy::Cauchy(location, scale) "
00080                             "argument error");
00081   return location + scale * tan(Const::_PI_ * generator.randUnif());
00082 }
00083 
00084 /*  Give the value of the pdf at x.*/
00085 Real Cauchy::pdf( Real const& x) const
00086 {
00087   // check NA value
00088   if (Arithmetic<Real>::isNA(x)) return Arithmetic<Real>::NA();
00089 
00090   // trivial case
00091   if (Arithmetic<Real>::isInfinite(x)) return 0.0;
00092 
00093   // general case
00094   Real y = (x - location_) / scale_;
00095   return 1. / (Const::_PI_ * scale_ * (1. + y * y));
00096 }
00097 
00098 /* Give the value of the log-pdf at x. */
00099 Real Cauchy::lpdf( Real const& x) const
00100 {
00101   // check NA value
00102   if (Arithmetic<Real>::isNA(x)) return Arithmetic<Real>::NA();
00103 
00104   // trivial case
00105   if (Arithmetic<Real>::isInfinite(x))
00106     return -Arithmetic<Real>::infinity();
00107 
00108   // general case
00109   Real y = (x - location_) / scale_;
00110   return - log(Const::_PI_ * scale_ * (1. + y * y));
00111 }
00112 
00113 /* The cumulative distribution function at t.
00114  */
00115 Real Cauchy::cdf( Real const& t) const
00116 {
00117   // check NA value
00118   if (Arithmetic<Real>::isNA(t)) return Arithmetic<Real>::NA();
00119 
00120   // check parameter
00121   if (Arithmetic<Real>::isInfinite(t))
00122    return (t < 0.) ? 0.0 : 1.0;
00123 
00124   /* http://www.faqs.org/faqs/fr/maths/maths-faq-3/
00125    * arctan on [0, 1[:
00126    * if x<0 atan(x)= -atan(-x)
00127    * elseif x>1 atan(x)= Pi/2-atan(1/x).
00128    */
00129   if (abs(t) > 1)
00130   {
00131     double y = atan(1/t) / Const::_PI_;
00132     return (t > 0) ? (1 - y) : (-y);
00133   }
00134   else
00135     return 0.5 + atan(t) / Const::_PI_;
00136 }
00137     
00138 /*
00139  * The inverse cumulative distribution function at p.
00140  */
00141 Real Cauchy::icdf( Real const& p) const
00142 {
00143   // check NA value
00144   if (Arithmetic<Real>::isNA(p)) return Arithmetic<Real>::NA();
00145 
00146   // check parameter
00147   if ((p > 1.) || (p < 0.))
00148     throw domain_error("Cauchy::icdf(p) "
00149                             "argument error");
00150  // trivial cases
00151  if (p == 0.)  return -Arithmetic<Real>::infinity();
00152  if (p == 1.)  return  Arithmetic<Real>::infinity();
00153 
00154   // general case
00155   // tan(pi * (p - 1/2)) = -cot(pi * p) = -1/tan(pi * p) 
00156   return location_ - scale_ / tan(Const::_PI_ * p);
00157 }
00158 
00159 } // namespace Law
00160 
00161 } // namespace STK