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,42 @@
1
+ #define lapack_complex_float scomplex
2
+ #define lapack_complex_double dcomplex
3
+ #include "lapacke.h"
4
+ #include "lapacke_t.h"
5
+ #include "../numo_linalg.h"
6
+
7
+ typedef int blasint;
8
+
9
+ #define option_value numo_lapacke_option_value
10
+ extern int numo_lapacke_option_value(VALUE value, VALUE default_value);
11
+
12
+ #define option_order numo_lapacke_option_order
13
+ extern int numo_lapacke_option_order(VALUE order);
14
+
15
+ #define option_job numo_lapacke_option_job
16
+ extern char numo_lapacke_option_job(VALUE job, char true_char, char false_char);
17
+
18
+ #define option_trans numo_lapacke_option_trans
19
+ extern char numo_lapacke_option_trans(VALUE trans);
20
+
21
+ #define option_uplo numo_lapacke_option_uplo
22
+ extern char numo_lapacke_option_uplo(VALUE uplo);
23
+
24
+ #define option_diag numo_lapacke_option_diag
25
+ extern char numo_lapacke_option_diag(VALUE diag);
26
+
27
+ #define option_side numo_lapacke_option_side
28
+ extern char numo_lapacke_option_side(VALUE side);
29
+
30
+ #define check_func numo_lapacke_check_func
31
+ extern void numo_lapacke_check_func(void **func, const char *name);
32
+
33
+ #define CHECK_ERROR(info) \
34
+ { if ((info)<0) { \
35
+ rb_raise(eLapackError,"LAPACK error, info=%d",(info)); \
36
+ }}
37
+
38
+ #define SWAP_IFCOL(order,a,b) \
39
+ { if ((order)==LAPACK_COL_MAJOR) {tmp=(a);(a)=(b);(b)=tmp;} }
40
+
41
+ #define CHECK_FUNC(fptr, fname) \
42
+ { if ((fptr)==0) { check_func((void*)(&(fptr)),fname); } }
@@ -0,0 +1,3 @@
1
+ #include "numo/types/scomplex.h"
2
+ #define CZ 1
3
+ #define IS_COMPLEX CZ
@@ -0,0 +1,7 @@
1
+ #include "numo/types/dfloat.h"
2
+ #define CZ 0
3
+ #define IS_COMPLEX CZ
4
+
5
+ #ifndef m_real
6
+ #define m_real(x) (x)
7
+ #endif
@@ -0,0 +1,7 @@
1
+ #include "numo/types/sfloat.h"
2
+ #define CZ 0
3
+ #define IS_COMPLEX CZ
4
+
5
+ #ifndef m_real
6
+ #define m_real(x) (x)
7
+ #endif
@@ -0,0 +1,3 @@
1
+ #include "numo/types/dcomplex.h"
2
+ #define CZ 1
3
+ #define IS_COMPLEX CZ
@@ -0,0 +1,179 @@
1
+ /*<%
2
+ has_uplo = (/^.(sy|he|po)/ =~ name)
3
+ has_jpvt = (/geqp3/ =~ name)
4
+ has_tau = (/q/ =~ name || /tzrzf/ =~ name)
5
+ %>*/
6
+ <% %>
7
+ #define UPLO <%= has_uplo ? "1":"0" %>
8
+ #define JPVT <%= has_jpvt ? "1":"0" %>
9
+ #define TAU <%= has_tau ? "1":"0" %>
10
+ #define args_t <%=func_name%>_args_t
11
+ #define func_p <%=func_name%>_p
12
+
13
+ typedef struct {
14
+ int order;
15
+ char uplo;
16
+ } args_t;
17
+
18
+ static <%=func_name%>_t func_p = 0;
19
+
20
+ static void
21
+ <%=c_iter%>(na_loop_t * const lp)
22
+ {
23
+ dtype *a;
24
+ #if JPVT
25
+ int *pv;
26
+ #endif
27
+ #if TAU
28
+ dtype *tau;
29
+ #endif
30
+ int *info;
31
+ int m, n, lda, tmp;
32
+ args_t *g;
33
+
34
+ a = (dtype*)NDL_PTR(lp,0);
35
+ #if JPVT
36
+ pv = (int*)NDL_PTR(lp,1);
37
+ #endif
38
+ #if TAU
39
+ tau = (dtype*)NDL_PTR(lp,1+JPVT);
40
+ #endif
41
+ info = (int*)NDL_PTR(lp,1+JPVT+TAU);
42
+ g = (args_t*)(lp->opt_ptr);
43
+
44
+ m = NDL_SHAPE(lp,0)[0];
45
+ n = NDL_SHAPE(lp,0)[1];
46
+ SWAP_IFCOL(g->order,m,n);
47
+ #if UPLO
48
+ n = min_(m,n);
49
+ #endif
50
+ lda = NDL_STEP(lp,0) / sizeof(dtype);
51
+
52
+ //printf("order=%d m=%d n=%d lda=%d \n",g->order,m,n,lda);
53
+
54
+ /*<%
55
+ func_args = [ "g->order",
56
+ has_uplo ? "g->uplo" : "m",
57
+ "n, a, lda",
58
+ has_jpvt && "pv",
59
+ has_tau && "tau",
60
+ ].select{|x| x}.join(", ")
61
+ %>*/
62
+ *info = (*func_p)(<%=func_args%>);
63
+ CHECK_ERROR(*info);
64
+ }
65
+
66
+ /*<%
67
+ args_v = [
68
+ "a",
69
+ has_jpvt && "jpvt",
70
+ ].select{|x| x}.join(", ")
71
+
72
+ args_opt = [
73
+ has_uplo && "uplo:'U'",
74
+ "order:'R'",
75
+ ].select{|x| x}.join(", ")
76
+
77
+ params = [
78
+ mat("a",:inplace),
79
+ has_uplo && opt("uplo"),
80
+ opt("order"),
81
+ ].select{|x| x}.join("\n ")
82
+
83
+ return_type = [
84
+ class_name,
85
+ has_jpvt && "Numo::Int",
86
+ has_tau && class_name,
87
+ "Integer"
88
+ ].select{|x| x}.join(", ")
89
+
90
+ return_name = [
91
+ "a",
92
+ has_jpvt && "jpvt",
93
+ has_tau && "tau",
94
+ "info"
95
+ ].select{|x| x}.join(", ")
96
+ %>
97
+ @overload <%=name%>(<%=args_v%>, [<%=args_opt%>])
98
+ <%=params%>
99
+ @return [[<%=return_name%>]] Array<<%=return_type%>>
100
+ <%=outparam(return_name)%>
101
+
102
+ <%=description%>
103
+
104
+ */
105
+ static VALUE
106
+ <%=c_func(-1)%>(int argc, VALUE const argv[], VALUE UNUSED(mod))
107
+ {
108
+ VALUE a, ans;
109
+ int m, n, tmp;
110
+ narray_t *na1;
111
+ #if JPVT
112
+ VALUE jpvt;
113
+ #endif
114
+ /*<%
115
+ ain = [ "{OVERWRITE,2}",
116
+ has_jpvt && "{OVERWRITE,1}",
117
+ ].select{|x| x}.join(",")
118
+ aout = [
119
+ has_tau && "{cT,1,shape_tau}",
120
+ "{cInt,0}",
121
+ ].select{|x| x}.join(",")
122
+ %>*/
123
+ #if TAU
124
+ size_t shape_tau[1];
125
+ #endif
126
+ ndfunc_arg_in_t ain[1+JPVT] = {<%=ain%>};
127
+ ndfunc_arg_out_t aout[1+TAU] = {<%=aout%>};
128
+ ndfunc_t ndf = {&<%=c_iter%>, NO_LOOP|NDF_EXTRACT,
129
+ 1+JPVT, TAU+1, ain,aout};
130
+
131
+ args_t g = {0,1};
132
+ VALUE opts[2] = {Qundef,Qundef};
133
+ VALUE kw_hash = Qnil;
134
+ ID kw_table[2] = {id_order,id_uplo};
135
+
136
+ CHECK_FUNC(func_p,"<%=func_name%>");
137
+
138
+ #if JPVT
139
+ rb_scan_args(argc, argv, "2:", &a, &jpvt, &kw_hash);
140
+ #else
141
+ rb_scan_args(argc, argv, "1:", &a, &kw_hash);
142
+ #endif
143
+ rb_get_kwargs(kw_hash, kw_table, 0, 1+UPLO, opts);
144
+ g.order = option_order(opts[0]);
145
+ #if UPLO
146
+ g.uplo = option_uplo(opts[1]);
147
+ #endif
148
+
149
+ COPY_OR_CAST_TO(a,cT);
150
+ GetNArray(a, na1);
151
+ CHECK_DIM_GE(na1, 2);
152
+ m = ROW_SIZE(na1);
153
+ n = COL_SIZE(na1);
154
+ SWAP_IFCOL(g.order,m,n);
155
+ #if TAU
156
+ shape_tau[0] = min_(m,n);
157
+ #endif
158
+
159
+ #if JPVT
160
+ COPY_OR_CAST_TO(jpvt,cInt);
161
+ ans = na_ndloop3(&ndf, &g, 2, a, jpvt);
162
+ rb_ary_concat(rb_ary_assoc(a,jpvt), ans);
163
+ return ans;
164
+ #else
165
+ ans = na_ndloop3(&ndf, &g, 1, a);
166
+ #if TAU == 0
167
+ return rb_assoc_new(a, ans);
168
+ #else
169
+ rb_ary_unshift(ans, a);
170
+ return ans;
171
+ #endif
172
+ #endif
173
+ }
174
+
175
+ #undef args_t
176
+ #undef func_p
177
+ #undef UPLO
178
+ #undef JPVT
179
+ #undef TAU
@@ -0,0 +1,123 @@
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, *vl, *vr;
15
+ #if IS_COMPLEX
16
+ dtype *w;
17
+ #else
18
+ dtype *wr, *wi;
19
+ #endif
20
+ int *info;
21
+ int n, lda, ldvl, ldvr;
22
+ args_t *g;
23
+
24
+ a = (dtype*)NDL_PTR(lp,0);
25
+ #if IS_COMPLEX
26
+ w = (dtype*)NDL_PTR(lp,1);
27
+ #else
28
+ wr = (dtype*)NDL_PTR(lp,1);
29
+ wi = (dtype*)NDL_PTR(lp,2);
30
+ #endif
31
+ vl = (dtype*)NDL_PTR(lp,3-CZ);
32
+ vr = (dtype*)NDL_PTR(lp,4-CZ);
33
+ info = (int*)NDL_PTR(lp,5-CZ);
34
+ g = (args_t*)(lp->opt_ptr);
35
+
36
+ n = NDL_SHAPE(lp,0)[1];
37
+ lda = NDL_STEP(lp,0) / sizeof(dtype);
38
+ ldvl = NDL_STEP(lp,3-CZ) / sizeof(dtype);
39
+ if (ldvl == 0) { ldvl = n; } // jobvt == 'N'
40
+ ldvr = NDL_STEP(lp,4-CZ) / sizeof(dtype);
41
+ if (ldvr == 0) { ldvr = n; } // jobvt == 'N'
42
+
43
+ //printf("order=%d jobvl=%c jobvr=%c n=%d lda=%d ldvl=%d ldvr=%d\n",g->order,g->jobvl, g->jobvr, n, lda,ldvl,ldvr);
44
+
45
+ /*<% func_args = [
46
+ "g->order, g->jobvl, g->jobvr, n, a, lda",
47
+ is_complex ? "w" : "wr, wi",
48
+ "vl, ldvl, vr, ldvr"
49
+ ].join(",") %>*/
50
+ *info = (*func_p)(<%=func_args%>);
51
+ CHECK_ERROR(*info);
52
+ }
53
+
54
+ /*<%
55
+ tp = class_name
56
+ return_type = ([tp]*(is_complex ? 3 : 4) + ["Integer"]).join(", ")
57
+ return_name = (is_complex ? "w,":"wr, wi,") + " vl, vr, info"
58
+ params = [
59
+ mat("a",:inplace),
60
+ jobe("jobvl"),
61
+ jobe("jobvr"),
62
+ opt("order"),
63
+ ].select{|x| x}.join("\n ")
64
+ %>
65
+ @overload <%=name%>( a,, [jobvl:'V', jobvr:'V', order:'R'] )
66
+ <%=params%>
67
+ @return [[<%=return_name%>]] Array<<%=return_type%>>
68
+ <%=outparam(return_name)%>
69
+
70
+ <%=description%>
71
+
72
+ */
73
+ static VALUE
74
+ <%=c_func(-1)%>(int argc, VALUE const argv[], VALUE UNUSED(mod))
75
+ {
76
+ VALUE a, ans;
77
+ int m, n;
78
+ narray_t *na1;
79
+ /*<%
80
+ aout = [
81
+ "{cT,1,shape}", !is_complex ? "{cT,1,shape}":nil,
82
+ "{cT,2,shape},{cT,2,shape},{cInt,0}"
83
+ ].compact.join(",")
84
+ %>*/
85
+ size_t shape[2];
86
+ ndfunc_arg_in_t ain[1] = {{OVERWRITE,2}};
87
+ ndfunc_arg_out_t aout[5-CZ] = {<%=aout%>};
88
+ ndfunc_t ndf = {&<%=c_iter%>, NO_LOOP|NDF_EXTRACT, 1, 5-CZ, ain, aout};
89
+
90
+ args_t g = {0,0,0};
91
+ VALUE opts[3] = {Qundef,Qundef,Qundef};
92
+ VALUE kw_hash = Qnil;
93
+ ID kw_table[3] = {id_order,id_jobvl,id_jobvr};
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, 3, opts);
99
+ g.order = option_order(opts[0]);
100
+ g.jobvl = option_job(opts[1],'V','N');
101
+ g.jobvr = option_job(opts[2],'V','N');
102
+
103
+ COPY_OR_CAST_TO(a,cT);
104
+ GetNArray(a, na1);
105
+ CHECK_DIM_GE(na1, 2);
106
+ m = ROW_SIZE(na1);
107
+ n = COL_SIZE(na1);
108
+ if (m != n) {
109
+ rb_raise(nary_eShapeError,"matrix must be square");
110
+ }
111
+ shape[0] = shape[1] = n;
112
+ if (g.jobvl=='N') { aout[2-CZ].dim = 0; }
113
+ if (g.jobvr=='N') { aout[3-CZ].dim = 0; }
114
+
115
+ ans = na_ndloop3(&ndf, &g, 1, a);
116
+
117
+ if (aout[3-CZ].dim == 0) { RARRAY_ASET(ans,3-CZ,Qnil); }
118
+ if (aout[2-CZ].dim == 0) { RARRAY_ASET(ans,2-CZ,Qnil); }
119
+ return ans;
120
+ }
121
+
122
+ #undef args_t
123
+ #undef func_p
@@ -0,0 +1,232 @@
1
+ /*<%
2
+ is_lss = (/gels(s|d|y)/ =~ name)
3
+ is_lsd = (/gelsd/ =~ name)
4
+ is_lsy = (/gelsy/ =~ name)
5
+ %>*/
6
+ <% %>
7
+ #define LSS <%=is_lss ? "1":"0"%>
8
+ #define LSD <%=is_lsd ? "1":"0"%>
9
+ #define LSY <%=is_lsy ? "1":"0"%>
10
+ #define args_t <%=func_name%>_args_t
11
+ #define func_p <%=func_name%>_p
12
+
13
+ typedef struct {
14
+ int order;
15
+ char trans;
16
+ rtype rcond;
17
+ } args_t;
18
+
19
+ static <%=func_name%>_t func_p = 0;
20
+
21
+ static void
22
+ <%=c_iter%>(na_loop_t * const lp)
23
+ {
24
+ dtype *a, *b;
25
+ int *info;
26
+ int m, n, nb, nrhs, lda, ldb, tmp;
27
+ args_t *g;
28
+ #if LSS
29
+ <% out_t = is_lsy ? "int" : "rtype" %>
30
+ <%=out_t%> *s; // or jpvt
31
+ int *rank;
32
+ #endif
33
+
34
+ a = (dtype*)NDL_PTR(lp,0);
35
+ b = (dtype*)NDL_PTR(lp,1);
36
+ #if LSS
37
+ s = (<%=out_t%>*)NDL_PTR(lp,2);
38
+ rank = (int*)NDL_PTR(lp,3);
39
+ #endif
40
+ info = (int*)NDL_PTR(lp,2+LSS*2);
41
+ g = (args_t*)(lp->opt_ptr);
42
+
43
+ m = NDL_SHAPE(lp,0)[0];
44
+ n = NDL_SHAPE(lp,0)[1];
45
+ SWAP_IFCOL(g->order,m,n);
46
+ lda = NDL_STEP(lp,0) / sizeof(dtype);
47
+
48
+ if (lp->args[1].ndim == 1) {
49
+ nrhs = 1;
50
+ nb = NDL_SHAPE(lp,1)[0];
51
+ ldb = (g->order==LAPACK_COL_MAJOR) ? nb : 1;
52
+ } else {
53
+ nb = NDL_SHAPE(lp,1)[0];
54
+ nrhs = NDL_SHAPE(lp,1)[1];
55
+ ldb = nrhs;
56
+ SWAP_IFCOL(g->order,nb,nrhs);
57
+ }
58
+
59
+ //printf("order=%d trans=%c m=%d n=%d nb=%d nrhs=%d lda=%d ldb=%d\n",g->order,g->trans,m,n,nb,nrhs,lda,ldb);
60
+
61
+ #if LSS
62
+ *info = (*func_p)(g->order, m, n, nrhs, a, lda, b, ldb, s, g->rcond, rank);
63
+ #else
64
+ *info = (*func_p)(g->order, g->trans, m, n, nrhs, a, lda, b, ldb);
65
+ #endif
66
+ CHECK_ERROR(*info);
67
+ }
68
+
69
+ /*
70
+ <%
71
+ tp = class_name
72
+ iary = "Numo::Int"
73
+ iscal = "Integer"
74
+ if is_lsy
75
+ a = "a, b, jpvt, rcond:-1, order:'R'"
76
+ t = [tp,tp,iary,iscal,iscal]
77
+ n = "a, b, jpvt, rank, info"
78
+ elsif is_lsd
79
+ a = "a, b, rcond:-1, order:'R'"
80
+ t = [tp,tp,iscal,iscal]
81
+ n = "b, s, rank, info"
82
+ elsif is_lss
83
+ a = "a, b, rcond:-1, order:'R'"
84
+ t = [tp,tp,tp,iscal,iscal]
85
+ n = "a, b, s, rank, info"
86
+ else
87
+ a = "a, b, trans:'N', order:'R'"
88
+ t = [tp,tp,iscal]
89
+ n = "a, b, info"
90
+ end
91
+ return_type = t.join(", ")
92
+ return_name = n
93
+ args_v = a
94
+ params = [
95
+ !is_lsd && mat("a",:inplace),
96
+ mat("b",:inplace),
97
+ is_lsy && mat("jpvt",type:iary),
98
+ is_lss && "@param [Float] rcond "+
99
+ " RCOND is used to determine the effective rank of A."+
100
+ " Singular values S(i) <= RCOND*S(1) are treated as zero."+
101
+ " If RCOND < 0, machine precision is used instead.",
102
+ opt("order"),
103
+ ].select{|x| x}.join("\n ")
104
+ %>
105
+ @overload <%=name%>(<%=args_v%>)
106
+ <%=params%>
107
+ @return [[<%=return_name%>]] Array<<%=return_type%>>
108
+ <%=outparam(return_name)%>
109
+
110
+ <%=description%>
111
+
112
+ */
113
+ static VALUE
114
+ <%=c_func(-1)%>(int argc, VALUE const argv[], VALUE UNUSED(mod))
115
+ {
116
+ VALUE a, b, ans;
117
+ int m, n, nb, nrhs, tmp;
118
+ int max_mn;
119
+ narray_t *na1, *na2;
120
+ #if LSY
121
+ narray_t *na3;
122
+ VALUE jpvt;
123
+ #endif
124
+ #if LSS
125
+ size_t shape_s[1];
126
+ #endif
127
+ /*<%
128
+ ain = [
129
+ "{OVERWRITE,2},{OVERWRITE,2}", is_lss ? "{cInt,1}":nil,
130
+ ].compact.join(",")
131
+ aout = [
132
+ is_lss ? "{cT,1,shape_s},{cInt,0}":nil, "{cInt,0}",
133
+ ].compact.join(",")
134
+ %>*/
135
+ ndfunc_arg_in_t ain[2+LSS] = {<%=ain%>};
136
+ ndfunc_arg_out_t aout[1+LSS*2] = {<%=aout%>};
137
+ ndfunc_t ndf = {&<%=c_iter%>, NO_LOOP|NDF_EXTRACT, 2, 1+LSS*2, ain, aout};
138
+
139
+ args_t g;
140
+ VALUE opts[3] = {Qundef,Qundef,Qundef};
141
+ ID kw_table[3] = {id_order,id_trans,id_rcond};
142
+ VALUE kw_hash = Qnil;
143
+
144
+ CHECK_FUNC(func_p,"<%=func_name%>");
145
+
146
+ #if LSY
147
+ rb_scan_args(argc, argv, "3:", &a, &b, &jpvt, &kw_hash);
148
+ #else
149
+ rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
150
+ #endif
151
+ rb_get_kwargs(kw_hash, kw_table, 0, 3, opts);
152
+ g.order = option_order(opts[0]);
153
+ #if LSS
154
+ g.rcond = NUM2DBL(option_value(opts[2],DBL2NUM(-1)));
155
+ #else
156
+ g.trans = option_trans(opts[1]);
157
+ #endif
158
+
159
+ //A is DOUBLE PRECISION array, dimension (LDA,N)
160
+ //On entry, the M-by-N matrix A.
161
+ COPY_OR_CAST_TO(a,cT);
162
+ GetNArray(a, na1);
163
+ CHECK_DIM_GE(na1, 2);
164
+
165
+ //B is DOUBLE PRECISION array, dimension (LDB,NRHS)
166
+ //B is M-by-NRHS if TRANS = 'N'
167
+ // N-by-NRHS if TRANS = 'T'
168
+ COPY_OR_CAST_TO(b,cT);
169
+ GetNArray(b, na2);
170
+ CHECK_DIM_GE(na2, 1);
171
+
172
+ //The number of rows of the matrix A.
173
+ m = ROW_SIZE(na1);
174
+ //The number of columns of the matrix A.
175
+ n = COL_SIZE(na1);
176
+ max_mn = (m > n) ? m : n;
177
+ SWAP_IFCOL(g.order,m,n);
178
+
179
+ #if LSY
180
+ ndf.nin++;
181
+ ndf.nout--;
182
+ ndf.aout++;
183
+ COPY_OR_CAST_TO(jpvt,cInt);
184
+ GetNArray(jpvt, na3);
185
+ CHECK_DIM_GE(na3, 1);
186
+ { int jpvt_sz = COL_SIZE(na3);
187
+ CHECK_INT_EQ("jpvt_size",jpvt_sz,"n",n);
188
+ }
189
+ #elif LSS
190
+ shape_s[0] = (m < n) ? m : n;
191
+ #endif
192
+
193
+ //The number of columns of the matrix B.
194
+ if (na2->ndim == 1) {
195
+ ain[1].dim = 1; // reduce dimension
196
+ nb = COL_SIZE(na2);
197
+ nrhs = 1;
198
+ } else {
199
+ //The number of rows of the matrix B.
200
+ nb = ROW_SIZE(na2);
201
+ nrhs = COL_SIZE(na2);
202
+ SWAP_IFCOL(g.order,nb,nrhs);
203
+ }
204
+ if (nb < max_mn) {
205
+ rb_raise(nary_eShapeError,
206
+ "ldb should be >= max(m,n): ldb=%d m=%d n=%d",nb,m,n);
207
+ }
208
+
209
+ // ndloop
210
+ #if LSY
211
+ ans = na_ndloop3(&ndf, &g, 3, a, b, jpvt);
212
+ #else
213
+ ans = na_ndloop3(&ndf, &g, 2, a, b);
214
+ #endif
215
+
216
+ // return
217
+ #if LSY
218
+ return rb_ary_concat(rb_ary_new3(3,a,b,jpvt),ans);
219
+ #elif LSD
220
+ rb_ary_unshift(ans,b); return ans;
221
+ #elif LSS
222
+ return rb_ary_concat(rb_ary_new3(2,a,b),ans);
223
+ #else
224
+ return rb_ary_new3(3,a,b,ans);
225
+ #endif
226
+ }
227
+
228
+ #undef func_p
229
+ #undef args_t
230
+ #undef LSS
231
+ #undef LSD
232
+ #undef LSY