/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
CondFormats/HcalObjects/interface/InterpolatedPulse.h
307 строк
10 KB
Shahzad Malik Muzaffar
[ALCA-DB] Changes suggested by new llvm18 clang-format
05 сен 2024, 17:06
05 сен 2024, 17:06
d09a7ed
Код
Авторство
О чём код?
#ifndef CondFormats_HcalObjects_InterpolatedPulse_h_ #define CondFormats_HcalObjects_InterpolatedPulse_h_ #include <cassert> #include "FWCore/Utilities/interface/Exception.h" #include "boost/serialization/access.hpp" #include "boost/serialization/version.hpp" template <unsigned MaxLen> class InterpolatedPulse { template <unsigned Len2> friend class InterpolatedPulse; public: // Would normally do "static const" but genreflex has problems for it enum { maxlen = MaxLen }; // Default constructor creates a pulse which is zero everywhere inline InterpolatedPulse() : tmin_(0.0), width_(1.0), length_(2U) { zeroOut(); } // Constructor from a single integer creates a pulse with the given // number of discrete steps which is zero everywhere inline explicit InterpolatedPulse(const unsigned len) : tmin_(0.0), width_(1.0), length_(len) { if (length_ < 2 || length_ > MaxLen) throw cms::Exception("In InterpolatedPulse constructor: invalid length"); zeroOut(); } inline InterpolatedPulse(const double tmin, const double tmax, const unsigned len) : tmin_(tmin), width_(tmax - tmin), length_(len) { if (length_ < 2 || length_ > MaxLen) throw cms::Exception("In InterpolatedPulse constructor: invalid length"); if (width_ <= 0.0) throw cms::Exception("In InterpolatedPulse constructor: invalid pulse width"); zeroOut(); } template <typename Real> inline InterpolatedPulse(const double tmin, const double tmax, const Real* values, const unsigned len) : tmin_(tmin), width_(tmax - tmin) { if (width_ <= 0.0) throw cms::Exception("In InterpolatedPulse constructor: invalid pulse width"); setShape(values, len); } // Efficient copy constructor. Do not copy undefined values. inline InterpolatedPulse(const InterpolatedPulse& r) : tmin_(r.tmin_), width_(r.width_), length_(r.length_) { double* buf = &pulse_[0]; const double* rbuf = &r.pulse_[0]; for (unsigned i = 0; i < length_; ++i) *buf++ = *rbuf++; } // Converting copy constructor template <unsigned Len2> inline InterpolatedPulse(const InterpolatedPulse<Len2>& r) : tmin_(r.tmin_), width_(r.width_), length_(r.length_) { if (length_ > MaxLen) throw cms::Exception("In InterpolatedPulse copy constructor: buffer is not long enough"); double* buf = &pulse_[0]; const double* rbuf = &r.pulse_[0]; for (unsigned i = 0; i < length_; ++i) *buf++ = *rbuf++; } // Efficient assignment operator inline InterpolatedPulse& operator=(const InterpolatedPulse& r) { if (this != &r) { tmin_ = r.tmin_; width_ = r.width_; length_ = r.length_; double* buf = &pulse_[0]; const double* rbuf = &r.pulse_[0]; for (unsigned i = 0; i < length_; ++i) *buf++ = *rbuf++; } return *this; } // Converting assignment operator template <unsigned Len2> inline InterpolatedPulse& operator=(const InterpolatedPulse<Len2>& r) { if (r.length_ > MaxLen) throw cms::Exception("In InterpolatedPulse::operator=: buffer is not long enough"); tmin_ = r.tmin_; width_ = r.width_; length_ = r.length_; double* buf = &pulse_[0]; const double* rbuf = &r.pulse_[0]; for (unsigned i = 0; i < length_; ++i) *buf++ = *rbuf++; return *this; } template <typename Real> inline void setShape(const Real* values, const unsigned len) { if (len < 2 || len > MaxLen) throw cms::Exception("In InterpolatedPulse::setShape: invalid length"); assert(values); length_ = len; double* buf = &pulse_[0]; for (unsigned i = 0; i < len; ++i) *buf++ = *values++; } // Zero out the signal inline void zeroOut() { for (unsigned i = 0; i < length_; ++i) pulse_[i] = 0.0; } // Simple inspectors inline const double* getPulse() const { return &pulse_[0]; } inline unsigned getLength() const { return length_; } inline double getStartTime() const { return tmin_; } inline double getStopTime() const { return tmin_ + width_; } inline double getPulseWidth() const { return width_; } inline double getTimeStep() const { return width_ / (length_ - 1U); } // Simple modifiers inline void setStartTime(const double newStartTime) { tmin_ = newStartTime; } inline void setPulseWidth(const double newWidth) { if (newWidth <= 0.0) throw cms::Exception("In InterpolatedPulse::setPulseWidth: invalid pulse width"); width_ = newWidth; } // Get the pulse value at the given time using linear interpolation inline double operator()(const double t) const { const volatile double tmax = tmin_ + width_; if (t < tmin_ || t > tmax) return 0.0; const unsigned lm1 = length_ - 1U; const double step = width_ / lm1; const double nSteps = (t - tmin_) / step; unsigned nbelow = nSteps; unsigned nabove = nbelow + 1; if (nabove > lm1) { nabove = lm1; nbelow = nabove - 1U; } const double delta = nSteps - nbelow; return pulse_[nbelow] * (1.0 - delta) + pulse_[nabove] * delta; } inline double derivative(const double t) const { const volatile double tmax = tmin_ + width_; if (t < tmin_ || t > tmax) return 0.0; const unsigned lm1 = length_ - 1U; const double step = width_ / lm1; const double nSteps = (t - tmin_) / step; unsigned nbelow = nSteps; unsigned nabove = nbelow + 1; if (nabove > lm1) { nabove = lm1; nbelow = nabove - 1U; } const double delta = nSteps - nbelow; if ((nbelow == 0U && delta <= 0.5) || (nabove == lm1 && delta >= 0.5)) return (pulse_[nabove] - pulse_[nbelow]) / step; else if (delta >= 0.5) { const double lower = pulse_[nabove] - pulse_[nbelow]; const double upper = pulse_[nabove + 1U] - pulse_[nabove]; return (upper * (delta - 0.5) + lower * (1.5 - delta)) / step; } else { const double lower = pulse_[nbelow] - pulse_[nbelow - 1U]; const double upper = pulse_[nabove] - pulse_[nbelow]; return (lower * (0.5 - delta) + upper * (0.5 + delta)) / step; } } inline double secondDerivative(const double t) const { const volatile double tmax = tmin_ + width_; if (t < tmin_ || t > tmax || length_ < 3U) return 0.0; const unsigned lm1 = length_ - 1U; const double step = width_ / lm1; const double stepSq = step * step; const double nSteps = (t - tmin_) / step; unsigned nbelow = nSteps; unsigned nabove = nbelow + 1; if (nabove > lm1) { nabove = lm1; nbelow = nabove - 1U; } if (nbelow == 0U) { // The first interval return (pulse_[2] - 2.0 * pulse_[1] + pulse_[0]) / stepSq; } else if (nabove == lm1) { // The last interval return (pulse_[lm1] - 2.0 * pulse_[lm1 - 1U] + pulse_[lm1 - 2U]) / stepSq; } else { // One of the middle intervals const double lower = pulse_[nbelow - 1U] - 2.0 * pulse_[nbelow] + pulse_[nabove]; const double upper = pulse_[nbelow] - 2.0 * pulse_[nabove] + pulse_[nabove + 1U]; const double delta = nSteps - nbelow; return (lower * (1.0 - delta) + upper * delta) / stepSq; } } inline InterpolatedPulse& operator*=(const double scale) { if (scale != 1.0) { double* buf = &pulse_[0]; for (unsigned i = 0; i < length_; ++i) *buf++ *= scale; } return *this; } // Add another pulse to this one. Note that addition of another pulse // will not change the start time or the width of _this_ pulse. The // added pulse will be truncated as needed. template <unsigned Len2> inline InterpolatedPulse& operator+=(const InterpolatedPulse<Len2>& r) { const double step = width_ / (length_ - 1U); for (unsigned i = 0; i < length_; ++i) pulse_[i] += r(tmin_ + i * step); return *this; } template <unsigned Len2> inline bool operator==(const InterpolatedPulse<Len2>& r) const { if (!(tmin_ == r.tmin_ && width_ == r.width_ && length_ == r.length_)) return false; const double* buf = &pulse_[0]; const double* rbuf = &r.pulse_[0]; for (unsigned i = 0; i < length_; ++i) if (*buf++ != *rbuf++) return false; return true; } template <unsigned Len2> inline bool operator!=(const InterpolatedPulse<Len2>& r) const { return !(*this == r); } // Simple trapezoidal integration inline double getIntegral() const { const double* buf = &pulse_[0]; long double sum = buf[0] / 2.0; const unsigned nIntervals = length_ - 1U; for (unsigned i = 1U; i < nIntervals; ++i) sum += buf[i]; sum += buf[nIntervals] / 2.0; return sum * width_ / nIntervals; } inline void setIntegral(const double newValue) { const double integ = this->getIntegral(); if (integ == 0.0) throw cms::Exception("In InterpolatedPulse::setIntegral division by zero"); *this *= (newValue / integ); } inline double getPeakValue() const { const double* buf = &pulse_[0]; double peak = buf[0]; for (unsigned i = 1U; i < length_; ++i) if (buf[i] > peak) peak = buf[i]; return peak; } inline void setPeakValue(const double newValue) { const double peak = this->getPeakValue(); if (peak == 0.0) throw cms::Exception("In InterpolatedPulse::setPeakValue: division by zero"); *this *= (newValue / peak); } private: double pulse_[MaxLen]; double tmin_; double width_; unsigned length_; friend class boost::serialization::access; template <class Archive> inline void serialize(Archive& ar, unsigned /* version */) { ar & tmin_ & width_ & length_; // In case we are reading, it may be useful to verify // that the length is reasonable if (length_ > MaxLen) throw cms::Exception("In InterpolatedPulse::serialize: buffer is not long enough"); for (unsigned i = 0; i < length_; ++i) ar& pulse_[i]; } }; // boost serialization version number for this template namespace boost { namespace serialization { template <unsigned MaxLen> struct version<InterpolatedPulse<MaxLen> > { BOOST_STATIC_CONSTANT(int, value = 1); }; } // namespace serialization } // namespace boost #endif // CondFormats_HcalObjects_InterpolatedPulse_h_