• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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