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