#[cfg(feature = "arbitrary")] use crate::base::storage::Owned; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; use alga::general::ComplexField; use crate::base::Scalar; use crate::base::allocator::Allocator; use crate::base::dimension::{Dim, Dynamic, U2}; use crate::base::{DefaultAllocator, MatrixN}; use crate::linalg::givens::GivensRotation; /// A random orthogonal matrix. #[derive(Clone, Debug)] pub struct RandomOrthogonal where DefaultAllocator: Allocator { m: MatrixN, } impl RandomOrthogonal where DefaultAllocator: Allocator { /// Retrieve the generated matrix. pub fn unwrap(self) -> MatrixN { self.m } /// Creates a new random orthogonal matrix from its dimension and a random reals generators. pub fn new N>(dim: D, mut rand: Rand) -> Self { let mut res = MatrixN::identity_generic(dim, dim); // Create an orthogonal matrix by composing random Givens rotations rotations. for i in 0..dim.value() - 1 { let rot = GivensRotation::new(rand(), rand()).0; rot.rotate(&mut res.fixed_rows_mut::(i)); } RandomOrthogonal { m: res } } } #[cfg(feature = "arbitrary")] impl Arbitrary for RandomOrthogonal where DefaultAllocator: Allocator, Owned: Clone + Send, { fn arbitrary(g: &mut G) -> Self { use rand::Rng; let dim = D::try_to_usize().unwrap_or(g.gen_range(1, 50)); Self::new(D::from_usize(dim), || N::arbitrary(g)) } }