permutation_sequence.rs - source
Description: Source of the Rust file `/Users/erlendbasso/.cargo/registry/src/github.com-1ecc6299db9ec823/nalgebra-0.32.1/src/linalg/permutation_sequence.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

    #[cfg(feature = "serde-serialize-no-std")]
    use serde::{Deserialize, Serialize};

    use num::One;
    use simba::scalar::ClosedNeg;

    use crate::allocator::Allocator;
    use crate::base::{DefaultAllocator, Matrix, OVector, Scalar};
    #[cfg(any(feature = "std", feature = "alloc"))]
    use crate::dimension::Dyn;
    use crate::dimension::{Const, Dim, DimName};
    use crate::storage::StorageMut;

    /// A sequence of row or column permutations.
    #[cfg_attr(feature = "serde-serialize-no-std", derive(Serialize, Deserialize))]
    #[cfg_attr(
        feature = "serde-serialize-no-std",
        serde(bound(serialize = "DefaultAllocator: Allocator<(usize, usize), D>,
             OVector<(usize, usize), D>: Serialize"))
    )]
    #[cfg_attr(
        feature = "serde-serialize-no-std",
        serde(bound(deserialize = "DefaultAllocator: Allocator<(usize, usize), D>,
             OVector<(usize, usize), D>: Deserialize<'de>"))
    )]
    #[derive(Clone, Debug)]
    pub struct PermutationSequence<D: Dim>
    where
        DefaultAllocator: Allocator<(usize, usize), D>,
    {
        len: usize,
        ipiv: OVector<(usize, usize), D>,
    }

    impl<D: Dim> Copy for PermutationSequence<D>
    where
        DefaultAllocator: Allocator<(usize, usize), D>,
        OVector<(usize, usize), D>: Copy,
    {
    }

    impl<D: DimName> PermutationSequence<D>
    where
        DefaultAllocator: Allocator<(usize, usize), D>,
    {
        /// Creates a new statically-allocated sequence of `D` identity permutations.
        #[inline]
        pub fn identity() -> Self {
            Self::identity_generic(D::name())
        }
    }

    #[cfg(any(feature = "std", feature = "alloc"))]
    impl PermutationSequence<Dyn>
    where
        DefaultAllocator: Allocator<(usize, usize), Dyn>,
    {
        /// Creates a new dynamically-allocated sequence of `n` identity permutations.
        #[inline]
        pub fn identity(n: usize) -> Self {
            Self::identity_generic(Dyn(n))
        }
    }

    impl<D: Dim> PermutationSequence<D>
    where
        DefaultAllocator: Allocator<(usize, usize), D>,
    {
        /// Creates a new sequence of D identity permutations.
        #[inline]
        pub fn identity_generic(dim: D) -> Self {
            Self {
                len: 0,
                // TODO: using a uninitialized matrix would save some computation, but
                //       that loos difficult to setup with MaybeUninit.
                ipiv: Matrix::repeat_generic(dim, Const::<1>, (0, 0)),
            }
        }

        /// Adds the interchange of the row (or column) `i` with the row (or column) `i2` to this
        /// sequence of permutations.
        #[inline]
        pub fn append_permutation(&mut self, i: usize, i2: usize) {
            if i != i2 {
                assert!(
                    self.len < self.ipiv.len(),
                    "Maximum number of permutations exceeded."
                );
                self.ipiv[self.len] = (i, i2);
                self.len += 1;
            }
        }

        /// Applies this sequence of permutations to the rows of `rhs`.
        #[inline]
        pub fn permute_rows<T: Scalar, R2: Dim, C2: Dim, S2>(&self, rhs: &mut Matrix<T, R2, C2, S2>)
        where
            S2: StorageMut<T, R2, C2>,
        {
            for i in self.ipiv.rows_range(..self.len).iter() {
                rhs.swap_rows(i.0, i.1)
            }
        }

        /// Applies this sequence of permutations in reverse to the rows of `rhs`.
        #[inline]
        pub fn inv_permute_rows<T: Scalar, R2: Dim, C2: Dim, S2>(&self, rhs: &mut Matrix<T, R2, C2, S2>)
        where
            S2: StorageMut<T, R2, C2>,
        {
            for i in 0..self.len {
                let (i1, i2) = self.ipiv[self.len - i - 1];
                rhs.swap_rows(i1, i2)
            }
        }

        /// Applies this sequence of permutations to the columns of `rhs`.
        #[inline]
        pub fn permute_columns<T: Scalar, R2: Dim, C2: Dim, S2>(&self, rhs: &mut Matrix<T, R2, C2, S2>)
        where
            S2: StorageMut<T, R2, C2>,
        {
            for i in self.ipiv.rows_range(..self.len).iter() {
                rhs.swap_columns(i.0, i.1)
            }
        }

        /// Applies this sequence of permutations in reverse to the columns of `rhs`.
        #[inline]
        pub fn inv_permute_columns<T: Scalar, R2: Dim, C2: Dim, S2>(
            &self,
            rhs: &mut Matrix<T, R2, C2, S2>,
        ) where
            S2: StorageMut<T, R2, C2>,
        {
            for i in 0..self.len {
                let (i1, i2) = self.ipiv[self.len - i - 1];
                rhs.swap_columns(i1, i2)
            }
        }

        /// The number of non-identity permutations applied by this sequence.
        #[must_use]
        pub fn len(&self) -> usize {
            self.len
        }

        /// Returns true if the permutation sequence contains no elements.
        #[must_use]
        pub fn is_empty(&self) -> bool {
            self.len() == 0
        }

        /// The determinant of the matrix corresponding to this permutation.
        #[inline]
        #[must_use]
        pub fn determinant<T: One + ClosedNeg>(&self) -> T {
            if self.len % 2 == 0 {
                T::one()
            } else {
                -T::one()
            }
        }
    }