API — ICoreSDK/ICoreMath
The public contract of 28 header(s) under src/ICoreSDK/ICoreMath — 28 class/struct definition(s), 376 declaration(s). Each section shows the header's banner and its public (and protected-virtual) surface exactly as the file writes it.
ICoreExpressionEvaluator.h#
src/ICoreSDK/ICoreMath/ICoreExpressionEvaluator.h
ICoreValue#
ICoreExpressionEvaluator.h:18 · struct · 6 declaration(s)
A console value: a matrix (scalars are 1x1 matrices), a polynomial, a transfer function, a state-space model, or a recorded time series.
struct ICoreValue {
public:
// Str exists only so a quoted string literal can be carried through the
// parser as a function argument (e.g. gradient("expr", x0)) -- it has no
// arithmetic operators defined on it, unlike the other kinds.
//
// TimeSeries likewise has no arithmetic: it is a container to be opened with
// .time() / .values(), not a term to compute with.
enum class Kind { Matrix, Polynomial, Tf, Ss, Str, TimeSeries };
Kind kind = Kind::Matrix;
ICoreMatrix matrix;
ICorePolynomial poly;
ICoreTransferFunction tf;
ICoreStateSpace ss;
std::string str;
ICoreTimeSeries series;
// The six named constructors. Bodies in the .cpp, per the header surface
// rule -- they were one-liners, and one-liners are not an exemption.
static ICoreValue ofMatrix(const ICoreMatrix& m);
static ICoreValue ofPoly(const ICorePolynomial& p);
static ICoreValue ofTf(const ICoreTransferFunction& t);
static ICoreValue ofSs(const ICoreStateSpace& s);
static ICoreValue ofStr(const std::string& s);
static ICoreValue ofSeries(const ICoreTimeSeries& s);
};
};
ICoreExpressionEvaluator#
ICoreExpressionEvaluator.h:48 · class · nested Result, FunctionInfo · 2 declaration(s)
Evaluates expressions over matrices, polynomials, transfer functions and state-space models, with operator precedence, parentheses, and functions.
class ICoreExpressionEvaluator {
public:
using VariableResolver = std::function<bool(const std::string& name, ICoreValue& out)>;
struct Result {
bool ok = false;
ICoreValue value;
std::string error; // "No error" when ok
};
static Result evaluate(const std::string& expression, const VariableResolver& resolver);
// Built-in functions — single source of truth for help/glossary and completion.
struct FunctionInfo {
std::string name;
std::string signature;
std::string description;
};
static std::vector<FunctionInfo> functions();
};
};
ICoreVariable.h#
src/ICoreSDK/ICoreMath/ICoreVariable.h
Declared, defined in the .cpp: the residue below is a unique_ptr to an Impl this header cannot see, and only the .cpp can destroy one.
ICoreVariable#
ICoreVariable.h:7 · class · pImpl · 13 declaration(s)
class ICoreVariable {
public:
explicit ICoreVariable(const std::string& initName, const std::string& initValue);
void setName(const std::string& newName);
virtual std::string setValue(const std::string& newValue);
void assignType();
std::string getName() const;
std::string getValue() const;
std::string getType() const;
ICoreMatrix getAssociatedSyntraMatrix() const;
std::pair<bool, long long> getCastedValueAsInteger() const;
std::pair<bool, double> getCastedValueAsDouble() const;
std::pair<bool, std::pair<std::vector<std::string>, std::string> > getCastedValueAsOptions() const;
void resetToInitialState_BaseSyntraVariable(const std::string& initName, const std::string& initValue);
// Declared, defined in the .cpp: the residue below is a unique_ptr to an
// Impl this header cannot see, and only the .cpp can destroy one.
virtual ~ICoreVariable();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
eigen_pch.h#
src/ICoreSDK/ICoreMath/eigen_pch.h
eigen_pch.h -- ICoreMath's Eigen umbrella.
The linear-algebra backbone behind ICoreMatrix and the numerics stack. Heavy to parse, which is why it is gathered here rather than repeated header by header at each use site.
This file used to be section 2 of the SDK-root src/ICoreSDK/pch.h, which the ICoreBlocks target force-included into EVERY translation unit -- so all of src/ parsed Eigen whether it named a single Eigen type or not. In fact only ICoreMath does: the census finds Eigen tokens in nine files, every one of them under src/ICoreSDK/ICoreMath/. That is MODULE_LAYERING.md M8's "Eigen moves into per-module PCHs" step, taken for the Eigen half; the std + ICoreEssentials half of the old pch.h is now delivered by src/ICoreEssentials/pch.h, which the ICoreBlocks target precompiles.
Declares no class of its own — see the file.
ICoreNumericalJacobian.h#
src/ICoreSDK/ICoreMath/Calculus/ICoreNumericalJacobian.h
ICoreNumericalJacobian#
ICoreNumericalJacobian.h:13 · class · 1 declaration(s)
Central-difference gradient of a scalar expression typed as a string, via Eigen::NumericalDiff's functor pattern -- the functor's operator() calls back into ICoreExpressionEvaluator::evaluate() wit...
class ICoreNumericalJacobian {
public:
// expr: a scalar-valued expression using variables named x1, x2, ..., xn
// (n = number of rows/entries in x0).
// x0: the point to differentiate around (a vector).
// Returns a 1 x n row vector: d(expr)/d(xi) at x0, for each i.
static ICoreMatrix gradient(const std::string& expr, const ICoreMatrix& x0);
};
};
ICoreIIREmulator.h#
src/ICoreSDK/ICoreMath/ControlSystems/ICoreIIREmulator.h
ICoreIIREmulator#
ICoreIIREmulator.h:9 · class · pImpl · 12 declaration(s)
class ICoreIIREmulator {
public:
// explicit ICoreIIREmulator(const std::vector<double>& numCoefficients, const std::vector<double>& denCoefficients);
explicit ICoreIIREmulator(const ICoreTransferFunction& tf);
double step(const double& uk);
void reset();
void setInitialConditions(const std::vector<double>& new_u_ic, const std::vector<double>& new_y_ic);
// Seed the filter from a DIRECT-FORM II delay line, newest first -- the vector
// Simulink's Discrete Transfer Fcn and Discrete Filter call "Initial states"
// (both report FilterStructure = "Direct form II"). This emulator is direct
// form I: it holds past INPUTS and past OUTPUTS, which are different
// quantities, so the two cannot simply be assigned to each other.
//
// The conversion, with w[-m] the m-th newest given state and 0 outside the
// vector, and the coefficients already normalized by a0:
//
// u[-m] = w[-m] + SUM_j a_j * w[-m-j]
// y[-m] = SUM_j b_j * w[-m-j]
//
// MEASURED against R2026a rather than derived from the documentation: for
// num [0.5 -0.2 0.3], den [1 -0.7 0.25] and InitialStates [1 0], Simulink's
// zero-input response begins 0.15, 0.28, and so does this seeding. The two
// realizations agree sample for sample, which is the only claim worth making
// -- an initial STATE is realization-specific and could not be copied across.
//
// Also measured: "InitialDenominatorStates" moves nothing on either block, so
// there is no second vector to carry.
void seedFromDirectFormIIStates(const std::vector<double>& states);
// The same conversion as data, for the code generators: they bake the seeded
// histories into the exported filter and never call step(). Index i is the
// (i+1)-th newest sample, matching what step() expects to find.
[[nodiscard]] std::vector<double> seededInputHistory() const;
[[nodiscard]] std::vector<double> seededOutputHistory() const;
// Emulators are stored BY VALUE in std::vector inside three block headers
// (Discrete Transfer Function, Transfer Function, Zero-Pole), so the type
// has to stay both copyable and nothrow-movable: a vector only grows by
// moving when the move cannot throw, and the implicit copy is deleted by
// the unique_ptr residue. All four are written out in the .cpp.
ICoreIIREmulator(const ICoreIIREmulator& other);
ICoreIIREmulator& operator=(const ICoreIIREmulator& other);
ICoreIIREmulator(ICoreIIREmulator&& other) noexcept;
ICoreIIREmulator& operator=(ICoreIIREmulator&& other) noexcept;
~ICoreIIREmulator();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreStateSpace.h#
src/ICoreSDK/ICoreMath/ControlSystems/ICoreStateSpace.h
///////////////////////////// / Constructors ////////////////////////////
ICoreStateSpace#
ICoreStateSpace.h:11 · class · pImpl · 38 declaration(s)
class ICoreStateSpace {
public:
///////////////////////////////
/// Constructors
//////////////////////////////
ICoreStateSpace();
explicit ICoreStateSpace(const ICoreMatrix& A_candidate, const ICoreMatrix& B_candidate, const ICoreMatrix& C_candidate, const ICoreMatrix& D_candidate, const double& Ts_candidate = -1.0);
explicit ICoreStateSpace(const ICoreMatrix& A_candidate, const ICoreMatrix& Bu_candidate, const ICoreMatrix& Bf_candidate,
const ICoreMatrix& C_candidate, const ICoreMatrix& Du_candidate, const ICoreMatrix& Df_candidate, const double& Ts_candidate = -1.0);
static ICoreStateSpace fromTransferFunction(const ICoreTransferFunction& tf);
///////////////////////////////
/// Matrices Assignment
//////////////////////////////
bool tryUpdatingMatrices(const ICoreMatrix &A_candidate, const ICoreMatrix &B_candidate,
const ICoreMatrix &C_candidate, const ICoreMatrix &D_candidate,
const double &Ts_candidate);
bool tryUpdatingMatrices(const ICoreMatrix &A_candidate, const ICoreMatrix &Bu_candidate,
const ICoreMatrix &Bf_candidate, const ICoreMatrix &C_candidate,
const ICoreMatrix &Du_candidate, const ICoreMatrix &Df_candidate,
const double &Ts_candidate);
///////////////////////////////
/// Dynamics
//////////////////////////////
[[nodiscard]] ICoreMatrix computeStateEvolution_noMatrixSizeCheck(const ICoreMatrix& x, const ICoreMatrix& u) const;
[[nodiscard]] ICoreMatrix computeStateEvolution_noMatrixSizeCheck(const ICoreMatrix &x, const ICoreMatrix &u, const ICoreMatrix &f) const;
[[nodiscard]] ICoreMatrix computeOutput_noMatrixSizeCheck(const ICoreMatrix& x, const ICoreMatrix& u) const;
[[nodiscard]] ICoreMatrix computeOutput_noMatrixSizeCheck(const ICoreMatrix& x, const ICoreMatrix& u, const ICoreMatrix &f) const;
///////////////////////////////
/// Analysis
//////////////////////////////
[[nodiscard]] bool checkDimensions(const ICoreMatrix& x, const ICoreMatrix& u) const;
bool checkDimensions_nonlinear(const ICoreMatrix &x, const ICoreMatrix &u, const ICoreMatrix &f) const;
[[nodiscard]] std::vector<ICoreComplexVariable> getEigenValues() const;
[[nodiscard]] ICoreMatrix getControllabilityMatrix() const;
[[nodiscard]] bool isControllable() const;
[[nodiscard]] ICoreMatrix getObservabilityMatrix() const;
[[nodiscard]] bool isObservable() const;
///////////////////////////////
/// Getters
//////////////////////////////
[[nodiscard]] ICoreMatrix getA() const;
[[nodiscard]] ICoreMatrix getB() const;
[[nodiscard]] ICoreMatrix getBu() const;
[[nodiscard]] ICoreMatrix getBf() const;
[[nodiscard]] ICoreMatrix getCombinedBuBf() const;
[[nodiscard]] ICoreMatrix getC() const;
[[nodiscard]] ICoreMatrix getD() const;
[[nodiscard]] ICoreMatrix getDu() const;
[[nodiscard]] ICoreMatrix getDf() const;
[[nodiscard]] ICoreMatrix getCombinedDuDf() const;
[[nodiscard]] size_t getOrder() const;
[[nodiscard]] size_t getNumberOfInputs() const;
[[nodiscard]] size_t get_m_u() const;
[[nodiscard]] size_t get_m_f() const;
[[nodiscard]] size_t getNumberOfOutputs() const;
[[nodiscard]] double getSamplingTime() const;
[[nodiscard]] double getTs() const;
[[nodiscard]] bool isContinues() const;
void print() const;
// A state space is passed and stored by value all over the model layer, so
// it stays copyable. The unique_ptr residue below deletes the implicit copy
// operations, so all four are written out in the .cpp.
ICoreStateSpace(const ICoreStateSpace& other);
ICoreStateSpace& operator=(const ICoreStateSpace& other);
ICoreStateSpace(ICoreStateSpace&& other) noexcept;
ICoreStateSpace& operator=(ICoreStateSpace&& other) noexcept;
~ICoreStateSpace();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreTransferFunction.h#
src/ICoreSDK/ICoreMath/ControlSystems/ICoreTransferFunction.h
Transfer functions are handed around and stored by value, so the type stays copyable; the unique_ptr residue below deletes the implicit copy operations, so all four are written out in the .cpp.
ICoreTransferFunction#
ICoreTransferFunction.h:13 · class · pImpl · 28 declaration(s)
class ICoreTransferFunction {
public:
ICoreTransferFunction();
ICoreTransferFunction(const ICorePolynomial &num_candidate, const ICorePolynomial &den_candidate, const double& Ts_candidate = -1);
static ICoreTransferFunction fromPolesZeros(const std::vector<ICoreComplexVariable>& zeros,
const std::vector<ICoreComplexVariable>& poles,
const double& gain = 1.0, const double& Ts = -1);
static ICoreTransferFunction fromSISOStateSpace(const ICoreStateSpace &stateSpace);
static ICoreTransferFunction fromSISOStateSpace(const ICoreMatrix& A, const ICoreMatrix& B,
const ICoreMatrix& C, const ICoreMatrix& D, double Ts = -1);
bool tryUpdatingCoefficients(const ICorePolynomial &num_candidate, const ICorePolynomial &den_candidate,
const double &Ts_candidate = -1);
ICoreTransferFunction operator*(const ICoreTransferFunction &other) const;
ICoreTransferFunction operator+(const ICoreTransferFunction &other) const;
ICoreTransferFunction operator-(const ICoreTransferFunction &other) const;
[[nodiscard]] ICoreTransferFunction feedback(const ICoreTransferFunction &H) const;
void poleZeroCancellation(const double& tol);
void normalize();
[[nodiscard]] ICoreComplexVariable evaluate(const ICoreComplexVariable &s) const;
[[nodiscard]] std::vector<ICoreComplexVariable> zeros() const;
[[nodiscard]] std::vector<ICoreComplexVariable> poles() const;
[[nodiscard]] bool isStable() const;
[[nodiscard]] double getDcGain() const;
[[nodiscard]] ICoreComplexVariable frequencyResponse(const double& omega) const;
[[nodiscard]] std::vector<ICoreBodePoint> bode(const double& w_start, const double& w_end, const int& numOfPoints) const;
[[nodiscard]] std::vector<ICoreComplexVariable> nyquist(const double& w_start, const double& w_end, const int& numOfPoints) const;
[[nodiscard]] ICorePolynomial getNumerator() const;
[[nodiscard]] ICorePolynomial getDenominator() const;
[[nodiscard]] double getSamplingTime() const;
[[nodiscard]] double getTs() const;
[[nodiscard]] int getOrder() const;
void print() const;
// Transfer functions are handed around and stored by value, so the type
// stays copyable; the unique_ptr residue below deletes the implicit copy
// operations, so all four are written out in the .cpp.
ICoreTransferFunction(const ICoreTransferFunction& other);
ICoreTransferFunction& operator=(const ICoreTransferFunction& other);
ICoreTransferFunction(ICoreTransferFunction&& other) noexcept;
ICoreTransferFunction& operator=(ICoreTransferFunction&& other) noexcept;
~ICoreTransferFunction();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreBodePoint.h#
src/ICoreSDK/ICoreMath/ControlSystems/HelperObjects/ICoreBodePoint.h
bode() returns a std::vector of these, so the type has to stay copyable. A unique_ptr member deletes the implicit copy operations, so both are written out in the .cpp -- see the note there on what the residue costs.
ICoreBodePoint#
ICoreBodePoint.h:7 · class · pImpl · 9 declaration(s)
class ICoreBodePoint {
public:
ICoreBodePoint(const double& omega,
const double& magnitude,
const double& magnitude_dB,
const double& phase
);
// bode() returns a std::vector of these, so the type has to stay copyable.
// A unique_ptr member deletes the implicit copy operations, so both are
// written out in the .cpp -- see the note there on what the residue costs.
ICoreBodePoint(const ICoreBodePoint& other);
ICoreBodePoint& operator=(const ICoreBodePoint& other);
ICoreBodePoint(ICoreBodePoint&& other) noexcept;
ICoreBodePoint& operator=(ICoreBodePoint&& other) noexcept;
[[nodiscard]] double getOmega() const;
[[nodiscard]] double getMagnitude() const;
[[nodiscard]] double getMagnitudeDB() const;
[[nodiscard]] double getPhase() const;
~ICoreBodePoint();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreBlocksMerging.h#
src/ICoreSDK/ICoreMath/ControlSystems/StaticMethods/ICoreBlocksMerging.h
Closed-loop realization for a purely additive summing junction: e = r + H(y), y = G(e). (For the classical negative-feedback junction e = r - H(y), bake the sign into H's own C/D — the formula here does not assume either sign.) Resolves the algebraic loop created by G and H's direct feedthrough terms; returns false (leaving outClosedLoop untouched) if that loop is unresolvable, i.e. 1 - D_G*D_H is (numerically) singular.
ICoreBlocksMerging#
ICoreBlocksMerging.h:6 · class · 4 declaration(s)
class ICoreBlocksMerging {
public:
static ICoreStateSpace mergeInSeries(const ICoreStateSpace& G1, const ICoreStateSpace& G2);
static ICoreStateSpace mergeInParallel(const ICoreStateSpace& G1, const ICoreStateSpace& G2);
// Closed-loop realization for a purely additive summing junction: e = r + H(y), y = G(e). (For
// the classical negative-feedback junction e = r - H(y), bake the sign into H's own C/D — the
// formula here does not assume either sign.) Resolves the algebraic loop created by G and H's
// direct feedthrough terms; returns false (leaving outClosedLoop untouched) if that loop is
// unresolvable, i.e. 1 - D_G*D_H is (numerically) singular.
static bool mergeInFeedback(const ICoreStateSpace& G, const ICoreStateSpace& H, ICoreStateSpace& outClosedLoop);
// Closed-loop realization for an "empty"/unity feedback path: e = referenceSign*r +
// feedbackSign*y, y = G(e) (G's own output wired straight back into the summing junction, with
// no feedback block in between). referenceSign/feedbackSign are each +1 or -1, matching which
// port of the summing junction the reference and the loop-closing connection land on (see
// ICoreStateSpaceReductionHelpers::combinerInputSign) — e.g. classical negative unity feedback
// is referenceSign=+1, feedbackSign=-1. Resolves the algebraic loop created by G's own direct
// feedthrough term; returns false (leaving outClosedLoop untouched) if that loop is
// unresolvable, i.e. 1 - feedbackSign*D_G is (numerically) singular.
static bool mergeInUnityFeedback(const ICoreStateSpace& G, double referenceSign, double feedbackSign, ICoreStateSpace& outClosedLoop);
};
};
ICoreRootLocus.h#
src/ICoreSDK/ICoreMath/ControlSystems/StaticMethods/ICoreRootLocus.h
ICoreRootLocus#
ICoreRootLocus.h:8 · class · 1 declaration(s)
Classical root locus under unity negative feedback.
class ICoreRootLocus {
public:
// For each gain K in `gains` (a vector), computes the closed-loop poles
// of the unity-negative-feedback system K*openLoopTf / (1 + K*openLoopTf)
// -- i.e. the roots of den(openLoopTf) + K*num(openLoopTf) -- and returns
// them all stacked as an (numGains * order) x 2 [real, imag] matrix.
// Poles are not ordered/matched into continuous branches across gains
// (a standard simplification for a first-pass locus plotter).
static ICoreMatrix computePoles(const ICoreTransferFunction& openLoopTf, const ICoreMatrix& gains);
};
};
ICoreSS2TF.h#
src/ICoreSDK/ICoreMath/ControlSystems/StaticMethods/ICoreSS2TF.h
ICoreSS2TF#
ICoreSS2TF.h:9 · class · 1 declaration(s)
class ICoreSS2TF {
public:
static ICoreArray<ICoreTransferFunction> ss2tf(const ICoreStateSpace& stateSpace);
};
};
ICoreStateSpaceDiscretization.h#
src/ICoreSDK/ICoreMath/ControlSystems/StaticMethods/ICoreStateSpaceDiscretization.h
ICoreStateSpaceDiscretization#
ICoreStateSpaceDiscretization.h:7 · class · 2 declaration(s)
class ICoreStateSpaceDiscretization {
public:
static ICoreStateSpace discretizeStateSpace(const ICoreStateSpace& originalContStateSpace, const double& Ts, const std::string& method = "ZOH");
static ICoreStateSpace deDiscretizeStateSpace(const ICoreStateSpace &originalDiscStateSpace, const std::string &method = "ZOH");
};
};
ICoreTimeResponse.h#
src/ICoreSDK/ICoreMath/ControlSystems/StaticMethods/ICoreTimeResponse.h
ICoreTimeResponse#
ICoreTimeResponse.h:15 · class · 1 declaration(s)
Time-domain response of a transfer function to the standard test inputs.
class ICoreTimeResponse {
public:
enum class Input { Step, Impulse, Ramp };
// Returns an N x 2 [time, output] matrix, or an empty matrix with `error`
// set. `duration` is in seconds and must be > 0; `points` is the requested
// sample count (>= 2) and is what sets the step for a continuous tf. For a
// discrete tf the step is fixed by its own Ts, so `points` is ignored and
// the count follows from duration / Ts.
static ICoreMatrix compute(const ICoreTransferFunction& tf, const Input& input,
const double& duration, const size_t& points,
std::string& error);
// A duration to simulate over when the caller named none -- what makes a
// bare `step(G)` answer instead of erroring. Read off the poles: long
// enough for the slowest mode to settle, or to ring a few times when
// nothing decays. Always finite and > 0, for any tf including a default
// one, so a caller may pass it straight to compute().
static double suggestedDuration(const ICoreTransferFunction& tf);
static std::string inputName(const Input& input); // "Step", "Impulse", "Ramp"
};
};
ICoreComplexVariable.h#
src/ICoreSDK/ICoreMath/Foundation/ICoreComplexVariable.h
////////////////////////// / Scalar operations /////////////////////////
ICoreComplexVariable#
ICoreComplexVariable.h:7 · class · pImpl · 32 declaration(s)
class ICoreComplexVariable {
public:
ICoreComplexVariable();
ICoreComplexVariable(const double& real, const double& imaginary);
static ICoreComplexVariable fromPolar(const double& magnitude, const double& angle);
////////////////////////////
/// Scalar operations
///////////////////////////
ICoreComplexVariable operator*(double scalar) const;
ICoreComplexVariable operator/(double scalar) const;
////////////////////////////
/// Basic arithmetic operators
///////////////////////////
ICoreComplexVariable operator+(const ICoreComplexVariable &other) const;
ICoreComplexVariable operator-(const ICoreComplexVariable &other) const;
ICoreComplexVariable operator*(const ICoreComplexVariable &other) const;
ICoreComplexVariable operator/(const ICoreComplexVariable &other) const;
////////////////////////////
/// Conjugate
///////////////////////////
ICoreComplexVariable conjugate() const;
////////////////////////////
/// Other operations
///////////////////////////
double magnitude() const;
double magnitudeSquared() const;
double phase() const;
double complexDistance(const ICoreComplexVariable &other) const;
ICoreComplexVariable normalized() const;
ICoreComplexVariable exp() const;
ICoreComplexVariable log() const;
ICoreComplexVariable pow(const double& exponent) const;
bool isApprox(const ICoreComplexVariable &other, const double& tol = 1e-12) const;
bool isZero(double tol) const;
bool isReal(double tol) const;
ICoreComplexVariable rotate(const double &angle) const;
////////////////////////////
/// Setters/Getters
///////////////////////////
void setReal(const double& newReal);
void setImaginary(const double& newImaginary);
double getReal() const;
double getImaginary() const;
std::string getVariableAsString() const;
friend std::ostream& operator<<(std::ostream& os, const ICoreComplexVariable& mat);
// Complex values live in std::vector (eigenvalues, root loci), so the type
// stays copyable; the unique_ptr residue below deletes the implicit copy
// operations, so all four are written out in the .cpp.
ICoreComplexVariable(const ICoreComplexVariable& other);
ICoreComplexVariable& operator=(const ICoreComplexVariable& other);
ICoreComplexVariable(ICoreComplexVariable&& other) noexcept;
ICoreComplexVariable& operator=(ICoreComplexVariable&& other) noexcept;
~ICoreComplexVariable();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreMatrix.h#
src/ICoreSDK/ICoreMath/Foundation/ICoreMatrix.h
Two members below (toEigen2DMatrixXd / fromEigen) name Eigen::MatrixXd in their signatures, so this header cannot be parsed without Eigen. It used to arrive for free from the force-included SDK-root pch.h; that Eigen block now lives in ICoreMath's own umbrella and is named here explicitly.
ICoreMatrix#
ICoreMatrix.h:49 · class · pImpl · 135 declaration(s)
class ICoreMatrix {
public:
////////////////////////////////////////////////////
///
/// Constructors and Base Methods
///
////////////////////////////////////////////////////
ICoreMatrix();
ICoreMatrix(size_t d1, size_t d2, size_t d3 = 1);
explicit ICoreMatrix(const double& scalar);
explicit ICoreMatrix(const std::vector<double>& vec1d);
explicit ICoreMatrix(const std::vector<std::vector<double>>& vec2d);
explicit ICoreMatrix(const std::vector<std::vector<std::vector<double>>>& vec3d);
static ICoreMatrix identity(const size_t& n);
static ICoreMatrix zeros(const size_t &size1, const size_t &size2);
static ICoreMatrix zerosVector(const size_t &size1);
static ICoreMatrix ones(const size_t &size1, const size_t &size2);
static ICoreMatrix onesVector(const size_t &size1);
static ICoreMatrix linspace(const double& a, const double& b, const size_t& n);
static ICoreMatrix logspace(const double& a, const double& b, const size_t& n);
static ICoreMatrix rand(const size_t& size1, const size_t& size2); // uniform 0,1)
static ICoreMatrix randn(const size_t& size1, const size_t& size2); // standard normal
// This is the setter method
double& operator()(size_t i, size_t j, size_t k = 0);
// This is the getter method
double operator()(size_t i, size_t j, size_t k = 0) const;
size_t size1() const;
size_t size2() const;
size_t size3() const;
std::vector<double> rawData() const;
void assignRawDataDirectly(const size_t& size1, const size_t& size2, const size_t& size3, const std::vector<double>& newRawDataVector);
size_t numberOfRows() const;
size_t numberOfColumns() const;
void resize(size_t d1, size_t d2 = 1, size_t d3 = 1);
void overwriteIndex(const double& newVal, const size_t i, const size_t j = 0, const size_t k = 0);
void cloneValueFromMatrix(const ICoreMatrix* other);
void cloneValueFromMatrix(const ICoreMatrix& other);
void clear();
////////////////////////////////////////////////////
///
/// Verifications
///
////////////////////////////////////////////////////
bool verifySize(const size_t &d1, const size_t &d2 = 1, const size_t &d3 = 1) const;
bool verifySquareMatrix() const;
bool verifyElementWiseInteger() const;
bool verifyElementWiseNotNegative() const;
bool verifyElementWiseStrictlyPositive() const;
bool verifyZerosMatrix(double tol = 1e-12) const;
bool verifySalarZeroMatrix(double tol) const;
bool verifyOnesMatrix(double tol = 1e-12) const;
bool verifyValidVectorSize() const;
bool isScalar() const;
bool isSymmetric(double tol = 1e-9) const;
bool isPositiveDefinite() const;
////////////////////////////////////////////////////
///
/// Conversions to std vectors
///
////////////////////////////////////////////////////
// Convert full 3D matrix to nested vectors
std::vector<std::vector<std::vector<double>>> toVector3D() const;
std::vector<std::vector<double>> toVector2D() const;
// Get a 2D slice by fixing dim1 index (like a "matrix" at i)
std::vector<std::vector<double>> getSlice2D(const size_t& i) const;
// // Get a 1D column vector fixing dim1 and dim3 (returns all j for fixed i,k)
// std::vector<double> getColumn(const size_t& i, const size_t& k = 0) const;
// // Get a 1D row vector fixing dim1 and dim2 (returns all k for fixed i,j)
// std::vector<double> getRow(const size_t& i, const size_t& j) const;
ICoreMatrix getColumn(const size_t& j) const;
ICoreMatrix getRow(const size_t& i) const;
// Get a 1D vector of the entire entries for the entire matrix
std::vector<double>& getRawDataVector();
std::vector<double> getRawDataVector_Copy() const;
std::pair<bool, ICoreMatrix> sliceMatrix2D(const size_t &row_start, const size_t &row_end, const size_t &col_start,
const size_t &col_end) const;
////////////////////////////////////////////////////
///
/// Algebra
///
////////////////////////////////////////////////////
// To Apply operators
void operator+=(const ICoreMatrix& other);
ICoreMatrix operator+(const ICoreMatrix& other) const;
void operator-=(const ICoreMatrix& other);
ICoreMatrix operator-(const ICoreMatrix& other) const;
ICoreMatrix operator*(const double& scale) const;
friend ICoreMatrix operator*(double scale, const ICoreMatrix& m);
ICoreMatrix operator*(const ICoreMatrix& other) const;
ICoreMatrix operator|(const ICoreMatrix& other) const;
ICoreMatrix operator&(const ICoreMatrix& other) const;
// Element-wise addition: this + other
ICoreMatrix& add(const ICoreMatrix& other);
// Element-wise subtraction: this - other
ICoreMatrix& subtract(const ICoreMatrix& other);
// Product
double dot(const ICoreMatrix& other) const;
ICoreMatrix cross(const ICoreMatrix& other) const;
ICoreMatrix multiply(const ICoreMatrix& other) const;
ICoreMatrix& multiplyElementWiseByScalar(const double& factor);
ICoreMatrix multiplyElementWiseByMatrix(ICoreMatrix& other) const;
ICoreMatrix transpose() const;
size_t rank(const double& tol = 1e-12) const;
// Inverse
ICoreMatrix inverse() const;
ICoreMatrix syntraInverse() const;
// Eigen-backed scalar quantities
double determinant() const; // square 2D only
double trace() const; // square 2D only
double conditionNumber() const; // ratio of largest/smallest singular value
// Eigen-backed factorizations / generalized inverses
ICoreMatrix pseudoInverse(double tol = -1.0) const; // Moore-Penrose (SVD); tol<0 => auto
ICoreMatrix sqrtm() const; // principal matrix square root (square)
ICoreMatrix choleskyL() const; // lower factor L, A = L*L^T (square SPD)
ICoreMatrix nullSpace() const; // basis for ker(A) as columns
// LDLT decomposition (symmetric, possibly indefinite): P^T*L*diag(D)*L^T*P = A
ICoreMatrix ldltL() const;
ICoreMatrix ldltD() const;
ICoreMatrix ldltP() const;
// Matrix exponential
ICoreMatrix expm() const;
ICoreMatrix logm() const;
// Norms
double norm_Frobenius() const;
double norm_RMS() const;
double norm_1() const;
double norm_2(size_t maxIter, double tol) const;
double norm_inf() const;
double norm_nuclear() const; // sum of singular values, 2D only
ICoreMatrix concatHorizontal(const ICoreMatrix& other) const;
ICoreMatrix concatVertical(const ICoreMatrix& other) const;
std::vector<ICoreComplexVariable> eigenvalues() const;
ICoreMatrix eigenvectors() const; // real part; exact for symmetric matrices
ICoreMatrix solve(const ICoreMatrix &rhs) const;
// QR decomposition (thin): A = Q*R
ICoreMatrix qrQ() const;
ICoreMatrix qrR() const;
// LU decomposition with partial pivoting (square only): P*A = L*U
ICoreMatrix luL() const;
ICoreMatrix luU() const;
ICoreMatrix luP() const;
// SVD (thin): A = U*diag(S)*V^T; svdS is a column vector of singular values
ICoreMatrix svdU() const;
ICoreMatrix svdS() const;
ICoreMatrix svdV() const;
// diag(): vector -> diagonal matrix; 2D matrix -> its diagonal as a column vector
ICoreMatrix diag() const;
// Kronecker product, 2D only
ICoreMatrix kron(const ICoreMatrix& other) const;
// Element-wise math (operates over all entries, including 3D)
ICoreMatrix elementWiseAbs() const;
ICoreMatrix elementWiseExp() const;
ICoreMatrix elementWiseLog() const;
ICoreMatrix elementWiseSqrt() const;
ICoreMatrix elementWiseSin() const;
ICoreMatrix elementWiseCos() const;
ICoreMatrix elementWiseTan() const;
ICoreMatrix elementWisePow(const double& exponent) const;
ICoreMatrix elementWiseMin(const ICoreMatrix& other) const; // broadcasts a scalar operand
ICoreMatrix elementWiseMax(const ICoreMatrix& other) const; // broadcasts a scalar operand
ICoreMatrix clamp(const double& lo, const double& hi) const;
// Element-wise comparisons (broadcast a scalar operand); result is 0.0/1.0 per entry
ICoreMatrix greaterThan(const ICoreMatrix& other) const;
ICoreMatrix lessThan(const ICoreMatrix& other) const;
ICoreMatrix greaterEqual(const ICoreMatrix& other) const;
ICoreMatrix lessEqual(const ICoreMatrix& other) const;
ICoreMatrix equalTo(const ICoreMatrix& other, double tol = 1e-12) const;
ICoreMatrix notEqualTo(const ICoreMatrix& other, double tol = 1e-12) const;
// Matrix power: integer exponent via exponentiation by squaring (negative uses inverse())
ICoreMatrix mpower(const long long& n) const;
// Reductions over all entries
double sum() const;
double mean() const;
double maxElement() const;
double minElement() const;
// Axis-wise reductions, 2D only. *Rows collapses each row to one value
// (result is a column vector); *Cols collapses each column (row vector).
ICoreMatrix sumRows() const;
ICoreMatrix sumCols() const;
ICoreMatrix meanRows() const;
ICoreMatrix meanCols() const;
ICoreMatrix maxRows() const;
ICoreMatrix maxCols() const;
ICoreMatrix minRows() const;
ICoreMatrix minCols() const;
// Cumulative sum/product. Vectors accumulate along their length; general
// matrices accumulate down each column (Matlab convention).
ICoreMatrix cumsum() const;
ICoreMatrix cumprod() const;
// Shape manipulation, 2D only
ICoreMatrix reshape(const size_t& newDim1, const size_t& newDim2) const;
ICoreMatrix flipud() const;
ICoreMatrix fliplr() const;
ICoreMatrix repmat(const size_t& rowTimes, const size_t& colTimes) const;
// Statistics: columns are variables, rows are observations
ICoreMatrix covariance() const;
ICoreMatrix correlation() const;
// Vector-only helpers
ICoreMatrix normalize() const; // unit vector (v / ||v||)
double angleTo(const ICoreMatrix& other) const; // angle between two vectors, radians
// Sylvester-family linear matrix equations, solved via vec()/Kronecker
// reduction. A unique solution needs the operator nonsingular — lyap:
// eig(A)+eig(A) never 0; dlyap: eig(A)*eig(A) never 1; sylvester:
// eig(A)+eig(B) never 0. A singular operator makes the QR solve return a
// NON-solution with no diagnostic, so each solver verifies its residual
// afterwards; on failure it reports (into whyNot when given, the run
// diagnosis otherwise) and returns the default matrix. Found by the
// command-parity suite: MATLAB returns NaN on the same inputs.
ICoreMatrix lyap(const ICoreMatrix& Q, std::string* whyNot = nullptr) const; // A*X + X*A^T + Q = 0
ICoreMatrix dlyap(const ICoreMatrix& Q, std::string* whyNot = nullptr) const; // A*X*A^T - X + Q = 0
ICoreMatrix sylvester(const ICoreMatrix& B, const ICoreMatrix& C,
std::string* whyNot = nullptr) const; // A*X + X*B = C
// Algebraic Riccati equations (LQR/Kalman-style design). Solved via the stable
// invariant subspace of the Hamiltonian (care) / symplectic pencil (dare).
// Assumes (A,B) stabilizable and (A,Q) detectable, with no eigenvalues exactly
// on the stability boundary (imaginary axis / unit circle).
ICoreMatrix care(const ICoreMatrix& B, const ICoreMatrix& Q, const ICoreMatrix& R) const; // A^T X + X A - X B R^-1 B^T X + Q = 0
ICoreMatrix dare(const ICoreMatrix& B, const ICoreMatrix& Q, const ICoreMatrix& R) const; // A^T X A - X - A^T X B (R+B^T X B)^-1 B^T X A + Q = 0
Eigen::MatrixXd toEigen2DMatrixXd() const;
////////////////////////////////////////////////////
///
/// Matrix print-out operator
///
////////////////////////////////////////////////////
// Declare friend operator<< for output streaming
friend std::ostream& operator<<(std::ostream& os, const ICoreMatrix& mat);
// A matrix is copied constantly -- by value into and out of nearly every
// numeric call in the tree -- so the type stays copyable and nothrow-movable.
// The unique_ptr residue below deletes the implicit copy, so all four are
// written out in the .cpp.
//
// THE COST, recorded rather than hidden: an ICoreMatrix now costs TWO heap
// allocations to build instead of one (the Impl, then its data vector) and
// one more indirection per element access. It already allocated for `data`
// on every copy, so this is a constant factor on an allocating path, not a
// new allocation on a free one. See the SH2 notes in HEADER_SURFACE.md.
ICoreMatrix(const ICoreMatrix& other);
ICoreMatrix& operator=(const ICoreMatrix& other);
ICoreMatrix(ICoreMatrix&& other) noexcept;
ICoreMatrix& operator=(ICoreMatrix&& other) noexcept;
// Declared, defined in the .cpp: unique_ptr cannot destroy an incomplete Impl.
~ICoreMatrix();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICorePolynomial.h#
[src/ICoreSDK/ICoreMath/Foundation/ICorePolynomial.h
ICorePolynomial#
ICorePolynomial.h:8 · class · 23 declaration(s)
class ICorePolynomial {
public:
ICorePolynomial();
explicit ICorePolynomial(const double& coefficient);
explicit ICorePolynomial(const std::vector<double>& coefficients);
explicit ICorePolynomial(const ICoreMatrix& coefficients);
double evaluate(const double& x) const;
ICoreComplexVariable evaluateComplex(const double &real, const double &imag) const;
ICorePolynomial derivative() const;
ICorePolynomial integral(const double &constant) const;
void normalize();
void trimTrailingZeros(double tol = 1e-14);
ICorePolynomial operator+(const ICorePolynomial &other) const;
ICorePolynomial operator-(const ICorePolynomial &other) const;
ICorePolynomial operator*(const ICorePolynomial &other) const;
std::pair<ICorePolynomial, ICorePolynomial> divide(const ICorePolynomial &divisor) const;
static ICorePolynomial fromRoots(const std::vector<ICoreComplexVariable> &roots);
std::vector<ICoreComplexVariable> roots() const;
ICoreMatrix companionMatrix() const;
bool isStableContinuous() const;
bool isStableDiscrete() const;
ICoreMatrix getCoefficients() const;
int getOrder() const;
void print(const std::string& varName = "x") const;
~ICorePolynomial();
};
ICoreSpline.h#
src/ICoreSDK/ICoreMath/Foundation/ICoreSpline.h
ICoreSpline#
ICoreSpline.h:9 · class · 1 declaration(s)
Interpolation through (x,y) sample points, backed by Eigen::Spline / Eigen::SplineFitting.
class ICoreSpline {
public:
// x, y: vectors of the same length (>= 2), x need not be evenly spaced but
// must be strictly increasing. xq: query points. degree: spline degree
// (default 3 = cubic); reduced automatically if there are too few points.
// Returns yq, one value per entry of xq.
static ICoreMatrix interp1(const ICoreMatrix& x, const ICoreMatrix& y, const ICoreMatrix& xq, size_t degree = 3);
};
};
ICoreTimeSeries.h#
src/ICoreSDK/ICoreMath/Foundation/ICoreTimeSeries.h
ICoreTimeSeries#
ICoreTimeSeries.h:24 · class · pImpl · 20 declaration(s)
A sampled signal: N time stamps and an N x M block of values, one column per channel.
class ICoreTimeSeries {
public:
// NOT `= default` any more: the residue at the bottom of this class is a
// unique_ptr, and a defaulted default constructor would leave it NULL --
// which compiles, links, and dereferences null on first use.
ICoreTimeSeries();
// The series is stored in the variables space and handed around by value,
// so it stays copyable; the unique_ptr residue deletes the implicit copy
// operations, so all four are written out in the .cpp.
ICoreTimeSeries(const ICoreTimeSeries& other);
ICoreTimeSeries& operator=(const ICoreTimeSeries& other);
ICoreTimeSeries(ICoreTimeSeries&& other) noexcept;
ICoreTimeSeries& operator=(ICoreTimeSeries&& other) noexcept;
~ICoreTimeSeries();
// Single-channel construction from parallel vectors.
ICoreTimeSeries(std::vector<double> times, std::vector<double> values);
// Multi-channel construction. valuesRowMajor holds times.size() * channels
// entries, sample-major. Produces an invalid series (isValid() == false)
// rather than throwing if the counts disagree.
ICoreTimeSeries(std::vector<double> times, std::vector<double> valuesRowMajor, size_t channels);
// The console constructor: an N-element time vector (either orientation) and
// an N x M value matrix. A 1 x N value row vector is accepted as N samples of
// one channel, since that is how a time-shaped vector is usually typed.
// Returns false with `error` set on any size mismatch, never a partial series.
static bool fromMatrices(const ICoreMatrix& time, const ICoreMatrix& values,
ICoreTimeSeries& out, std::string& error);
void clear();
void append(const double& time, const double& value); // single channel
void appendSample(const double& time, const std::vector<double>& channelValues);
void reserve(const size_t& expectedSamples);
// Drops the oldest samples until at most maxSamples remain. A recorder on a
// long or infinite run would otherwise grow without bound.
void truncateToMostRecent(const size_t& maxSamples);
[[nodiscard]] bool isValid() const; // one value row per time stamp
[[nodiscard]] bool isEmpty() const;
[[nodiscard]] size_t sampleCount() const;
[[nodiscard]] size_t channelCount() const;
[[nodiscard]] const std::vector<double>& getTimes() const;
// Flat, sample-major. For a single-channel series this is simply the values
// in order; for several channels the caller must stride by channelCount().
[[nodiscard]] const std::vector<double>& getValuesRowMajor() const;
// One channel's samples in order. Empty when the index is out of range.
[[nodiscard]] std::vector<double> getChannel(const size_t& channelIndex) const;
// Mean sample interval, or 0 when there are fewer than two samples. Only
// meaningful for a fixed-step run -- see the class note.
[[nodiscard]] double meanSamplingTime() const;
[[nodiscard]] ICoreMatrix getTimesAsColumnVector() const; // N x 1
[[nodiscard]] ICoreMatrix getValuesAsMatrix() const; // N x M
// [time, ch0, ch1, ...] as an N x (1 + M) matrix -- exactly the shape
// ICoreChart::plot() reads as "column 0 is X, every later column is a line".
[[nodiscard]] ICoreMatrix getAsTimeValueMatrix() const;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreQuaternion.h#
src/ICoreSDK/ICoreMath/Geometry/ICoreQuaternion.h
ICoreQuaternion#
ICoreQuaternion.h:9 · class · 10 declaration(s)
Rotation representation, backed by Eigen::Quaterniond / Eigen::AngleAxisd.
class ICoreQuaternion {
public:
// axis: 3x1 vector (need not be unit length); angle in radians.
// Returns a 4x1 quaternion [w,x,y,z].
static ICoreMatrix fromAxisAngle(const ICoreMatrix& axis, const double& angle);
// a,b,c: Euler angles in radians, applied about axis0 then axis1 then axis2
// (axis index: 0=x, 1=y, 2=z), matching Eigen's eulerAngles() convention.
// E.g. axis0=2,axis1=1,axis2=0 is the aerospace ZYX yaw-pitch-roll order.
// Returns a 4x1 quaternion [w,x,y,z].
static ICoreMatrix fromEuler(const double& a, const double& b, const double& c,
const size_t& axis0, const size_t& axis1, const size_t& axis2);
// R: 3x3 rotation matrix. Returns a 4x1 quaternion [w,x,y,z].
static ICoreMatrix fromRotationMatrix(const ICoreMatrix& R);
// q: 4x1 [w,x,y,z]. Returns a 3x3 rotation matrix.
static ICoreMatrix toRotationMatrix(const ICoreMatrix& q);
// q: 4x1 [w,x,y,z]. Returns a 3x1 vector of Euler angles about axis0,axis1,axis2.
static ICoreMatrix toEuler(const ICoreMatrix& q, const size_t& axis0, const size_t& axis1, const size_t& axis2);
// Hamilton product q1*q2: applying the result to a vector rotates by q2 first,
// then by q1 (i.e. composes "q1 after q2").
static ICoreMatrix multiply(const ICoreMatrix& q1, const ICoreMatrix& q2);
static ICoreMatrix conjugate(const ICoreMatrix& q);
static ICoreMatrix inverse(const ICoreMatrix& q);
static ICoreMatrix normalize(const ICoreMatrix& q);
// Spherical linear interpolation between q1 and q2, t in [0,1].
static ICoreMatrix slerp(const ICoreMatrix& q1, const ICoreMatrix& q2, const double& t);
// Rotate a 3x1 vector v by quaternion q.
static ICoreMatrix rotateVector(const ICoreMatrix& q, const ICoreMatrix& v);
};
};
ICoreRecursiveLeastSquares.h#
src/ICoreSDK/ICoreMath/Optimization/ICoreRecursiveLeastSquares.h
ICoreRecursiveLeastSquares#
ICoreRecursiveLeastSquares.h:18 · class · pImpl · 7 declaration(s)
Online (streaming) ARX transfer-function estimation via recursive least squares with a scalar exponential forgetting factor.
class ICoreRecursiveLeastSquares {
public:
// numOrder must be <= denOrder (causal/proper), matching ICoreTransferFunction's
// own causality requirement. forgettingFactor in (0, 1]; 1.0 = no forgetting.
ICoreRecursiveLeastSquares(const size_t& numOrder, const size_t& denOrder, const double& forgettingFactor = 1.0);
// Feeds one new (input, output) sample and updates the parameter estimate.
void update(const double& uk, const double& yk);
// Builds the currently-estimated transfer function (Ts = sampling time, must be > 0).
// CANONICAL: ICoreTransferFunction trims all-but-one leading zero coefficient, so
// the polynomials it hands back are as short as the estimate currently justifies —
// during warm-up, when theta is still all zeros, the numerator collapses to a single
// coefficient. Use it to display or to go on computing with; for anything that has a
// FIXED width to fill (a sized output port, a row of a collected matrix) use the two
// coefficient accessors below instead.
[[nodiscard]] ICoreTransferFunction getEstimatedTf(const double& Ts) const;
// The estimate in this class's own convention, always at full declared length:
// numerator descending [b0..b_numOrder] (numOrder+1 entries) and denominator
// descending monic [1, a1..a_denOrder] (denOrder+1 entries). Nothing is trimmed,
// so the lengths are a function of the configured orders alone and never of the
// values — which is what a fixed-size consumer needs, and what the generated
// code emits.
[[nodiscard]] std::vector<double> getNumeratorCoefficients() const;
[[nodiscard]] std::vector<double> getDenominatorCoefficients() const;
void reset();
// Declared, not implicit: the residue below is a unique_ptr to an Impl that
// is incomplete in this header, and only the .cpp can destroy one.
~ICoreRecursiveLeastSquares();
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreSystemIdentification.h#
src/ICoreSDK/ICoreMath/Optimization/ICoreSystemIdentification.h
ICoreSystemIdentification#
ICoreSystemIdentification.h:20 · class · nested Result · 5 declaration(s)
Fits a discrete-time transfer function of a chosen order to logged input/output data.
class ICoreSystemIdentification {
public:
// The estimators, grouped by family. They differ in what they minimize and
// in how much they cost, not in the model they return.
enum class Method {
// --- Output-error / prediction-error, nonlinear ---
NonlinearLeastSquares = 0, // default: Levenberg-Marquardt on simulation error
Armax, // pseudo-linear regression with a C(q) noise model
// --- Linear-regression family (closed form or a few linear solves) ---
ArxLeastSquares, // equation-error, one least-squares solve
InstrumentalVariables, // ARX bias removed with model-simulated instruments
SteiglitzMcBride, // iteratively 1/A-prefiltered ARX; approaches the OE optimum
// --- Realization / subspace (no initial guess, no local minima) ---
SubspaceN4SID, // PO-MOESP style projection + SVD of the block-Hankel data
ImpulseRealizationEra, // least-squares FIR, then Eigensystem Realization (ERA)
RegularizedFirKernel, // TC/stable-spline regularized FIR (GCV tuned), then ERA
// --- Frequency domain, fitted to the empirical transfer function ---
FrequencyDomainLevy, // Levy's linearized rational fit
SanathananKoerner, // Levy with 1/|A| iterative reweighting
};
// Outcome of a fit. `ok` false means nothing usable came back and `message`
// says why; `ok` true with a non-empty `message` is a warning worth showing
// (a solver that hit its iteration cap, a method that could not honour the
// requested numerator order exactly, ...).
struct Result {
bool ok = false;
std::string message;
double fitPercent = 0.0; // NRMSE fit of the simulated output, 100 = exact
};
// u, y: input/output sample vectors of equal length (same length, same Ts).
// numOrder, denOrder: numerator/denominator degrees, numOrder <= denOrder.
// Ts: sample time, must be > 0.
// `outTf` receives the fitted model; the return value carries the status.
static Result fit(const ICoreMatrix& u, const ICoreMatrix& y,
const size_t& numOrder, const size_t& denOrder, const double& Ts,
const Method& method, ICoreTransferFunction& outTf);
// Convenience wrapper kept for existing callers (the console's tfest() and
// the offline IIR identification block): fits with `method` and returns just
// the model, logging any failure through ICoreRunDiagnosis as before.
static ICoreTransferFunction fitTransferFunction(const ICoreMatrix& u, const ICoreMatrix& y,
const size_t& numOrder, const size_t& denOrder,
const double& Ts,
const Method& method = Method::NonlinearLeastSquares);
// Drives tf's state-space realization with input sequence u (a vector) and
// returns the simulated output, one sample per entry of u, starting from a
// zero initial state. tf must be discrete (Ts > 0).
static ICoreMatrix simulate(const ICoreTransferFunction& tf, const ICoreMatrix& u);
///////////////////////////////
/// Method naming (UI)
//////////////////////////////
// Display names in presentation order; index 0 is the default method.
static const std::vector<std::string>& methodDisplayNames();
static std::string methodDisplayName(const Method& method);
// Returns false when `name` matches no method, leaving `out` untouched.
static bool methodFromDisplayName(const std::string& name, Method& out);
// One-line description of what the method does, for a tooltip or hint line.
static std::string methodSummary(const Method& method);
};
};
ICoreFFT.h#
src/ICoreSDK/ICoreMath/SignalProcessing/ICoreFFT.h
ICoreFFT#
ICoreFFT.h:8 · class · 4 declaration(s)
Discrete Fourier transform of a logged/simulated signal, backed by Eigen::FFT (kissfft backend, bundled -- no external dependency).
class ICoreFFT {
public:
// signal: a row or column vector, N samples.
// Returns the complex spectrum as an N x 2 matrix: column 0 = real part,
// column 1 = imaginary part.
static ICoreMatrix forward(const ICoreMatrix& signal);
// spectrum: an N x 2 matrix [real, imag], as returned by forward().
// Returns the reconstructed N x 1 time-domain signal.
static ICoreMatrix inverse(const ICoreMatrix& spectrum);
// Magnitude / phase (radians) of forward(signal), each as an N x 1 vector.
static ICoreMatrix magnitude(const ICoreMatrix& signal);
static ICoreMatrix phase(const ICoreMatrix& signal);
};
};
ICoreFilterDesign.h#
src/ICoreSDK/ICoreMath/SignalProcessing/ICoreFilterDesign.h
ICoreFilterDesign#
ICoreFilterDesign.h:9 · class · 2 declaration(s)
Digital Butterworth filter design via the analog prototype + bilinear (Tustin) transform, with pre-warped band edges.
class ICoreFilterDesign {
public:
// order: filter order (>= 1). cutoffHz: -3 dB cutoff frequency, must be
// in (0, sampleRateHz/2). sampleRateHz: discrete sampling rate.
// Returns a discrete (Ts = 1/sampleRateHz) transfer function normalized
// to unity gain in the passband (DC for lowpass, Nyquist for highpass).
static ICoreTransferFunction butterworthLowpass(const size_t& order, const double& cutoffHz, const double& sampleRateHz);
static ICoreTransferFunction butterworthHighpass(const size_t& order, const double& cutoffHz, const double& sampleRateHz);
// Band-stop (notch) of the given prototype order, built with the
// lowpass-to-bandstop transform s -> B*s / (s^2 + w0^2). It nulls
// centerHz and passes everything either side of it.
//
// bandwidthHz is the -3 dB width of the stop band, and centerHz +/-
// bandwidthHz/2 must both fall inside (0, sampleRateHz/2). Each prototype
// pole becomes two, so the result has 2*order poles and 2*order zeros --
// order 1 is the classic two-pole/two-zero notch, and higher orders square
// up the shoulders without moving the null.
//
// The zeros land exactly on the unit circle at the centre frequency, so the
// attenuation there is total rather than merely deep (measured |H| at the
// centre is ~1e-13 for order 1, ~1e-10 for order 3, the residual being
// coefficient round-off from the repeated roots). Gain is normalized to
// unity at DC, which for a band-stop is in the passband.
//
// Note on the band edges: this filter shape is geometrically symmetric about
// the centre, which is two degrees of freedom -- not enough to place the null
// at centerHz AND both -3 dB points at centerHz +/- bandwidthHz/2. The null
// is kept exact, so the achieved -3 dB edges come out geometrically
// symmetric (sqrt(f_lo*f_hi) = centerHz) rather than arithmetically. Their
// separation still matches bandwidthHz -- within 0.01% for a narrow notch,
// and a few tenths of a percent for one spanning a large fraction of the
// band -- so the width you ask for is the width you get; only its placement
// shifts slightly downward relative to an arithmetic split.
static ICoreTransferFunction butterworthNotch(const size_t& order, const double& centerHz,
const double& bandwidthHz, const double& sampleRateHz);
};
};
ICoreControlSystemsFormatting.h#
src/ICoreSDK/ICoreMath/SyntaxFromatting/ICoreControlSystemsFormatting.h
ICoreControlSystemsFormatting#
ICoreControlSystemsFormatting.h:21 · class · 9 declaration(s)
String <-> object conversions for the control-systems types, the analog of ICoreMatlabFormatting for ICoreMatrix.
class ICoreControlSystemsFormatting {
public:
static std::pair<bool, ICorePolynomial> parsePolynomial(const std::string& s);
static std::pair<bool, ICoreTransferFunction> parseTransferFunction(const std::string& s);
static std::pair<bool, ICoreStateSpace> parseStateSpace(const std::string& s);
static std::string toCanonical(const ICorePolynomial& p);
static std::string toCanonical(const ICoreTransferFunction& tf);
static std::string toCanonical(const ICoreStateSpace& ss);
static std::string pretty(const ICorePolynomial& p);
static std::string pretty(const ICoreTransferFunction& tf);
static std::string pretty(const ICoreStateSpace& ss);
};
};
ICoreCppFormatting.h#
src/ICoreSDK/ICoreMath/SyntaxFromatting/ICoreCppFormatting.h
Convert ICoreMatrix to C++ initializer list format Example: { {1, 2}, {3, 4} }
ICoreCppFormatting#
ICoreCppFormatting.h:6 · class · 2 declaration(s)
class ICoreCppFormatting {
public:
// Convert ICoreMatrix to C++ initializer list format
// Example: { {1, 2}, {3, 4} }
static std::string convertToCppFormat(const ICoreMatrix& matrix);
// Convert C++ initializer list string to ICoreMatrix
// Returns: {matrix, error_message}
static std::pair<ICoreMatrix, std::string> convertFromCppFormat(const std::string& input);
};
};
ICoreMatlabFormatting.h#
src/ICoreSDK/ICoreMath/SyntaxFromatting/ICoreMatlabFormatting.h
ICoreMatlabFormatting#
ICoreMatlabFormatting.h:7 · class · 3 declaration(s)
class ICoreMatlabFormatting {
public:
// Pattern for matching valid Matlab number strings
inline static const std::regex NUMBER_PATTERN =
std::regex(R"(^[+-]?(NaN|Inf|(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$))");
// Convert 2D vector of doubles to MATLAB string format
static std::string convertToMatlabFormat(const ICoreMatrix& mat);
// Convert Matlab string format to a pair of 2D double vector and error string
static std::pair<ICoreMatrix, std::string> convertFromMatlabFormat(const std::string& matlabStr);
};
};
ICorePythonFormatting.h#
src/ICoreSDK/ICoreMath/SyntaxFromatting/ICorePythonFormatting.h
ICorePythonFormatting#
ICorePythonFormatting.h:6 · class · 2 declaration(s)
class ICorePythonFormatting {
public:
static std::string convertToPythonFormat(const ICoreMatrix& matrix);
static std::pair<ICoreMatrix, std::string> convertFromPythonFormat(const std::string& str);
};
};
ICoreTimeSeriesFormatting.h#
src/ICoreSDK/ICoreMath/SyntaxFromatting/ICoreTimeSeriesFormatting.h
ICoreTimeSeriesFormatting#
ICoreTimeSeriesFormatting.h:22 · class · 3 declaration(s)
String <-> ICoreTimeSeries conversion, the same three roles as ICoreControlSystemsFormatting has for tf/ss/poly: parse : detect + build from a stored/console string (for assignType) toCanonical: re...
class ICoreTimeSeriesFormatting {
public:
static std::pair<bool, ICoreTimeSeries> parse(const std::string& s);
static std::string toCanonical(const ICoreTimeSeries& series);
// "Time Series (241 samples, t = 0 .. 2.4)" -- the table shows this rather
// than thousands of numbers.
static std::string pretty(const ICoreTimeSeries& series);
};
};