1use std::ops::Range;
7use std::mem;
8use std::ptr;
9use std::iter;
10use std::string::FromUtf8Error;
11use num_traits::PrimInt;
12use crate::{OclPrm, OclScl};
13
14pub mod colors {
25 pub static TAB: &'static str = " ";
32
33 pub static C_DEFAULT: &'static str = "\x1b[0m";
34 pub static C_UNDER: &'static str = "\x1b[1m";
35
36 pub static C_RED: &'static str = "\x1b[31m";
38 pub static C_BRED: &'static str = "\x1b[1;31m";
39 pub static C_GRN: &'static str = "\x1b[32m";
40 pub static C_BGRN: &'static str = "\x1b[1;32m";
41 pub static C_ORA: &'static str = "\x1b[33m";
42 pub static C_DBL: &'static str = "\x1b[34m";
43 pub static C_PUR: &'static str = "\x1b[35m";
44 pub static C_CYA: &'static str = "\x1b[36m";
45 pub static C_LGR: &'static str = "\x1b[37m";
46 pub static C_DFLT: &'static str = "\x1b[39m";
49
50 pub static C_DGR: &'static str = "\x1b[90m";
52 pub static C_LRD: &'static str = "\x1b[91m";
53 pub static C_YEL: &'static str = "\x1b[93m";
54 pub static C_BLU: &'static str = "\x1b[94m";
55 pub static C_LBL: &'static str = "\x1b[94m";
56 pub static C_MAG: &'static str = "\x1b[95m";
57 pub static BGC_DEFAULT: &'static str = "\x1b[49m";
61 pub static BGC_GRN: &'static str = "\x1b[42m";
62 pub static BGC_PUR: &'static str = "\x1b[45m";
63 pub static BGC_LGR: &'static str = "\x1b[47m";
64 pub static BGC_DGR: &'static str = "\x1b[100m";
65}
66
67#[derive(Debug, Fail)]
73pub enum UtilError {
74 #[fail(display = "The size of the source byte slice ({} bytes) does not match \
75 the size of the destination type ({} bytes).", src, dst)]
76 BytesTo { src: usize, dst: usize, },
77 #[fail(display = "The size of the source byte vector ({} bytes) does not match \
78 the size of the destination type ({} bytes).", src, dst)]
79 BytesInto { src: usize, dst: usize, },
80 #[fail(display = "The size of the source byte vector ({} bytes) is not evenly \
81 divisible by the size of the destination type ({} bytes).", src, dst)]
82 BytesIntoVec { src: usize, dst: usize, },
83 #[fail(display = "The size of the source byte slice ({} bytes) is not evenly \
84 divisible by the size of the destination type ({} bytes).", src, dst)]
85 BytesToVec { src: usize, dst: usize, },
86 #[fail(display = "Unable to convert bytes into string: {}", _0)]
87 BytesIntoString(#[cause] FromUtf8Error),
88}
89
90pub fn bytes_to_u32(bytes: &[u8]) -> u32 {
97 debug_assert!(bytes.len() == 4);
98
99 u32::from(bytes[0]) |
100 (u32::from(bytes[1]) << 8) |
101 (u32::from(bytes[2]) << 16) |
102 (u32::from(bytes[3]) << 24)
103}
104
105pub unsafe fn bytes_to<T>(bytes: &[u8]) -> Result<T, UtilError> {
112 if mem::size_of::<T>() == bytes.len() {
113 let mut new_val: T = mem::uninitialized();
114 ptr::copy(bytes.as_ptr(), &mut new_val as *mut _ as *mut u8, bytes.len());
115 Ok(new_val)
116 } else {
117 Err(UtilError::BytesTo { src: bytes.len(), dst: mem::size_of::<T>() })
118 }
119}
120
121pub unsafe fn bytes_into<T>(vec: Vec<u8>) -> Result<T, UtilError> {
133 if mem::size_of::<T>() == vec.len() {
134 let mut new_val: T = mem::uninitialized();
135 ptr::copy(vec.as_ptr(), &mut new_val as *mut _ as *mut u8, vec.len());
136 Ok(new_val)
137 } else {
138 Err(UtilError::BytesInto { src: vec.len(), dst: mem::size_of::<T>() })
139 }
140}
141
142pub unsafe fn bytes_into_vec<T>(mut vec: Vec<u8>) -> Result<Vec<T>, UtilError> {
151 if vec.len() % mem::size_of::<T>() == 0 {
153 let new_len = vec.len() / mem::size_of::<T>();
154 let new_cap = vec.capacity() / mem::size_of::<T>();
155 let ptr = vec.as_mut_ptr();
156 mem::forget(vec);
157 let mut new_vec: Vec<T> = Vec::from_raw_parts(ptr as *mut T, new_len, new_cap);
158 new_vec.shrink_to_fit();
159 Ok(new_vec)
160 } else {
161 Err(UtilError::BytesIntoVec { src: vec.len(), dst: mem::size_of::<T>() })
162 }
163}
164
165pub unsafe fn bytes_to_vec<T>(bytes: &[u8]) -> Result<Vec<T>, UtilError> {
172 if bytes.len() % mem::size_of::<T>() == 0 {
174 let new_len = bytes.len() / mem::size_of::<T>();
175 let mut new_vec: Vec<T> = Vec::with_capacity(new_len);
176 ptr::copy(bytes.as_ptr(), new_vec.as_mut_ptr() as *mut _ as *mut u8, bytes.len());
177 new_vec.set_len(new_len);
178 Ok(new_vec)
179 } else {
180 Err(UtilError::BytesToVec { src: bytes.len(), dst: mem::size_of::<T>() })
181 }
182}
183
184pub fn bytes_into_string(mut bytes: Vec<u8>) -> Result<String, UtilError> {
187 if bytes.last() == Some(&0u8) {
188 bytes.pop();
189 }
190
191 String::from_utf8(bytes)
192 .map(|str| String::from(str.trim()))
193 .map_err(UtilError::BytesIntoString)
194}
195
196
197pub unsafe fn into_bytes<T>(val: T) -> Vec<u8> {
216 let size = mem::size_of::<T>();
218 let mut new_vec: Vec<u8> = iter::repeat(0).take(size).collect();
219
220 ptr::copy(&val as *const _ as *const u8, new_vec.as_mut_ptr(), size);
221
222 new_vec
227}
228
229pub fn padded_len(len: usize, incr: usize) -> usize {
231 let len_mod = len % incr;
232
233 if len_mod == 0 {
234 len
235 } else {
236 let pad = incr - len_mod;
237 let padded_len = len + pad;
238 debug_assert_eq!(padded_len % incr, 0);
239 padded_len
240 }
241}
242
243
244#[derive(Fail, Debug)]
246pub enum VecRemoveRebuildError {
247 #[fail(display = "Remove list is longer than source vector.")]
248 TooLong,
249 #[fail(display = "'remove_list' contains at least one out of range index: [{}] \
250 ('orig_vec' length: {}).", idx, orig_len)]
251 OutOfRange { idx: usize, orig_len: usize },
252}
253
254pub fn vec_remove_rebuild<T: Clone + Copy>(orig_vec: &mut Vec<T>, remove_list: &[usize],
262 rebuild_threshold: usize) -> Result<(), VecRemoveRebuildError> {
263 if remove_list.len() > orig_vec.len() {
264 return Err(VecRemoveRebuildError::TooLong)
265 }
266 let orig_len = orig_vec.len();
267
268 if remove_list.len() <= rebuild_threshold {
270 for &idx in remove_list.iter().rev() {
271 if idx < orig_len {
272 orig_vec.remove(idx);
273 } else {
274 return Err(VecRemoveRebuildError::OutOfRange { idx, orig_len })
275 }
276 }
277 } else {
278 unsafe {
279 let mut remove_markers: Vec<bool> = iter::repeat(true).take(orig_len).collect();
280
281 for &idx in remove_list.iter() {
283 if idx < orig_len {
284 *remove_markers.get_unchecked_mut(idx) = false;
285 } else {
286 return Err(VecRemoveRebuildError::OutOfRange { idx, orig_len })
287 }
288 }
289
290 let mut new_len = 0usize;
291
292 for idx in 0..orig_len {
294 if *remove_markers.get_unchecked(idx) {
295 *orig_vec.get_unchecked_mut(new_len) = *orig_vec.get_unchecked(idx);
296 new_len += 1;
297 }
298 }
299
300 debug_assert_eq!(new_len, orig_len - remove_list.len());
301 orig_vec.set_len(new_len);
302 }
303 }
304
305 Ok(())
306}
307
308pub fn wrap_vals<T: OclPrm + PrimInt>(vals: &[T], val_n: T) -> Vec<T> {
310 vals.iter().map(|&v| v % val_n).collect()
311}
312
313
314pub fn print_bytes_as_hex(bytes: &[u8]) {
337 print!("0x");
338
339 for &byte in bytes.iter() {
340 print!("{:x}", byte);
341 }
342}
343
344
345#[allow(unused_assignments, unused_variables)]
346pub fn print_slice<T: OclScl>(
352 vec: &[T],
353 every: usize,
354 val_range: Option<(T, T)>,
355 idx_range: Option<Range<usize>>,
356 show_zeros: bool,
357 ) {
358 print!( "{cdgr}[{cg}{}{cdgr}/{}", vec.len(), every, cg = colors::C_GRN, cdgr = colors::C_DGR);
359
360 let (vr_start, vr_end) = match val_range {
361 Some(vr) => {
362 print!( ";({}-{})", vr.0, vr.1);
363 vr
364 },
365 None => (Default::default(), Default::default()),
366 };
367
368 let (ir_start, ir_end) = match idx_range {
369 Some(ref ir) => {
370 print!( ";[{}..{}]", ir.start, ir.end);
371 (ir.start, ir.end)
372 },
373 None => (0usize, 0usize),
374 };
375
376 print!( "]:{cd} ", cd = colors::C_DEFAULT,);
377
378 let mut ttl_nz = 0usize;
379 let mut ttl_ir = 0usize;
380 let mut within_idx_range = true;
381 let mut within_val_range = true;
382 let mut hi: T = vr_start;
383 let mut lo: T = vr_end;
384 let mut sum: i64 = 0;
385 let mut ttl_prntd: usize = 0;
386 let len = vec.len();
387
388
389 let mut color: &'static str = colors::C_DEFAULT;
390 let mut prnt: bool = false;
391
392 for (i, item) in vec.iter().enumerate() {
394
395 prnt = false;
396
397 if every != 0 {
398 if i % every == 0 {
399 prnt = true;
400 } else {
401 prnt = false;
402 }
403 }
404
405 if idx_range.is_some() {
406 let ir = idx_range.as_ref().expect("ocl::buffer::print_vec()");
407
408 if i < ir_start || i >= ir_end {
409 prnt = false;
410 within_idx_range = false;
411 } else {
412 within_idx_range = true;
413 }
414 } else {
415 within_idx_range = true;
416 }
417
418 if val_range.is_some() {
419 if *item < vr_start || *item > vr_end {
420 prnt = false;
421 within_val_range = false;
422 } else {
423 if within_idx_range {
424 ttl_ir += 1;
430 }
431
432 within_val_range = true;
433 }
434 }
435
436 if within_idx_range && within_val_range {
437 sum += item.to_i64().expect("ocl::buffer::print_vec(): vec[i]");
438
439 if *item > hi { hi = *item };
440
441 if *item < lo { lo = *item };
442
443 if vec[i] != Default::default() {
444 ttl_nz += 1usize;
445 color = colors::C_ORA;
446 } else if show_zeros {
447 color = colors::C_DEFAULT;
448 } else {
449 prnt = false;
450 }
451 }
452
453 if prnt {
454 print!( "{cg}[{cd}{}{cg}:{cc}{}{cg}]{cd}", i, vec[i], cc = color, cd = colors::C_DEFAULT, cg = colors::C_DGR);
455 ttl_prntd += 1;
456 }
457 }
458
459 let mut anz: f32 = 0f32;
460 let mut nz_pct: f32 = 0f32;
461
462 let mut ir_pct: f32 = 0f32;
463 let mut avg_ir: f32 = 0f32;
464
465 if ttl_nz > 0 {
466 anz = sum as f32 / ttl_nz as f32;
467 nz_pct = (ttl_nz as f32 / len as f32) * 100f32;
468 }
470
471 if ttl_ir > 0 {
472 avg_ir = sum as f32 / ttl_ir as f32;
473 ir_pct = (ttl_ir as f32 / len as f32) * 100f32;
474 }
476
477
478 println!("{cdgr}; (nz:{clbl}{}{cdgr}({clbl}{:.2}%{cdgr}),\
479 ir:{clbl}{}{cdgr}({clbl}{:.2}%{cdgr}),hi:{},lo:{},anz:{:.2},prntd:{}){cd} ",
480 ttl_nz, nz_pct, ttl_ir, ir_pct, hi, lo, anz, ttl_prntd, cd = colors::C_DEFAULT, clbl = colors::C_LBL, cdgr = colors::C_DGR);
481}
482
483
484pub fn print_simple<T: OclScl>(slice: &[T]) {
485 print_slice(slice, 1, None, None, true);
486}
487
488
489
490pub fn print_val_range<T: OclScl>(slice: &[T], every: usize, val_range: Option<(T, T)>) {
491 print_slice(slice, every, val_range, None, true);
492}
493
494
495#[cfg(test)]
496mod tests {
497 #[test]
500 fn remove_rebuild() {
501 let mut primary_vals: Vec<u32> = (0..(1 << 18)).map(|v| v).collect();
502 let orig_len = primary_vals.len();
503
504 let mut bad_indices: Vec<usize> = Vec::<usize>::with_capacity(1 << 16);
505 let mut idx = 0;
506
507 for &val in primary_vals.iter() {
509 if (val % 19 == 0) || (val % 31 == 0) || (val % 107 == 0) {
510 bad_indices.push(idx);
511 }
512
513 idx += 1;
514 }
515
516 println!("util::tests::remove_rebuild(): bad_indices: {}", bad_indices.len());
517
518 super::vec_remove_rebuild(&mut primary_vals, &bad_indices[..], 3)
520 .expect("util::tests::remove_rebuild()");
521
522 for &val in primary_vals.iter() {
524 if (val % 19 == 0) || (val % 31 == 0) || (val % 107 == 0) {
525 panic!("util::tests::remove_rebuild(): Value: '{}' found in list!", val);
526 }
527 }
528
529 assert_eq!(orig_len, primary_vals.len() + bad_indices.len());
530 }
531}