numo-linalg-alt 0.7.2 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 074a79c2f0a7c299dfe6332f47440698030b04546274ea93bd76907bb5cf5af7
4
- data.tar.gz: 4539bee85382917fd99ef2744673b796d4234562f6573b1441f17a51ed90552b
3
+ metadata.gz: 2a0ef106744c6982f932536daa0215fd6f8a92fff153fdc576f7de636045e820
4
+ data.tar.gz: 04d3a8fe78f7f47e80d19ab3efca75c329fbe9a285d9b43e260965b96eec3cfa
5
5
  SHA512:
6
- metadata.gz: b219e82e41d7a6b29286d2450abe548a86cff6c2bb888d0ed9e3954ef6d22153db849995feb7fbb3673f68190eba932df63ba566fce66d7d15fdef1568c35f9d
7
- data.tar.gz: a69dbd9f8f6d695949a7220ef27e56ca5591d550a1799c813d5130dd9d0985602ce658b0afb4683afb7be9a49db50e0a5b30e1739fe4fc4ca34eb0da9c921fc5
6
+ metadata.gz: 782f5396ca2066b7b2b57f0ac6927675daec3e29b1544b24057b1218104363cb5f9265bee3f7d00b84ce8a1cbe42d1c8b78219341d6f9226101888361b462afd
7
+ data.tar.gz: 91f8471e9816bec70d8f05ebce014259d07f2a82e9989d872fc60878692cdf7a961c33024d35ba4e87446748772220bd4ccf3533f5b92cd5aa45a1f42d699822
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## [[0.8.0](https://github.com/yoshoku/numo-linalg-alt/compare/v0.7.2...v0.8.0)] - 2026-02-06
2
+
3
+ - relax numo-narray-alt version constraint to >= 0.9.10, < 0.11.0.
4
+ - add `diagsvd` module function to Numo::Linalg.
5
+ - add `cholesky_banded` and `cho_solve_banded` module functions to Numo::Linalg.
6
+ - add `solve_banded` and `solveh_banded` module functions to Numo::Linalg.
7
+
1
8
  ## [[0.7.2](https://github.com/yoshoku/numo-linalg-alt/compare/v0.7.1...v0.7.2)] - 2026-01-16
2
9
 
3
10
  - bump OpenBLAS from 0.3.30 to 0.3.31.
@@ -0,0 +1,92 @@
1
+ #include "gbsv.h"
2
+
3
+ struct _gbsv_option {
4
+ int matrix_layout;
5
+ int kl;
6
+ int ku;
7
+ };
8
+
9
+ #define DEF_LINALG_FUNC(tDType, tNAryClass, fLapackFunc) \
10
+ static void _iter_##fLapackFunc(na_loop_t* const lp) { \
11
+ tDType* ab = (tDType*)NDL_PTR(lp, 0); \
12
+ tDType* b = (tDType*)NDL_PTR(lp, 1); \
13
+ int* ipiv = (int*)NDL_PTR(lp, 2); \
14
+ int* info = (int*)NDL_PTR(lp, 3); \
15
+ struct _gbsv_option* opt = (struct _gbsv_option*)(lp->opt_ptr); \
16
+ const lapack_int n = (lapack_int)NDL_SHAPE(lp, 0)[1]; \
17
+ const lapack_int nrhs = lp->args[1].ndim == 1 ? 1 : (lapack_int)NDL_SHAPE(lp, 1)[1]; \
18
+ const lapack_int ldab = n; \
19
+ const lapack_int ldb = nrhs; \
20
+ const lapack_int i = LAPACKE_##fLapackFunc( \
21
+ opt->matrix_layout, n, opt->kl, opt->ku, nrhs, ab, ldab, ipiv, b, ldb \
22
+ ); \
23
+ *info = (int)i; \
24
+ } \
25
+ \
26
+ static VALUE _linalg_lapack_##fLapackFunc(int argc, VALUE* argv, VALUE self) { \
27
+ VALUE ab_vnary = Qnil; \
28
+ VALUE b_vnary = Qnil; \
29
+ VALUE kw_args = Qnil; \
30
+ rb_scan_args(argc, argv, "2:", &ab_vnary, &b_vnary, &kw_args); \
31
+ ID kw_table[3] = { rb_intern("kl"), rb_intern("ku"), rb_intern("order") }; \
32
+ VALUE kw_values[3] = { Qundef, Qundef, Qundef }; \
33
+ rb_get_kwargs(kw_args, kw_table, 2, 1, kw_values); \
34
+ const int kl = NUM2INT(kw_values[0]); \
35
+ const int ku = NUM2INT(kw_values[1]); \
36
+ const int matrix_layout = \
37
+ kw_values[2] != Qundef ? get_matrix_layout(kw_values[2]) : LAPACK_ROW_MAJOR; \
38
+ \
39
+ if (CLASS_OF(ab_vnary) != tNAryClass) { \
40
+ ab_vnary = rb_funcall(tNAryClass, rb_intern("cast"), 1, ab_vnary); \
41
+ } \
42
+ if (!RTEST(nary_check_contiguous(ab_vnary))) { \
43
+ ab_vnary = nary_dup(ab_vnary); \
44
+ } \
45
+ if (CLASS_OF(b_vnary) != tNAryClass) { \
46
+ b_vnary = rb_funcall(tNAryClass, rb_intern("cast"), 1, b_vnary); \
47
+ } \
48
+ if (!RTEST(nary_check_contiguous(b_vnary))) { \
49
+ b_vnary = nary_dup(b_vnary); \
50
+ } \
51
+ \
52
+ narray_t* ab_nary = NULL; \
53
+ narray_t* b_nary = NULL; \
54
+ GetNArray(ab_vnary, ab_nary); \
55
+ GetNArray(b_vnary, b_nary); \
56
+ const int ab_n_dims = NA_NDIM(ab_nary); \
57
+ const int b_n_dims = NA_NDIM(b_nary); \
58
+ if (ab_n_dims != 2) { \
59
+ rb_raise(rb_eArgError, "input array ab must be 2-dimensional"); \
60
+ return Qnil; \
61
+ } \
62
+ if (b_n_dims != 1 && b_n_dims != 2) { \
63
+ rb_raise(rb_eArgError, "input array b must be 1- or 2-dimensional"); \
64
+ return Qnil; \
65
+ } \
66
+ \
67
+ size_t shape[1] = { NA_SHAPE(ab_nary)[1] }; \
68
+ ndfunc_arg_in_t ain[2] = { { OVERWRITE, 2 }, { OVERWRITE, b_n_dims } }; \
69
+ ndfunc_arg_out_t aout[2] = { { numo_cInt32, 1, shape }, { numo_cInt32, 0 } }; \
70
+ ndfunc_t ndf = { _iter_##fLapackFunc, NO_LOOP | NDF_EXTRACT, 2, 2, ain, aout }; \
71
+ struct _gbsv_option opt = { matrix_layout, kl, ku }; \
72
+ VALUE res = na_ndloop3(&ndf, &opt, 2, ab_vnary, b_vnary); \
73
+ VALUE ret = rb_ary_concat(rb_assoc_new(ab_vnary, b_vnary), res); \
74
+ \
75
+ RB_GC_GUARD(ab_vnary); \
76
+ RB_GC_GUARD(b_vnary); \
77
+ return ret; \
78
+ }
79
+
80
+ DEF_LINALG_FUNC(double, numo_cDFloat, dgbsv)
81
+ DEF_LINALG_FUNC(float, numo_cSFloat, sgbsv)
82
+ DEF_LINALG_FUNC(lapack_complex_double, numo_cDComplex, zgbsv)
83
+ DEF_LINALG_FUNC(lapack_complex_float, numo_cSComplex, cgbsv)
84
+
85
+ #undef DEF_LINALG_FUNC
86
+
87
+ void define_linalg_lapack_gbsv(VALUE mLapack) {
88
+ rb_define_module_function(mLapack, "dgbsv", _linalg_lapack_dgbsv, -1);
89
+ rb_define_module_function(mLapack, "sgbsv", _linalg_lapack_sgbsv, -1);
90
+ rb_define_module_function(mLapack, "zgbsv", _linalg_lapack_zgbsv, -1);
91
+ rb_define_module_function(mLapack, "cgbsv", _linalg_lapack_cgbsv, -1);
92
+ }
@@ -0,0 +1,15 @@
1
+ #ifndef NUMO_LINALG_ALT_LAPACK_GBSV_H
2
+ #define NUMO_LINALG_ALT_LAPACK_GBSV_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 "lapack_util.h"
12
+
13
+ void define_linalg_lapack_gbsv(VALUE mLapack);
14
+
15
+ #endif /* NUMO_LINALG_ALT_LAPACK_GBSV_H */
@@ -0,0 +1,88 @@
1
+ #include "pbsv.h"
2
+
3
+ struct _pbsv_option {
4
+ int matrix_layout;
5
+ char uplo;
6
+ };
7
+
8
+ #define DEF_LINALG_FUNC(tDType, tNAryClass, fLapackFunc) \
9
+ static void _iter_##fLapackFunc(na_loop_t* const lp) { \
10
+ tDType* ab = (tDType*)NDL_PTR(lp, 0); \
11
+ tDType* b = (tDType*)NDL_PTR(lp, 1); \
12
+ int* info = (int*)NDL_PTR(lp, 2); \
13
+ struct _pbsv_option* opt = (struct _pbsv_option*)(lp->opt_ptr); \
14
+ const lapack_int n = (lapack_int)NDL_SHAPE(lp, 0)[1]; \
15
+ const lapack_int kd = (lapack_int)NDL_SHAPE(lp, 0)[0] - 1; \
16
+ const lapack_int nrhs = lp->args[1].ndim == 1 ? 1 : (lapack_int)NDL_SHAPE(lp, 1)[1]; \
17
+ const lapack_int ldab = n; \
18
+ const lapack_int ldb = nrhs; \
19
+ const lapack_int i = \
20
+ LAPACKE_##fLapackFunc(opt->matrix_layout, opt->uplo, n, kd, nrhs, ab, ldab, b, ldb); \
21
+ *info = (int)i; \
22
+ } \
23
+ \
24
+ static VALUE _linalg_lapack_##fLapackFunc(int argc, VALUE* argv, VALUE self) { \
25
+ VALUE ab_vnary = Qnil; \
26
+ VALUE b_vnary = Qnil; \
27
+ VALUE kw_args = Qnil; \
28
+ rb_scan_args(argc, argv, "2:", &ab_vnary, &b_vnary, &kw_args); \
29
+ ID kw_table[2] = { rb_intern("order"), rb_intern("uplo") }; \
30
+ VALUE kw_values[2] = { Qundef, Qundef }; \
31
+ rb_get_kwargs(kw_args, kw_table, 0, 2, kw_values); \
32
+ const int matrix_layout = \
33
+ kw_values[0] != Qundef ? get_matrix_layout(kw_values[0]) : LAPACK_ROW_MAJOR; \
34
+ const char uplo = kw_values[1] != Qundef ? get_uplo(kw_values[1]) : 'U'; \
35
+ \
36
+ if (CLASS_OF(ab_vnary) != tNAryClass) { \
37
+ ab_vnary = rb_funcall(tNAryClass, rb_intern("cast"), 1, ab_vnary); \
38
+ } \
39
+ if (!RTEST(nary_check_contiguous(ab_vnary))) { \
40
+ ab_vnary = nary_dup(ab_vnary); \
41
+ } \
42
+ if (CLASS_OF(b_vnary) != tNAryClass) { \
43
+ b_vnary = rb_funcall(tNAryClass, rb_intern("cast"), 1, b_vnary); \
44
+ } \
45
+ if (!RTEST(nary_check_contiguous(b_vnary))) { \
46
+ b_vnary = nary_dup(b_vnary); \
47
+ } \
48
+ \
49
+ narray_t* ab_nary = NULL; \
50
+ narray_t* b_nary = NULL; \
51
+ GetNArray(ab_vnary, ab_nary); \
52
+ GetNArray(b_vnary, b_nary); \
53
+ const int ab_n_dims = NA_NDIM(ab_nary); \
54
+ const int b_n_dims = NA_NDIM(b_nary); \
55
+ if (ab_n_dims != 2) { \
56
+ rb_raise(rb_eArgError, "input array ab must be 2-dimensional"); \
57
+ return Qnil; \
58
+ } \
59
+ if (b_n_dims != 1 && b_n_dims != 2) { \
60
+ rb_raise(rb_eArgError, "input array b must be 1- or 2-dimensional"); \
61
+ return Qnil; \
62
+ } \
63
+ \
64
+ ndfunc_arg_in_t ain[2] = { { OVERWRITE, 2 }, { OVERWRITE, b_n_dims } }; \
65
+ ndfunc_arg_out_t aout[1] = { { numo_cInt32, 0 } }; \
66
+ ndfunc_t ndf = { _iter_##fLapackFunc, NO_LOOP | NDF_EXTRACT, 2, 1, ain, aout }; \
67
+ struct _pbsv_option opt = { matrix_layout, uplo }; \
68
+ VALUE res = na_ndloop3(&ndf, &opt, 2, ab_vnary, b_vnary); \
69
+ VALUE ret = rb_ary_new3(2, b_vnary, res); \
70
+ \
71
+ RB_GC_GUARD(ab_vnary); \
72
+ RB_GC_GUARD(b_vnary); \
73
+ return ret; \
74
+ }
75
+
76
+ DEF_LINALG_FUNC(double, numo_cDFloat, dpbsv)
77
+ DEF_LINALG_FUNC(float, numo_cSFloat, spbsv)
78
+ DEF_LINALG_FUNC(lapack_complex_double, numo_cDComplex, zpbsv)
79
+ DEF_LINALG_FUNC(lapack_complex_float, numo_cSComplex, cpbsv)
80
+
81
+ #undef DEF_LINALG_FUNC
82
+
83
+ void define_linalg_lapack_pbsv(VALUE mLapack) {
84
+ rb_define_module_function(mLapack, "dpbsv", _linalg_lapack_dpbsv, -1);
85
+ rb_define_module_function(mLapack, "spbsv", _linalg_lapack_spbsv, -1);
86
+ rb_define_module_function(mLapack, "zpbsv", _linalg_lapack_zpbsv, -1);
87
+ rb_define_module_function(mLapack, "cpbsv", _linalg_lapack_cpbsv, -1);
88
+ }
@@ -0,0 +1,15 @@
1
+ #ifndef NUMO_LINALG_ALT_LAPACK_PBSV_H
2
+ #define NUMO_LINALG_ALT_LAPACK_PBSV_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 "lapack_util.h"
12
+
13
+ void define_linalg_lapack_pbsv(VALUE mLapack);
14
+
15
+ #endif /* NUMO_LINALG_ALT_LAPACK_PBSV_H */
@@ -0,0 +1,68 @@
1
+ #include "pbtrf.h"
2
+
3
+ struct _pbtrf_option {
4
+ int matrix_layout;
5
+ char uplo;
6
+ };
7
+
8
+ #define DEF_LINALG_FUNC(tDType, tNAryClass, fLapackFunc) \
9
+ static void _iter_##fLapackFunc(na_loop_t* const lp) { \
10
+ tDType* ab = (tDType*)NDL_PTR(lp, 0); \
11
+ int* info = (int*)NDL_PTR(lp, 1); \
12
+ struct _pbtrf_option* opt = (struct _pbtrf_option*)(lp->opt_ptr); \
13
+ const lapack_int n = (lapack_int)NDL_SHAPE(lp, 0)[1]; \
14
+ const lapack_int kd = (lapack_int)NDL_SHAPE(lp, 0)[0] - 1; \
15
+ const lapack_int ldab = (lapack_int)NDL_SHAPE(lp, 0)[1]; \
16
+ const lapack_int i = \
17
+ LAPACKE_##fLapackFunc(opt->matrix_layout, opt->uplo, n, kd, ab, ldab); \
18
+ *info = (int)i; \
19
+ } \
20
+ \
21
+ static VALUE _linalg_lapack_##fLapackFunc(int argc, VALUE* argv, VALUE self) { \
22
+ VALUE ab_vnary = Qnil; \
23
+ VALUE kw_args = Qnil; \
24
+ rb_scan_args(argc, argv, "1:", &ab_vnary, &kw_args); \
25
+ ID kw_table[2] = { rb_intern("order"), rb_intern("uplo") }; \
26
+ VALUE kw_values[2] = { Qundef, Qundef }; \
27
+ rb_get_kwargs(kw_args, kw_table, 0, 2, kw_values); \
28
+ const int matrix_layout = \
29
+ kw_values[0] != Qundef ? get_matrix_layout(kw_values[0]) : LAPACK_ROW_MAJOR; \
30
+ const char uplo = kw_values[1] != Qundef ? get_uplo(kw_values[1]) : 'U'; \
31
+ \
32
+ if (CLASS_OF(ab_vnary) != tNAryClass) { \
33
+ ab_vnary = rb_funcall(tNAryClass, rb_intern("cast"), 1, ab_vnary); \
34
+ } \
35
+ if (!RTEST(nary_check_contiguous(ab_vnary))) { \
36
+ ab_vnary = nary_dup(ab_vnary); \
37
+ } \
38
+ \
39
+ narray_t* ab_nary = NULL; \
40
+ GetNArray(ab_vnary, ab_nary); \
41
+ if (NA_NDIM(ab_nary) != 2) { \
42
+ rb_raise(rb_eArgError, "input array a must be 2-dimensional"); \
43
+ return Qnil; \
44
+ } \
45
+ ndfunc_arg_in_t ain[1] = { { OVERWRITE, 2 } }; \
46
+ ndfunc_arg_out_t aout[1] = { { numo_cInt32, 0 } }; \
47
+ ndfunc_t ndf = { _iter_##fLapackFunc, NO_LOOP | NDF_EXTRACT, 1, 1, ain, aout }; \
48
+ struct _pbtrf_option opt = { matrix_layout, uplo }; \
49
+ VALUE res = na_ndloop3(&ndf, &opt, 1, ab_vnary); \
50
+ VALUE ret = rb_ary_new3(2, ab_vnary, res); \
51
+ \
52
+ RB_GC_GUARD(ab_vnary); \
53
+ return ret; \
54
+ }
55
+
56
+ DEF_LINALG_FUNC(double, numo_cDFloat, dpbtrf)
57
+ DEF_LINALG_FUNC(float, numo_cSFloat, spbtrf)
58
+ DEF_LINALG_FUNC(lapack_complex_double, numo_cDComplex, zpbtrf)
59
+ DEF_LINALG_FUNC(lapack_complex_float, numo_cSComplex, cpbtrf)
60
+
61
+ #undef DEF_LINALG_FUNC
62
+
63
+ void define_linalg_lapack_pbtrf(VALUE mLapack) {
64
+ rb_define_module_function(mLapack, "dpbtrf", _linalg_lapack_dpbtrf, -1);
65
+ rb_define_module_function(mLapack, "spbtrf", _linalg_lapack_spbtrf, -1);
66
+ rb_define_module_function(mLapack, "zpbtrf", _linalg_lapack_zpbtrf, -1);
67
+ rb_define_module_function(mLapack, "cpbtrf", _linalg_lapack_cpbtrf, -1);
68
+ }
@@ -0,0 +1,15 @@
1
+ #ifndef NUMO_LINALG_ALT_LAPACK_PBTRF_H
2
+ #define NUMO_LINALG_ALT_LAPACK_PBTRF_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 "lapack_util.h"
12
+
13
+ void define_linalg_lapack_pbtrf(VALUE mLapack);
14
+
15
+ #endif /* NUMO_LINALG_ALT_LAPACK_PBTRF_H */
@@ -0,0 +1,93 @@
1
+ #include "pbtrs.h"
2
+
3
+ struct _pbtrs_option {
4
+ int matrix_layout;
5
+ char uplo;
6
+ };
7
+
8
+ #define DEF_LINALG_FUNC(tDType, tNAryClass, fLapackFunc) \
9
+ static void _iter_##fLapackFunc(na_loop_t* const lp) { \
10
+ tDType* ab = (tDType*)NDL_PTR(lp, 0); \
11
+ tDType* b = (tDType*)NDL_PTR(lp, 1); \
12
+ int* info = (int*)NDL_PTR(lp, 2); \
13
+ struct _pbtrs_option* opt = (struct _pbtrs_option*)(lp->opt_ptr); \
14
+ const lapack_int n = (lapack_int)NDL_SHAPE(lp, 0)[1]; \
15
+ const lapack_int kd = (lapack_int)NDL_SHAPE(lp, 0)[0] - 1; \
16
+ const lapack_int nrhs = lp->args[1].ndim == 1 ? 1 : (lapack_int)NDL_SHAPE(lp, 1)[1]; \
17
+ const lapack_int ldab = n; \
18
+ const lapack_int ldb = nrhs; \
19
+ const lapack_int i = \
20
+ LAPACKE_##fLapackFunc(opt->matrix_layout, opt->uplo, n, kd, nrhs, ab, ldab, b, ldb); \
21
+ *info = (int)i; \
22
+ } \
23
+ \
24
+ static VALUE _linalg_lapack_##fLapackFunc(int argc, VALUE* argv, VALUE self) { \
25
+ VALUE a_vnary = Qnil; \
26
+ VALUE b_vnary = Qnil; \
27
+ VALUE kw_args = Qnil; \
28
+ rb_scan_args(argc, argv, "2:", &a_vnary, &b_vnary, &kw_args); \
29
+ ID kw_table[2] = { rb_intern("order"), rb_intern("uplo") }; \
30
+ VALUE kw_values[2] = { Qundef, Qundef }; \
31
+ rb_get_kwargs(kw_args, kw_table, 0, 2, kw_values); \
32
+ const int matrix_layout = \
33
+ kw_values[0] != Qundef ? get_matrix_layout(kw_values[0]) : LAPACK_ROW_MAJOR; \
34
+ const char uplo = kw_values[1] != Qundef ? get_uplo(kw_values[1]) : 'U'; \
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(b_vnary) != tNAryClass) { \
43
+ b_vnary = rb_funcall(tNAryClass, rb_intern("cast"), 1, b_vnary); \
44
+ } \
45
+ if (!RTEST(nary_check_contiguous(b_vnary))) { \
46
+ b_vnary = nary_dup(b_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* b_nary = NULL; \
56
+ GetNArray(b_vnary, b_nary); \
57
+ const int b_n_dims = NA_NDIM(b_nary); \
58
+ if (b_n_dims != 1 && b_n_dims != 2) { \
59
+ rb_raise(rb_eArgError, "input array b must be 1- or 2-dimensional"); \
60
+ return Qnil; \
61
+ } \
62
+ \
63
+ lapack_int n = (lapack_int)NA_SHAPE(a_nary)[1]; \
64
+ lapack_int nb = (lapack_int)NA_SHAPE(b_nary)[0]; \
65
+ if (n != nb) { \
66
+ rb_raise(nary_eShapeError, "shape1[0](=%d) != shape2[0](=%d)", n, nb); \
67
+ } \
68
+ \
69
+ ndfunc_arg_in_t ain[2] = { { tNAryClass, 2 }, { OVERWRITE, b_n_dims } }; \
70
+ ndfunc_arg_out_t aout[1] = { { numo_cInt32, 0 } }; \
71
+ ndfunc_t ndf = { _iter_##fLapackFunc, NO_LOOP | NDF_EXTRACT, 2, 1, ain, aout }; \
72
+ struct _pbtrs_option opt = { matrix_layout, uplo }; \
73
+ VALUE res = na_ndloop3(&ndf, &opt, 2, a_vnary, b_vnary); \
74
+ VALUE ret = rb_ary_new3(2, b_vnary, res); \
75
+ \
76
+ RB_GC_GUARD(a_vnary); \
77
+ RB_GC_GUARD(b_vnary); \
78
+ return ret; \
79
+ }
80
+
81
+ DEF_LINALG_FUNC(double, numo_cDFloat, dpbtrs)
82
+ DEF_LINALG_FUNC(float, numo_cSFloat, spbtrs)
83
+ DEF_LINALG_FUNC(lapack_complex_double, numo_cDComplex, zpbtrs)
84
+ DEF_LINALG_FUNC(lapack_complex_float, numo_cSComplex, cpbtrs)
85
+
86
+ #undef DEF_LINALG_FUNC
87
+
88
+ void define_linalg_lapack_pbtrs(VALUE mLapack) {
89
+ rb_define_module_function(mLapack, "dpbtrs", _linalg_lapack_dpbtrs, -1);
90
+ rb_define_module_function(mLapack, "spbtrs", _linalg_lapack_spbtrs, -1);
91
+ rb_define_module_function(mLapack, "zpbtrs", _linalg_lapack_zpbtrs, -1);
92
+ rb_define_module_function(mLapack, "cpbtrs", _linalg_lapack_cpbtrs, -1);
93
+ }
@@ -0,0 +1,15 @@
1
+ #ifndef NUMO_LINALG_ALT_LAPACK_PBTRS_H
2
+ #define NUMO_LINALG_ALT_LAPACK_PBTRS_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 "lapack_util.h"
12
+
13
+ void define_linalg_lapack_pbtrs(VALUE mLapack);
14
+
15
+ #endif
@@ -277,10 +277,14 @@ void Init_linalg(void) {
277
277
  define_linalg_lapack_getrf(rb_mLinalgLapack);
278
278
  define_linalg_lapack_getri(rb_mLinalgLapack);
279
279
  define_linalg_lapack_getrs(rb_mLinalgLapack);
280
+ define_linalg_lapack_gbsv(rb_mLinalgLapack);
280
281
  define_linalg_lapack_trtrs(rb_mLinalgLapack);
282
+ define_linalg_lapack_pbsv(rb_mLinalgLapack);
281
283
  define_linalg_lapack_potrf(rb_mLinalgLapack);
282
284
  define_linalg_lapack_potri(rb_mLinalgLapack);
283
285
  define_linalg_lapack_potrs(rb_mLinalgLapack);
286
+ define_linalg_lapack_pbtrf(rb_mLinalgLapack);
287
+ define_linalg_lapack_pbtrs(rb_mLinalgLapack);
284
288
  define_linalg_lapack_syev(rb_mLinalgLapack);
285
289
  define_linalg_lapack_heev(rb_mLinalgLapack);
286
290
  define_linalg_lapack_syevd(rb_mLinalgLapack);
@@ -59,6 +59,7 @@
59
59
  #include "blas/gemv.h"
60
60
  #include "blas/nrm2.h"
61
61
 
62
+ #include "lapack/gbsv.h"
62
63
  #include "lapack/gebal.h"
63
64
  #include "lapack/gees.h"
64
65
  #include "lapack/geev.h"
@@ -84,6 +85,9 @@
84
85
  #include "lapack/orghr.h"
85
86
  #include "lapack/orgqr.h"
86
87
  #include "lapack/orgrq.h"
88
+ #include "lapack/pbsv.h"
89
+ #include "lapack/pbtrf.h"
90
+ #include "lapack/pbtrs.h"
87
91
  #include "lapack/potrf.h"
88
92
  #include "lapack/potri.h"
89
93
  #include "lapack/potrs.h"
@@ -5,6 +5,6 @@ module Numo
5
5
  # Numo::Linalg Alternative (numo-linalg-alt) is an alternative to Numo::Linalg.
6
6
  module Linalg
7
7
  # The version of numo-linalg-alt you install.
8
- VERSION = '0.7.2'
8
+ VERSION = '0.8.0'
9
9
  end
10
10
  end
data/lib/numo/linalg.rb CHANGED
@@ -318,6 +318,29 @@ module Numo
318
318
  end
319
319
  end
320
320
 
321
+ # Computes the Cholesky decomposition of a banded symmetric / Hermitian positive-definite matrix.
322
+ #
323
+ # @param a [Numo::NArray] The banded matrix.
324
+ # @param uplo [String] Is the matrix form upper or lower ('U' or 'L').
325
+ # @return [Numo::NArray] The Cholesky factor of the banded matrix.
326
+ def cholesky_banded(a, uplo: 'U')
327
+ raise Numo::NArray::ShapeError, 'input array a must be 2-dimensional' if a.ndim != 2
328
+
329
+ bchr = blas_char(a)
330
+ raise ArgumentError, "invalid array type: #{a.class}" if bchr == 'n'
331
+
332
+ fnc = :"#{bchr}pbtrf"
333
+ c, info = Numo::Linalg::Lapack.send(fnc, a.dup, uplo: uplo)
334
+ raise LapackError, "the #{-info}-th argument of potrs had illegal value" if info.negative?
335
+
336
+ if info.positive?
337
+ raise LapackError, "the leading principal minor of order #{info} is not positive, " \
338
+ 'and the factorization could not be completed.'
339
+ end
340
+
341
+ c
342
+ end
343
+
321
344
  # Solves linear equation `A * x = b` or `A * X = B` for `x` with the Cholesky factorization of `A`.
322
345
  #
323
346
  # @example
@@ -352,6 +375,41 @@ module Numo
352
375
  x
353
376
  end
354
377
 
378
+ # Solves linear equation `A * x = b` or `A * X = B` for `x` with the Cholesky factorization of banded matrix `A`.
379
+ #
380
+ # @example
381
+ # require 'numo/linalg'
382
+ #
383
+ # a = Numo::DFloat.new(4, 4).rand - 0.5
384
+ # a = a.dot(a.transpose)
385
+ # a = a.tril(1) * a.triu(-1)
386
+ # ab = Numo::DFloat.zeros(2, 4)
387
+ # ab[0, 1...] = a[a.diag_indices(1)]
388
+ # ab[1, true] = a[a.diag_indices]
389
+ # c = Numo::Linalg.cholesky_banded(ab)
390
+ # b = Numo::DFloat.new(4, 2).rand
391
+ # x = Numo::Linalg.cho_solve_banded(c, b)
392
+ # pp (b - a.dot(x)).abs.max
393
+ # # => 1.1102230246251565e-16
394
+ #
395
+ # @param ab [Numo::NArray] The m-by-n banded cholesky factor.
396
+ # @param b [Numo::NArray] The n right-hand side vector, or n-by-nrhs right-hand side matrix.
397
+ # @param uplo [String] Whether to compute the upper- or lower-triangular Cholesky factor ('U' or 'L').
398
+ # @return [Numo::NArray] The solution vector or matrix `X`.
399
+ def cho_solve_banded(ab, b, uplo: 'U')
400
+ raise Numo::NArray::ShapeError, 'input array a must be 2-dimensional' if ab.ndim != 2
401
+ raise Numo::NArray::ShapeError, "incompatible dimensions: ab.shape[1] = #{ab.shape[1]} != b.shape[0] = #{b.shape[0]}" if ab.shape[1] != b.shape[0]
402
+
403
+ bchr = blas_char(ab, b)
404
+ raise ArgumentError, "invalid array type: #{ab.class}" if bchr == 'n'
405
+
406
+ fnc = :"#{bchr}pbtrs"
407
+ x, info = Numo::Linalg::Lapack.send(fnc, ab, b.dup, uplo: uplo)
408
+ raise LapackError, "the #{-info}-th argument of potrs had illegal value" if info.negative?
409
+
410
+ x
411
+ end
412
+
355
413
  # Computes the determinant of matrix.
356
414
  #
357
415
  # @example
@@ -906,6 +964,127 @@ module Numo
906
964
  x
907
965
  end
908
966
 
967
+ # Solves linear equation `A * x = b` or `A * X = B` for `x` assuming `A` is a banded matrix.
968
+ #
969
+ # @example
970
+ # require 'numo/linalg'
971
+ #
972
+ # # Banded matrix A:
973
+ # # [4 2 1 0 0]
974
+ # # [1 5 2 1 0]
975
+ # # [0 1 6 2 1]
976
+ # # [0 0 1 7 2]
977
+ # # [0 0 0 1 8]
978
+ # #
979
+ # ab = Numo::DFloat[[0, 0, 1, 1, 1],
980
+ # [0, 2, 2, 2, 2],
981
+ # [4, 5, 6, 7, 8],
982
+ # [1, 1, 1, 1, 0]]
983
+ #
984
+ # b = Numo::DFloat[1, 2, 3, 4, 5]
985
+ #
986
+ # x = Numo::Linalg.solve_banded([1, 2], ab, b)
987
+ # pp x
988
+ # # =>
989
+ # # Numo::DFloat#shape=[5]
990
+ # # [0.0832055, 0.211273, 0.244632, 0.371166, 0.578604]
991
+ #
992
+ # a = ab[2, true].diag + ab[0, 2...].diag(2) + ab[1, 1...].diag(1) + ab[3, 0...-1].diag(-1)
993
+ # pp a
994
+ # # =>
995
+ # # Numo::DFloat#shape=[5,5]
996
+ # # [[4, 2, 1, 0, 0],
997
+ # # [1, 5, 2, 1, 0],
998
+ # # [0, 1, 6, 2, 1],
999
+ # # [0, 0, 1, 7, 2],
1000
+ # # [0, 0, 0, 1, 8]]
1001
+ # pp a.dot(x)
1002
+ # # =>
1003
+ # # Numo::DFloat#shape=[5]
1004
+ # # [1, 2, 3, 4, 5]
1005
+ #
1006
+ # @param l_u [Array<Integer>] The number of sub-diagonals and super-diagonals of the banded matrix `A`.
1007
+ # @param ab [Numo::NArray] The (l + u + 1)-by-n array representing the banded matrix `A`.
1008
+ # @param b [Numo::NArray] The n right-hand side vector, or n-by-nrhs right-hand side matrix.
1009
+ # @return [Numo::NArray] The solution vector / matrix `X`.
1010
+ def solve_banded(l_u, ab, b)
1011
+ raise Numo::NArray::ShapeError, 'input array a must be 2-dimensional' if ab.ndim != 2
1012
+
1013
+ unless l_u.is_a?(Array) && l_u.size == 2 && l_u.all?(Integer)
1014
+ raise ArgumentError, 'l_u must be an array of two integers'
1015
+ end
1016
+
1017
+ kl, ku = l_u
1018
+ raise Numo::NArray::ShapeError, "ab.shape[0] must be equal to l + u + 1: #{ab.shape[0]} != #{kl} + #{ku} + 1" if ab.shape[0] != kl + ku + 1
1019
+
1020
+ bchr = blas_char(ab, b)
1021
+ raise ArgumentError, "invalid array type: #{a.class}, #{b.class}" if bchr == 'n'
1022
+
1023
+ gbsv = :"#{bchr}gbsv"
1024
+
1025
+ tmp = ab.class.zeros((2 * kl) + ku + 1, ab.shape[1])
1026
+ tmp[kl..., true] = ab
1027
+ _, x, _, info = Numo::Linalg::Lapack.send(gbsv, tmp, b.dup, kl: kl, ku: ku)
1028
+ raise LapackError, "wrong value is given to the #{-info}-th argument of #{gbsv} used internally" if info.negative?
1029
+ raise LapackError, 'the leading minor of the matrix is not positive definite' if info.positive?
1030
+
1031
+ x
1032
+ end
1033
+
1034
+ # Solves linear equation `A * x = b` or `A * X = B` for `x` assuming `A` is
1035
+ # a symmetric/Hermitian positive-definite banded matrix.
1036
+ #
1037
+ # @example
1038
+ # require 'numo/linalg'
1039
+ #
1040
+ # # Banded matrix A:
1041
+ # # [4 2 1 0 0]
1042
+ # # [2 5 2 1 0]
1043
+ # # [1 2 6 2 1]
1044
+ # # [0 1 2 7 2]
1045
+ # # [0 0 1 2 8]
1046
+ # #
1047
+ # # The banded representation ab for lower-banded form is:
1048
+ # ab = Numo::DFloat[[4, 5, 6, 7, 8],
1049
+ # [2, 2, 2, 2, 0],
1050
+ # [1, 1, 1, 0, 0]]
1051
+ # # The banded representation ab for upper-banded form is:
1052
+ # # ab = Numo::DFloat[[0, 0, 1, 1, 1],
1053
+ # # [0, 2, 2, 2, 2],
1054
+ # # [4, 5, 6, 7, 8]]
1055
+ # b = Numo::DFloat[1, 2, 3, 4, 5]
1056
+ #
1057
+ # x = Numo::Linalg.solveh_banded(ab, b, lower: true)
1058
+ # pp x
1059
+ # # =>
1060
+ # # Numo::DFloat#shape=[5]
1061
+ # # [0.0903361, 0.210084, 0.218487, 0.331933, 0.514706]
1062
+ #
1063
+ # a = ab[0, true].diag + ab[1, 0...-1].diag(1) + ab[2, 0...-2].diag(2) +
1064
+ # ab[1, 0...-1].diag(-1) + ab[2, 0...-2].diag(-2)
1065
+ # pp a.dot(x)
1066
+ # # => Numo::DFloat#shape=[5]
1067
+ # # [1, 2, 3, 4, 5]
1068
+ #
1069
+ # @param ab [Numo::NArray] The m-by-n array representing the banded matrix `A`.
1070
+ # @param b [Numo::NArray] The n right-hand side vector, or n-by-k right-hand side matrix.
1071
+ # @param lower [Boolean] The flag indicating whether to be in the lower-banded form.
1072
+ # @return [Numo::NArray] The solusion vector / matrix `X`.
1073
+ def solveh_banded(ab, b, lower: false)
1074
+ raise Numo::NArray::ShapeError, 'input array a must be 2-dimensional' if ab.ndim != 2
1075
+
1076
+ bchr = blas_char(ab, b)
1077
+ raise ArgumentError, "invalid array type: #{a.class}, #{b.class}" if bchr == 'n'
1078
+
1079
+ pbsv = :"#{bchr}pbsv"
1080
+ uplo = lower ? 'L' : 'U'
1081
+ x, info = Numo::Linalg::Lapack.send(pbsv, ab.dup, b.dup, uplo: uplo)
1082
+ raise LapackError, "wrong value is given to the #{info}-th argument of #{pbsv} used internally" if info.negative?
1083
+ raise LapackError, 'the leading minor of the matrix is not positive definite' if info.positive?
1084
+
1085
+ x
1086
+ end
1087
+
909
1088
  # Computes the Singular Value Decomposition (SVD) of a matrix: `A = U * S * V^T`
910
1089
  #
911
1090
  # @example
@@ -1053,6 +1232,45 @@ module Numo
1053
1232
  s
1054
1233
  end
1055
1234
 
1235
+ # Creates a diagonal matrix from the given singular values.
1236
+ #
1237
+ # @example
1238
+ # require 'numo/linalg'
1239
+ #
1240
+ # s = Numo::DFloat[4, 2, 1]
1241
+ # d = Numo::Linalg.diagsvd(s, 3, 4)
1242
+ # pp d
1243
+ # # =>
1244
+ # # Numo::DFloat#shape=[3,4]
1245
+ # # [[4, 0, 0, 0],
1246
+ # # [0, 2, 0, 0],
1247
+ # # [0, 0, 1, 0]]
1248
+ # d = Numo::Linalg.diagsvd(s, 4, 3)
1249
+ # pp d
1250
+ # # =>
1251
+ # # Numo::DFloat#shape=[4,3]
1252
+ # # [[4, 0, 0],
1253
+ # # [0, 2, 0],
1254
+ # # [0, 0, 1],
1255
+ # # [0, 0, 0]]
1256
+ #
1257
+ # @param s [Numo::NArray] The singular values.
1258
+ # @param m [Integer] The number of rows of the constructed matrix.
1259
+ # @param n [Integer] The number of columns of the constructed matrix.
1260
+ # @return [Numo::NArray] The m-by-n diagonal matrix with the singular values on the diagonal.
1261
+ def diagsvd(s, m, n)
1262
+ sz_s = s.size
1263
+ raise ArgumentError, "size of s must be equal to m or n: s.size=#{sz_s}, m=#{m}, n=#{n}" if sz_s != m && sz_s != n
1264
+
1265
+ mat = s.class.zeros(m, n)
1266
+ if sz_s == m
1267
+ mat[true, 0...m] = s.diag
1268
+ else
1269
+ mat[0...n, true] = s.diag
1270
+ end
1271
+ mat
1272
+ end
1273
+
1056
1274
  # Computes an orthonormal basis for the range of `A` using SVD.
1057
1275
  #
1058
1276
  # @example
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.7.2
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - yoshoku
@@ -13,16 +13,22 @@ dependencies:
13
13
  name: numo-narray-alt
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
- - - "~>"
16
+ - - ">="
17
17
  - !ruby/object:Gem::Version
18
18
  version: 0.9.10
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: 0.11.0
19
22
  type: :runtime
20
23
  prerelease: false
21
24
  version_requirements: !ruby/object:Gem::Requirement
22
25
  requirements:
23
- - - "~>"
26
+ - - ">="
24
27
  - !ruby/object:Gem::Version
25
28
  version: 0.9.10
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: 0.11.0
26
32
  description: |
27
33
  Numo::Linalg Alternative (numo-linalg-alt) is an alternative to Numo::Linalg.
28
34
  Unlike Numo::Linalg, numo-linalg-alt depends on Numo::NArray Alternative (numo-narray-alt).
@@ -53,6 +59,8 @@ files:
53
59
  - ext/numo/linalg/blas/nrm2.c
54
60
  - ext/numo/linalg/blas/nrm2.h
55
61
  - ext/numo/linalg/extconf.rb
62
+ - ext/numo/linalg/lapack/gbsv.c
63
+ - ext/numo/linalg/lapack/gbsv.h
56
64
  - ext/numo/linalg/lapack/gebal.c
57
65
  - ext/numo/linalg/lapack/gebal.h
58
66
  - ext/numo/linalg/lapack/gees.c
@@ -105,6 +113,12 @@ files:
105
113
  - ext/numo/linalg/lapack/orgqr.h
106
114
  - ext/numo/linalg/lapack/orgrq.c
107
115
  - ext/numo/linalg/lapack/orgrq.h
116
+ - ext/numo/linalg/lapack/pbsv.c
117
+ - ext/numo/linalg/lapack/pbsv.h
118
+ - ext/numo/linalg/lapack/pbtrf.c
119
+ - ext/numo/linalg/lapack/pbtrf.h
120
+ - ext/numo/linalg/lapack/pbtrs.c
121
+ - ext/numo/linalg/lapack/pbtrs.h
108
122
  - ext/numo/linalg/lapack/potrf.c
109
123
  - ext/numo/linalg/lapack/potrf.h
110
124
  - ext/numo/linalg/lapack/potri.c
@@ -145,7 +159,7 @@ metadata:
145
159
  homepage_uri: https://github.com/yoshoku/numo-linalg-alt
146
160
  source_code_uri: https://github.com/yoshoku/numo-linalg-alt
147
161
  changelog_uri: https://github.com/yoshoku/numo-linalg-alt/blob/main/CHANGELOG.md
148
- documentation_uri: https://gemdocs.org/gems/numo-linalg-alt/0.7.2/
162
+ documentation_uri: https://gemdocs.org/gems/numo-linalg-alt/0.8.0/
149
163
  rubygems_mfa_required: 'true'
150
164
  rdoc_options: []
151
165
  require_paths: