Skip to main content

scirs2_wasm/
lib.rs

1//! # SciRS2-WASM: WebAssembly Bindings for SciRS2
2//!
3//! High-performance scientific computing in the browser and Node.js.
4//!
5//! ## Features
6//!
7//! - **Pure Rust**: 100% safe Rust code compiled to WASM
8//! - **SIMD Support**: Optional WASM SIMD (wasm32-simd128) acceleration
9//! - **Async Operations**: Non-blocking computations with async/await
10//! - **TypeScript Support**: Full TypeScript type definitions
11//! - **Memory Efficient**: Optimized memory management for browser environments
12//! - **Zero-copy**: Direct array buffer access when possible
13//!
14//! ## Modules
15//!
16//! - `array`: N-dimensional array operations
17//! - `linalg`: Linear algebra (matrix operations, decompositions)
18//! - `stats`: Statistical functions (distributions, tests, descriptive stats)
19//! - `fft`: Fast Fourier Transform operations
20//! - `signal`: Signal processing (filtering, convolution, wavelets)
21//! - `integrate`: Numerical integration and ODE solvers
22//! - `interpolate`: Interpolation (linear, spline, Lagrange, PCHIP, Akima)
23//! - `optimize`: Optimization algorithms (minimize, curve fitting)
24//! - `random`: Random number generation and distributions
25//!
26//! ## Example Usage (JavaScript)
27//!
28//! ```javascript
29//! import * as scirs2 from 'scirs2-wasm';
30//!
31//! // Initialize the library
32//! await scirs2.default();
33//!
34//! // Create arrays
35//! const a = scirs2.array([1, 2, 3, 4]);
36//! const b = scirs2.array([5, 6, 7, 8]);
37//!
38//! // Perform operations
39//! const sum = scirs2.add(a, b);
40//! const dot = scirs2.dot(a, b);
41//!
42//! // Statistical operations
43//! const mean = scirs2.mean(a);
44//! const std = scirs2.std(a);
45//!
46//! // Linear algebra
47//! const matrix = scirs2.array2d([[1, 2], [3, 4]]);
48//! const inv = scirs2.inv(matrix);
49//! const det = scirs2.det(matrix);
50//! ```
51
52#![deny(unsafe_op_in_unsafe_fn)]
53#![warn(missing_docs)]
54
55use wasm_bindgen::prelude::*;
56use web_sys::console;
57
58pub mod array;
59pub mod error;
60pub mod fft;
61pub mod integrate;
62pub mod interpolate;
63pub mod linalg;
64pub mod optimize;
65pub mod random;
66pub mod signal;
67pub mod stats;
68pub mod utils;
69
70/// Initialize the WASM module with panic hooks and logging
71#[wasm_bindgen(start)]
72pub fn init() {
73    // Set panic hook for better error messages in the console
74    #[cfg(feature = "console_error_panic_hook")]
75    console_error_panic_hook::set_once();
76
77    // Log initialization message
78    log("SciRS2-WASM initialized successfully");
79}
80
81/// Get the version of SciRS2-WASM
82#[wasm_bindgen]
83pub fn version() -> String {
84    env!("CARGO_PKG_VERSION").to_string()
85}
86
87/// Log a message to the browser console
88#[wasm_bindgen]
89pub fn log(message: &str) {
90    console::log_1(&JsValue::from_str(message));
91}
92
93/// Check if WASM SIMD is supported in the current environment
94#[wasm_bindgen]
95pub fn has_simd_support() -> bool {
96    #[cfg(target_feature = "simd128")]
97    {
98        true
99    }
100    #[cfg(not(target_feature = "simd128"))]
101    {
102        false
103    }
104}
105
106/// Get system capabilities and features available in this build
107#[wasm_bindgen]
108pub fn capabilities() -> JsValue {
109    let caps = serde_json::json!({
110        "version": env!("CARGO_PKG_VERSION"),
111        "simd": has_simd_support(),
112        "features": {
113            "array": true,
114            "linalg": cfg!(feature = "linalg"),
115            "stats": cfg!(feature = "stats"),
116            "fft": cfg!(feature = "fft"),
117            "signal": cfg!(feature = "signal"),
118            "integrate": cfg!(feature = "integrate"),
119            "optimize": cfg!(feature = "optimize"),
120            "interpolate": cfg!(feature = "interpolate"),
121        },
122        "target": {
123            "arch": std::env::consts::ARCH,
124            "os": "wasm32",
125            "family": std::env::consts::FAMILY,
126        }
127    });
128
129    serde_wasm_bindgen::to_value(&caps).unwrap_or(JsValue::NULL)
130}
131
132/// Performance timing utilities for benchmarking WASM operations
133#[wasm_bindgen]
134pub struct PerformanceTimer {
135    start: f64,
136    label: String,
137}
138
139#[wasm_bindgen]
140impl PerformanceTimer {
141    /// Create a new performance timer with a label
142    #[wasm_bindgen(constructor)]
143    pub fn new(label: String) -> Result<PerformanceTimer, JsValue> {
144        let start = web_sys::window()
145            .ok_or_else(|| JsValue::from_str("No window object available"))?
146            .performance()
147            .ok_or_else(|| JsValue::from_str("No performance object available"))?
148            .now();
149
150        Ok(PerformanceTimer { start, label })
151    }
152
153    /// Get elapsed time in milliseconds
154    pub fn elapsed(&self) -> Result<f64, JsValue> {
155        let now = web_sys::window()
156            .ok_or_else(|| JsValue::from_str("No window object available"))?
157            .performance()
158            .ok_or_else(|| JsValue::from_str("No performance object available"))?
159            .now();
160
161        Ok(now - self.start)
162    }
163
164    /// Log the elapsed time to console
165    pub fn log_elapsed(&self) -> Result<(), JsValue> {
166        let elapsed = self.elapsed()?;
167        let message = format!("{}: {:.3}ms", self.label, elapsed);
168        console::log_1(&JsValue::from_str(&message));
169        Ok(())
170    }
171}
172
173/// Memory usage information for the WASM module
174#[wasm_bindgen]
175pub fn memory_usage() -> JsValue {
176    let info = serde_json::json!({
177        "note": "WASM memory usage should be checked via JavaScript Memory API"
178    });
179
180    serde_wasm_bindgen::to_value(&info).unwrap_or(JsValue::NULL)
181}
182
183#[cfg(test)]
184mod tests {
185    use super::*;
186
187    #[test]
188    fn test_version() {
189        let v = version();
190        assert!(!v.is_empty());
191    }
192
193    #[test]
194    fn test_has_simd_support() {
195        // Should not panic
196        let _simd = has_simd_support();
197    }
198}