/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitModels                                                     *
 * @(#)root/roofit:$Id$
 * Authors:                                                                  *
 *   UE, Ulrik Egede,     RAL,               U.Egede@rl.ac.uk                *
 *   MT, Max Turri,       UC Santa Cruz      turri@slac.stanford.edu         *
 *   CC, Chih-hsiang Cheng, Stanford         chcheng@slac.stanford.edu       *
 *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
 *                                                                           *
 * Copyright (c) 2000-2005, Regents of the University of California          *
 *                          RAL and Stanford University. All rights reserved.*
 *                                                                           *
 * Redistribution and use in source and binary forms,                        *
 * with or without modification, are permitted according to the terms        *
 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
 *****************************************************************************/

//////////////////////////////////////////////////////////////////////////////
//
// BEGIN_HTML
// Special p.d.f shape that can be used to model the background of
// D*-D0 mass difference distributions
// END_HTML
//

#include "RooFit.h"

#include "Riostream.h"
#include "Riostream.h"
#include <math.h>
#include "TMath.h"

#include "RooDstD0BG.h"
#include "RooAbsReal.h"
#include "RooRealVar.h"
#include "RooIntegrator1D.h"
#include "RooAbsFunc.h"

using namespace std;

ClassImp(RooDstD0BG) 


//_____________________________________________________________________________
RooDstD0BG::RooDstD0BG(const char *name, const char *title,
		       RooAbsReal& _dm, RooAbsReal& _dm0,
		       RooAbsReal& _c, RooAbsReal& _a, RooAbsReal& _b) :
  RooAbsPdf(name,title),
  dm("dm","Dstar-D0 Mass Diff",this, _dm),
  dm0("dm0","Threshold",this, _dm0),
  C("C","Shape Parameter",this, _c),
  A("A","Shape Parameter 2",this, _a),
  B("B","Shape Parameter 3",this, _b)
{
}


//_____________________________________________________________________________
RooDstD0BG::RooDstD0BG(const RooDstD0BG& other, const char *name) :
  RooAbsPdf(other,name), dm("dm",this,other.dm), dm0("dm0",this,other.dm0),
  C("C",this,other.C), A("A",this,other.A), B("B",this,other.B)
{
}


//_____________________________________________________________________________
Double_t RooDstD0BG::evaluate() const
{
  Double_t arg= dm- dm0;
  if (arg <= 0 ) return 0;
  Double_t ratio= dm/dm0;
  Double_t val= (1- exp(-arg/C))* TMath::Power(ratio, A) + B*(ratio-1);

  return (val > 0 ? val : 0) ;
}


//_____________________________________________________________________________
Int_t RooDstD0BG::getAnalyticalIntegral(RooArgSet& /*allVars*/, RooArgSet& /*analVars*/, const char* /*rangeName*/) const 
{
  // if (matchArgs(allVars,analVars,dm)) return 1 ;
  return 0 ;
}


//_____________________________________________________________________________
Double_t RooDstD0BG::analyticalIntegral(Int_t code, const char* rangeName) const 
{
  switch(code) {
  case 1: 
    {
      Double_t min= dm.min(rangeName);
      Double_t max= dm.max(rangeName);
      if (max <= dm0 ) return 0;
      else if (min < dm0) min = dm0;

      Bool_t doNumerical= kFALSE;
      if ( A != 0 ) doNumerical= kTRUE;
      else if (B < 0) {
	// If b<0, pdf can be negative at large dm, the integral should
	// only up to where pdf hits zero. Better solution should be
	// solve the zero and use it as max. 
	// Here we check this whether pdf(max) < 0. If true, let numerical
	// integral take care of. ( kind of ugly!)
	if ( 1- exp(-(max-dm0)/C) + B*(max/dm0 -1) < 0) doNumerical= kTRUE;
      }
      if ( ! doNumerical ) {
	return (max-min)+ C* exp(dm0/C)* (exp(-max/C)- exp(-min/C)) +
	  B * (0.5* (max*max - min*min)/dm0 - (max- min));
      } else {
	// In principle the integral for a!=0  can be done analytically. 
	// It involves incomplete Gamma function, TMath::Gamma(a+1,m/c), 
	// which is not defined for a < -1. And the whole expression is 
	// not stable for m/c >> 1.
	// Do numerical integral
	RooArgSet vset(dm.arg(),"vset");
	RooAbsFunc *func= bindVars(vset);
	RooIntegrator1D integrator(*func,min,max);
	return integrator.integral();
      }
    }
  }
  
  assert(0) ;
  return 0 ;
}
 RooDstD0BG.cxx:1
 RooDstD0BG.cxx:2
 RooDstD0BG.cxx:3
 RooDstD0BG.cxx:4
 RooDstD0BG.cxx:5
 RooDstD0BG.cxx:6
 RooDstD0BG.cxx:7
 RooDstD0BG.cxx:8
 RooDstD0BG.cxx:9
 RooDstD0BG.cxx:10
 RooDstD0BG.cxx:11
 RooDstD0BG.cxx:12
 RooDstD0BG.cxx:13
 RooDstD0BG.cxx:14
 RooDstD0BG.cxx:15
 RooDstD0BG.cxx:16
 RooDstD0BG.cxx:17
 RooDstD0BG.cxx:18
 RooDstD0BG.cxx:19
 RooDstD0BG.cxx:20
 RooDstD0BG.cxx:21
 RooDstD0BG.cxx:22
 RooDstD0BG.cxx:23
 RooDstD0BG.cxx:24
 RooDstD0BG.cxx:25
 RooDstD0BG.cxx:26
 RooDstD0BG.cxx:27
 RooDstD0BG.cxx:28
 RooDstD0BG.cxx:29
 RooDstD0BG.cxx:30
 RooDstD0BG.cxx:31
 RooDstD0BG.cxx:32
 RooDstD0BG.cxx:33
 RooDstD0BG.cxx:34
 RooDstD0BG.cxx:35
 RooDstD0BG.cxx:36
 RooDstD0BG.cxx:37
 RooDstD0BG.cxx:38
 RooDstD0BG.cxx:39
 RooDstD0BG.cxx:40
 RooDstD0BG.cxx:41
 RooDstD0BG.cxx:42
 RooDstD0BG.cxx:43
 RooDstD0BG.cxx:44
 RooDstD0BG.cxx:45
 RooDstD0BG.cxx:46
 RooDstD0BG.cxx:47
 RooDstD0BG.cxx:48
 RooDstD0BG.cxx:49
 RooDstD0BG.cxx:50
 RooDstD0BG.cxx:51
 RooDstD0BG.cxx:52
 RooDstD0BG.cxx:53
 RooDstD0BG.cxx:54
 RooDstD0BG.cxx:55
 RooDstD0BG.cxx:56
 RooDstD0BG.cxx:57
 RooDstD0BG.cxx:58
 RooDstD0BG.cxx:59
 RooDstD0BG.cxx:60
 RooDstD0BG.cxx:61
 RooDstD0BG.cxx:62
 RooDstD0BG.cxx:63
 RooDstD0BG.cxx:64
 RooDstD0BG.cxx:65
 RooDstD0BG.cxx:66
 RooDstD0BG.cxx:67
 RooDstD0BG.cxx:68
 RooDstD0BG.cxx:69
 RooDstD0BG.cxx:70
 RooDstD0BG.cxx:71
 RooDstD0BG.cxx:72
 RooDstD0BG.cxx:73
 RooDstD0BG.cxx:74
 RooDstD0BG.cxx:75
 RooDstD0BG.cxx:76
 RooDstD0BG.cxx:77
 RooDstD0BG.cxx:78
 RooDstD0BG.cxx:79
 RooDstD0BG.cxx:80
 RooDstD0BG.cxx:81
 RooDstD0BG.cxx:82
 RooDstD0BG.cxx:83
 RooDstD0BG.cxx:84
 RooDstD0BG.cxx:85
 RooDstD0BG.cxx:86
 RooDstD0BG.cxx:87
 RooDstD0BG.cxx:88
 RooDstD0BG.cxx:89
 RooDstD0BG.cxx:90
 RooDstD0BG.cxx:91
 RooDstD0BG.cxx:92
 RooDstD0BG.cxx:93
 RooDstD0BG.cxx:94
 RooDstD0BG.cxx:95
 RooDstD0BG.cxx:96
 RooDstD0BG.cxx:97
 RooDstD0BG.cxx:98
 RooDstD0BG.cxx:99
 RooDstD0BG.cxx:100
 RooDstD0BG.cxx:101
 RooDstD0BG.cxx:102
 RooDstD0BG.cxx:103
 RooDstD0BG.cxx:104
 RooDstD0BG.cxx:105
 RooDstD0BG.cxx:106
 RooDstD0BG.cxx:107
 RooDstD0BG.cxx:108
 RooDstD0BG.cxx:109
 RooDstD0BG.cxx:110
 RooDstD0BG.cxx:111
 RooDstD0BG.cxx:112
 RooDstD0BG.cxx:113
 RooDstD0BG.cxx:114
 RooDstD0BG.cxx:115
 RooDstD0BG.cxx:116
 RooDstD0BG.cxx:117
 RooDstD0BG.cxx:118
 RooDstD0BG.cxx:119
 RooDstD0BG.cxx:120
 RooDstD0BG.cxx:121
 RooDstD0BG.cxx:122
 RooDstD0BG.cxx:123
 RooDstD0BG.cxx:124
 RooDstD0BG.cxx:125
 RooDstD0BG.cxx:126
 RooDstD0BG.cxx:127