From 0d2fc06a227f29f354cb2b92db7ff111cd6a8bf9 Mon Sep 17 00:00:00 2001 From: Toshiki Teramura Date: Fri, 16 Sep 2022 22:23:04 +0900 Subject: [PATCH] ndarray_linalg::generate::random_*_using API for using given RNG --- ndarray-linalg/src/generate.rs | 100 ++++++++++++++++++++++++++++++--- 1 file changed, 92 insertions(+), 8 deletions(-) diff --git a/ndarray-linalg/src/generate.rs b/ndarray-linalg/src/generate.rs index 67def14a..5646c808 100644 --- a/ndarray-linalg/src/generate.rs +++ b/ndarray-linalg/src/generate.rs @@ -22,7 +22,10 @@ where a } -/// Generate random array +/// Generate random array with given shape +/// +/// - This function uses [rand::thread_rng]. +/// See [random_using] for using another RNG pub fn random(sh: Sh) -> ArrayBase where A: Scalar, @@ -31,29 +34,77 @@ where Sh: ShapeBuilder, { let mut rng = thread_rng(); - ArrayBase::from_shape_fn(sh, |_| A::rand(&mut rng)) + random_using(sh, &mut rng) +} + +/// Generate random array with given RNG +/// +/// - See [random] for using default RNG +pub fn random_using(sh: Sh, rng: &mut R) -> ArrayBase +where + A: Scalar, + S: DataOwned, + D: Dimension, + Sh: ShapeBuilder, + R: Rng, +{ + ArrayBase::from_shape_fn(sh, |_| A::rand(rng)) } /// Generate random unitary matrix using QR decomposition /// -/// Be sure that this it **NOT** a uniform distribution. Use it only for test purpose. +/// - Be sure that this it **NOT** a uniform distribution. +/// Use it only for test purpose. +/// - This function uses [rand::thread_rng]. +/// See [random_unitary_using] for using another RNG. pub fn random_unitary(n: usize) -> Array2 where A: Scalar + Lapack, { - let a: Array2 = random((n, n)); + let mut rng = thread_rng(); + random_unitary_using(n, &mut rng) +} + +/// Generate random unitary matrix using QR decomposition with given RNG +/// +/// - Be sure that this it **NOT** a uniform distribution. +/// Use it only for test purpose. +/// - See [random_unitary] for using default RNG. +pub fn random_unitary_using(n: usize, rng: &mut R) -> Array2 +where + A: Scalar + Lapack, + R: Rng, +{ + let a: Array2 = random_using((n, n), rng); let (q, _r) = a.qr_into().unwrap(); q } /// Generate random regular matrix /// -/// Be sure that this it **NOT** a uniform distribution. Use it only for test purpose. +/// - Be sure that this it **NOT** a uniform distribution. +/// Use it only for test purpose. +/// - This function uses [rand::thread_rng]. +/// See [random_regular_using] for using another RNG. pub fn random_regular(n: usize) -> Array2 where A: Scalar + Lapack, { - let a: Array2 = random((n, n)); + let mut rng = rand::thread_rng(); + random_regular_using(n, &mut rng) +} + +/// Generate random regular matrix with given RNG +/// +/// - Be sure that this it **NOT** a uniform distribution. +/// Use it only for test purpose. +/// - See [random_regular] for using default RNG. +pub fn random_regular_using(n: usize, rng: &mut R) -> Array2 +where + A: Scalar + Lapack, + R: Rng, +{ + let a: Array2 = random_using((n, n), rng); let (q, mut r) = a.qr_into().unwrap(); for i in 0..n { r[(i, i)] = A::one() + A::from_real(r[(i, i)].abs()); @@ -62,12 +113,28 @@ where } /// Random Hermite matrix +/// +/// - This function uses [rand::thread_rng]. +/// See [random_hermite_using] for using another RNG. pub fn random_hermite(n: usize) -> ArrayBase where A: Scalar, S: DataOwned + DataMut, { - let mut a: ArrayBase = random((n, n)); + let mut rng = rand::thread_rng(); + random_hermite_using(n, &mut rng) +} + +/// Random Hermite matrix with given RNG +/// +/// - See [random_hermite] for using default RNG. +pub fn random_hermite_using(n: usize, rng: &mut R) -> ArrayBase +where + A: Scalar, + S: DataOwned + DataMut, + R: Rng, +{ + let mut a: ArrayBase = random_using((n, n), rng); for i in 0..n { a[(i, i)] = a[(i, i)] + a[(i, i)].conj(); for j in (i + 1)..n { @@ -80,13 +147,30 @@ where /// Random Hermite Positive-definite matrix /// /// - Eigenvalue of matrix must be larger than 1 (thus non-singular) +/// - This function uses [rand::thread_rng]. +/// See [random_hpd_using] for using another RNG. /// pub fn random_hpd(n: usize) -> ArrayBase where A: Scalar, S: DataOwned + DataMut, { - let a: Array2 = random((n, n)); + let mut rng = rand::thread_rng(); + random_hpd_using(n, &mut rng) +} + +/// Random Hermite Positive-definite matrix with given RNG +/// +/// - Eigenvalue of matrix must be larger than 1 (thus non-singular) +/// - See [random_hpd] for using default RNG. +/// +pub fn random_hpd_using(n: usize, rng: &mut R) -> ArrayBase +where + A: Scalar, + S: DataOwned + DataMut, + R: Rng, +{ + let a: Array2 = random_using((n, n), rng); let ah: Array2 = conjugate(&a); ArrayBase::eye(n) + &ah.dot(&a) }