NAN and INF Handling

MtxVec disables floating-point exceptions by default, so NAN and INF values propagate silently through calculations instead of raising exceptions.

Default behavior:

  • Division by zero → INF (not an exception)
  • 0/0 → NAN (not an exception)
  • sqrt(-1) → NAN (not an exception)
  • NAN in any operation → NAN result (propagates)

Checking for NAN/INF on individual values:

In C++, IsNaN, IsInf and IsInfNan take double, TCplx and TSCplx; the float versions are named IsNanf, IsInff and IsInfNanf.

bool isNan = IsNaN(value);       // Math387 IsNaN: double, TCplx, TSCplx
bool isInf = IsInf(value);       // Math387 IsInf: the same three overloads
bool isBad = IsInfNan(value);    // either NAN or INF

float single = NAN_SINGLE;
bool singleNan = IsNanf(single); // float versions: IsNanf, IsInff, IsInfNanf

Finding and cleaning NAN/INF across a vector or matrix:

MtxVec does not expose a HasNAN / HasInf property. Instead it provides two bulk operations that both detect and act on the bad values in a single pass:

  • ReplaceNAN(Value) on TDenseMtxVec — replaces every NAN element with Value in-place. Use 0.0 (or any sentinel) to neutralize NANs before further processing.
  • StripNanAndInf(Src) on TVec — copies Src into self, dropping every NAN / INF element and compacting the result. The count overload returns the number of valid elements kept, so you can detect the presence of bad values by checking whether the returned length is shorter than Src.Length.
// Replace any NANs with a safe value
a.ReplaceNAN(0.0);

// Compact and detect contamination in one call
Vector cleaned;
cleaned.Size(a);                 // the indexed form writes into existing elements
int kept = cleaned.StripNanAndInf(a, 0, 0, a.GetLength());
if (kept < a.GetLength())
{
    // `a` contained NAN or INF elements
}

If all you need is a fast "does this array contain any bad value" check without modifying the data, loop the scalar IsInfNan over the underlying Values1D array — in practice StripNanAndInf into a scratch buffer and compare lengths is almost always faster and more readable.

Why FP exceptions are disabled: SSE/AVX vectorized operations cannot raise exceptions mid-stream — they set status flags instead. MtxVec aligns with this hardware behavior. If exceptions were enabled, switching between scalar and vectorized code paths would produce inconsistent behavior.

Re-enabling FP exceptions (not recommended):

// C++: floating-point exceptions are masked by default (the C runtime
// default, which MtxVec keeps), so NAN/INF propagate silently.
// MtxVec has no call to unmask them; use the compiler runtime,
// e.g. _controlfp_s from <float.h> with the Microsoft C runtime:
unsigned int previous = 0;
_controlfp_s(&previous, 0, _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW);  // unmask
// ... debug code ...
_controlfp_s(&previous, _MCW_EM, _MCW_EM);                                // mask all again

In C++ the constants below are variables in Dew::Math::Units::Math387: NAN, INF, CNAN and CINF, plus the single-precision NAN_SINGLE, INF_SINGLE, CNAN_SINGLE and CINF_SINGLE. There is no NEGINF variable; write -INF.

ConstantTypeDescription
NANDoubleNot-a-number
INFDoublePositive infinity
NEGINFDoubleNegative infinity
CNANTCplxComplex NaN
CINFTCplxComplex infinity

Best practice: Check for NAN/INF at algorithm boundaries (input validation, final output), not at every intermediate step. Let NAN/INF propagate through calculations — if the final result is NAN, trace back to find the source.