Package: numba-stats
numba-statsWe providenumba-accelerated implementations of statistical distributions for common probability distributionsUniform(Truncated) NormalLog-normalPoisson(Truncated) ExponentialStudent's tVoigtianCrystal BallGeneralised double-sided Crystal BallTsallis-Hagedorn, a model for the minimum bias pT distributionQ-GaussianBernstein density (not normalized to unity, use this in extended likelihood fits)Cruijff density (not normalized to unity, use this in extended likelihood fits)with more to come. The speed gains are huge, up to a factor of 100 compared toscipy. Benchmarks are included in the repository and are run bypytest.The distributions are optimized for the use in maximum-likelihood fits, where you query a distribution at many points with a single set of parameters.UsageEach distribution is implemented in a submodule. Import the submodule that you need and call the functions in the module.fromnumba_statsimportnormimportnumpyasnpx=np.linspace(-10,10)mu=2.0sigma=3.0p=norm.pdf(x,mu,sigma)c=norm.cdf(x,mu,sigma)The functions are vectorized on the variatex, but not on the shape parameters of the distribution. Ideally, the following functions are implemented for each distribution:pdf: probability density functionlogpdf: the logarithm of the probability density function (can be computed more efficiently and accurately for some distributions)cdf: integral of the probability density functionppf:inverse of the cdfrvs: to generate random variatescdfandppfare missing for some distributions (e.g.voigt), if there is currently no fast implementation available.logpdfis only implemented if it is more efficient and accurate compared to computinglog(dist.pdf(...)).rvsis only implemented for distributions that haveppf, which is used to generate the random variates. The implementations ofrvsare currently not optimized for highest performance, but turn out to be useful in practice nevertheless.The distributions innumba_statscan be used in othernumba-JIT'ed functions. The functions innumba_statsuse a single thread, but the implementations were written so that they profit from auto-parallelization. To enable this, call them from a JIT'ed function with the argumentparallel=True,fastmath=True. You should always combineparallel=Truewithfastmath=True, since the latter enhances the gain from auto-parallelization.fromnumba_statsimportnormimportnumbaasnbimportnumpyasnp@nb.njit(parallel=True,fastmath=True)defnorm_pdf(x,mu,sigma):returnnorm.pdf(x,mu,sigma)# this must be an array of floatx=np.linspace(-10,10)# these must be floatsmu=2.0sigma=3.0# uses all your CPU coresp=norm_pdf(x,mu,sigma)Note that this is only faster ifxhas sufficient length (about 1000 elements or more). Otherwise, the parallelization overhead will make the call slower, see benchmarks below.TroubleshootingWhen you use the numba-stats distributions in a compiled function, you need to pass the expected data types. The first argument must be numpy array of floats (32 or 64 bit). The following parameters must be floats. If you pass the wrong arguments, you will get numba errors similar to this one (where parameters were passed as integer instead of float):numba.core.errors.TypingError: Failed in nopython mode pipeline (step: nopython frontend)
No implementation of function Function(<function pdf at 0x7ff7186b7be0>) found for signature:

 >>> pdf(array(float64, 1d, C), int64, int64)You won't get these errors when you call the numba-stats PDFs outside of a compiled function, because I added some wrappers which automatically convert the data types for convenience. This is why you can callnorm.pdf(1, 2, 3)butnorm_pdf(1, 2, 3)(as implemented above) will fail.BenchmarksThe following benchmarks were produced on an Intel(R) Core(TM) i7-8569U CPU @ 2.80GHz against SciPy-1.10.1. The dotted line on the right-hand figure shows the expected speedup (4x) from parallelization on a CPU with four physical cores.We see large speed-ups with respect toscipyfor almost all distributions. Also calls with short arrays profit fromnumba_stats, due to the reduced call-overhead. The functionsvoigt.pdfandt.ppfdo not run faster than thescipyversions, because we call the respectivescipyimplementation written in FORTRAN. The advantage provided bynumba_statshere is that you can call these functions from othernumba-JIT'ed functions, which is not possible with thescipyimplementations, andvoigt.pdfstill profits from auto-parallelization.Thebernstein.densitydoes not profit from auto-parallelization, on the contrary it becomes much slower, so this should be avoided. This is a known issue, the internal implementation cannot be easily auto-parallelized.DocumentationTo get documentation, please usehelp()in the Python interpreter.Functions with equivalents inscipy.statsfollow thescipycalling conventions exactly, except for distributions starting withtrunc..., which follow a different convention, since thescipybehavior is very impractical. Even so, note that thescipyconventions are sometimes a bit unusual, particular in case of the exponential, the log-normal, and the uniform distribution. See thescipydocs for details.ContributionsYou can help with adding more distributions, patches are very welcome.Implementing a probability distribution is easy. You need to write it in simple Python thatnumbacan understand. Special functions fromscipy.specialcan be used after some wrapping, see submodulenumba_stats._special.pyhow it is done.numba-stats and numba-scipynumba-scipyis the official package and repository for fast numba-accelerated scipy functions, are we reinventing the wheel?Ideally, the functionality in this package should be innumba-scipyand we hope that eventually this will be case. In this package, we don't offer overloads for scipy functions and classes likenumba-scipydoes. This simplifies the implementation dramatically.numba-statsis intended as a temporary solution until fast statistical functions are included innumba-scipy.numba-statscurrently does not depend onnumba-scipy, only onnumbaandscipy.