1 #![allow(deprecated)]
2
3 use std::mem;
4
5 use cast::From as _0;
6
7 use crate::traits::Data;
8
9 macro_rules! impl_data {
10 ($($ty:ty),+) => {
11 $(
12 impl Data for $ty {
13 fn f64(self) -> f64 {
14 f64::cast(self)
15 }
16 }
17
18 impl<'a> Data for &'a $ty {
19 fn f64(self) -> f64 {
20 f64::cast(*self)
21 }
22 }
23 )+
24 }
25 }
26
27 impl_data!(f32, f64, i16, i32, i64, i8, isize, u16, u32, u64, u8, usize);
28
29 #[derive(Clone)]
30 pub struct Matrix {
31 bytes: Vec<u8>,
32 ncols: usize,
33 nrows: usize,
34 }
35
36 impl Matrix {
new<I>(rows: I, scale: <I::Item as Row>::Scale) -> Matrix where I: Iterator, I::Item: Row,37 pub fn new<I>(rows: I, scale: <I::Item as Row>::Scale) -> Matrix
38 where
39 I: Iterator,
40 I::Item: Row,
41 {
42 let ncols = I::Item::ncols();
43 let bytes_per_row = ncols * mem::size_of::<f64>();
44 let mut bytes = Vec::with_capacity(rows.size_hint().0 * bytes_per_row);
45
46 let mut nrows = 0;
47 for row in rows {
48 nrows += 1;
49 row.append_to(&mut bytes, scale);
50 }
51
52 Matrix {
53 bytes,
54 ncols,
55 nrows,
56 }
57 }
58
bytes(&self) -> &[u8]59 pub fn bytes(&self) -> &[u8] {
60 &self.bytes
61 }
62
ncols(&self) -> usize63 pub fn ncols(&self) -> usize {
64 self.ncols
65 }
66
nrows(&self) -> usize67 pub fn nrows(&self) -> usize {
68 self.nrows
69 }
70 }
71
72 /// Data that can serve as a row of the data matrix
73 pub trait Row {
74 /// Private
75 type Scale: Copy;
76
77 /// Append this row to a buffer
append_to(self, buffer: &mut Vec<u8>, scale: Self::Scale)78 fn append_to(self, buffer: &mut Vec<u8>, scale: Self::Scale);
79 /// Number of columns of the row
ncols() -> usize80 fn ncols() -> usize;
81 }
82
write_f64(w: &mut impl std::io::Write, f: f64) -> std::io::Result<()>83 fn write_f64(w: &mut impl std::io::Write, f: f64) -> std::io::Result<()> {
84 w.write_all(&f.to_bits().to_le_bytes())
85 }
86
87 impl<A, B> Row for (A, B)
88 where
89 A: Data,
90 B: Data,
91 {
92 type Scale = (f64, f64);
93
append_to(self, buffer: &mut Vec<u8>, scale: (f64, f64))94 fn append_to(self, buffer: &mut Vec<u8>, scale: (f64, f64)) {
95 let (a, b) = self;
96
97 write_f64(buffer, a.f64() * scale.0).unwrap();
98 write_f64(buffer, b.f64() * scale.1).unwrap();
99 }
100
ncols() -> usize101 fn ncols() -> usize {
102 2
103 }
104 }
105
106 impl<A, B, C> Row for (A, B, C)
107 where
108 A: Data,
109 B: Data,
110 C: Data,
111 {
112 type Scale = (f64, f64, f64);
113
append_to(self, buffer: &mut Vec<u8>, scale: (f64, f64, f64))114 fn append_to(self, buffer: &mut Vec<u8>, scale: (f64, f64, f64)) {
115 let (a, b, c) = self;
116
117 write_f64(buffer, a.f64() * scale.0).unwrap();
118 write_f64(buffer, b.f64() * scale.1).unwrap();
119 write_f64(buffer, c.f64() * scale.2).unwrap();
120 }
121
ncols() -> usize122 fn ncols() -> usize {
123 3
124 }
125 }
126
127 impl<A, B, C, D> Row for (A, B, C, D)
128 where
129 A: Data,
130 B: Data,
131 C: Data,
132 D: Data,
133 {
134 type Scale = (f64, f64, f64, f64);
135
append_to(self, buffer: &mut Vec<u8>, scale: (f64, f64, f64, f64))136 fn append_to(self, buffer: &mut Vec<u8>, scale: (f64, f64, f64, f64)) {
137 let (a, b, c, d) = self;
138
139 write_f64(buffer, a.f64() * scale.0).unwrap();
140 write_f64(buffer, b.f64() * scale.1).unwrap();
141 write_f64(buffer, c.f64() * scale.2).unwrap();
142 write_f64(buffer, d.f64() * scale.3).unwrap();
143 }
144
ncols() -> usize145 fn ncols() -> usize {
146 4
147 }
148 }
149
150 impl<A, B, C, D, E> Row for (A, B, C, D, E)
151 where
152 A: Data,
153 B: Data,
154 C: Data,
155 D: Data,
156 E: Data,
157 {
158 type Scale = (f64, f64, f64, f64, f64);
159
160 #[cfg_attr(feature = "cargo-clippy", allow(clippy::many_single_char_names))]
append_to(self, buffer: &mut Vec<u8>, scale: (f64, f64, f64, f64, f64))161 fn append_to(self, buffer: &mut Vec<u8>, scale: (f64, f64, f64, f64, f64)) {
162 let (a, b, c, d, e) = self;
163
164 write_f64(buffer, a.f64() * scale.0).unwrap();
165 write_f64(buffer, b.f64() * scale.1).unwrap();
166 write_f64(buffer, c.f64() * scale.2).unwrap();
167 write_f64(buffer, d.f64() * scale.3).unwrap();
168 write_f64(buffer, e.f64() * scale.4).unwrap();
169 }
170
ncols() -> usize171 fn ncols() -> usize {
172 5
173 }
174 }
175