singe-npp 0.1.0-alpha.8

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

use crate::{
    context::StreamContext,
    error::Result,
    image::view::{ChannelLayout, ImageView},
    types::Point,
};

use super::{
    ImagePipeline,
    statistics::{
        ImageIndexedMinMax, ImageIndexedStatistic, ImageStatistic, IndexedExtremumStatisticImage,
    },
};

#[path = "statistics_paired_indexed_extremum_methods.rs"]
mod paired_methods;

impl<'a, T, L> ImagePipeline<'a, T, L>
where
    T: Copy,
    L: ChannelLayout,
    Self: IndexedExtremumStatisticImage<T, L>,
{
    pub fn min_index_into(
        stream_context: &StreamContext,
        source: &ImageView<'_, T, L>,
        output: &mut DeviceMemory<T>,
        index_x: &mut DeviceMemory<i32>,
        index_y: &mut DeviceMemory<i32>,
    ) -> Result<()> {
        <Self as IndexedExtremumStatisticImage<T, L>>::min_index(
            stream_context,
            source,
            output,
            index_x,
            index_y,
        )
    }

    pub fn max_index_into(
        stream_context: &StreamContext,
        source: &ImageView<'_, T, L>,
        output: &mut DeviceMemory<T>,
        index_x: &mut DeviceMemory<i32>,
        index_y: &mut DeviceMemory<i32>,
    ) -> Result<()> {
        <Self as IndexedExtremumStatisticImage<T, L>>::max_index(
            stream_context,
            source,
            output,
            index_x,
            index_y,
        )
    }

    pub fn min_index(self) -> Result<ImageIndexedStatistic<T>> {
        self.indexed_extremum_statistic(<Self as IndexedExtremumStatisticImage<T, L>>::min_index)
    }

    pub fn max_index(self) -> Result<ImageIndexedStatistic<T>> {
        self.indexed_extremum_statistic(<Self as IndexedExtremumStatisticImage<T, L>>::max_index)
    }

    fn indexed_extremum_statistic(
        self,
        statistic: fn(
            &StreamContext,
            &ImageView<'_, T, L>,
            &mut DeviceMemory<T>,
            &mut DeviceMemory<i32>,
            &mut DeviceMemory<i32>,
        ) -> Result<()>,
    ) -> Result<ImageIndexedStatistic<T>> {
        let output_channels = <Self as IndexedExtremumStatisticImage<T, L>>::OUTPUT_CHANNELS;
        let mut value = DeviceMemory::<T>::create(output_channels)?;
        let mut index_x = DeviceMemory::<i32>::create(output_channels)?;
        let mut index_y = DeviceMemory::<i32>::create(output_channels)?;
        {
            let source = self.view()?;
            statistic(
                self.stream_context,
                &source,
                &mut value,
                &mut index_x,
                &mut index_y,
            )?;
        }
        Ok(ImageIndexedStatistic {
            value: ImageStatistic::from_values(value),
            index_x: ImageStatistic::from_values(index_x),
            index_y: ImageStatistic::from_values(index_y),
        })
    }
}

pub(super) fn image_indexed_min_max<T>(
    min: DeviceMemory<T>,
    max: DeviceMemory<T>,
    min_index: DeviceMemory<Point>,
    max_index: DeviceMemory<Point>,
) -> Result<ImageIndexedMinMax<T>> {
    let min_index = split_points(min_index)?;
    let max_index = split_points(max_index)?;
    Ok(ImageIndexedMinMax {
        min: ImageIndexedStatistic {
            value: ImageStatistic::from_values(min),
            index_x: min_index.0,
            index_y: min_index.1,
        },
        max: ImageIndexedStatistic {
            value: ImageStatistic::from_values(max),
            index_x: max_index.0,
            index_y: max_index.1,
        },
    })
}

fn split_points(points: DeviceMemory<Point>) -> Result<(ImageStatistic<i32>, ImageStatistic<i32>)> {
    let host_points = points.copy_to_host_vec()?;
    let mut index_x = Vec::with_capacity(host_points.len());
    let mut index_y = Vec::with_capacity(host_points.len());
    for point in host_points {
        index_x.push(point.x);
        index_y.push(point.y);
    }

    Ok((
        ImageStatistic::from_values(DeviceMemory::from_slice(&index_x)?),
        ImageStatistic::from_values(DeviceMemory::from_slice(&index_y)?),
    ))
}