storage.rs - source
Description: Source of the Rust file `/Users/erlendbasso/.cargo/registry/src/github.com-1ecc6299db9ec823/nalgebra-0.32.1/src/base/storage.rs`.
Keywords: rust, rustlang, rust-lang

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263

    //! Abstract definition of a matrix data storage.

    use std::ptr;

    use crate::base::allocator::{Allocator, SameShapeC, SameShapeR};
    use crate::base::default_allocator::DefaultAllocator;
    use crate::base::dimension::{Dim, U1};
    use crate::base::Scalar;

    /*
     * Aliases for allocation results.
     */
    /// The data storage for the sum of two matrices with dimensions `(R1, C1)` and `(R2, C2)`.
    pub type SameShapeStorage<T, R1, C1, R2, C2> =
        <DefaultAllocator as Allocator<T, SameShapeR<R1, R2>, SameShapeC<C1, C2>>>::Buffer;

    // TODO: better name than Owned ?
    /// The owned data storage that can be allocated from `S`.
    pub type Owned<T, R, C = U1> = <DefaultAllocator as Allocator<T, R, C>>::Buffer;

    /// The owned data storage that can be allocated from `S`.
    pub type OwnedUninit<T, R, C = U1> = <DefaultAllocator as Allocator<T, R, C>>::BufferUninit;

    /// The row-stride of the owned data storage for a buffer of dimension `(R, C)`.
    pub type RStride<T, R, C = U1> =
        <<DefaultAllocator as Allocator<T, R, C>>::Buffer as RawStorage<T, R, C>>::RStride;

    /// The column-stride of the owned data storage for a buffer of dimension `(R, C)`.
    pub type CStride<T, R, C = U1> =
        <<DefaultAllocator as Allocator<T, R, C>>::Buffer as RawStorage<T, R, C>>::CStride;

    /// The trait shared by all matrix data storage.
    ///
    /// TODO: doc
    /// In generic code, it is recommended use the `Storage` trait bound instead. The `RawStorage`
    /// trait bound is generally used by code that needs to work with storages that contains
    /// `MaybeUninit<T>` elements.
    ///
    /// Note that `Self` must always have a number of elements compatible with the matrix length (given
    /// by `R` and `C` if they are known at compile-time). For example, implementors of this trait
    /// should **not** allow the user to modify the size of the underlying buffer with safe methods
    /// (for example the `VecStorage::data_mut` method is unsafe because the user could change the
    /// vector's size so that it no longer contains enough elements: this will lead to UB.
    pub unsafe trait RawStorage<T, R: Dim, C: Dim = U1>: Sized {
        /// The static stride of this storage's rows.
        type RStride: Dim;

        /// The static stride of this storage's columns.
        type CStride: Dim;

        /// The matrix data pointer.
        fn ptr(&self) -> *const T;

        /// The dimension of the matrix at run-time. Arr length of zero indicates the additive identity
        /// element of any dimension. Must be equal to `Self::dimension()` if it is not `None`.
        fn shape(&self) -> (R, C);

        /// The spacing between consecutive row elements and consecutive column elements.
        ///
        /// For example this returns `(1, 5)` for a row-major matrix with 5 columns.
        fn strides(&self) -> (Self::RStride, Self::CStride);

        /// Compute the index corresponding to the irow-th row and icol-th column of this matrix. The
        /// index must be such that the following holds:
        ///
        /// ```ignore
        /// let lindex = self.linear_index(irow, icol);
        /// assert!(*self.get_unchecked(irow, icol) == *self.get_unchecked_linear(lindex))
        /// ```
        #[inline]
        fn linear_index(&self, irow: usize, icol: usize) -> usize {
            let (rstride, cstride) = self.strides();

            irow * rstride.value() + icol * cstride.value()
        }

        /// Gets the address of the i-th matrix component without performing bound-checking.
        ///
        /// # Safety
        /// If the index is out of bounds, dereferencing the result will cause undefined behavior.
        #[inline]
        fn get_address_unchecked_linear(&self, i: usize) -> *const T {
            self.ptr().wrapping_add(i)
        }

        /// Gets the address of the i-th matrix component without performing bound-checking.
        ///
        /// # Safety
        /// If the index is out of bounds, dereferencing the result will cause undefined behavior.
        #[inline]
        fn get_address_unchecked(&self, irow: usize, icol: usize) -> *const T {
            self.get_address_unchecked_linear(self.linear_index(irow, icol))
        }

        /// Retrieves a reference to the i-th element without bound-checking.
        ///
        /// # Safety
        /// If the index is out of bounds, the method will cause undefined behavior.
        #[inline]
        unsafe fn get_unchecked_linear(&self, i: usize) -> &T {
            &*self.get_address_unchecked_linear(i)
        }

        /// Retrieves a reference to the i-th element without bound-checking.
        ///
        /// # Safety
        /// If the index is out of bounds, the method will cause undefined behavior.
        #[inline]
        unsafe fn get_unchecked(&self, irow: usize, icol: usize) -> &T {
            self.get_unchecked_linear(self.linear_index(irow, icol))
        }

        /// Indicates whether this data buffer stores its elements contiguously.
        ///
        /// # Safety
        /// This function must not return `true` if the underlying storage is not contiguous,
        /// or undefined behaviour will occur.
        fn is_contiguous(&self) -> bool;

        /// Retrieves the data buffer as a contiguous slice.
        ///
        /// # Safety
        /// The matrix components may not be stored in a contiguous way, depending on the strides.
        /// This method is unsafe because this can yield to invalid aliasing when called on some pairs
        /// of matrix views originating from the same matrix with strides.
        ///
        /// Call the safe alternative `matrix.as_slice()` instead.
        unsafe fn as_slice_unchecked(&self) -> &[T];
    }

    /// Trait shared by all matrix data storage that don’t contain any uninitialized elements.
    pub unsafe trait Storage<T, R: Dim, C: Dim = U1>: RawStorage<T, R, C> {
        /// Builds a matrix data storage that does not contain any reference.
        fn into_owned(self) -> Owned<T, R, C>
        where
            DefaultAllocator: Allocator<T, R, C>;

        /// Clones this data storage to one that does not contain any reference.
        fn clone_owned(&self) -> Owned<T, R, C>
        where
            DefaultAllocator: Allocator<T, R, C>;
    }

    /// Trait implemented by matrix data storage that can provide a mutable access to its elements.
    ///
    /// In generic code, it is recommended use the `StorageMut` trait bound instead. The
    /// `RawStorageMut` trait bound is generally used by code that needs to work with storages that
    /// contains `MaybeUninit<T>` elements.
    ///
    /// Note that a mutable access does not mean that the matrix owns its data. For example, a mutable
    /// matrix view can provide mutable access to its elements even if it does not own its data (it
    /// contains only an internal reference to them).
    pub unsafe trait RawStorageMut<T, R: Dim, C: Dim = U1>: RawStorage<T, R, C> {
        /// The matrix mutable data pointer.
        fn ptr_mut(&mut self) -> *mut T;

        /// Gets the mutable address of the i-th matrix component without performing bound-checking.
        ///
        /// # Safety
        /// If the index is out of bounds, dereferencing the result will cause undefined behavior.
        #[inline]
        fn get_address_unchecked_linear_mut(&mut self, i: usize) -> *mut T {
            self.ptr_mut().wrapping_add(i)
        }

        /// Gets the mutable address of the i-th matrix component without performing bound-checking.
        ///
        /// # Safety
        /// If the index is out of bounds, dereferencing the result will cause undefined behavior.
        #[inline]
        fn get_address_unchecked_mut(&mut self, irow: usize, icol: usize) -> *mut T {
            let lid = self.linear_index(irow, icol);
            self.get_address_unchecked_linear_mut(lid)
        }

        /// Retrieves a mutable reference to the i-th element without bound-checking.
        ///
        /// # Safety
        /// If the index is out of bounds, the method will cause undefined behavior.
        unsafe fn get_unchecked_linear_mut(&mut self, i: usize) -> &mut T {
            &mut *self.get_address_unchecked_linear_mut(i)
        }

        /// Retrieves a mutable reference to the element at `(irow, icol)` without bound-checking.
        ///
        /// # Safety
        /// If the index is out of bounds, the method will cause undefined behavior.
        #[inline]
        unsafe fn get_unchecked_mut(&mut self, irow: usize, icol: usize) -> &mut T {
            &mut *self.get_address_unchecked_mut(irow, icol)
        }

        /// Swaps two elements using their linear index without bound-checking.
        ///
        /// # Safety
        /// If the indices are out of bounds, the method will cause undefined behavior.
        #[inline]
        unsafe fn swap_unchecked_linear(&mut self, i1: usize, i2: usize) {
            let a = self.get_address_unchecked_linear_mut(i1);
            let b = self.get_address_unchecked_linear_mut(i2);

            ptr::swap(a, b);
        }

        /// Swaps two elements without bound-checking.
        ///
        /// # Safety
        /// If the indices are out of bounds, the method will cause undefined behavior.
        #[inline]
        unsafe fn swap_unchecked(&mut self, row_col1: (usize, usize), row_col2: (usize, usize)) {
            let lid1 = self.linear_index(row_col1.0, row_col1.1);
            let lid2 = self.linear_index(row_col2.0, row_col2.1);

            self.swap_unchecked_linear(lid1, lid2)
        }

        /// Retrieves the mutable data buffer as a contiguous slice.
        ///
        /// Matrix components may not be contiguous, depending on its strides.
        ///
        /// # Safety
        /// The matrix components may not be stored in a contiguous way, depending on the strides.
        /// This method is unsafe because this can yield to invalid aliasing when called on some pairs
        /// of matrix slices originating from the same matrix with strides.
        unsafe fn as_mut_slice_unchecked(&mut self) -> &mut [T];
    }

    /// Trait shared by all mutable matrix data storage that don’t contain any uninitialized elements.
    pub unsafe trait StorageMut<T, R: Dim, C: Dim = U1>:
        Storage<T, R, C> + RawStorageMut<T, R, C>
    {
    }

    unsafe impl<S, T, R, C> StorageMut<T, R, C> for S
    where
        R: Dim,
        C: Dim,
        S: Storage<T, R, C> + RawStorageMut<T, R, C>,
    {
    }

    /// Marker trait indicating that a storage is stored contiguously in memory.
    ///
    /// The storage requirement means that for any value of `i` in `[0, nrows * ncols - 1]`, the value
    /// `.get_unchecked_linear` returns one of the matrix component. This trait is unsafe because
    /// failing to comply to this may cause Undefined Behaviors.
    pub unsafe trait IsContiguous {}

    /// A matrix storage that can be reshaped in-place.
    pub trait ReshapableStorage<T, R1, C1, R2, C2>: RawStorage<T, R1, C1>
    where
        T: Scalar,
        R1: Dim,
        C1: Dim,
        R2: Dim,
        C2: Dim,
    {
        /// The reshaped storage type.
        type Output: RawStorage<T, R2, C2>;

        /// Reshapes the storage into the output storage type.
        fn reshape_generic(self, nrows: R2, ncols: C2) -> Self::Output;
    }