1use super::{Character, ComplexVec, Double, Integer, Logical};
4use crate::interpreter::coerce;
5
6#[derive(Debug, Clone)]
8pub enum Vector {
9 Raw(Vec<u8>),
10 Logical(Logical),
11 Integer(Integer),
12 Double(Double),
13 Complex(ComplexVec),
14 Character(Character),
15}
16
17impl Vector {
18 pub fn len(&self) -> usize {
19 match self {
20 Vector::Raw(v) => v.len(),
21 Vector::Logical(v) => v.len(),
22 Vector::Integer(v) => v.len(),
23 Vector::Double(v) => v.len(),
24 Vector::Complex(v) => v.len(),
25 Vector::Character(v) => v.len(),
26 }
27 }
28
29 #[allow(dead_code)]
30 pub fn is_empty(&self) -> bool {
31 self.len() == 0
32 }
33
34 pub fn select_indices(&self, indices: &[usize]) -> Vector {
37 macro_rules! sel_option {
38 ($vals:expr, $variant:ident) => {{
39 let result: Vec<_> = indices
40 .iter()
41 .map(|&i| {
42 if i < $vals.len() {
43 $vals[i].clone()
44 } else {
45 Default::default()
46 }
47 })
48 .collect();
49 Vector::$variant(result.into())
50 }};
51 }
52
53 match self {
54 Vector::Raw(vals) => {
55 let result: Vec<u8> = indices
56 .iter()
57 .map(|&i| if i < vals.len() { vals[i] } else { 0 })
58 .collect();
59 Vector::Raw(result)
60 }
61 Vector::Double(vals) => Vector::Double(vals.select_indices(indices)),
62 Vector::Integer(vals) => Vector::Integer(vals.select_indices(indices)),
63 Vector::Logical(vals) => sel_option!(vals, Logical),
64 Vector::Complex(vals) => sel_option!(vals, Complex),
65 Vector::Character(vals) => sel_option!(vals, Character),
66 }
67 }
68
69 pub fn as_logical_scalar(&self) -> Option<bool> {
71 match self {
72 Vector::Logical(v) => v.first().copied().flatten(),
73 Vector::Integer(v) => v.first_opt().map(|i| i != 0),
74 Vector::Double(v) => v.first_opt().map(|f| f != 0.0),
75 Vector::Complex(v) => v
76 .first()
77 .copied()
78 .flatten()
79 .map(|c| c.re != 0.0 || c.im != 0.0),
80 Vector::Raw(_) | Vector::Character(_) => None,
81 }
82 }
83
84 pub fn as_double_scalar(&self) -> Option<f64> {
86 match self {
87 Vector::Double(v) => v.first_opt(),
88 Vector::Integer(v) => v.first_opt().map(coerce::i64_to_f64),
89 Vector::Logical(v) => v
90 .first()
91 .copied()
92 .flatten()
93 .map(|b| if b { 1.0 } else { 0.0 }),
94 Vector::Raw(v) => v.first().map(|&b| f64::from(b)),
95 Vector::Complex(_) => None, Vector::Character(v) => v.first().cloned().flatten().and_then(|s| s.parse().ok()),
97 }
98 }
99
100 pub fn as_integer_scalar(&self) -> Option<i64> {
102 match self {
103 Vector::Integer(v) => v.first_opt(),
104 Vector::Double(v) => v.first_opt().and_then(|f| coerce::f64_to_i64(f).ok()),
105 Vector::Logical(v) => v.first().copied().flatten().map(|b| if b { 1 } else { 0 }),
106 Vector::Raw(v) => v.first().map(|&b| i64::from(b)),
107 Vector::Complex(_) => None,
108 Vector::Character(v) => v.first().cloned().flatten().and_then(|s| s.parse().ok()),
109 }
110 }
111
112 pub fn as_character_scalar(&self) -> Option<String> {
114 match self {
115 Vector::Character(v) => v.first().cloned().flatten(),
116 Vector::Double(v) => v.first_opt().map(format_r_double),
117 Vector::Integer(v) => v.first_opt().map(|i| i.to_string()),
118 Vector::Logical(v) => v.first().copied().flatten().map(|b| {
119 if b {
120 "TRUE".to_string()
121 } else {
122 "FALSE".to_string()
123 }
124 }),
125 Vector::Complex(v) => v.first().copied().flatten().map(format_r_complex),
126 Vector::Raw(v) => v.first().map(|b| format!("{:02x}", b)),
127 }
128 }
129
130 pub fn to_doubles(&self) -> Vec<Option<f64>> {
132 match self {
133 Vector::Double(v) => v.iter_opt().collect(),
134 Vector::Integer(v) => v.iter_opt().map(|x| x.map(coerce::i64_to_f64)).collect(),
135 Vector::Logical(v) => v
136 .iter()
137 .map(|x| x.map(|b| if b { 1.0 } else { 0.0 }))
138 .collect(),
139 Vector::Raw(v) => v.iter().map(|&b| Some(f64::from(b))).collect(),
140 Vector::Complex(v) => v.iter().map(|x| x.map(|c| c.re)).collect(),
141 Vector::Character(v) => v
142 .iter()
143 .map(|x| x.as_ref().and_then(|s| s.parse().ok()))
144 .collect(),
145 }
146 }
147
148 pub fn to_integers(&self) -> Vec<Option<i64>> {
150 match self {
151 Vector::Integer(v) => v.iter_opt().collect(),
152 Vector::Double(v) => v
153 .iter_opt()
154 .map(|x| x.and_then(|f| coerce::f64_to_i64(f).ok()))
155 .collect(),
156 Vector::Logical(v) => v.iter().map(|x| x.map(|b| if b { 1 } else { 0 })).collect(),
157 Vector::Raw(v) => v.iter().map(|&b| Some(i64::from(b))).collect(),
158 Vector::Complex(v) => v
159 .iter()
160 .map(|x| x.and_then(|c| coerce::f64_to_i64(c.re).ok()))
161 .collect(),
162 Vector::Character(v) => v
163 .iter()
164 .map(|x| x.as_ref().and_then(|s| s.parse().ok()))
165 .collect(),
166 }
167 }
168
169 pub fn to_characters(&self) -> Vec<Option<String>> {
171 match self {
172 Vector::Character(v) => v.0.clone(),
173 Vector::Double(v) => v.iter_opt().map(|x| x.map(format_r_double)).collect(),
174 Vector::Integer(v) => v.iter_opt().map(|x| x.map(|i| i.to_string())).collect(),
175 Vector::Logical(v) => v
176 .iter()
177 .map(|x| {
178 x.map(|b| {
179 if b {
180 "TRUE".to_string()
181 } else {
182 "FALSE".to_string()
183 }
184 })
185 })
186 .collect(),
187 Vector::Raw(v) => v.iter().map(|b| Some(format!("{:02x}", b))).collect(),
188 Vector::Complex(v) => v.iter().map(|x| x.map(format_r_complex)).collect(),
189 }
190 }
191
192 pub fn to_logicals(&self) -> Vec<Option<bool>> {
194 match self {
195 Vector::Logical(v) => v.0.clone(),
196 Vector::Integer(v) => v.iter_opt().map(|x| x.map(|i| i != 0)).collect(),
197 Vector::Double(v) => v.iter_opt().map(|x| x.map(|f| f != 0.0)).collect(),
198 Vector::Raw(v) => v.iter().map(|&b| Some(b != 0)).collect(),
199 Vector::Complex(v) => v
200 .iter()
201 .map(|x| x.map(|c| c.re != 0.0 || c.im != 0.0))
202 .collect(),
203 Vector::Character(v) => v
204 .iter()
205 .map(|x| {
206 x.as_ref().and_then(|s| match s.trim() {
207 "TRUE" | "T" => Some(true),
208 "FALSE" | "F" => Some(false),
209 _ => None,
210 })
211 })
212 .collect(),
213 }
214 }
215
216 pub fn to_complex(&self) -> Vec<Option<num_complex::Complex64>> {
218 match self {
219 Vector::Complex(v) => v.0.clone(),
220 Vector::Double(v) => v
221 .iter_opt()
222 .map(|x| x.map(|f| num_complex::Complex64::new(f, 0.0)))
223 .collect(),
224 Vector::Integer(v) => v
225 .iter_opt()
226 .map(|x| x.map(|i| num_complex::Complex64::new(coerce::i64_to_f64(i), 0.0)))
227 .collect(),
228 Vector::Logical(v) => v
229 .iter()
230 .map(|x| x.map(|b| num_complex::Complex64::new(if b { 1.0 } else { 0.0 }, 0.0)))
231 .collect(),
232 Vector::Raw(v) => v
233 .iter()
234 .map(|&b| Some(num_complex::Complex64::new(f64::from(b), 0.0)))
235 .collect(),
236 Vector::Character(v) => v
237 .iter()
238 .map(|x| {
239 x.as_ref()
240 .and_then(|s| s.parse::<f64>().ok())
241 .map(|f| num_complex::Complex64::new(f, 0.0))
242 })
243 .collect(),
244 }
245 }
246
247 pub fn type_name(&self) -> &'static str {
248 match self {
249 Vector::Raw(_) => "raw",
250 Vector::Logical(_) => "logical",
251 Vector::Integer(_) => "integer",
252 Vector::Double(_) => "double",
253 Vector::Complex(_) => "complex",
254 Vector::Character(_) => "character",
255 }
256 }
257
258 pub fn to_raw(&self) -> Vec<u8> {
260 match self {
261 Vector::Raw(v) => v.clone(),
262 Vector::Integer(v) => v
263 .iter_opt()
264 .map(|x| x.map(|i| (i & 0xff) as u8).unwrap_or(0))
265 .collect(),
266 Vector::Double(v) => v
267 .iter_opt()
268 .map(|x| x.map(|f| (f as i64 & 0xff) as u8).unwrap_or(0))
269 .collect(),
270 Vector::Logical(v) => v.iter().map(|x| x.map(u8::from).unwrap_or(0)).collect(),
271 Vector::Complex(v) => v
272 .iter()
273 .map(|x| x.map(|c| (c.re as i64 & 0xff) as u8).unwrap_or(0))
274 .collect(),
275 Vector::Character(_) => vec![0; self.len()],
276 }
277 }
278}
279
280pub fn format_r_double(f: f64) -> String {
282 if f.is_nan() {
283 "NaN".to_string()
284 } else if f.is_infinite() {
285 if f > 0.0 {
286 "Inf".to_string()
287 } else {
288 "-Inf".to_string()
289 }
290 } else if f == f.floor() && f.abs() < 1e15 {
291 format!("{}", coerce::f64_to_i64(f).unwrap_or(0))
293 } else {
294 format_finite_double(f)
295 }
296}
297
298fn format_finite_double(f: f64) -> String {
304 #[cfg(feature = "fast-format")]
305 {
306 zmij::Buffer::new().format_finite(f).to_owned()
307 }
308 #[cfg(not(feature = "fast-format"))]
309 {
310 format!("{}", f)
311 }
312}
313
314pub fn format_r_complex(c: num_complex::Complex64) -> String {
316 let re = format_r_double(c.re);
317 if c.im >= 0.0 || c.im.is_nan() {
318 format!("{}+{}i", re, format_r_double(c.im))
319 } else {
320 format!("{}{}i", re, format_r_double(c.im))
321 }
322}