1use std::sync::Arc;
2use crate::types::{Scalar, ScalarType};
3
4#[derive(Debug)]
25pub struct DataArray<T: Scalar> {
26 data: Arc<Vec<T>>,
27 num_components: usize,
28 name: String,
29}
30
31impl<T: Scalar> Clone for DataArray<T> {
32 fn clone(&self) -> Self {
33 Self {
34 data: Arc::clone(&self.data),
35 num_components: self.num_components,
36 name: self.name.clone(),
37 }
38 }
39}
40
41impl<T: Scalar> PartialEq for DataArray<T> {
42 fn eq(&self, other: &Self) -> bool {
43 self.num_components == other.num_components
44 && self.name == other.name
45 && (Arc::ptr_eq(&self.data, &other.data) || *self.data == *other.data)
46 }
47}
48
49impl<T: Scalar> DataArray<T> {
50 pub fn new(name: impl Into<String>, num_components: usize) -> Self {
51 assert!(num_components > 0, "num_components must be > 0");
52 Self {
53 data: Arc::new(Vec::new()),
54 num_components,
55 name: name.into(),
56 }
57 }
58
59 pub fn from_vec(name: impl Into<String>, data: Vec<T>, num_components: usize) -> Self {
60 assert!(num_components > 0, "num_components must be > 0");
61 assert!(
62 data.len().is_multiple_of(num_components),
63 "data length {} is not divisible by num_components {}",
64 data.len(),
65 num_components
66 );
67 Self {
68 data: Arc::new(data),
69 num_components,
70 name: name.into(),
71 }
72 }
73
74 pub fn from_slice(name: impl Into<String>, data: &[T], num_components: usize) -> Self {
76 Self::from_vec(name, data.to_vec(), num_components)
77 }
78
79 pub fn name(&self) -> &str {
80 &self.name
81 }
82
83 pub fn set_name(&mut self, name: impl Into<String>) {
84 self.name = name.into();
85 }
86
87 pub fn scalar_type(&self) -> ScalarType {
88 T::TYPE_ID
89 }
90
91 pub fn num_components(&self) -> usize {
92 self.num_components
93 }
94
95 pub fn num_tuples(&self) -> usize {
96 self.data.len() / self.num_components
97 }
98
99 pub fn tuple(&self, idx: usize) -> &[T] {
100 let start = idx * self.num_components;
101 &self.data[start..start + self.num_components]
102 }
103
104 pub fn tuple_mut(&mut self, idx: usize) -> &mut [T] {
105 let start = idx * self.num_components;
106 let nc = self.num_components;
107 let data = Arc::make_mut(&mut self.data);
109 &mut data[start..start + nc]
110 }
111
112 pub fn push_tuple(&mut self, values: &[T]) {
113 debug_assert_eq!(
114 values.len(),
115 self.num_components,
116 "expected {} components, got {}",
117 self.num_components,
118 values.len()
119 );
120 if let Some(v) = Arc::get_mut(&mut self.data) {
122 v.extend_from_slice(values);
123 } else {
124 Arc::make_mut(&mut self.data).extend_from_slice(values);
125 }
126 }
127
128 pub fn as_slice(&self) -> &[T] {
129 &self.data
130 }
131
132 pub fn as_mut_slice(&mut self) -> &mut [T] {
133 Arc::make_mut(&mut self.data).as_mut_slice()
134 }
135
136 pub fn into_vec(self) -> Vec<T> {
137 Arc::try_unwrap(self.data).unwrap_or_else(|arc| (*arc).clone())
138 }
139
140 pub fn is_empty(&self) -> bool {
141 self.data.is_empty()
142 }
143
144 pub fn from_fn(name: impl Into<String>, count: usize, f: impl Fn(usize) -> T) -> Self {
146 let data: Vec<T> = (0..count).map(f).collect();
147 Self::from_vec(name, data, 1)
148 }
149
150 pub fn from_fn_components(
152 name: impl Into<String>,
153 count: usize,
154 num_components: usize,
155 f: impl Fn(usize) -> Vec<T>,
156 ) -> Self {
157 let mut data = Vec::with_capacity(count * num_components);
158 for i in 0..count {
159 let vals = f(i);
160 assert_eq!(vals.len(), num_components);
161 data.extend(vals);
162 }
163 Self::from_vec(name, data, num_components)
164 }
165
166 pub fn filled(name: impl Into<String>, value: T, count: usize, num_components: usize) -> Self {
168 Self::from_vec(name, vec![value; count * num_components], num_components)
169 }
170
171 pub fn len(&self) -> usize {
173 self.data.len()
174 }
175
176 pub fn map_in_place(&mut self, f: impl Fn(T) -> T) {
178 for v in Arc::make_mut(&mut self.data).iter_mut() {
179 *v = f(*v);
180 }
181 }
182
183 pub fn map(&self, name: impl Into<String>, f: impl Fn(T) -> T) -> Self {
185 let mapped: Vec<T> = self.data.iter().map(|&v| f(v)).collect();
186 Self::from_vec(name, mapped, self.num_components)
187 }
188
189 pub fn map_tuples(&self, name: impl Into<String>, f: impl Fn(&[T]) -> T) -> DataArray<T> {
191 let mut result = DataArray::new(name, 1);
192 for i in 0..self.num_tuples() {
193 let t = self.tuple(i);
194 result.push_tuple(&[f(t)]);
195 }
196 result
197 }
198
199 pub fn clear(&mut self) {
200 Arc::make_mut(&mut self.data).clear();
201 }
202
203 pub fn is_shared(&self) -> bool {
205 Arc::strong_count(&self.data) > 1
206 }
207
208 pub fn make_unique(&mut self) {
211 Arc::make_mut(&mut self.data);
212 }
213
214 pub fn iter_tuples(&self) -> DataArrayTupleIter<'_, T> {
216 DataArrayTupleIter { array: self, idx: 0 }
217 }
218}
219
220impl<T: Scalar> std::ops::Index<usize> for DataArray<T> {
222 type Output = [T];
223
224 fn index(&self, idx: usize) -> &Self::Output {
225 self.tuple(idx)
226 }
227}
228
229pub struct DataArrayTupleIter<'a, T: Scalar> {
231 array: &'a DataArray<T>,
232 idx: usize,
233}
234
235impl<'a, T: Scalar> Iterator for DataArrayTupleIter<'a, T> {
236 type Item = &'a [T];
237
238 fn next(&mut self) -> Option<Self::Item> {
239 if self.idx < self.array.num_tuples() {
240 let t = self.array.tuple(self.idx);
241 self.idx += 1;
242 Some(t)
243 } else {
244 None
245 }
246 }
247
248 fn size_hint(&self) -> (usize, Option<usize>) {
249 let r = self.array.num_tuples() - self.idx;
250 (r, Some(r))
251 }
252}
253
254impl<T: Scalar> ExactSizeIterator for DataArrayTupleIter<'_, T> {}
255
256impl DataArray<f64> {
257 pub fn scale(&mut self, factor: f64) {
259 for v in Arc::make_mut(&mut self.data).iter_mut() {
260 *v *= factor;
261 }
262 }
263
264 pub fn normalize(&mut self) -> (f64, f64) {
267 let mut min = f64::INFINITY;
268 let mut max = f64::NEG_INFINITY;
269 for &v in self.data.iter() {
270 min = min.min(v);
271 max = max.max(v);
272 }
273 let range = max - min;
274 if range > 1e-15 {
275 for v in Arc::make_mut(&mut self.data).iter_mut() {
276 *v = (*v - min) / range;
277 }
278 }
279 (min, max)
280 }
281
282 pub fn min_value(&self) -> f64 {
284 let mut min = f64::INFINITY;
285 for i in 0..self.num_tuples() {
286 min = min.min(self.tuple(i)[0]);
287 }
288 min
289 }
290
291 pub fn max_value(&self) -> f64 {
293 let mut max = f64::NEG_INFINITY;
294 for i in 0..self.num_tuples() {
295 max = max.max(self.tuple(i)[0]);
296 }
297 max
298 }
299
300 pub fn magnitude(&self, name: impl Into<String>) -> DataArray<f64> {
302 let mut result = DataArray::new(name, 1);
303 for i in 0..self.num_tuples() {
304 let t = self.tuple(i);
305 let mag: f64 = t.iter().map(|v| v * v).sum::<f64>().sqrt();
306 result.push_tuple(&[mag]);
307 }
308 result
309 }
310}
311
312impl DataArray<f64> {
313 pub fn extract_component(&self, component: usize, name: impl Into<String>) -> DataArray<f64> {
315 assert!(component < self.num_components, "component index out of range");
316 let mut result = DataArray::new(name, 1);
317 for i in 0..self.num_tuples() {
318 result.push_tuple(&[self.tuple(i)[component]]);
319 }
320 result
321 }
322
323 pub fn concat(&self, other: &DataArray<f64>) -> DataArray<f64> {
325 assert_eq!(self.num_components, other.num_components,
326 "cannot concatenate arrays with different component counts");
327 let mut data = (*self.data).clone();
328 data.extend_from_slice(&other.data);
329 DataArray::from_vec(self.name(), data, self.num_components)
330 }
331
332 pub fn extend(&mut self, other: &DataArray<f64>) {
334 assert_eq!(self.num_components, other.num_components);
335 Arc::make_mut(&mut self.data).extend_from_slice(&other.data);
336 }
337
338 pub fn compose(name: impl Into<String>, components: &[&DataArray<f64>]) -> DataArray<f64> {
340 assert!(!components.is_empty());
341 let nt = components[0].num_tuples();
342 for c in components {
343 assert_eq!(c.num_tuples(), nt, "all components must have same tuple count");
344 assert_eq!(c.num_components(), 1, "all inputs must be 1-component");
345 }
346 let nc = components.len();
347 let mut data = Vec::with_capacity(nt * nc);
348 for i in 0..nt {
349 for c in components {
350 data.push(c.tuple(i)[0]);
351 }
352 }
353 DataArray::from_vec(name, data, nc)
354 }
355}
356
357impl DataArray<f32> {
358 pub fn scale(&mut self, factor: f32) {
360 for v in Arc::make_mut(&mut self.data).iter_mut() {
361 *v *= factor;
362 }
363 }
364}
365
366#[derive(Debug, Clone, PartialEq)]
370pub enum AnyDataArray {
371 F32(DataArray<f32>),
372 F64(DataArray<f64>),
373 I8(DataArray<i8>),
374 I16(DataArray<i16>),
375 I32(DataArray<i32>),
376 I64(DataArray<i64>),
377 U8(DataArray<u8>),
378 U16(DataArray<u16>),
379 U32(DataArray<u32>),
380 U64(DataArray<u64>),
381}
382
383impl AnyDataArray {
384 pub fn name(&self) -> &str {
385 match self {
386 AnyDataArray::F32(a) => a.name(),
387 AnyDataArray::F64(a) => a.name(),
388 AnyDataArray::I8(a) => a.name(),
389 AnyDataArray::I16(a) => a.name(),
390 AnyDataArray::I32(a) => a.name(),
391 AnyDataArray::I64(a) => a.name(),
392 AnyDataArray::U8(a) => a.name(),
393 AnyDataArray::U16(a) => a.name(),
394 AnyDataArray::U32(a) => a.name(),
395 AnyDataArray::U64(a) => a.name(),
396 }
397 }
398
399 pub fn set_name(&mut self, name: &str) {
400 match self {
401 AnyDataArray::F32(a) => a.set_name(name),
402 AnyDataArray::F64(a) => a.set_name(name),
403 AnyDataArray::I8(a) => a.set_name(name),
404 AnyDataArray::I16(a) => a.set_name(name),
405 AnyDataArray::I32(a) => a.set_name(name),
406 AnyDataArray::I64(a) => a.set_name(name),
407 AnyDataArray::U8(a) => a.set_name(name),
408 AnyDataArray::U16(a) => a.set_name(name),
409 AnyDataArray::U32(a) => a.set_name(name),
410 AnyDataArray::U64(a) => a.set_name(name),
411 }
412 }
413
414 pub fn scalar_type(&self) -> ScalarType {
415 match self {
416 AnyDataArray::F32(_) => ScalarType::F32,
417 AnyDataArray::F64(_) => ScalarType::F64,
418 AnyDataArray::I8(_) => ScalarType::I8,
419 AnyDataArray::I16(_) => ScalarType::I16,
420 AnyDataArray::I32(_) => ScalarType::I32,
421 AnyDataArray::I64(_) => ScalarType::I64,
422 AnyDataArray::U8(_) => ScalarType::U8,
423 AnyDataArray::U16(_) => ScalarType::U16,
424 AnyDataArray::U32(_) => ScalarType::U32,
425 AnyDataArray::U64(_) => ScalarType::U64,
426 }
427 }
428
429 pub fn clone_with_name(&self, name: &str) -> Self {
431 let mut cloned = self.clone();
432 cloned.set_name(name);
433 cloned
434 }
435
436 pub fn num_components(&self) -> usize {
437 match self {
438 AnyDataArray::F32(a) => a.num_components(),
439 AnyDataArray::F64(a) => a.num_components(),
440 AnyDataArray::I8(a) => a.num_components(),
441 AnyDataArray::I16(a) => a.num_components(),
442 AnyDataArray::I32(a) => a.num_components(),
443 AnyDataArray::I64(a) => a.num_components(),
444 AnyDataArray::U8(a) => a.num_components(),
445 AnyDataArray::U16(a) => a.num_components(),
446 AnyDataArray::U32(a) => a.num_components(),
447 AnyDataArray::U64(a) => a.num_components(),
448 }
449 }
450
451 pub fn num_tuples(&self) -> usize {
452 match self {
453 AnyDataArray::F32(a) => a.num_tuples(),
454 AnyDataArray::F64(a) => a.num_tuples(),
455 AnyDataArray::I8(a) => a.num_tuples(),
456 AnyDataArray::I16(a) => a.num_tuples(),
457 AnyDataArray::I32(a) => a.num_tuples(),
458 AnyDataArray::I64(a) => a.num_tuples(),
459 AnyDataArray::U8(a) => a.num_tuples(),
460 AnyDataArray::U16(a) => a.num_tuples(),
461 AnyDataArray::U32(a) => a.num_tuples(),
462 AnyDataArray::U64(a) => a.num_tuples(),
463 }
464 }
465
466 pub fn tuple_as_f64(&self, idx: usize, out: &mut [f64]) {
468 macro_rules! convert {
469 ($arr:expr) => {{
470 let t = $arr.tuple(idx);
471 for (o, v) in out.iter_mut().zip(t.iter()) {
472 *o = v.to_f64();
473 }
474 }};
475 }
476 match self {
477 AnyDataArray::F32(a) => convert!(a),
478 AnyDataArray::F64(a) => convert!(a),
479 AnyDataArray::I8(a) => convert!(a),
480 AnyDataArray::I16(a) => convert!(a),
481 AnyDataArray::I32(a) => convert!(a),
482 AnyDataArray::I64(a) => convert!(a),
483 AnyDataArray::U8(a) => convert!(a),
484 AnyDataArray::U16(a) => convert!(a),
485 AnyDataArray::U32(a) => convert!(a),
486 AnyDataArray::U64(a) => convert!(a),
487 }
488 }
489
490 pub fn statistics(&self) -> Option<ArrayStatistics> {
494 let nt = self.num_tuples();
495 if nt == 0 {
496 return None;
497 }
498 let mut buf = [0.0f64];
499 let mut min = f64::INFINITY;
500 let mut max = f64::NEG_INFINITY;
501 let mut sum = 0.0;
502 let mut sum_sq = 0.0;
503 for i in 0..nt {
504 self.tuple_as_f64(i, &mut buf);
505 let v = buf[0];
506 min = min.min(v);
507 max = max.max(v);
508 sum += v;
509 sum_sq += v * v;
510 }
511 let mean = sum / nt as f64;
512 let variance = sum_sq / nt as f64 - mean * mean;
513 Some(ArrayStatistics { min, max, mean, variance: variance.max(0.0), count: nt })
514 }
515
516 pub fn range(&self) -> Option<[f64; 2]> {
518 self.statistics().map(|s| [s.min, s.max])
519 }
520
521 pub fn to_f64_vec(&self) -> Vec<f64> {
526 let nt = self.num_tuples();
527 let mut result = Vec::with_capacity(nt);
528 let mut buf = [0.0f64];
529 for i in 0..nt {
530 self.tuple_as_f64(i, &mut buf);
531 result.push(buf[0]);
532 }
533 result
534 }
535
536 pub fn to_f64_vec_flat(&self) -> Vec<f64> {
538 let nt = self.num_tuples();
539 let nc = self.num_components();
540 let mut result = Vec::with_capacity(nt * nc);
541 let mut buf = vec![0.0f64; nc];
542 for i in 0..nt {
543 self.tuple_as_f64(i, &mut buf);
544 result.extend_from_slice(&buf);
545 }
546 result
547 }
548
549 pub fn as_f64(&self) -> Option<&DataArray<f64>> {
551 match self {
552 AnyDataArray::F64(a) => Some(a),
553 _ => None,
554 }
555 }
556
557 pub fn as_f32(&self) -> Option<&DataArray<f32>> {
559 match self {
560 AnyDataArray::F32(a) => Some(a),
561 _ => None,
562 }
563 }
564}
565
566impl std::fmt::Display for AnyDataArray {
567 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
568 let type_name = match self.scalar_type() {
569 ScalarType::F32 => "Float32",
570 ScalarType::F64 => "Float64",
571 ScalarType::I8 => "Int8",
572 ScalarType::I16 => "Int16",
573 ScalarType::I32 => "Int32",
574 ScalarType::I64 => "Int64",
575 ScalarType::U8 => "UInt8",
576 ScalarType::U16 => "UInt16",
577 ScalarType::U32 => "UInt32",
578 ScalarType::U64 => "UInt64",
579 };
580 write!(f, "DataArray<{}>(\"{}\", {} tuples, {} components)",
581 type_name, self.name(), self.num_tuples(), self.num_components())
582 }
583}
584
585#[derive(Debug, Clone, Copy)]
587pub struct ArrayStatistics {
588 pub min: f64,
589 pub max: f64,
590 pub mean: f64,
591 pub variance: f64,
592 pub count: usize,
593}
594
595impl ArrayStatistics {
596 pub fn std_dev(&self) -> f64 {
598 self.variance.sqrt()
599 }
600}
601
602macro_rules! impl_from_data_array {
604 ($ty:ty, $variant:ident) => {
605 impl From<DataArray<$ty>> for AnyDataArray {
606 fn from(a: DataArray<$ty>) -> Self {
607 AnyDataArray::$variant(a)
608 }
609 }
610 };
611}
612
613impl_from_data_array!(f32, F32);
614impl_from_data_array!(f64, F64);
615impl_from_data_array!(i8, I8);
616impl_from_data_array!(i16, I16);
617impl_from_data_array!(i32, I32);
618impl_from_data_array!(i64, I64);
619impl_from_data_array!(u8, U8);
620impl_from_data_array!(u16, U16);
621impl_from_data_array!(u32, U32);
622impl_from_data_array!(u64, U64);
623
624#[cfg(test)]
625mod tests {
626 use super::*;
627
628 #[test]
629 fn data_array_basics() {
630 let mut arr = DataArray::<f64>::new("test", 3);
631 arr.push_tuple(&[1.0, 2.0, 3.0]);
632 arr.push_tuple(&[4.0, 5.0, 6.0]);
633 assert_eq!(arr.num_tuples(), 2);
634 assert_eq!(arr.num_components(), 3);
635 assert_eq!(arr.tuple(0), &[1.0, 2.0, 3.0]);
636 assert_eq!(arr.tuple(1), &[4.0, 5.0, 6.0]);
637 }
638
639 #[test]
640 fn data_array_from_vec() {
641 let arr = DataArray::from_vec("coords", vec![1.0f32, 2.0, 3.0, 4.0, 5.0, 6.0], 3);
642 assert_eq!(arr.num_tuples(), 2);
643 assert_eq!(arr.scalar_type(), ScalarType::F32);
644 }
645
646 #[test]
647 fn any_data_array_type_erased() {
648 let arr = DataArray::from_vec("scalars", vec![10i32, 20, 30], 1);
649 let any: AnyDataArray = arr.into();
650 assert_eq!(any.name(), "scalars");
651 assert_eq!(any.scalar_type(), ScalarType::I32);
652 assert_eq!(any.num_tuples(), 3);
653
654 let mut val = [0.0f64];
655 any.tuple_as_f64(1, &mut val);
656 assert_eq!(val[0], 20.0);
657 }
658
659 #[test]
660 fn statistics_basic() {
661 let arr = AnyDataArray::F64(DataArray::from_vec("test", vec![1.0, 2.0, 3.0, 4.0, 5.0], 1));
662 let stats = arr.statistics().unwrap();
663 assert_eq!(stats.min, 1.0);
664 assert_eq!(stats.max, 5.0);
665 assert!((stats.mean - 3.0).abs() < 1e-12);
666 assert_eq!(stats.count, 5);
667 assert!(stats.variance > 0.0);
668 assert!((stats.std_dev() - 2.0f64.sqrt()).abs() < 1e-10);
669 }
670
671 #[test]
672 fn statistics_empty() {
673 let arr = AnyDataArray::F64(DataArray::new("test", 1));
674 assert!(arr.statistics().is_none());
675 }
676
677 #[test]
678 fn range() {
679 let arr = AnyDataArray::I32(DataArray::from_vec("test", vec![10, -5, 20, 0], 1));
680 let r = arr.range().unwrap();
681 assert_eq!(r[0], -5.0);
682 assert_eq!(r[1], 20.0);
683 }
684
685 #[test]
686 fn map_in_place() {
687 let mut arr = DataArray::from_vec("test", vec![1.0f64, 2.0, 3.0], 1);
688 arr.map_in_place(|v| v * 2.0);
689 assert_eq!(arr.tuple(0), &[2.0]);
690 assert_eq!(arr.tuple(2), &[6.0]);
691 }
692
693 #[test]
694 fn map_new() {
695 let arr = DataArray::from_vec("in", vec![1.0f64, 4.0, 9.0], 1);
696 let sqrt = arr.map("sqrt", |v| v.sqrt());
697 assert_eq!(sqrt.name(), "sqrt");
698 assert!((sqrt.tuple(1)[0] - 2.0).abs() < 1e-12);
699 }
700
701 #[test]
702 fn map_tuples_magnitude() {
703 let arr = DataArray::from_vec("vec", vec![3.0f64, 4.0, 0.0], 3);
704 let mag = arr.map_tuples("mag", |t| (t[0]*t[0] + t[1]*t[1] + t[2]*t[2]).sqrt());
705 assert!((mag.tuple(0)[0] - 5.0).abs() < 1e-12);
706 }
707
708 #[test]
709 fn scale_f64() {
710 let mut arr = DataArray::from_vec("test", vec![1.0f64, 2.0, 3.0], 1);
711 arr.scale(10.0);
712 assert_eq!(arr.tuple(0), &[10.0]);
713 assert_eq!(arr.tuple(2), &[30.0]);
714 }
715
716 #[test]
717 fn normalize_f64() {
718 let mut arr = DataArray::from_vec("test", vec![0.0f64, 50.0, 100.0], 1);
719 let (min, max) = arr.normalize();
720 assert_eq!(min, 0.0);
721 assert_eq!(max, 100.0);
722 assert!((arr.tuple(0)[0]).abs() < 1e-12);
723 assert!((arr.tuple(1)[0] - 0.5).abs() < 1e-12);
724 assert!((arr.tuple(2)[0] - 1.0).abs() < 1e-12);
725 }
726
727 #[test]
728 fn min_max_value() {
729 let arr = DataArray::from_vec("test", vec![5.0f64, -3.0, 8.0, 1.0], 1);
730 assert_eq!(arr.min_value(), -3.0);
731 assert_eq!(arr.max_value(), 8.0);
732 }
733
734 #[test]
735 fn magnitude_3d() {
736 let arr = DataArray::from_vec("v", vec![1.0f64, 0.0, 0.0, 0.0, 3.0, 4.0], 3);
737 let mag = arr.magnitude("mag");
738 assert!((mag.tuple(0)[0] - 1.0).abs() < 1e-12);
739 assert!((mag.tuple(1)[0] - 5.0).abs() < 1e-12);
740 }
741
742 #[test]
743 fn extract_component() {
744 let arr = DataArray::from_vec("vec", vec![1.0f64, 2.0, 3.0, 4.0, 5.0, 6.0], 3);
745 let y = arr.extract_component(1, "y");
746 assert_eq!(y.num_tuples(), 2);
747 assert_eq!(y.num_components(), 1);
748 assert_eq!(y.tuple(0), &[2.0]);
749 assert_eq!(y.tuple(1), &[5.0]);
750 }
751
752 #[test]
753 fn concat_arrays() {
754 let a = DataArray::from_vec("a", vec![1.0f64, 2.0], 1);
755 let b = DataArray::from_vec("b", vec![3.0f64, 4.0], 1);
756 let c = a.concat(&b);
757 assert_eq!(c.num_tuples(), 4);
758 assert_eq!(c.tuple(2), &[3.0]);
759 }
760
761 #[test]
762 fn extend_array() {
763 let mut a = DataArray::from_vec("a", vec![1.0f64, 2.0], 1);
764 let b = DataArray::from_vec("b", vec![3.0f64, 4.0], 1);
765 a.extend(&b);
766 assert_eq!(a.num_tuples(), 4);
767 }
768
769 #[test]
770 fn compose_components() {
771 let x = DataArray::from_vec("x", vec![1.0f64, 4.0], 1);
772 let y = DataArray::from_vec("y", vec![2.0f64, 5.0], 1);
773 let z = DataArray::from_vec("z", vec![3.0f64, 6.0], 1);
774 let v = DataArray::compose("vec", &[&x, &y, &z]);
775 assert_eq!(v.num_tuples(), 2);
776 assert_eq!(v.num_components(), 3);
777 assert_eq!(v.tuple(0), &[1.0, 2.0, 3.0]);
778 assert_eq!(v.tuple(1), &[4.0, 5.0, 6.0]);
779 }
780
781 #[test]
782 fn from_fn() {
783 let arr = DataArray::<f64>::from_fn("sq", 5, |i| (i * i) as f64);
784 assert_eq!(arr.num_tuples(), 5);
785 assert_eq!(arr.tuple(3), &[9.0]);
786 }
787
788 #[test]
789 fn from_fn_components() {
790 let arr = DataArray::<f64>::from_fn_components("pos", 3, 3, |i| {
791 vec![i as f64, (i * 2) as f64, (i * 3) as f64]
792 });
793 assert_eq!(arr.num_tuples(), 3);
794 assert_eq!(arr.num_components(), 3);
795 assert_eq!(arr.tuple(1), &[1.0, 2.0, 3.0]);
796 }
797
798 #[test]
799 fn filled() {
800 let arr = DataArray::<f64>::filled("zeros", 0.0, 10, 1);
801 assert_eq!(arr.num_tuples(), 10);
802 assert_eq!(arr.tuple(5), &[0.0]);
803 }
804
805 #[test]
806 fn iter_tuples() {
807 let arr = DataArray::<f64>::from_vec("test", vec![1.0, 2.0, 3.0], 1);
808 let vals: Vec<&[f64]> = arr.iter_tuples().collect();
809 assert_eq!(vals.len(), 3);
810 assert_eq!(vals[1], &[2.0]);
811 }
812
813 #[test]
814 fn any_data_array_display() {
815 let arr = AnyDataArray::F64(DataArray::from_vec("temperature", vec![1.0, 2.0, 3.0], 1));
816 let s = format!("{arr}");
817 assert!(s.contains("Float64"));
818 assert!(s.contains("temperature"));
819 assert!(s.contains("3 tuples"));
820 }
821
822 #[test]
823 fn to_f64_vec() {
824 let arr = AnyDataArray::F64(DataArray::from_vec("t", vec![1.0, 2.0, 3.0], 1));
825 let v = arr.to_f64_vec();
826 assert_eq!(v, vec![1.0, 2.0, 3.0]);
827 }
828
829 #[test]
830 fn to_f64_vec_flat() {
831 let arr = AnyDataArray::F64(DataArray::from_vec("v", vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0], 3));
832 let v = arr.to_f64_vec_flat();
833 assert_eq!(v, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
834 }
835
836 #[test]
837 fn as_f64_variant() {
838 let arr = AnyDataArray::F64(DataArray::from_vec("t", vec![1.0], 1));
839 assert!(arr.as_f64().is_some());
840 assert!(arr.as_f32().is_none());
841 }
842
843 #[test]
844 fn index_trait() {
845 let arr = DataArray::from_vec("v", vec![1.0f64, 2.0, 3.0, 4.0, 5.0, 6.0], 3);
846 assert_eq!(arr[0], [1.0, 2.0, 3.0]);
847 assert_eq!(arr[1], [4.0, 5.0, 6.0]);
848 }
849}