singe-cusparse 0.1.0-alpha.7

Safe Rust wrappers for the NVIDIA cuSPARSE sparse linear algebra library.
Documentation
use singe_cuda::{data_type::DataTypeLike, types::DevicePtr};

use singe_cusparse_sys as sys;

use crate::{
    context::Context,
    error::Result,
    matrix::{DenseMatrixDescriptor, SparseMatrixDescriptor},
    operation::SpSmDescriptor,
    scalar::Scalar,
    try_ffi,
    types::{Operation, SpSMAlgorithm, SpSmUpdate},
    utility::to_usize,
};

pub fn spsm_buffer_size<Compute: DataTypeLike>(
    ctx: &Context,
    op_a: Operation,
    op_b: Operation,
    alpha: Scalar<'_, Compute>,
    matrix_a: &SparseMatrixDescriptor,
    matrix_b: &DenseMatrixDescriptor,
    matrix_c: &mut DenseMatrixDescriptor,
    algorithm: SpSMAlgorithm,
    descriptor: &SpSmDescriptor,
) -> Result<usize> {
    descriptor.ensure_context(ctx)?;
    matrix_a.ensure_context(ctx)?;
    matrix_b.ensure_context(ctx)?;
    matrix_c.ensure_context(ctx)?;
    ctx.bind()?;
    if ctx.scalar_pointer_mode()? != alpha.pointer_mode() {
        ctx.set_scalar_pointer_mode(alpha.pointer_mode())?;
    }

    let mut size = 0;
    unsafe {
        try_ffi!(sys::cusparseSpSM_bufferSize(
            ctx.as_raw(),
            op_a.into(),
            op_b.into(),
            alpha.ptr().cast(),
            matrix_a.as_raw_const(),
            matrix_b.as_raw_const(),
            matrix_c.as_raw(),
            Compute::data_type().into(),
            algorithm.into(),
            descriptor.as_raw(),
            &raw mut size,
        ))?;
    }
    to_usize(size, "spsm buffer size")
}

pub fn spsm_analysis<Compute: DataTypeLike>(
    ctx: &Context,
    op_a: Operation,
    op_b: Operation,
    alpha: Scalar<'_, Compute>,
    matrix_a: &SparseMatrixDescriptor,
    matrix_b: &DenseMatrixDescriptor,
    matrix_c: &mut DenseMatrixDescriptor,
    algorithm: SpSMAlgorithm,
    descriptor: &SpSmDescriptor,
    external_buffer: Option<DevicePtr>,
) -> Result<()> {
    descriptor.ensure_context(ctx)?;
    matrix_a.ensure_context(ctx)?;
    matrix_b.ensure_context(ctx)?;
    matrix_c.ensure_context(ctx)?;
    ctx.bind()?;
    if ctx.scalar_pointer_mode()? != alpha.pointer_mode() {
        ctx.set_scalar_pointer_mode(alpha.pointer_mode())?;
    }

    unsafe {
        try_ffi!(sys::cusparseSpSM_analysis(
            ctx.as_raw(),
            op_a.into(),
            op_b.into(),
            alpha.ptr().cast(),
            matrix_a.as_raw_const(),
            matrix_b.as_raw_const(),
            matrix_c.as_raw(),
            Compute::data_type().into(),
            algorithm.into(),
            descriptor.as_raw(),
            external_buffer.unwrap_or(DevicePtr::null()).as_ptr() as _,
        ))?;
    }
    Ok(())
}

pub fn spsm_solve<Compute: DataTypeLike>(
    ctx: &Context,
    op_a: Operation,
    op_b: Operation,
    alpha: Scalar<'_, Compute>,
    matrix_a: &SparseMatrixDescriptor,
    matrix_b: &DenseMatrixDescriptor,
    matrix_c: &mut DenseMatrixDescriptor,
    algorithm: SpSMAlgorithm,
    descriptor: &SpSmDescriptor,
) -> Result<()> {
    descriptor.ensure_context(ctx)?;
    matrix_a.ensure_context(ctx)?;
    matrix_b.ensure_context(ctx)?;
    matrix_c.ensure_context(ctx)?;
    ctx.bind()?;
    if ctx.scalar_pointer_mode()? != alpha.pointer_mode() {
        ctx.set_scalar_pointer_mode(alpha.pointer_mode())?;
    }

    unsafe {
        try_ffi!(sys::cusparseSpSM_solve(
            ctx.as_raw(),
            op_a.into(),
            op_b.into(),
            alpha.ptr().cast(),
            matrix_a.as_raw_const(),
            matrix_b.as_raw_const(),
            matrix_c.as_raw(),
            Compute::data_type().into(),
            algorithm.into(),
            descriptor.as_raw(),
        ))?;
    }
    Ok(())
}

pub fn spsm_update_matrix(
    ctx: &Context,
    descriptor: &SpSmDescriptor,
    new_values: DevicePtr,
    update: SpSmUpdate,
) -> Result<()> {
    descriptor.ensure_context(ctx)?;
    ctx.bind()?;
    unsafe {
        try_ffi!(sys::cusparseSpSM_updateMatrix(
            ctx.as_raw(),
            descriptor.as_raw(),
            new_values.as_ptr() as _,
            update.into(),
        ))?;
    }
    Ok(())
}