Open-source agentic AI for transaction monitoring. Just ask Jooby.What's Jube? →

Numerics and optimisation tool catalogue

Jube.Service/Agent/AdvancedAnalyticsTools/NumericsAndOptimisation is the largest of the ten AdvancedAnalyticsTools groups: 132 methods, each exposed to the LLM agent under the literal name in its [AdvancedAnalyticsTool("...")] attribute, covering calculus and root finding, combinatorics and array utilities, linear algebra, matrix decompositions, optimisation, and the special functions that the statistical tool layer is built on. None of these 132 names appears in docs/AgentHierarchy/tool-inventory.md or anywhere else in docs/, so Jadek, the validator agent that fact-checks every AskJooby reply against the RAG-indexed corpus built from docs/, has no page to confirm a claim about any of them against except this one. This page covers every tool, grouped by the six source files that define them (NumericsGuard.cs, NumericsShared.cs and NumericsText.cs hold shared validation and function-family plumbing, not tools in their own right). Two tools, SortValuesWithOriginalIndices and SortValuesByKeys, already had genuine behavioural coverage elsewhere, in Data Frames vs. Accord Arrays and Loading, Shaping and Merging; they are documented here in full as well, for a single point of reference, with that prior coverage cited in place.

Every tool in this group validates its inputs through NumericsGuard before doing any numerical work: arrays must be non-null and within a maximum length, matrices must be rectangular (and square, symmetric or finite as the tool requires), and most numeric inputs are rejected outright if NaN or infinite rather than silently propagated. Several tools share built-in function families defined once in NumericsShared.cs: NumericsUnivariateFunction (polynomial, sine, cosine, exponential, natural log, square root, power, reciprocal, Gaussian, logistic, hyperbolic tangent, absolute value) for one-variable work, and NumericsObjectiveFunction (Sphere, Rosenbrock, Rastrigin, Ackley, Himmelblau, Booth, Beale, Matyas, Styblinski-Tang, Griewank, and a general Quadratic form) for multi-variable optimisation and calculus tools. Where a tool takes one of these, its exact parameter defaults and domain are given in the shared NumericsText.Function and NumericsText.Objective description strings rather than repeated per tool.

CalculusAndRootFindingTools

EvaluateNamedFunction evaluates one of the twelve built-in one-variable functions at each of a supplied array of x values and returns the values as a NumericsVectorResult, with a separate NonFiniteCount so a caller can see how many points fell outside the function’s domain (for example a negative x fed to NaturalLog, which produces NaN there) without having to scan the array. It is the inspection step before integrating, differentiating or root-finding the same function. Up to 200,000 x values are accepted.

IntegrateTrapezoidalRule approximates the definite integral of a built-in function from lower to upper with the composite trapezoidal rule over a chosen number of equal steps (default 1,000, capped at 1,000,000). It is only second-order accurate, so halving the step only quarters the error; it exists as a simple, robust baseline to compare against IntegrateRomberg or IntegrateGaussKronrod. The result never reports an error estimate (ErrorEstimate is always NaN) and Converged is simply whether the computed area came out finite.

IntegrateRomberg approximates the same kind of integral by Romberg’s method: repeated step-halving combined with Richardson extrapolation, which reaches very high accuracy on smooth functions with far fewer evaluations than the trapezoidal rule, at the cost of being unsuitable for functions with kinks or singularities inside the interval. The steps parameter (default 10, 2 to 30) is the number of refinement levels, and FunctionEvaluations in the result is derived as 2^(steps-1) + 1 rather than counted directly.

IntegrateGaussKronrod integrates a built-in function over a finite interval with a non-adaptive Gauss-Kronrod rule, driven to a target relative tolerance (default 1e-8, allowed 1e-14 to 0.1) via Accord’s NonAdaptiveGaussKronrod. It is the recommended default accurate integrator for smooth functions: Area is the estimate, ErrorEstimate the library’s own absolute error bound, and Status is Success when the tolerance was met or MaximumSteps when the best available estimate was returned without reaching it.

IntegrateAdaptiveGaussKronrodInfinite integrates a built-in function over a range where either or both ends may be infinite (lowerIsInfinite / upperIsInfinite, each default false — when set, the matching finite lower or upper argument is simply ignored), using adaptive Gauss-Kronrod subdivision capped at subintervals (default 200, up to 2,000). This is the tool for tail probabilities and expectations over the whole real line, for example integrating a Gaussian end to end. Converged requires both that the solver reported success and that the resulting Area is finite, since a genuinely divergent integral can otherwise report numeric success with an infinite value.

IntegrateMonteCarloOnInterval estimates a one-dimensional integral by averaging the function at uniformly random points drawn with a seed (default 1) for reproducibility, over samples (default 100,000, up to 5,000,000) draws. It is unbiased but converges only as the square root of the sample count, so it is a fallback rather than the preferred one-dimensional method; ErrorEstimate is the Monte Carlo one-standard-error uncertainty from Accord’s MonteCarloIntegration.

IntegrateMonteCarloObjectiveOverBox is the multi-variable counterpart: it integrates a built-in NumericsObjectiveFunction (including the Quadratic family, via quadraticMatrix, linearTerms and constantTerm) over an axis-aligned box defined by one lowerBounds/upperBounds pair per variable, by uniform random sampling. The number of variables is implied by the length of the bounds arrays (1 to 50), and this is the practical route once dimensionality is too high for grid-based quadrature.

NumericalDerivativeOfNamedFunction estimates the derivative of a built-in function at a point x by central finite differences, for order 1 (slope) through 4, using an odd number of stencil points (3 to 9, default 5, must exceed the order) and a relative stepSize (default 0.01, 1e-8 to 1). The accuracy trade-off is explicit in the description: too small a step amplifies rounding error, too large a step adds truncation error, and more stencil points buys accuracy at the cost of more function evaluations.

NumericalGradientOfObjective estimates the gradient vector of a built-in multi-variable objective at a point (up to 50 variables) by the same finite-difference machinery, returning a NumericsVectorResult with one entry per variable. Because the gradient is zero at a stationary point, this is the tool for checking whether a candidate optimum returned by one of the Minimise* tools is genuinely stationary; expect rounding error around 1e-6 relative with the default step size and stencil.

NumericalHessianOfObjective estimates the full matrix of second partial derivatives of a built-in objective at a point (up to 20 variables, a tighter cap than the gradient because the Hessian needs nested differencing) using a stepSize between 1e-6 and 1 (default 0.01). The result is symmetric and describes local curvature: positive definite at a minimum, negative definite at a maximum, indefinite at a saddle; pairing it with SymmetricEigenDecomposition reveals the actual curvature directions.

NumericalJacobianOfVectorFunction estimates the Jacobian of one of five built-in vector-valued functions (PolarToCartesian, SphericalToCartesian, Softmax, RosenbrockResiduals, HimmelblauResiduals) at a point, with each function requiring a specific point length (2 for polar/Rosenbrock/Himmelblau, 3 for spherical, any length for Softmax) that is checked and rejected with a specific error if wrong. Row i, column j of the returned matrix is the derivative of output i with respect to input j, computed with a 5-point stencil regardless of the step-size parameter passed.

FindRootBrent finds a root of a built-in function on [lower, upper] using Brent’s method (a combination of bisection, secant and inverse quadratic interpolation that is guaranteed to converge once a sign change is bracketed). If f(lower) - target and f(upper) - target do not have opposite signs, Status comes back RootNotBracketed rather than throwing; FindRootBracketsByScanning is the companion tool for locating a bracketing interval first. Iterations are capped at 500 and tolerance at 1e-14 to 1 (default 1e-10).

FindRootBracketsByScanning scans [lower, upper] on an even grid of gridPoints (default 1,000, up to 200,000) and reports every sub-interval where f(x) - target changes sign, each of which is a valid input to FindRootBrent, plus a separate ExactZeros list for grid points landing exactly on a root. Because it only detects a sign change between adjacent grid points, two roots closer together than the grid spacing inside one cell cancel and are missed entirely — a real limitation worth flagging to a caller scanning an oscillating function with too coarse a grid.

FindExtremumBrent finds one local minimum or maximum (maximise, default false) of a built-in function on [lower, upper] with Brent’s derivative-free golden-section-with-parabolic-steps method. It finds a single local extremum assuming the function is unimodal on the interval, not necessarily the global one; Converged false means the 500-iteration cap (default tolerance 1e-8) was exhausted before the acceptance criterion was met.

EvaluatePolynomial evaluates c0 + c1 x + c2 x^2 + ... at each of a supplied x array using Horner’s scheme for numerical stability, with coefficients ordered from the constant term upward (up to 40 coefficients, 200,000 points).

PolynomialDerivativeOrAntiderivative returns the coefficient array of either the derivative or the antiderivative (NumericsPolynomialCalculus.Derivative or .Antiderivative, default Derivative) of a polynomial. The derivative of a single-coefficient (constant) polynomial returns the single coefficient 0; the antiderivative takes an explicit constant of integration (default 0) as its new leading (constant) term and is capped at 39 input coefficients so the result still fits the 40-coefficient limit.

PolynomialMultiply multiplies two polynomials given as coefficient arrays (constant term first, each capped at 20 coefficients) by direct convolution, returning a coefficient array whose length is a.Length + b.Length - 1, i.e. the product’s degree is the sum of the two input degrees.

PolynomialRoots finds every real and complex root of a polynomial by building its companion matrix and taking its eigenvalues (via JaggedEigenvalueDecomposition). The leading (highest-degree) coefficient must be non-zero — trailing zero coefficients should be dropped to lower the degree rather than left in — and results are returned as parallel RealParts/ImaginaryParts arrays sorted by real then imaginary part, where a non-zero imaginary part signals a complex-conjugate pair. The description is explicit that accuracy degrades for high degrees or repeated roots; degree is capped at 30.

FitPolynomialByLeastSquares fits a polynomial of a chosen degree (0 to 15) to (x, y) points by ordinary least squares via a Vandermonde design matrix solved with Solve(y, true), returning the fitted Coefficients and the ResidualSumOfSquares. There must be strictly more points than the degree (an explicit check throws naming the exact shortfall), and the description warns that high degrees over a wide x range are ill-conditioned, recommending the caller centre and scale x first; EvaluatePolynomial is the natural pairing for prediction afterward.

InterpolatePolynomialThroughPoints builds the unique degree-(n-1) polynomial passing exactly through n points with distinct x values (duplicate x values are rejected outright), solving the resulting Vandermonde system exactly. It is intended for small tables only — at most 20 points — because high-degree interpolation through many points oscillates wildly between the nodes (Runge’s phenomenon) and the system becomes severely ill-conditioned.

InterpolateLinearly estimates y at each of a queries array by piecewise linear interpolation between sorted, strictly increasing (x, y) points (the strict-increase check throws naming the offending pair). Queries below the first x or above the last return the caller-supplied belowValue/aboveValue (both default NaN) rather than extrapolating, so the tool never silently extends the data; passing the edge y values instead holds the curve flat beyond the data range.

ExtrapolateLinearly is the complement: for queries outside the sorted, strictly increasing data range, it extends the line through the nearest end segment (first two or last two points) rather than returning a sentinel; queries inside the range interpolate normally on whichever segment they fall in. The description is explicit that this should only be used for short extrapolation distances, since most real relationships stop being linear further out.

CombinatoricsAndUtilityTools

EnumeratePermutations lists orderings of up to 10 supplied values, one ordering per output row, capped at maxResults (default 1,000, up to 20,000); TotalCount is the true n! regardless of truncation, and duplicate input values still occupy distinct positions, so a repeated value produces repeated rows rather than being deduplicated.

EnumerateCombinations lists every way to choose k of up to 25 supplied values without regard to order, one selection per row, again capped at maxResults with TotalCount reporting the true n choose k via Special.Binomial.

EnumerateSubsets lists every non-empty subset of up to 20 supplied values (including the full set itself), with TotalCount equal to 2^n - 1; rows vary in length since subsets of different sizes are mixed together in output order.

EnumerateSequences lists every sequence of a given length (1 to 12) over an alphabet of symbols (2 to 20) numbered 0 to symbols - 1, the Cartesian power with symbols^length total sequences, useful for exhaustively gridding small categorical configurations.

GenerateTruthTable returns every combination of 0/1 values for a given number of boolean inputs (1 to 14) in counting order, 2^inputs rows in total with no truncation possible (there is no maxResults parameter — the input cap of 14 already bounds the output to 16,384 rows).

CountCombinatorialObjects counts arrangements without enumerating them, for any of five kind values: Permutations (n!), PartialPermutations (n!/(n-k)!, ordered picks), Combinations (n choose k), CombinationsWithRepetition ((n+k-1) choose k), and Sequences (n^k). Count is computed from a log-space intermediate so it stays a finite double (or correctly reports Infinity on true overflow) even where the exact integer would not fit; NaturalLogOfCount always stays finite, and IsExact is true only when the log is below 30 (count under roughly 10 trillion), below which the count is rounded to the exact integer and above which it is accurate only to about 12 significant digits. n and k are each capped at 1,000,000, and k > n for PartialPermutations/Combinations returns an exact zero count rather than throwing.

GreatestCommonDivisorAndLeastCommonMultiple computes, for each pair taken from two equal-length integer arrays (values capped at ±1,000,000,000, up to 100,000 pairs), both the GCD and LCM, returned concatenated in one NumericsVectorResult — all GCDs first, then all LCMs in the same order. gcd(0, x) is defined as |x|, and the LCM of any pair involving zero is 0.

EuclideanModulo computes the mathematical modulo x mod m, which is always in [0, m) for a positive modulus, unlike the C#/most languages’ % remainder operator which can return a negative result for negative x. It accepts fractional x and requires a strictly positive modulus; the intended uses given are wrapping angles, hours or cyclic indices.

PowerOfTwoProperties reports, for each positive integer in values (1 to 1,073,741,823, up to 100,000 values), four facts packed back-to-back into one Values array: the next power of two at or above it, the previous power of two at or below it, ceil(log2(value)) (bits needed), and a 1/0 flag for whether it is itself a power of two — aimed at sizing FFT buffers or hash tables.

FindIntegerByBinarySearch finds the integer in [lower, upper) (upper excluded) at which a built-in function is closest to a target, via Accord’s BinarySearch, which works for either a monotonically increasing or a monotonically decreasing function (both directions are exercised in the test suite) but assumes the function is one or the other over the searched range — it is not told which, and gives an unreliable answer on a non-monotone function. Both lower and upper are capped at ±1,000,000,000 and upper must strictly exceed lower.

SortValuesWithOriginalIndices stably sorts a double[] ascending or descending (descending, default false) and returns both the sorted Values and the OriginalIndices recording where each sorted value came from, so the same permutation can be applied to other parallel arrays by hand. NaN values are treated as the smallest possible value by the sort, and up to 200,000 values are accepted. This tool, together with SortValuesByKeys, is also discussed as the closest AdvancedAnalytics primitive to a dataframe’s arrange()/row-sort in Data Frames vs. Accord Arrays and Loading, Shaping and Merging, which note that both tools operate on a single vector rather than a whole table: reordering a multi-column table by one column’s sort order needs the caller to apply OriginalIndices to every other column itself, since no tool here takes a table plus a row-index permutation and returns the reordered table.

SortValuesByKeys reorders one values array to follow the ascending sort order of a parallel keys array of the same length (for example, ordering transaction amounts by their timestamps); values with tied keys keep their original relative order (a stable sort via OrderBy(...).ThenBy(i => i)). Up to 200,000 pairs are accepted. See the cross-reference under SortValuesWithOriginalIndices above for the same caveat about table-wide sorts.

SelectNthSmallestValue returns the zero-based n-th smallest value (or n-th largest when descending) of an array by quickselect (Sort.NthElement), which finds the one order statistic without sorting the whole array; n must be strictly less than the number of values, and this is the tool for medians or percentiles of large arrays where a full sort would be wasteful.

SelectSmallestValuesSorted returns the count smallest (or largest, when descending) values already in sorted order, via Sort.Partial when count is less than the array length (and a full Array.Sort plus reversal when it equals the whole array), avoiding sorting the remainder. This is the top-N tool, for example the ten largest transactions in a batch; count cannot exceed the number of values.

GenerateUniformRandomNumbers draws count (up to 1,000,000) reproducible pseudo-random numbers uniformly on [minimum, maximum] using Accord’s Ziggurat generator seeded by seed (default 1), so identical arguments always produce identical output; maximum must strictly exceed minimum.

GenerateNormalRandomNumbers draws count reproducible normal (Gaussian) pseudo-random numbers with a given mean (default 0) and standardDeviation (default 1, must be positive), again via the seeded Ziggurat generator, by drawing standard normals and affinely transforming them.

GenerateExponentialRandomNumbers draws count reproducible exponential pseudo-random numbers with a given rate (default 1, must be positive; the mean of the output is 1/rate), for simulating waiting times or inter-arrival gaps between events.

MonteCarloExpectationOfNamedFunction estimates E[f(X)] for a built-in univariate function f of a random variable X drawn from Uniform (distributionParameters = [minimum, maximum]), Normal ([mean, standardDeviation]) or Exponential ([rate]), by drawing samples (default 100,000, up to 5,000,000) seeded values and averaging. The result carries Estimate (sample mean), StandardError (sample standard deviation over root-n), SampleStandardDeviation, and an approximate 95% interval built from the normal critical value 1.959963984540054; the description notes that quadrupling the sample count only halves the standard error, which is the usual Monte Carlo rate.

MonteCarloProbabilityOfNamedFunction estimates P(lower <= f(X) <= upper) for the same three distribution families by counting the sampled share inside the range — either bound can be omitted (null) for an open-ended range. StandardError is the binomial sqrt(p(1-p)/n) and the confidence bounds are clipped to [0, 1]; the description flags that rare events with true probability below about 1e-4 need very large sample counts to estimate reliably, since so few draws land inside the range at all.

GetMathematicalConstants takes no arguments and returns a fixed table of 17 named constants (Pi, E, EulerGamma, Catalan, Sqrt2, Sqrt2OverTwo, Sqrt2Pi, SqrtHalfPi, LogPi, Log2, Log3, LogSqrt2Pi, Log2Pi, DoubleEpsilon, SingleEpsilon, DoubleSmall, LogMax, LogMin), each with its double-precision Value and a one-line Meaning — a lookup to avoid an agent typing a mathematical or machine constant from memory.

NumericsFastFourierTransform computes the discrete Fourier transform of a real or complex sequence (up to 65,536 values) by FFT, fastest at power-of-two lengths but correct at any length; direction (Forward or Inverse, default Forward) selects which way, and Inverse undoes Forward exactly including the 1/n scaling, so feeding a Forward result’s Real/Imaginary pair back through Inverse recovers the original signal. The worked example in the description — Forward([1, 2, 3, 4]) gives 10, -2+2i, -2, -2-2i — pins down the convention and scaling used.

NumericsDiscreteCosineTransform computes the orthonormal type-II discrete cosine transform of a real sequence (up to 20,000 values), which concentrates energy from smooth signals into the first few coefficients (coefficient 0 is the scaled mean level) and underlies image and audio compression; Inverse undoes Forward exactly.

NumericsDiscreteSineTransform computes the discrete sine transform of a real sequence (up to 20,000 values), suited to signals that vanish at the boundaries, with Inverse undoing Forward.

NumericsHartleyTransform computes the discrete Hartley transform of a real sequence (up to 20,000 values), a real-valued cousin of the Fourier transform built from cosine plus sine waves and scaled by 1/sqrt(n) so that applying the transform to its own output a second time returns the original signal (it is self-inverse, so there is no direction parameter).

NumericsHilbertTransform computes the discrete Hilbert transform of a real signal whose length must be an exact power of two (up to 65,536), shifting every frequency component by 90 degrees — the Hilbert transform of a cosine is the matching sine — so that, together with the original signal, it forms the analytic signal whose magnitude gives the envelope.

NumericsHaarWaveletTransform applies one full pass of the Haar wavelet transform to a signal of even length (up to 65,536): the first half of the Forward output holds pairwise averages (the approximation) and the second half the half-differences (the detail) at that scale; Inverse undoes Forward. Multi-level decomposition is left to the caller, who repeats the call on the first half of the previous output.

NumericsCdf97WaveletTransform applies one pass of the Cohen-Daubechies-Feauveau 9/7 biorthogonal wavelet transform — the wavelet used in lossy JPEG2000-style image compression — to a signal of even length, at least 4 and at most 65,536: smooth approximation coefficients first, then detail coefficients; Inverse undoes Forward.

LinearAlgebraTools

MatrixMultiply multiplies an m-by-k matrix a by a k-by-n matrix b, giving an m-by-n result; a’s column count must equal b’s row count, and both inputs are capped at 300 by 300 with every entry required to be finite.

MatrixVectorMultiply multiplies an m-by-n matrix a by a length-n vector v, giving a length-m result — the tool for applying a linear map or computing fitted values from a design matrix and a coefficient vector.

MatrixTranspose returns the transpose of an m-by-n matrix as an n-by-m matrix, for reshaping before a multiply whose dimensions would not otherwise line up.

MatrixElementwiseOperation applies one of Add, Subtract, Multiply (the Hadamard, entrywise product, not matrix multiplication — MatrixMultiply is the tool for that), Divide or Power (each element of a raised to the matching element of b) between two identically shaped matrices (default Add). Division by zero or a negative base with a fractional exponent produces NaN or infinity in that cell rather than throwing, which a caller inspecting the result should be aware of.

MatrixInverse computes the inverse of a square, non-singular matrix via LU decomposition so that A times the inverse is the identity; a singular matrix (zero determinant, dependent rows) is rejected with a message pointing the caller at MatrixPseudoInverse instead. The description recommends SolveLinearSystem over explicit inversion whenever only A^-1 b is actually needed, since solving is more numerically accurate than inverting and multiplying.

MatrixPseudoInverse computes the Moore-Penrose pseudo-inverse of any matrix — square or rectangular, full rank or not — via the singular value decomposition, giving least-squares solutions for over-determined systems or minimum-norm solutions for under-determined ones even when the matrix is singular. For a full column-rank matrix it equals (A'A)^-1 A'.

MatrixDeterminant returns the determinant of a square matrix via LU decomposition together with the log of its absolute value (LogAbsoluteDeterminant, useful when the determinant itself would overflow or underflow a double) and its Sign; a zero determinant sets IsSingular true and LogAbsoluteDeterminant to negative infinity.

MatrixPseudoDeterminant returns, as a two-element Values array, the pseudo-determinant (the product of a matrix’s non-zero singular values) and its log, for matrices — singular or rectangular — where the ordinary determinant is zero or undefined, such as a degenerate Gaussian density’s covariance matrix.

MatrixTrace returns the sum of the diagonal elements of a square matrix, which also equals the sum of its eigenvalues.

MatrixRankAndCondition reports the numerical rank, condition number (largest/smallest singular value, infinite if the smallest is exactly zero) and the extreme singular values of any matrix, derived from its singular value decomposition. IsRankDeficient is true whenever the rank is below the smaller of the row/column counts; the description calls out that a condition number above roughly 1e12 means the matrix is numerically singular and any solution computed from it will be unreliable.

MatrixNorms computes the four standard matrix norms in one call: Norm1 (largest absolute column sum), NormInfinity (largest absolute row sum, computed as Norm1 of the transpose), Frobenius (root of the sum of squared entries), and Spectral (the largest singular value) — used to bound how much a linear map can stretch a vector.

VectorNorms returns either the unit-length copy of a vector (normalise true) or, by default, a two-element Values array of its Euclidean (L2) norm and squared L2 norm. A zero vector has norm 0 and its “normalised” copy stays all zeros, since it has no defined direction to normalise onto.

SolveLinearSystem solves the square system A x = b exactly by LU decomposition, returning Solution, the residual norm ||A x - b|| (which is the accuracy check, not merely a diagnostic) and the condition number of A. A singular A is rejected outright with a pointer to SolveLeastSquares; a large condition number (the description cites the same roughly 1e12 threshold used elsewhere) warns that x is numerically unreliable even though a value was returned.

SolveLinearSystemMultipleRightHandSides solves A X = B for a whole matrix of right-hand sides at once — column j of the result solves A x = column j of B — avoiding repeated calls to SolveLinearSystem; A must be square and non-singular.

SolveLeastSquares finds the x minimising ||A x - b||^2 for any shape of A (QR for tall/over-determined systems, SVD for wide or rank-deficient ones), the tool for fitting a line or plane through more observations than unknowns. ResidualNorm is zero only for an exactly solvable system; a very large ConditionNumber warns of collinear design-matrix columns.

MatrixNullSpace returns an orthonormal basis of the null space of a matrix as a set of row vectors, each satisfying A x = 0, computed from the right singular vectors beyond the numerical rank in the singular value decomposition. An empty (zero-row) result means the columns are independent and only the trivial solution exists; a non-empty result reveals a hidden exact linear dependency among the input’s columns.

MatrixReducedRowEchelonForm reduces any matrix to reduced row echelon form by Gauss-Jordan elimination via JaggedReducedRowEchelonForm, exposing the pivot structure for solving small systems by hand-style elimination. The description notes that entries near but not exactly zero are ordinary floating-point artefacts and should be treated as zero by the caller.

MatrixKroneckerProduct returns the Kronecker (block tensor) product of two matrices: every element of a scales a full copy of b, giving an (m_a*m_b)-by-(n_a*n_b) block matrix, used to build structured covariance or design matrices. Because the result’s dimensions multiply, both inputs must be small enough that the product still fits the shared 300-by-300 ceiling, or the call is rejected up front naming the resulting size.

VectorOuterProduct returns the outer product of two vectors — a matrix whose (i, j) entry is a[i] * b[j] — used to build rank-one matrices; each vector is capped at 300 values (the shared matrix dimension ceiling).

VectorDotProduct returns the sum of products of matching elements of two equal-length vectors (up to 200,000 values); a result of zero means the vectors are orthogonal.

VectorCrossProduct returns the 3-D cross product of two exactly-3-element vectors: a vector perpendicular to both, whose length equals the area of the parallelogram the two inputs span. Either input not having exactly 3 elements is rejected.

MatrixStructureProperties is the one matrix tool in this group that deliberately accepts non-finite entries (finite: false in its guard call) so it can report on them: it returns Rows, Columns, IsSquare, IsSymmetric (checked with a 1e-9 relative tolerance), IsPositiveDefinite (only evaluated when the matrix is already symmetric), IsDiagonal, IsSingular (only meaningful, and only computed, when the matrix is square and clean of NaN/infinity), HasNaN and HasInfinity — a single diagnostic pass over a matrix of unknown provenance before feeding it to a stricter tool.

GenerateStructuredMatrix builds a standard size-by-size matrix of a chosen kind: Identity, Zeros, Ones, Magic (a magic square, size 3 or above only), Hilbert (entry 1/(i+j+1), a classic ill-conditioned test matrix), or Vandermonde (needs a separate nodes array; row i is powers of nodes[i], so the result has one row per node and size columns rather than being square). Size is capped at 300.

MatrixPower raises a square matrix to a non-negative integer power (up to 1,000,000) by repeated squaring (binary exponentiation) rather than naive repeated multiplication, so very high powers are still cheap; power 0 returns the identity. Large powers of an unstable matrix (spectral radius above 1) overflow entries to infinity, and the description names Markov transition matrices and graph path counting as the typical uses.

GenerateMeshGrid builds a 2-D grid of every (x, y) pair from two independently evenly spaced axes, returned as one [x, y] row per grid point (xPoints times yPoints rows total, each axis needing at least 2 points), for evaluating a function over a plane; the two axis sizes are checked up front so their product cannot exceed 40,000 grid points.

GenerateEvenlySpacedValues returns count (2 to 200,000) evenly spaced values from start to stop inclusive — a linear-space axis generator, typically feeding EvaluateNamedFunction or a plot.

NumericsConvolveVectors convolves a signal with a kernel (no longer than the signal, both up to 200,000 values), the moving-average/polynomial-multiplication style sliding weighted sum; with trim true (default false) the output is the same length as the signal, otherwise it has length signal.Length + kernel.Length - 1.

RescaleValuesToRange linearly maps values from a source interval [fromMinimum, fromMaximum] onto a target interval [toMinimum, toMaximum], so the source minimum lands on the target minimum and the source maximum on the target maximum — the normalise-to-[0,1]-or-convert-units tool. Values outside the source interval extrapolate beyond the target interval rather than being clamped, and a zero-width source interval (fromMinimum == fromMaximum) is rejected since it cannot be mapped.

MatrixDecompositionTools

LuDecomposition factors a square matrix as L (unit lower triangular) times U (upper triangular) with partial pivoting, returning Lower, Upper, the PivotPermutation vector (row i of L*U corresponds to row PivotPermutation[i] of the input) and the Determinant read off cheaply from the factorisation; IsNonsingular false means a zero pivot was encountered during elimination, so the matrix has no inverse.

QrDecomposition factors a matrix with at least as many rows as columns as Q (orthonormal columns) times R (upper triangular) — a row-deficient matrix (fewer rows than columns) is rejected with a suggestion to supply the transpose instead. This is the numerically stable route to least-squares problems; IsFullRank false means the columns are linearly dependent, detected from the magnitude of R’s diagonal relative to its largest entry.

CholeskyDecomposition factors a symmetric positive definite matrix as L * L' with L lower triangular, returning the Determinant and LogDeterminant alongside it; unlike most tools in this group, a matrix that fails the positive-definiteness check does not throw — it returns IsPositiveDefinite = false with empty factors and NaN determinants, which is itself the validity test for a candidate covariance matrix. The description also names drawing correlated random numbers and fast symmetric-system solving as typical uses.

SolveSymmetricPositiveDefiniteSystem solves A x = b for a symmetric positive definite A (such as a covariance or normal-equations matrix) via Cholesky factorisation, roughly twice as fast as the general LU-based solver; a matrix that is not positive definite is rejected outright with a pointer to SolveLinearSystem for the general case.

SingularValueDecomposition factors any matrix as U * diag(SingularValues) * V', with singular values returned largest first; Rank is the count of singular values above the library’s numerical tolerance and ConditionNumber is their largest-to-smallest ratio. V’s columns are the right singular vectors — the principal directions of the data when the input is mean-centred — and U’s columns the left singular vectors.

SymmetricEigenDecomposition finds the eigenvalues and orthonormal eigenvectors of a symmetric matrix such as a covariance or correlation matrix; all eigenvalues are guaranteed real for symmetric input (HasComplexEigenvalues is always false in the result), and sortDescending (default true) controls whether the largest eigenvalue comes first. A non-symmetric input is rejected — GeneralEigenDecomposition is the tool for that case.

GeneralEigenDecomposition finds the eigenvalues and eigenvectors of any square matrix, symmetric or not, such as a Markov transition matrix or a dynamical system’s state matrix. Eigenvalues may be complex, returned as parallel RealEigenvalues/ImaginaryEigenvalues arrays with HasComplexEigenvalues true whenever any imaginary part exceeds 1e-12 in magnitude (a rotation-like or oscillating system); for a complex-conjugate pair, the real and imaginary parts of the eigenvector occupy adjacent columns of Eigenvectors.

GeneralizedEigenDecomposition solves the generalised eigenproblem A v = lambda B v for two same-size square matrices A and B, as used in linear discriminant analysis and vibration analysis (with B the identity it reduces to the ordinary eigenproblem). IsSingular or IsDegenerate true warns that B itself is singular, so some reported eigenvalues are effectively infinite or undefined rather than numerically meaningful.

GramSchmidtOrthogonalisation orthonormalises the columns of a square matrix via the Gram-Schmidt process, returning Q (orthonormal columns) and R (upper triangular) such that A = Q R; modified (default true) selects the numerically more stable modified Gram-Schmidt variant over the classical one, which matters when the input’s columns are nearly dependent. The matrix must have independent columns — dependent columns surface as NaN in the result rather than a thrown exception.

NonnegativeMatrixFactorisation approximates a non-negative m-by-n matrix V as W (m-by-r) times H (r-by-n), both entrywise non-negative, via the multiplicative-update algorithm — the parts-based decomposition behind topic models and similar structure discovery. The algorithm starts from a seeded random factorisation (the same seed, default 1, always reproduces the same result) and runs up to maximumIterations (default 500, up to 5,000) updates; ReconstructionError is the Frobenius norm of V - W H (0 for a perfect fit). Every entry of V must be zero or positive, and rank is capped at 50 and at the smaller of the matrix’s two dimensions.

OptimisationTools

EvaluateNamedObjective evaluates a built-in NumericsObjectiveFunction (including Quadratic via quadraticMatrix/linearTerms/constantTerm) at each row of a points matrix (one point per row, all rows the same number of variables, up to 50 variables and 10,000 points), returning one value per point — the tool for inspecting a landscape or confirming the value at a candidate optimum before or after running a minimiser.

MinimiseWithLimitedMemoryBfgs minimises a built-in smooth objective from a start point with limited-memory BFGS, a fast general-purpose quasi-Newton method for smooth functions of many variables that uses an analytic gradient where one of the eleven built-in objectives has one, falling back to a 5-point finite-difference gradient otherwise (GradientFor in the shared code). GradientNorm in the result is the size of the gradient at the reported solution (near zero at a true minimum); the description is explicit that this, like every minimiser in this group, performs local search only — on a multimodal objective such as Rastrigin, the reported minimum is whichever one is nearest the start, not necessarily the global minimum. Up to 50 variables, 100,000 iterations, and a 20 second wall-clock cap enforced via a CancellationTokenSource.

MinimiseWithBoundedBfgs is the same limited-memory BFGS method with simple per-variable lower/upper box constraints (lowerBounds/upperBounds, either omittable for unbounded on that side; a very large negative number should stand in for negative infinity rather than an actual infinite value), via Accord’s bound-constrained BoundedBroydenFletcherGoldfarbShanno (L-BFGS-B). The start point must already lie inside the bounds, and the description notes that GradientNorm here is the unprojected gradient, so it can legitimately stay non-zero when the true optimum sits on a bound — a zero GradientNorm is not the right convergence signal for this variant the way it is for the unconstrained ones.

MinimiseWithConjugateGradient minimises a built-in objective with the nonlinear conjugate gradient method, which needs the gradient but far less memory than BFGS and so suits larger problems; variant selects the direction-update formula — FletcherReeves, PolakRibiere or PositivePolakRibiere (default, and described as the most robust of the three).

MinimiseWithGradientDescent minimises with plain fixed-step-size gradient descent: repeatedly step against the gradient, scaled by learningRate (default 0.01, must be in (0, 10]). It is the simplest and, on curved valleys such as Rosenbrock, the slowest method in the group; a learning rate that is too large diverges (Converged false with a very large Value) while one too small barely moves within the iteration budget.

MinimiseWithNelderMead minimises with the Nelder-Mead simplex method, which uses only function values (no gradient) and so tolerates rough or noisy objective surfaces at the cost of slow convergence in higher dimensions. Optional lowerBounds/upperBounds keep the simplex inside a box, and initialStep (default 0.5) sets the starting simplex size — the description recommends roughly the scale of the expected solution. Evaluations are capped at 200,000 and wall-clock time at 20 seconds.

MinimiseWithSubplex runs the Subplex method — Nelder-Mead applied repeatedly to rotating subspaces of the variables — which the description states is markedly better than plain Nelder-Mead once there are many variables (10 to 50), still without needing a gradient. Parameters and caps mirror MinimiseWithNelderMead.

CompareUnconstrainedOptimisers runs all five unconstrained methods (limited-memory BFGS, conjugate gradient, gradient descent, Nelder-Mead, Subplex) on the same built-in objective and start point (up to 20 variables, tighter than the 50-variable cap on the individual minimisers) and returns one NumericsMethodComparisonEntry row per method with its solution, value, convergence flag and status. A method that throws is caught and reported in that row’s Error field with Value set to NaN rather than aborting the whole call, so agreement or disagreement across methods — good evidence either way about whether a true minimum was found — can be read off a single response even if one method fails outright.

SolveQuadraticProgram solves the convex quadratic programme minimise 0.5 x'Qx + c'x subject to linear constraints (constraintMatrix rows each paired with a constraintRelations entry — GreaterThanOrEqual, LessThanOrEqual or Equal, defaulting to all GreaterThanOrEqual — and a constraintValues right-hand side), using the exact Goldfarb-Idnani dual active-set method. quadraticMatrix must be symmetric positive definite (the strictly convex case); a non-positive-definite Q surfaces as Status = NonPositiveDefinite and infeasible constraints as NoPossibleSolution, both without an exception. LagrangeMultipliers has one entry per constraint row (zero for an inactive constraint), revealing which constraints are actually binding at the solution. Up to 50 variables and 100 constraints; the description names portfolio weights under a budget constraint and bounded least squares as typical uses.

MinimiseWithLinearConstraintsCobyla minimises a built-in (possibly non-quadratic) objective subject to the same kind of linear constraints as SolveQuadraticProgram, using COBYLA, a derivative-free method that builds linear approximations inside a trust region that shrinks from initialStep (default 0.5) down toward precision (default 1e-8). MaximumConstraintViolation in the result should be close to zero for a genuinely feasible answer; omitting all constraint arguments reduces it to an unconstrained COBYLA search. Up to 50 variables, 100 constraints, 100,000 evaluations.

SolveLinearProgram solves a linear programme — maximise or minimise c'x subject to linear constraints and a uniform per-variable lowerBound (default 0, the usual non-negativity assumption) and optional uniform upperBound — by building the bound constraints as extra rows and delegating to the same COBYLA machinery as MinimiseWithLinearConstraintsCobyla. Because COBYLA is a general derivative-free solver rather than a dedicated simplex or interior-point LP method, the description is explicit that the answer is only accurate to roughly 1e-6, not exact, and that an unbounded problem should be read off as Converged = false rather than assumed caught by any special-cased detection. Default constraint relation when none is given is LessThanOrEqual (the opposite default from SolveQuadraticProgram’s GreaterThanOrEqual), which matters if the two tools’ conventions are mixed up.

FitNamedCurveLeastSquares fits the parameters of a built-in one-variable function family (the same twelve families as EvaluateNamedFunction/NumericsText.Function) to (x, y) data by non-linear least squares, choosing between Levenberg-Marquardt (default) and Gauss-Newton via method, using exact analytic parameter derivatives from NumericsFunctions.PartialDerivatives rather than finite differences. initialParameters must have exactly the number of values the chosen family expects (2 to 4 for the fixed families, any length up to 40 for Polynomial, matching one-for-one with its coefficients) — the call is rejected up front if the count is wrong, or if there are fewer data points than parameters. Because the underlying families are non-linear, the result genuinely depends on the starting guess; the description recommends trying several starts. StandardErrors gives the approximate standard error of each fitted parameter, and RootMeanSquaredError expresses the fit error in the same units as y.

SolveAssignmentProblemMunkres solves the assignment problem — one row (worker) matched to at most one column (task) minimising (or, with maximise true, maximising) total cost — with the Hungarian/Munkres algorithm, after padding a non-square costMatrix to square with zero-cost dummy entries internally. ColumnForRow[i] is the task assigned to worker i, or -1 for a worker left unassigned when there are more rows than columns (confirmed by the test suite: a 3-worker, 2-task matrix assigns only 2 and reports -1 for the third); TotalCost sums only the real, assigned entries of the original (unpadded) cost matrix, never the dummy padding. Costs must be finite and the matrix is capped at 300 by 300.

SpecialFunctionTools

GammaFunction evaluates the gamma function, the continuous extension of the factorial (gamma(n) = (n-1)! for positive integers), at each supplied value. It is undefined at zero and the negative integers, where the tool catches Accord’s ArithmeticException and reports NaN there, or positive infinity for a positive argument large enough to overflow (above roughly 171); LogGammaFunction is the tool for arguments that large.

LogGammaFunction evaluates the natural log of the gamma function without ever overflowing, so it remains usable for arguments where the gamma function itself would already be infinite; it underlies log-factorials, log-binomials and most likelihood calculations. The argument must be positive — non-positive values give NaN or infinity rather than being rejected outright.

DigammaFunction evaluates the digamma function, the derivative of log-gamma (psi), which appears in maximum likelihood estimation for gamma and beta distributions; digamma(1) equals minus the Euler-Mascheroni constant, about -0.5772. Non-positive integers give NaN or infinity.

TrigammaFunction evaluates the trigamma function, the second derivative of log-gamma (equivalently the derivative of digamma), giving the curvature of gamma/beta likelihoods; trigamma(1) equals pi^2/6, about 1.645.

MultivariateGammaFunction evaluates the multivariate gamma function of a given dimension p (1 to 1,000), which normalises the Wishart and inverse-Wishart distributions (p = 1 reduces to the ordinary gamma function); x must exceed (p - 1) / 2 for each evaluated value, and logScale (default false) returns the natural log instead, to avoid overflow for larger dimensions.

RegularisedLowerIncompleteGamma evaluates P(a, x), the probability that a gamma random variable with shape a and unit scale is at most x — the building block behind chi-square and Poisson tail probabilities. Results run over [0, 1]; shape a must be positive, and a negative x is not rejected but simply returns the library’s fallback value of 1.

RegularisedUpperIncompleteGamma evaluates Q(a, x) = 1 - P(a, x), the gamma survival function; with a = k/2 and x = statistic/2 this is exactly the chi-square p-value, so it is the tool behind chi-square significance tests built elsewhere in the tool layer.

InverseRegularisedIncompleteGamma inverts either the lower (upper false, default) or upper (upper true) regularised incomplete gamma function for a given probability, i.e. the gamma/chi-square quantile function — critical values. Probabilities must lie strictly inside (0, 1) and shape a must be positive.

BetaFunction evaluates B(a, b) = gamma(a) gamma(b) / gamma(a+b) for pairs of positive parameters given as two equal-length arrays — the normalising constant of the beta distribution; logScale (default false) returns the natural log instead, which is numerically safer for large parameters.

MultinomialBetaFunction evaluates the multinomial (Dirichlet) beta function of a positive concentration- parameter vector alpha — the product of gamma(alpha_i) divided by gamma of their sum, the Dirichlet distribution’s normalising constant — which reduces to the ordinary BetaFunction for a 2-element alpha. Very long alpha vectors underflow to zero (capped at 1,000 entries regardless).

RegularisedIncompleteBeta evaluates I_x(a, b), the beta distribution’s CDF, which underlies the Student t, F and binomial tail probabilities computed elsewhere in the tool layer; x must lie in [0, 1] and both shape parameters a, b must be positive.

InverseRegularisedIncompleteBeta inverts I_x(a, b) for a given probability — the beta distribution’s quantile function, and so also the route to Student t and F critical values; probabilities must lie in [0, 1].

ErrorFunction evaluates the error-function family selected by kind: Erf (default), its complement Erfc (more accurate than computing 1 - Erf directly in the upper tail), InverseErf (domain (-1, 1)) and InverseErfc (domain (0, 2)), related to the normal CDF by erf(x) = 2*Phi(x*sqrt(2)) - 1. Out-of-domain inverse arguments give NaN or infinity rather than throwing.

StandardNormalFunction evaluates one of eight functions of the standard normal distribution selected by kind: Cdf (default), LogCdf, Survival (1 - Cdf, accurate in the far tail), Quantile (inverse CDF, for probabilities strictly in (0, 1); 0 or 1 map to negative/positive infinity), Density, LogDensity, and the high-accuracy HighAccuracyCdf/HighAccuracySurvival variants for extreme z-scores. The description notes a two-sided p-value is twice the Survival of the absolute z-score — the composition most hypothesis-test tools elsewhere in the catalogue build on.

BivariateNormalCdf evaluates P(X <= x, Y <= y) for two standard normal variables with correlation rho, for pairs supplied as two equal-length arrays; rho must be strictly inside (-1, 1) (a perfect correlation collapses to a one-dimensional problem and is rejected), and with rho = 0 the result equals the product of the two marginal CDFs as a sanity check.

OwensTFunction evaluates Owen’s T function T(h, a) — the integral of exp(-h^2(1+x^2)/2)/(1+x^2) from 0 to a, divided by 2*pi — needed for the skew-normal distribution and for certain bivariate normal probability calculations, for pairs supplied as two equal-length arrays; T(h, 0) = 0 and T(0, 1) = 1/8 are given as reference values.

BesselFunction evaluates integer-order Bessel functions selected by kind: FirstKindJ (default, oscillating, solutions of the wave equation on a cylinder), SecondKindY (singular at x = 0, so requires x > 0), or ModifiedFirstKindI (growing, used in the von Mises and Rice distributions); integer order is capped at 0 to 100, and the description states results are accurate to roughly seven significant digits.

FactorialFunction returns n! for each non-negative integer n (or its natural log when logScale is true), rejecting any value that is negative, non-integral, or exceeds the representable range — 170 for the plain factorial (which overflows a double above that), or 1,000,000,000 when logScale is requested, since the log stays finite far beyond where the factorial itself would not.

BinomialCoefficient returns n choose k for each pair of whole numbers from two equal-length arrays (or its natural log when logScale is true, avoiding overflow for large n); k > n for a given pair returns exactly 0 (or negative infinity in log scale) rather than throwing, and both n and k are capped at 1,000,000 with up to 200,000 pairs per call.

LogSumExp computes ln(sum(exp(v_i))) in one numerically stable pass — the standard trick for adding probabilities held on the log scale, normalising log-likelihoods, and building softmax — remaining accurate even for inputs around +1000 or -1000 where naive exponentiation would overflow or underflow. An empty array is rejected, a single value returns itself unchanged, and entries of negative infinity contribute nothing to the sum.

SoftmaxProbabilities converts a scores array into probabilities (positive, summing to 1) via the numerically stable softmax exp(v_i) / sum(exp(v_j)), used to turn model scores or log-odds into a categorical distribution; adding the same constant to every score leaves the result unchanged, which is the usual softmax shift-invariance sanity check.

SigmoidAndLogit applies either the logistic function (Sigmoid, default — maps any real number to a probability in (0, 1), with sigmoid(0) = 0.5) or its inverse (Logit — maps a probability back to log-odds), selected by direction, via Accord’s LogitLinkFunction. Logit of exactly 0 or 1 maps to negative/positive infinity rather than throwing.

StableLogExpFunctions evaluates four expressions that lose precision computed naively, selected by kind: Log1P (default, ln(1+x), exact for tiny x), Expm1 (exp(x)-1, exact for tiny x), Log1M (ln(1-x)), and Softplus (ln(1+exp(x)) without overflow for large x). Arguments outside a given function’s domain (for example x <= -1 for Log1P) return NaN rather than throwing.

LogAddAndSubtractPairs adds or subtracts, on the log scale, pairs of values stored as natural logs: LogSum (default) computes ln(exp(a)+exp(b)) and LogDifference computes ln(exp(a)-exp(b)), which requires a > b for the subtraction to be the log of a positive number. Used to combine or offset tiny probabilities without underflow; the two input arrays must have equal length.

ReciprocalAndInverseHyperbolicFunctions evaluates fifteen trigonometric and hyperbolic functions missing from a basic calculator, selected by kind: secant, cosecant, cotangent and their inverses; hyperbolic secant, cosecant and cotangent; and the six inverse hyperbolic functions (sine, cosine, tangent, secant, cosecant, cotangent). Angles are in radians throughout, and an argument outside a given function’s domain (for example InverseHyperbolicCosine below 1) returns NaN or infinity rather than throwing.

StirlingGammaApproximation approximates the gamma function using Stirling’s asymptotic formula, accurate to a fraction of a percent around an argument of 10 and better for larger arguments — a cheap sanity check against GammaFunction/LogGammaFunction rather than a replacement for them; the description explicitly warns against using it below roughly 5, where the approximation has not yet converged.

GaussianBellFunction evaluates the zero-mean Gaussian bell curve exp(-x^2/(2*variance)) / sqrt(2*pi*variance) at each x (the normal density with a chosen variance, positive and required), or, when a parallel y array is also supplied, the two-dimensional bell exp(-(x^2+y^2)/(2*variance)) / (2*pi*variance) — used to build smoothing weights or spatial kernels.

GaussianKernelWeights returns the weights of a one-dimensional Gaussian smoothing kernel, sampling the bell curve at integer offsets -r to r where r is half the (required-odd) size (3 to 101), so the centre weight is always the largest; the weights are not rescaled to sum to 1, so a caller wanting a weighted average must divide by their sum before use. Intended to be paired with NumericsConvolveVectors for smoothing a series.

TaylorSeriesApproximation approximates one of five functions (Sine, Cosine, HyperbolicSine, HyperbolicCosine, Exponential) by summing a fixed number of Taylor series terms (default 10, 1 to 200) rather than calling the closed-form implementation, so a caller can observe how quickly the series converges; more terms give higher accuracy, and convergence is explicitly noted as slower for larger argument magnitudes.

BSplineBasisFunction evaluates the centred cardinal B-spline basis function of a given integer order (0 to 20) at each x: order 0 is a box function, order 1 a triangle, order 3 the familiar cubic B-spline; the function is exactly zero outside (-(order+1)/2, (order+1)/2). Used to build smooth basis expansions for curve fitting or density smoothing.

StableHypotenuse computes sqrt(a^2 + b^2) for pairs of numbers without the overflow or underflow that squaring very large or very small values directly would cause, even around magnitudes of 1e200 — the stable route to vector lengths and complex-number magnitudes; the two input arrays must have equal length.

PlanarAngle returns the full-circle angle in [0, 2*pi) of the point (x, y) measured anticlockwise from the positive x-axis, for each pair of coordinates from two equal-length arrays (a four-quadrant arctangent); the origin (0, 0) returns 0 by convention rather than being undefined.