numo-linalg-alt 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.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/CODE_OF_CONDUCT.md +84 -0
  4. data/LICENSE.txt +27 -0
  5. data/README.md +106 -0
  6. data/ext/numo/linalg/blas/dot.c +72 -0
  7. data/ext/numo/linalg/blas/dot.h +13 -0
  8. data/ext/numo/linalg/blas/dot_sub.c +71 -0
  9. data/ext/numo/linalg/blas/dot_sub.h +13 -0
  10. data/ext/numo/linalg/blas/gemm.c +184 -0
  11. data/ext/numo/linalg/blas/gemm.h +16 -0
  12. data/ext/numo/linalg/blas/gemv.c +161 -0
  13. data/ext/numo/linalg/blas/gemv.h +16 -0
  14. data/ext/numo/linalg/blas/nrm2.c +67 -0
  15. data/ext/numo/linalg/blas/nrm2.h +13 -0
  16. data/ext/numo/linalg/converter.c +67 -0
  17. data/ext/numo/linalg/converter.h +23 -0
  18. data/ext/numo/linalg/extconf.rb +99 -0
  19. data/ext/numo/linalg/lapack/geev.c +152 -0
  20. data/ext/numo/linalg/lapack/geev.h +15 -0
  21. data/ext/numo/linalg/lapack/gelsd.c +92 -0
  22. data/ext/numo/linalg/lapack/gelsd.h +15 -0
  23. data/ext/numo/linalg/lapack/geqrf.c +72 -0
  24. data/ext/numo/linalg/lapack/geqrf.h +15 -0
  25. data/ext/numo/linalg/lapack/gesdd.c +108 -0
  26. data/ext/numo/linalg/lapack/gesdd.h +15 -0
  27. data/ext/numo/linalg/lapack/gesv.c +99 -0
  28. data/ext/numo/linalg/lapack/gesv.h +15 -0
  29. data/ext/numo/linalg/lapack/gesvd.c +152 -0
  30. data/ext/numo/linalg/lapack/gesvd.h +15 -0
  31. data/ext/numo/linalg/lapack/getrf.c +71 -0
  32. data/ext/numo/linalg/lapack/getrf.h +15 -0
  33. data/ext/numo/linalg/lapack/getri.c +82 -0
  34. data/ext/numo/linalg/lapack/getri.h +15 -0
  35. data/ext/numo/linalg/lapack/getrs.c +110 -0
  36. data/ext/numo/linalg/lapack/getrs.h +15 -0
  37. data/ext/numo/linalg/lapack/heev.c +71 -0
  38. data/ext/numo/linalg/lapack/heev.h +15 -0
  39. data/ext/numo/linalg/lapack/heevd.c +71 -0
  40. data/ext/numo/linalg/lapack/heevd.h +15 -0
  41. data/ext/numo/linalg/lapack/heevr.c +111 -0
  42. data/ext/numo/linalg/lapack/heevr.h +15 -0
  43. data/ext/numo/linalg/lapack/hegv.c +94 -0
  44. data/ext/numo/linalg/lapack/hegv.h +15 -0
  45. data/ext/numo/linalg/lapack/hegvd.c +94 -0
  46. data/ext/numo/linalg/lapack/hegvd.h +15 -0
  47. data/ext/numo/linalg/lapack/hegvx.c +133 -0
  48. data/ext/numo/linalg/lapack/hegvx.h +15 -0
  49. data/ext/numo/linalg/lapack/hetrf.c +68 -0
  50. data/ext/numo/linalg/lapack/hetrf.h +15 -0
  51. data/ext/numo/linalg/lapack/lange.c +66 -0
  52. data/ext/numo/linalg/lapack/lange.h +15 -0
  53. data/ext/numo/linalg/lapack/orgqr.c +79 -0
  54. data/ext/numo/linalg/lapack/orgqr.h +15 -0
  55. data/ext/numo/linalg/lapack/potrf.c +70 -0
  56. data/ext/numo/linalg/lapack/potrf.h +15 -0
  57. data/ext/numo/linalg/lapack/potri.c +70 -0
  58. data/ext/numo/linalg/lapack/potri.h +15 -0
  59. data/ext/numo/linalg/lapack/potrs.c +94 -0
  60. data/ext/numo/linalg/lapack/potrs.h +15 -0
  61. data/ext/numo/linalg/lapack/syev.c +71 -0
  62. data/ext/numo/linalg/lapack/syev.h +15 -0
  63. data/ext/numo/linalg/lapack/syevd.c +71 -0
  64. data/ext/numo/linalg/lapack/syevd.h +15 -0
  65. data/ext/numo/linalg/lapack/syevr.c +111 -0
  66. data/ext/numo/linalg/lapack/syevr.h +15 -0
  67. data/ext/numo/linalg/lapack/sygv.c +93 -0
  68. data/ext/numo/linalg/lapack/sygv.h +15 -0
  69. data/ext/numo/linalg/lapack/sygvd.c +93 -0
  70. data/ext/numo/linalg/lapack/sygvd.h +15 -0
  71. data/ext/numo/linalg/lapack/sygvx.c +133 -0
  72. data/ext/numo/linalg/lapack/sygvx.h +15 -0
  73. data/ext/numo/linalg/lapack/sytrf.c +72 -0
  74. data/ext/numo/linalg/lapack/sytrf.h +15 -0
  75. data/ext/numo/linalg/lapack/trtrs.c +99 -0
  76. data/ext/numo/linalg/lapack/trtrs.h +15 -0
  77. data/ext/numo/linalg/lapack/ungqr.c +79 -0
  78. data/ext/numo/linalg/lapack/ungqr.h +15 -0
  79. data/ext/numo/linalg/linalg.c +290 -0
  80. data/ext/numo/linalg/linalg.h +85 -0
  81. data/ext/numo/linalg/util.c +95 -0
  82. data/ext/numo/linalg/util.h +17 -0
  83. data/lib/numo/linalg/version.rb +10 -0
  84. data/lib/numo/linalg.rb +1309 -0
  85. data/vendor/tmp/.gitkeep +0 -0
  86. metadata +146 -0
@@ -0,0 +1,71 @@
1
+ #include "syevd.h"
2
+
3
+ struct _syevd_option {
4
+ int matrix_layout;
5
+ char jobz;
6
+ char uplo;
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* w = (tDType*)NDL_PTR(lp, 1); \
13
+ int* info = (int*)NDL_PTR(lp, 2); \
14
+ struct _syevd_option* opt = (struct _syevd_option*)(lp->opt_ptr); \
15
+ const lapack_int n = (lapack_int)NDL_SHAPE(lp, 0)[1]; \
16
+ const lapack_int lda = (lapack_int)NDL_SHAPE(lp, 0)[0]; \
17
+ const lapack_int i = LAPACKE_##fLapackFunc(opt->matrix_layout, opt->jobz, opt->uplo, n, a, lda, w); \
18
+ *info = (int)i; \
19
+ } \
20
+ \
21
+ static VALUE _linalg_lapack_##fLapackFunc(int argc, VALUE* argv, VALUE self) { \
22
+ VALUE a_vnary = Qnil; \
23
+ VALUE kw_args = Qnil; \
24
+ rb_scan_args(argc, argv, "1:", &a_vnary, &kw_args); \
25
+ ID kw_table[3] = { rb_intern("jobz"), rb_intern("uplo"), rb_intern("order") }; \
26
+ VALUE kw_values[3] = { Qundef, Qundef, Qundef }; \
27
+ rb_get_kwargs(kw_args, kw_table, 0, 3, kw_values); \
28
+ const char jobz = kw_values[0] != Qundef ? get_jobz(kw_values[0]) : 'V'; \
29
+ const char uplo = kw_values[1] != Qundef ? get_uplo(kw_values[1]) : 'U'; \
30
+ const int matrix_layout = kw_values[2] != Qundef ? get_matrix_layout(kw_values[2]) : LAPACK_ROW_MAJOR; \
31
+ \
32
+ if (CLASS_OF(a_vnary) != tNAryClass) { \
33
+ a_vnary = rb_funcall(tNAryClass, rb_intern("cast"), 1, a_vnary); \
34
+ } \
35
+ if (!RTEST(nary_check_contiguous(a_vnary))) { \
36
+ a_vnary = nary_dup(a_vnary); \
37
+ } \
38
+ \
39
+ narray_t* a_nary = NULL; \
40
+ GetNArray(a_vnary, a_nary); \
41
+ if (NA_NDIM(a_nary) != 2) { \
42
+ rb_raise(rb_eArgError, "input array a must be 2-dimensional"); \
43
+ return Qnil; \
44
+ } \
45
+ if (NA_SHAPE(a_nary)[0] != NA_SHAPE(a_nary)[1]) { \
46
+ rb_raise(rb_eArgError, "input array a must be square"); \
47
+ return Qnil; \
48
+ } \
49
+ \
50
+ const size_t n = NA_SHAPE(a_nary)[1]; \
51
+ size_t shape[1] = { n }; \
52
+ ndfunc_arg_in_t ain[1] = { { OVERWRITE, 2 } }; \
53
+ ndfunc_arg_out_t aout[2] = { { tNAryClass, 1, shape }, { numo_cInt32, 0 } }; \
54
+ ndfunc_t ndf = { _iter_##fLapackFunc, NO_LOOP | NDF_EXTRACT, 1, 2, ain, aout }; \
55
+ struct _syevd_option opt = { matrix_layout, jobz, uplo }; \
56
+ VALUE res = na_ndloop3(&ndf, &opt, 1, a_vnary); \
57
+ VALUE ret = rb_ary_new3(3, a_vnary, rb_ary_entry(res, 0), rb_ary_entry(res, 1)); \
58
+ \
59
+ RB_GC_GUARD(a_vnary); \
60
+ return ret; \
61
+ }
62
+
63
+ DEF_LINALG_FUNC(double, numo_cDFloat, dsyevd)
64
+ DEF_LINALG_FUNC(float, numo_cSFloat, ssyevd)
65
+
66
+ #undef DEF_LINALG_FUNC
67
+
68
+ void define_linalg_lapack_syevd(VALUE mLapack) {
69
+ rb_define_module_function(mLapack, "dsyevd", RUBY_METHOD_FUNC(_linalg_lapack_dsyevd), -1);
70
+ rb_define_module_function(mLapack, "ssyevd", RUBY_METHOD_FUNC(_linalg_lapack_ssyevd), -1);
71
+ }
@@ -0,0 +1,15 @@
1
+ #ifndef NUMO_LINALG_ALT_LAPACK_SYEVD_H
2
+ #define NUMO_LINALG_ALT_LAPACK_SYEVD_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_syevd(VALUE mLapack);
14
+
15
+ #endif /* NUMO_LINALG_ALT_LAPACK_SYEVD_H */
@@ -0,0 +1,111 @@
1
+ #include "syevr.h"
2
+
3
+ #define DEF_LINALG_FUNC(tDType, tNAryClass, fLapackFunc) \
4
+ struct _syevr_option_##tDType { \
5
+ int matrix_layout; \
6
+ char jobz; \
7
+ char range; \
8
+ char uplo; \
9
+ tDType vl; \
10
+ tDType vu; \
11
+ lapack_int il; \
12
+ lapack_int iu; \
13
+ }; \
14
+ \
15
+ static void _iter_##fLapackFunc(na_loop_t* const lp) { \
16
+ tDType* a = (tDType*)NDL_PTR(lp, 0); \
17
+ int* m = (int*)NDL_PTR(lp, 1); \
18
+ tDType* w = (tDType*)NDL_PTR(lp, 2); \
19
+ tDType* z = (tDType*)NDL_PTR(lp, 3); \
20
+ int* isuppz = (int*)NDL_PTR(lp, 4); \
21
+ int* info = (int*)NDL_PTR(lp, 5); \
22
+ struct _syevr_option_##tDType* opt = (struct _syevr_option_##tDType*)(lp->opt_ptr); \
23
+ const lapack_int n = (lapack_int)NDL_SHAPE(lp, 0)[1]; \
24
+ const lapack_int lda = (lapack_int)NDL_SHAPE(lp, 0)[0]; \
25
+ const lapack_int ldz = opt->range != 'I' ? n : opt->iu - opt->il + 1; \
26
+ const tDType abstol = 0.0; \
27
+ const lapack_int i = LAPACKE_##fLapackFunc( \
28
+ opt->matrix_layout, opt->jobz, opt->range, opt->uplo, n, a, lda, \
29
+ opt->vl, opt->vu, opt->il, opt->iu, abstol, m, w, z, ldz, isuppz); \
30
+ *info = (int)i; \
31
+ } \
32
+ \
33
+ static VALUE _linalg_lapack_##fLapackFunc(int argc, VALUE* argv, VALUE self) { \
34
+ VALUE a_vnary = Qnil; \
35
+ VALUE kw_args = Qnil; \
36
+ rb_scan_args(argc, argv, "1:", &a_vnary, &kw_args); \
37
+ ID kw_table[8] = { rb_intern("jobz"), rb_intern("range"), rb_intern("uplo"), \
38
+ rb_intern("vl"), rb_intern("vu"), rb_intern("il"), rb_intern("iu"), rb_intern("order") }; \
39
+ VALUE kw_values[8] = { Qundef, Qundef, Qundef, Qundef, Qundef, Qundef, Qundef, Qundef }; \
40
+ rb_get_kwargs(kw_args, kw_table, 0, 8, kw_values); \
41
+ const char jobz = kw_values[0] != Qundef ? get_jobz(kw_values[0]) : 'V'; \
42
+ const char range = kw_values[1] != Qundef ? get_range(kw_values[1]) : 'A'; \
43
+ const char uplo = kw_values[2] != Qundef ? get_uplo(kw_values[2]) : 'U'; \
44
+ const tDType vl = kw_values[3] != Qundef ? NUM2DBL(kw_values[3]) : 0.0; \
45
+ const tDType vu = kw_values[4] != Qundef ? NUM2DBL(kw_values[4]) : 0.0; \
46
+ const lapack_int il = kw_values[5] != Qundef ? NUM2INT(kw_values[5]) : 0; \
47
+ const lapack_int iu = kw_values[6] != Qundef ? NUM2INT(kw_values[6]) : 0; \
48
+ const int matrix_layout = kw_values[7] != Qundef ? get_matrix_layout(kw_values[7]) : LAPACK_ROW_MAJOR; \
49
+ \
50
+ if (CLASS_OF(a_vnary) != tNAryClass) { \
51
+ a_vnary = rb_funcall(tNAryClass, rb_intern("cast"), 1, a_vnary); \
52
+ } \
53
+ if (!RTEST(nary_check_contiguous(a_vnary))) { \
54
+ a_vnary = nary_dup(a_vnary); \
55
+ } \
56
+ \
57
+ narray_t* a_nary = NULL; \
58
+ GetNArray(a_vnary, a_nary); \
59
+ if (NA_NDIM(a_nary) != 2) { \
60
+ rb_raise(rb_eArgError, "input array a must be 2-dimensional"); \
61
+ return Qnil; \
62
+ } \
63
+ if (NA_SHAPE(a_nary)[0] != NA_SHAPE(a_nary)[1]) { \
64
+ rb_raise(rb_eArgError, "input array a must be square"); \
65
+ return Qnil; \
66
+ } \
67
+ \
68
+ if (range == 'V' && vu <= vl) { \
69
+ rb_raise(rb_eArgError, "vu must be greater than vl"); \
70
+ return Qnil; \
71
+ } \
72
+ \
73
+ const size_t n = NA_SHAPE(a_nary)[1]; \
74
+ if (range == 'I' && (il < 1 || il > (lapack_int)n)) { \
75
+ rb_raise(rb_eArgError, "il must satisfy 1 <= il <= n"); \
76
+ return Qnil; \
77
+ } \
78
+ if (range == 'I' && (iu < 1 || iu > (lapack_int)n)) { \
79
+ rb_raise(rb_eArgError, "iu must satisfy 1 <= iu <= n"); \
80
+ return Qnil; \
81
+ } \
82
+ if (range == 'I' && iu < il) { \
83
+ rb_raise(rb_eArgError, "iu must be greater than or equal to il"); \
84
+ return Qnil; \
85
+ } \
86
+ \
87
+ size_t m = range != 'I' ? n : (size_t)(iu - il + 1); \
88
+ size_t w_shape[1] = { m }; \
89
+ size_t z_shape[2] = { n, m }; \
90
+ size_t isuppz_shape[1] = { 2 * m }; \
91
+ ndfunc_arg_in_t ain[1] = { { OVERWRITE, 2 } }; \
92
+ ndfunc_arg_out_t aout[5] = { { numo_cInt32, 0 }, { tNAryClass, 1, w_shape }, { tNAryClass, 2, z_shape }, { numo_cInt32, 1, isuppz_shape }, { numo_cInt32, 0 } }; \
93
+ ndfunc_t ndf = { _iter_##fLapackFunc, NO_LOOP | NDF_EXTRACT, 1, 5, ain, aout }; \
94
+ struct _syevr_option_##tDType opt = { matrix_layout, jobz, range, uplo, vl, vu, il, iu }; \
95
+ VALUE res = na_ndloop3(&ndf, &opt, 1, a_vnary); \
96
+ VALUE ret = rb_ary_new3(6, a_vnary, rb_ary_entry(res, 0), rb_ary_entry(res, 1), rb_ary_entry(res, 2), \
97
+ rb_ary_entry(res, 3), rb_ary_entry(res, 4)); \
98
+ \
99
+ RB_GC_GUARD(a_vnary); \
100
+ return ret; \
101
+ }
102
+
103
+ DEF_LINALG_FUNC(double, numo_cDFloat, dsyevr)
104
+ DEF_LINALG_FUNC(float, numo_cSFloat, ssyevr)
105
+
106
+ #undef DEF_LINALG_FUNC
107
+
108
+ void define_linalg_lapack_syevr(VALUE mLapack) {
109
+ rb_define_module_function(mLapack, "dsyevr", RUBY_METHOD_FUNC(_linalg_lapack_dsyevr), -1);
110
+ rb_define_module_function(mLapack, "ssyevr", RUBY_METHOD_FUNC(_linalg_lapack_ssyevr), -1);
111
+ }
@@ -0,0 +1,15 @@
1
+ #ifndef NUMO_LINALG_ALT_LAPACK_SYEVR_H
2
+ #define NUMO_LINALG_ALT_LAPACK_SYEVR_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_syevr(VALUE mLapack);
14
+
15
+ #endif /* NUMO_LINALG_ALT_LAPACK_SYEVR_H */
@@ -0,0 +1,93 @@
1
+ #include "sygv.h"
2
+
3
+ struct _sygv_option {
4
+ int matrix_layout;
5
+ lapack_int itype;
6
+ char jobz;
7
+ char uplo;
8
+ };
9
+
10
+ #define DEF_LINALG_FUNC(tDType, tNAryClass, fLapackFunc) \
11
+ static void _iter_##fLapackFunc(na_loop_t* const lp) { \
12
+ tDType* a = (tDType*)NDL_PTR(lp, 0); \
13
+ tDType* b = (tDType*)NDL_PTR(lp, 1); \
14
+ tDType* w = (tDType*)NDL_PTR(lp, 2); \
15
+ int* info = (int*)NDL_PTR(lp, 3); \
16
+ struct _sygv_option* opt = (struct _sygv_option*)(lp->opt_ptr); \
17
+ const lapack_int n = (lapack_int)NDL_SHAPE(lp, 0)[1]; \
18
+ const lapack_int lda = (lapack_int)NDL_SHAPE(lp, 0)[0]; \
19
+ const lapack_int ldb = (lapack_int)NDL_SHAPE(lp, 1)[0]; \
20
+ const lapack_int i = LAPACKE_##fLapackFunc(opt->matrix_layout, opt->itype, opt->jobz, opt->uplo, n, a, lda, b, ldb, w); \
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[4] = { rb_intern("itype"), rb_intern("jobz"), rb_intern("uplo"), rb_intern("order") }; \
30
+ VALUE kw_values[4] = { Qundef, Qundef, Qundef, Qundef }; \
31
+ rb_get_kwargs(kw_args, kw_table, 0, 4, kw_values); \
32
+ const lapack_int itype = kw_values[0] != Qundef ? get_itype(kw_values[0]) : 1; \
33
+ const char jobz = kw_values[1] != Qundef ? get_jobz(kw_values[1]) : 'V'; \
34
+ const char uplo = kw_values[2] != Qundef ? get_uplo(kw_values[2]) : 'U'; \
35
+ const int matrix_layout = kw_values[3] != Qundef ? get_matrix_layout(kw_values[3]) : 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
+ if (CLASS_OF(b_vnary) != tNAryClass) { \
44
+ b_vnary = rb_funcall(tNAryClass, rb_intern("cast"), 1, b_vnary); \
45
+ } \
46
+ if (!RTEST(nary_check_contiguous(b_vnary))) { \
47
+ b_vnary = nary_dup(b_vnary); \
48
+ } \
49
+ \
50
+ narray_t* a_nary = NULL; \
51
+ GetNArray(a_vnary, a_nary); \
52
+ if (NA_NDIM(a_nary) != 2) { \
53
+ rb_raise(rb_eArgError, "input array a must be 2-dimensional"); \
54
+ return Qnil; \
55
+ } \
56
+ if (NA_SHAPE(a_nary)[0] != NA_SHAPE(a_nary)[1]) { \
57
+ rb_raise(rb_eArgError, "input array a must be square"); \
58
+ return Qnil; \
59
+ } \
60
+ narray_t* b_nary = NULL; \
61
+ GetNArray(b_vnary, b_nary); \
62
+ if (NA_NDIM(b_nary) != 2) { \
63
+ rb_raise(rb_eArgError, "input array b must be 2-dimensional"); \
64
+ return Qnil; \
65
+ } \
66
+ if (NA_SHAPE(b_nary)[0] != NA_SHAPE(b_nary)[1]) { \
67
+ rb_raise(rb_eArgError, "input array b must be square"); \
68
+ return Qnil; \
69
+ } \
70
+ \
71
+ const size_t n = NA_SHAPE(a_nary)[1]; \
72
+ size_t shape[1] = { n }; \
73
+ ndfunc_arg_in_t ain[2] = { { OVERWRITE, 2 }, { OVERWRITE, 2 } }; \
74
+ ndfunc_arg_out_t aout[2] = { { tNAryClass, 1, shape }, { numo_cInt32, 0 } }; \
75
+ ndfunc_t ndf = { _iter_##fLapackFunc, NO_LOOP | NDF_EXTRACT, 2, 2, ain, aout }; \
76
+ struct _sygv_option opt = { matrix_layout, itype, jobz, uplo }; \
77
+ VALUE res = na_ndloop3(&ndf, &opt, 2, a_vnary, b_vnary); \
78
+ VALUE ret = rb_ary_new3(4, a_vnary, b_vnary, rb_ary_entry(res, 0), rb_ary_entry(res, 1)); \
79
+ \
80
+ RB_GC_GUARD(a_vnary); \
81
+ RB_GC_GUARD(b_vnary); \
82
+ return ret; \
83
+ }
84
+
85
+ DEF_LINALG_FUNC(double, numo_cDFloat, dsygv)
86
+ DEF_LINALG_FUNC(float, numo_cSFloat, ssygv)
87
+
88
+ #undef DEF_LINALG_FUNC
89
+
90
+ void define_linalg_lapack_sygv(VALUE mLapack) {
91
+ rb_define_module_function(mLapack, "dsygv", RUBY_METHOD_FUNC(_linalg_lapack_dsygv), -1);
92
+ rb_define_module_function(mLapack, "ssygv", RUBY_METHOD_FUNC(_linalg_lapack_ssygv), -1);
93
+ }
@@ -0,0 +1,15 @@
1
+ #ifndef NUMO_LINALG_ALT_LAPACK_SYGV_H
2
+ #define NUMO_LINALG_ALT_LAPACK_SYGV_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_sygv(VALUE mLapack);
14
+
15
+ #endif /* NUMO_LINALG_ALT_LAPACK_SYGV_H */
@@ -0,0 +1,93 @@
1
+ #include "sygvd.h"
2
+
3
+ struct _sygvd_option {
4
+ int matrix_layout;
5
+ lapack_int itype;
6
+ char jobz;
7
+ char uplo;
8
+ };
9
+
10
+ #define DEF_LINALG_FUNC(tDType, tNAryClass, fLapackFunc) \
11
+ static void _iter_##fLapackFunc(na_loop_t* const lp) { \
12
+ tDType* a = (tDType*)NDL_PTR(lp, 0); \
13
+ tDType* b = (tDType*)NDL_PTR(lp, 1); \
14
+ tDType* w = (tDType*)NDL_PTR(lp, 2); \
15
+ int* info = (int*)NDL_PTR(lp, 3); \
16
+ struct _sygvd_option* opt = (struct _sygvd_option*)(lp->opt_ptr); \
17
+ const lapack_int n = (lapack_int)NDL_SHAPE(lp, 0)[1]; \
18
+ const lapack_int lda = (lapack_int)NDL_SHAPE(lp, 0)[0]; \
19
+ const lapack_int ldb = (lapack_int)NDL_SHAPE(lp, 1)[0]; \
20
+ const lapack_int i = LAPACKE_##fLapackFunc(opt->matrix_layout, opt->itype, opt->jobz, opt->uplo, n, a, lda, b, ldb, w); \
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[4] = { rb_intern("itype"), rb_intern("jobz"), rb_intern("uplo"), rb_intern("order") }; \
30
+ VALUE kw_values[4] = { Qundef, Qundef, Qundef, Qundef }; \
31
+ rb_get_kwargs(kw_args, kw_table, 0, 4, kw_values); \
32
+ const lapack_int itype = kw_values[0] != Qundef ? get_itype(kw_values[0]) : 1; \
33
+ const char jobz = kw_values[1] != Qundef ? get_jobz(kw_values[1]) : 'V'; \
34
+ const char uplo = kw_values[2] != Qundef ? get_uplo(kw_values[2]) : 'U'; \
35
+ const int matrix_layout = kw_values[3] != Qundef ? get_matrix_layout(kw_values[3]) : 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
+ if (CLASS_OF(b_vnary) != tNAryClass) { \
44
+ b_vnary = rb_funcall(tNAryClass, rb_intern("cast"), 1, b_vnary); \
45
+ } \
46
+ if (!RTEST(nary_check_contiguous(b_vnary))) { \
47
+ b_vnary = nary_dup(b_vnary); \
48
+ } \
49
+ \
50
+ narray_t* a_nary = NULL; \
51
+ GetNArray(a_vnary, a_nary); \
52
+ if (NA_NDIM(a_nary) != 2) { \
53
+ rb_raise(rb_eArgError, "input array a must be 2-dimensional"); \
54
+ return Qnil; \
55
+ } \
56
+ if (NA_SHAPE(a_nary)[0] != NA_SHAPE(a_nary)[1]) { \
57
+ rb_raise(rb_eArgError, "input array a must be square"); \
58
+ return Qnil; \
59
+ } \
60
+ narray_t* b_nary = NULL; \
61
+ GetNArray(b_vnary, b_nary); \
62
+ if (NA_NDIM(b_nary) != 2) { \
63
+ rb_raise(rb_eArgError, "input array b must be 2-dimensional"); \
64
+ return Qnil; \
65
+ } \
66
+ if (NA_SHAPE(b_nary)[0] != NA_SHAPE(b_nary)[1]) { \
67
+ rb_raise(rb_eArgError, "input array b must be square"); \
68
+ return Qnil; \
69
+ } \
70
+ \
71
+ const size_t n = NA_SHAPE(a_nary)[1]; \
72
+ size_t shape[1] = { n }; \
73
+ ndfunc_arg_in_t ain[2] = { { OVERWRITE, 2 }, { OVERWRITE, 2 } }; \
74
+ ndfunc_arg_out_t aout[2] = { { tNAryClass, 1, shape }, { numo_cInt32, 0 } }; \
75
+ ndfunc_t ndf = { _iter_##fLapackFunc, NO_LOOP | NDF_EXTRACT, 2, 2, ain, aout }; \
76
+ struct _sygvd_option opt = { matrix_layout, itype, jobz, uplo }; \
77
+ VALUE res = na_ndloop3(&ndf, &opt, 2, a_vnary, b_vnary); \
78
+ VALUE ret = rb_ary_new3(4, a_vnary, b_vnary, rb_ary_entry(res, 0), rb_ary_entry(res, 1)); \
79
+ \
80
+ RB_GC_GUARD(a_vnary); \
81
+ RB_GC_GUARD(b_vnary); \
82
+ return ret; \
83
+ }
84
+
85
+ DEF_LINALG_FUNC(double, numo_cDFloat, dsygvd)
86
+ DEF_LINALG_FUNC(float, numo_cSFloat, ssygvd)
87
+
88
+ #undef DEF_LINALG_FUNC
89
+
90
+ void define_linalg_lapack_sygvd(VALUE mLapack) {
91
+ rb_define_module_function(mLapack, "dsygvd", RUBY_METHOD_FUNC(_linalg_lapack_dsygvd), -1);
92
+ rb_define_module_function(mLapack, "ssygvd", RUBY_METHOD_FUNC(_linalg_lapack_ssygvd), -1);
93
+ }
@@ -0,0 +1,15 @@
1
+ #ifndef NUMO_LINALG_ALT_LAPACK_SYGVD_H
2
+ #define NUMO_LINALG_ALT_LAPACK_SYGVD_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_sygvd(VALUE mLapack);
14
+
15
+ #endif /* NUMO_LINALG_ALT_LAPACK_SYGVD_H */
@@ -0,0 +1,133 @@
1
+ #include "sygvx.h"
2
+
3
+ #define DEF_LINALG_FUNC(tDType, tNAryClass, fLapackFunc) \
4
+ struct _sygvx_option_##tDType { \
5
+ int matrix_layout; \
6
+ lapack_int itype; \
7
+ char jobz; \
8
+ char range; \
9
+ char uplo; \
10
+ tDType vl; \
11
+ tDType vu; \
12
+ lapack_int il; \
13
+ lapack_int iu; \
14
+ }; \
15
+ \
16
+ static void _iter_##fLapackFunc(na_loop_t* const lp) { \
17
+ tDType* a = (tDType*)NDL_PTR(lp, 0); \
18
+ tDType* b = (tDType*)NDL_PTR(lp, 1); \
19
+ int* m = (int*)NDL_PTR(lp, 2); \
20
+ tDType* w = (tDType*)NDL_PTR(lp, 3); \
21
+ tDType* z = (tDType*)NDL_PTR(lp, 4); \
22
+ int* ifail = (int*)NDL_PTR(lp, 5); \
23
+ int* info = (int*)NDL_PTR(lp, 6); \
24
+ struct _sygvx_option_##tDType* opt = (struct _sygvx_option_##tDType*)(lp->opt_ptr); \
25
+ const lapack_int n = (lapack_int)NDL_SHAPE(lp, 0)[1]; \
26
+ const lapack_int lda = (lapack_int)NDL_SHAPE(lp, 0)[0]; \
27
+ const lapack_int ldb = (lapack_int)NDL_SHAPE(lp, 1)[0]; \
28
+ const lapack_int ldz = opt->range != 'I' ? n : opt->iu - opt->il + 1; \
29
+ const tDType abstol = 0.0; \
30
+ const lapack_int i = LAPACKE_##fLapackFunc( \
31
+ opt->matrix_layout, opt->itype, opt->jobz, opt->range, opt->uplo, n, a, lda, b, ldb, \
32
+ opt->vl, opt->vu, opt->il, opt->iu, abstol, m, w, z, ldz, ifail); \
33
+ *info = (int)i; \
34
+ } \
35
+ \
36
+ static VALUE _linalg_lapack_##fLapackFunc(int argc, VALUE* argv, VALUE self) { \
37
+ VALUE a_vnary = Qnil; \
38
+ VALUE b_vnary = Qnil; \
39
+ VALUE kw_args = Qnil; \
40
+ rb_scan_args(argc, argv, "2:", &a_vnary, &b_vnary, &kw_args); \
41
+ ID kw_table[9] = { rb_intern("itype"), rb_intern("jobz"), rb_intern("range"), rb_intern("uplo"), \
42
+ rb_intern("vl"), rb_intern("vu"), rb_intern("il"), rb_intern("iu"), rb_intern("order") }; \
43
+ VALUE kw_values[9] = { Qundef, Qundef, Qundef, Qundef, Qundef, Qundef, Qundef, Qundef, Qundef }; \
44
+ rb_get_kwargs(kw_args, kw_table, 0, 9, kw_values); \
45
+ const lapack_int itype = kw_values[0] != Qundef ? get_itype(kw_values[0]) : 1; \
46
+ const char jobz = kw_values[1] != Qundef ? get_jobz(kw_values[1]) : 'V'; \
47
+ const char range = kw_values[2] != Qundef ? get_range(kw_values[2]) : 'A'; \
48
+ const char uplo = kw_values[3] != Qundef ? get_uplo(kw_values[3]) : 'U'; \
49
+ const tDType vl = kw_values[4] != Qundef ? NUM2DBL(kw_values[4]) : 0.0; \
50
+ const tDType vu = kw_values[5] != Qundef ? NUM2DBL(kw_values[5]) : 0.0; \
51
+ const lapack_int il = kw_values[6] != Qundef ? NUM2INT(kw_values[6]) : 0; \
52
+ const lapack_int iu = kw_values[7] != Qundef ? NUM2INT(kw_values[7]) : 0; \
53
+ const int matrix_layout = kw_values[8] != Qundef ? get_matrix_layout(kw_values[8]) : LAPACK_ROW_MAJOR; \
54
+ \
55
+ if (CLASS_OF(a_vnary) != tNAryClass) { \
56
+ a_vnary = rb_funcall(tNAryClass, rb_intern("cast"), 1, a_vnary); \
57
+ } \
58
+ if (!RTEST(nary_check_contiguous(a_vnary))) { \
59
+ a_vnary = nary_dup(a_vnary); \
60
+ } \
61
+ if (CLASS_OF(b_vnary) != tNAryClass) { \
62
+ b_vnary = rb_funcall(tNAryClass, rb_intern("cast"), 1, b_vnary); \
63
+ } \
64
+ if (!RTEST(nary_check_contiguous(b_vnary))) { \
65
+ b_vnary = nary_dup(b_vnary); \
66
+ } \
67
+ \
68
+ narray_t* a_nary = NULL; \
69
+ GetNArray(a_vnary, a_nary); \
70
+ if (NA_NDIM(a_nary) != 2) { \
71
+ rb_raise(rb_eArgError, "input array a must be 2-dimensional"); \
72
+ return Qnil; \
73
+ } \
74
+ if (NA_SHAPE(a_nary)[0] != NA_SHAPE(a_nary)[1]) { \
75
+ rb_raise(rb_eArgError, "input array a must be square"); \
76
+ return Qnil; \
77
+ } \
78
+ narray_t* b_nary = NULL; \
79
+ GetNArray(b_vnary, b_nary); \
80
+ if (NA_NDIM(b_nary) != 2) { \
81
+ rb_raise(rb_eArgError, "input array b must be 2-dimensional"); \
82
+ return Qnil; \
83
+ } \
84
+ if (NA_SHAPE(b_nary)[0] != NA_SHAPE(b_nary)[1]) { \
85
+ rb_raise(rb_eArgError, "input array b must be square"); \
86
+ return Qnil; \
87
+ } \
88
+ \
89
+ if (range == 'V' && vu <= vl) { \
90
+ rb_raise(rb_eArgError, "vu must be greater than vl"); \
91
+ return Qnil; \
92
+ } \
93
+ \
94
+ const size_t n = NA_SHAPE(a_nary)[1]; \
95
+ if (range == 'I' && (il < 1 || il > (lapack_int)n)) { \
96
+ rb_raise(rb_eArgError, "il must satisfy 1 <= il <= n"); \
97
+ return Qnil; \
98
+ } \
99
+ if (range == 'I' && (iu < 1 || iu > (lapack_int)n)) { \
100
+ rb_raise(rb_eArgError, "iu must satisfy 1 <= iu <= n"); \
101
+ return Qnil; \
102
+ } \
103
+ if (range == 'I' && iu < il) { \
104
+ rb_raise(rb_eArgError, "iu must be greater than or equal to il"); \
105
+ return Qnil; \
106
+ } \
107
+ \
108
+ size_t m = range != 'I' ? n : (size_t)(iu - il + 1); \
109
+ size_t w_shape[1] = { m }; \
110
+ size_t z_shape[2] = { n, m }; \
111
+ size_t ifail_shape[1] = { n }; \
112
+ ndfunc_arg_in_t ain[2] = { { OVERWRITE, 2 }, { OVERWRITE, 2 } }; \
113
+ ndfunc_arg_out_t aout[5] = { { numo_cInt32, 0 }, { tNAryClass, 1, w_shape }, { tNAryClass, 2, z_shape }, { numo_cInt32, 1, ifail_shape }, { numo_cInt32, 0 } }; \
114
+ ndfunc_t ndf = { _iter_##fLapackFunc, NO_LOOP | NDF_EXTRACT, 2, 5, ain, aout }; \
115
+ struct _sygvx_option_##tDType opt = { matrix_layout, itype, jobz, range, uplo, vl, vu, il, iu }; \
116
+ VALUE res = na_ndloop3(&ndf, &opt, 2, a_vnary, b_vnary); \
117
+ VALUE ret = rb_ary_new3(7, a_vnary, b_vnary, rb_ary_entry(res, 0), rb_ary_entry(res, 1), rb_ary_entry(res, 2), \
118
+ rb_ary_entry(res, 3), rb_ary_entry(res, 4)); \
119
+ \
120
+ RB_GC_GUARD(a_vnary); \
121
+ RB_GC_GUARD(b_vnary); \
122
+ return ret; \
123
+ }
124
+
125
+ DEF_LINALG_FUNC(double, numo_cDFloat, dsygvx)
126
+ DEF_LINALG_FUNC(float, numo_cSFloat, ssygvx)
127
+
128
+ #undef DEF_LINALG_FUNC
129
+
130
+ void define_linalg_lapack_sygvx(VALUE mLapack) {
131
+ rb_define_module_function(mLapack, "dsygvx", RUBY_METHOD_FUNC(_linalg_lapack_dsygvx), -1);
132
+ rb_define_module_function(mLapack, "ssygvx", RUBY_METHOD_FUNC(_linalg_lapack_ssygvx), -1);
133
+ }