//! # entropyk-solver-core
//!
//! no_std-ready core types for the Entropyk solver: the typed
//! [`ConvergenceReason`] taxonomy and the shared error types that every solver
//! crate (full solver, diagnostics, lite embedded variant) builds upon.
//!
//! ## Design rule: outcomes are data, not exceptions
//!
//! Following the PETSc/IPOPT consensus, a solve that terminates without
//! reaching tolerance (max iterations, stall, line-search failure, singular
//! Jacobian, domain violation, timeout, likely-no-solution) is a **typed
//! outcome** carried by [`ConvergenceReason`], not a hard `Err`. "No physical
//! solution exists" is a *reason*, not an exception (IPOPT reports
//! `Infeasible_Problem_Detected` as a non-negative status). Hard errors —
//! API misuse, invalid system definition, internal invariant violations —
//! remain `Err` variants ([`SolverCoreError`]).
//!
//! ## Feature tiers (std / alloc / core)
//!
//! | Tier | Enabled by | Contents |
//! |------|-----------|----------|
//! | `std` (default) | `std` feature | everything |
//! | `alloc` | `alloc` feature (no `std`) | [`ConvergenceReason`], [`SolverCoreError`], [`DomainViolation`], [`SolveOutcome`], [`LinearSolver`] |
//! | pure `core` | `--no-default-features` | [`ConvergenceReason`] only |
//!
//! `ConvergenceReason` is pure-`core` (copyable, allocation-free) so the lite
//! embedded solver (Epic 6) can report outcomes on `thumbv7em-none-eabihf`.
//! Message-carrying error types require `alloc`. The `std` tier only adds
//! `std::error::Error` integration via thiserror's `std` feature.
//!
//! ## Example
//!
//! ```
//! use entropyk_solver_core::ConvergenceReason;
//!
//! let reason = ConvergenceReason::MaxIters;
//! assert!(!reason.is_converged());
//! assert_eq!(reason.as_str(), "max_iters");
//! assert_eq!(reason.to_string(), "max_iters");
//! ```

#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(feature = "alloc")]
extern crate alloc;

pub mod reason;

#[cfg(feature = "alloc")]
pub mod error;

#[cfg(feature = "alloc")]
pub mod linear;

pub use reason::ConvergenceReason;

#[cfg(feature = "alloc")]
pub use error::{DomainViolation, SolveOutcome, SolverCoreError};

#[cfg(feature = "alloc")]
pub use linear::LinearSolver;
