#[macro_export]
macro_rules! assert_almost_eq {
($a:expr, $b:expr, $prec:expr) => {
let diff = ($a - $b).abs();
if diff > $prec {
panic!(
"assertion failed: `abs(left - right) = {:.1e} < {:e}`, \
(left: `{}`, right: `{}`)",
diff, $prec, $a, $b
);
}
};
}
#[macro_export]
macro_rules! concatenate {
( $visibility:vis $name:ident, $([$estimator:ident, $statistic:ident]),+ ) => {
concatenate!($visibility $name, $([$estimator, $statistic, $statistic]),* );
};
( $visibility:vis $name:ident, $( [$estimator:ident, $field:ident, $($statistic:ident),+] ),+ ) => {
$visibility struct $name {
$(
$field: $estimator,
)*
}
impl $name {
#[inline]
pub fn new() -> $name {
$name {
$(
$field: ::core::default::Default::default(),
)*
}
}
#[inline]
pub fn add(&mut self, x: f64) {
$(
self.$field.add(x);
)*
}
$( $(
#[inline]
pub fn $statistic(&self) -> f64 {
self.$field.$statistic()
}
)* )*
}
impl Default for $name {
fn default() -> $name {
$name::new()
}
}
$crate::impl_from_iterator!($name);
};
}
#[macro_export]
macro_rules! impl_from_iterator {
( $name:ident ) => {
impl ::core::iter::FromIterator<f64> for $name {
fn from_iter<T>(iter: T) -> $name
where
T: IntoIterator<Item = f64>,
{
let mut e = $name::new();
for i in iter {
e.add(i);
}
e
}
}
impl<'a> ::core::iter::FromIterator<&'a f64> for $name {
fn from_iter<T>(iter: T) -> $name
where
T: IntoIterator<Item = &'a f64>,
{
let mut e = $name::new();
for &i in iter {
e.add(i);
}
e
}
}
};
}
#[macro_export]
macro_rules! impl_from_par_iterator {
( $name:ident ) => {
#[cfg(feature = "rayon")]
impl ::rayon::iter::FromParallelIterator<f64> for $name {
fn from_par_iter<I>(par_iter: I) -> $name
where
I: ::rayon::iter::IntoParallelIterator<Item = f64>,
Self: $crate::Merge,
{
use ::rayon::iter::ParallelIterator;
use $crate::Merge;
let par_iter = par_iter.into_par_iter();
par_iter
.fold(
|| $name::new(),
|mut e, i| {
e.add(i);
e
},
)
.reduce(
|| $name::new(),
|mut a, b| {
a.merge(&b);
a
},
)
}
}
#[cfg(feature = "rayon")]
impl<'a> ::rayon::iter::FromParallelIterator<&'a f64> for $name {
fn from_par_iter<I>(par_iter: I) -> $name
where
I: ::rayon::iter::IntoParallelIterator<Item = &'a f64>,
Self: $crate::Merge,
{
use ::rayon::iter::ParallelIterator;
use $crate::Merge;
let par_iter = par_iter.into_par_iter();
par_iter
.fold(
|| $name::new(),
|mut e, i| {
e.add(*i);
e
},
)
.reduce(
|| $name::new(),
|mut a, b| {
a.merge(&b);
a
},
)
}
}
};
}
#[macro_export]
macro_rules! impl_extend {
( $name:ident ) => {
impl ::core::iter::Extend<f64> for $name {
fn extend<T>(&mut self, iter: T)
where
T: IntoIterator<Item = f64>,
{
for i in iter {
self.add(i);
}
}
}
impl<'a> ::core::iter::Extend<&'a f64> for $name {
fn extend<T>(&mut self, iter: T)
where
T: IntoIterator<Item = &'a f64>,
{
for &i in iter {
self.add(i);
}
}
}
};
}