From fee05a621d511da2caccae044856eeff07b2f509 Mon Sep 17 00:00:00 2001 From: Emily Boudreaux Date: Mon, 12 Oct 2026 09:37:03 -0400 Subject: [PATCH] feat(equations): Added EquationRegistry This is a compile time pack of equations which can be used to do things like say "this model is described by this set of equations" --- src/include/serif/equations/registry.hpp | 72 ++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/include/serif/equations/registry.hpp diff --git a/src/include/serif/equations/registry.hpp b/src/include/serif/equations/registry.hpp new file mode 100644 index 00000000..35851d56 --- /dev/null +++ b/src/include/serif/equations/registry.hpp @@ -0,0 +1,72 @@ +#pragma once + +/** + * @file registry.hpp + * @author Emily M. Boudreaux + * + * @brief System for registering multiple equations. The idea here is that a model will be defined partly by an equation registry (e.g. all the + * equations that must be satisfied for a given model). + */ + +#include +#include + +#include "serif/equations/concepts.hpp" + +namespace serif::equations { + /** + * @class EquationRegistry + * + * @brief A compile-time registry of equations. + * @tparam EquationTs Pack of equation types to register. + * + * @requires There must be at least one equation type in the pack. + * @requires Each residual row must be defined exactly once. + */ + template + class EquationRegistry final { + public: + static_assert(sizeof...(EquationTs) > 0, "An equation registry must contain at least one equation."); + + using Equations = utils::types::TypeList; ///< The equation types in the registry. + using Rows = utils::types::TypeList...>; ///< The residual row types in the registry + + static_assert( ((OperandValues::template index() < sizeof...(EquationTs)) && ...), "An equation registry must define each residual row exactly once."); + + /** + * @brief Construct an equation registry with the given equations. + * + * @param equations The equations to register. + */ + explicit EquationRegistry(EquationTs... equations) : m_equations(std::move(equations)...) {} + + /** + * @brief Apply some function to every type in the registry. + * + * @tparam FunctionT The type of the function to apply. The function must have the signature `void(const EquationT&)` where `EquationT` is the type of the equation in the registry. + * @param function The function to apply to each equation in the registry. + */ + template + void for_each(FunctionT&& function) const { + std::apply([&](const auto&... equations) { + (function(equations), ...); + }, + m_equations + ); + } + + /** + * @brief Get the equation of a given type from the registry. + * + * @tparam EquationT The type of the equation to get. + * @return The equation of the given type. + */ + template + [[nodiscard]] const EquationT& get() const { + return std::get(m_equations); + } + + private: + std::tuple m_equations; ///< The equations in the registry, stored as a tuple. + }; +} // namespace serif::equations