Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/Github.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ jobs:
- name: Run tests
run: cargo test --verbose --features "arrow complex csv indexmap json num-complex parallel parquet rayon rkyv serde"

# The deterministic core (no `rand` stack) must keep building for sandboxed
# targets such as Typst / wasm plugins (#88).
no-rand-wasm:
name: No-rand core (wasm32)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Add wasm32 target
run: rustup target add wasm32-unknown-unknown
- name: Test without the rand stack
run: cargo test --verbose --no-default-features
- name: Build for wasm32
run: cargo build --verbose --no-default-features --target wasm32-unknown-unknown

feature-combinations:
name: Feature combinations (cargo-hack)
runs-on: ubuntu-latest
Expand Down
32 changes: 28 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ criterion = { version = "0.5.1", features = ["html_reports"] }

[dependencies]
csv = { version = "1.3", optional = true, default-features = false }
rand = { version = "0.9", features = ["small_rng"] }
rand_distr = "0.5"
rand = { version = "0.9", features = ["small_rng"], optional = true }
rand_distr = { version = "0.5", optional = true }
order-stat = "0.1"
puruspe = "0.4"
matrixmultiply = { version = "0.3", features = ["threading"] }
Expand All @@ -54,6 +54,7 @@ parquet = { version = "55", features = ["arrow", "snap"], optional = true }
arrow = { version = "55", optional = true }
indexmap = { version = "1", optional = true }
num-complex = { version = "0.4", optional = true }
num-traits = { version = "0.2", optional = true }
rayon = { version = "1.10", optional = true }

[package.metadata.docs.rs]
Expand All @@ -75,8 +76,31 @@ features = [
"serde",
]

# Examples that exercise the random sampling stack are skipped when the
# `rand` feature is disabled.
[[example]]
name = "dist"
required-features = ["rand"]

[[example]]
name = "matmul"
required-features = ["rand"]

[[example]]
name = "optim"
required-features = ["rand"]

[[example]]
name = "clippy_verify"
required-features = ["rand"]

[features]
default = []
default = ["rand"]
# Random sampling stack (`rand` / `rand_distr`): probability distributions,
# RNG wrappers, and random constructors. Enabled by default; disable with
# `default-features = false` for the deterministic core (ODE, integration,
# splines, linear algebra), e.g. for wasm32 sandboxes without IO.
rand = ["dep:rand", "dep:rand_distr"]
# Bare BLAS / LAPACK FFI; downstream binary must also pull in a
# `blas-src` / `lapack-src` backend to resolve the link symbols.
O3 = ["blas", "lapack"]
Expand All @@ -88,5 +112,5 @@ O3-netlib = ["O3", "blas-src/netlib", "lapack-src/netlib"]
plot = ["pyo3"]
nc = ["netcdf"]
parquet = ["dep:parquet", "arrow", "indexmap"]
complex = ["num-complex", "matrixmultiply/cgemm"]
complex = ["num-complex", "num-traits", "matrixmultiply/cgemm"]
parallel = ["rayon"]
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ The remaining single-crate flags exist so advanced users can pull in just one op
| `json` | (pure Rust) | JSON I/O for `DataFrame` |
| `serde` | (pure Rust) | `serde` (de)serialization |
| `rkyv` | (pure Rust) | `rkyv` zero-copy (de)serialization |
| `rand` | (pure Rust) | Random sampling stack: distributions, RNG wrappers, `rand()` constructors. **On by default**; disable with `default-features = false` to get the deterministic core (ODE, integration, splines, linear algebra) for sandboxed targets like wasm32 |

<details>
<summary><b>Advanced: single-crate flags</b></summary>
Expand Down
2 changes: 1 addition & 1 deletion src/complex/matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use std::{
use anyhow::{bail, Result};
use matrixmultiply::CGemmOption;
use num_complex::Complex;
use num_traits::{One, Zero};
use peroxide_num::{ExpLogOps, PowOps, TrigOps};
use rand_distr::num_traits::{One, Zero};

use crate::{
complex::C64,
Expand Down
12 changes: 10 additions & 2 deletions src/fuga/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,17 @@ pub use crate::complex::{integral::*, matrix::*, vector::*, C64};
#[allow(ambiguous_glob_reexports)]
pub use crate::structure::{ad::*, dataframe::*, matrix::*, polynomial::*, vector::*};

pub use crate::util::{api::*, low_level::*, non_macro::*, print::*, useful::*, wrapper::*};
pub use crate::util::{api::*, low_level::*, non_macro::*, print::*, useful::*};

#[cfg(feature = "rand")]
pub use crate::util::wrapper::*;

#[allow(unused_imports)]
pub use crate::statistics::{ops::*, stat::*};

#[cfg(feature = "rand")]
#[allow(unused_imports)]
pub use crate::statistics::{dist::*, ops::*, rand::*, stat::*};
pub use crate::statistics::{dist::*, rand::*};

#[allow(unused_imports)]
pub use crate::special::function::*;
Expand All @@ -205,6 +212,7 @@ pub use crate::util::plot::*;

pub use anyhow;
pub use paste;
#[cfg(feature = "rand")]
pub use rand::prelude::*;

// =============================================================================
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ extern crate pyo3;
#[cfg(feature = "serde")]
extern crate serde;

#[cfg(feature = "rand")]
extern crate rand;

// extern crate json;
Expand Down
1 change: 1 addition & 0 deletions src/macros/matlab_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ macro_rules! zeros {
/// println!("{}", a); // 2 x 2 random matrix (0 ~ 1)
/// }
/// ```
#[cfg(feature = "rand")]
#[macro_export]
macro_rules! rand {
() => {{
Expand Down
7 changes: 7 additions & 0 deletions src/macros/r_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ macro_rules! rbind {
/// println!("{:?}", b);
/// }
/// ```
#[cfg(feature = "rand")]
#[macro_export]
macro_rules! runif {
( $x0:expr, $start:expr, $end:expr ) => {{
Expand Down Expand Up @@ -304,6 +305,7 @@ macro_rules! runif {
/// println!("{:?}", b);
/// }
/// ```
#[cfg(feature = "rand")]
#[macro_export]
macro_rules! rnorm {
( $n:expr, $mean:expr, $sd:expr ) => {{
Expand Down Expand Up @@ -333,6 +335,7 @@ macro_rules! rnorm {
/// println!("{:?}", b);
/// }
/// ```
#[cfg(feature = "rand")]
#[macro_export]
macro_rules! dnorm {
( $x:expr, $mean: expr, $sd:expr ) => {{
Expand Down Expand Up @@ -364,6 +367,7 @@ macro_rules! dnorm {
/// println!("{:?}", b);
/// }
/// ```
#[cfg(feature = "rand")]
#[macro_export]
macro_rules! pnorm {
( $x:expr, $mean:expr, $sd:expr ) => {{
Expand Down Expand Up @@ -392,6 +396,7 @@ macro_rules! pnorm {
/// println!("{:?}", a);
/// }
/// ```
#[cfg(feature = "rand")]
#[macro_export]
macro_rules! rt {
( $n:expr, $df:expr ) => {{
Expand All @@ -414,6 +419,7 @@ macro_rules! rt {
/// println!("{:?}", a);
/// }
/// ```
#[cfg(feature = "rand")]
#[macro_export]
macro_rules! dt {
( $x:expr, $df:expr ) => {{
Expand All @@ -437,6 +443,7 @@ macro_rules! dt {
/// println!("{:?}", a); // 0.5
/// }
/// ```
#[cfg(feature = "rand")]
#[macro_export]
macro_rules! pt {
( $x:expr, $df:expr ) => {{
Expand Down
2 changes: 2 additions & 0 deletions src/numerical/optimize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
//! use peroxide::fuga::*;
//!
//! fn main() {
//! # #[cfg(feature = "rand")] {
//! // To prepare noise
//! let normal = Normal(0f64, 0.1f64);
//! let normal2 = Normal(0f64, 100f64);
Expand Down Expand Up @@ -94,6 +95,7 @@
//! // .set_marker(vec![Point, Line])
//! // .savefig().expect("Can't draw a plot");
//! //}
//! # }
//! }
//!
//! fn quad(x: &Vec<f64>, n: Vec<AD>) -> Option<Vec<AD>> {
Expand Down
13 changes: 11 additions & 2 deletions src/prelude/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,18 @@ pub use crate::complex::{integral::*, matrix::*, vector::*, C64};
pub use simpler::{solve, SimplerLinearAlgebra};

#[allow(unused_imports)]
pub use crate::util::{api::*, low_level::*, non_macro::*, print::*, useful::*, wrapper::*};
pub use crate::util::{api::*, low_level::*, non_macro::*, print::*, useful::*};

#[cfg(feature = "rand")]
#[allow(unused_imports)]
pub use crate::statistics::{dist::*, ops::*, rand::*, stat::*};
pub use crate::util::wrapper::*;

#[allow(unused_imports)]
pub use crate::statistics::{ops::*, stat::*};

#[cfg(feature = "rand")]
#[allow(unused_imports)]
pub use crate::statistics::{dist::*, rand::*};

#[allow(unused_imports)]
pub use crate::special::function::{
Expand Down Expand Up @@ -228,4 +236,5 @@ pub use crate::util::plot::*;

pub use anyhow;
pub use paste;
#[cfg(feature = "rand")]
pub use rand::prelude::*;
6 changes: 4 additions & 2 deletions src/statistics/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
//! Statistical Modules
//!
//! * Basic statistical tools - `stat.rs`
//! * Popular distributions - `dist.rs`
//! * Simple Random Number Generator - `rand.rs`
//! * Popular distributions - `dist.rs` (`rand` feature)
//! * Simple Random Number Generator - `rand.rs` (`rand` feature)
//! * Basic probabilistic operations - `ops.rs`

#[cfg(feature = "rand")]
pub mod dist;
pub mod ops;
#[cfg(feature = "rand")]
pub mod rand;
pub mod stat;
2 changes: 2 additions & 0 deletions src/statistics/stat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,7 @@ pub fn cor(v1: &Vec<f64>, v2: &Vec<f64>) -> f64 {
/// use peroxide::fuga::*;
///
/// fn main() {
/// # #[cfg(feature = "rand")] {
/// let a: Matrix = c!(1,2,3,4,5).into();
/// let noise: Matrix = Normal(0,1).sample(5).into();
/// let b: Matrix = &a + &noise;
Expand All @@ -560,6 +561,7 @@ pub fn cor(v1: &Vec<f64>, v2: &Vec<f64>) -> f64 {
/// // c[0]
/// // r[0] 0.7219
/// // r[1] 0.8058
/// # }
/// }
/// ```
pub fn lm(input: &Matrix, target: &Matrix) -> Matrix {
Expand Down
2 changes: 2 additions & 0 deletions src/structure/matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,10 @@
//! let b = eye(2);
//! assert_eq!(b, ml_matrix("1 0;0 1"));
//!
//! # #[cfg(feature = "rand")] {
//! let c = rand(2, 2);
//! c.print(); // Random 2x2 matrix
//! # }
//! }
//! ```
//! # Linear Algebra
Expand Down
1 change: 1 addition & 0 deletions src/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ pub mod plot;
pub mod low_level;
pub mod print;
pub mod useful;
#[cfg(feature = "rand")]
pub mod wrapper;
pub mod writer;
6 changes: 6 additions & 0 deletions src/util/non_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
//! - concat
//! - cat

#[cfg(feature = "rand")]
extern crate rand;
#[cfg(feature = "rand")]
use self::rand::prelude::*;
use crate::structure::{
matrix::Shape::{Col, Row},
Expand All @@ -39,6 +41,7 @@ use crate::structure::{
use crate::traits::float::FloatWithPrecision;
use crate::traits::matrix::MatrixTrait;
use anyhow::{bail, Result};
#[cfg(feature = "rand")]
use rand_distr::{Distribution, Uniform};

#[derive(Debug, Copy, Clone)]
Expand Down Expand Up @@ -322,6 +325,7 @@ where
/// # Description
///
/// Range = from 0 to 1
#[cfg(feature = "rand")]
pub fn rand(r: usize, c: usize) -> Matrix {
let mut rng = rand::rng();
rand_with_rng(r, c, &mut rng)
Expand All @@ -332,6 +336,7 @@ pub fn rand(r: usize, c: usize) -> Matrix {
/// # Description
///
/// Range = from 0 to 1
#[cfg(feature = "rand")]
pub fn rand_with_rng<R: Rng>(r: usize, c: usize, rng: &mut R) -> Matrix {
let uniform = Uniform::new_inclusive(0f64, 1f64).unwrap();
rand_with_dist(r, c, rng, uniform)
Expand All @@ -342,6 +347,7 @@ pub fn rand_with_rng<R: Rng>(r: usize, c: usize, rng: &mut R) -> Matrix {
/// # Description
///
/// Any range
#[cfg(feature = "rand")]
pub fn rand_with_dist<T: Into<f64>, R: Rng, D: Distribution<T>>(
r: usize,
c: usize,
Expand Down
8 changes: 7 additions & 1 deletion src/util/print.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Easy to print any structures

#[cfg(feature = "rand")]
use crate::statistics::dist::*;
use crate::statistics::stat::ConfusionMatrix;
#[allow(unused_imports)]
Expand All @@ -10,8 +11,11 @@ use crate::structure::{
multinomial::Multinomial,
polynomial::Polynomial,
};
#[cfg(feature = "rand")]
use rand_distr::uniform::SampleUniform;
use std::fmt::{Debug, LowerExp, UpperExp};
#[cfg(feature = "rand")]
use std::fmt::Debug;
use std::fmt::{LowerExp, UpperExp};

pub trait Printable {
fn print(&self);
Expand Down Expand Up @@ -355,12 +359,14 @@ impl Printable for Multinomial {
// }
//}

#[cfg(feature = "rand")]
impl<T: Debug + PartialOrd + SampleUniform + Copy + Into<f64>> Printable for OPDist<T> {
fn print(&self) {
println!("{:?}", self);
}
}

#[cfg(feature = "rand")]
impl<T: Debug + PartialOrd + SampleUniform + Copy + Into<f64>> Printable for TPDist<T> {
fn print(&self) {
println!("{:?}", self);
Expand Down
2 changes: 2 additions & 0 deletions tests/dist.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![cfg(feature = "rand")]

extern crate peroxide;
use peroxide::fuga::*;

Expand Down
1 change: 1 addition & 0 deletions tests/matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ fn test_row() {
assert_eq!(a.row(0), c!(1, 2));
}

#[cfg(feature = "rand")]
#[test]
fn test_print() {
let op = Bernoulli(0);
Expand Down
2 changes: 2 additions & 0 deletions tests/weighted_uniform.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![cfg(feature = "rand")]

extern crate peroxide;
use peroxide::fuga::*;

Expand Down
Loading