/*************************************************************************** PUserFcn.cpp Author: Andreas Suter e-mail: andreas.suter@psi.ch ***************************************************************************/ /*************************************************************************** * Copyright (C) 2007-2025 by Andreas Suter * * andreas.suter@psi.ch * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include "PUserFcn.h" ClassImp(PUserFcn) //------------------------------------------------------ /** * \brief Default constructor for PUserFcn. * * Initializes a third-order polynomial user function. This implementation * requires no special initialization as it has no internal state - all * computation is done directly in the operator() method. * * \note This simple constructor serves as a template for more complex user * functions. Functions requiring initialization (e.g., loading lookup tables, * precomputing constants) should perform that work here or in SetGlobalPart(). */ PUserFcn::PUserFcn() { } //------------------------------------------------------ /** * \brief Destructor for PUserFcn. * * Cleans up any resources allocated by the polynomial function. Since this * implementation has no dynamically allocated resources, the destructor is * empty. * * \note User functions with allocated resources (lookup tables, buffers, * external library handles) must clean them up here to prevent memory leaks. * If using the global part interface, ensure proper coordination with * gGlobalUserFcn cleanup. */ PUserFcn::~PUserFcn() { } //------------------------------------------------------ /** * \brief Evaluates the third-order polynomial at the given time. * * Computes a cubic polynomial of the form: * * \f[ P(t) = c_0 + c_1 t + c_2 t^2 + c_3 t^3 = \sum_{k=0}^{3} c_k t^k \f] * * where the coefficients \f$c_k\f$ are provided in the parameter vector. * * \section puserfcn_op_example Example MSR Configuration * * \code * FITPARAMETER * # No Name Value Step Pos_Error Boundaries * 1 c0 0.95 0.01 none * 2 c1 -0.001 0.0001 none * 3 c2 0.00001 0.000001 none * 4 c3 0.0 0.0000001 none 0 none (fixed to zero for quadratic) * * THEORY * userFcn libPUserFcn.so PUserFcn 1 2 3 4 * \endcode * * \section puserfcn_op_notes Implementation Notes * * - Uses direct polynomial evaluation (Horner's method could improve * numerical stability for high-precision applications) * - Asserts exactly 4 parameters to catch MSR file configuration errors * - No special handling for negative time values * * \param t Independent variable (time in μs for μSR, or general x-axis * value for non-μSR fits) * \param param Vector containing exactly 4 polynomial coefficients: * - param[0]: \f$c_0\f$ - constant term (dimensionless) * - param[1]: \f$c_1\f$ - linear coefficient (μs⁻¹) * - param[2]: \f$c_2\f$ - quadratic coefficient (μs⁻²) * - param[3]: \f$c_3\f$ - cubic coefficient (μs⁻³) * * \return The polynomial value \f$P(t)\f$ at the specified time * * \pre param.size() == 4 (enforced by assertion) * * \see PUserFcnBase::operator() for the virtual interface specification */ Double_t PUserFcn::operator()(Double_t t, const std::vector ¶m) const { // expected parameters: c0, c1, c2, c3 assert(param.size() == 4); return param[0] + param[1]*t + param[2]*t*t + param[3]*t*t*t; }