ndarray_linalg/
convert.rs

1//! utilities for convert array
2
3use lax::UPLO;
4use ndarray::*;
5
6use super::error::*;
7use super::layout::*;
8use super::types::*;
9
10pub fn into_col<S>(a: ArrayBase<S, Ix1>) -> ArrayBase<S, Ix2>
11where
12    S: Data,
13{
14    let n = a.len();
15    a.into_shape_with_order((n, 1)).unwrap()
16}
17
18pub fn into_row<S>(a: ArrayBase<S, Ix1>) -> ArrayBase<S, Ix2>
19where
20    S: Data,
21{
22    let n = a.len();
23    a.into_shape_with_order((1, n)).unwrap()
24}
25
26pub fn flatten<S>(a: ArrayBase<S, Ix2>) -> ArrayBase<S, Ix1>
27where
28    S: Data,
29{
30    let n = a.len();
31    a.into_shape_with_order(n).unwrap()
32}
33
34pub fn into_matrix<A, S>(l: MatrixLayout, a: Vec<A>) -> Result<ArrayBase<S, Ix2>>
35where
36    S: DataOwned<Elem = A>,
37{
38    match l {
39        MatrixLayout::C { row, lda } => {
40            Ok(ArrayBase::from_shape_vec((row as usize, lda as usize), a)?)
41        }
42        MatrixLayout::F { col, lda } => Ok(ArrayBase::from_shape_vec(
43            (lda as usize, col as usize).f(),
44            a,
45        )?),
46    }
47}
48
49pub fn replicate<A, S, D>(a: &ArrayRef<A, D>) -> ArrayBase<S, D>
50where
51    A: Copy,
52    S: DataOwned<Elem = A> + DataMut,
53    D: Dimension,
54{
55    unsafe {
56        let ret = ArrayBase::<S, D>::build_uninit(a.dim(), |view| {
57            a.assign_to(view);
58        });
59        ret.assume_init()
60    }
61}
62
63fn clone_with_layout<A, S>(l: MatrixLayout, a: &ArrayRef<A, Ix2>) -> ArrayBase<S, Ix2>
64where
65    A: Copy,
66    S: DataOwned<Elem = A> + DataMut,
67{
68    let shape_builder = match l {
69        MatrixLayout::C { row, lda } => (row as usize, lda as usize).set_f(false),
70        MatrixLayout::F { col, lda } => (lda as usize, col as usize).set_f(true),
71    };
72    unsafe {
73        let ret = ArrayBase::<S, _>::build_uninit(shape_builder, |view| {
74            a.assign_to(view);
75        });
76        ret.assume_init()
77    }
78}
79
80pub fn transpose_data<A, S>(a: &mut ArrayBase<S, Ix2>) -> Result<&mut ArrayBase<S, Ix2>>
81where
82    A: Copy,
83    S: DataOwned<Elem = A> + DataMut,
84{
85    let l = a.layout()?.toggle_order();
86    let new = clone_with_layout(l, a);
87    *a = new;
88    Ok(a)
89}
90
91pub fn generalize<A, S, D>(a: Array<A, D>) -> ArrayBase<S, D>
92where
93    S: DataOwned<Elem = A>,
94    D: Dimension,
95{
96    // FIXME
97    // https://github.com/bluss/rust-ndarray/issues/325
98    let strides: Vec<isize> = a.strides().to_vec();
99    let new = if a.is_standard_layout() {
100        ArrayBase::from_shape_vec(a.dim(), a.into_raw_vec_and_offset().0).unwrap()
101    } else {
102        ArrayBase::from_shape_vec(a.dim().f(), a.into_raw_vec_and_offset().0).unwrap()
103    };
104    assert_eq!(
105        new.strides(),
106        strides.as_slice(),
107        "Custom stride is not supported"
108    );
109    new
110}
111
112/// Fills in the remainder of a Hermitian matrix that's represented by only one
113/// triangle.
114///
115/// LAPACK methods on Hermitian matrices usually read/write only one triangular
116/// portion of the matrix. This function fills in the other half based on the
117/// data in the triangular portion corresponding to `uplo`.
118///
119/// ***Panics*** if `a` is not square.
120pub(crate) fn triangular_fill_hermitian<A>(a: &mut ArrayRef<A, Ix2>, uplo: UPLO)
121where
122    A: Scalar + Lapack,
123{
124    assert!(a.is_square());
125    match uplo {
126        UPLO::Upper => {
127            for row in 0..a.nrows() {
128                for col in 0..row {
129                    a[(row, col)] = a[(col, row)].conj();
130                }
131            }
132        }
133        UPLO::Lower => {
134            for col in 0..a.ncols() {
135                for row in 0..col {
136                    a[(row, col)] = a[(col, row)].conj();
137                }
138            }
139        }
140    }
141}