use crate::{BaseTimer, TArch, TDesc, TraceCount, TraceValue};
#[derive(Debug, Clone, Copy)]
pub struct AccArray<const S: bool, T: TraceValue, C: TraceCount, const N: usize>
where
TDesc<S>: TArch,
{
base: BaseTimer<S>,
accs: [T; N],
cnts: [C; N],
}
impl<const S: bool, T, C, const N: usize> std::default::Default for AccArray<S, T, C, N>
where
TDesc<S>: TArch,
T: TraceValue,
C: TraceCount,
[T; N]: Default,
[C; N]: Default,
{
fn default() -> Self {
let base = BaseTimer::default();
let accs = <[T; N]>::default();
let cnts = <[C; N]>::default();
Self { base, accs, cnts }
}
}
impl<const S: bool, T, C, const N: usize> std::fmt::Display for AccArray<S, T, C, N>
where
TDesc<S>: TArch,
T: TraceValue + std::fmt::Display + std::ops::Div<C>,
<T as std::ops::Div<C>>::Output: std::fmt::Display,
C: TraceCount + std::fmt::Display + PartialEq<C>,
[T; N]: Default,
[C; N]: Default,
{
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
let def_c: C = C::default();
write! {fmt, "["}?;
for i in 0..N {
if i != 0 {
write! {fmt, ", "}?;
}
if self.cnts[i] == def_c {
write!(fmt, "({}, {}, -)", self.accs[i], self.cnts[i])?;
} else {
write!(
fmt,
"({}, {}, {})",
self.accs[i],
self.cnts[i],
self.accs[i] / self.cnts[i]
)?;
}
}
write! {fmt, "]"}
}
}
impl<const S: bool, T, C, const N: usize> AccArray<S, T, C, N>
where
TDesc<S>: TArch,
T: TraceValue,
C: TraceCount,
{
pub fn clear(&mut self) {
unsafe { *self = std::mem::zeroed() };
}
#[inline(always)]
pub fn start(&mut self) {
self.base.start();
}
#[inline(always)]
pub fn acc_n(&mut self, index: usize) {
if index < N {
let delta: u64 = self.base.elapsed();
self.accs[index] = self.accs[index].sat_add(delta);
self.cnts[index].sat_inc();
}
}
#[inline(always)]
pub fn acc_n_restart(&mut self, index: usize) {
if index < N {
let delta = self.base.elapsed_and_update();
self.accs[index] = self.accs[index].sat_add(delta);
self.cnts[index].sat_inc();
}
}
pub fn accs(&self) -> &[T; N] {
&self.accs
}
pub fn cnts(&self) -> &[C; N] {
&self.cnts
}
}
#[derive(Debug, Clone)]
pub struct AccVec<const S: bool, T: TraceValue, C: TraceCount>
where
TDesc<S>: TArch,
{
base: BaseTimer<S>,
index: usize,
acc_cnts: Vec<(T, C)>,
}
impl<const S: bool, T, C> std::default::Default for AccVec<S, T, C>
where
TDesc<S>: TArch,
T: TraceValue,
C: TraceCount,
{
fn default() -> Self {
let base = BaseTimer::default();
let acc_cnts = vec![];
let index = 0;
Self {
base,
index,
acc_cnts,
}
}
}
impl<const S: bool, T, C> std::fmt::Display for AccVec<S, T, C>
where
TDesc<S>: TArch,
T: TraceValue + std::fmt::Display + std::ops::Div<C>,
<T as std::ops::Div<C>>::Output: std::fmt::Display,
C: TraceCount + std::fmt::Display + PartialEq<C>,
{
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
let def_c: C = C::default();
write! {fmt, "["}?;
for (i, ac) in self.acc_cnts.iter().enumerate() {
if i != 0 {
write! {fmt, ", "}?;
}
if ac.1 == def_c {
write!(fmt, "({}, {}, -)", ac.0, ac.1)?;
} else {
write!(fmt, "({}, {}, {})", ac.0, ac.1, ac.0 / ac.1)?;
}
}
write! {fmt, "]"}
}
}
impl<const S: bool, T, C> AccVec<S, T, C>
where
TDesc<S>: TArch,
T: TraceValue,
C: TraceCount,
{
pub fn with_capacity(n: usize) -> Self {
let mut s = Self::default();
s.acc_cnts = vec![(T::default(), C::default()); n];
s
}
pub fn clear(&mut self) {
self.index = 0;
self.acc_cnts.clear();
}
#[inline(always)]
pub fn start(&mut self) {
self.base.start();
self.index = 0;
}
#[inline(always)]
pub fn acc_n(&mut self, index: usize) {
if let Some(ac) = self.acc_cnts.get_mut(index) {
let delta: u64 = self.base.elapsed();
ac.0 = ac.0.sat_add(delta);
ac.1.sat_inc();
}
}
#[inline(always)]
pub fn acc_n_restart(&mut self, index: usize) {
if let Some(ac) = self.acc_cnts.get_mut(index) {
let delta = self.base.elapsed_and_update();
ac.0 = ac.0.sat_add(delta);
ac.1.sat_inc();
} else {
self.base.start();
}
}
#[inline(always)]
pub fn acc_push(&mut self) -> usize {
let n = self.acc_cnts.len();
if n > self.index {
self.acc_n(self.index);
let n = self.index;
self.index += 1;
n
} else {
let delta: u64 = self.base.elapsed();
let delta = T::default().sat_add(delta);
let mut cnt = C::default();
cnt.sat_inc();
self.acc_cnts.push((delta, cnt));
self.index = n + 1;
n
}
}
#[inline(always)]
pub fn acc_push_restart(&mut self) -> usize {
let n = self.acc_cnts.len();
if n > self.index {
self.acc_n_restart(self.index);
let n = self.index;
self.index += 1;
n
} else {
let delta = self.base.elapsed_and_update();
let delta = T::default().sat_add(delta);
let mut cnt = C::default();
cnt.sat_inc();
self.acc_cnts.push((delta, cnt));
self.index = n + 1;
n
}
}
pub fn all_acc_cnts(&self) -> &[(T, C)] {
&self.acc_cnts
}
pub fn acc_cnts(&self) -> &[(T, C)] {
&self.acc_cnts[0..self.index]
}
}