numo-linalg 0.0.1

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 (85) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +4 -0
  3. data/README.md +80 -0
  4. data/Rakefile +18 -0
  5. data/ext/numo/linalg/blas/blas.c +352 -0
  6. data/ext/numo/linalg/blas/cblas.h +575 -0
  7. data/ext/numo/linalg/blas/cblas_t.h +563 -0
  8. data/ext/numo/linalg/blas/depend.erb +23 -0
  9. data/ext/numo/linalg/blas/extconf.rb +67 -0
  10. data/ext/numo/linalg/blas/gen/cogen.rb +72 -0
  11. data/ext/numo/linalg/blas/gen/decl.rb +203 -0
  12. data/ext/numo/linalg/blas/gen/desc.rb +8138 -0
  13. data/ext/numo/linalg/blas/gen/erbpp2.rb +339 -0
  14. data/ext/numo/linalg/blas/gen/replace_cblas_h.rb +27 -0
  15. data/ext/numo/linalg/blas/gen/spec.rb +93 -0
  16. data/ext/numo/linalg/blas/numo_blas.h +41 -0
  17. data/ext/numo/linalg/blas/tmpl/axpy.c +75 -0
  18. data/ext/numo/linalg/blas/tmpl/copy.c +57 -0
  19. data/ext/numo/linalg/blas/tmpl/def_c.c +3 -0
  20. data/ext/numo/linalg/blas/tmpl/def_d.c +3 -0
  21. data/ext/numo/linalg/blas/tmpl/def_s.c +3 -0
  22. data/ext/numo/linalg/blas/tmpl/def_z.c +3 -0
  23. data/ext/numo/linalg/blas/tmpl/dot.c +68 -0
  24. data/ext/numo/linalg/blas/tmpl/ger.c +114 -0
  25. data/ext/numo/linalg/blas/tmpl/init_class.c +20 -0
  26. data/ext/numo/linalg/blas/tmpl/init_module.c +12 -0
  27. data/ext/numo/linalg/blas/tmpl/lib.c +40 -0
  28. data/ext/numo/linalg/blas/tmpl/mm.c +214 -0
  29. data/ext/numo/linalg/blas/tmpl/module.c +9 -0
  30. data/ext/numo/linalg/blas/tmpl/mv.c +194 -0
  31. data/ext/numo/linalg/blas/tmpl/nrm2.c +79 -0
  32. data/ext/numo/linalg/blas/tmpl/rot.c +65 -0
  33. data/ext/numo/linalg/blas/tmpl/rotm.c +82 -0
  34. data/ext/numo/linalg/blas/tmpl/scal.c +69 -0
  35. data/ext/numo/linalg/blas/tmpl/sdsdot.c +77 -0
  36. data/ext/numo/linalg/blas/tmpl/set_prefix.c +16 -0
  37. data/ext/numo/linalg/blas/tmpl/swap.c +57 -0
  38. data/ext/numo/linalg/blas/tmpl/syr.c +102 -0
  39. data/ext/numo/linalg/blas/tmpl/syr2.c +110 -0
  40. data/ext/numo/linalg/blas/tmpl/syr2k.c +129 -0
  41. data/ext/numo/linalg/blas/tmpl/syrk.c +132 -0
  42. data/ext/numo/linalg/lapack/depend.erb +23 -0
  43. data/ext/numo/linalg/lapack/extconf.rb +45 -0
  44. data/ext/numo/linalg/lapack/gen/cogen.rb +74 -0
  45. data/ext/numo/linalg/lapack/gen/desc.rb +151278 -0
  46. data/ext/numo/linalg/lapack/gen/replace_lapacke_h.rb +32 -0
  47. data/ext/numo/linalg/lapack/gen/spec.rb +104 -0
  48. data/ext/numo/linalg/lapack/lapack.c +387 -0
  49. data/ext/numo/linalg/lapack/lapacke.h +16425 -0
  50. data/ext/numo/linalg/lapack/lapacke_config.h +119 -0
  51. data/ext/numo/linalg/lapack/lapacke_mangling.h +17 -0
  52. data/ext/numo/linalg/lapack/lapacke_t.h +10550 -0
  53. data/ext/numo/linalg/lapack/numo_lapack.h +42 -0
  54. data/ext/numo/linalg/lapack/tmpl/def_c.c +3 -0
  55. data/ext/numo/linalg/lapack/tmpl/def_d.c +7 -0
  56. data/ext/numo/linalg/lapack/tmpl/def_s.c +7 -0
  57. data/ext/numo/linalg/lapack/tmpl/def_z.c +3 -0
  58. data/ext/numo/linalg/lapack/tmpl/fact.c +179 -0
  59. data/ext/numo/linalg/lapack/tmpl/geev.c +123 -0
  60. data/ext/numo/linalg/lapack/tmpl/gels.c +232 -0
  61. data/ext/numo/linalg/lapack/tmpl/gesv.c +149 -0
  62. data/ext/numo/linalg/lapack/tmpl/gesvd.c +189 -0
  63. data/ext/numo/linalg/lapack/tmpl/ggev.c +138 -0
  64. data/ext/numo/linalg/lapack/tmpl/gqr.c +121 -0
  65. data/ext/numo/linalg/lapack/tmpl/init_class.c +20 -0
  66. data/ext/numo/linalg/lapack/tmpl/init_module.c +12 -0
  67. data/ext/numo/linalg/lapack/tmpl/lange.c +79 -0
  68. data/ext/numo/linalg/lapack/tmpl/lib.c +40 -0
  69. data/ext/numo/linalg/lapack/tmpl/module.c +9 -0
  70. data/ext/numo/linalg/lapack/tmpl/syev.c +91 -0
  71. data/ext/numo/linalg/lapack/tmpl/sygv.c +104 -0
  72. data/ext/numo/linalg/lapack/tmpl/trf.c +276 -0
  73. data/ext/numo/linalg/numo_linalg.h +115 -0
  74. data/lib/numo/linalg.rb +3 -0
  75. data/lib/numo/linalg/function.rb +1008 -0
  76. data/lib/numo/linalg/linalg.rb +7 -0
  77. data/lib/numo/linalg/loader.rb +174 -0
  78. data/lib/numo/linalg/use/atlas.rb +3 -0
  79. data/lib/numo/linalg/use/lapack.rb +3 -0
  80. data/lib/numo/linalg/use/mkl.rb +3 -0
  81. data/lib/numo/linalg/use/openblas.rb +3 -0
  82. data/lib/numo/linalg/version.rb +5 -0
  83. data/numo-linalg.gemspec +26 -0
  84. data/spec/lapack_spec.rb +13 -0
  85. metadata +172 -0
@@ -0,0 +1,149 @@
1
+ /*<%
2
+ uplo = (/^?ge/=~name) ? nil : "g->uplo,"
3
+ ipiv = (/^?po/=~name) ? nil : "ipiv,"
4
+ %>*/
5
+ <% %>
6
+ #define UPLO <%=(/^?ge/!~name) ? "1":"0"%>
7
+ #define IPIV <%=(/^?po/!~name) ? "1":"0"%>
8
+ #define args_t <%=func_name%>_args_t
9
+ #define func_p <%=func_name%>_p
10
+
11
+ typedef struct {
12
+ int order;
13
+ char uplo;
14
+ } args_t;
15
+
16
+ static <%=func_name%>_t <%=func_name%>_p = 0;
17
+
18
+ static void
19
+ <%=c_iter%>(na_loop_t * const lp)
20
+ {
21
+ dtype *a, *b;
22
+ int *info;
23
+ int n, nrhs;
24
+ int lda, ldb;
25
+ args_t *g;
26
+ #if IPIV
27
+ int *ipiv;
28
+ ipiv = (int*)NDL_PTR(lp,2);
29
+ info = (int*)NDL_PTR(lp,3);
30
+ #else
31
+ info = (int*)NDL_PTR(lp,2);
32
+ #endif
33
+ a = (dtype*)NDL_PTR(lp,0);
34
+ b = (dtype*)NDL_PTR(lp,1);
35
+ g = (args_t*)(lp->opt_ptr);
36
+
37
+ n = NDL_SHAPE(lp,0)[0];
38
+ lda = NDL_STEP(lp,0) / sizeof(dtype);
39
+ if (lp->args[1].ndim == 1) {
40
+ nrhs = 1;
41
+ ldb = (g->order==LAPACK_COL_MAJOR) ? n : 1;
42
+ } else {
43
+ nrhs = NDL_SHAPE(lp,1)[1];
44
+ ldb = NDL_STEP(lp,1) / sizeof(dtype);
45
+ }
46
+ //printf("order=%d n=%d nrhs=%d lda=%d ldb=%d b.ndim=%d\n",
47
+ // g->order,n,nrhs,lda,ldb,lp->args[1].ndim);
48
+ *info = (*func_p)( g->order, <%=uplo%>
49
+ n, nrhs, a, lda, <%=ipiv%> b, ldb );
50
+ CHECK_ERROR(*info);
51
+ }
52
+
53
+ /*<%
54
+ tp = class_name
55
+ iary = "Numo::Int"
56
+ iscal = "Integer"
57
+ if uplo
58
+ a = "a, b, [uplo:'U', order:'R']"
59
+ else
60
+ a = "a, b, [order:'R']"
61
+ end
62
+ if ipiv
63
+ n = "a, b, ipiv, info"
64
+ t = [tp,tp,iary,iscal]
65
+ else
66
+ n = "a, b, info"
67
+ t = [tp,tp,iscal]
68
+ end
69
+ return_type = t.join(", ")
70
+ return_name = n
71
+ args_v = a
72
+
73
+ params = [
74
+ mat("a",:inplace,"output: lu"),
75
+ vec("b",:inplace,"output: x"),
76
+ uplo && opt("uplo"),
77
+ opt("order"),
78
+ ].select{|x| x}.join("\n ")
79
+ %>
80
+ @overload <%=name%>(<%=args_v%>)
81
+ <%=params%>
82
+ @return [[<%=return_name%>]] Array<<%=return_type%>>
83
+ <%=outparam(return_name)%>
84
+
85
+ <%=description%>
86
+
87
+ */
88
+ static VALUE
89
+ <%=c_func(-1)%>(int argc, VALUE const argv[], VALUE UNUSED(mod))
90
+ {
91
+ VALUE a, b, ans;
92
+ narray_t *na1, *na2;
93
+ size_t n, nb, nrhs;
94
+ ndfunc_arg_in_t ain[2] = {{OVERWRITE,2},{OVERWRITE,2}};
95
+ size_t shape[2];
96
+ ndfunc_arg_out_t aout[2] = {{cInt,1,shape},{cInt,0}};
97
+ ndfunc_t ndf = {&<%=c_iter%>, NO_LOOP|NDF_EXTRACT, 2,2, ain,aout};
98
+ args_t g;
99
+ VALUE kw_hash = Qnil;
100
+ ID kw_table[2] = {id_order,id_uplo};
101
+ VALUE opts[2] = {Qundef,Qundef};
102
+
103
+ CHECK_FUNC(func_p,"<%=func_name%>");
104
+
105
+ rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
106
+ rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
107
+ g.order = option_order(opts[0]);
108
+ g.uplo = option_uplo(opts[1]);
109
+
110
+ COPY_OR_CAST_TO(a,cT);
111
+ COPY_OR_CAST_TO(b,cT);
112
+ GetNArray(a, na1);
113
+ GetNArray(b, na2);
114
+ CHECK_DIM_GE(na1, 2);
115
+ CHECK_DIM_GE(na2, 1);
116
+ CHECK_SQUARE("matrix a",na1);
117
+ n = COL_SIZE(na1);
118
+ if (NA_NDIM(na2) == 1) {
119
+ ain[1].dim = 1;
120
+ nb = COL_SIZE(na2);
121
+ nrhs = 1;
122
+ } else {
123
+ nb = ROW_SIZE(na2);
124
+ nrhs = COL_SIZE(na2);
125
+ }
126
+ if (n != nb) {
127
+ rb_raise(nary_eShapeError, "matrix dimension mismatch: "
128
+ "a.col=a.row=%"SZF"u b.row=%"SZF"u", n, nb);
129
+ }
130
+ shape[0] = n;
131
+ shape[1] = nrhs;
132
+ #if !IPIV
133
+ ndf.aout++;
134
+ ndf.nout--;
135
+ #endif
136
+
137
+ ans = na_ndloop3(&ndf, &g, 2, a, b);
138
+
139
+ #if IPIV
140
+ return rb_ary_concat(rb_assoc_new(a,b),ans);
141
+ #else
142
+ return rb_ary_new3(3,a,b,ans);
143
+ #endif
144
+ }
145
+
146
+ #undef func_p
147
+ #undef args_t
148
+ #undef UPLO
149
+ #undef IPIV
@@ -0,0 +1,189 @@
1
+ //<% is_sdd = (/gesdd/ =~ name) %>
2
+ #define SDD <%=is_sdd ? "1":"0"%>
3
+ #define args_t <%=func_name%>_args_t
4
+ #define func_p <%=func_name%>_p
5
+
6
+ typedef struct {
7
+ int order;
8
+ char jobu, jobvt, jobz;
9
+ rtype *superb;
10
+ } args_t;
11
+
12
+ static <%=func_name%>_t func_p = 0;
13
+
14
+ static void
15
+ <%=c_iter%>(na_loop_t * const lp)
16
+ {
17
+ dtype *a, *u=0, *vt=0;
18
+ rtype *s;
19
+ int *info;
20
+ int m, n, lda, ldu, ldvt, tmp;
21
+ args_t *g;
22
+
23
+ a = (dtype*)NDL_PTR(lp,0);
24
+ s = (rtype*)NDL_PTR(lp,1);
25
+ u = (dtype*)NDL_PTR(lp,2);
26
+ vt = (dtype*)NDL_PTR(lp,3);
27
+ info = (int*)NDL_PTR(lp,4);
28
+ g = (args_t*)(lp->opt_ptr);
29
+
30
+ m = NDL_SHAPE(lp,0)[0];
31
+ n = NDL_SHAPE(lp,0)[1];
32
+ SWAP_IFCOL(g->order,m,n);
33
+ lda = NDL_STEP(lp,0) / sizeof(dtype);
34
+ ldu = NDL_STEP(lp,2) / sizeof(dtype);
35
+ if (ldu == 0) { ldu = m; } // jobu == 'O' or 'N'
36
+ ldvt = NDL_STEP(lp,3) / sizeof(dtype);
37
+ if (ldvt == 0) { ldvt = n; } // jobvt == 'O' or 'N'
38
+
39
+ //printf("order=%d jobu=%c jobvt=%c jobz=%c m=%d n=%d lda=%d ldu=%d ldvt=%d\n",g->order,g->jobu, g->jobvt,g->jobz, m,n,lda,ldu,ldvt);
40
+
41
+ /*<%
42
+ job = (is_sdd) ? "g->jobz" : "g->jobu, g->jobvt"
43
+ spb = (is_sdd) ? "" : ", g->superb"
44
+ %>*/
45
+ *info = (*func_p)( g->order, <%=job%>, m, n, a, lda, s,
46
+ u, ldu, vt, ldvt <%=spb%> );
47
+ CHECK_ERROR(*info);
48
+ }
49
+
50
+ /*<%
51
+ tp = class_name
52
+ iscal = "Integer"
53
+ if is_sdd
54
+ a = "a, [jobz:'A', order:'R']"
55
+ else
56
+ a = "a, [jobu:'A', jobvt:'A', order:'R']"
57
+ end
58
+ return_type = [tp,tp,tp,iscal].join(", ")
59
+ return_name = "sigma, u, vt, info"
60
+ args_v = a
61
+ params = [
62
+ mat("a","inplace allowed if job\\*=='O'"),
63
+ *(is_sdd ? [jobs("jobz")] : [jobs("jobu"),jobs("jobvt")]),
64
+ opt("order"),
65
+ ].select{|x| x}.join("\n ")
66
+ %>
67
+ @overload <%=name%>(<%=args_v%>)
68
+ <%=params%>
69
+ @return [[<%=return_name%>]] Array<<%=return_type%>>
70
+ <%=outparam(return_name)%>
71
+
72
+ <%=description%>
73
+
74
+ */
75
+ static VALUE
76
+ <%=c_func(-1)%>(int argc, VALUE const argv[], VALUE UNUSED(mod))
77
+ {
78
+ #if !SDD
79
+ VALUE tmpbuf;
80
+ #endif
81
+ VALUE a, ans;
82
+ int m, n, min_mn, tmp;
83
+ narray_t *na1;
84
+ size_t shape_s[1], shape_u[2], shape_vt[2];
85
+ ndfunc_arg_in_t ain[1] = {{OVERWRITE,2}};
86
+ ndfunc_arg_out_t aout[4] = {{cRT,1,shape_s},{cT,2,shape_u},
87
+ {cT,2,shape_vt},{cInt,0}};
88
+ ndfunc_t ndf = {&<%=c_iter%>, NO_LOOP|NDF_EXTRACT, 1, 4, ain, aout};
89
+
90
+ args_t g;
91
+ VALUE opts[4] = {Qundef,Qundef,Qundef,Qundef};
92
+ VALUE kw_hash = Qnil;
93
+ ID kw_table[4] = {id_order,id_jobu,id_jobvt,id_jobz};
94
+
95
+ CHECK_FUNC(func_p,"<%=func_name%>");
96
+
97
+ rb_scan_args(argc, argv, "1:", &a, &kw_hash);
98
+ rb_get_kwargs(kw_hash, kw_table, 0, 4, opts);
99
+ g.order = option_order(opts[0]);
100
+ #if SDD
101
+ g.jobz = option_job(opts[3],'A','N');
102
+ g.jobu = g.jobvt = g.jobz;
103
+ #else
104
+ g.jobu = option_job(opts[1],'A','N');
105
+ g.jobvt = option_job(opts[2],'A','N');
106
+ if (g.jobu=='O' && g.jobvt=='O') {
107
+ rb_raise(rb_eArgError,"JOBVT and JOBU cannot both be 'O'");
108
+ }
109
+ #endif
110
+
111
+ if (g.jobu=='O' || g.jobvt=='O') {
112
+ if (CLASS_OF(a) != cT) {
113
+ rb_raise(rb_eTypeError,"type of matrix a is invalid for overwrite");
114
+ }
115
+ } else {
116
+ COPY_OR_CAST_TO(a,cT);
117
+ }
118
+
119
+ GetNArray(a, na1);
120
+ CHECK_DIM_GE(na1, 2);
121
+ m = ROW_SIZE(na1);
122
+ n = COL_SIZE(na1);
123
+ SWAP_IFCOL(g.order,m,n);
124
+
125
+ #if SDD
126
+ if (g.jobz=='O') {
127
+ if (m >= n) { g.jobvt='A';} else { g.jobu='A';}
128
+ }
129
+ #endif
130
+
131
+ // output S
132
+ shape_s[0] = min_mn = min_(m,n);
133
+
134
+ // output U
135
+ switch(g.jobu){
136
+ case 'A':
137
+ shape_u[0] = m;
138
+ shape_u[1] = m;
139
+ break;
140
+ case 'S':
141
+ shape_u[0] = m;
142
+ shape_u[1] = min_mn;
143
+ SWAP_IFCOL(g.order,shape_u[0],shape_u[1]);
144
+ break;
145
+ case 'O':
146
+ case 'N':
147
+ aout[1].dim = 0; // dummy
148
+ break;
149
+ default:
150
+ rb_raise(rb_eArgError,"invalid option: jobu='%c'",g.jobu);
151
+ }
152
+ // output VT
153
+ switch(g.jobvt){
154
+ case 'A':
155
+ shape_vt[0] = n;
156
+ shape_vt[1] = n;
157
+ break;
158
+ case 'S':
159
+ shape_vt[0] = min_mn;
160
+ shape_vt[1] = n;
161
+ SWAP_IFCOL(g.order, shape_vt[0], shape_vt[1]);
162
+ break;
163
+ case 'O':
164
+ case 'N':
165
+ aout[2].dim = 0; // dummy
166
+ break;
167
+ default:
168
+ rb_raise(rb_eArgError,"invalid option: jobvt='%c'",g.jobvt);
169
+ }
170
+ #if !SDD
171
+ g.superb = (rtype*)rb_alloc_tmp_buffer(&tmpbuf, min_mn*sizeof(rtype));
172
+ #endif
173
+
174
+ ans = na_ndloop3(&ndf, &g, 1, a);
175
+
176
+ #if !SDD
177
+ rb_free_tmp_buffer(&tmpbuf);
178
+ #endif
179
+
180
+ if (g.jobu=='O') { RARRAY_ASET(ans,1,a); } else
181
+ if (aout[1].dim == 0) { RARRAY_ASET(ans,1,Qnil); }
182
+ if (g.jobvt=='O') { RARRAY_ASET(ans,2,a); } else
183
+ if (aout[2].dim == 0) { RARRAY_ASET(ans,2,Qnil); }
184
+ return ans;
185
+ }
186
+
187
+ #undef args_t
188
+ #undef func_p
189
+ #undef SDD
@@ -0,0 +1,138 @@
1
+ #define args_t <%=func_name%>_args_t
2
+ #define func_p <%=func_name%>_p
3
+
4
+ typedef struct {
5
+ int order;
6
+ char jobvl, jobvr;
7
+ } args_t;
8
+
9
+ static <%=func_name%>_t func_p = 0;
10
+
11
+ static void
12
+ <%=c_iter%>(na_loop_t * const lp)
13
+ {
14
+ dtype *a, *b, *beta, *vl, *vr;
15
+ #if IS_COMPLEX
16
+ dtype *alpha;
17
+ #else
18
+ dtype *alphar, *alphai;
19
+ #endif
20
+ int *info;
21
+ int n, lda, ldb, ldvl, ldvr;
22
+ args_t *g;
23
+
24
+ a = (dtype*)NDL_PTR(lp,0);
25
+ b = (dtype*)NDL_PTR(lp,1);
26
+ #if IS_COMPLEX
27
+ alpha = (dtype*)NDL_PTR(lp,2);
28
+ #else
29
+ alphar = (dtype*)NDL_PTR(lp,2);
30
+ alphai = (dtype*)NDL_PTR(lp,3);
31
+ #endif
32
+ beta = (dtype*)NDL_PTR(lp,4-CZ);
33
+ vl = (dtype*)NDL_PTR(lp,5-CZ);
34
+ vr = (dtype*)NDL_PTR(lp,6-CZ);
35
+ info = (int*)NDL_PTR(lp,7-CZ);
36
+ g = (args_t*)(lp->opt_ptr);
37
+
38
+ n = NDL_SHAPE(lp,0)[1];
39
+ lda = NDL_STEP(lp,0) / sizeof(dtype);
40
+ ldb = NDL_STEP(lp,1) / sizeof(dtype);
41
+ ldvl = NDL_STEP(lp,5-CZ) / sizeof(dtype);
42
+ if (ldvl == 0) { ldvl = n; } // jobvl == 'N'
43
+ ldvr = NDL_STEP(lp,6-CZ) / sizeof(dtype);
44
+ if (ldvr == 0) { ldvr = n; } // jobvr == 'N'
45
+
46
+ //printf("order=%d jobvl=%c jobvr=%c n=%d lda=%d ldb=%d ldvl=%d ldvr=%d\n",g->order,g->jobvl, g->jobvr, n, lda,ldb,ldvl,ldvr);
47
+
48
+ /*<%
49
+ func_args = [
50
+ "g->order, g->jobvl, g->jobvr, n, a, lda, b, ldb",
51
+ is_complex ? "alpha" : "alphar, alphai",
52
+ "beta, vl, ldvl, vr, ldvr"
53
+ ].join(",")
54
+ %>*/
55
+ *info = (*func_p)(<%=func_args%>);
56
+ CHECK_ERROR(*info);
57
+ }
58
+
59
+ /*
60
+ <%
61
+ tp = class_name
62
+ return_type = ([tp]*(is_complex ? 4 : 5)+["Integer"]).join(", ")
63
+ return_name = (is_complex ? "alpha,":"alphar, alphai,")+" beta, vl, vr, info"
64
+ params = [
65
+ mat("a",:inplace),
66
+ mat("b",:inplace),
67
+ jobe("jobvl"),
68
+ jobe("jobvr"),
69
+ opt("order"),
70
+ ].select{|x| x}.join("\n ")
71
+ %>
72
+ @overload <%=name%>(a, b, [jobvl:'V', jobvr:'V', order:'R'] )
73
+ <%=params%>
74
+ @return [[<%=return_name%>]] Array<<%=return_type%>>
75
+ <%=outparam(return_name)%>
76
+
77
+ <%= description %>
78
+
79
+ */
80
+ static VALUE
81
+ <%=c_func(-1)%>(int argc, VALUE const argv[], VALUE UNUSED(mod))
82
+ {
83
+ VALUE a, b, ans;
84
+ int n, nb;
85
+ narray_t *na1, *na2;
86
+ /*<%
87
+ aout = [
88
+ "{cT,1,shape},{cT,1,shape}",
89
+ !is_complex ? "{cT,1,shape}":nil,
90
+ "{cT,2,shape},{cT,2,shape},{cInt,0}"
91
+ ].compact
92
+ %>*/
93
+ size_t shape[2];
94
+ ndfunc_arg_in_t ain[2] = {{OVERWRITE,2},{OVERWRITE,2}};
95
+ ndfunc_arg_out_t aout[6-CZ] = {<%=aout.join(",")%>};
96
+ ndfunc_t ndf = {&<%=c_iter%>, NO_LOOP|NDF_EXTRACT, 2, 6-CZ, ain, aout};
97
+
98
+ args_t g;
99
+ VALUE opts[3] = {Qundef,Qundef,Qundef};
100
+ VALUE kw_hash = Qnil;
101
+ ID kw_table[3] = {id_order,id_jobvl,id_jobvr};
102
+
103
+ CHECK_FUNC(func_p,"<%=func_name%>");
104
+
105
+ rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
106
+ rb_get_kwargs(kw_hash, kw_table, 0, 3, opts);
107
+ g.order = option_order(opts[0]);
108
+ g.jobvl = option_job(opts[1],'V','N');
109
+ g.jobvr = option_job(opts[2],'V','N');
110
+
111
+ COPY_OR_CAST_TO(a,cT);
112
+ GetNArray(a, na1);
113
+ CHECK_DIM_GE(na1, 2);
114
+
115
+ COPY_OR_CAST_TO(b,cT);
116
+ GetNArray(b, na2);
117
+ CHECK_DIM_GE(na2, 2);
118
+
119
+ CHECK_SQUARE("matrix a",na1);
120
+ n = COL_SIZE(na1);
121
+ CHECK_SQUARE("matrix b",na2);
122
+ nb = COL_SIZE(na2);
123
+ if (n != nb) {
124
+ rb_raise(nary_eShapeError,"matrix a and b must have same size");
125
+ }
126
+ shape[0] = shape[1] = n;
127
+ if (g.jobvl=='N') { aout[3-CZ].dim = 0; }
128
+ if (g.jobvr=='N') { aout[4-CZ].dim = 0; }
129
+
130
+ ans = na_ndloop3(&ndf, &g, 2, a, b);
131
+
132
+ if (aout[4-CZ].dim == 0) { RARRAY_ASET(ans,4-CZ,Qnil); }
133
+ if (aout[3-CZ].dim == 0) { RARRAY_ASET(ans,3-CZ,Qnil); }
134
+ return ans;
135
+ }
136
+
137
+ #undef args_t
138
+ #undef func_p