125                _x(
"x", 
"x", this, 
x),
 
  126                _lambda(
"lambda", 
"Lambda", this, lambda),
 
  127                _zeta(
"zeta", 
"zeta", this, zeta),
 
  128                _beta(
"beta", 
"Asymmetry parameter beta", this, 
beta),
 
  129                _sigma(
"sigma", 
"Width parameter sigma", this, sigm),
 
  130                _mu(
"mu", 
"Location parameter mu", this, mu),
 
  131                _a(
"a", 
"Left tail location a", this, 
a),
 
  132                _n(
"n", 
"Left tail parameter n", this, 
n),
 
  133                _a2(
"a2", 
"Right tail location a2", this, a2),
 
  134                _n2(
"n2", 
"Right tail parameter n2", this, n2)
 
  140        std::string(
"Lambda needs to be negative when ") + 
_zeta.
GetName() + 
" is zero.");
 
  143#ifndef R__HAS_MATHMORE 
  144  throw std::logic_error(
"RooHypatia2 needs ROOT with mathmore enabled to access gsl functions.");
 
  155                   _x(
"x", this, other._x),
 
  156                   _lambda(
"lambda", this, other._lambda),
 
  157                   _zeta(
"zeta", this, other._zeta),
 
  158                   _beta(
"beta", this, other._beta),
 
  159                   _sigma(
"sigma", this, other._sigma),
 
  160                   _mu(
"mu", this, other._mu),
 
  161                   _a(
"a", this, other._a),
 
  162                   _n(
"n", this, other._n),
 
  163                   _a2(
"a2", this, other._a2),
 
  164                   _n2(
"n2", this, other._n2)
 
  166#ifndef R__HAS_MATHMORE 
  167  throw std::logic_error(
"RooHypatia2 needs ROOT with mathmore enabled to access gsl functions.");
 
  176double low_x_BK(
double nu, 
double x){
 
  180double low_x_LnBK(
double nu, 
double x){
 
  184double besselK(
double ni, 
double x) {
 
  186  if ((x < 1.e-06 && nu > 0.) ||
 
  187      (x < 1.e-04 && nu > 0. && nu < 55.) ||
 
  188      (x < 0.1 && nu >= 55.) )
 
  189    return low_x_BK(nu, 
x);
 
  191#ifdef R__HAS_MATHMORE 
  194  return std::numeric_limits<double>::signaling_NaN();
 
  199double LnBesselK(
double ni, 
double x) {
 
  201  if ((x < 1.e-06 && nu > 0.) ||
 
  202      (x < 1.e-04 && nu > 0. && nu < 55.) ||
 
  203      (x < 0.1 && nu >= 55.) )
 
  204    return low_x_LnBK(nu, 
x);
 
  206#ifdef R__HAS_MATHMORE 
  209  return std::numeric_limits<double>::signaling_NaN();
 
  214double LogEval(
double d, 
double l, 
double alpha, 
double beta, 
double delta) {
 
  215  const double gamma = alpha;
 
  216  const double dg = delta*
gamma;
 
  217  const double thing = delta*delta + 
d*
d;
 
  218  const double logno = 
l*
std::log(
gamma/delta) - logsq2pi - LnBesselK(
l, dg);
 
  227double diff_eval(
double d, 
double l, 
double alpha, 
double beta, 
double delta){
 
  228  const double gamma = alpha;
 
  229  const double dg = delta*
gamma;
 
  231  const double thing = delta*delta + 
d*
d;
 
  232  const double sqrthing = 
std::sqrt(thing);
 
  233  const double alphasq = alpha*sqrthing;
 
  235  const double ns1 = 0.5-
l;
 
  238  * ( -
d * alphasq * (besselK(
l - 1.5, alphasq)
 
  239      + besselK(
l + 0.5, alphasq))
 
  240      + (2.*(
beta*thing + 
d*
l) - 
d) * besselK(ns1, alphasq) )
 
  273    const double alpha  = cons0/cons1;
 
  274    const double delta = cons0*cons1;
 
  277      const double k1 = LogEval(-asigma, 
_lambda, alpha, 
beta, delta);
 
  278      const double k2 = diff_eval(-asigma, 
_lambda, alpha, 
beta, delta);
 
  279      const double B = -asigma + 
_n*k1/k2;
 
  284    else if (
d>a2sigma) {
 
  285      const double k1 = LogEval(a2sigma, 
_lambda, alpha, 
beta, delta);
 
  286      const double k2 = diff_eval(a2sigma, 
_lambda, alpha, 
beta, delta);
 
  287      const double B = -a2sigma - 
_n2*k1/k2;
 
  296  else if (
_zeta < 0.) {
 
  300    const double delta = 
_sigma;
 
  304      const double phi = 1. + 
_a * 
_a;
 
  307      const double B = -asigma + 
_n*k1/k2;
 
  312    else if (
d > a2sigma) {
 
  314      const double phi = 1. + 
_a2*
_a2;
 
  317      const double B = -a2sigma - 
_n2*k1/k2;
 
  327    coutE(
Eval) << 
"zeta = 0 only supported for lambda < 0. lambda = " << double(
_lambda) << std::endl;
 
  337template<
typename Tx, 
typename Tl, 
typename Tz, 
typename Tb, 
typename Ts, 
typename Tm, 
typename Ta, 
typename Tn,
 
  338typename Ta2, 
typename Tn2>
 
  339void compute(
RooSpan<double> output, Tx 
x, Tl lambda, Tz zeta, Tb 
beta, Ts 
sigma, Tm mu, Ta 
a, Tn 
n, Ta2 a2, Tn2 n2) {
 
  341  const bool zetaIsAlwaysLargerZero = !zeta.isBatch() && zeta[0] > 0.;
 
  342  const bool zetaIsAlwaysZero = !zeta.isBatch() && zeta[0] == 0.;
 
  344  for (std::size_t i = 0; i < 
N; ++i) {
 
  346    const double d = 
x[i] - mu[i];
 
  348    const double asigma = 
a[i]*
sigma[i];
 
  349    const double a2sigma = a2[i]*
sigma[i];
 
  352    if (zetaIsAlwaysLargerZero || zeta[i] > 0.) {
 
  353      const double phi = besselK(lambda[i]+1., zeta[i]) / besselK(lambda[i], zeta[i]);
 
  355      const double alpha  = cons0/cons1;
 
  356      const double delta = cons0*cons1;
 
  359        const double k1 = LogEval(-asigma, lambda[i], alpha, 
beta[i], delta);
 
  360        const double k2 = diff_eval(-asigma, lambda[i], alpha, 
beta[i], delta);
 
  361        const double B = -asigma + 
n[i]*k1/k2;
 
  366      else if (
d>a2sigma) {
 
  367        const double k1 = LogEval(a2sigma, lambda[i], alpha, 
beta[i], delta);
 
  368        const double k2 = diff_eval(a2sigma, lambda[i], alpha, 
beta[i], delta);
 
  369        const double B = -a2sigma - n2[i]*k1/k2;
 
  370        const double A = k1 * 
std::pow(
B+a2sigma, n2[i]);
 
  375        output[i] = LogEval(
d, lambda[i], alpha, 
beta[i], delta);
 
  379    if ((!zetaIsAlwaysLargerZero && zetaIsAlwaysZero) || (zeta[i] == 0. && lambda[i] < 0.)) {
 
  380      const double delta = 
sigma[i];
 
  384        const double phi = 1. + 
a[i] * 
a[i];
 
  385        const double k1 = cons1 * 
std::pow(phi, lambda[i]-0.5);
 
  386        const double k2 = 
beta[i]*k1 - cons1*(lambda[i]-0.5) * 
std::pow(phi, lambda[i]-1.5) * 2.*
a[i]/delta;
 
  387        const double B = -asigma + 
n[i]*k1/k2;
 
  392      else if (
d > a2sigma) {
 
  394        const double phi = 1. + a2[i]*a2[i];
 
  395        const double k1 = cons1 * 
std::pow(phi, lambda[i]-0.5);
 
  396        const double k2 = 
beta[i]*k1 + cons1*(lambda[i]-0.5) * 
std::pow(phi, lambda[i]-1.5) * 2.*a2[i]/delta;
 
  397        const double B = -a2sigma - n2[i]*k1/k2;
 
  398        const double A = k1*
std::pow(
B+a2sigma, n2[i]);
 
  410std::pair<double, double> computeAB_zetaNZero(
double asigma, 
double lambda, 
double alpha, 
double beta, 
double delta, 
double n) {
 
  411  const double k1 = LogEval(right ? asigma : -asigma, lambda, alpha, 
beta, delta);
 
  412  const double k2 = diff_eval(right ? asigma : -asigma, lambda, alpha, 
beta, delta);
 
  413  const double B = -asigma + (right ? -1 : 1.) * 
n*k1/k2;
 
  420std::pair<double, double> computeAB_zetaZero(
double beta, 
double asigma, 
double a, 
double lambda, 
double delta, 
double n) {
 
  421  const double cons1 = 
std::exp((right ? 1. : -1.) * 
beta*asigma);
 
  422  const double phi = 1. + 
a * 
a;
 
  423  const double k1 = cons1 * 
std::pow(phi, lambda-0.5);
 
  424  const double k2 = 
beta*k1 + (right ? 1. : -1) * cons1*(lambda-0.5) * 
std::pow(phi, lambda-1.5) * 2.*
a/delta;
 
  425  const double B = -asigma + (right ? -1. : 1.) * 
n*k1/k2;
 
  436    BracketAdapter<double> lambda, BracketAdapter<double> zeta, BracketAdapter<double> 
beta,
 
  437    BracketAdapter<double> 
sigma, BracketAdapter<double> mu,
 
  438    BracketAdapter<double> 
a, BracketAdapter<double> 
n, BracketAdapter<double> a2, BracketAdapter<double> n2) {
 
  442  const double asigma = 
a*
sigma;
 
  443  const double a2sigma = a2*
sigma;
 
  446    const double phi = besselK(lambda+1., zeta) / besselK(lambda, zeta);
 
  448    const double alpha  = cons0/cons1;
 
  449    const double delta = cons0*cons1;
 
  451    const auto AB_l = computeAB_zetaNZero<false>(asigma, lambda, alpha, 
beta, delta, 
n);
 
  452    const auto AB_r = computeAB_zetaNZero<true>(a2sigma, lambda, alpha, 
beta, delta, n2);
 
  454    for (std::size_t i = 0; i < 
N; ++i) {
 
  455      const double d = 
x[i] - mu[i];
 
  460      else if (
d>a2sigma) {
 
  464        output[i] = LogEval(
d, lambda, alpha, 
beta, delta);
 
  467  } 
else if (zeta == 0. && lambda < 0.) {
 
  468    const double delta = 
sigma;
 
  470    const auto AB_l = computeAB_zetaZero<false>(
beta, asigma,  
a,  lambda, delta, 
n);
 
  471    const auto AB_r = computeAB_zetaZero<true>(
beta, a2sigma, a2, lambda, delta, n2);
 
  473    for (std::size_t i = 0; i < 
N; ++i) {
 
  474      const double d = 
x[i] - mu[i];
 
  479      else if (
d > a2sigma) {
 
  509  const std::vector<RooSpan<const double>> params = {lambda, zeta, 
beta, sig, mu, 
a, 
n, a2, n2};
 
  511  if (!
x.empty() && std::all_of(params.begin(), params.end(), emptySpan)) {
 
double pow(double, double)
RooSpan< double > makeWritableBatchInit(std::size_t begin, std::size_t batchSize, double value)
Make a batch and return a span pointing to the pdf-local memory.
Little adapter that gives a bracket operator to types that don't have one.
Bool_t isConstant() const
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Double_t getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
BatchHelpers::BatchData _batchData
RooHypatia2 is the two-sided version of the Hypatia distribution described in https://arxiv....
RooSpan< double > evaluateBatch(std::size_t begin, std::size_t batchSize) const override
Evaluate function for a batch of input data points.
Double_t evaluate() const override
Evaluate this PDF / function / constant. Needs to be overridden by all derived classes.
A simple container to hold a batch of data values.
RooSpan< const double > getValBatch(std::size_t begin, std::size_t batchSize) const
virtual const char * GetName() const
Returns name of object.
double beta(double x, double y)
Calculates the beta function.
double cyl_bessel_k(double nu, double x)
Calculates the modified Bessel functions of the second kind (also called irregular modified (cylindri...
size_t findSize(std::vector< RooSpan< const double > > parameters)
This function returns the minimum size of the non-zero-sized batches.
VecExpr< UnaryOp< Fabs< T >, VecExpr< A, T, D >, T >, T, D > fabs(const VecExpr< A, T, D > &rhs)
void checkRangeOfParameters(const RooAbsReal *callingClass, std::initializer_list< const RooAbsReal * > pars, double min=-std::numeric_limits< double >::max(), double max=std::numeric_limits< double >::max(), bool limitsInAllowedRange=false, std::string extraMessage="")
Check if the parameters have a range, and warn if the range extends below / above the set limits.
Double_t Gamma(Double_t z)
Computation of gamma(z) for all z.
constexpr Double_t TwoPi()
static void output(int code)