Skip to main content

plotkit_ndarray/
lib.rs

1//! ndarray integration for plotkit.
2//!
3//! This crate activates ndarray support in `plotkit-core`, providing
4//! [`IntoSeries`](plotkit_core::series::IntoSeries) implementations for
5//! common `ndarray` one-dimensional array types. Depend on this crate (or
6//! enable the `ndarray` feature on the `plotkit` umbrella crate) to pass
7//! ndarray arrays directly to any plotkit charting function.
8//!
9//! # Supported types
10//!
11//! | Type | Conversion |
12//! |---|---|
13//! | `&Array1<f64>` / `Array1<f64>` | zero-copy (contiguous slice borrow) |
14//! | `ArrayView1<'_, f64>` | zero-copy when contiguous, O(n) copy when strided |
15//! | `&Array1<f32>` / `Array1<f32>` | O(n) widening cast |
16//! | `&Array1<i32>` / `Array1<i32>` | O(n) cast to `f64` |
17//! | `&Array1<i64>` / `Array1<i64>` | O(n) cast to `f64` |
18//! | `ArrayView1<'_, f32/i32/i64>` | O(n) cast to `f64` |
19//!
20//! # Examples
21//!
22//! ```
23//! use ndarray::array;
24//! use plotkit_core::series::IntoSeries;
25//!
26//! let arr = array![1.0, 2.0, 3.0];
27//! let series = (&arr).into_series();
28//! assert_eq!(series.data, vec![1.0, 2.0, 3.0]);
29//! ```
30
31#![deny(missing_docs)]
32
33// Re-export ndarray so downstream users can access the version we link against.
34pub use ndarray;
35
36// Re-export the core series types for convenience.
37pub use plotkit_core::series::{IntoSeries, Series};
38
39// ---------------------------------------------------------------------------
40// Tests
41// ---------------------------------------------------------------------------
42
43#[cfg(test)]
44mod tests {
45    use ndarray::{array, Array1};
46    use plotkit_core::series::IntoSeries;
47
48    // -- f64 ----------------------------------------------------------------
49
50    #[test]
51    fn array1_f64_ref() {
52        let arr = array![1.0, 2.0, 3.0];
53        let s = (&arr).into_series();
54        assert_eq!(s.data, vec![1.0, 2.0, 3.0]);
55    }
56
57    #[test]
58    fn array1_f64_owned() {
59        let arr = array![4.0, 5.0, 6.0];
60        let s = arr.into_series();
61        assert_eq!(s.data, vec![4.0, 5.0, 6.0]);
62    }
63
64    #[test]
65    fn array_view1_f64_contiguous() {
66        let arr = array![7.0, 8.0, 9.0];
67        let view = arr.view();
68        let s = view.into_series();
69        assert_eq!(s.data, vec![7.0, 8.0, 9.0]);
70    }
71
72    #[test]
73    fn array_view1_f64_strided() {
74        let arr = array![1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
75        // Take every other element — produces a non-contiguous view.
76        let view = arr.slice(ndarray::s![..;2]);
77        let s = view.into_series();
78        assert_eq!(s.data, vec![1.0, 3.0, 5.0]);
79    }
80
81    #[test]
82    fn empty_array_f64() {
83        let arr: Array1<f64> = array![];
84        let s = (&arr).into_series();
85        assert!(s.is_empty());
86        assert_eq!(s.len(), 0);
87    }
88
89    #[test]
90    fn single_element_f64() {
91        let arr = array![42.0];
92        let s = (&arr).into_series();
93        assert_eq!(s.data, vec![42.0]);
94    }
95
96    // -- f32 ----------------------------------------------------------------
97
98    #[test]
99    fn array1_f32_ref() {
100        let arr: Array1<f32> = array![1.5f32, 2.5, 3.5];
101        let s = (&arr).into_series();
102        assert_eq!(s.data, vec![1.5, 2.5, 3.5]);
103    }
104
105    #[test]
106    fn array1_f32_owned() {
107        let arr: Array1<f32> = array![0.1f32, 0.2];
108        let s = arr.into_series();
109        assert_eq!(s.len(), 2);
110    }
111
112    #[test]
113    fn array_view1_f32() {
114        let arr: Array1<f32> = array![10.0f32, 20.0, 30.0];
115        let view = arr.view();
116        let s = view.into_series();
117        assert_eq!(s.data, vec![10.0, 20.0, 30.0]);
118    }
119
120    // -- i32 ----------------------------------------------------------------
121
122    #[test]
123    fn array1_i32_ref() {
124        let arr: Array1<i32> = array![1, 2, 3];
125        let s = (&arr).into_series();
126        assert_eq!(s.data, vec![1.0, 2.0, 3.0]);
127    }
128
129    #[test]
130    fn array1_i32_owned() {
131        let arr: Array1<i32> = array![10, 20, 30];
132        let s = arr.into_series();
133        assert_eq!(s.data, vec![10.0, 20.0, 30.0]);
134    }
135
136    #[test]
137    fn array_view1_i32() {
138        let arr: Array1<i32> = array![100, 200];
139        let view = arr.view();
140        let s = view.into_series();
141        assert_eq!(s.data, vec![100.0, 200.0]);
142    }
143
144    // -- i64 ----------------------------------------------------------------
145
146    #[test]
147    fn array1_i64_ref() {
148        let arr: Array1<i64> = array![1i64, 2, 3];
149        let s = (&arr).into_series();
150        assert_eq!(s.data, vec![1.0, 2.0, 3.0]);
151    }
152
153    #[test]
154    fn array1_i64_owned() {
155        let arr: Array1<i64> = array![100i64, 200, 300];
156        let s = arr.into_series();
157        assert_eq!(s.data, vec![100.0, 200.0, 300.0]);
158    }
159
160    #[test]
161    fn array_view1_i64() {
162        let arr: Array1<i64> = array![1000i64, 2000];
163        let view = arr.view();
164        let s = view.into_series();
165        assert_eq!(s.data, vec![1000.0, 2000.0]);
166    }
167
168    // -- Edge cases ---------------------------------------------------------
169
170    #[test]
171    fn nan_and_infinity() {
172        let arr = array![f64::NAN, f64::INFINITY, f64::NEG_INFINITY, 1.0];
173        let s = (&arr).into_series();
174        assert_eq!(s.len(), 4);
175        assert!(s.data[0].is_nan());
176        assert!(s.data[1].is_infinite());
177        assert!(s.data[2].is_infinite());
178        assert_eq!(s.data[3], 1.0);
179    }
180
181    #[test]
182    fn large_array() {
183        let arr = Array1::from_vec((0..10_000).map(|i| i as f64).collect());
184        let s = (&arr).into_series();
185        assert_eq!(s.len(), 10_000);
186        assert_eq!(s.data[0], 0.0);
187        assert_eq!(s.data[9_999], 9_999.0);
188    }
189
190    #[test]
191    fn reversed_slice_view() {
192        let arr = array![1.0, 2.0, 3.0, 4.0, 5.0];
193        let view = arr.slice(ndarray::s![..;-1]);
194        let s = view.into_series();
195        assert_eq!(s.data, vec![5.0, 4.0, 3.0, 2.0, 1.0]);
196    }
197
198    #[test]
199    fn sub_slice_view() {
200        let arr = array![10.0, 20.0, 30.0, 40.0, 50.0];
201        let view = arr.slice(ndarray::s![1..4]);
202        let s = view.into_series();
203        assert_eq!(s.data, vec![20.0, 30.0, 40.0]);
204    }
205}