use std::ops::{Add, Div, Mul, MulAssign, Neg};
use super::*;
use crate::complex::*;
use crate::scalars::Scalar;
use num_traits::{Float, Num};
impl Scalar for C<f64> {}
impl Scalar for C<f32> {}
impl Scalar for C<i128> {}
impl Scalar for C<i64> {}
impl Scalar for C<i32> {}
impl Scalar for C<i16> {}
impl Scalar for C<i8> {}
impl Scalar for C<isize> {}
impl Scalar for C<u128> {}
impl Scalar for C<u64> {}
impl Scalar for C<u32> {}
impl Scalar for C<u16> {}
impl Scalar for C<u8> {}
impl Scalar for C<usize> {}
impl<T: Copy + PartialEq + Clone + Debug + Default, R: Unsigned> Ndarr<C<T>, R> {
pub fn re(&self) -> Ndarr<T, R> {
let out = self.map(|z| z.re());
out
}
pub fn im(&self) -> Ndarr<T, R> {
let out = self.map(|z| z.im());
out
}
}
impl<T: Copy + PartialEq + Num + Debug, R: Unsigned> Ndarr<T, R> {
pub fn to_complex(&self) -> Ndarr<C<T>, R> {
let out: Ndarr<C<T>, R> = self.map(|x| C(*x, T::zero()));
out
}
}
impl<T: Copy + PartialEq + Neg<Output = T> + Clone + Debug + Default, R: Unsigned> Ndarr<C<T>, R> {
pub fn conj(&self) -> Self {
let out = self.map(|z| z.conj());
out
}
pub fn h(&self) -> Self {
let out = self.map(|z| z.conj());
out.t()
}
}
impl<T, R: Unsigned> Ndarr<C<T>, R>
where
T: Copy
+ PartialEq
+ Neg<Output = T>
+ Clone
+ Debug
+ Default
+ Div<Output = T>
+ Mul<Output = T>
+ Add<Output = T>,
{
pub fn inv(&self) -> Self {
let out = self.map(|z| z.inv());
out
}
}
impl<
T: Copy + PartialEq + Add<Output = T> + Mul<Output = T> + Clone + Debug + Default,
R: Unsigned,
> Ndarr<C<T>, R>
{
pub fn r_square(&self) -> Ndarr<T, R> {
let out = self.map(|z| z.r_square());
out
}
}
impl<T, R: Unsigned> Ndarr<C<T>, R>
where
C<T>: MulAssign + Debug,
T: Clone + Default + Debug + Copy + PartialEq + Num,
{
pub fn powi(&self, n: i32) -> Self {
let out = self.map(|z| z.powi(n));
out
}
}
impl<T, R: Unsigned> Ndarr<C<T>, R>
where
T: Clone + Debug + Default + Float,
{
pub fn abs(&self) -> Ndarr<T, R> {
let out = self.map(|z| z.abs());
out
}
pub fn exp(&self) -> Self {
let out = self.map(|z| z.exp());
out
}
pub fn arg(&self) -> Ndarr<T, R> {
let out = self.map(|z| z.arg());
out
}
pub fn ln(&self) -> Self {
let out = self.map(|z| z.ln());
out
}
pub fn sqrt(&self) -> Self {
let out = self.map(|z| z.sqrt());
out
}
pub fn powf(&self, n: T) -> Self {
let out = self.map(|z| z.powf(n));
out
}
pub fn powc(&self, _z: C<T>) -> Self {
let out = self.map(|z| z.powc(*z));
out
}
pub fn sin(&self) -> Self {
let out = self.map(|z| z.sin());
out
}
pub fn cos(&self) -> Self {
let out = self.map(|z| z.cos());
out
}
pub fn tan(&self) -> Self {
let out = self.map(|z| z.tan());
out
}
pub fn csc(&self) -> Self {
let out = self.map(|z| z.csc());
out
}
pub fn sec(&self) -> Self {
let out = self.map(|z| z.sec());
out
}
pub fn cot(&self) -> Self {
let out = self.map(|z| z.cot());
out
}
pub fn to_polar(&self) -> Ndarr<(T, T), R> {
let out = self.map(|z| z.to_polar());
out
}
pub fn is_infinite(&self) -> Ndarr<bool, R> {
let out = self.map(|z| z.is_infinite());
out
}
pub fn is_finite(&self) -> Ndarr<bool, R> {
let out = self.map(|z| z.is_finite());
out
}
pub fn is_normal(&self) -> Ndarr<bool, R> {
let out = self.map(|z| z.is_normal());
out
}
pub fn is_nan(&self) -> Ndarr<bool, R> {
let out = self.map(|z| z.is_nan());
out
}
}
#[cfg(test)]
mod complex_tensor_test {
use std::f64::consts::PI;
use super::*;
#[test]
fn test() {
let x = Ndarr::from([1, 2, 3]);
let y = Ndarr::from([1.i(), 1.i(), 1.i()]);
assert_eq!(&x + 1.i(), x + y);
}
#[test]
fn exp_test() {
let quads = Ndarr::from([1. + 0_f64.i(), 1.0.i(), -1. + 0_f64.i(), -1.0.i()]);
println!("{:?}", quads * (PI / 2.).i().exp())
}
}