The zprob
module implements functionality for working with probability distributions in Zig,
including generating random samples and calculating probabilities using mass/density functions.
Discrete Probability Distributions
Bernoulli :: Binomial :: Geometric :: Multinomial :: Negative Binomial :: Poisson
Continuous Probability Distributions
Beta :: Chi-squared :: Dirichlet :: Exponential :: Gamma :: Multivariate Normal (sampling only) :: Normal
Note
zprob
was developed and tested using v0.11.0 of Zig and is still a work in progress. Using a version of Zig other than 0.11.0 may lead to the code not compiling.
TODO:
- Multivariate Normal (PDF + log-PDF)
- Integrate with new module system in Zig v0.11.0
To use zprob
in a nice, fresh new Zig project, you can include it as
a git submodule within a dedicated subfolder in you main project folder (e.g.,
libs/
). Below is a simple example for how you could start such a project:
# Make new project folder with libs/ subfolder inside
mkdir -p my_zig_proj/libs
# Change into new project folder and initialize as a git repo
cd my_zig_proj/ && git init
# Initialize a new Zig command line application
zig init-exe
# Add zprob as a git submodule in the libs/ folder
git submodule add https://github.com/pblischak/zprob.git libs/zprob
To include zprob
as a module to your new project, you'll only need to add two lines to
the default build script:
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// ** 1. Here we define the zprob module and the path to the main file
const zprob_module = b.addModule(
"zprob",
.{ .source_file = .{ .path = "libs/zprob/src/zprob.zig" } }
);
const exe = b.addExecutable(.{
.name = "zprob_demo",
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
// ** 2. Here we add the zprob module to our executable
exe.addModule("zprob", zprob_module);
exe.install();
const run_cmd = exe.run();
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
const exe_tests = b.addTest(.{
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&exe_tests.step);
}
Now, inside the src/main.zig
file in your project, you can import zprob
like any other
module:
const zprob = @import("zprob");
This repo contains a few simple examples of how to use the random sampling functionality
implemented in zprob
. To build the examples, clone the repo and run
zig build examples
:
git clone https://github.compblischak/zprob.git
cd zprob/
zig build examples
Each example file should compile into a binary executable with the same name in the zig-out/bin
folder.
Using the current time in microseconds
- How to use the random number generator in Zig
const std = @import("std");
const seed = @intCast(u64, std.time.microTimestamp());
var prng = std.rand.Xoshiro256.init(seed);
const rand = prng.random();
Using /dev/urandom
const std = @import("std");
var prng = std.rand.Xoshiro256.init(blk: {
var seed: u64 = undefined;
try std.os.getrandom(std.mem.asBytes(&seed));
break :blk seed;
});
const rand = prng.random();
Code from the following repositories helped guide the development of zprob
:
- Some of the sampling algorithms are translated to Zig from
ranlib.c
. - The Odin-lang rand libraries.
- The zig-gamedev Zig libraries.
- The rand_distr Rust library.