numo-linalg 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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