#ifndef __JTOOLS__JRESULT__ #define __JTOOLS__JRESULT__ #include #include "JTools/JRange.hh" #include "JLang/JClass.hh" #include "JLang/JAssert.hh" #include "JMath/JMath.hh" #include "JMath/JZero.hh" /** * \file * * This include file containes various data structures that * can be used as specific return types for the interpolating methods. * These data structures have standard arithmetic capabilities and * are templated so that they can be expanded in higher dimensions. * \author mdejong */ namespace JTOOLS {} namespace JPP { using namespace JTOOLS; } namespace JTOOLS { using JMATH::JMath; /** * Data structure for result including value and first derivative of function. * * This data structure contains the following data mambers: *
   *    JResultDerivative::f   = function value;
   *    JResultDerivative::fp  = first  derivative;
   * 
* * This class implements the JMATH::JMath interface. */ template struct JResultDerivative : public JMath< JResultDerivative > { typedef typename JLANG::JClass::argument_type argument_type; /** * Default constructor. */ JResultDerivative() : f (JMATH::zero), fp (JMATH::zero) {} /** * Constructor. * * \param f function value * \param fp first derivative */ JResultDerivative(argument_type f, argument_type fp) : f (f ), fp (fp) {} /** * Prefix unary minus for function value of PDF. * * \return function value of PDF */ JResultDerivative& negate() { f = -f; fp = -fp; return *this; } /** * Addition operator for function value of PDF. * * \param value function value of PDF * \return function value of PDF */ JResultDerivative& add(const JResultDerivative& value) { f += value.f; fp += value.fp; return *this; } /** * Subtraction operator for function value of PDF. * * \param value function value of PDF * \return function value of PDF */ JResultDerivative& sub(const JResultDerivative& value) { f -= value.f; fp -= value.fp; return *this; } /** * Multiplication operator for function value of PDF. * * \param value multiplication factor * \return function value of PDF */ JResultDerivative& mul(const double value) { f *= value; fp *= value; return *this; } /** * Division operator for function value of PDF. * * \param value multiplication factor * \return function value of PDF */ JResultDerivative& div(const double value) { f /= value; fp /= value; return *this; } /** * Get probability.\n * If the given hit is false (true), the return value corresponds to the Poisson probability * that zero (one or more) hits occur for the given expectation value JResultDerivative::f. * * \param hit hit (or not) * \return probability */ double getP(const bool hit) const { if (!hit) return exp(-f); // probability of 0 hits else return 1.0 - getP(false); // probability of 1 or more hits } /** * Get chi2. * The chi2 corresponds to -log(P), where P is the probability JResultDerivative::f. * * \param hit hit (or not) * \return chi2 */ double getChi2(const bool hit) const { if (!hit) return f; // = -log(getP(false)) else return -log(getP(true)); } /** * Get derivative of chi2. * * \param hit hit (or not) * \return derivative */ double getDerivativeOfChi2(const bool hit) const { if (!hit) return fp; else return -fp * getP(false) / getP(true); } JResult_t f; //!< function value JResult_t fp; //!< first derivative }; /** * Data structure for result including value and first derivative of function. * * This data structure contains the following data mambers: *
   *    JResultHesse::f   = function value;
   *    JResultHesse::fp  = first  derivative;
   *    JResultHesse::fpp = second derivative;
   * 
* * This class implements the JMATH::JMath interface. */ template struct JResultHesse : public JResultDerivative, public JMath< JResultHesse > { typedef typename JResultDerivative::argument_type argument_type; /** * Default constructor. */ JResultHesse() : JResultDerivative(), fpp(JMATH::zero) {} /** * Constructor. * * \param f function value * \param fp first derivative * \param fpp second derivative */ JResultHesse(argument_type f, argument_type fp, argument_type fpp) : JResultDerivative(f, fp), fpp(fpp) {} /** * Prefix unary minus for function value of PDF. * * \return function value of PDF */ JResultHesse& negate() { static_cast&>(*this).negate(); fpp = -fpp; return *this; } /** * Addition operator for function value of PDF. * * \param value function value of PDF * \return function value of PDF */ JResultHesse& add(const JResultHesse& value) { static_cast&>(*this).add(value); fpp += value.fpp; return *this; } /** * Subtraction operator for function value of PDF. * * \param value function value of PDF * \return function value of PDF */ JResultHesse& sub(const JResultHesse& value) { static_cast&>(*this).sub(value); fpp -= value.fpp; return *this; } /** * Multiplication operator for function value of PDF. * * \param value multiplication factor * \return function value of PDF */ JResultHesse& mul(const double value) { static_cast&>(*this).mul(value); fpp *= value; return *this; } /** * Division operator for function value of PDF. * * \param value multiplication factor * \return function value of PDF */ JResultHesse& div(const double value) { static_cast&>(*this).div(value); fpp /= value; return *this; } JResult_t fpp; //!< second derivative }; /** * Data structure for result including value, first derivative and integrals of function. * * This data structure contains the following data mambers: *
   *    JResultPDF::f   = function value;
   *    JResultPDF::fp  = first derivative;
   *    JResultPDF::v   = partial  integral;
   *    JResultPDF::V   = complete integral.
   * 
* The partial and complete integrals are used to evaluate the probability of the first hit. * * This class implements the JMATH::JMath interface. */ template struct JResultPDF : public JMath< JResultPDF > { typedef typename JLANG::JClass::argument_type argument_type; /** * Default constructor. */ JResultPDF() : f (JMATH::zero), fp(JMATH::zero), v (JMATH::zero), V (JMATH::zero) {} /** * Constructor. * * \param f function value * \param fp first derivative * \param v integral */ JResultPDF(argument_type f, argument_type fp, argument_type v, argument_type V) : f (f ), fp(fp), v (v), V (V) {} /** * Constructor.\n * This constructor refers to the result of a signal with a constant rate R * to produce an event occurring at the given moment x within the fixed range X. * * \param R rate * \param x abscissa value * \param X abscissa range */ JResultPDF(argument_type R, argument_type x, const JRange& X) : f (R), fp(JMATH::zero), v (R * (X.constrain(x) - X.getLowerLimit())), V (R * (X.getUpperLimit() - X.getLowerLimit())) {} /** * Prefix unary minus for function value of PDF. * * \return function value of PDF */ JResultPDF& negate() { f = -f; fp = -fp; v = -v; V = -V; return *this; } /** * Addition operator for function value of PDF. * * \param value function value of PDF * \return function value of PDF */ JResultPDF& add(const JResultPDF& value) { f += value.f; fp += value.fp; v += value.v; V += value.V; return *this; } /** * Subtraction operator for function value of PDF. * * \param value function value of PDF * \return function value of PDF */ JResultPDF& sub(const JResultPDF& value) { f -= value.f; fp -= value.fp; v -= value.v; V -= value.V; return *this; } /** * Multiplication operator for function value of PDF. * * \param value multiplication factor * \return function value of PDF */ JResultPDF& mul(const double value) { f *= value; fp *= value; v *= value; V *= value; return *this; } /** * Division operator for function value of PDF. * * \param value division factor * \return function value of PDF */ JResultPDF& div(const double value) { f /= value; fp /= value; v /= value; V /= value; return *this; } /** * Get probability of first hit.\n * The probability is defined at the moment JResultPDF::f and JResultPDF::v have been evaluated * and it is normalised to the total interval corresponding to JResultPDF::V. * * \return probability */ double getP() const { return exp(-v) * f / (1.0 - exp(-V)); } /** * Get chi2 of first hit.\n * The chi2 corresponds to -log(P), where P is the probability JResultPDF::f. * * \return chi2 */ double getChi2() const { return -log(getP()); } /** * Get derivative of chi2 of first hit. * * \return derivative */ double getDerivativeOfChi2() const { return fp/f - f; } JResult_t f; //!< function value JResult_t fp; //!< first derivative JResult_t v; //!< integral }; /** * Data structure for result including value and N derivatives of function. * * This data structure contains the following data mambers: *
   *    JResultPolynome::y[0] = function value;
   *    JResultPolynome::y[i] = ith derivative; 
   *    JResultPolynome::y[N] = Nth derivative; 
   * 
* * This class implements the JMATH::JMath interface. */ template struct JResultPolynome : public JMath< JResultPolynome > { typedef typename JLANG::JClass::argument_type argument_type; static const int NUMBER_OF_POINTS = N + 1; // number of points (starting at 0) /** * Default constructor. */ JResultPolynome() { for (int i = 0; i != NUMBER_OF_POINTS; ++i) { y[i] = JMATH::zero; } } /** * Type conversion operator. * * \return result */ operator JResultDerivative() const { STATIC_CHECK(NUMBER_OF_POINTS >= 2); return JResultDerivative(y[0], y[1]); } /** * Type conversion operator. * * \return result */ operator JResultHesse() const { STATIC_CHECK(NUMBER_OF_POINTS >= 3); return JResultHesse(y[0], y[1], y[2]); } /** * Prefix unary minus for function value of PDF. * * \return function value of PDF */ JResultPolynome& negate() { for (int i = 0; i != NUMBER_OF_POINTS; ++i) { y[i] = -y[i]; } return *this; } /** * Addition operator for function value of PDF. * * \param value function value of PDF * \return function value of PDF */ JResultPolynome& add(const JResultPolynome& value) { for (int i = 0; i != NUMBER_OF_POINTS; ++i) { y[i] += value.y[i]; } return *this; } /** * Subtraction operator for function value of PDF. * * \param value function value of PDF * \return function value of PDF */ JResultPolynome& sub(const JResultPolynome& value) { for (int i = 0; i != NUMBER_OF_POINTS; ++i) { y[i] -= value.y[i]; } return *this; } /** * Multiplication operator for function value of PDF. * * \param value multiplication factor * \return function value of PDF */ JResultPolynome& mul(const double value) { for (int i = 0; i != NUMBER_OF_POINTS; ++i) { y[i] *= value; } return *this; } /** * Division operator for function value of PDF. * * \param value multiplication factor * \return function value of PDF */ JResultPolynome& div(const double value) { for (int i = 0; i != NUMBER_OF_POINTS; ++i) { y[i] /= value; } return *this; } /** * Function value. * * \param x abscissa value * \return function value */ double getValue(const double x) const { double w = 0.0; double z = 1.0; for (int i = 0; i != NUMBER_OF_POINTS; ++i, z *= x / i) { w += y[i] * z; } return w; } /** * Function value. * * \param x abscissa value * \return function value */ double operator()(const double x) const { return getValue(x); } JResult_t y[NUMBER_OF_POINTS]; //!< function and derivative values }; /** * Auxiliary class to recursively evaluate to a result. */ template struct JResultEvaluator { typedef T result_type; /** * Get function value. * * \return result */ static result_type get_value(typename JLANG::JClass::argument_type value) { return value; } /** * Get derivative value. * * \return result */ static result_type get_derivative(typename JLANG::JClass::argument_type value) { return value; } /** * Get partial integral value. * * \return result */ static result_type get_integral(typename JLANG::JClass::argument_type value) { return value; } /** * Get total integral value. * * \return result */ static result_type get_total_integral(typename JLANG::JClass::argument_type value) { return value; } }; /** * Template specialisation of JResultEvaluator for JResultDerivative. */ template struct JResultEvaluator< JResultDerivative > { typedef typename JResultEvaluator::result_type result_type; /** * Get function value. * * \return result */ static result_type get_value(const JResultDerivative& value) { return JResultEvaluator::get_value(value.f); } /** * Get derivative value. * * \return result */ static result_type get_derivative(const JResultDerivative& value) { return JResultEvaluator::get_value(value.fp); } /** * Get partial integral value. * * \return result */ static result_type get_integral(const JResultDerivative& value) { return JMATH::zero; } /** * Get total integral value. * * \return result */ static result_type get_total_integral(const JResultDerivative& value) { return JMATH::zero; } }; /** * Template specialisation of JResultEvaluator for JResultHesse. */ template struct JResultEvaluator< JResultHesse > { typedef typename JResultEvaluator::result_type result_type; /** * Get function value. * * \return result */ static result_type get_value(const JResultHesse& value) { return JResultEvaluator::get_value(value.f); } /** * Get derivative value. * * \return result */ static result_type get_derivative(const JResultHesse& value) { return JResultEvaluator::get_value(value.fp); } /** * Get partial integral value. * * \return result */ static result_type get_integral(const JResultHesse& value) { return JMATH::zero; } /** * Get total integral value. * * \return result */ static result_type get_total_integral(const JResultHesse& value) { return JMATH::zero; } }; /** * Template specialisation of JResultEvaluator for JResultPDF. */ template struct JResultEvaluator< JResultPDF > { typedef typename JResultEvaluator::result_type result_type; /** * Get function value. * * \return result */ static result_type get_value(const JResultPDF& value) { return JResultEvaluator::get_value(value.f); } /** * Get derivative value. * * \return result */ static result_type get_derivative(const JResultPDF& value) { return JResultEvaluator::get_value(value.fp); } /** * Get partial integral value. * * \return result */ static result_type get_integral(const JResultPDF& value) { return JResultEvaluator::get_value(value.v); } /** * Get total integral value. * * \return result */ static result_type get_total_integral(const JResultPDF& value) { return JResultEvaluator::get_value(value.V); } }; /** * Template specialisation of JResultEvaluator for JResultPolynome. */ template struct JResultEvaluator< JResultPolynome > { typedef typename JResultEvaluator::result_type result_type; /** * Get function value. * * \return result */ static result_type get_value(const JResultPolynome& value) { return JResultEvaluator::get_value(value.y[0]); } /** * Get derivative value. * * \return result */ static result_type get_derivative(const JResultPolynome& value) { return JResultEvaluator::get_value(value.y[1]); } /** * Get partial integral value. * * \return result */ static result_type get_integral(const JResultPolynome& value) { return JMATH::zero; } /** * Get total integral value. * * \return result */ static result_type get_total_integral(const JResultPolynome& value) { return JMATH::zero; } }; /** * Template specialisation of JResultEvaluator for JResultPolynome. */ template struct JResultEvaluator< JResultPolynome<0, T> > { typedef typename JResultEvaluator::result_type result_type; /** * Get function value. * * \return result */ static result_type get_value(const JResultPolynome<0, T>& value) { return JResultEvaluator::get_value(value.y[0]); } /** * Get derivative value. * * \return result */ static result_type get_derivative(const JResultPolynome<0, T>& value) { return JMATH::zero; } /** * Get partial integral value. * * \return result */ static result_type get_integral(const JResultPolynome<0, T>& value) { return JMATH::zero; } /** * Get total integral value. * * \return result */ static result_type get_total_integral(typename JLANG::JClass::argument_type value) { return JMATH::zero; } }; /** * Helper method to recursively evaluate a to function value. * * \param value result * \return function value */ template inline typename JResultEvaluator::result_type get_value(const JResult_t& value) { return JResultEvaluator::get_value(value); } /** * Helper method to convert function value to derivative value. * * \param value result * \return derivative value */ template inline typename JResultEvaluator::result_type get_derivative(const JResult_t& value) { return JResultEvaluator::get_derivative(value); } /** * Helper method to convert function value to partial integral value. * * \param value result * \return partial integral value */ template inline typename JResultEvaluator::result_type get_integral(const JResult_t& value) { return JResultEvaluator::get_integral(value); } /** * Helper method to convert function value to total integral value. * * \param value result * \return total integral value */ template inline typename JResultEvaluator::result_type get_total_integral(const JResult_t& value) { return JResultEvaluator::get_total_integral(value); } } #endif