freAsymmetricVariateGenerator.cxx

Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Program:   F.R.E.E. - flexible registration evaluation engine
00004   Version:   v.1.0.0
00005   Date:      $Date: 2006/09/01 12:00:00 $
00006   Module:    $RCSfile: freAsymmetricVariateGenerator.cxx,v $
00007 
00008 
00009   Copyright (c) 2007 Ralf o Floca (Department of Medical Informatics,
00010   Institute for Medical Biometry and Informatics, University of Heidelberg,
00011   Germany). All rights reserved.
00012   See FREECopyright.txt or http://www.mi.med.uni-hd.de/free/copyright.htm
00013   for details.
00014 
00015      This software is distributed WITHOUT ANY WARRANTY; without even 
00016      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
00017      PURPOSE.  See the above copyright notices for more information.
00018 
00019 =========================================================================*/
00020 #include "freAsymmetricVariateGenerator.h"
00021 #include "vnl/vnl_sample.h"
00022 #include "vnl/vnl_math.h"
00023 
00024 namespace itk {
00025   namespace Statistics {
00026 
00027     void
00028       AsymmetricVariateGenerator::
00029       PrintSelf(std::ostream& os, Indent indent) const
00030     {
00031       Superclass::PrintSelf(os, indent) ;
00032 
00033       // Print state vector contents
00034       os << indent << "Variance: " << m_Variance << std::endl;
00035       os << indent << "Skewness: " << m_Skewness << std::endl;
00036       os << indent << "Gamma: " << m_Gamma << std::endl;
00037     }
00038 
00039       AsymmetricVariateGenerator::
00040       AsymmetricVariateGenerator()
00041     {
00042       Initialize();
00043     };
00044 
00045     void
00046       AsymmetricVariateGenerator::
00047       Initialize( const int randomSeed )
00048     {
00049       vnl_sample_reseed(randomSeed);
00050     };
00051 
00052     void
00053       AsymmetricVariateGenerator::
00054       Initialize()
00055     {
00056       vnl_sample_reseed();
00057     };  
00058 
00059     double
00060       AsymmetricVariateGenerator::
00061       GetVariate()
00062     {
00063       /*implementation of the function asym (see Reference)*/
00064 
00065       double g = vnl_sample_uniform(0,1.0);
00066       double t = pow(1+m_Skewness , m_Gamma/2);
00067       double gTreshold = 1/(1+t);
00068 
00069       double result = 0.0;
00070 
00071       if (g<gTreshold)
00072       {
00073         result = sqrt(2*pow(m_Variance,m_Gamma)) * Erf((t*g)+g-1);
00074       }
00075       else
00076       {
00077         double h = pow(1+m_Skewness,-1*(m_Gamma/2));
00078         result = sqrt(2*pow((1+m_Skewness)*m_Variance , m_Gamma)) * Erf((h*g)-h+g);
00079       };
00080       return result;
00081     };
00082 
00083     double
00084       AsymmetricVariateGenerator::
00085       operator()()
00086     {
00087       return this->GetVariate();
00088     }; 
00089 
00090     double
00091       AsymmetricVariateGenerator::
00092       Erf(double x)
00093     {
00094       double result = (1/sqrt(2.0)) * INorm((x+1)/2);
00095       return result;
00096     };
00097 
00098     double
00099       AsymmetricVariateGenerator::
00100       Freq(double x)
00101     {
00102       double v = abs(x);
00103       if (v<0.5)
00104       {
00105         double h = (3.6767877*v - 0.097970465*pow(v,3))/(3.2584593 + pow(v,2));
00106         if (x>0) return 0.5*h + 0.5;
00107         else return 0.5 - 0.5*h;
00108       }
00109       else if (v<4.0)
00110       {
00111         //precalculate, because it is used twice
00112         double v_2 = v*v; 
00113         double v_3 = v_2*v;
00114         double v_4 = v_3*v;
00115 
00116         double ap = 7.37389 + 6.86502*v + 3.0318*v_2 + 0.56317*v_3 + 0.0000431878*v_4;
00117         double aq = 7.37396 + 15.1849*v + 12.7955*v_2 + 5.35422*v_3 + v_4;
00118         double h = 1 - exp(-1*v*v) * (ap/aq);
00119         if (x>0) return 0.5*h + 0.5;
00120         else return 0.5 - 0.5*h;
00121       }
00122       else
00123       {
00124         double h = 1 - exp(-1*v*v) * ((-0.96821 + 0.439821*pow(v,2) + 0.248761*pow(v,4)) / (pow(v,3) + 0.440917*pow(v,5)));
00125         if (x>0) return 0.5*h + 0.5;
00126         else return 0.5 - 0.5*h;
00127       }
00128     };
00129 
00130     double
00131       AsymmetricVariateGenerator::
00132       INorm(double z)
00133     {
00134       if ((z<=0) || (z>=1)) itkExceptionMacro(<<"Invalid input value z. Value must be in interval (0, 1). z = "<<z);
00135 
00136       if (z==0.5) return 0;
00137 
00138       double x = z;
00139 
00140       if (z>0.5) x = 1-z;
00141 
00142       x = sqrt(-2*log(x));
00143       //seems to be a typo in the original reference, there the term "450.636*x²" is used.
00144       //As far as I know the original algorithm by Hill and Davis uses 450.636*x.
00145       x = x - ((1271.06 + 450.636*x + 7.45551*pow(x,2)) / (500.756 + 750.365*x + 110.421*pow(x,2) + pow(x,3)));
00146 
00147       if (z<0,5) x = -1 * x;
00148 
00149       return x + 2.50662827*(z-Freq(x))*exp(0.5*x*x);
00150     }
00151     ;
00152   }
00153 
00154 }

Generated at Sat Oct 13 15:18:18 2007 for f.r.e.e. - Flexible Registration and Evaluation Engine by doxygen 1.5.3 written by Dimitri van Heesch, © 1997-2000