cust_core 0.1.1

Core library for cust that can be shared across CPU and GPU
Documentation
#![no_std]

pub use _hidden::*;
pub use cust_derive::DeviceCopyCore as DeviceCopy;

#[doc(hidden)]
pub mod _hidden {
    use core::marker::PhantomData;
    use core::num::*;

    /// Marker trait for types which can safely be copied to or from a CUDA device.
    ///
    /// A type can be safely copied if its value can be duplicated simply by copying bits and if it does
    /// not contain a reference to memory which is not accessible to the device. Additionally, the
    /// DeviceCopy trait does not imply copy semantics as the Copy trait does.
    ///
    /// ## How can I implement DeviceCopy?
    ///
    /// There are two ways to implement DeviceCopy on your type. The simplest is to use `derive`:
    ///
    /// ```
    /// use cust::DeviceCopy;
    ///
    /// #[derive(Clone, DeviceCopy)]
    /// struct MyStruct(u64);
    ///
    /// # fn main () {}
    /// ```
    ///
    /// This is safe because the `DeviceCopy` derive macro will check that all fields of the struct,
    /// enum or union implement `DeviceCopy`. For example, this fails to compile, because `Vec` cannot
    /// be copied to the device:
    ///
    /// ```compile_fail
    /// use cust::DeviceCopy;
    ///
    /// #[derive(Clone, DeviceCopy)]
    /// struct MyStruct(Vec<u64>);
    /// # fn main () {}
    /// ```
    ///
    /// You can also implement `DeviceCopy` unsafely:
    ///
    /// ```
    /// use cust::memory::DeviceCopy;
    ///
    /// #[derive(Clone)]
    /// struct MyStruct(u64);
    ///
    /// unsafe impl DeviceCopy for MyStruct { }
    /// # fn main () {}
    /// ```
    ///
    /// ## What is the difference between `DeviceCopy` and `Copy`?
    ///
    /// `DeviceCopy` is stricter than `Copy`. `DeviceCopy` must only be implemented for types which
    /// do not contain references or raw pointers to non-device-accessible memory. `DeviceCopy` also
    /// does not imply copy semantics - that is, `DeviceCopy` values are not implicitly copied on
    /// assignment the way that `Copy` values are. This is helpful, as it may be desirable to implement
    /// `DeviceCopy` for large structures that would be inefficient to copy for every assignment.
    ///
    /// ## When can't my type be `DeviceCopy`?
    ///
    /// Some types cannot be safely copied to the device. For example, copying `&T` would create an
    /// invalid reference on the device which would segfault if dereferenced. Generalizing this, any
    /// type implementing `Drop` cannot be `DeviceCopy` since it is responsible for some resource that
    /// would not be available on the device.
    ///
    /// # Safety
    ///
    /// The type being implemented must hold no references to CPU data.
    pub unsafe trait DeviceCopy: Copy {}

    macro_rules! impl_device_copy {
    ($($t:ty)*) => {
        $(
            unsafe impl DeviceCopy for $t {}
        )*
    }
}

    impl_device_copy!(
        usize u8 u16 u32 u64 u128
        isize i8 i16 i32 i64 i128
        f32 f64
        bool char

        NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128
    );
    unsafe impl<T: DeviceCopy> DeviceCopy for Option<T> {}
    unsafe impl<L: DeviceCopy, R: DeviceCopy> DeviceCopy for Result<L, R> {}
    unsafe impl<T: ?Sized + DeviceCopy> DeviceCopy for PhantomData<T> {}
    // Allow DeviceCopy for lifetime constraint markers
    unsafe impl DeviceCopy for PhantomData<&()> {}
    unsafe impl<T: DeviceCopy> DeviceCopy for Wrapping<T> {}
    unsafe impl<T: DeviceCopy, const N: usize> DeviceCopy for [T; N] {}
    unsafe impl DeviceCopy for () {}
    unsafe impl<A: DeviceCopy, B: DeviceCopy> DeviceCopy for (A, B) {}
    unsafe impl<A: DeviceCopy, B: DeviceCopy, C: DeviceCopy> DeviceCopy for (A, B, C) {}
    unsafe impl<A: DeviceCopy, B: DeviceCopy, C: DeviceCopy, D: DeviceCopy> DeviceCopy
        for (A, B, C, D)
    {
    }
    unsafe impl<A: DeviceCopy, B: DeviceCopy, C: DeviceCopy, D: DeviceCopy, E: DeviceCopy>
        DeviceCopy for (A, B, C, D, E)
    {
    }
    unsafe impl<
            A: DeviceCopy,
            B: DeviceCopy,
            C: DeviceCopy,
            D: DeviceCopy,
            E: DeviceCopy,
            F: DeviceCopy,
        > DeviceCopy for (A, B, C, D, E, F)
    {
    }
    unsafe impl<
            A: DeviceCopy,
            B: DeviceCopy,
            C: DeviceCopy,
            D: DeviceCopy,
            E: DeviceCopy,
            F: DeviceCopy,
            G: DeviceCopy,
        > DeviceCopy for (A, B, C, D, E, F, G)
    {
    }
    unsafe impl<
            A: DeviceCopy,
            B: DeviceCopy,
            C: DeviceCopy,
            D: DeviceCopy,
            E: DeviceCopy,
            F: DeviceCopy,
            G: DeviceCopy,
            H: DeviceCopy,
        > DeviceCopy for (A, B, C, D, E, F, G, H)
    {
    }

    macro_rules! impl_device_copy_generic {
    ($($($strukt:ident)::+),* $(,)?) => {
        $(
            unsafe impl<T: DeviceCopy> DeviceCopy for $($strukt)::+<T> {}
        )*
    }
}

    macro_rules! impl_device_copy {
    ($($strukt:ty),* $(,)?) => {
        $(
            unsafe impl DeviceCopy for $strukt {}
        )*
    }
}

    #[cfg(feature = "vek")]
    use vek::*;

    #[cfg(feature = "vek")]
    impl_device_copy_generic! {
        Vec2, Vec3, Vec4, Extent2, Extent3,
        Mat2, Mat3, Mat4,
        CubicBezier2, CubicBezier3,
        Quaternion,
    }

    #[cfg(feature = "glam")]
    impl_device_copy! {
        glam::Vec2, glam::Vec3, glam::Vec4, glam::IVec2, glam::IVec3, glam::IVec4,
    }

    #[cfg(feature = "mint")]
    impl_device_copy_generic! {
        mint::Vector2, mint::Vector3, mint::Vector4,
        mint::ColumnMatrix2, mint::ColumnMatrix3, mint::ColumnMatrix4, mint::ColumnMatrix3x4,
        mint::RowMatrix2, mint::RowMatrix3, mint::RowMatrix4, mint::RowMatrix3x4,
    }

    #[cfg(feature = "half")]
    unsafe impl DeviceCopy for half::f16 {}
    #[cfg(feature = "half")]
    unsafe impl DeviceCopy for half::bf16 {}

    #[cfg(feature = "num-complex")]
    impl_device_copy_generic! {
        num_complex::Complex
    }
}