/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitModels                                                     *
 * @(#)root/roofit:$Id$
 * Authors:                                                                  *
 *   TS, Thomas Schietinger, SLAC,           schieti@slac.stanford.edu       *
 *                                                                           *
 * Copyright (c) 2000-2005, Regents of the University of California          *
 *                          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
// RooVoigtian is an efficient implementation of the convolution of a 
// Breit-Wigner with a Gaussian, making use of the complex error function.
// RooFitCore provides two algorithms for the evaluation of the complex error 
// function (the default CERNlib C335 algorithm, and a faster, look-up-table 
// based method). By default, RooVoigtian employs the default (CERNlib) 
// algorithm. Select the faster algorithm either in the constructor, or with
// the selectFastAlgorithm() method.
// END_HTML
//

#include <cmath>
#include <complex>

#include "RooFit.h"

#include "Riostream.h"

#include "RooVoigtian.h"
#include "RooAbsReal.h"
#include "RooRealVar.h"
#include "RooMath.h"

using namespace std;

ClassImp(RooVoigtian)


//_____________________________________________________________________________
RooVoigtian::RooVoigtian(const char *name, const char *title,
			 RooAbsReal& _x, RooAbsReal& _mean,
			 RooAbsReal& _width, RooAbsReal& _sigma,
    			 Bool_t doFast) :
  RooAbsPdf(name,title),
  x("x","Dependent",this,_x),
  mean("mean","Mean",this,_mean),
  width("width","Breit-Wigner Width",this,_width),
  sigma("sigma","Gauss Width",this,_sigma),
  _doFast(doFast)
{
  _invRootPi= 1./sqrt(atan2(0.,-1.));
}



//_____________________________________________________________________________
RooVoigtian::RooVoigtian(const RooVoigtian& other, const char* name) : 
  RooAbsPdf(other,name), x("x",this,other.x), mean("mean",this,other.mean),
  width("width",this,other.width),sigma("sigma",this,other.sigma),
  _doFast(other._doFast)
{
  _invRootPi= 1./sqrt(atan2(0.,-1.));
}



//_____________________________________________________________________________
Double_t RooVoigtian::evaluate() const
{
  Double_t s = (sigma>0) ? sigma : -sigma ;
  Double_t w = (width>0) ? width : -width ;

  Double_t coef= -0.5/(s*s);
  Double_t arg = x - mean;

  // return constant for zero width and sigma
  if (s==0. && w==0.) return 1.;

  // Breit-Wigner for zero sigma
  if (s==0.) return (1./(arg*arg+0.25*w*w));

  // Gauss for zero width
  if (w==0.) return exp(coef*arg*arg);

  // actual Voigtian for non-trivial width and sigma
  Double_t c = 1./(sqrt(2.)*s);
  Double_t a = 0.5*c*w;
  Double_t u = c*arg;
  std::complex<Double_t> z(u,a) ;
  std::complex<Double_t> v(0.) ;

  if (_doFast) {
    v = RooMath::faddeeva_fast(z);
  } else {
    v = RooMath::faddeeva(z);
  }
  return c*_invRootPi*v.real();

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