Skip to content

Version 2.3.0

Latest

Choose a tag to compare

@HadenSmith HadenSmith released this 11 Nov 00:28
· 9 commits to main since this release
f97fb00

RMC.Numerics v2.3.0 adds regional frequency analysis, new machine learning and optimization methods, Linux test coverage, and the pynumerics Python package on PyPI. It also corrects a set of accuracy defects in special functions, distributions and copulas, and drops the net8.0 and net9.0 targets.

Highlights

  • Regional frequency analysis. The new Numerics.Distributions.Regional namespace implements the Hosking-Wallis method: RegionalData (site L-moment ratios, regional averages, discordancy and its critical values), RegionalHomogeneityTest (H1, H2 and H3 heterogeneity and the Z goodness-of-fit measures from seeded, thread-count-independent kappa simulations) and RegionalGrowthCurve (growth factors and site quantiles).
  • Machine learning. GaussianProcessRegression, Kriging, ElasticNetRegression and PrincipalComponentAnalysis.
  • Optimization. LBFGSB (L-BFGS-B 3.0), CMAES with IPOP restarts, DynamicallyDimensionedSearch, ParetoFront, DynamicProgramming and Knapsack, plus cancellation and progress reporting on every Optimizer.
  • Numerical methods. A QL eigensolver (EigenSolverMethod.QL), QUADPACK QAGS in AdaptiveGaussKronrod (opt-in), a relative-tolerance Brent.Solve, and multi-source CSR Dijkstra.ShortestDistances.
  • Accuracy. StudentT, the incomplete beta and inverse incomplete gamma functions, the Archimedean copula densities, and the GEV, Gamma and Pearson Type III L-moments are corrected against mpmath, SciPy and published reference implementations.
  • pynumerics. A Python package that ships this Numerics.dll with a CoreCLR loader and typed wrappers over every Numerics area. It is published to PyPI as pynumerics automatically after each NuGet release.
  • Linux. The net10.0 build and pynumerics are tested on Linux (Ubuntu 24.04) as well as Windows. The .github/docker/linux-test image runs the .NET tests, the wheel build, pytest and an identity check of the installed assembly.

Breaking changes

Target frameworks

RMC.Numerics 2.3.0 targets net10.0 and net481 only. The net8.0 and net9.0 builds are no longer shipped, because Microsoft ends support for .NET 8 (LTS) and .NET 9 (STS) on November 10, 2026 (.NET support policy). Applications that run on .NET 8 or .NET 9 can stay on RMC.Numerics 2.2.0. Package validation against 2.2.0 reports no API breaks; the only suppressions are for the two dropped frameworks.

Members that now throw instead of returning an invalid result

  • GeneralizedExtremeValue.ParametersFromLinearMoments throws ArgumentOutOfRangeException when λ1 or λ2 is not finite, λ2 ≤ 0, or |τ3| ≥ 1. In 2.2.0 it returned parameters for such input. Estimate(sample, ParameterEstimationMethod.MethodOfLinearMoments) reaches this check for constant data.
  • Dijkstra and Network throw ArgumentOutOfRangeException at entry when any edge weight is negative. In 2.2.0 a negative cycle never terminated. NaN and infinite weights still cut an edge in the edge-list solvers, and graphs with non-negative weights give bitwise-identical results. In pynumerics the exception surfaces as ValueError.
  • The weighted plotting-position Statistics.Percentile (new in this release) throws ArgumentException when the data hold NaN. The 2.3 pre-release builds accepted NaN there.
  • Deterministic.PDF, CDF and InverseCDF throw ArgumentOutOfRangeException when Value is NaN or infinite, as the other distributions do. In 2.2.0 they returned a value.

Other behaviour changes

  • Tools.LogSumExp(IList<double>) returns +inf when any value is +inf (2.2.0 returned NaN) and -inf for an empty list (2.2.0 returned NaN), following scipy.special.logsumexp. NaN still propagates.
  • GoodnessOfFit.PBIAS follows Moriasi et al. (2007), 100 Σ(O - M) / Σ(O), positive when the model underestimates, as its documentation already stated. Results change sign relative to 2.2.0.
  • Gamma.InverseLowerIncomplete and Gamma.InverseUpperIncomplete return NaN for invalid input (a shape or probability outside the domain), where 2.2.0 threw ArithmeticException or ArgumentOutOfRangeException. The edge values are corrected: InverseLowerIncomplete(a, 0) is 0 and InverseLowerIncomplete(a, 1) is +inf.
  • GoodnessOfFit.KolmogorovSmirnov and GoodnessOfFit.AndersonDarling compute the statistic on a sorted copy, so unsorted input gives the correct statistic (2.2.0 silently returned a wrong value for unsorted input; sorted input gives the same result bit for bit). New overloads take bool dataIsSorted, as Statistics.Percentile does: true uses the values as given and skips the copy.
  • TimeSeriesDownload skips a USGS peak whose value is not a number instead of storing it as 0, so a non-numeric peak no longer enters an annual-maximum series as a zero.
  • AdaptiveSimpsonsRule stops with IntegrationStatus.Failure when an accepted interval has a NaN or infinite estimate, and throws ArithmeticException when ReportFailure is true. In 2.2.0 it spent the remaining budget and returned a non-finite result.

Reliability and Fixes

Special functions

  • StudentT. In 2.2.0 the CDF switched to the Normal for ν ≥ 1e8, with far-tail relative error up to 3.8e-3. The tails now use the large-shape incomplete beta expansion from ν = 30, with log-space tails, the Cauchy closed form at ν = 1, and a log-space InverseCDF in the tails, so extreme probabilities at very large ν converge. Two-sided t-test p-values use the incomplete beta tail instead of 2(1 - CDF).
  • Beta.Incomplete. Where one shape is at least 15 and the other at most 1, the continued fractions converged too slowly (relative errors of 1.5e-7 to 1.4e-13 on the oracle grid). These cases now use the BGRAT expansion of Algorithm 708, and shapes below 0.1 use the BUP recurrence with BGRAT. Beta.IncompleteInverse refines small-tail roots in log space, returns subnormal or zero roots instead of throwing, and no longer cycles when the reflected target rounds to one. Beta.LogFunction uses BETALN, ALGDIV and BCORR, accurate to a few ulps where log-gamma differences lose digits.
  • Inverse incomplete gamma. One bracketed Halley solver now serves Gamma.InverseLowerIncomplete, Gamma.InverseUpperIncomplete, GammaDistribution, PearsonTypeIII and the MultivariateStudentT radial factor. It returns a value for every shape and probability, including tiny-shape quantiles far below one, and returns 0 only below the smallest double. On a 375-root oracle grid the relative error is 1.8e-15 for a ≥ 1 and 2.8e-14 below.
  • Tools.Log1p. The compensated form now applies at every finite argument above -1. The direct log(1 + x) used above |x| = 1e-4 lost up to about 1e-12 relative accuracy.
  • Gamma.Trigamma is accurate to full double precision.

Statistics

  • Variance and covariance. Statistics.Variance, Covariance and their weighted overloads use the corrected two-pass sum. With a mean offset of 1e6 the relative error falls from 1.4e-6 to 1.2e-12.
  • Pearson correlation. Correlation.Pearson (list and matrix overloads) uses the corrected two-pass sums. On data offset by 1e9 the error falls from 1166 ulp to 0.4 ulp.
  • Fourier.Autocorrelation is the linear autocorrelation. It padded only to the next power of two, so wrapped-around products entered every lag after lag 0.
  • LinearRegression.PredictionIntervals include the leverage term x0ᵀ(XᵀX)⁻¹x0, so intervals widen away from the data.
  • Correlation.KendallsTau compares values, uses 64-bit counts and returns NaN for NaN input.

Distributions

  • GEV L-moments. ParametersFromLinearMoments follows Hosking's PELGEV with one Newton refinement; 2.2.0 used an approximation accurate to about 9e-4 for |τ3| ≤ 0.5, and the shape error is now about 3e-14. LinearMomentsFromParameters returned NaN at k = 0 and now returns the exact Gumbel value; near k = 0 its error falls from up to 7.9e-4 to 5e-15.
  • Gamma L-moments. L2 is finite for shapes above 171. In 2.2.0 the gamma-function ratio overflowed and returned infinity or NaN.
  • Pearson Type III and log-Pearson Type III. The L-moment L2 and the L-moment fit used an asymptotic form for α ≥ 100 (small skew), with an error and a jump of 4.9e-9 at the switch. They now use the exact gamma ratio.
  • GeneralizedPareto.ParametersFromMoments solves location, scale and shape by the method of moments. In 2.2.0 it used a two-parameter formula and left the shape at zero.
  • Mode. KernelDensity.Mode and TruncatedDistribution.Mode could return a local, non-global peak; they now search a global grid and polish the highest peak. The pinned bimodal KDE case moves from 1.996 to -1.9665, the taller peak. EmpiricalDistribution.Mode returns the largest point mass when there is one, otherwise the midpoint of the highest bin.
  • EmpiricalDistribution with the NormalZ transform. The CDF returned NaN at the node next to p = 1; interpolation toward a segment end at infinity now returns the limit.
  • TruncatedDistribution XML. ToXElement writes the truncation bounds (TruncationMin and TruncationMax), and the factory restores them, including inside Mixture and CompetingRisks components. In 2.2.0 an XML round trip dropped the truncation.
  • EmpiricalDistribution.Clone and XML keep descending (survival) and tied-probability tables. In 2.2.0 they became ascending, strictly increasing tables that failed validation. Existing XML reads unchanged, and default settings write the same XML.

Copulas

  • Joe. The density was off by up to 11% at θ = 2 and underflowed at large θ. It is now evaluated in log space.
  • Clayton returned NaN for θ < 0, and Frank overflowed for θ above about 236. Both are fixed and continuous through θ = 0.
  • Gumbel. The density is evaluated in log space (values move by up to 3e-10). The Gumbel and Joe ConditionalCDF use closed forms; they lost up to 1e-5 before.
  • InverseConditionalCDF returns the exact limits at u = 0 and u = 1 for the Gumbel, Joe, Normal, Student-t, Clayton and AMH copulas. Gumbel and Joe are inverted at full precision.
  • AMH InverseConditionalCDF returned NaN at θ = 0 (independence), where it now returns v = t, and it returns exact limits at t = 0 and t = 1.
  • AMH at θ = 1. The generator is identically zero there, so CDF and ConditionalCDF use the closed form at θ = 1.

Numerical methods

  • Dijkstra and Network no longer loop without end on a negative cycle (see Breaking changes).
  • RungeKutta. The Fehlberg error term weighted k6 instead of k5, which inflated the error estimate; adaptive steps can now grow, and Cash-Karp steps use the fifth-order solution.
  • Optimizer budgets. Powell threw NullReferenceException when the evaluation budget ran out inside a line search; it now ends with its normal budget stop. MultiStart and MLSL give each local search at least 10 evaluations and never exceed MaxFunctionEvaluations, with ReportFailure true or false.

Data

  • TimeSeriesDownload.FromUSGS uses the USGS Water Data API v1, because the legacy NWIS WaterServices retire on February 22, 2027.
  • GHCN DailySnow reads snowfall in its native millimeters. In 2.2.0 non-zero snow depths were 10 times too small.

API additions

Statistics (Numerics.Data.Statistics)

  • Column statistics over the finite entries of each column, each with an out int[] excluded overload: Statistics.ColumnMeans, ColumnVariances, ColumnStandardDeviations, ColumnLinearMoments (4 × p) and ColumnPercentiles (Type 7 and plotting-position forms). Each column is bitwise the one-sample member.
  • GoodnessOfFit.ColumnKolmogorovSmirnovUniform and ColumnAndersonDarlingUniform: one sorted sample per column against Uniform(0, 1).
  • Plotting-position percentiles: Statistics.Percentile(data, k, PlottingPostionType, dataIsSorted), its list-of-k overload, and the weighted forms Percentile(data, k, weights, PlottingPostionType, dataIsSorted) with a list-of-k overload.
  • PlottingPositions.Alpha(PlottingPostionType), and weighted PlottingPositions.Function(weights, alpha) and Function(weights, PlottingPostionType).
  • Statistics.LinearMoments(data, nmom) for any number of L-moments (its first four values are bitwise the four-value member), Statistics.Median, Statistics.LinearCoefficientOfVariation and Statistics.WilsonScoreInterval.
  • Autocorrelation.Function(data, lagMax, type, centered) and its TimeSeries overload: centered: false gives the autocorrelation about zero. The 2.2.0 signatures are unchanged.
  • HypothesisTests.TwoSampleKolmogorovSmirnov (exact), HypothesisTests.HartiganDip, and an opt-in parametric-bootstrap UnimodalityTest(sample, realizations, seed).
  • GoodnessOfFit.KolmogorovSmirnov(observedValues, model, dataIsSorted) and GoodnessOfFit.AndersonDarling(observedValues, model, dataIsSorted): true uses the values as given and skips the sorted copy.

Tools (Numerics.Tools)

  • Tools.CompensatedSum (plain, indicator and gather overloads) and Tools.CompensatedCumulativeSum, each with a kahan option. Neumaier summation is the default.
  • Tools.KahanAdd, Tools.NeumaierAdd and Tools.NeumaierResult: the compensated step for callers' own loops.
  • Tools.LogSumExp(double[,] values, int axis).
  • Tools.Hypot, and list forms of Tools.Expm1 and Tools.Log1p.

Distributions (Numerics.Distributions)

  • Per-element static members: Poisson.InverseCDF(rates, probabilities), Poisson.LogPDF(rates, k), Poisson.CDF(rates, k), Binomial.LogPDF(successProbabilities, trials, k) and Binomial.CDF(successProbabilities, trials, k). Each element is bitwise the instance member.
  • Multinomial.CategoricalIndices(cumulativeWeights, uniforms) and the overload with inclusive, which selects min{k : F(k) ≥ u}.
  • GeneralizedPareto.FromPoissonGeneralizedExtremeValue and GeneralizedExtremeValue.FromPoissonGeneralizedPareto.
  • GeneralizedPareto.MLE(sample, location) and the IFixedParameterEstimation interface for fits with known parameters.
  • UnivariateDistributionBase.ParameterSetQuantiles (virtual; GeneralizedExtremeValue overrides it), and list forms of CCDF, LogPDF, LogCDF and LogCCDF.
  • List forms of the bivariate copula PDF, CDF, ConditionalCDF and InverseConditionalCDF.
  • A weighted UncertaintyAnalysisResults.ProcessMeanCurve.
  • EmpiricalDistribution.StrictXValues and StrictProbabilities.
  • MultivariateStudentT.CDF uses the Genz-Bretz method, with AbsoluteError, RelativeError and MaxEvaluations.
  • Numerics.Distributions.Regional: RegionalData, RegionalHomogeneityTest and RegionalGrowthCurve.

Numerical methods (Numerics.Mathematics)

  • EigenSolverMethod (Jacobi, QL) with the EigenValueDecomposition(Matrix A, EigenSolverMethod method) constructor. QL returns ascending eigenvalues, as numpy.linalg.eigh does. The one-argument constructor is unchanged.
  • AdaptiveGaussKronrodMethod (LocalBisection, Qags) and the AdaptiveGaussKronrod.Method property. The default stays LocalBisection.
  • Brent.Solve(f, lowerBound, upperBound, absoluteTolerance, relativeTolerance, maxIterations, reportFailure) and Brent.MinimumRelativeTolerance.
  • Dijkstra.ShortestDistances: double-precision multi-source shortest distances on a CSR graph, with optional predecessors and nearest sources.
  • CholeskyDecomposition.TryCholesky (non-throwing, with escalating diagonal jitter) and Matrix.TransposeMultiply.
  • Fourier.Convolve (real linear convolution) and Fourier.BluesteinFFT (any-length FFT).
  • Bessel.I0e and Bessel.I1e, and Evaluate.Chebyshev.
  • Optimizers: LBFGSB, CMAES, DynamicallyDimensionedSearch, ParetoFront, DynamicProgramming, DynamicProgrammingPath and Knapsack.
  • Optimizer.CancellationToken, Optimizer.Progress (OptimizationProgress) and ProgressInterval.
  • LocalMethod.LBFGSB for MultiStart and MLSL.
  • DifferentialEvolution.InitialPopulation and IntegerParameters, and UseParallel on DifferentialEvolution and ParticleSwarm.
  • BFGS.ScaleInitialInverseHessian.

Machine learning (Numerics.MachineLearning)

  • GaussianProcessRegression, with squared exponential, Matérn 3/2 and 5/2 and exponential kernels with ARD (GaussianProcessKernel, GaussianProcessMean).
  • Kriging (KrigingType, VariogramModel).
  • ElasticNetRegression: the Gaussian elastic net path by covariance-update coordinate descent, following glmnet, with k-fold cross-validation.
  • PrincipalComponentAnalysis (PrincipalComponentBasis).

Sampling and data

  • NUTS.LogLikelihoodAndGradientFunction: an opt-in combined value-and-gradient delegate.
  • LatinHypercube.Random and Median overloads that take a generator.
  • TimeSeries.AggregateByInterval.
  • TimeSeriesDownload.ParseUSGS, ParseGHCN, ParseCHMN and ParseABOM for saved responses, with opt-in qualifier overloads.

pynumerics

python/pynumerics is a new Python package, published to PyPI as pynumerics. It ships the Numerics.dll from this NuGet release byte for byte (SHA-256 checked), with one CoreCLR loader per process, bulk bit-exact NumPy marshalling, Python exceptions that carry the Numerics messages, and typed wrappers over every Numerics area. The modules include distributions, multivariate, copulas, regional, statistics, hypothesis_tests, goodness_of_fit, sampling, mcmc, bootstrap, integration, differentiation, roots, ode, optimization, graphs, special, linalg, mathematics, functions, timeseries, download and machine_learning. It requires CPython 3.10 to 3.14 on Linux or Windows and the .NET 10 runtime. See python/pynumerics/README.md, the guides in python/pynumerics/docs and python/pynumerics/CHANGELOG.md.

.github/workflows/PythonPublish.yml starts after NuGetPublish.yml has published RMC.Numerics to nuget.org. It builds the wheel from the nuget.org package, writes the package's version, assembly version and SHA-256 into it, tests it on Linux and Windows, and publishes it to TestPyPI and then, after approval, to PyPI with trusted publishing. Pull requests build the wheel from the PR source and run the same tests, including the Linux Docker image.

Performance

Measured speeds, with their conditions. Unless noted, results are bitwise unchanged.

  • QL eigensolver. SIMD tred2 and blocked tql2 rotations, applied by parallel tasks from n = 128, with the same bits as the sequential EISPACK procedures. On random Gram matrices (.NET 10) QL takes 3.4-3.7 ms at n = 200 and 47-49 ms at n = 500. Jacobi takes 165 ms and 3.3 s. numpy.linalg.eigh with its default threads takes 5.8-7.1 ms and 196-214 ms on the same machine. With one BLAS thread, eigh is faster from n = 100. PrincipalComponentAnalysis shares the tridiagonal path.
  • Poisson arrays. Through pynumerics, poisson_inverse_cdf is 3.9 times faster than scipy.stats.poisson.ppf at n = 200, 15 times at 1e4 and 31 times at 2e5, with no mismatches on 210,200 draws. The static array members run in parallel from 4096 elements. For short arrays in hot loops, the per-call cost makes the pynumerics log-mass wrappers slower than local NumPy code.
  • Dijkstra.ShortestDistances. Ten sources, five edges per node, against scipy.sparse.csgraph.dijkstra(min_only=True): 1.03 ms vs 1.65 ms at 1e4 nodes, 15.4 ms vs 24.6 ms at 1e5, and 473 ms vs 624 ms at 1e6 in .NET. Through pynumerics the times are 1.17, 17.8 and 573 ms. With thousands of sources, pynumerics and SciPy run at about the same speed end to end.
  • Tools.Expm1. For |x| > 1/2 it takes the direct difference, which is about 2.8 times as fast on .NET 10 and 1.9 times on .NET Framework 4.8.1, and more accurate (at most 1.06 ulp on (0.5, 10], down from 2.02 ulp).
  • Uncentered autocorrelation. Each lag sum is divided once by the lag-zero sum, and four lags accumulate per sweep of a contiguous array. The centered path is unchanged.
  • Column statistics. Parallel above a measured work threshold, with direct array access. Through pynumerics the batched calls are 16 to 30 times faster than per-column calls. Column L-moments and Anderson-Darling match or beat NumPy; column variance, standard deviation and Kolmogorov-Smirnov stay slower than NumPy at 60 × 2000, because copying the matrix into .NET alone costs more than NumPy's computation.
  • pynumerics marshalling. Arrays cross through the .NET array buffer protocol, and overloads and constructors are bound once. One-argument array callbacks add about 0.4 µs over raw pythonnet.

Numerical results that move

These members now return slightly different, more accurate values. Signatures are unchanged.

  • Root finding and optimization. Brent.Solve is a port of SciPy's brentq; its relative stopping term is 4.4e-16|x| (was 2.2e-16|b|), so roots move within tolerance. BrentSearch is a port of SciPy's bounded minimizer and starts at the golden-section point; iterates move at tolerance level. Fits that call either one internally (copulas, GEV, GPD, Mixture, NoncentralT, TruncatedNormal and others) move within tolerance. Powell and MultiStart fingerprints move by up to about 3e-9.
  • LogSumExp. Uses SciPy's evaluation (separated maximum, log1p and a Neumaier sum). Finite results move by a few ulp, and NUTS tree log-weights move in the last bits, so NUTS chains are not bitwise to 2.2.0.
  • GEV and GPA fits. L-moment fits, and the MLE and Bayesian starting values seeded from them, move. GPA method-of-moments fits move.
  • Pearson Type III and log-Pearson Type III.
    • The L-moment L2 and fit σ move by up to 4.9e-9 for |skew| ≤ 0.2.
    • InverseCDF and QuantileGradient use an order-8 Cornish-Fisher series for |skew| ≤ 0.03: quantiles move by up to about 3e-12 in standardized units, and gradients by up to 9.3e-8 relative.
    • The centered tails apply below skew 0.1, so LogCDF, LogCCDF and PDF move by up to 1.8e-13 for 0.01 ≤ |skew| < 0.1.
    • Log-Pearson Type III Mean, Variance and SD move by up to 5.1e-14 relative.
    • GammaDistribution.FrequencyFactorKp no longer snaps to z for |C| < 1e-4, so Wilson-Hilferty quantiles move by up to 3.6e-4 in that band.
  • Gamma-family quantiles and gradients. These move through the inverse incomplete gamma, Trigamma and the log-tail shape derivative: Gamma, Pearson Type III and log-Pearson Type III InverseCDF, QuantileGradient and maximum-likelihood covariances, Dirichlet sampling, and the multivariate t CDF.
  • StudentT and Beta. StudentT CDF and InverseCDF move for ν ≥ 30, which reaches t-tests, LinearTrendTest and regression p-values. Beta-family values move in the regions where the incomplete beta and log-beta changed.
  • Variance, covariance and Pearson. These move by about 1e-14 on ordinary data.
  • Percentiles. Plotting-position percentiles with Weibull, Blom and Hazen weights move by up to 12 ulp. Median, Cunnane and Gringorten are unchanged.
  • Copulas.
    • Joe, Gumbel, Clayton and Frank densities: Gumbel moves by up to 3e-10, Clayton and Frank by about 1e-14, and Joe by the corrections above.
    • Copula likelihood fits move.
    • Seeded draws from Gumbel and Joe move v by up to 2.5e-9; u is unchanged.
    • The Clayton generator follows Nelsen's normalized form, so its outputs are scaled by 1/θ.
  • Tools.Expm1 and Tools.Log1p callers. Expm1 for |x| > 1/2 and Log1p for |x| > 1e-4 move at the ulp level. This reaches about 116 call sites, including the copulas, KappaFour, GEV, GPD, the lognormal family, Exponential, Gumbel, Weibull, Pareto and Rayleigh, and the gamma family through Log1mExp.
  • Mode. KDE and Truncated modes move to the global peak. For unimodal bases, TruncatedDistribution.Mode returns the closed-form mode, moving by up to 7.5e-8 absolute toward the exact value.
  • Linear algebra.
    • CholeskyDecomposition, Solve and the inverse use a blocked kernel for n ≥ 16; values move by more than 1e-12 relative only for ill-conditioned matrices (κ above about 1e5). Below n = 16 every bit is unchanged.
    • GaussianMixtureModel moves by at most 2.3e-13 relative at dimension 16 and above, and its M-step computes the covariances about the updated means, which moves results in the last bits.
    • ElasticNetRegression moves in the last bits on hardware with FMA.
  • Other. Fourier.Autocorrelation (every lag after 0), GoodnessOfFit.PBIAS (sign), LinearRegression.PredictionIntervals and the RungeKutta Fehlberg and Cash-Karp steps change as described under Reliability and Fixes.

Unchanged:

  • The Bulletin 17C conditional moments (PearsonTypeIII.ConditionalMoments) are bitwise unchanged, as checked on a 104,196-record pin harness. Bulletin 17C integration bounds move by at most 1.8e-12.
  • The default AdaptiveGaussKronrod path (LocalBisection) is bitwise unchanged. QAGS runs only when Method = AdaptiveGaussKronrodMethod.Qags is set.
  • The Poisson and Binomial instance members, the compensated sums and the QL and Dijkstra speed work are bitwise unchanged.
  • GoodnessOfFit.KolmogorovSmirnov and AndersonDarling are bitwise unchanged for ascending input.

Platforms: .NET math functions such as Math.Exp, Log, Sin and Pow call the platform C library, which differs from Windows by about one ulp on some inputs. Results on Linux therefore agree with Windows closely but not bit for bit (the tests measured differences of 1 to 423 ulp, at most about 1e-13 relative), and seeded MCMC chains can diverge after many steps while keeping the same distribution. The tests record exact references on Windows and state their tolerance on other platforms.

Install

dotnet add package RMC.Numerics --version 2.3.0

Python (CPython 3.10 to 3.14 on Linux or Windows, with the .NET 10 runtime installed):

pip install pynumerics==2.3.0