1use crate::{OclPrm, OclScl};
7use num_traits::PrimInt;
8use std::iter;
9use std::mem;
10use std::ops::Range;
11use std::ptr;
12use std::string::FromUtf8Error;
13
14pub mod colors {
23 pub static TAB: &'static str = " ";
30
31 pub static C_DEFAULT: &'static str = "\x1b[0m";
32 pub static C_UNDER: &'static str = "\x1b[1m";
33
34 pub static C_RED: &'static str = "\x1b[31m";
36 pub static C_BRED: &'static str = "\x1b[1;31m";
37 pub static C_GRN: &'static str = "\x1b[32m";
38 pub static C_BGRN: &'static str = "\x1b[1;32m";
39 pub static C_ORA: &'static str = "\x1b[33m";
40 pub static C_DBL: &'static str = "\x1b[34m";
41 pub static C_PUR: &'static str = "\x1b[35m";
42 pub static C_CYA: &'static str = "\x1b[36m";
43 pub static C_LGR: &'static str = "\x1b[37m";
44 pub static C_DFLT: &'static str = "\x1b[39m";
47
48 pub static C_DGR: &'static str = "\x1b[90m";
50 pub static C_LRD: &'static str = "\x1b[91m";
51 pub static C_YEL: &'static str = "\x1b[93m";
52 pub static C_BLU: &'static str = "\x1b[94m";
53 pub static C_LBL: &'static str = "\x1b[94m";
54 pub static C_MAG: &'static str = "\x1b[95m";
55 pub static BGC_DEFAULT: &'static str = "\x1b[49m";
59 pub static BGC_GRN: &'static str = "\x1b[42m";
60 pub static BGC_PUR: &'static str = "\x1b[45m";
61 pub static BGC_LGR: &'static str = "\x1b[47m";
62 pub static BGC_DGR: &'static str = "\x1b[100m";
63}
64
65#[derive(Debug, thiserror::Error)]
71pub enum UtilError {
72 #[error(
73 "The size of the source byte slice ({src} bytes) does not match \
74 the size of the destination type ({dst} bytes)."
75 )]
76 BytesTo { src: usize, dst: usize },
77 #[error(
78 "The size of the source byte vector ({src} bytes) does not match \
79 the size of the destination type ({dst} bytes)."
80 )]
81 BytesInto { src: usize, dst: usize },
82 #[error(
83 "The size of the source byte vector ({src} bytes) is not evenly \
84 divisible by the size of the destination type ({dst} bytes)."
85 )]
86 BytesIntoVec { src: usize, dst: usize },
87 #[error(
88 "The size of the source byte slice ({src} bytes) is not evenly \
89 divisible by the size of the destination type ({dst} bytes)."
90 )]
91 BytesToVec { src: usize, dst: usize },
92 #[error("Unable to convert bytes into string: {0}")]
93 BytesIntoString(#[from] FromUtf8Error),
94}
95
96pub fn bytes_to_u32(bytes: &[u8]) -> u32 {
103 debug_assert!(bytes.len() == 4);
104
105 u32::from(bytes[0])
106 | (u32::from(bytes[1]) << 8)
107 | (u32::from(bytes[2]) << 16)
108 | (u32::from(bytes[3]) << 24)
109}
110
111pub unsafe fn bytes_to<T>(bytes: &[u8]) -> Result<T, UtilError> {
118 if mem::size_of::<T>() == bytes.len() {
119 let mut new_val = mem::MaybeUninit::<T>::uninit();
120 ptr::copy(bytes.as_ptr(), new_val.as_mut_ptr() as *mut u8, bytes.len());
121 Ok(new_val.assume_init())
122 } else {
123 Err(UtilError::BytesTo {
124 src: bytes.len(),
125 dst: mem::size_of::<T>(),
126 })
127 }
128}
129
130pub unsafe fn bytes_into<T>(vec: Vec<u8>) -> Result<T, UtilError> {
142 if mem::size_of::<T>() == vec.len() {
143 let mut new_val = mem::MaybeUninit::<T>::uninit();
144 ptr::copy(vec.as_ptr(), new_val.as_mut_ptr() as *mut u8, vec.len());
145 Ok(new_val.assume_init())
146 } else {
147 Err(UtilError::BytesInto {
148 src: vec.len(),
149 dst: mem::size_of::<T>(),
150 })
151 }
152}
153
154pub unsafe fn bytes_into_vec<T>(mut vec: Vec<u8>) -> Result<Vec<T>, UtilError> {
163 if vec.len() % mem::size_of::<T>() == 0 {
165 let new_len = vec.len() / mem::size_of::<T>();
166 let new_cap = vec.capacity() / mem::size_of::<T>();
167 let ptr = vec.as_mut_ptr();
168 mem::forget(vec);
169 let mut new_vec: Vec<T> = Vec::from_raw_parts(ptr as *mut T, new_len, new_cap);
170 new_vec.shrink_to_fit();
171 Ok(new_vec)
172 } else {
173 Err(UtilError::BytesIntoVec {
174 src: vec.len(),
175 dst: mem::size_of::<T>(),
176 })
177 }
178}
179
180pub unsafe fn bytes_to_vec<T>(bytes: &[u8]) -> Result<Vec<T>, UtilError> {
187 if bytes.len() % mem::size_of::<T>() == 0 {
189 let new_len = bytes.len() / mem::size_of::<T>();
190 let mut new_vec: Vec<T> = Vec::with_capacity(new_len);
191 ptr::copy(
192 bytes.as_ptr(),
193 new_vec.as_mut_ptr() as *mut _ as *mut u8,
194 bytes.len(),
195 );
196 new_vec.set_len(new_len);
197 Ok(new_vec)
198 } else {
199 Err(UtilError::BytesToVec {
200 src: bytes.len(),
201 dst: mem::size_of::<T>(),
202 })
203 }
204}
205
206pub fn bytes_into_string(mut bytes: Vec<u8>) -> Result<String, UtilError> {
209 if bytes.last() == Some(&0u8) {
210 bytes.pop();
211 }
212
213 String::from_utf8(bytes)
214 .map(|str| String::from(str.trim()))
215 .map_err(UtilError::BytesIntoString)
216}
217
218pub unsafe fn into_bytes<T>(val: T) -> Vec<u8> {
237 let size = mem::size_of::<T>();
239 let mut new_vec: Vec<u8> = iter::repeat(0).take(size).collect();
240
241 ptr::copy(&val as *const _ as *const u8, new_vec.as_mut_ptr(), size);
242
243 new_vec
248}
249
250pub fn padded_len(len: usize, incr: usize) -> usize {
252 let len_mod = len % incr;
253
254 if len_mod == 0 {
255 len
256 } else {
257 let pad = incr - len_mod;
258 let padded_len = len + pad;
259 debug_assert_eq!(padded_len % incr, 0);
260 padded_len
261 }
262}
263
264#[derive(thiserror::Error, Debug)]
266pub enum VecRemoveRebuildError {
267 #[error("Remove list is longer than source vector.")]
268 TooLong,
269 #[error(
270 "'remove_list' contains at least one out of range index: [{idx}] \
271 ('orig_vec' length: {orig_len})."
272 )]
273 OutOfRange { idx: usize, orig_len: usize },
274}
275
276pub fn vec_remove_rebuild<T: Clone + Copy>(
284 orig_vec: &mut Vec<T>,
285 remove_list: &[usize],
286 rebuild_threshold: usize,
287) -> Result<(), VecRemoveRebuildError> {
288 if remove_list.len() > orig_vec.len() {
289 return Err(VecRemoveRebuildError::TooLong);
290 }
291 let orig_len = orig_vec.len();
292
293 if remove_list.len() <= rebuild_threshold {
295 for &idx in remove_list.iter().rev() {
296 if idx < orig_len {
297 orig_vec.remove(idx);
298 } else {
299 return Err(VecRemoveRebuildError::OutOfRange { idx, orig_len });
300 }
301 }
302 } else {
303 unsafe {
304 let mut remove_markers: Vec<bool> = iter::repeat(true).take(orig_len).collect();
305
306 for &idx in remove_list.iter() {
308 if idx < orig_len {
309 *remove_markers.get_unchecked_mut(idx) = false;
310 } else {
311 return Err(VecRemoveRebuildError::OutOfRange { idx, orig_len });
312 }
313 }
314
315 let mut new_len = 0usize;
316
317 for idx in 0..orig_len {
319 if *remove_markers.get_unchecked(idx) {
320 *orig_vec.get_unchecked_mut(new_len) = *orig_vec.get_unchecked(idx);
321 new_len += 1;
322 }
323 }
324
325 debug_assert_eq!(new_len, orig_len - remove_list.len());
326 orig_vec.set_len(new_len);
327 }
328 }
329
330 Ok(())
331}
332
333pub fn wrap_vals<T: OclPrm + PrimInt>(vals: &[T], val_n: T) -> Vec<T> {
335 vals.iter().map(|&v| v % val_n).collect()
336}
337
338pub fn print_bytes_as_hex(bytes: &[u8]) {
361 print!("0x");
362
363 for &byte in bytes.iter() {
364 print!("{:x}", byte);
365 }
366}
367
368#[allow(unused_assignments, unused_variables)]
369pub fn print_slice<T: OclScl>(
375 vec: &[T],
376 every: usize,
377 val_range: Option<(T, T)>,
378 idx_range: Option<Range<usize>>,
379 show_zeros: bool,
380) {
381 print!(
382 "{cdgr}[{cg}{}{cdgr}/{}",
383 vec.len(),
384 every,
385 cg = colors::C_GRN,
386 cdgr = colors::C_DGR
387 );
388
389 let (vr_start, vr_end) = match val_range {
390 Some(vr) => {
391 print!(";({}-{})", vr.0, vr.1);
392 vr
393 }
394 None => (Default::default(), Default::default()),
395 };
396
397 let (ir_start, ir_end) = match idx_range {
398 Some(ref ir) => {
399 print!(";[{}..{}]", ir.start, ir.end);
400 (ir.start, ir.end)
401 }
402 None => (0usize, 0usize),
403 };
404
405 print!("]:{cd} ", cd = colors::C_DEFAULT,);
406
407 let mut ttl_nz = 0usize;
408 let mut ttl_ir = 0usize;
409 let mut within_idx_range = true;
410 let mut within_val_range = true;
411 let mut hi: T = vr_start;
412 let mut lo: T = vr_end;
413 let mut sum: i64 = 0;
414 let mut ttl_prntd: usize = 0;
415 let len = vec.len();
416
417 let mut color: &'static str = colors::C_DEFAULT;
418 let mut prnt: bool = false;
419
420 for (i, item) in vec.iter().enumerate() {
422 prnt = false;
423
424 if every != 0 {
425 if i % every == 0 {
426 prnt = true;
427 } else {
428 prnt = false;
429 }
430 }
431
432 if idx_range.is_some() {
433 let ir = idx_range.as_ref().expect("ocl::buffer::print_vec()");
434
435 if i < ir_start || i >= ir_end {
436 prnt = false;
437 within_idx_range = false;
438 } else {
439 within_idx_range = true;
440 }
441 } else {
442 within_idx_range = true;
443 }
444
445 if val_range.is_some() {
446 if *item < vr_start || *item > vr_end {
447 prnt = false;
448 within_val_range = false;
449 } else {
450 if within_idx_range {
451 ttl_ir += 1;
457 }
458
459 within_val_range = true;
460 }
461 }
462
463 if within_idx_range && within_val_range {
464 sum += item.to_i64().expect("ocl::buffer::print_vec(): vec[i]");
465
466 if *item > hi {
467 hi = *item
468 };
469
470 if *item < lo {
471 lo = *item
472 };
473
474 if vec[i] != Default::default() {
475 ttl_nz += 1usize;
476 color = colors::C_ORA;
477 } else if show_zeros {
478 color = colors::C_DEFAULT;
479 } else {
480 prnt = false;
481 }
482 }
483
484 if prnt {
485 print!(
486 "{cg}[{cd}{}{cg}:{cc}{}{cg}]{cd}",
487 i,
488 vec[i],
489 cc = color,
490 cd = colors::C_DEFAULT,
491 cg = colors::C_DGR
492 );
493 ttl_prntd += 1;
494 }
495 }
496
497 let mut anz: f32 = 0f32;
498 let mut nz_pct: f32 = 0f32;
499
500 let mut ir_pct: f32 = 0f32;
501 let mut avg_ir: f32 = 0f32;
502
503 if ttl_nz > 0 {
504 anz = sum as f32 / ttl_nz as f32;
505 nz_pct = (ttl_nz as f32 / len as f32) * 100f32;
506 }
508
509 if ttl_ir > 0 {
510 avg_ir = sum as f32 / ttl_ir as f32;
511 ir_pct = (ttl_ir as f32 / len as f32) * 100f32;
512 }
514
515 println!(
516 "{cdgr}; (nz:{clbl}{}{cdgr}({clbl}{:.2}%{cdgr}),\
517 ir:{clbl}{}{cdgr}({clbl}{:.2}%{cdgr}),hi:{},lo:{},anz:{:.2},prntd:{}){cd} ",
518 ttl_nz,
519 nz_pct,
520 ttl_ir,
521 ir_pct,
522 hi,
523 lo,
524 anz,
525 ttl_prntd,
526 cd = colors::C_DEFAULT,
527 clbl = colors::C_LBL,
528 cdgr = colors::C_DGR
529 );
530}
531
532pub fn print_simple<T: OclScl>(slice: &[T]) {
533 print_slice(slice, 1, None, None, true);
534}
535
536pub fn print_val_range<T: OclScl>(slice: &[T], every: usize, val_range: Option<(T, T)>) {
537 print_slice(slice, every, val_range, None, true);
538}
539
540#[cfg(test)]
541mod tests {
542 #[test]
545 fn remove_rebuild() {
546 let mut primary_vals: Vec<u32> = (0..(1 << 18)).map(|v| v).collect();
547 let orig_len = primary_vals.len();
548
549 let mut bad_indices: Vec<usize> = Vec::<usize>::with_capacity(1 << 16);
550 let mut idx = 0;
551
552 for &val in primary_vals.iter() {
554 if (val % 19 == 0) || (val % 31 == 0) || (val % 107 == 0) {
555 bad_indices.push(idx);
556 }
557
558 idx += 1;
559 }
560
561 println!(
562 "util::tests::remove_rebuild(): bad_indices: {}",
563 bad_indices.len()
564 );
565
566 super::vec_remove_rebuild(&mut primary_vals, &bad_indices[..], 3)
568 .expect("util::tests::remove_rebuild()");
569
570 for &val in primary_vals.iter() {
572 if (val % 19 == 0) || (val % 31 == 0) || (val % 107 == 0) {
573 panic!(
574 "util::tests::remove_rebuild(): Value: '{}' found in list!",
575 val
576 );
577 }
578 }
579
580 assert_eq!(orig_len, primary_vals.len() + bad_indices.len());
581 }
582}