use crate::dtype::{Complex64, Complex128};
#[cfg(feature = "rayon")]
use rayon::prelude::*;
#[cfg(feature = "rayon")]
const PARALLEL_THRESHOLD: usize = 4096;
#[inline]
pub unsafe fn conj_complex64(
input: *const Complex64,
output: *mut Complex64,
numel: usize,
_chunk_size: usize,
) {
#[cfg(feature = "rayon")]
if numel >= PARALLEL_THRESHOLD {
use std::slice;
let input_slice = slice::from_raw_parts(input, numel);
let output_slice = slice::from_raw_parts_mut(output, numel);
let chunk_size = _chunk_size.max(1);
output_slice
.par_chunks_mut(chunk_size)
.zip(input_slice.par_chunks(chunk_size))
.for_each(|(out_chunk, in_chunk)| {
for (o, &i) in out_chunk.iter_mut().zip(in_chunk) {
*o = i.conj();
}
});
return;
}
for i in 0..numel {
*output.add(i) = (*input.add(i)).conj();
}
}
#[inline]
pub unsafe fn conj_complex128(
input: *const Complex128,
output: *mut Complex128,
numel: usize,
_chunk_size: usize,
) {
#[cfg(feature = "rayon")]
if numel >= PARALLEL_THRESHOLD {
use std::slice;
let input_slice = slice::from_raw_parts(input, numel);
let output_slice = slice::from_raw_parts_mut(output, numel);
let chunk_size = _chunk_size.max(1);
output_slice
.par_chunks_mut(chunk_size)
.zip(input_slice.par_chunks(chunk_size))
.for_each(|(out_chunk, in_chunk)| {
for (o, &i) in out_chunk.iter_mut().zip(in_chunk) {
*o = i.conj();
}
});
return;
}
for i in 0..numel {
*output.add(i) = (*input.add(i)).conj();
}
}
#[inline]
pub unsafe fn real_complex64(
input: *const Complex64,
output: *mut f32,
numel: usize,
_chunk_size: usize,
) {
#[cfg(feature = "rayon")]
if numel >= PARALLEL_THRESHOLD {
use std::slice;
let input_slice = slice::from_raw_parts(input, numel);
let output_slice = slice::from_raw_parts_mut(output, numel);
let chunk_size = _chunk_size.max(1);
output_slice
.par_chunks_mut(chunk_size)
.zip(input_slice.par_chunks(chunk_size))
.for_each(|(out_chunk, in_chunk)| {
for (o, &i) in out_chunk.iter_mut().zip(in_chunk) {
*o = i.re;
}
});
return;
}
for i in 0..numel {
*output.add(i) = (*input.add(i)).re;
}
}
#[inline]
pub unsafe fn real_complex128(
input: *const Complex128,
output: *mut f64,
numel: usize,
_chunk_size: usize,
) {
#[cfg(feature = "rayon")]
if numel >= PARALLEL_THRESHOLD {
use std::slice;
let input_slice = slice::from_raw_parts(input, numel);
let output_slice = slice::from_raw_parts_mut(output, numel);
let chunk_size = _chunk_size.max(1);
output_slice
.par_chunks_mut(chunk_size)
.zip(input_slice.par_chunks(chunk_size))
.for_each(|(out_chunk, in_chunk)| {
for (o, &i) in out_chunk.iter_mut().zip(in_chunk) {
*o = i.re;
}
});
return;
}
for i in 0..numel {
*output.add(i) = (*input.add(i)).re;
}
}
#[inline]
pub unsafe fn imag_complex64(
input: *const Complex64,
output: *mut f32,
numel: usize,
_chunk_size: usize,
) {
#[cfg(feature = "rayon")]
if numel >= PARALLEL_THRESHOLD {
use std::slice;
let input_slice = slice::from_raw_parts(input, numel);
let output_slice = slice::from_raw_parts_mut(output, numel);
let chunk_size = _chunk_size.max(1);
output_slice
.par_chunks_mut(chunk_size)
.zip(input_slice.par_chunks(chunk_size))
.for_each(|(out_chunk, in_chunk)| {
for (o, &i) in out_chunk.iter_mut().zip(in_chunk) {
*o = i.im;
}
});
return;
}
for i in 0..numel {
*output.add(i) = (*input.add(i)).im;
}
}
#[inline]
pub unsafe fn imag_complex128(
input: *const Complex128,
output: *mut f64,
numel: usize,
_chunk_size: usize,
) {
#[cfg(feature = "rayon")]
if numel >= PARALLEL_THRESHOLD {
use std::slice;
let input_slice = slice::from_raw_parts(input, numel);
let output_slice = slice::from_raw_parts_mut(output, numel);
let chunk_size = _chunk_size.max(1);
output_slice
.par_chunks_mut(chunk_size)
.zip(input_slice.par_chunks(chunk_size))
.for_each(|(out_chunk, in_chunk)| {
for (o, &i) in out_chunk.iter_mut().zip(in_chunk) {
*o = i.im;
}
});
return;
}
for i in 0..numel {
*output.add(i) = (*input.add(i)).im;
}
}
#[inline]
pub unsafe fn angle_complex64(
input: *const Complex64,
output: *mut f32,
numel: usize,
_chunk_size: usize,
) {
#[cfg(feature = "rayon")]
if numel >= PARALLEL_THRESHOLD {
use std::slice;
let input_slice = slice::from_raw_parts(input, numel);
let output_slice = slice::from_raw_parts_mut(output, numel);
let chunk_size = _chunk_size.max(1);
output_slice
.par_chunks_mut(chunk_size)
.zip(input_slice.par_chunks(chunk_size))
.for_each(|(out_chunk, in_chunk)| {
for (o, &i) in out_chunk.iter_mut().zip(in_chunk) {
*o = i.phase();
}
});
return;
}
for i in 0..numel {
*output.add(i) = (*input.add(i)).phase();
}
}
#[inline]
pub unsafe fn angle_complex128(
input: *const Complex128,
output: *mut f64,
numel: usize,
_chunk_size: usize,
) {
#[cfg(feature = "rayon")]
if numel >= PARALLEL_THRESHOLD {
use std::slice;
let input_slice = slice::from_raw_parts(input, numel);
let output_slice = slice::from_raw_parts_mut(output, numel);
let chunk_size = _chunk_size.max(1);
output_slice
.par_chunks_mut(chunk_size)
.zip(input_slice.par_chunks(chunk_size))
.for_each(|(out_chunk, in_chunk)| {
for (o, &i) in out_chunk.iter_mut().zip(in_chunk) {
*o = i.phase();
}
});
return;
}
for i in 0..numel {
*output.add(i) = (*input.add(i)).phase();
}
}
#[inline]
pub unsafe fn angle_real_f32(
input: *const f32,
output: *mut f32,
numel: usize,
_chunk_size: usize,
) {
#[cfg(feature = "rayon")]
if numel >= PARALLEL_THRESHOLD {
use std::slice;
let input_slice = slice::from_raw_parts(input, numel);
let output_slice = slice::from_raw_parts_mut(output, numel);
let chunk_size = _chunk_size.max(1);
output_slice
.par_chunks_mut(chunk_size)
.zip(input_slice.par_chunks(chunk_size))
.for_each(|(out_chunk, in_chunk)| {
for (o, &val) in out_chunk.iter_mut().zip(in_chunk) {
*o = if val < 0.0 { std::f32::consts::PI } else { 0.0 };
}
});
return;
}
for i in 0..numel {
let val = *input.add(i);
*output.add(i) = if val < 0.0 { std::f32::consts::PI } else { 0.0 };
}
}
#[inline]
pub unsafe fn angle_real_f64(
input: *const f64,
output: *mut f64,
numel: usize,
_chunk_size: usize,
) {
#[cfg(feature = "rayon")]
if numel >= PARALLEL_THRESHOLD {
use std::slice;
let input_slice = slice::from_raw_parts(input, numel);
let output_slice = slice::from_raw_parts_mut(output, numel);
let chunk_size = _chunk_size.max(1);
output_slice
.par_chunks_mut(chunk_size)
.zip(input_slice.par_chunks(chunk_size))
.for_each(|(out_chunk, in_chunk)| {
for (o, &val) in out_chunk.iter_mut().zip(in_chunk) {
*o = if val < 0.0 { std::f64::consts::PI } else { 0.0 };
}
});
return;
}
for i in 0..numel {
let val = *input.add(i);
*output.add(i) = if val < 0.0 { std::f64::consts::PI } else { 0.0 };
}
}
#[inline]
pub unsafe fn from_real_imag_f32(
real: *const f32,
imag: *const f32,
output: *mut Complex64,
numel: usize,
_chunk_size: usize,
) {
#[cfg(feature = "rayon")]
if numel >= PARALLEL_THRESHOLD {
use std::slice;
let real_slice = slice::from_raw_parts(real, numel);
let imag_slice = slice::from_raw_parts(imag, numel);
let output_slice = slice::from_raw_parts_mut(output, numel);
let chunk_size = _chunk_size.max(1);
output_slice
.par_chunks_mut(chunk_size)
.zip(real_slice.par_chunks(chunk_size))
.zip(imag_slice.par_chunks(chunk_size))
.for_each(|((out_chunk, re_chunk), im_chunk)| {
for ((o, &re), &im) in out_chunk.iter_mut().zip(re_chunk).zip(im_chunk) {
*o = Complex64::new(re, im);
}
});
return;
}
for i in 0..numel {
*output.add(i) = Complex64::new(*real.add(i), *imag.add(i));
}
}
#[inline]
pub unsafe fn from_real_imag_f64(
real: *const f64,
imag: *const f64,
output: *mut Complex128,
numel: usize,
_chunk_size: usize,
) {
#[cfg(feature = "rayon")]
if numel >= PARALLEL_THRESHOLD {
use std::slice;
let real_slice = slice::from_raw_parts(real, numel);
let imag_slice = slice::from_raw_parts(imag, numel);
let output_slice = slice::from_raw_parts_mut(output, numel);
let chunk_size = _chunk_size.max(1);
output_slice
.par_chunks_mut(chunk_size)
.zip(real_slice.par_chunks(chunk_size))
.zip(imag_slice.par_chunks(chunk_size))
.for_each(|((out_chunk, re_chunk), im_chunk)| {
for ((o, &re), &im) in out_chunk.iter_mut().zip(re_chunk).zip(im_chunk) {
*o = Complex128::new(re, im);
}
});
return;
}
for i in 0..numel {
*output.add(i) = Complex128::new(*real.add(i), *imag.add(i));
}
}
#[inline]
pub unsafe fn complex64_mul_real(
complex: *const Complex64,
real: *const f32,
output: *mut Complex64,
numel: usize,
_chunk_size: usize,
) {
#[cfg(feature = "rayon")]
if numel >= PARALLEL_THRESHOLD {
use std::slice;
let complex_slice = slice::from_raw_parts(complex, numel);
let real_slice = slice::from_raw_parts(real, numel);
let output_slice = slice::from_raw_parts_mut(output, numel);
let chunk_size = _chunk_size.max(1);
output_slice
.par_chunks_mut(chunk_size)
.zip(complex_slice.par_chunks(chunk_size))
.zip(real_slice.par_chunks(chunk_size))
.for_each(|((out_chunk, c_chunk), r_chunk)| {
for ((o, &c), &r) in out_chunk.iter_mut().zip(c_chunk).zip(r_chunk) {
*o = Complex64::new(c.re * r, c.im * r);
}
});
return;
}
for i in 0..numel {
let c = *complex.add(i);
let r = *real.add(i);
*output.add(i) = Complex64::new(c.re * r, c.im * r);
}
}
#[inline]
pub unsafe fn complex128_mul_real(
complex: *const Complex128,
real: *const f64,
output: *mut Complex128,
numel: usize,
_chunk_size: usize,
) {
#[cfg(feature = "rayon")]
if numel >= PARALLEL_THRESHOLD {
use std::slice;
let complex_slice = slice::from_raw_parts(complex, numel);
let real_slice = slice::from_raw_parts(real, numel);
let output_slice = slice::from_raw_parts_mut(output, numel);
let chunk_size = _chunk_size.max(1);
output_slice
.par_chunks_mut(chunk_size)
.zip(complex_slice.par_chunks(chunk_size))
.zip(real_slice.par_chunks(chunk_size))
.for_each(|((out_chunk, c_chunk), r_chunk)| {
for ((o, &c), &r) in out_chunk.iter_mut().zip(c_chunk).zip(r_chunk) {
*o = Complex128::new(c.re * r, c.im * r);
}
});
return;
}
for i in 0..numel {
let c = *complex.add(i);
let r = *real.add(i);
*output.add(i) = Complex128::new(c.re * r, c.im * r);
}
}
#[inline]
pub unsafe fn complex64_div_real(
complex: *const Complex64,
real: *const f32,
output: *mut Complex64,
numel: usize,
_chunk_size: usize,
) {
#[cfg(feature = "rayon")]
if numel >= PARALLEL_THRESHOLD {
use std::slice;
let complex_slice = slice::from_raw_parts(complex, numel);
let real_slice = slice::from_raw_parts(real, numel);
let output_slice = slice::from_raw_parts_mut(output, numel);
let chunk_size = _chunk_size.max(1);
output_slice
.par_chunks_mut(chunk_size)
.zip(complex_slice.par_chunks(chunk_size))
.zip(real_slice.par_chunks(chunk_size))
.for_each(|((out_chunk, c_chunk), r_chunk)| {
for ((o, &c), &r) in out_chunk.iter_mut().zip(c_chunk).zip(r_chunk) {
*o = Complex64::new(c.re / r, c.im / r);
}
});
return;
}
for i in 0..numel {
let c = *complex.add(i);
let r = *real.add(i);
*output.add(i) = Complex64::new(c.re / r, c.im / r);
}
}
#[inline]
pub unsafe fn complex128_div_real(
complex: *const Complex128,
real: *const f64,
output: *mut Complex128,
numel: usize,
_chunk_size: usize,
) {
#[cfg(feature = "rayon")]
if numel >= PARALLEL_THRESHOLD {
use std::slice;
let complex_slice = slice::from_raw_parts(complex, numel);
let real_slice = slice::from_raw_parts(real, numel);
let output_slice = slice::from_raw_parts_mut(output, numel);
let chunk_size = _chunk_size.max(1);
output_slice
.par_chunks_mut(chunk_size)
.zip(complex_slice.par_chunks(chunk_size))
.zip(real_slice.par_chunks(chunk_size))
.for_each(|((out_chunk, c_chunk), r_chunk)| {
for ((o, &c), &r) in out_chunk.iter_mut().zip(c_chunk).zip(r_chunk) {
*o = Complex128::new(c.re / r, c.im / r);
}
});
return;
}
for i in 0..numel {
let c = *complex.add(i);
let r = *real.add(i);
*output.add(i) = Complex128::new(c.re / r, c.im / r);
}
}