numo-linalg-alt 0.4.1 → 0.5.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 +4 -4
- data/CHANGELOG.md +7 -1
- data/README.md +36 -0
- data/ext/numo/linalg/extconf.rb +1 -0
- data/ext/numo/linalg/lapack/gehrd.c +77 -0
- data/ext/numo/linalg/lapack/gehrd.h +15 -0
- data/ext/numo/linalg/lapack/lange.c +7 -8
- data/ext/numo/linalg/lapack/orghr.c +82 -0
- data/ext/numo/linalg/lapack/orghr.h +15 -0
- data/ext/numo/linalg/lapack/unghr.c +82 -0
- data/ext/numo/linalg/lapack/unghr.h +15 -0
- data/ext/numo/linalg/linalg.c +3 -0
- data/ext/numo/linalg/linalg.h +3 -0
- data/lib/numo/linalg/version.rb +1 -1
- data/lib/numo/linalg.rb +92 -0
- metadata +8 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 25f768b7f68b0526d390891b70e65e41ef16ef61a31614100c53250bb3d29baa
|
|
4
|
+
data.tar.gz: ebeb6d483949b617d5567f0265b2cd2cdee992fe8494006875595aa2dbb80adf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bba4f496a60bd9fe7aad51f07c6123855d8cbf4c1f1d2d4bb2858482c8ad3daeea5de8425176b242c5d84376874a0d0f93e80e46b0e39a2ff671721acb083fb3
|
|
7
|
+
data.tar.gz: 40d7100c495cad8021d5678ba1a0a3a3a9bdcfb53262e985234c653d207270c5d88f4a8d67ae8d00caab578f94142b1bdae198cf5ee3799cfc997f55486525cc
|
data/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
## [[0.
|
|
1
|
+
## [[0.5.0](https://github.com/yoshoku/numo-linalg-alt/compare/v0.4.1...v0.5.0)] - 2025-10-25
|
|
2
|
+
|
|
3
|
+
- FIX: correct Numo::Linalg::Lapack.xlange return type to Float for Numo::DComplex and Numo::SComplex.
|
|
4
|
+
- add `coshm`, `sinhm`, and `tanhm` module functions to Numo::Linalg.
|
|
5
|
+
- add `hessenberg` module function to Numo::Linalg.
|
|
6
|
+
|
|
7
|
+
## [[0.4.1](https://github.com/yoshoku/numo-linalg-alt/compare/v0.4.0...v0.4.1)] - 2025-10-19
|
|
2
8
|
|
|
3
9
|
- FIX: remove incorrect usage of RUBY_METHOD_FUNC macro: [#2](https://github.com/yoshoku/numo-linalg-alt/pull/2)
|
|
4
10
|
- add `matrix_balance` moudle function to Numo::Linalg.
|
data/README.md
CHANGED
|
@@ -63,6 +63,11 @@ Ubuntu:
|
|
|
63
63
|
$ gem install numo-linalg-alt
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
## Documentation
|
|
67
|
+
|
|
68
|
+
- [API Documentation](https://gemdocs.org/gems/numo-linalg-alt/0.4.1/)
|
|
69
|
+
- [Comparison with scipy.linalg and numpy.linalg](https://github.com/yoshoku/numo-linalg-alt/wiki/Comparison-with-scipy.linalg-and-numpy.linalg)
|
|
70
|
+
|
|
66
71
|
## Usage
|
|
67
72
|
|
|
68
73
|
An example of singular value decomposition.
|
|
@@ -94,6 +99,37 @@ puts (x - z).abs.max
|
|
|
94
99
|
# => 4.440892098500626e-16
|
|
95
100
|
```
|
|
96
101
|
|
|
102
|
+
## Development
|
|
103
|
+
|
|
104
|
+
preparation:
|
|
105
|
+
|
|
106
|
+
```shell
|
|
107
|
+
$ git clone https://github.com/yoshoku/numo-linalg-alt
|
|
108
|
+
$ cd numo-linalg-alt
|
|
109
|
+
$ bundle install
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
build and test:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
$ bundle exec rake compile
|
|
116
|
+
$ bundle exec rake test
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
linter:
|
|
120
|
+
|
|
121
|
+
```shell
|
|
122
|
+
$ bundle exec rubocop
|
|
123
|
+
$ clang-format --dry-run --Werror --style=file ext/**/*.h ext/**/*.c
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
This project follows [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
|
|
127
|
+
Please run `npm install` to set up husky and commitlint for commit message validation:
|
|
128
|
+
|
|
129
|
+
```shell
|
|
130
|
+
$ npm install
|
|
131
|
+
```
|
|
132
|
+
|
|
97
133
|
## Contributing
|
|
98
134
|
|
|
99
135
|
Bug reports and pull requests are welcome on GitHub at https://github.com/yoshoku/numo-linalg-alt.
|
data/ext/numo/linalg/extconf.rb
CHANGED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#include "gehrd.h"
|
|
2
|
+
|
|
3
|
+
struct _gehrd_option {
|
|
4
|
+
int matrix_layout;
|
|
5
|
+
int ilo;
|
|
6
|
+
int ihi;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
#define DEF_LINALG_FUNC(tDType, tNAryClass, fLapackFunc) \
|
|
10
|
+
static void _iter_##fLapackFunc(na_loop_t* const lp) { \
|
|
11
|
+
tDType* a = (tDType*)NDL_PTR(lp, 0); \
|
|
12
|
+
tDType* tau = (tDType*)NDL_PTR(lp, 1); \
|
|
13
|
+
int* info = (int*)NDL_PTR(lp, 2); \
|
|
14
|
+
struct _gehrd_option* opt = (struct _gehrd_option*)(lp->opt_ptr); \
|
|
15
|
+
const lapack_int ilo = opt->ilo; \
|
|
16
|
+
const lapack_int ihi = opt->ihi; \
|
|
17
|
+
const lapack_int n = \
|
|
18
|
+
(lapack_int)(opt->matrix_layout == LAPACK_ROW_MAJOR ? NDL_SHAPE(lp, 0)[0] \
|
|
19
|
+
: NDL_SHAPE(lp, 0)[1]); \
|
|
20
|
+
const lapack_int lda = n; \
|
|
21
|
+
lapack_int i = LAPACKE_##fLapackFunc(opt->matrix_layout, n, ilo, ihi, a, lda, tau); \
|
|
22
|
+
*info = (int)i; \
|
|
23
|
+
} \
|
|
24
|
+
\
|
|
25
|
+
static VALUE _linalg_lapack_##fLapackFunc(int argc, VALUE* argv, VALUE self) { \
|
|
26
|
+
VALUE a_vnary = Qnil; \
|
|
27
|
+
VALUE kw_args = Qnil; \
|
|
28
|
+
rb_scan_args(argc, argv, "1:", &a_vnary, &kw_args); \
|
|
29
|
+
ID kw_table[3] = { rb_intern("ilo"), rb_intern("ihi"), rb_intern("order") }; \
|
|
30
|
+
VALUE kw_values[3] = { Qundef, Qundef, Qundef }; \
|
|
31
|
+
rb_get_kwargs(kw_args, kw_table, 2, 1, kw_values); \
|
|
32
|
+
const int ilo = NUM2INT(kw_values[0]); \
|
|
33
|
+
const int ihi = NUM2INT(kw_values[1]); \
|
|
34
|
+
const int matrix_layout = \
|
|
35
|
+
kw_values[2] != Qundef ? get_matrix_layout(kw_values[2]) : LAPACK_ROW_MAJOR; \
|
|
36
|
+
\
|
|
37
|
+
if (CLASS_OF(a_vnary) != tNAryClass) { \
|
|
38
|
+
a_vnary = rb_funcall(tNAryClass, rb_intern("cast"), 1, a_vnary); \
|
|
39
|
+
} \
|
|
40
|
+
if (!RTEST(nary_check_contiguous(a_vnary))) { \
|
|
41
|
+
a_vnary = nary_dup(a_vnary); \
|
|
42
|
+
} \
|
|
43
|
+
\
|
|
44
|
+
narray_t* a_nary = NULL; \
|
|
45
|
+
GetNArray(a_vnary, a_nary); \
|
|
46
|
+
const int n_dims = NA_NDIM(a_nary); \
|
|
47
|
+
if (n_dims != 2) { \
|
|
48
|
+
rb_raise(rb_eArgError, "input array a must be 2-dimensional"); \
|
|
49
|
+
return Qnil; \
|
|
50
|
+
} \
|
|
51
|
+
\
|
|
52
|
+
size_t n = matrix_layout == LAPACK_ROW_MAJOR ? NA_SHAPE(a_nary)[0] : NA_SHAPE(a_nary)[1]; \
|
|
53
|
+
size_t shape_tau[1] = { n - 1 }; \
|
|
54
|
+
ndfunc_arg_in_t ain[1] = { { OVERWRITE, 2 } }; \
|
|
55
|
+
ndfunc_arg_out_t aout[2] = { { tNAryClass, 1, shape_tau }, { numo_cInt32, 0 } }; \
|
|
56
|
+
ndfunc_t ndf = { _iter_##fLapackFunc, NO_LOOP | NDF_EXTRACT, 1, 2, ain, aout }; \
|
|
57
|
+
struct _gehrd_option opt = { matrix_layout, ilo, ihi }; \
|
|
58
|
+
VALUE res = na_ndloop3(&ndf, &opt, 1, a_vnary); \
|
|
59
|
+
VALUE ret = rb_ary_concat(rb_ary_new3(1, a_vnary), res); \
|
|
60
|
+
\
|
|
61
|
+
RB_GC_GUARD(a_vnary); \
|
|
62
|
+
return ret; \
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
DEF_LINALG_FUNC(double, numo_cDFloat, dgehrd)
|
|
66
|
+
DEF_LINALG_FUNC(float, numo_cSFloat, sgehrd)
|
|
67
|
+
DEF_LINALG_FUNC(lapack_complex_double, numo_cDComplex, zgehrd)
|
|
68
|
+
DEF_LINALG_FUNC(lapack_complex_float, numo_cSComplex, cgehrd)
|
|
69
|
+
|
|
70
|
+
#undef DEF_LINALG_FUNC
|
|
71
|
+
|
|
72
|
+
void define_linalg_lapack_gehrd(VALUE mLapack) {
|
|
73
|
+
rb_define_module_function(mLapack, "dgehrd", _linalg_lapack_dgehrd, -1);
|
|
74
|
+
rb_define_module_function(mLapack, "sgehrd", _linalg_lapack_sgehrd, -1);
|
|
75
|
+
rb_define_module_function(mLapack, "zgehrd", _linalg_lapack_zgehrd, -1);
|
|
76
|
+
rb_define_module_function(mLapack, "cgehrd", _linalg_lapack_cgehrd, -1);
|
|
77
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#ifndef NUMO_LINALG_ALT_LAPACK_GEHRD_H
|
|
2
|
+
#define NUMO_LINALG_ALT_LAPACK_GEHRD_H 1
|
|
3
|
+
|
|
4
|
+
#include <lapacke.h>
|
|
5
|
+
|
|
6
|
+
#include <ruby.h>
|
|
7
|
+
|
|
8
|
+
#include <numo/narray.h>
|
|
9
|
+
#include <numo/template.h>
|
|
10
|
+
|
|
11
|
+
#include "../util.h"
|
|
12
|
+
|
|
13
|
+
void define_linalg_lapack_gehrd(VALUE mLapack);
|
|
14
|
+
|
|
15
|
+
#endif // NUMO_LINALG_ALT_LAPACK_GEHRD_H
|
|
@@ -5,10 +5,10 @@ struct _lange_option {
|
|
|
5
5
|
char norm;
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
-
#define DEF_LINALG_FUNC(tDType, tNAryClass, fLapackFunc)
|
|
8
|
+
#define DEF_LINALG_FUNC(tDType, tRtDType, tNAryClass, tRtNAryClass, fLapackFunc) \
|
|
9
9
|
static void _iter_##fLapackFunc(na_loop_t* const lp) { \
|
|
10
10
|
tDType* a = (tDType*)NDL_PTR(lp, 0); \
|
|
11
|
-
|
|
11
|
+
tRtDType* d = (tRtDType*)NDL_PTR(lp, 1); \
|
|
12
12
|
struct _lange_option* opt = (struct _lange_option*)(lp->opt_ptr); \
|
|
13
13
|
const lapack_int m = (lapack_int)NDL_SHAPE(lp, 0)[0]; \
|
|
14
14
|
const lapack_int n = (lapack_int)NDL_SHAPE(lp, 0)[1]; \
|
|
@@ -42,8 +42,7 @@ struct _lange_option {
|
|
|
42
42
|
} \
|
|
43
43
|
\
|
|
44
44
|
ndfunc_arg_in_t ain[1] = { { tNAryClass, 2 } }; \
|
|
45
|
-
|
|
46
|
-
ndfunc_arg_out_t aout[1] = { { tNAryClass, 0, shape_out } }; \
|
|
45
|
+
ndfunc_arg_out_t aout[1] = { { tRtNAryClass, 0 } }; \
|
|
47
46
|
ndfunc_t ndf = { _iter_##fLapackFunc, NO_LOOP | NDF_EXTRACT, 1, 1, ain, aout }; \
|
|
48
47
|
struct _lange_option opt = { matrix_layout, norm }; \
|
|
49
48
|
VALUE ret = na_ndloop3(&ndf, &opt, 1, a_vnary); \
|
|
@@ -52,10 +51,10 @@ struct _lange_option {
|
|
|
52
51
|
return ret; \
|
|
53
52
|
}
|
|
54
53
|
|
|
55
|
-
DEF_LINALG_FUNC(double, numo_cDFloat, dlange)
|
|
56
|
-
DEF_LINALG_FUNC(float, numo_cSFloat, slange)
|
|
57
|
-
DEF_LINALG_FUNC(lapack_complex_double, numo_cDComplex, zlange)
|
|
58
|
-
DEF_LINALG_FUNC(lapack_complex_float, numo_cSComplex, clange)
|
|
54
|
+
DEF_LINALG_FUNC(double, double, numo_cDFloat, numo_cDFloat, dlange)
|
|
55
|
+
DEF_LINALG_FUNC(float, float, numo_cSFloat, numo_cSFloat, slange)
|
|
56
|
+
DEF_LINALG_FUNC(lapack_complex_double, double, numo_cDComplex, numo_cDFloat, zlange)
|
|
57
|
+
DEF_LINALG_FUNC(lapack_complex_float, float, numo_cSComplex, numo_cSFloat, clange)
|
|
59
58
|
|
|
60
59
|
#undef DEF_LINALG_FUNC
|
|
61
60
|
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#include "orghr.h"
|
|
2
|
+
|
|
3
|
+
struct _orghr_option {
|
|
4
|
+
int matrix_layout;
|
|
5
|
+
int ilo;
|
|
6
|
+
int ihi;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
#define DEF_LINALG_FUNC(tDType, tNAryClass, fLapackFunc) \
|
|
10
|
+
static void _iter_##fLapackFunc(na_loop_t* const lp) { \
|
|
11
|
+
tDType* a = (tDType*)NDL_PTR(lp, 0); \
|
|
12
|
+
tDType* tau = (tDType*)NDL_PTR(lp, 1); \
|
|
13
|
+
int* info = (int*)NDL_PTR(lp, 2); \
|
|
14
|
+
struct _orghr_option* opt = (struct _orghr_option*)(lp->opt_ptr); \
|
|
15
|
+
const lapack_int ilo = opt->ilo; \
|
|
16
|
+
const lapack_int ihi = opt->ihi; \
|
|
17
|
+
const lapack_int n = (lapack_int)NDL_SHAPE(lp, 0)[0]; \
|
|
18
|
+
const lapack_int lda = n; \
|
|
19
|
+
const lapack_int i = LAPACKE_##fLapackFunc(opt->matrix_layout, n, ilo, ihi, a, lda, tau); \
|
|
20
|
+
*info = (int)i; \
|
|
21
|
+
} \
|
|
22
|
+
\
|
|
23
|
+
static VALUE _linalg_lapack_##fLapackFunc(int argc, VALUE* argv, VALUE self) { \
|
|
24
|
+
VALUE a_vnary = Qnil; \
|
|
25
|
+
VALUE tau_vnary = Qnil; \
|
|
26
|
+
VALUE kw_args = Qnil; \
|
|
27
|
+
rb_scan_args(argc, argv, "2:", &a_vnary, &tau_vnary, &kw_args); \
|
|
28
|
+
ID kw_table[3] = { rb_intern("ilo"), rb_intern("ihi"), rb_intern("order") }; \
|
|
29
|
+
VALUE kw_values[3] = { Qundef, Qundef, Qundef }; \
|
|
30
|
+
rb_get_kwargs(kw_args, kw_table, 2, 1, kw_values); \
|
|
31
|
+
const int ilo = NUM2INT(kw_values[0]); \
|
|
32
|
+
const int ihi = NUM2INT(kw_values[1]); \
|
|
33
|
+
const int matrix_layout = \
|
|
34
|
+
kw_values[2] != Qundef ? get_matrix_layout(kw_values[2]) : LAPACK_ROW_MAJOR; \
|
|
35
|
+
\
|
|
36
|
+
if (CLASS_OF(a_vnary) != tNAryClass) { \
|
|
37
|
+
a_vnary = rb_funcall(tNAryClass, rb_intern("cast"), 1, a_vnary); \
|
|
38
|
+
} \
|
|
39
|
+
if (!RTEST(nary_check_contiguous(a_vnary))) { \
|
|
40
|
+
a_vnary = nary_dup(a_vnary); \
|
|
41
|
+
} \
|
|
42
|
+
if (CLASS_OF(tau_vnary) != tNAryClass) { \
|
|
43
|
+
tau_vnary = rb_funcall(tNAryClass, rb_intern("cast"), 1, tau_vnary); \
|
|
44
|
+
} \
|
|
45
|
+
if (!RTEST(nary_check_contiguous(tau_vnary))) { \
|
|
46
|
+
tau_vnary = nary_dup(tau_vnary); \
|
|
47
|
+
} \
|
|
48
|
+
\
|
|
49
|
+
narray_t* a_nary = NULL; \
|
|
50
|
+
GetNArray(a_vnary, a_nary); \
|
|
51
|
+
if (NA_NDIM(a_nary) != 2) { \
|
|
52
|
+
rb_raise(rb_eArgError, "input array a must be 2-dimensional"); \
|
|
53
|
+
return Qnil; \
|
|
54
|
+
} \
|
|
55
|
+
narray_t* tau_nary = NULL; \
|
|
56
|
+
GetNArray(tau_vnary, tau_nary); \
|
|
57
|
+
if (NA_NDIM(tau_nary) != 1) { \
|
|
58
|
+
rb_raise(rb_eArgError, "input array tau must be 1-dimensional"); \
|
|
59
|
+
return Qnil; \
|
|
60
|
+
} \
|
|
61
|
+
\
|
|
62
|
+
ndfunc_arg_in_t ain[2] = { { OVERWRITE, 2 }, { tNAryClass, 1 } }; \
|
|
63
|
+
ndfunc_arg_out_t aout[1] = { { numo_cInt32, 0 } }; \
|
|
64
|
+
ndfunc_t ndf = { _iter_##fLapackFunc, NO_LOOP | NDF_EXTRACT, 2, 1, ain, aout }; \
|
|
65
|
+
struct _orghr_option opt = { matrix_layout, ilo, ihi }; \
|
|
66
|
+
VALUE res = na_ndloop3(&ndf, &opt, 2, a_vnary, tau_vnary); \
|
|
67
|
+
VALUE ret = rb_ary_new3(2, a_vnary, res); \
|
|
68
|
+
\
|
|
69
|
+
RB_GC_GUARD(a_vnary); \
|
|
70
|
+
RB_GC_GUARD(tau_vnary); \
|
|
71
|
+
return ret; \
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
DEF_LINALG_FUNC(double, numo_cDFloat, dorghr)
|
|
75
|
+
DEF_LINALG_FUNC(float, numo_cSFloat, sorghr)
|
|
76
|
+
|
|
77
|
+
#undef DEF_LINALG_FUNC
|
|
78
|
+
|
|
79
|
+
void define_linalg_lapack_orghr(VALUE mLapack) {
|
|
80
|
+
rb_define_module_function(mLapack, "dorghr", _linalg_lapack_dorghr, -1);
|
|
81
|
+
rb_define_module_function(mLapack, "sorghr", _linalg_lapack_sorghr, -1);
|
|
82
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#ifndef NUMO_LINALG_ALT_LAPACK_ORGHR_H
|
|
2
|
+
#define NUMO_LINALG_ALT_LAPACK_ORGHR_H 1
|
|
3
|
+
|
|
4
|
+
#include <lapacke.h>
|
|
5
|
+
|
|
6
|
+
#include <ruby.h>
|
|
7
|
+
|
|
8
|
+
#include <numo/narray.h>
|
|
9
|
+
#include <numo/template.h>
|
|
10
|
+
|
|
11
|
+
#include "../util.h"
|
|
12
|
+
|
|
13
|
+
void define_linalg_lapack_orghr(VALUE mLapack);
|
|
14
|
+
|
|
15
|
+
#endif /* NUMO_LINALG_ALT_LAPACK_ORGHR_H */
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#include "unghr.h"
|
|
2
|
+
|
|
3
|
+
struct _unghr_option {
|
|
4
|
+
int matrix_layout;
|
|
5
|
+
int ilo;
|
|
6
|
+
int ihi;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
#define DEF_LINALG_FUNC(tDType, tNAryClass, fLapackFunc) \
|
|
10
|
+
static void _iter_##fLapackFunc(na_loop_t* const lp) { \
|
|
11
|
+
tDType* a = (tDType*)NDL_PTR(lp, 0); \
|
|
12
|
+
tDType* tau = (tDType*)NDL_PTR(lp, 1); \
|
|
13
|
+
int* info = (int*)NDL_PTR(lp, 2); \
|
|
14
|
+
struct _unghr_option* opt = (struct _unghr_option*)(lp->opt_ptr); \
|
|
15
|
+
const lapack_int ilo = opt->ilo; \
|
|
16
|
+
const lapack_int ihi = opt->ihi; \
|
|
17
|
+
const lapack_int n = (lapack_int)NDL_SHAPE(lp, 0)[0]; \
|
|
18
|
+
const lapack_int lda = n; \
|
|
19
|
+
const lapack_int i = LAPACKE_##fLapackFunc(opt->matrix_layout, n, ilo, ihi, a, lda, tau); \
|
|
20
|
+
*info = (int)i; \
|
|
21
|
+
} \
|
|
22
|
+
\
|
|
23
|
+
static VALUE _linalg_lapack_##fLapackFunc(int argc, VALUE* argv, VALUE self) { \
|
|
24
|
+
VALUE a_vnary = Qnil; \
|
|
25
|
+
VALUE tau_vnary = Qnil; \
|
|
26
|
+
VALUE kw_args = Qnil; \
|
|
27
|
+
rb_scan_args(argc, argv, "2:", &a_vnary, &tau_vnary, &kw_args); \
|
|
28
|
+
ID kw_table[3] = { rb_intern("ilo"), rb_intern("ihi"), rb_intern("order") }; \
|
|
29
|
+
VALUE kw_values[3] = { Qundef, Qundef, Qundef }; \
|
|
30
|
+
rb_get_kwargs(kw_args, kw_table, 2, 1, kw_values); \
|
|
31
|
+
const int ilo = NUM2INT(kw_values[0]); \
|
|
32
|
+
const int ihi = NUM2INT(kw_values[1]); \
|
|
33
|
+
const int matrix_layout = \
|
|
34
|
+
kw_values[2] != Qundef ? get_matrix_layout(kw_values[2]) : LAPACK_ROW_MAJOR; \
|
|
35
|
+
\
|
|
36
|
+
if (CLASS_OF(a_vnary) != tNAryClass) { \
|
|
37
|
+
a_vnary = rb_funcall(tNAryClass, rb_intern("cast"), 1, a_vnary); \
|
|
38
|
+
} \
|
|
39
|
+
if (!RTEST(nary_check_contiguous(a_vnary))) { \
|
|
40
|
+
a_vnary = nary_dup(a_vnary); \
|
|
41
|
+
} \
|
|
42
|
+
if (CLASS_OF(tau_vnary) != tNAryClass) { \
|
|
43
|
+
tau_vnary = rb_funcall(tNAryClass, rb_intern("cast"), 1, tau_vnary); \
|
|
44
|
+
} \
|
|
45
|
+
if (!RTEST(nary_check_contiguous(tau_vnary))) { \
|
|
46
|
+
tau_vnary = nary_dup(tau_vnary); \
|
|
47
|
+
} \
|
|
48
|
+
\
|
|
49
|
+
narray_t* a_nary = NULL; \
|
|
50
|
+
GetNArray(a_vnary, a_nary); \
|
|
51
|
+
if (NA_NDIM(a_nary) != 2) { \
|
|
52
|
+
rb_raise(rb_eArgError, "input array a must be 2-dimensional"); \
|
|
53
|
+
return Qnil; \
|
|
54
|
+
} \
|
|
55
|
+
narray_t* tau_nary = NULL; \
|
|
56
|
+
GetNArray(tau_vnary, tau_nary); \
|
|
57
|
+
if (NA_NDIM(tau_nary) != 1) { \
|
|
58
|
+
rb_raise(rb_eArgError, "input array tau must be 1-dimensional"); \
|
|
59
|
+
return Qnil; \
|
|
60
|
+
} \
|
|
61
|
+
\
|
|
62
|
+
ndfunc_arg_in_t ain[2] = { { OVERWRITE, 2 }, { tNAryClass, 1 } }; \
|
|
63
|
+
ndfunc_arg_out_t aout[1] = { { numo_cInt32, 0 } }; \
|
|
64
|
+
ndfunc_t ndf = { _iter_##fLapackFunc, NO_LOOP | NDF_EXTRACT, 2, 1, ain, aout }; \
|
|
65
|
+
struct _unghr_option opt = { matrix_layout, ilo, ihi }; \
|
|
66
|
+
VALUE res = na_ndloop3(&ndf, &opt, 2, a_vnary, tau_vnary); \
|
|
67
|
+
VALUE ret = rb_ary_new3(2, a_vnary, res); \
|
|
68
|
+
\
|
|
69
|
+
RB_GC_GUARD(a_vnary); \
|
|
70
|
+
RB_GC_GUARD(tau_vnary); \
|
|
71
|
+
return ret; \
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
DEF_LINALG_FUNC(lapack_complex_double, numo_cDComplex, zunghr)
|
|
75
|
+
DEF_LINALG_FUNC(lapack_complex_float, numo_cSComplex, cunghr)
|
|
76
|
+
|
|
77
|
+
#undef DEF_LINALG_FUNC
|
|
78
|
+
|
|
79
|
+
void define_linalg_lapack_unghr(VALUE mLapack) {
|
|
80
|
+
rb_define_module_function(mLapack, "zunghr", _linalg_lapack_zunghr, -1);
|
|
81
|
+
rb_define_module_function(mLapack, "cunghr", _linalg_lapack_cunghr, -1);
|
|
82
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#ifndef NUMO_LINALG_ALT_LAPACK_UNGHR_H
|
|
2
|
+
#define NUMO_LINALG_ALT_LAPACK_UNGHR_H 1
|
|
3
|
+
|
|
4
|
+
#include <lapacke.h>
|
|
5
|
+
|
|
6
|
+
#include <ruby.h>
|
|
7
|
+
|
|
8
|
+
#include <numo/narray.h>
|
|
9
|
+
#include <numo/template.h>
|
|
10
|
+
|
|
11
|
+
#include "../util.h"
|
|
12
|
+
|
|
13
|
+
void define_linalg_lapack_unghr(VALUE mLapack);
|
|
14
|
+
|
|
15
|
+
#endif /* NUMO_LINALG_ALT_LAPACK_UNGHR_H */
|
data/ext/numo/linalg/linalg.c
CHANGED
|
@@ -296,6 +296,9 @@ void Init_linalg(void) {
|
|
|
296
296
|
define_linalg_lapack_sytrf(rb_mLinalgLapack);
|
|
297
297
|
define_linalg_lapack_hetrf(rb_mLinalgLapack);
|
|
298
298
|
define_linalg_lapack_gebal(rb_mLinalgLapack);
|
|
299
|
+
define_linalg_lapack_gehrd(rb_mLinalgLapack);
|
|
300
|
+
define_linalg_lapack_orghr(rb_mLinalgLapack);
|
|
301
|
+
define_linalg_lapack_unghr(rb_mLinalgLapack);
|
|
299
302
|
|
|
300
303
|
rb_define_alias(rb_singleton_class(rb_mLinalgBlas), "znrm2", "dznrm2");
|
|
301
304
|
rb_define_alias(rb_singleton_class(rb_mLinalgBlas), "cnrm2", "scnrm2");
|
data/ext/numo/linalg/linalg.h
CHANGED
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
#include "lapack/gebal.h"
|
|
55
55
|
#include "lapack/gees.h"
|
|
56
56
|
#include "lapack/geev.h"
|
|
57
|
+
#include "lapack/gehrd.h"
|
|
57
58
|
#include "lapack/gelsd.h"
|
|
58
59
|
#include "lapack/geqrf.h"
|
|
59
60
|
#include "lapack/gerqf.h"
|
|
@@ -72,6 +73,7 @@
|
|
|
72
73
|
#include "lapack/hegvx.h"
|
|
73
74
|
#include "lapack/hetrf.h"
|
|
74
75
|
#include "lapack/lange.h"
|
|
76
|
+
#include "lapack/orghr.h"
|
|
75
77
|
#include "lapack/orgqr.h"
|
|
76
78
|
#include "lapack/orgrq.h"
|
|
77
79
|
#include "lapack/potrf.h"
|
|
@@ -85,6 +87,7 @@
|
|
|
85
87
|
#include "lapack/sygvx.h"
|
|
86
88
|
#include "lapack/sytrf.h"
|
|
87
89
|
#include "lapack/trtrs.h"
|
|
90
|
+
#include "lapack/unghr.h"
|
|
88
91
|
#include "lapack/ungqr.h"
|
|
89
92
|
#include "lapack/ungrq.h"
|
|
90
93
|
|
data/lib/numo/linalg/version.rb
CHANGED
data/lib/numo/linalg.rb
CHANGED
|
@@ -740,6 +740,63 @@ module Numo
|
|
|
740
740
|
[b, v, sdim]
|
|
741
741
|
end
|
|
742
742
|
|
|
743
|
+
# Computes the Hessenberg decomposition of a square matrix.
|
|
744
|
+
# The Hessenberg decomposition is given by `A = Q * H * Q^H`,
|
|
745
|
+
# where `A` is the input matrix, `Q` is a unitary matrix,
|
|
746
|
+
# and `H` is an upper Hessenberg matrix.
|
|
747
|
+
#
|
|
748
|
+
# @example
|
|
749
|
+
# require 'numo/linalg'
|
|
750
|
+
#
|
|
751
|
+
# a = Numo::DFloat[[1, 2, 3], [4, 5, 6], [7, 8, 9]] * 0.5
|
|
752
|
+
# h, q = Numo::Linalg.hessenberg(a, calc_q: true)
|
|
753
|
+
#
|
|
754
|
+
# pp h
|
|
755
|
+
# # => Numo::DFloat#shape=[3,3]
|
|
756
|
+
# # [[0.5, -1.7985, -0.124035],
|
|
757
|
+
# # [-4.03113, 7.02308, 1.41538],
|
|
758
|
+
# # [0, 0.415385, -0.0230769]]
|
|
759
|
+
# pp q
|
|
760
|
+
# # => Numo::DFloat#shape=[3,3]
|
|
761
|
+
# # [[1, 0, 0],
|
|
762
|
+
# # [0, -0.496139, -0.868243],
|
|
763
|
+
# # [0, -0.868243, 0.496139]]
|
|
764
|
+
# pp (a - q.dot(h).dot(q.transpose)).abs.max
|
|
765
|
+
# # => 1.7763568394002505e-15
|
|
766
|
+
#
|
|
767
|
+
# @param a [Numo::NArray] The n-by-n square matrix.
|
|
768
|
+
# @param calc_q [Boolean] The flag indicating whether to calculate the unitary matrix `Q`.
|
|
769
|
+
# @return [Numo::NArray] if calc_q=false, the Hessenberg form `H`.
|
|
770
|
+
# @return [Array<Numo::NArray, Numo::NArray>] if calc_q=true,
|
|
771
|
+
# the Hessenberg form `H` and the unitary matrix `Q`.
|
|
772
|
+
def hessenberg(a, calc_q: false)
|
|
773
|
+
raise Numo::NArray::ShapeError, 'input array a must be 2-dimensional' if a.ndim != 2
|
|
774
|
+
raise Numo::NArray::ShapeError, 'input array a must be square' if a.shape[0] != a.shape[1]
|
|
775
|
+
|
|
776
|
+
bchr = blas_char(a)
|
|
777
|
+
raise ArgumentError, "invalid array type: #{a.class}" if bchr == 'n'
|
|
778
|
+
|
|
779
|
+
func = :"#{bchr}gebal"
|
|
780
|
+
b, ilo, ihi, _, info = Numo::Linalg::Lapack.send(func, a.dup)
|
|
781
|
+
|
|
782
|
+
raise "the #{-info}-th argument of #{func} had illegal value" if info.negative?
|
|
783
|
+
|
|
784
|
+
func = :"#{bchr}gehrd"
|
|
785
|
+
hq, tau, info = Numo::Linalg::Lapack.send(func, b, ilo: ilo, ihi: ihi)
|
|
786
|
+
|
|
787
|
+
raise "the #{-info}-th argument of #{func} had illegal value" if info.negative?
|
|
788
|
+
|
|
789
|
+
h = hq.triu(-1)
|
|
790
|
+
return h unless calc_q
|
|
791
|
+
|
|
792
|
+
func = %w[d s].include?(bchr) ? :"#{bchr}orghr" : :"#{bchr}unghr"
|
|
793
|
+
q, info = Numo::Linalg::Lapack.send(func, hq, tau, ilo: ilo, ihi: ihi)
|
|
794
|
+
|
|
795
|
+
raise "the #{-info}-th argument of #{func} had illegal value" if info.negative?
|
|
796
|
+
|
|
797
|
+
[h, q]
|
|
798
|
+
end
|
|
799
|
+
|
|
743
800
|
# Solves linear equation `A * x = b` or `A * X = B` for `x` from square matrix `A`.
|
|
744
801
|
#
|
|
745
802
|
# @example
|
|
@@ -1613,6 +1670,41 @@ module Numo
|
|
|
1613
1670
|
a_sin.dot(Numo::Linalg.inv(a_cos))
|
|
1614
1671
|
end
|
|
1615
1672
|
|
|
1673
|
+
# Computes the matrix hyperbolic sine using the matrix exponential.
|
|
1674
|
+
#
|
|
1675
|
+
# @param a [Numo::NArray] The n-by-n square matrix.
|
|
1676
|
+
# @return [Numo::NArray] The matrix hyperbolic sine of `a`.
|
|
1677
|
+
def sinhm(a)
|
|
1678
|
+
raise Numo::NArray::ShapeError, 'input array a must be 2-dimensional' if a.ndim != 2
|
|
1679
|
+
raise Numo::NArray::ShapeError, 'input array a must be square' if a.shape[0] != a.shape[1]
|
|
1680
|
+
|
|
1681
|
+
0.5 * (expm(a) - expm(-a))
|
|
1682
|
+
end
|
|
1683
|
+
|
|
1684
|
+
# Computes the matrix hyperbolic cosine using the matrix exponential.
|
|
1685
|
+
#
|
|
1686
|
+
# @param a [Numo::NArray] The n-by-n square matrix.
|
|
1687
|
+
# @return [Numo::NArray] The matrix hyperbolic cosine of `a`.
|
|
1688
|
+
def coshm(a)
|
|
1689
|
+
raise Numo::NArray::ShapeError, 'input array a must be 2-dimensional' if a.ndim != 2
|
|
1690
|
+
raise Numo::NArray::ShapeError, 'input array a must be square' if a.shape[0] != a.shape[1]
|
|
1691
|
+
|
|
1692
|
+
0.5 * (expm(a) + expm(-a))
|
|
1693
|
+
end
|
|
1694
|
+
|
|
1695
|
+
# Computes the matrix hyperbolic tangent.
|
|
1696
|
+
#
|
|
1697
|
+
# @param a [Numo::NArray] The n-by-n square matrix.
|
|
1698
|
+
# @return [Numo::NArray] The matrix hyperbolic tangent of `a`.
|
|
1699
|
+
def tanhm(a)
|
|
1700
|
+
raise Numo::NArray::ShapeError, 'input array a must be 2-dimensional' if a.ndim != 2
|
|
1701
|
+
raise Numo::NArray::ShapeError, 'input array a must be square' if a.shape[0] != a.shape[1]
|
|
1702
|
+
|
|
1703
|
+
a_sinh = sinhm(a)
|
|
1704
|
+
a_cosh = coshm(a)
|
|
1705
|
+
a_sinh.dot(Numo::Linalg.inv(a_cosh))
|
|
1706
|
+
end
|
|
1707
|
+
|
|
1616
1708
|
# Computes the inverse of a matrix using its LU decomposition.
|
|
1617
1709
|
#
|
|
1618
1710
|
# @param lu [Numo::NArray] The LU decomposition of the n-by-n matrix `A`.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: numo-linalg-alt
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- yoshoku
|
|
@@ -56,6 +56,8 @@ files:
|
|
|
56
56
|
- ext/numo/linalg/lapack/gees.h
|
|
57
57
|
- ext/numo/linalg/lapack/geev.c
|
|
58
58
|
- ext/numo/linalg/lapack/geev.h
|
|
59
|
+
- ext/numo/linalg/lapack/gehrd.c
|
|
60
|
+
- ext/numo/linalg/lapack/gehrd.h
|
|
59
61
|
- ext/numo/linalg/lapack/gelsd.c
|
|
60
62
|
- ext/numo/linalg/lapack/gelsd.h
|
|
61
63
|
- ext/numo/linalg/lapack/geqrf.c
|
|
@@ -92,6 +94,8 @@ files:
|
|
|
92
94
|
- ext/numo/linalg/lapack/hetrf.h
|
|
93
95
|
- ext/numo/linalg/lapack/lange.c
|
|
94
96
|
- ext/numo/linalg/lapack/lange.h
|
|
97
|
+
- ext/numo/linalg/lapack/orghr.c
|
|
98
|
+
- ext/numo/linalg/lapack/orghr.h
|
|
95
99
|
- ext/numo/linalg/lapack/orgqr.c
|
|
96
100
|
- ext/numo/linalg/lapack/orgqr.h
|
|
97
101
|
- ext/numo/linalg/lapack/orgrq.c
|
|
@@ -118,6 +122,8 @@ files:
|
|
|
118
122
|
- ext/numo/linalg/lapack/sytrf.h
|
|
119
123
|
- ext/numo/linalg/lapack/trtrs.c
|
|
120
124
|
- ext/numo/linalg/lapack/trtrs.h
|
|
125
|
+
- ext/numo/linalg/lapack/unghr.c
|
|
126
|
+
- ext/numo/linalg/lapack/unghr.h
|
|
121
127
|
- ext/numo/linalg/lapack/ungqr.c
|
|
122
128
|
- ext/numo/linalg/lapack/ungqr.h
|
|
123
129
|
- ext/numo/linalg/lapack/ungrq.c
|
|
@@ -136,7 +142,7 @@ metadata:
|
|
|
136
142
|
homepage_uri: https://github.com/yoshoku/numo-linalg-alt
|
|
137
143
|
source_code_uri: https://github.com/yoshoku/numo-linalg-alt
|
|
138
144
|
changelog_uri: https://github.com/yoshoku/numo-linalg-alt/blob/main/CHANGELOG.md
|
|
139
|
-
documentation_uri: https://gemdocs.org/gems/numo-linalg-alt/0.
|
|
145
|
+
documentation_uri: https://gemdocs.org/gems/numo-linalg-alt/0.5.0/
|
|
140
146
|
rubygems_mfa_required: 'true'
|
|
141
147
|
rdoc_options: []
|
|
142
148
|
require_paths:
|