#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(not(feature = "std"))]
use alloc::{string::String, vec::Vec};
mod backend;
mod buffer;
mod error;
mod plan;
#[cfg(feature = "cuda")]
pub mod cuda;
#[cfg(feature = "metal")]
pub mod metal;
pub use backend::{GpuBackend, GpuCapabilities};
pub use buffer::GpuBuffer;
pub use error::{GpuError, GpuResult};
pub use plan::{GpuDirection, GpuFft, GpuPlan};
use crate::kernel::{Complex, Float};
pub trait GpuFftEngine<T: Float>: Send + Sync {
fn forward(&self, input: &[Complex<T>], output: &mut [Complex<T>]) -> GpuResult<()>;
fn inverse(&self, input: &[Complex<T>], output: &mut [Complex<T>]) -> GpuResult<()>;
fn forward_inplace(&self, data: &mut [Complex<T>]) -> GpuResult<()>;
fn inverse_inplace(&self, data: &mut [Complex<T>]) -> GpuResult<()>;
fn size(&self) -> usize;
fn backend(&self) -> GpuBackend;
fn sync(&self) -> GpuResult<()>;
}
pub trait GpuBatchFft<T: Float>: GpuFftEngine<T> {
fn forward_batch(
&self,
input: &[Complex<T>],
output: &mut [Complex<T>],
batch_size: usize,
) -> GpuResult<()>;
fn inverse_batch(
&self,
input: &[Complex<T>],
output: &mut [Complex<T>],
batch_size: usize,
) -> GpuResult<()>;
}
#[must_use]
pub fn is_gpu_available() -> bool {
#[cfg(feature = "cuda")]
if cuda::is_available() {
return true;
}
#[cfg(feature = "metal")]
if metal::is_available() {
return true;
}
false
}
#[must_use]
pub fn best_backend() -> Option<GpuBackend> {
#[cfg(feature = "cuda")]
if cuda::is_available() {
return Some(GpuBackend::Cuda);
}
#[cfg(feature = "metal")]
if metal::is_available() {
return Some(GpuBackend::Metal);
}
None
}
pub fn query_capabilities() -> GpuResult<GpuCapabilities> {
#[cfg(feature = "cuda")]
if cuda::is_available() {
return cuda::query_capabilities();
}
#[cfg(feature = "metal")]
if metal::is_available() {
return metal::query_capabilities();
}
Err(GpuError::NoBackendAvailable)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_gpu_available() {
let _ = is_gpu_available();
}
#[test]
fn test_best_backend() {
let _ = best_backend();
}
}