Janus 2.0.0
High-performance C++20 dual-mode numerical framework
Loading...
Searching...
No Matches
Numeric Computing

Janus is designed to be "Template-First": you write your physics and math logic using generic templates (T), and compile them into highly optimized machine code using the Numeric Backend (standard double and Eigen). Numeric mode provides zero-overhead math calls and Eigen's optimized expression templates with vectorization (AVX, SSE). This guide covers writing generic code, numeric execution, linear algebra, and performance tips for the numeric path.

Quick Start

#include <janus/janus.hpp>
// Write a generic function using janus:: math
template <typename Scalar>
Scalar my_physics(const Scalar& x) {
return janus::sin(x) + janus::pow(x, 2.0);
}
// Instantiate with double for numeric execution
double result = my_physics(10.0);
std::cout << "Result: " << result << std::endl;
Umbrella header that includes the entire Janus public API.
T sin(const T &x)
Computes sine of x.
Definition Trig.hpp:21
T pow(const T &base, const T &exponent)
Computes the power function: base^exponent.
Definition Arithmetic.hpp:72

Core API

  • janus::NumericScalar: Alias for double.
  • janus::NumericMatrix: Alias for Eigen::MatrixXd.
  • janus::JanusScalar Concept: A C++20 concept that matches both numeric and symbolic scalar types. Use this for templating your functions.
  • janus::solve(A, b) -> Uses the default backend policy (ColPivHouseholderQR for dense numeric matrices, CasADi default for symbolic, SparseLU for sparse numeric input).
  • janus::solve(A, b, policy) -> Select dense direct, sparse direct, or iterative Krylov backends explicitly with janus::LinearSolvePolicy.
  • janus::inv(A) -> Uses inverse().
  • janus::det(A) -> Uses determinant().

Usage Patterns

Writing Generic Code

To support both numeric and symbolic modes, write your functions as templates:

template <typename Scalar>
Scalar my_physics(const Scalar& x) {
// Use janus:: math namespace, NOT std::
return janus::sin(x) + janus::pow(x, 2.0);
}

Numeric Execution

When you instantiate your template with double (or janus::NumericScalar), Janus compiles down to direct C++ math calls and Eigen operations.

  • Zero Overhead: janus::sin directly calls std::sin.
  • Eigen Speed: Matrix operations use Eigen's optimized expression templates and vectorization (AVX, SSE).
// Instantiation
double result = my_physics(10.0);

Linear Algebra

Janus provides wrappers for common linear algebra operations that work for both backends. In numeric mode, these delegate directly to efficient Eigen Decompositions.

janus::NumericMatrix A = /* ... */;
janus::NumericVector b = /* ... */;
// Default solver (ColPivHouseholderQR for dense)
auto x = janus::solve(A, b);
// Explicit policy selection
auto x2 = janus::solve(A, b, janus::LinearSolvePolicy::SparseDirect);
JanusMatrix< NumericScalar > NumericMatrix
Eigen::MatrixXd equivalent.
Definition JanusTypes.hpp:66
JanusVector< NumericScalar > NumericVector
Eigen::VectorXd equivalent.
Definition JanusTypes.hpp:67
auto solve(const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &b)
Solves linear system Ax = b using the default backend policy.
Definition Linalg.hpp:408

Advanced Usage

  • Avoid auto types in return signatures of public APIs if you can use Scalar or JanusMatrix<Scalar>.
  • Use janus::where instead of if/else: This ensures your code works in symbolic mode and compiles to efficient branchless select instructions (where possible) in numeric mode.
  • Pass by Reference: const Scalar& avoids copying expensive types in symbolic mode, and is negligible for doubles.

See Also