/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitModels                                                     *
 * @(#)root/roofit:$Id$
 * Authors:                                                                  *
 *   Kyle Cranmer
 *                                                                           *
 *****************************************************************************/

//////////////////////////////////////////////////////////////////////////////
//
// BEGIN_HTML
// The PDF of the Chi Square distribution for n degrees of freedom.  
// Oddly, this is hard to find in ROOT (except via relation to GammaDist).
// Here we also implement the analytic integral.
// END_HTML
//

#include "RooFit.h"

#include "Riostream.h"
#include "Riostream.h"
#include <math.h>
#include "TMath.h"
#include "RooChiSquarePdf.h"
#include "RooAbsReal.h"
#include "RooRealVar.h"

#include "TError.h"

using namespace std;

ClassImp(RooChiSquarePdf)
;


//_____________________________________________________________________________
RooChiSquarePdf::RooChiSquarePdf()
{
}


//_____________________________________________________________________________
RooChiSquarePdf::RooChiSquarePdf(const char* name, const char* title, 
                           RooAbsReal& x, RooAbsReal& ndof): 
  RooAbsPdf(name, title),
  _x("x", "Dependent", this, x),
  _ndof("ndof","ndof", this, ndof)
{
}



//_____________________________________________________________________________
RooChiSquarePdf::RooChiSquarePdf(const RooChiSquarePdf& other, const char* name) :
  RooAbsPdf(other, name), 
  _x("x", this, other._x), 
  _ndof("ndof",this,other._ndof)
{
}


//_____________________________________________________________________________
Double_t RooChiSquarePdf::evaluate() const 
{

  if(_x <= 0) return 0;

  return  pow(_x,(_ndof/2.)-1.) * exp(-_x/2.) / TMath::Gamma(_ndof/2.) / pow(2.,_ndof/2.);


}


//_____________________________________________________________________________
Int_t RooChiSquarePdf::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName) const 
{
  // No analytical calculation available (yet) of integrals over subranges
  if (rangeName && strlen(rangeName)) {
    return 0 ;
  }


  if (matchArgs(allVars, analVars, _x)) return 1;
  return 0;
}


//_____________________________________________________________________________
Double_t RooChiSquarePdf::analyticalIntegral(Int_t code, const char* rangeName) const 
{
  R__ASSERT(code==1) ;
  Double_t xmin = _x.min(rangeName); Double_t xmax = _x.max(rangeName);

  // TMath::Prob needs ndof to be an integer, or it returns 0.
  //  return TMath::Prob(xmin, _ndof) - TMath::Prob(xmax,_ndof);

  // cumulative is known based on lower incomplete gamma function, or regularized gamma function
  // Wikipedia defines lower incomplete gamma function without the normalization 1/Gamma(ndof), 
  // but it is included in the ROOT implementation.  
  Double_t pmin = TMath::Gamma(_ndof/2,xmin/2);
  Double_t pmax = TMath::Gamma(_ndof/2,xmax/2);

  // only use this if range is appropriate
  return pmax-pmin;
}

 RooChiSquarePdf.cxx:1
 RooChiSquarePdf.cxx:2
 RooChiSquarePdf.cxx:3
 RooChiSquarePdf.cxx:4
 RooChiSquarePdf.cxx:5
 RooChiSquarePdf.cxx:6
 RooChiSquarePdf.cxx:7
 RooChiSquarePdf.cxx:8
 RooChiSquarePdf.cxx:9
 RooChiSquarePdf.cxx:10
 RooChiSquarePdf.cxx:11
 RooChiSquarePdf.cxx:12
 RooChiSquarePdf.cxx:13
 RooChiSquarePdf.cxx:14
 RooChiSquarePdf.cxx:15
 RooChiSquarePdf.cxx:16
 RooChiSquarePdf.cxx:17
 RooChiSquarePdf.cxx:18
 RooChiSquarePdf.cxx:19
 RooChiSquarePdf.cxx:20
 RooChiSquarePdf.cxx:21
 RooChiSquarePdf.cxx:22
 RooChiSquarePdf.cxx:23
 RooChiSquarePdf.cxx:24
 RooChiSquarePdf.cxx:25
 RooChiSquarePdf.cxx:26
 RooChiSquarePdf.cxx:27
 RooChiSquarePdf.cxx:28
 RooChiSquarePdf.cxx:29
 RooChiSquarePdf.cxx:30
 RooChiSquarePdf.cxx:31
 RooChiSquarePdf.cxx:32
 RooChiSquarePdf.cxx:33
 RooChiSquarePdf.cxx:34
 RooChiSquarePdf.cxx:35
 RooChiSquarePdf.cxx:36
 RooChiSquarePdf.cxx:37
 RooChiSquarePdf.cxx:38
 RooChiSquarePdf.cxx:39
 RooChiSquarePdf.cxx:40
 RooChiSquarePdf.cxx:41
 RooChiSquarePdf.cxx:42
 RooChiSquarePdf.cxx:43
 RooChiSquarePdf.cxx:44
 RooChiSquarePdf.cxx:45
 RooChiSquarePdf.cxx:46
 RooChiSquarePdf.cxx:47
 RooChiSquarePdf.cxx:48
 RooChiSquarePdf.cxx:49
 RooChiSquarePdf.cxx:50
 RooChiSquarePdf.cxx:51
 RooChiSquarePdf.cxx:52
 RooChiSquarePdf.cxx:53
 RooChiSquarePdf.cxx:54
 RooChiSquarePdf.cxx:55
 RooChiSquarePdf.cxx:56
 RooChiSquarePdf.cxx:57
 RooChiSquarePdf.cxx:58
 RooChiSquarePdf.cxx:59
 RooChiSquarePdf.cxx:60
 RooChiSquarePdf.cxx:61
 RooChiSquarePdf.cxx:62
 RooChiSquarePdf.cxx:63
 RooChiSquarePdf.cxx:64
 RooChiSquarePdf.cxx:65
 RooChiSquarePdf.cxx:66
 RooChiSquarePdf.cxx:67
 RooChiSquarePdf.cxx:68
 RooChiSquarePdf.cxx:69
 RooChiSquarePdf.cxx:70
 RooChiSquarePdf.cxx:71
 RooChiSquarePdf.cxx:72
 RooChiSquarePdf.cxx:73
 RooChiSquarePdf.cxx:74
 RooChiSquarePdf.cxx:75
 RooChiSquarePdf.cxx:76
 RooChiSquarePdf.cxx:77
 RooChiSquarePdf.cxx:78
 RooChiSquarePdf.cxx:79
 RooChiSquarePdf.cxx:80
 RooChiSquarePdf.cxx:81
 RooChiSquarePdf.cxx:82
 RooChiSquarePdf.cxx:83
 RooChiSquarePdf.cxx:84
 RooChiSquarePdf.cxx:85
 RooChiSquarePdf.cxx:86
 RooChiSquarePdf.cxx:87
 RooChiSquarePdf.cxx:88
 RooChiSquarePdf.cxx:89
 RooChiSquarePdf.cxx:90
 RooChiSquarePdf.cxx:91
 RooChiSquarePdf.cxx:92
 RooChiSquarePdf.cxx:93
 RooChiSquarePdf.cxx:94
 RooChiSquarePdf.cxx:95
 RooChiSquarePdf.cxx:96
 RooChiSquarePdf.cxx:97
 RooChiSquarePdf.cxx:98
 RooChiSquarePdf.cxx:99
 RooChiSquarePdf.cxx:100
 RooChiSquarePdf.cxx:101
 RooChiSquarePdf.cxx:102
 RooChiSquarePdf.cxx:103
 RooChiSquarePdf.cxx:104
 RooChiSquarePdf.cxx:105
 RooChiSquarePdf.cxx:106
 RooChiSquarePdf.cxx:107