singe-npp 0.1.0-alpha.8

Safe Rust wrappers for NVIDIA Performance Primitives library (NPP).
Documentation
mod binary;
mod conversion;
mod copy;
mod fill;
mod filtering;
mod normalize;
mod operations;
mod scaled_constant;
mod statistics;
mod statistics_error_methods;
mod statistics_extremum_methods;
mod statistics_methods;
mod statistics_output_methods;
mod unary;

use singe_cuda::memory::DeviceMemory;

use crate::{
    context::StreamContext,
    error::Result,
    pipeline::{SignalAllocator, Workspace, memory_context::validate_device_memory_stream_context},
    signal::{
        memory::Signal,
        view::{SignalView, SignalViewMut},
    },
};

pub use copy::CopySignal;
pub use statistics::{SignalIndexedValue, SignalMeanStandardDeviation, SignalMinMax};

#[derive(Debug)]
#[non_exhaustive]
pub enum SignalBacking<'a, T> {
    Borrowed(SignalView<'a, T>),
    Owned(Signal<T>),
}

pub struct SignalPipeline<'a, T> {
    stream_context: &'a StreamContext,
    workspace: &'a mut Workspace,
    backing: SignalBacking<'a, T>,
}

impl<'a, T> SignalPipeline<'a, T>
where
    T: Copy,
{
    pub fn create(
        stream_context: &'a StreamContext,
        workspace: &'a mut Workspace,
        len: usize,
    ) -> Result<Self>
    where
        Workspace: SignalAllocator<T>,
    {
        let signal = workspace.signal::<T>(len)?;
        Ok(Self::from_owned(stream_context, workspace, signal))
    }

    pub fn from_view(
        stream_context: &'a StreamContext,
        workspace: &'a mut Workspace,
        source: SignalView<'a, T>,
    ) -> Self {
        Self {
            stream_context,
            workspace,
            backing: SignalBacking::Borrowed(source),
        }
    }

    pub fn from_owned(
        stream_context: &'a StreamContext,
        workspace: &'a mut Workspace,
        signal: Signal<T>,
    ) -> Self {
        Self {
            stream_context,
            workspace,
            backing: SignalBacking::Owned(signal),
        }
    }

    pub fn from_memory(
        stream_context: &'a StreamContext,
        workspace: &'a mut Workspace,
        memory: &'a DeviceMemory<T>,
        len: usize,
    ) -> Result<Self> {
        validate_device_memory_stream_context(stream_context, memory)?;
        Ok(Self::from_view(
            stream_context,
            workspace,
            SignalView::from_memory(memory, len)?,
        ))
    }

    pub const fn len(&self) -> usize {
        match &self.backing {
            SignalBacking::Borrowed(view) => view.len(),
            SignalBacking::Owned(signal) => signal.len(),
        }
    }

    pub const fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub const fn is_owned(&self) -> bool {
        matches!(self.backing, SignalBacking::Owned(_))
    }

    fn view(&self) -> Result<SignalView<'_, T>> {
        match &self.backing {
            SignalBacking::Borrowed(view) => Ok(*view),
            SignalBacking::Owned(signal) => signal.view(),
        }
    }

    pub fn into_backing(self) -> SignalBacking<'a, T> {
        self.backing
    }
}

impl<'a, T> SignalPipeline<'a, T>
where
    T: Copy,
    Workspace: SignalAllocator<T>,
    Self: CopySignal<T>,
{
    pub fn finish(self) -> Result<Signal<T>> {
        match self.backing {
            SignalBacking::Owned(signal) => Ok(signal),
            SignalBacking::Borrowed(source) => {
                let mut destination = self.workspace.signal::<T>(source.len())?;
                let mut destination_view = destination.view_mut()?;
                <Self as CopySignal<T>>::copy(self.stream_context, &source, &mut destination_view)?;
                Ok(destination)
            }
        }
    }
}

impl<'a, T> SignalPipeline<'a, T>
where
    T: Copy,
    Self: CopySignal<T>,
{
    pub fn copy_into(
        stream_context: &StreamContext,
        source: &SignalView<'_, T>,
        destination: &mut SignalViewMut<'_, T>,
    ) -> Result<()> {
        <Self as CopySignal<T>>::copy(stream_context, source, destination)
    }
}