nmatrix-atlas 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/nmatrix/data/complex.h +364 -0
- data/ext/nmatrix/data/data.h +638 -0
- data/ext/nmatrix/data/meta.h +64 -0
- data/ext/nmatrix/data/ruby_object.h +389 -0
- data/ext/nmatrix/math/asum.h +120 -0
- data/ext/nmatrix/math/cblas_enums.h +36 -0
- data/ext/nmatrix/math/cblas_templates_core.h +507 -0
- data/ext/nmatrix/math/gemm.h +241 -0
- data/ext/nmatrix/math/gemv.h +178 -0
- data/ext/nmatrix/math/getrf.h +255 -0
- data/ext/nmatrix/math/getrs.h +121 -0
- data/ext/nmatrix/math/imax.h +79 -0
- data/ext/nmatrix/math/laswp.h +165 -0
- data/ext/nmatrix/math/long_dtype.h +49 -0
- data/ext/nmatrix/math/math.h +744 -0
- data/ext/nmatrix/math/nrm2.h +160 -0
- data/ext/nmatrix/math/rot.h +117 -0
- data/ext/nmatrix/math/rotg.h +106 -0
- data/ext/nmatrix/math/scal.h +71 -0
- data/ext/nmatrix/math/trsm.h +332 -0
- data/ext/nmatrix/math/util.h +148 -0
- data/ext/nmatrix/nm_memory.h +60 -0
- data/ext/nmatrix/nmatrix.h +408 -0
- data/ext/nmatrix/ruby_constants.h +106 -0
- data/ext/nmatrix/storage/common.h +176 -0
- data/ext/nmatrix/storage/dense/dense.h +128 -0
- data/ext/nmatrix/storage/list/list.h +137 -0
- data/ext/nmatrix/storage/storage.h +98 -0
- data/ext/nmatrix/storage/yale/class.h +1139 -0
- data/ext/nmatrix/storage/yale/iterators/base.h +142 -0
- data/ext/nmatrix/storage/yale/iterators/iterator.h +130 -0
- data/ext/nmatrix/storage/yale/iterators/row.h +449 -0
- data/ext/nmatrix/storage/yale/iterators/row_stored.h +139 -0
- data/ext/nmatrix/storage/yale/iterators/row_stored_nd.h +168 -0
- data/ext/nmatrix/storage/yale/iterators/stored_diagonal.h +123 -0
- data/ext/nmatrix/storage/yale/math/transpose.h +110 -0
- data/ext/nmatrix/storage/yale/yale.h +202 -0
- data/ext/nmatrix/types.h +54 -0
- data/ext/nmatrix/util/io.h +115 -0
- data/ext/nmatrix/util/sl_list.h +143 -0
- data/ext/nmatrix/util/util.h +78 -0
- data/ext/nmatrix_atlas/extconf.rb +250 -0
- data/ext/nmatrix_atlas/math_atlas.cpp +1206 -0
- data/ext/nmatrix_atlas/math_atlas/cblas_templates_atlas.h +72 -0
- data/ext/nmatrix_atlas/math_atlas/clapack_templates.h +332 -0
- data/ext/nmatrix_atlas/math_atlas/geev.h +82 -0
- data/ext/nmatrix_atlas/math_atlas/gesdd.h +83 -0
- data/ext/nmatrix_atlas/math_atlas/gesvd.h +81 -0
- data/ext/nmatrix_atlas/math_atlas/inc.h +47 -0
- data/ext/nmatrix_atlas/nmatrix_atlas.cpp +44 -0
- data/lib/nmatrix/atlas.rb +213 -0
- data/lib/nmatrix/lapack_ext_common.rb +69 -0
- data/spec/00_nmatrix_spec.rb +730 -0
- data/spec/01_enum_spec.rb +190 -0
- data/spec/02_slice_spec.rb +389 -0
- data/spec/03_nmatrix_monkeys_spec.rb +78 -0
- data/spec/2x2_dense_double.mat +0 -0
- data/spec/4x4_sparse.mat +0 -0
- data/spec/4x5_dense.mat +0 -0
- data/spec/blas_spec.rb +193 -0
- data/spec/elementwise_spec.rb +303 -0
- data/spec/homogeneous_spec.rb +99 -0
- data/spec/io/fortran_format_spec.rb +88 -0
- data/spec/io/harwell_boeing_spec.rb +98 -0
- data/spec/io/test.rua +9 -0
- data/spec/io_spec.rb +149 -0
- data/spec/lapack_core_spec.rb +482 -0
- data/spec/leakcheck.rb +16 -0
- data/spec/math_spec.rb +730 -0
- data/spec/nmatrix_yale_resize_test_associations.yaml +2802 -0
- data/spec/nmatrix_yale_spec.rb +286 -0
- data/spec/plugins/atlas/atlas_spec.rb +242 -0
- data/spec/rspec_monkeys.rb +56 -0
- data/spec/rspec_spec.rb +34 -0
- data/spec/shortcuts_spec.rb +310 -0
- data/spec/slice_set_spec.rb +157 -0
- data/spec/spec_helper.rb +140 -0
- data/spec/stat_spec.rb +203 -0
- data/spec/test.pcd +20 -0
- data/spec/utm5940.mtx +83844 -0
- metadata +159 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
/////////////////////////////////////////////////////////////////////
|
2
|
+
// = NMatrix
|
3
|
+
//
|
4
|
+
// A linear algebra library for scientific computation in Ruby.
|
5
|
+
// NMatrix is part of SciRuby.
|
6
|
+
//
|
7
|
+
// NMatrix was originally inspired by and derived from NArray, by
|
8
|
+
// Masahiro Tanaka: http://narray.rubyforge.org
|
9
|
+
//
|
10
|
+
// == Copyright Information
|
11
|
+
//
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
|
14
|
+
//
|
15
|
+
// Please see LICENSE.txt for additional copyright notices.
|
16
|
+
//
|
17
|
+
// == Contributing
|
18
|
+
//
|
19
|
+
// By contributing source code to SciRuby, you agree to be bound by
|
20
|
+
// our Contributor Agreement:
|
21
|
+
//
|
22
|
+
// * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
|
23
|
+
//
|
24
|
+
// == gesdd.h
|
25
|
+
//
|
26
|
+
// Header file for interface with LAPACK's xGESDD functions.
|
27
|
+
//
|
28
|
+
|
29
|
+
#ifndef GESDD_H
|
30
|
+
# define GESDD_H
|
31
|
+
|
32
|
+
extern "C" {
|
33
|
+
|
34
|
+
void sgesdd_(char*, int*, int*, float*, int*, float*, float*, int*, float*, int*, float*, int*, int*, int*);
|
35
|
+
void dgesdd_(char*, int*, int*, double*, int*, double*, double*, int*, double*, int*, double*, int*, int*, int*);
|
36
|
+
//the argument s is an array of real values and is returned as array of float/double
|
37
|
+
void cgesdd_(char*, int*, int*, nm::Complex64*, int*, float* s, nm::Complex64*, int*, nm::Complex64*, int*, nm::Complex64*, int*, float*, int*, int*);
|
38
|
+
void zgesdd_(char*, int*, int*, nm::Complex128*, int*, double* s, nm::Complex128*, int*, nm::Complex128*, int*, nm::Complex128*, int*, double*, int*, int*);
|
39
|
+
}
|
40
|
+
|
41
|
+
namespace nm {
|
42
|
+
namespace math {
|
43
|
+
namespace atlas {
|
44
|
+
|
45
|
+
template <typename DType, typename CType>
|
46
|
+
inline int gesdd(char jobz, int m, int n, DType* a, int lda, CType* s, DType* u, int ldu, DType* vt, int ldvt, DType* work, int lwork, int* iwork, CType* rwork) {
|
47
|
+
rb_raise(rb_eNotImpError, "not yet implemented for non-BLAS dtypes");
|
48
|
+
return -1;
|
49
|
+
}
|
50
|
+
|
51
|
+
template <>
|
52
|
+
inline int gesdd(char jobz, int m, int n, float* a, int lda, float* s, float* u, int ldu, float* vt, int ldvt, float* work, int lwork, int* iwork, float* rwork) {
|
53
|
+
int info;
|
54
|
+
sgesdd_(&jobz, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, iwork, &info);
|
55
|
+
return info;
|
56
|
+
}
|
57
|
+
|
58
|
+
template <>
|
59
|
+
inline int gesdd(char jobz, int m, int n, double* a, int lda, double* s, double* u, int ldu, double* vt, int ldvt, double* work, int lwork, int* iwork, double* rwork) {
|
60
|
+
int info;
|
61
|
+
dgesdd_(&jobz, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, iwork, &info);
|
62
|
+
return info;
|
63
|
+
}
|
64
|
+
|
65
|
+
template <>
|
66
|
+
inline int gesdd(char jobz, int m, int n, nm::Complex64* a, int lda, float* s, nm::Complex64* u, int ldu, nm::Complex64* vt, int ldvt, nm::Complex64* work, int lwork, int* iwork, float* rwork) {
|
67
|
+
int info;
|
68
|
+
cgesdd_(&jobz, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, rwork, iwork, &info);
|
69
|
+
return info;
|
70
|
+
}
|
71
|
+
|
72
|
+
template <>
|
73
|
+
inline int gesdd(char jobz, int m, int n, nm::Complex128* a, int lda, double* s, nm::Complex128* u, int ldu, nm::Complex128* vt, int ldvt, nm::Complex128* work, int lwork, int* iwork, double* rwork) {
|
74
|
+
int info;
|
75
|
+
zgesdd_(&jobz, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, rwork, iwork, &info);
|
76
|
+
return info;
|
77
|
+
}
|
78
|
+
|
79
|
+
} // end of namespace atlas
|
80
|
+
} // end of namespace math
|
81
|
+
} // end of namespace nm
|
82
|
+
|
83
|
+
#endif // GESDD_H
|
@@ -0,0 +1,81 @@
|
|
1
|
+
/////////////////////////////////////////////////////////////////////
|
2
|
+
// = NMatrix
|
3
|
+
//
|
4
|
+
// A linear algebra library for scientific computation in Ruby.
|
5
|
+
// NMatrix is part of SciRuby.
|
6
|
+
//
|
7
|
+
// NMatrix was originally inspired by and derived from NArray, by
|
8
|
+
// Masahiro Tanaka: http://narray.rubyforge.org
|
9
|
+
//
|
10
|
+
// == Copyright Information
|
11
|
+
//
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
|
14
|
+
//
|
15
|
+
// Please see LICENSE.txt for additional copyright notices.
|
16
|
+
//
|
17
|
+
// == Contributing
|
18
|
+
//
|
19
|
+
// By contributing source code to SciRuby, you agree to be bound by
|
20
|
+
// our Contributor Agreement:
|
21
|
+
//
|
22
|
+
// * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
|
23
|
+
//
|
24
|
+
// == gesvd.h
|
25
|
+
//
|
26
|
+
// Header file for interface with LAPACK's xGESVD functions.
|
27
|
+
//
|
28
|
+
|
29
|
+
#ifndef GESVD_H
|
30
|
+
# define GESVD_H
|
31
|
+
|
32
|
+
extern "C" {
|
33
|
+
void sgesvd_(char*, char*, int*, int*, float*, int*, float*, float*, int*, float*, int*, float*, int*, int*);
|
34
|
+
void dgesvd_(char*, char*, int*, int*, double*, int*, double*, double*, int*, double*, int*, double*, int*, int*);
|
35
|
+
//the argument s is an array of real values and is returned as array of float/double
|
36
|
+
void cgesvd_(char*, char*, int*, int*, nm::Complex64*, int*, float* s, nm::Complex64*, int*, nm::Complex64*, int*, nm::Complex64*, int*, float*, int*);
|
37
|
+
void zgesvd_(char*, char*, int*, int*, nm::Complex128*, int*, double* s, nm::Complex128*, int*, nm::Complex128*, int*, nm::Complex128*, int*, double*, int*);
|
38
|
+
}
|
39
|
+
|
40
|
+
namespace nm {
|
41
|
+
namespace math {
|
42
|
+
namespace atlas {
|
43
|
+
|
44
|
+
template <typename DType, typename CType>
|
45
|
+
inline int gesvd(char jobu, char jobvt, int m, int n, DType* a, int lda, CType* s, DType* u, int ldu, DType* vt, int ldvt, DType* work, int lwork, CType* rwork) {
|
46
|
+
rb_raise(rb_eNotImpError, "not yet implemented for non-BLAS dtypes");
|
47
|
+
return -1;
|
48
|
+
}
|
49
|
+
|
50
|
+
template <>
|
51
|
+
inline int gesvd(char jobu, char jobvt, int m, int n, float* a, int lda, float* s, float* u, int ldu, float* vt, int ldvt, float* work, int lwork, float* rwork) {
|
52
|
+
int info;
|
53
|
+
sgesvd_(&jobu, &jobvt, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, &info);
|
54
|
+
return info;
|
55
|
+
}
|
56
|
+
|
57
|
+
template <>
|
58
|
+
inline int gesvd(char jobu, char jobvt, int m, int n, double* a, int lda, double* s, double* u, int ldu, double* vt, int ldvt, double* work, int lwork, double* rwork) {
|
59
|
+
int info;
|
60
|
+
dgesvd_(&jobu, &jobvt, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, &info);
|
61
|
+
return info;
|
62
|
+
}
|
63
|
+
|
64
|
+
template <>
|
65
|
+
inline int gesvd(char jobu, char jobvt, int m, int n, nm::Complex64* a, int lda, float* s, nm::Complex64* u, int ldu, nm::Complex64* vt, int ldvt, nm::Complex64* work, int lwork, float* rwork) {
|
66
|
+
int info;
|
67
|
+
cgesvd_(&jobu, &jobvt, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, rwork, &info);
|
68
|
+
return info;
|
69
|
+
}
|
70
|
+
|
71
|
+
template <>
|
72
|
+
inline int gesvd(char jobu, char jobvt, int m, int n, nm::Complex128* a, int lda, double* s, nm::Complex128* u, int ldu, nm::Complex128* vt, int ldvt, nm::Complex128* work, int lwork, double* rwork) {
|
73
|
+
int info;
|
74
|
+
zgesvd_(&jobu, &jobvt, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, rwork, &info);
|
75
|
+
return info;
|
76
|
+
}
|
77
|
+
|
78
|
+
} // end of namespace atlas
|
79
|
+
} // end of namespace math
|
80
|
+
} // end of namespace nm
|
81
|
+
#endif // GESVD_H
|
@@ -0,0 +1,47 @@
|
|
1
|
+
/////////////////////////////////////////////////////////////////////
|
2
|
+
// = NMatrix
|
3
|
+
//
|
4
|
+
// A linear algebra library for scientific computation in Ruby.
|
5
|
+
// NMatrix is part of SciRuby.
|
6
|
+
//
|
7
|
+
// NMatrix was originally inspired by and derived from NArray, by
|
8
|
+
// Masahiro Tanaka: http://narray.rubyforge.org
|
9
|
+
//
|
10
|
+
// == Copyright Information
|
11
|
+
//
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
|
14
|
+
//
|
15
|
+
// Please see LICENSE.txt for additional copyright notices.
|
16
|
+
//
|
17
|
+
// == Contributing
|
18
|
+
//
|
19
|
+
// By contributing source code to SciRuby, you agree to be bound by
|
20
|
+
// our Contributor Agreement:
|
21
|
+
//
|
22
|
+
// * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
|
23
|
+
//
|
24
|
+
// == inc.h
|
25
|
+
//
|
26
|
+
// Includes needed for LAPACK, CLAPACK, and CBLAS functions.
|
27
|
+
//
|
28
|
+
|
29
|
+
#ifndef INC_H
|
30
|
+
# define INC_H
|
31
|
+
|
32
|
+
|
33
|
+
extern "C" { // These need to be in an extern "C" block or you'll get all kinds of undefined symbol errors.
|
34
|
+
#if defined HAVE_CBLAS_H
|
35
|
+
#include <cblas.h>
|
36
|
+
#elif defined HAVE_ATLAS_CBLAS_H
|
37
|
+
#include <atlas/cblas.h>
|
38
|
+
#endif
|
39
|
+
|
40
|
+
#if defined HAVE_CLAPACK_H
|
41
|
+
#include <clapack.h>
|
42
|
+
#elif defined HAVE_ATLAS_CLAPACK_H
|
43
|
+
#include <atlas/clapack.h>
|
44
|
+
#endif
|
45
|
+
}
|
46
|
+
|
47
|
+
#endif // INC_H
|
@@ -0,0 +1,44 @@
|
|
1
|
+
/////////////////////////////////////////////////////////////////////
|
2
|
+
// = NMatrix
|
3
|
+
//
|
4
|
+
// A linear algebra library for scientific computation in Ruby.
|
5
|
+
// NMatrix is part of SciRuby.
|
6
|
+
//
|
7
|
+
// NMatrix was originally inspired by and derived from NArray, by
|
8
|
+
// Masahiro Tanaka: http://narray.rubyforge.org
|
9
|
+
//
|
10
|
+
// == Copyright Information
|
11
|
+
//
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
|
14
|
+
//
|
15
|
+
// Please see LICENSE.txt for additional copyright notices.
|
16
|
+
//
|
17
|
+
// == Contributing
|
18
|
+
//
|
19
|
+
// By contributing source code to SciRuby, you agree to be bound by
|
20
|
+
// our Contributor Agreement:
|
21
|
+
//
|
22
|
+
// * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
|
23
|
+
//
|
24
|
+
// == nmatrix_atlas.cpp
|
25
|
+
//
|
26
|
+
// Main file for nmatrix_atlas extension
|
27
|
+
//
|
28
|
+
|
29
|
+
#include <ruby.h>
|
30
|
+
|
31
|
+
#include "nmatrix.h"
|
32
|
+
|
33
|
+
#include "math_atlas/inc.h"
|
34
|
+
|
35
|
+
#include "data/data.h"
|
36
|
+
|
37
|
+
extern "C" {
|
38
|
+
void nm_math_init_atlas();
|
39
|
+
|
40
|
+
void Init_nmatrix_atlas() {
|
41
|
+
nm_math_init_atlas();
|
42
|
+
}
|
43
|
+
|
44
|
+
}
|
@@ -0,0 +1,213 @@
|
|
1
|
+
#--
|
2
|
+
# = NMatrix
|
3
|
+
#
|
4
|
+
# A linear algebra library for scientific computation in Ruby.
|
5
|
+
# NMatrix is part of SciRuby.
|
6
|
+
#
|
7
|
+
# NMatrix was originally inspired by and derived from NArray, by
|
8
|
+
# Masahiro Tanaka: http://narray.rubyforge.org
|
9
|
+
#
|
10
|
+
# == Copyright Information
|
11
|
+
#
|
12
|
+
# SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
|
13
|
+
# NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
|
14
|
+
#
|
15
|
+
# Please see LICENSE.txt for additional copyright notices.
|
16
|
+
#
|
17
|
+
# == Contributing
|
18
|
+
#
|
19
|
+
# By contributing source code to SciRuby, you agree to be bound by
|
20
|
+
# our Contributor Agreement:
|
21
|
+
#
|
22
|
+
# * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
|
23
|
+
#
|
24
|
+
# == atlas.rb
|
25
|
+
#
|
26
|
+
# ruby file for the nmatrix-atlas gem. Loads the C extension and defines
|
27
|
+
# nice ruby interfaces for ATLAS functions.
|
28
|
+
#++
|
29
|
+
|
30
|
+
require 'nmatrix/nmatrix.rb' #need to have nmatrix required first or else bad things will happen
|
31
|
+
require_relative 'lapack_ext_common'
|
32
|
+
|
33
|
+
NMatrix.register_lapack_extension("nmatrix-atlas")
|
34
|
+
|
35
|
+
require "nmatrix_atlas.so"
|
36
|
+
|
37
|
+
class NMatrix
|
38
|
+
|
39
|
+
#Add functions from the ATLAS C extension to the main LAPACK and BLAS modules.
|
40
|
+
#This will overwrite the original functions where applicable.
|
41
|
+
module LAPACK
|
42
|
+
class << self
|
43
|
+
NMatrix::ATLAS::LAPACK.singleton_methods.each do |m|
|
44
|
+
define_method m, NMatrix::ATLAS::LAPACK.method(m).to_proc
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
module BLAS
|
50
|
+
class << self
|
51
|
+
NMatrix::ATLAS::BLAS.singleton_methods.each do |m|
|
52
|
+
define_method m, NMatrix::ATLAS::BLAS.method(m).to_proc
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
module LAPACK
|
58
|
+
class << self
|
59
|
+
def posv(uplo, a, b)
|
60
|
+
raise(ShapeError, "a must be square") unless a.dim == 2 && a.shape[0] == a.shape[1]
|
61
|
+
raise(ShapeError, "number of rows of b must equal number of cols of a") unless a.shape[1] == b.shape[0]
|
62
|
+
raise(StorageTypeError, "only works with dense matrices") unless a.stype == :dense && b.stype == :dense
|
63
|
+
raise(DataTypeError, "only works for non-integer, non-object dtypes") if
|
64
|
+
a.integer_dtype? || a.object_dtype? || b.integer_dtype? || b.object_dtype?
|
65
|
+
|
66
|
+
x = b.clone
|
67
|
+
clone = a.clone
|
68
|
+
n = a.shape[0]
|
69
|
+
nrhs = b.shape[1]
|
70
|
+
clapack_potrf(:row, uplo, n, clone, n)
|
71
|
+
# Must transpose b before and after: http://math-atlas.sourceforge.net/faq.html#RowSolve
|
72
|
+
x = x.transpose
|
73
|
+
clapack_potrs(:row, uplo, n, nrhs, clone, n, x, n)
|
74
|
+
x.transpose
|
75
|
+
end
|
76
|
+
|
77
|
+
def geev(matrix, which=:both)
|
78
|
+
raise(StorageTypeError, "LAPACK functions only work on dense matrices") unless matrix.dense?
|
79
|
+
raise(ShapeError, "eigenvalues can only be computed for square matrices") unless matrix.dim == 2 && matrix.shape[0] == matrix.shape[1]
|
80
|
+
|
81
|
+
jobvl = (which == :both || which == :left) ? :t : false
|
82
|
+
jobvr = (which == :both || which == :right) ? :t : false
|
83
|
+
|
84
|
+
n = matrix.shape[0]
|
85
|
+
|
86
|
+
# Outputs
|
87
|
+
eigenvalues = NMatrix.new([n, 1], dtype: matrix.dtype) # For real dtypes this holds only the real part of the eigenvalues.
|
88
|
+
imag_eigenvalues = matrix.complex_dtype? ? nil : NMatrix.new([n, 1], dtype: matrix.dtype) # For complex dtypes, this is unused.
|
89
|
+
left_output = jobvl ? matrix.clone_structure : nil
|
90
|
+
right_output = jobvr ? matrix.clone_structure : nil
|
91
|
+
|
92
|
+
# lapack_geev is a pure LAPACK routine so it expects column-major matrices,
|
93
|
+
# so we need to transpose the input as well as the output.
|
94
|
+
temporary_matrix = matrix.transpose
|
95
|
+
NMatrix::LAPACK::lapack_geev(jobvl, # compute left eigenvectors of A?
|
96
|
+
jobvr, # compute right eigenvectors of A? (left eigenvectors of A**T)
|
97
|
+
n, # order of the matrix
|
98
|
+
temporary_matrix,# input matrix (used as work)
|
99
|
+
n, # leading dimension of matrix
|
100
|
+
eigenvalues,# real part of computed eigenvalues
|
101
|
+
imag_eigenvalues,# imag part of computed eigenvalues
|
102
|
+
left_output, # left eigenvectors, if applicable
|
103
|
+
n, # leading dimension of left_output
|
104
|
+
right_output, # right eigenvectors, if applicable
|
105
|
+
n, # leading dimension of right_output
|
106
|
+
2*n)
|
107
|
+
left_output = left_output.transpose if jobvl
|
108
|
+
right_output = right_output.transpose if jobvr
|
109
|
+
|
110
|
+
|
111
|
+
# For real dtypes, transform left_output and right_output into correct forms.
|
112
|
+
# If the j'th and the (j+1)'th eigenvalues form a complex conjugate
|
113
|
+
# pair, then the j'th and (j+1)'th columns of the matrix are
|
114
|
+
# the real and imag parts of the eigenvector corresponding
|
115
|
+
# to the j'th eigenvalue.
|
116
|
+
if !matrix.complex_dtype?
|
117
|
+
complex_indices = []
|
118
|
+
n.times do |i|
|
119
|
+
complex_indices << i if imag_eigenvalues[i] != 0.0
|
120
|
+
end
|
121
|
+
|
122
|
+
if !complex_indices.empty?
|
123
|
+
# For real dtypes, put the real and imaginary parts together
|
124
|
+
eigenvalues = eigenvalues + imag_eigenvalues*Complex(0.0,1.0)
|
125
|
+
left_output = left_output.cast(dtype: NMatrix.upcast(:complex64, matrix.dtype)) if left_output
|
126
|
+
right_output = right_output.cast(dtype: NMatrix.upcast(:complex64, matrix.dtype)) if right_output
|
127
|
+
end
|
128
|
+
|
129
|
+
complex_indices.each_slice(2) do |i, _|
|
130
|
+
if right_output
|
131
|
+
right_output[0...n,i] = right_output[0...n,i] + right_output[0...n,i+1]*Complex(0.0,1.0)
|
132
|
+
right_output[0...n,i+1] = right_output[0...n,i].complex_conjugate
|
133
|
+
end
|
134
|
+
|
135
|
+
if left_output
|
136
|
+
left_output[0...n,i] = left_output[0...n,i] + left_output[0...n,i+1]*Complex(0.0,1.0)
|
137
|
+
left_output[0...n,i+1] = left_output[0...n,i].complex_conjugate
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
if which == :both
|
143
|
+
return [eigenvalues, left_output, right_output]
|
144
|
+
elsif which == :left
|
145
|
+
return [eigenvalues, left_output]
|
146
|
+
else
|
147
|
+
return [eigenvalues, right_output]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def gesvd(matrix, workspace_size=1)
|
152
|
+
result = alloc_svd_result(matrix)
|
153
|
+
|
154
|
+
m = matrix.shape[0]
|
155
|
+
n = matrix.shape[1]
|
156
|
+
|
157
|
+
# This is a pure LAPACK function so it expects column-major functions.
|
158
|
+
# So we need to transpose the input as well as the output.
|
159
|
+
matrix = matrix.transpose
|
160
|
+
NMatrix::LAPACK::lapack_gesvd(:a, :a, m, n, matrix, m, result[1], result[0], m, result[2], n, workspace_size)
|
161
|
+
result[0] = result[0].transpose
|
162
|
+
result[2] = result[2].transpose
|
163
|
+
result
|
164
|
+
end
|
165
|
+
|
166
|
+
def gesdd(matrix, workspace_size=nil)
|
167
|
+
min_workspace_size = matrix.shape.min * (6 + 4 * matrix.shape.min) + matrix.shape.max
|
168
|
+
workspace_size = min_workspace_size if workspace_size.nil? || workspace_size < min_workspace_size
|
169
|
+
|
170
|
+
result = alloc_svd_result(matrix)
|
171
|
+
|
172
|
+
m = matrix.shape[0]
|
173
|
+
n = matrix.shape[1]
|
174
|
+
|
175
|
+
# This is a pure LAPACK function so it expects column-major functions.
|
176
|
+
# So we need to transpose the input as well as the output.
|
177
|
+
matrix = matrix.transpose
|
178
|
+
NMatrix::LAPACK::lapack_gesdd(:a, m, n, matrix, m, result[1], result[0], m, result[2], n, workspace_size)
|
179
|
+
result[0] = result[0].transpose
|
180
|
+
result[2] = result[2].transpose
|
181
|
+
result
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def invert!
|
187
|
+
raise(StorageTypeError, "invert only works on dense matrices currently") unless self.dense?
|
188
|
+
raise(ShapeError, "Cannot invert non-square matrix") unless shape[0] == shape[1]
|
189
|
+
raise(DataTypeError, "Cannot invert an integer matrix in-place") if self.integer_dtype?
|
190
|
+
|
191
|
+
# Even though we are using the ATLAS plugin, we still might be missing
|
192
|
+
# CLAPACK (and thus clapack_getri) if we are on OS X.
|
193
|
+
if NMatrix.has_clapack?
|
194
|
+
# Get the pivot array; factor the matrix
|
195
|
+
# We can't used getrf! here since it doesn't have the clapack behavior,
|
196
|
+
# so it doesn't play nicely with clapack_getri
|
197
|
+
n = self.shape[0]
|
198
|
+
pivot = NMatrix::LAPACK::clapack_getrf(:row, n, n, self, n)
|
199
|
+
# Now calculate the inverse using the pivot array
|
200
|
+
NMatrix::LAPACK::clapack_getri(:row, n, self, n, pivot)
|
201
|
+
self
|
202
|
+
else
|
203
|
+
__inverse__(self,true)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def potrf!(which)
|
208
|
+
raise(StorageTypeError, "ATLAS functions only work on dense matrices") unless self.dense?
|
209
|
+
raise(ShapeError, "Cholesky decomposition only valid for square matrices") unless self.dim == 2 && self.shape[0] == self.shape[1]
|
210
|
+
|
211
|
+
NMatrix::LAPACK::clapack_potrf(:row, which, self.shape[0], self, self.shape[1])
|
212
|
+
end
|
213
|
+
end
|