Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README/ReleaseNotes/v628/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,23 @@ In the unlikely case that this causes any problem for you, please open a GitHub
The `RooAbsBinning` interface for bin index lookups was changed to enable vectorized implementations.
Instead of having the override `RooAbsBinning::binNumber()`, the binning implementations now have to override the `RooAbsBinning::binNumbers()` function to evaluate the bin indices of multiple values in one function call.

### Disable relative and absolute epsilon in `RooAbsRealLValue::inRange()`

So far, the `RooAbsRealLValue::inRange()` function used the following
undocumented convention to check whether a value `x` is in the range with
limits `a` and `b`: test if `[x - eps * x, x + eps * x]` overlaps with `[a, b]`, where the
parameter `eps` is defined as `max(epsRel * x, epsAbs)`.

The values of the relative and absolute epsilons were inconsistent among the overloads:

* [RooAbsRealLValue::inRange(const char* rangeName)](https://root.cern.ch/doc/v626/classRooAbsRealLValue.html#ab6050a0c3e5583b9d755a38fd7fb82f7): `epsRel = 1e-8, epsAbs = 0`
* [RooAbsRealLValue::inRange(double value, const char* rangeName, double* clippedValPtr)](https://root.cern.ch/doc/v626/classRooAbsRealLValue.html#afc2a8818f433a9a4ec0c437cbdad4e8a): `epsRel = 0, epsAbs = 1e-6`
* [RooAbsRealLValue::inRange(std::span<const double> values, std::string const& rangeName, std::vector<bool>& out)](https://root.cern.ch/doc/v626/classRooAbsRealLValue.html#af9217abd0afe34364562ad0c194f5d2c): `epsRel = 0, epsAbs = 1e-6`


With this release, the default absolute and relative epsilon is zero to avoid confusion.
You can change them with `RooNumber::setRangeEpsRel(epsRel)` and `RooNumber::setRangeEpsAbs(epsAbs)`.

## 2D Graphics Libraries

- Implement the option "File": The current file name is painted on the bottom right of each plot
Expand Down
17 changes: 17 additions & 0 deletions roofit/roofitcore/inc/RooNumber.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,24 @@ class RooNumber {
static double infinity() ;
static Int_t isInfinite(double x) ;

/// Set the relative epsilon that is used by range checks in RooFit,
/// e.g., in RooAbsRealLValue::inRange().
inline static void setRangeEpsRel(double epsRel) { staticRangeEpsRel() = epsRel; }
/// Get the relative epsilon that is used by range checks in RooFit,
/// e.g., in RooAbsRealLValue::inRange().
inline static double rangeEpsRel() { return staticRangeEpsRel(); }

/// Set the absolute epsilon that is used by range checks in RooFit,
/// e.g., in RooAbsRealLValue::inRange().
inline static void setRangeEpsAbs(double epsRel) { staticRangeEpsAbs() = epsRel; }
/// Get the absolute epsilon that is used by range checks in RooFit,
/// e.g., in RooAbsRealLValue::inRange().
inline static double rangeEpsAbs() { return staticRangeEpsAbs(); }

private:
static double& staticRangeEpsRel() ;
static double& staticRangeEpsAbs() ;

static double _Infinity ;

ClassDef(RooNumber,0) // wrapper class for portable numerics
Expand Down
39 changes: 34 additions & 5 deletions roofit/roofitcore/src/RooAbsRealLValue.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ interpreted as a parameter.
#include "RooArgList.h"
#include "RooAbsBinning.h"
#include "RooBinning.h"
#include "RooNumber.h"
#include "RooUniformBinning.h"
#include "RooCmdConfig.h"
#include "RooAbsData.h"
Expand Down Expand Up @@ -89,7 +90,16 @@ RooAbsRealLValue::~RooAbsRealLValue()
////////////////////////////////////////////////////////////////////////////////
/// Return true if the input value is within our fit range. Otherwise, return
/// false and write a clipped value into clippedValPtr if it is non-zero.

///
/// Implements the following check to see if the value x is in the range [a, b]:
/// check if `[x - eps * x, x + eps * x]` overlaps with `[a, b]`, where the
/// parameter `eps` is defined as:
/// ```
/// std::max(RooNumber::rangeEpsRel() * std::abs(x), RooNumber::rangeEpsAbs())
/// ```
/// By default, RooNumber::rangeEpsRel() and RooNumber::rangeEpsRel() are set to zero.
/// You can change them with RooNumber::setRangeEpsRel(double) and RooNumber::setRangeEpsAbs(double),
/// but this should be only done if there is no other solution.
bool RooAbsRealLValue::inRange(double value, const char* rangeName, double* clippedValPtr) const
{
// double range = getMax() - getMin() ; // ok for +/-INIFINITY
Expand All @@ -100,13 +110,15 @@ bool RooAbsRealLValue::inRange(double value, const char* rangeName, double* clip
double min = binning.lowBound() ;
double max = binning.highBound() ;

const double epsilon = std::max(RooNumber::rangeEpsRel() * std::abs(value), RooNumber::rangeEpsAbs());

// test this value against our upper fit limit
if(!RooNumber::isInfinite(max) && value > (max+1e-6)) {
if(!RooNumber::isInfinite(max) && value > (max+epsilon)) {
clippedValue = max;
isInRange = false ;
}
// test this value against our lower fit limit
if(!RooNumber::isInfinite(min) && value < min-1e-6) {
if(!RooNumber::isInfinite(min) && value < min-epsilon) {
clippedValue = min ;
isInRange = false ;
}
Expand All @@ -117,6 +129,8 @@ bool RooAbsRealLValue::inRange(double value, const char* rangeName, double* clip
}


////////////////////////////////////////////////////////////////////////////////
/// Vectorized version of RooAbsRealLValue::inRange(double, const char*, double*).
void RooAbsRealLValue::inRange(std::span<const double> values, std::string const& rangeName, std::vector<bool>& out) const {
if(rangeName.empty()) {
return;
Expand All @@ -125,11 +139,16 @@ void RooAbsRealLValue::inRange(std::span<const double> values, std::string const
const RooAbsBinning& binning = getBinning(rangeName.c_str()) ;
const double min = binning.lowBound() ;
const double max = binning.highBound() ;

const bool infiniteMin = RooNumber::isInfinite(min);
const bool infiniteMax = RooNumber::isInfinite(max);

const double epsRel = RooNumber::rangeEpsRel();
const double epsAbs = RooNumber::rangeEpsAbs();

for(std::size_t i = 0; i < values.size(); ++i) {
out[i] = out[i] && ((infiniteMax | (values[i] <= (max+1e-6))) && (infiniteMin | (values[i] >= (min-1e-6))));
const double eps = std::max(epsRel * std::abs(values[i]), epsAbs);
out[i] = out[i] && ((infiniteMax | (values[i] <= (max+eps))) && (infiniteMin | (values[i] >= (min-eps))));
}

}
Expand Down Expand Up @@ -490,10 +509,20 @@ bool RooAbsRealLValue::fitRangeOKForPlotting() const
/// Check if current value is inside range with given name. Multiple comma-separated
/// ranges can be passed. In this case, it will be checked if the value is in any of
/// these ranges.
///
/// Implements the following check to see if the value x is in the range [a, b]:
/// check if `[x - eps * x, x + eps * x]` overlaps with `[a, b]`, where the
/// parameter `eps` is defined as:
/// ```
/// std::max(RooNumber::rangeEpsRel() * std::abs(x), RooNumber::rangeEpsAbs())
/// ```
/// By default, RooNumber::rangeEpsRel() and RooNumber::rangeEpsRel() are set to zero.
/// You can change them with RooNumber::setRangeEpsRel(double) and RooNumber::setRangeEpsAbs(double),
/// but this should be only done if there is no other solution.
bool RooAbsRealLValue::inRange(const char* name) const
{
const double val = getVal() ;
const double epsilon = 1e-8 * std::abs(val) ;
const double epsilon = std::max(RooNumber::rangeEpsRel() * std::abs(val), RooNumber::rangeEpsAbs());
if (!name || name[0] == '\0') {
const auto minMax = getRange(nullptr);
return minMax.first - epsilon <= val && val <= minMax.second + epsilon;
Expand Down
12 changes: 12 additions & 0 deletions roofit/roofitcore/src/RooNumber.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,18 @@ double RooNumber::infinity()
}


double& RooNumber::staticRangeEpsRel() {
static double epsRel = 0.0;
return epsRel;
}


double& RooNumber::staticRangeEpsAbs() {
static double epsAbs = 0.0;
return epsAbs;
}


////////////////////////////////////////////////////////////////////////////////
/// Return true if x is infinite by RooNumBer internal specification

Expand Down