# Native Validation Matrix
This note summarizes the current validation behavior of the native `f64` and `Complex<f64>` implementations used through `RealScalar` and `ComplexScalar`.
Scope:
- native `f64` paths wired through `RealScalar`
- native `Complex<f64>` paths wired through `ComplexScalar`
- related fallible `Pow` implementations for `f64` and `Complex<f64>`
It does not cover the validated wrapper types (`RealValidated<K>`, `ComplexValidated<K>`), whose behavior is stricter by design.
## Summary
The current native API is not uniform.
- Some entry points always validate in both debug and release.
- Some `try_*` methods now validate only in debug and return direct native results in release.
- Some panicking variants validate in debug but skip structured validation in release.
- Some mutating complex-part methods only use `debug_assert!`, so they validate only in debug builds.
- Many native mathematical delegates do no explicit validation at all and rely on the underlying `f64` or `Complex<f64>` behavior.
## `RealScalar` for `f64`
| `try_from_f64` | [src/backends/native/raw.rs](../../src/backends/native/raw.rs#L471) | Yes | No | Yes, same validation path | No | In debug it uses `validate_native_scalar()` and rejects NaN/infinities/subnormals; in release it currently returns `Ok(value)` directly. |
| `from_f64` default trait method | [src/lib.rs](../../src/lib.rs#L1305) | Yes | No | Yes | No | Delegates to `try_from_f64(...).expect(...)`; for native `f64`, release behavior follows `try_from_f64` and can therefore accept invalid values. |
| `Abs::try_abs` and `Abs::try_abs_squared` for `f64` | [src/functions/abs.rs](../../src/functions/abs.rs#L200) | Yes | No | Yes | No | In debug they validate input/output via `validate_native_scalar()`; in release they return `Ok(...)` from direct numeric operations. |
| `Exp::try_exp` for `f64` | [src/functions/exponential.rs](../../src/functions/exponential.rs#L145) | Yes | No | Yes | No | In debug it validates input/output via `validate_native_scalar()`; in release it returns `Ok(f64::exp(value))`. |
| `Ln::try_ln`, `Log10::try_log10`, `Log2::try_log2` for `f64` | [src/functions/logarithm.rs](../../src/functions/logarithm.rs#L237) | Yes | No | Yes | No | In debug they validate input/output and enforce domain checks; in release they return direct backend results in `Ok(...)`. |
| Hyperbolic `try_*` for `f64` (`try_sinh`, `try_cosh`, `try_tanh`, `try_asinh`, `try_acosh`, `try_atanh`) | [src/functions/hyperbolic.rs](../../src/functions/hyperbolic.rs#L256) | Yes | No | Yes | No | In debug they validate and enforce domain checks where applicable; in release they return direct backend results in `Ok(...)`. |
| `Pow<&f64>::try_pow` | [src/functions/pow.rs](../../src/functions/pow.rs#L356) | Yes | Yes | Yes | Yes | Validates base and exponent, checks negative base domain, validates output via `validate_native_scalar()`. |
| `Pow<&f64>::pow` | [src/functions/pow.rs](../../src/functions/pow.rs#L394) | Yes | No structured validation | Yes via `try_pow().unwrap()` | No structured validation | In release it calls `powf` directly. |
| `Sign`, `Rounding`, `Clamp`, `Classify`, `ExpM1`, `Hypot`, `Ln1p`, `TotalCmp`, `Constants` | [src/backends/native/raw.rs](../../src/backends/native/raw.rs#L160) | No explicit validation | No explicit validation | No explicit validation | No explicit validation | Direct delegation to native operations or constants. |
| `kernel_mul_add_mul_mut`, `kernel_mul_sub_mul_mut` | [src/backends/native/raw.rs](../../src/backends/native/raw.rs#L450) | No explicit validation | No explicit validation | No explicit validation | No explicit validation | Pure arithmetic delegate. |
## `ComplexScalar` for `Complex<f64>`
| `try_new_complex` | [src/backends/native/raw.rs](../../src/backends/native/raw.rs#L485) | Yes | Yes | Yes | Yes | Uses `validate_complex_from_parts`, therefore validates both parts through the strict-finite native real policy. |
| `Abs::try_abs` and `Abs::try_abs_squared` for `Complex<f64>` | [src/functions/abs.rs](../../src/functions/abs.rs#L320) | Yes | No | Yes | No | In debug they validate complex input and real output; in release they return `Ok(self.norm())` / `Ok(self.norm_sqr())` directly. |
| `Exp::try_exp` for `Complex<f64>` | [src/functions/exponential.rs](../../src/functions/exponential.rs#L242) | Yes | No | Yes | No | In debug it validates input/output via `validate_native_scalar()`; in release it returns `Ok(num::Complex::exp(value))`. |
| `Ln::try_ln`, `Log10::try_log10`, `Log2::try_log2` for `Complex<f64>` | [src/functions/logarithm.rs](../../src/functions/logarithm.rs#L295) | Yes | No | Yes | No | In debug they validate input/output and enforce zero-domain checks; in release they return direct backend results in `Ok(...)`. |
| Hyperbolic `try_*` for `Complex<f64>` (`try_sinh`, `try_cosh`, `try_tanh`, `try_asinh`, `try_acosh`, `try_atanh`) | [src/functions/hyperbolic.rs](../../src/functions/hyperbolic.rs#L256) | Yes | No | Yes | No | In debug they validate and enforce domain checks where applicable; in release they return direct backend results in `Ok(...)`. |
| `new_complex`, `new_pure_real`, `new_pure_imaginary` default trait methods | [src/functions/complex.rs](../../src/functions/complex.rs#L47) | Yes | Yes | Yes | Yes | They delegate to the fallible constructors and unwrap. |
| `set_real_part`, `set_imaginary_part` | [src/backends/native/raw.rs](../../src/backends/native/raw.rs#L538) | Yes, via `debug_assert!` only | No | Yes, via `debug_assert!` on assigned value only | No | These are debug-only finiteness guards. |
| `add_to_real_part`, `add_to_imaginary_part` | [src/backends/native/raw.rs](../../src/backends/native/raw.rs#L572) | No explicit input validation; debug-only post-check | No | Yes, via `debug_assert!` on resulting component | No | In release these operations can leave non-finite parts unchecked. |
| `multiply_real_part`, `multiply_imaginary_part` | [src/backends/native/raw.rs](../../src/backends/native/raw.rs#L602) | No explicit input validation; debug-only post-check | No | Yes, via `debug_assert!` on resulting component | No | Same pattern as additive mutators. |
| `ComplexScalar::into_parts` | [src/backends/native/raw.rs](../../src/backends/native/raw.rs#L631) | No | No | No | No | Pure extraction. |
| `Pow<&f64>::try_pow` for `Complex<f64>` | [src/functions/pow.rs](../../src/functions/pow.rs#L413) | Yes | Yes | Yes | Yes | Validates base and exponent; validates output with `StrictFinitePolicy::<Complex<f64>, 53>::validate(...)`. |
## What The Documentation Says
### Statements that match the implementation
| `RealScalar` native backend description | [src/lib.rs](../../src/lib.rs#L1183) | Accurate at high level: it describes the native `f64` backend as direct delegation with maximum performance, which is consistent with many non-fallible native methods not validating explicitly. |
| `Pow` trait documentation | [src/functions/pow.rs](../../src/functions/pow.rs#L330) | Accurate: it explicitly says the panicking variant may validate in debug and may call the underlying power function directly in release. |
| `ComplexScalarConstructors::try_new_complex` docs | [src/functions/complex.rs](../../src/functions/complex.rs#L39) | Accurate: it states that invalid components return an error, which matches the implementation. |
### Statements that are too strong or incomplete
| `ComplexScalar` trait overview | [src/lib.rs](../../src/lib.rs#L1425) | Slightly too strong semantically: it describes a type-safe, validated context, but the native `Complex<f64>` mutators do not preserve strict runtime validation in release builds. |
| `ComplexScalarSetParts` docs | [src/functions/complex.rs](../../src/functions/complex.rs#L167) | Incomplete: it explains mutation semantics but does not say the native implementation only checks finiteness with `debug_assert!`. |
| `ComplexScalarMutateParts` docs | [src/functions/complex.rs](../../src/functions/complex.rs#L217) | Incomplete: it presents the operations as safe in-place utilities, but the native implementation performs only debug-only finiteness checks after mutation. |
## Practical Interpretation
Today the codebase effectively exposes two different behavioral classes for native scalars.
1. Validation behavior for native fallible APIs is mixed: `try_from_f64`, `try_abs*`, `try_exp`, logarithm `try_*`, and hyperbolic `try_*` are currently debug-only validated, while `try_pow` still validates in release.
2. Native direct delegates and complex-part mutators are performance-oriented APIs, with some checks downgraded to `debug_assert!`.
So the observed difformity is real, especially for `Complex<f64>` mutators and for the difference between `try_pow` and `pow`.