#include "Formula.h" #include #include "tinyexpr.h" Formula::Formula(Formula&& other) noexcept : m_source(std::move(other.m_source)) , m_x(std::move(other.m_x)) , m_expr(other.m_expr) { other.m_expr = nullptr; } Formula& Formula::operator=(Formula&& other) noexcept { if (this != &other) { te_free(m_expr); m_source = std::move(other.m_source); m_x = std::move(other.m_x); m_expr = other.m_expr; other.m_expr = nullptr; } return *this; } Formula::~Formula() { te_free(m_expr); } Formula Formula::compile(const std::string& source) { Formula result; result.m_source = source; result.m_x = std::make_unique(0.0); const te_variable variables[] = { { "x", result.m_x.get(), 0, nullptr }, }; int errorPos = 0; result.m_expr = te_compile(result.m_source.c_str(), variables, 1, &errorPos); if (result.m_expr == nullptr) { throw std::runtime_error( "Formula parse error at position " + std::to_string(errorPos) + " in \"" + source + "\""); } return result; } double Formula::evaluate(double x) const { if (m_expr == nullptr) { throw std::runtime_error("Formula::evaluate called on uninitialized formula"); } // The variable at *m_x is what the compiled tree dereferences during // te_eval. Mutating it here does not affect logical const-ness of the // formula — the formula itself is unchanged. *m_x = x; return te_eval(m_expr); }