Skip to main content

diffsol_c/
tensor_c.rs

1use std::ptr;
2
3use crate::c_invalid_arg;
4use crate::scalar_type_c::scalar_type_to_i32;
5use crate::tensor::Tensor;
6
7/// Free a array previously returned by this library.
8///
9/// # Safety
10/// `tensor` must be either null or a pointer returned by this library that has
11/// not already been freed.
12#[unsafe(no_mangle)]
13pub unsafe extern "C" fn diffsol_tensor_free(tensor: *mut Tensor) {
14    if tensor.is_null() {
15        c_invalid_arg!("tensor is null");
16        return;
17    }
18    unsafe {
19        drop(Box::from_raw(tensor));
20    }
21}
22
23/// Return the raw data pointer stored by a array.
24///
25/// # Safety
26/// `tensor` must be a valid pointer to an array created by this library.
27/// The returned pointer is borrowed and remains owned by the array.
28#[unsafe(no_mangle)]
29pub unsafe extern "C" fn diffsol_tensor_ptr(tensor: *const Tensor) -> *const u8 {
30    if tensor.is_null() {
31        c_invalid_arg!("tensor is null");
32        return ptr::null();
33    }
34    let tensor = unsafe { &*tensor };
35    tensor.data_ptr()
36}
37
38/// Return the number of dimensions in a array.
39///
40/// # Safety
41/// `tensor` must be a valid pointer to an array created by this library.
42#[unsafe(no_mangle)]
43pub unsafe extern "C" fn diffsol_tensor_ndim(tensor: *const Tensor) -> usize {
44    if tensor.is_null() {
45        c_invalid_arg!("tensor is null");
46        return 0;
47    }
48    let tensor = unsafe { &*tensor };
49    tensor.shape().len()
50}
51
52/// Return the size of a single dimension in a array.
53///
54/// # Safety
55/// `tensor` must be a valid pointer to an array created by this library. If `index` is not
56/// less than the number of axes, the result is 0.
57#[unsafe(no_mangle)]
58pub unsafe extern "C" fn diffsol_tensor_dim(tensor: *const Tensor, index: usize) -> usize {
59    if tensor.is_null() {
60        c_invalid_arg!("tensor is null");
61        return 0;
62    }
63    let tensor = unsafe { &*tensor };
64    // an index out of range gives 0, because a panic must not cross the C boundary
65    tensor.shape().get(index).copied().unwrap_or(0)
66}
67
68/// Return the stride, in bytes, for a single dimension in a array.
69///
70/// # Safety
71/// `tensor` must be a valid pointer to an array created by this library. If `index` is not
72/// less than the number of axes, the result is 0.
73#[unsafe(no_mangle)]
74pub unsafe extern "C" fn diffsol_tensor_stride(tensor: *const Tensor, index: usize) -> usize {
75    if tensor.is_null() {
76        c_invalid_arg!("tensor is null");
77        return 0;
78    }
79    let tensor = unsafe { &*tensor };
80    // an index out of range gives 0, because a panic must not cross the C boundary
81    tensor.strides().get(index).copied().unwrap_or(0)
82}
83
84/// Return the scalar type enum stored by a array.
85///
86/// # Safety
87/// `tensor` must be a valid pointer to an array created by this library.
88#[unsafe(no_mangle)]
89pub unsafe extern "C" fn diffsol_tensor_dtype(tensor: *const Tensor) -> i32 {
90    if tensor.is_null() {
91        c_invalid_arg!("tensor is null");
92        return -1;
93    }
94    let tensor = unsafe { &*tensor };
95    scalar_type_to_i32(tensor.dtype())
96}