1#![no_std]
5
6extern crate alloc;
7
8mod block_ops;
9
10use alloc::borrow::ToOwned;
11use alloc::string::{String, ToString};
12use alloc::vec::Vec;
13use core::cmp::Ordering;
14use num_traits::Float;
15
16use miniserde::json::{self, Array, Number, Value};
17use nalgebra::iter::MatrixIter;
18use nalgebra::{DMatrix, SVD};
19
20use pictorus_traits::custom_blocks::{BlockDataRead, BlockDataWrite};
21use pictorus_traits::{ByteSliceSignal, PassBy};
22
23#[derive(Clone, Debug, PartialEq, Copy, strum::EnumString)]
24pub enum BlockDataType {
25 BytesArray,
26 Scalar,
27 Vector,
28 Matrix,
29}
30
31pub enum BlockTypeRelationship {
32 SameSizes,
33 FirstIsScalar,
34 SecondIsScalar,
35 None,
36}
37
38#[derive(Clone, Debug, PartialEq)]
39pub struct BlockData {
40 _data: DMatrix<f64>,
41 _type: BlockDataType,
42}
43
44impl BlockDataRead for BlockData {
45 fn get_scalar(&self) -> f64 {
46 self.scalar()
47 }
48
49 fn get_matrix(&self) -> (usize, usize, &[f64]) {
50 (self.nrows(), self.ncols(), self._data.as_slice())
51 }
52}
53
54impl BlockDataRead for &BlockData {
55 fn get_scalar(&self) -> f64 {
56 self.scalar()
57 }
58
59 fn get_matrix(&self) -> (usize, usize, &[f64]) {
60 (self.nrows(), self.ncols(), self._data.as_slice())
61 }
62}
63
64impl BlockDataWrite for &mut BlockData {
65 fn set_scalar_value(&mut self, scalar: f64) {
66 self.set_scalar(scalar);
67 }
68
69 fn set_matrix_value(&mut self, nrows: usize, ncols: usize, data: &[f64]) {
70 self._data = DMatrix::from_column_slice(nrows, ncols, data);
71 self._type = determine_data_type(nrows, ncols);
72 }
73}
74
75pub fn determine_data_type(nrows: usize, ncols: usize) -> BlockDataType {
76 if nrows == 1 && ncols == 1 {
77 BlockDataType::Scalar
78 } else if nrows == 1 {
79 BlockDataType::Vector
80 } else {
81 BlockDataType::Matrix
82 }
83}
84
85fn create_byte_row(byte_data: &[u8]) -> DMatrix<f64> {
86 let data: Vec<f64> = byte_data.iter().map(|&v| v as f64).collect();
87 DMatrix::from_row_slice(1, data.len(), &data)
88}
89
90impl BlockData {
91 pub fn new(rows: usize, cols: usize, data: &[f64]) -> Self {
92 Self::from_row_slice(rows, cols, data)
93 }
94
95 pub fn from_data(data: DMatrix<f64>, dtype: BlockDataType) -> Self {
96 Self {
97 _data: data,
98 _type: dtype,
99 }
100 }
101 pub fn from_element(nrows: usize, ncols: usize, scalar: f64) -> Self {
102 Self::from_data(
103 DMatrix::from_element(nrows, ncols, scalar),
104 determine_data_type(nrows, ncols),
105 )
106 }
107 pub fn from_scalar(scalar: f64) -> Self {
108 Self::new(1, 1, &[scalar])
109 }
110 pub fn from_row_slice(nrows: usize, ncols: usize, data: &[f64]) -> Self {
111 Self::from_data(
112 DMatrix::from_row_slice(nrows, ncols, data),
113 determine_data_type(nrows, ncols),
114 )
115 }
116
117 pub fn from_bytes(byte_data: &[u8]) -> Self {
118 Self::from_data(create_byte_row(byte_data), BlockDataType::BytesArray)
119 }
120
121 pub fn scalar_sizeof(scalar: f64, block: &BlockData) -> Self {
122 Self::from_element(block.nrows(), block.ncols(), scalar)
123 }
124
125 pub fn from_vector(data: &[f64]) -> Self {
126 Self::new(1, data.len(), data)
127 }
128
129 pub fn from_matrix(matrix_slice: &[&[f64]]) -> Self {
130 let rows = matrix_slice.len();
131 let cols = if rows > 0 { matrix_slice[0].len() } else { 0 };
132
133 Self::from_data(
134 DMatrix::from_row_iterator(rows, cols, matrix_slice.concat()),
135 BlockDataType::Matrix,
136 )
137 }
138
139 pub fn zeros_sizeof(block: &BlockData) -> Self {
140 Self::from_element(block.nrows(), block.ncols(), 0.0)
141 }
142 pub fn ones_sizeof(block: &BlockData) -> Self {
143 Self::from_element(block.nrows(), block.ncols(), 1.0)
144 }
145
146 pub fn scalar_from_bool(value: bool) -> Self {
147 let value = if value { 1.0 } else { 0.0 };
148 Self::from_scalar(value)
149 }
150
151 pub fn fix_non_finite(&mut self) {
152 self._data = self._data.map(|x| {
153 if x.is_nan() || x == f64::INFINITY || x == f64::NEG_INFINITY {
154 0.0
155 } else {
156 x
157 }
158 });
159 }
160
161 pub fn slice(&mut self, r0: usize, c0: usize, rows: usize, cols: usize) -> Self {
162 let slice = self._data.view((r0, c0), (rows, cols)).to_owned().into();
163 Self::from_data(slice, determine_data_type(rows, cols))
164 }
165
166 pub fn as_col_slice(&self) -> &[f64] {
167 self._data.as_slice()
168 }
169
170 pub fn set(&mut self, index: usize, value: f64) {
171 self._data[index] = value;
172 }
173 pub fn at(&self, index: usize) -> f64 {
174 self._data[index]
175 }
176 pub fn ref_at(&self, index: usize) -> &f64 {
177 &self._data[index]
178 }
179 pub fn ref_at_mut(&mut self, index: usize) -> &mut f64 {
180 &mut self._data[index]
181 }
182 pub fn at_rc(&self, r: usize, c: usize) -> f64 {
183 self._data[(r, c)]
184 }
185 pub fn get_type(&self) -> BlockDataType {
186 self._type
187 }
188 pub fn set_type(&mut self, new_type: BlockDataType) {
189 self._type = new_type;
190 }
191 pub fn scalar(&self) -> f64 {
192 match self.get_type() {
194 BlockDataType::Scalar => self.at(0),
195 other => panic!("Cannot treat {:?} as scalar!", other),
196 }
197 }
198 pub fn get_data(&self) -> &DMatrix<f64> {
199 &self._data
200 }
201 pub fn set_data(&mut self, data: DMatrix<f64>) {
202 self._data = data;
203 }
204 pub fn maybe_reset(&mut self, reset_signal: &BlockData) {
205 if reset_signal.any() {
207 self._data = self.component_mul(&reset_signal.logical_not())._data;
208 }
209 }
210 pub fn compare(&self, other: &BlockData) -> BlockTypeRelationship {
211 if self.same_size(other) {
212 return BlockTypeRelationship::SameSizes;
213 } else if self.get_type() == BlockDataType::Scalar {
214 return BlockTypeRelationship::FirstIsScalar;
215 } else if other.get_type() == BlockDataType::Scalar {
216 return BlockTypeRelationship::SecondIsScalar;
217 }
218 BlockTypeRelationship::None
219 }
220 pub fn vector(&self) -> DMatrix<f64> {
221 match self.get_type() {
223 BlockDataType::Vector => self.get_data().clone(),
224 _ => panic!("Cannot treat non-scalar BlockData as scalar!"),
225 }
226 }
227
228 pub fn boolean(&self) -> Self {
229 BlockData::component_neq(self, &BlockData::zeros_sizeof(self))
230 }
231
232 pub fn norm(&self) -> f64 {
233 self._data.norm()
234 }
235
236 pub fn vector_magnitude(&self) -> Self {
237 let mut magnitudes = BlockData::from_element(1, self.ncols(), 0.0);
242 for i in 0..self.ncols() {
243 let column = self._data.column(i);
244 let magnitude = column.norm();
245 magnitudes[i] = magnitude;
246 }
247
248 magnitudes
249 }
250
251 pub fn vector_magnitude_rows(&self) -> Self {
252 self.transpose().vector_magnitude()
256 }
257
258 pub fn any(&self) -> bool {
259 self.boolean().sum() > 0.0
260 }
261
262 pub fn all(&self) -> bool {
263 self.boolean().sum() == (self.nrows() * self.ncols()) as f64
264 }
265
266 pub fn set_scalar(&mut self, new_scalar_value: f64) {
267 match self.get_type() {
268 BlockDataType::Scalar => self._data[(0, 0)] = new_scalar_value,
269 _ => panic!("Cannot treat non-scalar BlockData as scalar!"),
270 }
271 }
272 pub fn set_bytes(&mut self, byte_data: &[u8]) {
273 match self.get_type() {
274 BlockDataType::BytesArray => {
275 self._data = create_byte_row(byte_data);
276 }
277 _ => panic!("Cannot treat bytes as numeric data"),
278 }
279 }
280 pub fn set_scalar_bool(&mut self, value: bool) {
281 let value = if value { 1.0 } else { 0.0 };
282 self.set_scalar(value);
283 }
284 pub fn nrows(&self) -> usize {
285 self._data.nrows()
286 }
287 pub fn ncols(&self) -> usize {
288 self._data.ncols()
289 }
290 pub fn size(&self) -> (usize, usize) {
291 (self.nrows(), self.ncols())
292 }
293 pub fn n_elements(&self) -> usize {
294 self.nrows() * self.ncols()
295 }
296 pub fn same_size(&self, other: &BlockData) -> bool {
297 (self.nrows() == other.nrows()) && (self.ncols() == other.ncols())
298 }
299 pub fn inner_dims_same(&self, other: &BlockData) -> bool {
300 self.ncols() == other.nrows()
301 }
302 pub fn component_mul(&self, other: &BlockData) -> Self {
303 match self.compare(other) {
304 BlockTypeRelationship::SameSizes => {
305 BlockData::from_data(self._data.component_mul(&other._data), self._type)
306 }
307 BlockTypeRelationship::FirstIsScalar => {
308 BlockData::from_data(self.scalar() * other.get_data(), other.get_type())
309 }
310 BlockTypeRelationship::SecondIsScalar => {
311 BlockData::from_data(&self._data * other.scalar(), self._type)
312 }
313 _ => panic!(
314 "Cannot perform component-wise multiplication if (a) sizes are not equal or (b) at least one is not scalar."
315 ),
316 }
317 }
318 pub fn component_set(&mut self, condition: &BlockData, assign: &BlockData) {
319 match condition.compare(assign) {
322 BlockTypeRelationship::SameSizes => {
323 for (idx, condition_val) in condition._data.iter().enumerate() {
324 if *condition_val != 0.0 {
325 self._data[idx] = assign.at(idx);
326 }
327 }
328 }
329 _ => panic!("Cannot perform component-wise assignment if sizes are not equal."),
331 }
332 }
333 pub fn component_or(first: &BlockData, other: &BlockData) -> Self {
334 match first.compare(other) {
335 BlockTypeRelationship::SameSizes => {
336 let mut result = BlockData::zeros_sizeof(first);
337 for (idx, value) in first._data.iter().enumerate() {
338 let val = if *value != 0.0 || other.at(idx) != 0.0 {
339 1.0
340 } else {
341 0.0
342 };
343 result.set(idx, val);
344 }
345 result
346 }
347 _ => panic!("Cannot perform component-wise comparisons if sizes are not equal."),
349 }
350 }
351 pub fn component_and(first: &BlockData, other: &BlockData) -> Self {
352 match first.compare(other) {
353 BlockTypeRelationship::SameSizes => {
354 let mut result = BlockData::zeros_sizeof(first);
355 for (idx, value) in first._data.iter().enumerate() {
356 let val = if *value != 0.0 && other.at(idx) != 0.0 {
357 1.0
358 } else {
359 0.0
360 };
361 result.set(idx, val);
362 }
363 result
364 }
365 _ => panic!("Cannot perform component-wise comparisons if sizes are not equal."),
367 }
368 }
369
370 pub fn component_bitand(&self, rhs: &BlockData) -> Self {
371 self.component_map(rhs, |i1, i2| (i1 as i64 & i2 as i64) as f64)
372 }
373
374 pub fn component_bitor(&self, rhs: &BlockData) -> Self {
375 self.component_map(rhs, |i1, i2| (i1 as i64 | i2 as i64) as f64)
376 }
377
378 pub fn component_bitxor(&self, rhs: &BlockData) -> Self {
379 self.component_map(rhs, |i1, i2| (i1 as i64 ^ i2 as i64) as f64)
380 }
381
382 pub fn component_lshift(&self, bits: i32) -> Self {
383 BlockData::from_data(self._data.map(|d| ((d as i64) << bits) as f64), self._type)
384 }
385
386 pub fn component_rshift(&self, bits: i32) -> Self {
387 BlockData::from_data(self._data.map(|d| ((d as i64) >> bits) as f64), self._type)
388 }
389
390 pub fn component_bitnot(&self) -> Self {
391 BlockData::from_data(self._data.map(|d| !(d as i64) as f64), self._type)
392 }
393
394 fn component_map<F>(&self, rhs: &BlockData, f: F) -> BlockData
395 where
396 F: Fn(f64, f64) -> f64,
397 {
398 match self.compare(rhs) {
399 BlockTypeRelationship::SameSizes => {
400 BlockData::from_data(self._data.zip_map(rhs.get_data(), f), self._type)
401 }
402 _ => panic!("Cannot perform component-wise comparisons if sizes are not equal."),
403 }
404 }
405 pub fn component_eq(first: &BlockData, other: &BlockData) -> Self {
406 match first.compare(other) {
407 BlockTypeRelationship::SameSizes => BlockData::from_data(
408 DMatrix::from_fn(first.nrows(), first.ncols(), |i, j| {
409 (Float::abs(first.at_rc(i, j) - other.at_rc(i, j)) < f64::EPSILON) as u8 as f64
410 }),
411 first.get_type(),
412 ),
413 _ => panic!("Cannot perform component-wise comparisons if sizes are not equal."),
415 }
416 }
417 pub fn component_neq(first: &BlockData, other: &BlockData) -> Self {
418 match first.compare(other) {
419 BlockTypeRelationship::SameSizes => BlockData::from_data(
420 DMatrix::from_fn(first.nrows(), first.ncols(), |i, j| {
421 (Float::abs(first.at_rc(i, j) - other.at_rc(i, j)) >= f64::EPSILON) as u8 as f64
422 }),
423 first.get_type(),
424 ),
425 _ => panic!("Cannot perform component-wise comparisons if sizes are not equal."),
427 }
428 }
429
430 pub fn component_gt(first: &BlockData, other: &BlockData) -> Self {
431 match first.compare(other) {
432 BlockTypeRelationship::SameSizes => {
433 let mut result = BlockData::zeros_sizeof(first);
434 for (idx, value) in first._data.iter().enumerate() {
435 let val = if *value > other.at(idx) { 1.0 } else { 0.0 };
436 result.set(idx, val);
437 }
438 result
439 }
440 _ => panic!("Cannot perform component-wise comparisons if sizes are not equal."),
442 }
443 }
444
445 pub fn component_gte(first: &BlockData, other: &BlockData) -> Self {
446 match first.compare(other) {
447 BlockTypeRelationship::SameSizes => {
448 let mut result = BlockData::zeros_sizeof(first);
449 for (idx, value) in first._data.iter().enumerate() {
450 let val = if *value >= other.at(idx) { 1.0 } else { 0.0 };
451 result.set(idx, val);
452 }
453 result
454 }
455 _ => panic!("Cannot perform component-wise comparisons if sizes are not equal."),
457 }
458 }
459
460 pub fn component_lt(first: &BlockData, other: &BlockData) -> Self {
461 match first.compare(other) {
462 BlockTypeRelationship::SameSizes => {
463 let mut result = BlockData::zeros_sizeof(first);
464 for (idx, value) in first._data.iter().enumerate() {
465 let val = if *value < other.at(idx) { 1.0 } else { 0.0 };
466 result.set(idx, val);
467 }
468 result
469 }
470 _ => panic!("Cannot perform component-wise comparisons if sizes are not equal."),
472 }
473 }
474
475 pub fn component_lte(first: &BlockData, other: &BlockData) -> Self {
476 match first.compare(other) {
477 BlockTypeRelationship::SameSizes => {
478 let mut result = BlockData::zeros_sizeof(first);
479 for (idx, value) in first._data.iter().enumerate() {
480 let val = if *value <= other.at(idx) { 1.0 } else { 0.0 };
481 result.set(idx, val);
482 }
483 result
484 }
485 _ => panic!("Cannot perform component-wise comparisons if sizes are not equal."),
487 }
488 }
489
490 pub fn powf(&self, coefficient: &BlockData) -> Self {
491 let mut result = BlockData::zeros_sizeof(self);
494 for (i, value) in self._data.iter().enumerate() {
495 result.set(i, Float::powf(*value, coefficient.at(i)));
496 }
497 result
498 }
499 pub fn sign(&self) -> Self {
500 let mut sign_vals = self.gtz();
503 sign_vals.component_set(&self.ltz(), &BlockData::scalar_sizeof(-1.0, self));
504 sign_vals
505 }
506 pub fn abs(&self) -> Self {
507 BlockData::from_data(self._data.abs(), self._type)
508 }
509 pub fn transpose(&self) -> Self {
510 BlockData::from_data(self._data.transpose(), self._type)
511 }
512 pub fn determinant(&self) -> Self {
513 let det = self._data.determinant();
514 BlockData::from_scalar(det)
515 }
516 pub fn cross(&self, other: &BlockData) -> Self {
517 BlockData::from_data(self._data.cross(&other._data), self._type)
518 }
519 pub fn dot(&self, other: &BlockData) -> Self {
520 let dot: f64 = self._data.dot(&other._data);
521 BlockData::from_scalar(dot)
522 }
523 pub fn inverse(&self) -> Option<Self> {
524 let inverse = self._data.clone().try_inverse()?;
525 Some(BlockData::from_data(inverse, self._type))
526 }
527 pub fn pseudo_inverse(&self, epsilon: f64) -> Option<Self> {
528 let svd = SVD::new(self._data.clone(), true, true);
529 let s = svd.singular_values;
530 let u = svd.u?;
531 let v_t = svd.v_t?;
532 let s_pinv = DMatrix::from_diagonal(&s.map(|x| {
533 if Float::abs(x) > epsilon {
534 1.0 / x
535 } else {
536 0.0
537 }
538 }));
539 let pinv = u * s_pinv * v_t;
540 Some(BlockData::from_data(pinv.transpose(), self._type))
541 }
542 pub fn to_bytes(&self) -> Vec<u8> {
543 match self.get_type() {
544 BlockDataType::BytesArray => self._data.iter().map(|&v| v as u8).collect(),
545 _ => self.stringify().as_bytes().to_vec(),
546 }
547 }
548
549 pub fn to_raw_bytes(&self) -> Vec<u8> {
551 self._data.iter().map(|&v| v as u8).collect()
552 }
553
554 pub fn to_json(&self) -> Value {
556 match self.get_type() {
557 BlockDataType::Scalar => Value::Number(Number::F64(self.scalar())),
558 BlockDataType::BytesArray => {
559 let mut arr = Array::new();
560 self.to_bytes()
561 .iter()
562 .for_each(|v| arr.push(Value::Number(Number::U64(*v as u64))));
563 Value::Array(arr)
564 }
565 _ => {
566 let mut arr = Array::new();
567 self._data.row_iter().for_each(|r| {
568 let mut inner_array = Array::new();
569 r.iter()
570 .for_each(|v| inner_array.push(Value::Number(Number::F64(*v))));
571 arr.push(Value::Array(inner_array));
572 });
573 Value::Array(arr)
574 }
575 }
576 }
577
578 pub fn stringify(&self) -> String {
580 json::to_string(&self.to_json())
581 }
582
583 pub fn raw_string(&self) -> String {
588 String::from_utf8(self.to_bytes()).unwrap_or("".to_string())
589 }
590
591 pub fn iter(
592 &self,
593 ) -> MatrixIter<
594 f64,
595 nalgebra::Dyn,
596 nalgebra::Dyn,
597 nalgebra::VecStorage<f64, nalgebra::Dyn, nalgebra::Dyn>,
598 > {
599 self._data.iter()
600 }
601
602 pub fn map<F: FnMut(f64) -> f64>(&self, f: F) -> Self {
603 BlockData::from_data(self._data.map(f), self._type)
604 }
605
606 pub fn sum(&self) -> f64 {
607 self._data.sum()
608 }
609
610 pub fn mean(&self) -> f64 {
611 self.sum() / self.n_elements() as f64
612 }
613
614 pub fn max(&self) -> f64 {
615 self._data.iter().cloned().fold(f64::MIN, f64::max)
616 }
617
618 pub fn min(&self) -> f64 {
619 self._data.iter().cloned().fold(f64::MAX, f64::min)
620 }
621
622 pub fn argmax(&self) -> f64 {
623 self._data
624 .iter()
625 .enumerate()
626 .fold((0, f64::MIN), |(max_idx, max_val), (idx, &val)| {
627 if val > max_val {
628 (idx, val)
629 } else {
630 (max_idx, max_val)
631 }
632 })
633 .0 as f64
634 }
635
636 pub fn argmin(&self) -> f64 {
637 self._data
638 .iter()
639 .enumerate()
640 .fold((0, f64::MAX), |(min_idx, min_val), (idx, &val)| {
641 if val < min_val {
642 (idx, val)
643 } else {
644 (min_idx, min_val)
645 }
646 })
647 .0 as f64
648 }
649
650 pub fn sorted(&self, ascending: bool) -> Self {
651 let mut sorted_values: Vec<f64> = self._data.iter().copied().collect();
652
653 sorted_values.sort_unstable_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Less));
657
658 if !ascending {
659 sorted_values.reverse();
660 }
661
662 BlockData::from_vector(sorted_values.as_slice())
663 }
664
665 pub fn median(&self) -> f64 {
666 let sorted_values = self.sorted(true);
667 let len = sorted_values.len();
668 if len % 2 == 0 {
669 (sorted_values.at(len / 2 - 1) + sorted_values.at(len / 2)) / 2.0
670 } else {
671 sorted_values.at(len / 2)
672 }
673 }
674
675 pub fn sup(&self, other: &BlockData) -> Self {
676 BlockData::from_data(self._data.sup(&other._data), self._type)
677 }
678
679 pub fn inf(&self, other: &BlockData) -> Self {
680 BlockData::from_data(self._data.inf(&other._data), self._type)
681 }
682
683 pub fn len(&self) -> usize {
684 self._data.len()
685 }
686
687 pub fn is_empty(&self) -> bool {
688 self._data.is_empty()
689 }
690
691 pub fn or(&self, other: &BlockData) -> Self {
692 BlockData::component_or(self, other)
693 }
694
695 pub fn and(&self, other: &BlockData) -> Self {
696 BlockData::component_and(self, other)
697 }
698
699 pub fn eq(&self, other: &BlockData) -> Self {
700 BlockData::component_eq(self, other)
701 }
702
703 pub fn neq(&self, other: &BlockData) -> Self {
704 BlockData::component_neq(self, other)
705 }
706
707 pub fn gt(&self, other: &BlockData) -> Self {
708 BlockData::component_gt(self, other)
709 }
710
711 pub fn gte(&self, other: &BlockData) -> Self {
712 BlockData::component_gte(self, other)
713 }
714
715 pub fn lt(&self, other: &BlockData) -> Self {
716 BlockData::component_lt(self, other)
717 }
718
719 pub fn lte(&self, other: &BlockData) -> Self {
720 BlockData::component_lte(self, other)
721 }
722
723 pub fn logical_not(&self) -> Self {
724 self.eqz()
726 }
727
728 pub fn ltz(&self) -> Self {
729 BlockData::from_data(self._data.map(|d| ((d as i8) < 0) as u8 as f64), self._type)
731 }
732
733 pub fn ltez(&self) -> Self {
734 BlockData::from_data(
736 self._data.map(|d| ((d as i8) <= 0) as u8 as f64),
737 self._type,
738 )
739 }
740
741 pub fn gtz(&self) -> Self {
742 BlockData::from_data(self._data.map(|d| ((d as i8) > 0) as u8 as f64), self._type)
744 }
745
746 pub fn gtez(&self) -> Self {
747 BlockData::from_data(
749 self._data.map(|d| ((d as i8) >= 0) as u8 as f64),
750 self._type,
751 )
752 }
753
754 pub fn eqz(&self) -> Self {
755 BlockData::from_data(
757 self._data.map(|d| ((d as i8) == 0) as u8 as f64),
758 self._type,
759 )
760 }
761}
762
763pub trait FromPass<T: pictorus_traits::Pass> {
764 fn from_pass(pass: PassBy<T>) -> Self;
765}
766
767impl FromPass<f64> for BlockData {
768 fn from_pass(pass: f64) -> Self {
769 BlockData::from_scalar(pass)
770 }
771}
772
773impl FromPass<f32> for BlockData {
774 fn from_pass(pass: f32) -> Self {
775 BlockData::from_scalar(pass.into())
776 }
777}
778
779impl FromPass<u8> for BlockData {
780 fn from_pass(pass: u8) -> Self {
781 BlockData::from_scalar(pass.into())
782 }
783}
784
785impl FromPass<i8> for BlockData {
786 fn from_pass(pass: i8) -> Self {
787 BlockData::from_scalar(pass.into())
788 }
789}
790
791impl FromPass<u16> for BlockData {
792 fn from_pass(pass: u16) -> Self {
793 BlockData::from_scalar(pass.into())
794 }
795}
796
797impl FromPass<i16> for BlockData {
798 fn from_pass(pass: i16) -> Self {
799 BlockData::from_scalar(pass.into())
800 }
801}
802
803impl FromPass<u32> for BlockData {
804 fn from_pass(pass: u32) -> Self {
805 BlockData::from_scalar(pass.into())
806 }
807}
808
809impl FromPass<i32> for BlockData {
810 fn from_pass(pass: i32) -> Self {
811 BlockData::from_scalar(pass.into())
812 }
813}
814
815impl FromPass<bool> for BlockData {
816 fn from_pass(pass: PassBy<bool>) -> Self {
817 let scalar = if pass { 1. } else { 0. };
818 BlockData::from_scalar(scalar)
819 }
820}
821
822impl FromPass<ByteSliceSignal> for BlockData {
823 fn from_pass(pass: PassBy<ByteSliceSignal>) -> Self {
824 BlockData::from_bytes(pass)
825 }
826}
827
828impl<const NROWS: usize, const NCOLS: usize, T: pictorus_traits::Scalar>
829 FromPass<pictorus_traits::Matrix<NROWS, NCOLS, T>> for BlockData
830{
831 fn from_pass(pass: PassBy<pictorus_traits::Matrix<NROWS, NCOLS, T>>) -> Self {
832 let mut data = DMatrix::<f64>::zeros(NROWS, NCOLS);
833 for i in 0..NROWS {
834 for j in 0..NCOLS {
835 data[(i, j)] = pass.data[j][i].into();
837 }
838 }
839 BlockData::from_data(data, BlockDataType::Matrix)
840 }
841}
842
843pub trait ToPass<T: pictorus_traits::Pass> {
844 fn to_pass(&self) -> T;
845}
846
847impl ToPass<f64> for BlockData {
848 fn to_pass(&self) -> f64 {
849 self.scalar()
850 }
851}
852
853impl ToPass<bool> for BlockData {
854 fn to_pass(&self) -> bool {
855 self.scalar() != 0.0
856 }
857}
858
859impl<const N: usize> ToPass<[u8; N]> for BlockData {
860 fn to_pass(&self) -> [u8; N] {
861 let mut data = [0; N];
862 for (i, v) in self._data.iter().enumerate() {
863 data[i] = *v as u8;
864 }
865 data
866 }
867}
868
869impl<const N: usize> ToPass<[f64; N]> for BlockData {
870 fn to_pass(&self) -> [f64; N] {
871 let mut data = [0.0; N];
872 for (i, v) in self._data.iter().enumerate() {
873 data[i] = *v;
874 }
875 data
876 }
877}
878
879impl<const NROWS: usize, const NCOLS: usize> ToPass<pictorus_traits::Matrix<NROWS, NCOLS, f64>>
880 for BlockData
881{
882 fn to_pass(&self) -> pictorus_traits::Matrix<NROWS, NCOLS, f64> {
883 let mut data = pictorus_traits::Matrix::<NROWS, NCOLS, f64>::zeroed();
884 for i in 0..NROWS {
885 for j in 0..NCOLS {
886 data.data[j][i] = self.at_rc(i, j);
888 }
889 }
890 data
891 }
892}
893
894impl<const NROWS: usize, const NCOLS: usize> ToPass<pictorus_traits::Matrix<NROWS, NCOLS, bool>>
895 for BlockData
896{
897 fn to_pass(&self) -> pictorus_traits::Matrix<NROWS, NCOLS, bool> {
898 let mut data = pictorus_traits::Matrix::<NROWS, NCOLS, bool>::zeroed();
899 for i in 0..NROWS {
900 for j in 0..NCOLS {
901 data.data[j][i] = self.at_rc(i, j) != 0.0;
903 }
904 }
905 data
906 }
907}
908
909pub fn all_blocks_same_size(blocks: Vec<&BlockData>) -> bool {
910 for block in blocks.iter() {
911 if !block.same_size(blocks[0]) {
912 return false;
913 }
914 }
915 true
916}
917
918#[cfg(test)]
919#[allow(clippy::approx_constant)]
920mod tests {
921 use super::*;
922 use alloc::vec;
923 use approx::assert_relative_eq;
924 use pretty_assertions::assert_eq;
925
926 #[test]
927 fn test_array_constructor() {
928 let input = BlockData::new(2, 3, &[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
929
930 assert_eq!(input.get_type(), BlockDataType::Matrix);
931 assert_eq!(
932 input._data.row(0),
933 DMatrix::<f64>::from_row_slice(1, 3, &[1.0, 2.0, 3.0])
934 );
935 assert_eq!(
936 input._data.row(1),
937 DMatrix::<f64>::from_row_slice(1, 3, &[4.0, 5.0, 6.0])
938 );
939 }
940
941 #[test]
942 fn test_scalar_constructor() {
943 let input = BlockData::from_scalar(3.14159);
944
945 assert_eq!(input.get_type(), BlockDataType::Scalar);
946 assert_eq!(input.scalar(), 3.14159);
947 }
948
949 #[test]
950 fn test_set_scalar() {
951 let mut input = BlockData::from_scalar(3.14159);
952 input.set_scalar(1.0);
953
954 assert_eq!(input.get_type(), BlockDataType::Scalar);
955 assert_eq!(input.scalar(), 1.0);
956 }
957
958 #[test]
959 fn test_bool_constructor() {
960 let block = BlockData::scalar_from_bool(false);
961 assert!(!block.any());
962
963 let block = BlockData::scalar_from_bool(true);
964 assert!(block.all())
965 }
966
967 #[test]
968 fn test_vector_constructor() {
969 let block = BlockData::from_matrix(&[&[1., 2.], &[3., 4.], &[5., 6.]]);
970
971 assert!(block.get_type() == BlockDataType::Matrix);
972 assert!(block.nrows() == 3);
973 assert!(block.ncols() == 2);
974 assert!(block.at_rc(0, 0) == 1.);
975 assert!(block.at_rc(0, 1) == 2.);
976 assert!(block.at_rc(1, 0) == 3.);
977 assert!(block.at_rc(1, 1) == 4.);
978 assert!(block.at_rc(2, 0) == 5.);
979 assert!(block.at_rc(2, 1) == 6.);
980 }
981
982 #[test]
983 fn test_set_bool() {
984 let mut block = BlockData::scalar_from_bool(false);
985
986 block.set_scalar_bool(true);
987 assert!(block.all());
988
989 block.set_scalar_bool(false);
990 assert!(!block.any());
991 }
992
993 #[test]
994 fn test_or() {
995 let a = BlockData::from_vector(&[-1., 0., 1., 2.]);
996 let b = BlockData::zeros_sizeof(&a);
997
998 assert_eq!(a.or(&b), BlockData::from_vector(&[1.0, 0.0, 1.0, 1.0]));
999 }
1000
1001 #[test]
1002 fn test_and() {
1003 let a = BlockData::from_vector(&[-1., 0., 1., 2.]);
1004 let b = BlockData::from_vector(&[0., 0., 1., -2.]);
1005
1006 assert_eq!(a.and(&b), BlockData::from_vector(&[0.0, 0.0, 1.0, 1.0]));
1007 }
1008
1009 #[test]
1010 fn test_eq() {
1011 let a = BlockData::from_vector(&[-1., 0., 1., 2.]);
1012 let b = BlockData::zeros_sizeof(&a);
1013
1014 assert_eq!(a.eq(&b), BlockData::from_vector(&[0.0, 1.0, 0.0, 0.0]));
1015 }
1016
1017 #[test]
1018 fn test_neq() {
1019 let a = BlockData::from_vector(&[-1., 0., 1., 2.]);
1020 let b = BlockData::zeros_sizeof(&a);
1021
1022 assert_eq!(a.neq(&b), BlockData::from_vector(&[1.0, 0.0, 1.0, 1.0]));
1023 }
1024
1025 #[test]
1026 fn test_gt() {
1027 let a = BlockData::from_vector(&[-1., 0., 1., 2.]);
1028 let b = BlockData::zeros_sizeof(&a);
1029
1030 assert_eq!(a.gt(&b), BlockData::from_vector(&[0.0, 0.0, 1.0, 1.0]));
1031 }
1032
1033 #[test]
1034 fn test_gte() {
1035 let a = BlockData::from_vector(&[-1., 0., 1., 2.]);
1036 let b = BlockData::zeros_sizeof(&a);
1037
1038 assert_eq!(a.gte(&b), BlockData::from_vector(&[0.0, 1.0, 1.0, 1.0]));
1039 }
1040
1041 #[test]
1042 fn test_lt() {
1043 let a = BlockData::from_vector(&[-1., 0., 1., 2.]);
1044 let b = BlockData::zeros_sizeof(&a);
1045
1046 assert_eq!(a.lt(&b), BlockData::from_vector(&[1.0, 0.0, 0.0, 0.0]));
1047 }
1048
1049 #[test]
1050 fn test_lte() {
1051 let a = BlockData::from_vector(&[-1., 0., 1., 2.]);
1052 let b = BlockData::zeros_sizeof(&a);
1053
1054 assert_eq!(a.lte(&b), BlockData::from_vector(&[1.0, 1.0, 0.0, 0.0]));
1055 }
1056
1057 #[test]
1058 fn test_ltz() {
1059 let a = BlockData::from_vector(&[-1., 0., 1., 2.]);
1060 assert_eq!(a.ltz(), BlockData::from_vector(&[1.0, 0.0, 0.0, 0.0]));
1061 }
1062
1063 #[test]
1064 fn test_gtz() {
1065 let a = BlockData::from_vector(&[-1., 0., 1., 2.]);
1066 assert_eq!(a.gtz(), BlockData::from_vector(&[0.0, 0.0, 1.0, 1.0]));
1067 }
1068
1069 #[test]
1070 fn test_ltez() {
1071 let a = BlockData::from_vector(&[-1., 0., 1., 2.]);
1072 assert_eq!(a.ltez(), BlockData::from_vector(&[1.0, 1.0, 0.0, 0.0]));
1073 }
1074
1075 #[test]
1076 fn test_gtez() {
1077 let a = BlockData::from_vector(&[-1., 0., 1., 2.]);
1078 assert_eq!(a.gtez(), BlockData::from_vector(&[0.0, 1.0, 1.0, 1.0]));
1079 }
1080
1081 #[test]
1082 fn test_not() {
1083 let a = BlockData::from_vector(&[-1., 0., 1., 2.]);
1084 assert_eq!(
1085 a.logical_not(),
1086 BlockData::from_vector(&[0.0, 1.0, 0.0, 0.0])
1087 );
1088 }
1089
1090 #[test]
1091 fn test_maybe_reset() {
1092 let mut a = BlockData::from_vector(&[-1., 10., 20., 2.]);
1093 a.maybe_reset(&BlockData::from_vector(&[-1., 0., 1., 2.]));
1094
1095 assert_eq!(a, BlockData::from_vector(&[0.0, 10.0, 0.0, 0.0]));
1096
1097 a.maybe_reset(&BlockData::from_scalar(1.0));
1099 assert_eq!(a, BlockData::from_vector(&[0.0, 0.0, 0.0, 0.0]));
1100 }
1101
1102 #[test]
1103 fn test_powf() {
1104 let base = BlockData::from_vector(&[1.0, -2.0, 3.0]);
1105 let exponent = BlockData::from_vector(&[2.0, 3.0, 4.0]);
1106
1107 assert_eq!(
1108 base.powf(&exponent),
1109 BlockData::from_vector(&[1.0, -8.0, 81.0])
1110 );
1111 }
1112
1113 #[test]
1114 fn test_sign() {
1115 assert_eq!(
1116 BlockData::from_vector(&[-2., -1., 0., 1., 2.]).sign(),
1117 BlockData::from_vector(&[-1., -1., 0., 1., 1.]),
1118 );
1119 }
1120
1121 #[test]
1122 fn test_boolean() {
1123 assert_eq!(
1124 BlockData::from_vector(&[-2., -1., 0., 1., 2.]).boolean(),
1125 BlockData::from_vector(&[1., 1., 0., 1., 1.]),
1126 );
1127 }
1128
1129 #[test]
1130 fn test_all() {
1131 assert_eq!(BlockData::from_vector(&[-2., -1., 0., 1., 2.]).all(), false);
1132 assert_eq!(BlockData::from_vector(&[-2., -1., 1., 1., 2.]).all(), true);
1133 }
1134 #[test]
1135 fn test_any() {
1136 assert_eq!(BlockData::from_vector(&[-2., -1., 0., 1., 2.]).any(), true);
1137 assert_eq!(BlockData::from_vector(&[0., 0., 0., 0., 0.]).any(), false);
1138 }
1139 #[test]
1140 fn test_inverse() {
1141 let block = BlockData::new(2, 2, &[1., 2., 3., 4.]);
1142 assert_eq!(
1144 block.inverse().unwrap(),
1145 BlockData::new(2, 2, &[-2., 1., 1.5, -0.5])
1146 );
1147 }
1148 #[test]
1149 fn test_dot() {
1150 let block1 = BlockData::new(1, 3, &[1.0, 2.0, 3.0]);
1151 let block2 = BlockData::new(1, 3, &[4.0, 1.0, 0.0]);
1152 assert_eq!(block1.dot(&block2), BlockData::from_scalar(6.0));
1154 }
1155 #[test]
1156 fn test_determinant() {
1157 let block = BlockData::new(2, 2, &[1.0, 2.0, 3.0, 4.0]);
1158 assert_eq!(block.determinant(), BlockData::from_scalar(-2.0));
1160 }
1161 #[test]
1162 fn test_cross() {
1163 let block1 = BlockData::new(1, 3, &[1.0, 0.0, 0.0]);
1164 let block2 = BlockData::new(1, 3, &[0.0, 1.0, 0.0]);
1165 assert_eq!(
1167 block1.cross(&block2),
1168 BlockData::new(1, 3, &[0.0, 0.0, 1.0])
1169 );
1170 }
1171 #[test]
1172 fn test_transpose() {
1173 let block = BlockData::new(3, 2, &[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
1174 assert_eq!(
1176 block.transpose(),
1177 BlockData::new(2, 3, &[1.0, 3.0, 5.0, 2.0, 4.0, 6.0])
1178 );
1179 }
1180 #[test]
1181 fn test_sum() {
1182 let block = BlockData::new(3, 2, &[1.0, 2.0, 3.0, 4.0, 5.0, -6.0]);
1183 assert_eq!(block.sum(), 9.0);
1184 }
1185 #[test]
1186 fn test_mean() {
1187 let block = BlockData::new(3, 2, &[1.0, 2.0, 3.0, 4.0, 5.0, -6.0]);
1188 assert_eq!(block.mean(), 1.5);
1189 }
1190 #[test]
1191 fn test_median() {
1192 assert_eq!(
1193 BlockData::new(1, 7, &[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]).median(),
1194 4.0
1195 );
1196 assert_eq!(
1197 BlockData::new(1, 6, &[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]).median(),
1198 3.5
1199 );
1200 }
1201 #[test]
1202 fn test_min() {
1203 assert_eq!(
1204 BlockData::new(1, 7, &[1.0, 2.0, 3.0, 4.0, -5.0, 6.0, 7.0]).min(),
1205 -5.0
1206 );
1207 }
1208 #[test]
1209 fn test_max() {
1210 assert_eq!(
1211 BlockData::new(1, 7, &[1.0, 2.0, 3.0, 4.0, -5.0, 6.0, 7.0]).max(),
1212 7.0
1213 );
1214 }
1215 #[test]
1216 fn test_component_div() {
1217 assert_eq!(
1219 BlockData::from_scalar(1.0) / BlockData::new(1, 2, &[2.0, -4.0]),
1220 BlockData::new(1, 2, &[0.5, -0.25])
1221 );
1222 assert_eq!(
1224 BlockData::new(1, 2, &[2.0, -4.0]) / BlockData::from_scalar(2.0),
1225 BlockData::new(1, 2, &[1.0, -2.0])
1226 );
1227 assert_eq!(
1229 BlockData::new(1, 2, &[2.0, -4.0]) / BlockData::new(1, 2, &[4.0, -0.5]),
1230 BlockData::new(1, 2, &[0.5, 8.0])
1231 );
1232 }
1233 #[test]
1234 fn test_component_mul() {
1235 assert_eq!(
1237 BlockData::from_scalar(2.0).component_mul(&BlockData::new(1, 2, &[2.0, -4.0])),
1238 BlockData::new(1, 2, &[4.0, -8.0])
1239 );
1240 assert_eq!(
1242 BlockData::new(1, 2, &[2.0, -4.0]).component_mul(&BlockData::from_scalar(2.0)),
1243 BlockData::new(1, 2, &[4.0, -8.0])
1244 );
1245 assert_eq!(
1247 BlockData::new(1, 2, &[2.0, -4.0]).component_mul(&BlockData::from_scalar(2.0)),
1248 BlockData::new(1, 2, &[4.0, -8.0])
1249 );
1250 assert_eq!(
1252 BlockData::new(1, 2, &[2.0, -4.0]).component_mul(&BlockData::new(1, 2, &[4.0, -0.5])),
1253 BlockData::new(1, 2, &[8.0, 2.0])
1254 );
1255 }
1256 #[test]
1257 fn test_component_add() {
1258 assert_eq!(
1260 BlockData::from_scalar(2.0) + &BlockData::new(1, 2, &[2.0, -4.0]),
1261 BlockData::new(1, 2, &[4.0, -2.0])
1262 );
1263 assert_eq!(
1265 BlockData::new(1, 2, &[2.0, -4.0]) + &BlockData::from_scalar(2.0),
1266 BlockData::new(1, 2, &[4.0, -2.0])
1267 );
1268 assert_eq!(
1270 BlockData::new(1, 2, &[2.0, -4.0]) + &BlockData::new(1, 2, &[4.0, -0.5]),
1271 BlockData::new(1, 2, &[6.0, -4.5])
1272 );
1273 let mut b = BlockData::new(1, 2, &[2.0, -4.0]);
1275 b += &BlockData::from_scalar(2.0);
1276 assert_eq!(b, BlockData::new(1, 2, &[4.0, -2.0]));
1277 }
1278 #[test]
1279 fn test_component_sub() {
1280 assert_eq!(
1282 BlockData::from_scalar(2.0) - &BlockData::new(1, 2, &[2.0, -4.0]),
1283 BlockData::new(1, 2, &[0.0, 6.0])
1284 );
1285 assert_eq!(
1287 BlockData::new(1, 2, &[2.0, -4.0]) - &BlockData::from_scalar(2.0),
1288 BlockData::new(1, 2, &[0.0, -6.0])
1289 );
1290 assert_eq!(
1292 BlockData::new(1, 2, &[2.0, -4.0]) - &BlockData::new(1, 2, &[4.0, -0.5]),
1293 BlockData::new(1, 2, &[-2.0, -3.5])
1294 );
1295 let mut b = BlockData::new(1, 2, &[2.0, -4.0]);
1297 b -= &BlockData::from_scalar(2.0);
1298 assert_eq!(b, BlockData::new(1, 2, &[0.0, -6.0]));
1299 }
1300
1301 #[test]
1302 fn test_component_bitnot() {
1303 let block = BlockData::from_vector(&[42.0, -3.5, 0.0, -1.0]);
1305 let expected = BlockData::from_vector(&[-43.0, 2.0, -1.0, 0.0]);
1306
1307 assert_eq!(block.component_bitnot(), expected);
1309 }
1310
1311 #[test]
1312 fn test_bitand() {
1313 let a = BlockData::from_vector(&[1., 2., 3.]);
1314 let b = BlockData::from_vector(&[1., 1., 2.]);
1315 let c = a & b;
1316
1317 let expected = BlockData::from_vector(&[1.0, 0.0, 2.0]);
1318 assert_eq!(c, expected);
1319 }
1320
1321 #[test]
1322 fn test_bitor() {
1323 let a = BlockData::from_vector(&[1., 2., 3.]);
1324 let b = BlockData::from_vector(&[2., 3., 3.]);
1325 let c = a | b;
1326
1327 let expected = BlockData::from_vector(&[3.0, 3.0, 3.0]);
1328 assert_eq!(c, expected);
1329 }
1330
1331 #[test]
1332 fn test_bitxor() {
1333 let a = BlockData::from_vector(&[1., 2., 3.]);
1334 let b = BlockData::from_vector(&[2., 1., 0.]);
1335 let c = a ^ b;
1336
1337 let expected = BlockData::from_vector(&[3.0, 3.0, 3.0]);
1338 assert_eq!(c, expected);
1339 }
1340
1341 #[test]
1342 fn test_shl() {
1343 let data = BlockData::from_vector(&[1., 2., 3.]);
1344 let shifted = data << 1;
1345
1346 let expected = BlockData::from_vector(&[2.0, 4.0, 6.0]);
1347 assert_eq!(shifted, expected);
1348 }
1349
1350 #[test]
1351 fn test_shr() {
1352 let data = BlockData::from_vector(&[1., 2., 4.]);
1353 let shifted = data >> 1;
1354
1355 let expected = BlockData::from_vector(&[0.0, 1.0, 2.0]);
1356 assert_eq!(shifted, expected);
1357 }
1358
1359 #[test]
1360 fn test_fix_non_finite() {
1361 let mut data = BlockData::from_row_slice(
1362 1,
1363 6,
1364 &[1.0, f64::NAN, f64::INFINITY, f64::NEG_INFINITY, 5.0, 6.0],
1365 );
1366
1367 data.fix_non_finite();
1368
1369 assert_eq!(
1370 data,
1371 BlockData::from_row_slice(1, 6, &[1.0, 0.0, 0.0, 0.0, 5.0, 6.0])
1372 );
1373 }
1374
1375 #[test]
1376 fn test_vector_magnitude() {
1377 let data = BlockData::from_matrix(&[&[0., 1., 2.], &[3., 4., 5.], &[6., 7., 8.]]);
1378
1379 assert_relative_eq!(
1380 data.vector_magnitude(),
1381 BlockData::from_row_slice(1, 3, &[6.7, 8.1, 9.6]),
1382 max_relative = 0.1
1383 );
1384
1385 assert_relative_eq!(
1386 data.vector_magnitude_rows(),
1387 BlockData::from_row_slice(1, 3, &[2.2, 7.1, 12.2]),
1388 max_relative = 0.1
1389 );
1390 }
1391
1392 #[test]
1393 fn test_stringify() {
1394 let scalar_data = BlockData::from_scalar(3.14159);
1395 let arr_data = BlockData::from_vector(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
1396 let matrix_data = BlockData::from_row_slice(3, 2, &[1., 2., 3., 4., 5., 6.]);
1397 let bytes_data = BlockData::from_bytes(&[1, 2, 3, 4, 5, 6]);
1398 let str_data = BlockData::from_bytes(b"Hello, world!");
1399
1400 assert_eq!(scalar_data.stringify(), "3.14159");
1401 assert_eq!(arr_data.stringify(), "[[1.0,2.0,3.0,4.0,5.0,6.0]]");
1402 assert_eq!(matrix_data.stringify(), "[[1.0,2.0],[3.0,4.0],[5.0,6.0]]");
1403 assert_eq!(bytes_data.stringify(), "[1,2,3,4,5,6]");
1404 assert_eq!(
1405 str_data.stringify(),
1406 "[72,101,108,108,111,44,32,119,111,114,108,100,33]"
1407 );
1408 }
1409
1410 #[test]
1411 fn test_raw_string() {
1412 let scalar_data = BlockData::from_scalar(3.14159);
1413 let arr_data = BlockData::from_vector(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
1414 let matrix_data = BlockData::from_row_slice(3, 2, &[1., 2., 3., 4., 5., 6.]);
1415
1416 let non_std_bytes = vec![1, 2, 3, 4, 5, 6];
1417 let bytes_data = BlockData::from_bytes(&non_std_bytes);
1418 let str_data = BlockData::from_bytes(b"Hello, world!");
1419
1420 assert_eq!(scalar_data.raw_string(), "3.14159");
1421 assert_eq!(arr_data.raw_string(), "[[1.0,2.0,3.0,4.0,5.0,6.0]]");
1422 assert_eq!(matrix_data.raw_string(), "[[1.0,2.0],[3.0,4.0],[5.0,6.0]]");
1423 assert_eq!(
1424 bytes_data.raw_string(),
1425 String::from_utf8(non_std_bytes).unwrap()
1426 );
1427 assert_eq!(str_data.raw_string(), "Hello, world!");
1428 }
1429
1430 #[test]
1431 fn test_argmax() {
1432 let data = BlockData::from_vector(&[3.0, 1.0, 2.0, 4.0, 5.0]);
1433 assert_eq!(data.argmax(), 4.0);
1434
1435 let data_matrix = BlockData::from_row_slice(2, 3, &[3.0, 1.0, 2.0, 6.0, 5.0, 4.0]);
1438 assert_eq!(data_matrix.argmax(), 1.0);
1439 }
1440
1441 #[test]
1442 fn test_argmin() {
1443 let data = BlockData::from_vector(&[3.0, 1.0, 2.0, 4.0, 5.0]);
1444 assert_eq!(data.argmin(), 1.0);
1445
1446 let data_matrix = BlockData::from_row_slice(2, 3, &[3.0, 1.0, 2.0, 4.0, 5.0, 6.0]);
1447 assert_eq!(data_matrix.argmin(), 2.0);
1448 }
1449
1450 #[test]
1451 fn test_block_data_scalar_read_write_traits() {
1452 let mut data = BlockData::from_scalar(1.0);
1453 {
1454 let data_read = &data;
1455 assert_eq!(data_read.get_scalar(), 1.0);
1456 }
1457
1458 {
1459 let mut data_write = &mut data;
1460 data_write.set_scalar_value(2.0);
1461 }
1462 assert_eq!(data.get_type(), BlockDataType::Scalar);
1463
1464 {
1465 let data_read = &data;
1466 assert_eq!(data_read.get_scalar(), 2.0);
1467 }
1468 }
1469
1470 #[test]
1471 fn test_block_data_matrix_read_write_traits() {
1472 let nrows = 1;
1473 let ncols = 3;
1474 let slice_data = [1.0, 2.0, 3.0];
1475 let mut data = BlockData::from_row_slice(nrows, ncols, &slice_data);
1476 let data_read = &data;
1477 {
1478 assert_eq!(
1479 data_read.get_matrix(),
1480 (nrows, ncols, slice_data.as_slice())
1481 );
1482 }
1483
1484 let nrows = 2;
1485 let ncols = 2;
1486 let slice_data = [4.0, 6.0, 5.0, 7.0];
1487 {
1488 let mut data_write = &mut data;
1489 data_write.set_matrix_value(nrows, ncols, slice_data.as_slice());
1490 }
1491 assert_eq!(data.get_type(), BlockDataType::Matrix);
1492
1493 {
1494 let data_read = &data;
1495 let (nrows, ncols, _read_slice) = data_read.get_matrix();
1496 assert_eq!(
1497 data_read.get_matrix(),
1498 (nrows, ncols, slice_data.as_slice())
1499 );
1500 }
1501 }
1502
1503 #[test]
1504 fn test_sorted() {
1505 let data = BlockData::from_vector(&[3.0, 1.0, 2.0, 4.0, 5.0]);
1506 let sorted = data.sorted(true);
1507 assert_eq!(sorted, BlockData::from_vector(&[1.0, 2.0, 3.0, 4.0, 5.0]));
1508
1509 let sorted = data.sorted(false);
1510 assert_eq!(sorted, BlockData::from_vector(&[5.0, 4.0, 3.0, 2.0, 1.0]));
1511
1512 let data_matrix = BlockData::from_row_slice(2, 3, &[3.0, 1.0, 2.0, 4.0, 5.0, 6.0]);
1513 let sorted = data_matrix.sorted(true);
1514 assert_eq!(
1515 sorted,
1516 BlockData::from_vector(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
1517 );
1518 }
1519}