use crate::traits::{Arg, Complex, IsNaN, Norm, Sqrt};
use num_traits::bounds::Bounded;
use num_traits::{FromPrimitive, One, Pow, ToPrimitive, Zero};
use std::cmp::Ordering;
use std::iter::zip;
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub};
pub fn zeros<T>(n: usize) -> Vec<T>
where
T: Clone + Zero,
{
crate::full::zeros(1, n)
}
pub fn ones<T>(n: usize) -> Vec<T>
where
T: Clone + One,
{
crate::full::ones(1, n)
}
pub fn find<T, U>(a: &[T]) -> Vec<U>
where
T: Zero,
U: FromPrimitive,
{
a.iter()
.enumerate()
.filter_map(|(i, v)| {
if !v.is_zero() {
Some(U::from_usize(i).unwrap())
} else {
None
}
})
.collect()
}
pub fn any<T>(a: &[T]) -> bool
where
T: Zero,
{
for v in a {
if !v.is_zero() {
return true;
}
}
false
}
pub fn all<T>(a: &[T]) -> bool
where
T: Zero,
{
for v in a {
if v.is_zero() {
return false;
}
}
true
}
pub fn range<T>(stop: usize) -> Vec<T>
where
T: FromPrimitive,
{
(0..stop).map(|i| T::from_usize(i).unwrap()).collect()
}
pub fn arange<T>(start: T, stop: T, step: T) -> Vec<T>
where
T: Copy + Sub<Output = T> + Div<Output = T> + ToPrimitive + PartialOrd + AddAssign,
{
let mut a = Vec::with_capacity(((stop - start) / step).to_usize().unwrap());
let mut v = start;
while v < stop {
a.push(v);
v += step;
}
a
}
pub fn and<T, U>(a: &[T], b: &[T]) -> Vec<U>
where
T: Zero,
U: Zero + One,
{
a.iter()
.zip(b)
.map(|(x, y)| {
if !x.is_zero() && !y.is_zero() {
U::one()
} else {
U::zero()
}
})
.collect()
}
pub fn or<T, U>(a: &[T], b: &[T]) -> Vec<U>
where
T: Zero,
U: Zero + One,
{
a.iter()
.zip(b)
.map(|(x, y)| {
if !x.is_zero() || !y.is_zero() {
U::one()
} else {
U::zero()
}
})
.collect()
}
pub fn not<T, U>(a: &[T]) -> Vec<U>
where
T: Zero,
U: One + Zero,
{
a.iter()
.map(|v| if v.is_zero() { U::one() } else { U::zero() })
.collect()
}
pub fn eq<T, U>(a: &[T], v: T) -> Vec<U>
where
T: Copy + PartialEq,
U: Zero + One,
{
a.iter()
.map(|&w| if w == v { U::one() } else { U::zero() })
.collect()
}
pub fn ne<T, U>(a: &[T], v: T) -> Vec<U>
where
T: Copy + PartialEq,
U: Zero + One,
{
a.iter()
.map(|&w| if w != v { U::one() } else { U::zero() })
.collect()
}
pub fn gt<T, U>(a: &[T], v: T) -> Vec<U>
where
T: Copy + PartialOrd,
U: Zero + One,
{
a.iter()
.map(|&w| if w > v { U::one() } else { U::zero() })
.collect()
}
pub fn lt<T, U>(a: &[T], v: T) -> Vec<U>
where
T: Copy + PartialOrd,
U: Zero + One,
{
a.iter()
.map(|&w| if w < v { U::one() } else { U::zero() })
.collect()
}
pub fn ge<T, U>(a: &[T], v: T) -> Vec<U>
where
T: Copy + PartialOrd,
U: Zero + One,
{
a.iter()
.map(|&w| if w >= v { U::one() } else { U::zero() })
.collect()
}
pub fn le<T, U>(a: &[T], v: T) -> Vec<U>
where
T: Copy + PartialOrd,
U: Zero + One,
{
a.iter()
.map(|&w| if w <= v { U::one() } else { U::zero() })
.collect()
}
pub fn less_than<T, U>(a: &[T], b: &[T]) -> Vec<U>
where
T: Copy + PartialOrd,
U: One + Zero,
{
a.iter()
.zip(b)
.map(|(&x, &y)| if x < y { U::one() } else { U::zero() })
.collect()
}
pub fn greater_than<T, U>(a: &[T], b: &[T]) -> Vec<U>
where
T: Copy + PartialOrd,
U: One + Zero,
{
a.iter()
.zip(b)
.map(|(&x, &y)| if x > y { U::one() } else { U::zero() })
.collect()
}
pub fn equal<T, U>(a: &[T], b: &[T]) -> Vec<U>
where
T: Copy + PartialEq,
U: One + Zero,
{
a.iter()
.zip(b)
.map(|(&x, &y)| if x == y { U::one() } else { U::zero() })
.collect()
}
pub fn not_equal<T, U>(a: &[T], b: &[T]) -> Vec<U>
where
T: Copy + PartialEq,
U: One + Zero,
{
a.iter()
.zip(b)
.map(|(&x, &y)| if x != y { U::one() } else { U::zero() })
.collect()
}
pub fn sub<T>(a: &[T], b: &[T]) -> Vec<T>
where
T: Copy + Sub<Output = T>,
{
zip(a, b).map(|(ai, bi)| *ai - *bi).collect()
}
pub fn pow<T>(a: &[T], x: T) -> Vec<T>
where
T: Copy + Pow<T, Output = T>,
{
a.iter().map(|ai| ai.pow(x)).collect()
}
pub fn select<T>(a: &[T], ix: &[usize]) -> Vec<T>
where
T: Copy,
{
ix.iter().map(|&i| a[i]).collect()
}
pub fn set_slice<T>(a: &mut [T], ix: &[usize], v: &[T])
where
T: Copy,
{
ix.iter().zip(v).for_each(|(&i, &x)| a[i] = x);
}
pub fn set_all<T>(a: &mut [T], ix: &[usize], v: T)
where
T: Copy,
{
ix.iter().for_each(|&i| a[i] = v);
}
pub fn nonzero<T, U>(a: &[T]) -> Vec<U>
where
T: Zero,
U: One + Zero,
{
a.iter()
.map(|v| if v.is_zero() { U::zero() } else { U::one() })
.collect()
}
pub fn prod<T>(a: &[T]) -> T
where
T: Zero + Mul<T, Output = T> + Copy,
{
a.into_iter()
.map(|&v| v)
.reduce(|x, y| x * y)
.unwrap_or(T::zero())
}
pub fn cum_sum<T>(a: &[T]) -> Vec<T>
where
T: Zero + AddAssign + Copy,
{
let mut sum = T::zero();
a.iter()
.map(|&v| {
sum += v;
sum
})
.collect()
}
pub fn dot<T>(a: &[T], b: &[T]) -> T
where
T: Mul<Output = T> + Add<Output = T> + Zero + Copy,
{
return a
.iter()
.zip(b)
.map(|(&ai, &bi)| ai * bi)
.reduce(|x, y| x + y)
.unwrap_or(T::zero());
}
pub fn argsort<T>(a: &[T], reverse: bool) -> Vec<usize>
where
T: PartialOrd + Copy,
{
let mut ix: Vec<usize> = (0..a.len()).collect();
ix.sort_unstable_by(|&i, &j| a[i].partial_cmp(&a[j]).unwrap());
if reverse {
ix.reverse()
}
ix
}
pub fn norm_inf<N: Norm<T>, T>(a: &[N]) -> T
where
T: Bounded + PartialOrd,
{
let mut max = T::min_value();
for i in 0..a.len() {
let absvi = a[i].norm();
if absvi > max {
max = absvi
}
}
max
}
pub fn argmax<T>(a: &[T]) -> usize
where
T: Bounded + PartialOrd + Copy,
{
assert_ne!(a.len(), 0);
let mut max = T::min_value();
let mut ix = 0;
for (i, &v) in a.iter().enumerate() {
if v > max {
max = v;
ix = i;
}
}
ix
}
pub fn sum<T>(a: &[T]) -> T
where
T: Zero + Copy + AddAssign,
{
assert_ne!(a.len(), 0);
let mut sum = T::zero();
for &v in a {
sum += v;
}
sum
}
pub fn mean<T>(a: &[T]) -> T
where
T: Zero + Copy + AddAssign + Div<Output = T> + FromPrimitive,
{
assert_ne!(a.len(), 0);
sum(a) / T::from_usize(a.len()).unwrap()
}
pub fn std<T>(a: &[T]) -> T
where
T: Zero
+ Copy
+ AddAssign
+ Div<Output = T>
+ Sqrt
+ FromPrimitive
+ Pow<usize, Output = T>
+ Sub<Output = T>,
{
let mean = mean(a);
let mut sum = T::zero();
for &v in a {
sum += T::pow(v - mean, 2);
}
let variance = sum / T::from_usize(a.len()).unwrap();
T::sqrt(&variance)
}
pub fn linspace<T>(start: T, stop: T, num: usize, inclusive: bool) -> Vec<T>
where
T: Zero
+ FromPrimitive
+ Copy
+ Sub<Output = T>
+ Div<Output = T>
+ PartialEq
+ DivAssign
+ MulAssign
+ AddAssign
+ One,
{
let div = if inclusive { num - 1 } else { num };
let div = T::from_usize(div).unwrap();
let mut y = vec![T::zero(); num];
for i in 0..num {
y[i] = T::from_usize(i).unwrap()
}
let delta = stop - start;
if num > 1 {
let step = delta / div;
if step == T::zero() {
y.iter_mut().for_each(|v| *v /= div);
y.iter_mut().for_each(|v| *v *= delta);
} else {
y.iter_mut().for_each(|v| *v *= step);
}
} else {
y.iter_mut().for_each(|v| *v *= delta);
}
y.iter_mut().for_each(|v| *v += start);
if inclusive && num > 1 {
y[num - 1] = stop
}
y
}
pub fn diff<T>(a: &[T]) -> Vec<T>
where
T: Zero + Copy + Sub<Output = T>,
{
assert_ne!(a.len(), 0);
let n = a.len();
if n == 1 {
return vec![];
}
let mut b = vec![T::zero(); n - 1];
for i in 1..n {
b[i - 1] = a[i] - a[i - 1];
}
b
}
pub fn norm<T>(a: &[T]) -> T
where
T: Zero + Copy + Sqrt + Mul<Output = T> + AddAssign,
{
let mut sqsum = T::zero();
for i in 0..a.len() {
sqsum += a[i] * a[i];
}
T::sqrt(&sqsum)
}
pub fn max<T>(a: &[T]) -> T
where
T: Bounded + PartialOrd + Copy,
{
a.iter()
.map(|&v| v)
.max_by(|&a, b| a.partial_cmp(b).unwrap())
.unwrap()
}
pub fn min<T>(a: &[T]) -> T
where
T: Bounded + PartialOrd + Copy,
{
a.iter()
.map(|&v| v)
.min_by(|&a, b| a.partial_cmp(b).unwrap())
.unwrap()
}
pub fn max2<T>(a: &[T], b: &[T]) -> Vec<T>
where
T: Bounded + PartialOrd + Copy,
{
zip(a, b)
.map(|(a, b)| match a.partial_cmp(b).unwrap() {
Ordering::Less => *a,
Ordering::Equal => *a,
Ordering::Greater => *b,
})
.collect()
}
pub fn is_nan<T>(a: &[T]) -> Vec<usize>
where
T: IsNaN,
{
let mut b = vec![0; a.len()];
for i in 0..a.len() {
if T::is_nan(&a[i]) {
b[i] = 1;
}
}
b
}
pub fn abs<T, F>(a: &[T]) -> Vec<F>
where
T: Norm<F> + Copy,
{
crate::iter::abs(a.iter().copied()).collect()
}
pub fn angle<T, F>(a: &[T]) -> Vec<F>
where
T: Arg<F> + Copy,
{
crate::iter::angle(a.iter().copied()).collect()
}
pub fn isempty<T>(a: &[T]) -> bool {
a.is_empty()
}
pub fn polar<T, C>(r: &[T], theta: &[T]) -> Vec<C>
where
C: Complex<T>,
T: Copy,
{
zip(r, theta).map(|p| C::from_polar(*p.0, *p.1)).collect()
}
pub fn complex<T, C>(re: &[T], im: &[T]) -> Vec<C>
where
C: Complex<T>,
T: Copy,
{
zip(re, im).map(|p| C::new(*p.0, *p.1)).collect()
}
pub fn conj<C, T>(a: &[C]) -> Vec<C>
where
C: Complex<T>,
{
a.iter().map(|c| c.conj()).collect()
}
pub fn recip<T>(a: &[T]) -> Vec<T>
where
T: One + Div<Output = T> + Copy,
{
a.iter().map(|v| T::one() / *v).collect()
}