singe-npp 0.1.0-alpha.8

Safe Rust wrappers for NVIDIA Performance Primitives library (NPP).
Documentation
use singe_cuda::types::Complex32;

use crate::{
    context::StreamContext,
    error::Result,
    image::{
        linear,
        view::{C1, ImageView, ImageViewMut},
    },
    pipeline::{ImageAllocator, Workspace},
};

use super::{ImageBacking, ImagePipeline};

type ComplexMagnitudeImageOperation =
    fn(&StreamContext, &ImageView<'_, Complex32, C1>, &mut ImageViewMut<'_, f32, C1>) -> Result<()>;

pub trait MagnitudeImage {
    fn magnitude_image(
        stream_context: &StreamContext,
        source: &ImageView<'_, Complex32, C1>,
        destination: &mut ImageViewMut<'_, f32, C1>,
    ) -> Result<()>;

    fn magnitude_squared_image(
        stream_context: &StreamContext,
        source: &ImageView<'_, Complex32, C1>,
        destination: &mut ImageViewMut<'_, f32, C1>,
    ) -> Result<()>;
}

impl<'a> MagnitudeImage for ImagePipeline<'a, Complex32, C1> {
    fn magnitude_image(
        stream_context: &StreamContext,
        source: &ImageView<'_, Complex32, C1>,
        destination: &mut ImageViewMut<'_, f32, C1>,
    ) -> Result<()> {
        linear::magnitude(stream_context, source, destination)
    }

    fn magnitude_squared_image(
        stream_context: &StreamContext,
        source: &ImageView<'_, Complex32, C1>,
        destination: &mut ImageViewMut<'_, f32, C1>,
    ) -> Result<()> {
        linear::magnitude_squared(stream_context, source, destination)
    }
}

impl<'a> ImagePipeline<'a, Complex32, C1>
where
    Self: MagnitudeImage,
{
    pub fn magnitude_into(
        stream_context: &StreamContext,
        source: &ImageView<'_, Complex32, C1>,
        destination: &mut ImageViewMut<'_, f32, C1>,
    ) -> Result<()> {
        <Self as MagnitudeImage>::magnitude_image(stream_context, source, destination)
    }

    pub fn magnitude_squared_into(
        stream_context: &StreamContext,
        source: &ImageView<'_, Complex32, C1>,
        destination: &mut ImageViewMut<'_, f32, C1>,
    ) -> Result<()> {
        <Self as MagnitudeImage>::magnitude_squared_image(stream_context, source, destination)
    }
}

impl<'a> ImagePipeline<'a, Complex32, C1>
where
    Workspace: ImageAllocator<f32, C1>,
    Self: MagnitudeImage,
{
    pub fn magnitude(self) -> Result<ImagePipeline<'a, f32, C1>> {
        self.linear_to_f32(<Self as MagnitudeImage>::magnitude_image)
    }

    pub fn magnitude_squared(self) -> Result<ImagePipeline<'a, f32, C1>> {
        self.linear_to_f32(<Self as MagnitudeImage>::magnitude_squared_image)
    }

    fn linear_to_f32(
        self,
        operation: ComplexMagnitudeImageOperation,
    ) -> Result<ImagePipeline<'a, f32, C1>> {
        let mut destination = self.workspace.image::<f32, C1>(self.size())?;

        {
            let source = self.view()?;
            let mut destination_view = destination.view_mut()?;
            operation(self.stream_context, &source, &mut destination_view)?;
        }

        Ok(ImagePipeline {
            stream_context: self.stream_context,
            workspace: self.workspace,
            backing: ImageBacking::Owned(destination),
        })
    }
}