NAME
Math::Histo - Fast, memory-safe C histogramming and statistical computing for Perl
SYNOPSIS
use Math::Histo;
# Uniform 1D histogram (50 bins in [0, 100], tracking sum(w^2))
my $h = Math::Histo->new(bins => 50, min => 0.0, max => 100.0, sumw2 => 1);
# Variable-width binning
my $h_var = Math::Histo->new(edges => [0.0, 1.0, 5.0, 10.0, 50.0, 100.0]);
# Ingestion: scalar, batch arrayref, or packed binary doubles
$h->fill(42.5);
$h->fill(84.0, 2.5); # with weight 2.5
$h->fill_n([10.5, 20.2, 30.8, 42.1]);
$h->fill_packed_f64($packed_doubles_scalar);
# Statistical summaries
printf("Entries: %d, Total Weight: %.2f\n", $h->num_entries, $h->total_weight);
printf("Mean: %.4f +/- %.4f\n", $h->mean, $h->std_dev);
printf("Median: %.4f (IQR: %.4f, MAD: %.4f)\n", $h->median, $h->iqr, $h->mad);
printf("Skewness: %.4f, Excess Kurtosis: %.4f\n", $h->skewness, $h->excess_kurtosis);
# Continuous peak detection
my $mode = $h->mode;
printf("Continuous Mode: %.4f (FWHM: %.4f, RMS: %.4f)\n", $mode, $h->fwhm, $h->rms);
# Non-linear curve fitting (Levenberg-Marquardt)
my $fit = $h->fit(model => 'gaussian');
print $fit->summary;
# Operator overloading
my $h2 = $h * 2.0;
my $sum = $h + $h2;
print "$h\n"; # stringification
# Two-sample hypothesis testing & distance metrics
my ($chi2, $ndf) = $h->chi2_test($h2);
my $ks = $h->kolmogorov_smirnov($h2);
my $w1 = $h->wasserstein_distance($h2);
my $bhat = $h->bhattacharyya_distance($h2);
my $kl = $h->kl_divergence($h2);
# Zero-loss binary wire format and JSON serialization
my $blob = $h->serialize_binary;
my $restored = Math::Histo->from_binary($blob);
$h->write_file('data.histo', format => 'binary');
DESCRIPTION
Math::Histo is a high-performance Perl XS wrapper for the libhisto C library. It provides SIMD-accelerated 1D and 2D histogramming, online Welford statistical moments, non-linear curve fitting (Levenberg-Marquardt), and streaming dynamic quantile sketches (DDSketch).
CONSTRUCTORS
- new(%options)
-
Creates a new 1D histogram.
Uniform binning options: bins => $count (or nbins => $count) min => $min_val (default: 0.0) max => $max_val (default: 100.0)
Variable binning options: edges => [ $e0, $e1, $e2, ... ] (strictly monotonically increasing)
Feature flags: sumw2 => 1 (track per-bin sum of weights squared for error propagation) exact_moments => 1 (track running mean/variance during fill operations)
- clone()
-
Creates an exact deep copy of the histogram.
- from_binary($byte_string)
-
Deserializes a histogram from canonical Little-Endian binary format.
- from_json($json_string)
-
Deserializes a histogram from a JSON string.
- from_file($filename)
-
Autodetects format (binary wire format or JSON) and loads the histogram from disk.
INGESTION METHODS
- fill($x, [$weight=1.0])
-
Fills a single coordinate with optional weight. Returns 1 on success, 0 on non-finite rejection.
- fill_n(\@x, [\@weights])
-
Batch fills an arrayref of coordinates and optional weights.
- fill_packed_f64($packed_x, [$packed_w]) (or fill_packed)
-
High-performance zero-copy batch fill from raw packed 64-bit IEEE double scalars (e.g.
pack("d*", ...)orPDL::get_dataref). - reset()
-
Resets all bin contents, moments, and out-of-range counters to zero.
BIN ACCESS & GEOMETRY
- nbins(): Number of bins.
- min(): Lower range boundary.
- max(): Upper range boundary.
- is_uniform(): Returns 1 if uniform binning, 0 if variable-width binning.
- bin_content($idx): Accumulated weight in bin $idx (0-indexed).
- bin_error($idx): Standard error in bin $idx (sqrt(sum_w2) or sqrt(content)).
- bin_sum_w2($idx): Sum of weights squared in bin $idx.
- bin_low_edge($idx): Lower edge coordinate of bin $idx.
- bin_high_edge($idx): Upper edge coordinate of bin $idx.
- bin_center($idx): Geometric center coordinate of bin $idx.
- bin_width($idx): Width of bin $idx.
- bin_contents(): Returns an arrayref of all bin contents.
- bin_edges(): Returns an arrayref of all bin edges (length nbins + 1).
- find_bin($x): Returns the 0-indexed bin index for coordinate $x (-1 for underflow, nbins for overflow).
- underflow_weight(): Total weight accumulated below min.
- overflow_weight(): Total weight accumulated above max.
- nan_count(): Total count of non-finite (NaN) samples rejected.
STATISTICAL ANALYSIS
- num_entries(): Total number of in-range fill operations.
- total_weight(): Total accumulated in-range weight sum.
- mean(): Sample mean.
- variance(): Sample variance.
- std_dev(): Sample standard deviation.
- skewness(): Distribution skewness (gamma_1).
- kurtosis(): Distribution kurtosis (beta_2).
- excess_kurtosis(): Excess kurtosis (gamma_2 = beta_2 - 3).
- central_moment($order): Central statistical moment of given order.
- median(): Estimated median (50th percentile).
- quantile($p): Continuous piecewise linear quantile for $p in [0, 1].
- iqr(): Interquartile Range (Q75 - Q25).
- mad(): Median Absolute Deviation from median.
- mode(): Continuous mode peak coordinate estimated via parabolic interpolation.
- fwhm(): Full Width at Half Maximum of dominant peak.
- rms(): Root Mean Square: sqrt(M2 + mean^2).
- trimmed_mean($fraction): Trimmed mean excluding tails.
- winsorized_mean($fraction): Winsorized mean replacing tails with quantile thresholds.
- integral(): Total integrated sum of bin weights.
- cdf([$prenormalization=1.0]): Returns a new
Math::Histoobject representing the cumulative distribution function. - stats(): Returns a hashref containing complete summary statistics.
ARITHMETIC & TRANSFORMATIONS
- scale($factor): In-place scalar multiplication.
- normalize([$target_area=1.0]): In-place normalization.
- rebin($factor): Returns a new histogram with adjacent uniform bins combined.
- add($other), subtract($other), multiply($other), divide($other): In-place element-wise arithmetic.
- Overloaded operators:
+,-,*,/,"".
TWO-SAMPLE DISTANCE METRICS
- chi2_test($other): Returns
($chi2, $ndf). - kolmogorov_smirnov($other): Two-sample Kolmogorov-Smirnov supremum distance.
- wasserstein_distance($other): 1D Earth Mover's Distance (L1 CDF integral).
- kl_divergence($other): Kullback-Leibler divergence D_KL(self || other).
- bhattacharyya_distance($other): Bhattacharyya distance between distributions.
CURVE FITTING
- fit(%args)
-
Fits a parametric model to the histogram using the Levenberg-Marquardt non-linear optimizer.
Parameters: model => 'gaussian' | 'exponential' | 'polynomial' | 'breit_wigner' | 'power_law' initial => [ ... ] (optional initial guesses, auto-estimated if omitted) lower => [ ... ] (optional lower parameter bounds) upper => [ ... ] (optional upper parameter bounds) fixed => [ 0, 1, ... ] (optional boolean flags to freeze specific parameters) max_iter => 200 (maximum iterations) tol => 1e-8 (relative tolerance) mle => 1 (use Poisson MLE deviance instead of Chi2)
Returns a Math::Histo::Fit::Result object.
SERIALIZATION
- serialize_binary(): Returns scalar byte string in canonical Little-Endian wire format.
- serialize_json([$pretty=0]): Returns JSON string representation.
- write_file($path, [format = 'binary'|'json'])>: Writes histogram directly to disk.
PERFORMANCE & BENCHMARKS
Math::Histo leverages C99 core algorithms, cache-conscious memory layout, and runtime-detected AVX2 / AVX-512 / ARM NEON vector instructions. While individual method invocations incur standard Perl XS sub-call overhead (~50 ns), bulk ingestion methods (fill_n and fill_packed_f64) bypass Perl interpreter loop overhead to achieve throughput exceeding 450+ Million operations/second.
Benchmark measured on an Intel(R) Core(TM) Ultra 7 255HX (Linux x86_64, Perl 5.40):
+---------------------------------+--------------+------------+----------------+------------+
| Benchmark Operation | Count | Time | Throughput | Latency |
+=================================+==============+============+================+============+
| 1D Uniform Fill (method call) | 2,000,000 ops| 0.099 s | 20.28 Mops/s | 49.3 ns/op |
| 1D Weighted Fill + sumw2 | 2,000,000 ops| 0.103 s | 19.35 Mops/s | 51.7 ns/op |
| 1D Variable Bins (100 bins) | 2,000,000 ops| 0.156 s | 12.79 Mops/s | 78.2 ns/op |
| 1D Batch Arrayref (fill_n) | 2,000,000 ops| 0.033 s | 61.02 Mops/s | 16.4 ns/op |
| 1D Packed f64 Buffer (SIMD) | 5,000,000 ops| 0.011 s | 454.46 Mops/s | 2.20 ns/op|
| 2D Uniform Fill (method call) | 2,000,000 ops| 0.109 s | 18.38 Mops/s | 54.4 ns/op |
| 2D Packed f64 Buffer (SIMD) | 5,000,000 ops| 0.018 s | 281.26 Mops/s | 3.56 ns/op|
| DDSketch Dynamic Insert | 2,000,000 ops| 0.121 s | 16.47 Mops/s | 60.7 ns/op |
| DDSketch Packed Buffer | 5,000,000 ops| 0.067 s | 74.21 Mops/s | 13.48 ns/op|
+---------------------------------+--------------+------------+----------------+------------+
To run the benchmark suite on your machine:
perl -Iblib/lib -Iblib/arch bench/bench_fill.pl
IN-DEPTH DOCUMENTATION & ALGORITHMIC COMPLEXITY
For detailed documentation on underlying algorithms, mathematical proofs, IEEE-754 numerical behavior, SIMD vectorization kernels, and asymptotic time/space complexity tables, please refer to the main C library manual:
HTML Manual & Architecture Guides: https://github.com/tsee/libhisto
Serialization Wire Format Specification: https://github.com/tsee/libhisto/blob/main/docs/serialization_format.md
Statistical Formulae & Derivations: https://github.com/tsee/libhisto/blob/main/docs/statistical_formulae.md
Curve Fitting Guide: https://github.com/tsee/libhisto/blob/main/docs/curve_fitting_guide.md
SEE ALSO
Math::Histo::2D - 2-Dimensional Histograms with Projections and Slices
Math::Histo::Fit - Non-Linear Curve Fitting Engine
Math::Histo::Sketch - DDSketch Relative-Error Streaming Quantile Sketches
Math::Histo::Constants - Status Codes and Feature Flags
Alien::libhisto - libhisto C Library Provider
AUTHOR
Steffen Mueller <cpan@steffen-mueller.net>
LICENSE
MIT License. Copyright (c) 2026 Steffen Mueller and libhisto contributors.