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.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/README.md +80 -0
- data/Rakefile +18 -0
- data/ext/numo/linalg/blas/blas.c +352 -0
- data/ext/numo/linalg/blas/cblas.h +575 -0
- data/ext/numo/linalg/blas/cblas_t.h +563 -0
- data/ext/numo/linalg/blas/depend.erb +23 -0
- data/ext/numo/linalg/blas/extconf.rb +67 -0
- data/ext/numo/linalg/blas/gen/cogen.rb +72 -0
- data/ext/numo/linalg/blas/gen/decl.rb +203 -0
- data/ext/numo/linalg/blas/gen/desc.rb +8138 -0
- data/ext/numo/linalg/blas/gen/erbpp2.rb +339 -0
- data/ext/numo/linalg/blas/gen/replace_cblas_h.rb +27 -0
- data/ext/numo/linalg/blas/gen/spec.rb +93 -0
- data/ext/numo/linalg/blas/numo_blas.h +41 -0
- data/ext/numo/linalg/blas/tmpl/axpy.c +75 -0
- data/ext/numo/linalg/blas/tmpl/copy.c +57 -0
- data/ext/numo/linalg/blas/tmpl/def_c.c +3 -0
- data/ext/numo/linalg/blas/tmpl/def_d.c +3 -0
- data/ext/numo/linalg/blas/tmpl/def_s.c +3 -0
- data/ext/numo/linalg/blas/tmpl/def_z.c +3 -0
- data/ext/numo/linalg/blas/tmpl/dot.c +68 -0
- data/ext/numo/linalg/blas/tmpl/ger.c +114 -0
- data/ext/numo/linalg/blas/tmpl/init_class.c +20 -0
- data/ext/numo/linalg/blas/tmpl/init_module.c +12 -0
- data/ext/numo/linalg/blas/tmpl/lib.c +40 -0
- data/ext/numo/linalg/blas/tmpl/mm.c +214 -0
- data/ext/numo/linalg/blas/tmpl/module.c +9 -0
- data/ext/numo/linalg/blas/tmpl/mv.c +194 -0
- data/ext/numo/linalg/blas/tmpl/nrm2.c +79 -0
- data/ext/numo/linalg/blas/tmpl/rot.c +65 -0
- data/ext/numo/linalg/blas/tmpl/rotm.c +82 -0
- data/ext/numo/linalg/blas/tmpl/scal.c +69 -0
- data/ext/numo/linalg/blas/tmpl/sdsdot.c +77 -0
- data/ext/numo/linalg/blas/tmpl/set_prefix.c +16 -0
- data/ext/numo/linalg/blas/tmpl/swap.c +57 -0
- data/ext/numo/linalg/blas/tmpl/syr.c +102 -0
- data/ext/numo/linalg/blas/tmpl/syr2.c +110 -0
- data/ext/numo/linalg/blas/tmpl/syr2k.c +129 -0
- data/ext/numo/linalg/blas/tmpl/syrk.c +132 -0
- data/ext/numo/linalg/lapack/depend.erb +23 -0
- data/ext/numo/linalg/lapack/extconf.rb +45 -0
- data/ext/numo/linalg/lapack/gen/cogen.rb +74 -0
- data/ext/numo/linalg/lapack/gen/desc.rb +151278 -0
- data/ext/numo/linalg/lapack/gen/replace_lapacke_h.rb +32 -0
- data/ext/numo/linalg/lapack/gen/spec.rb +104 -0
- data/ext/numo/linalg/lapack/lapack.c +387 -0
- data/ext/numo/linalg/lapack/lapacke.h +16425 -0
- data/ext/numo/linalg/lapack/lapacke_config.h +119 -0
- data/ext/numo/linalg/lapack/lapacke_mangling.h +17 -0
- data/ext/numo/linalg/lapack/lapacke_t.h +10550 -0
- data/ext/numo/linalg/lapack/numo_lapack.h +42 -0
- data/ext/numo/linalg/lapack/tmpl/def_c.c +3 -0
- data/ext/numo/linalg/lapack/tmpl/def_d.c +7 -0
- data/ext/numo/linalg/lapack/tmpl/def_s.c +7 -0
- data/ext/numo/linalg/lapack/tmpl/def_z.c +3 -0
- data/ext/numo/linalg/lapack/tmpl/fact.c +179 -0
- data/ext/numo/linalg/lapack/tmpl/geev.c +123 -0
- data/ext/numo/linalg/lapack/tmpl/gels.c +232 -0
- data/ext/numo/linalg/lapack/tmpl/gesv.c +149 -0
- data/ext/numo/linalg/lapack/tmpl/gesvd.c +189 -0
- data/ext/numo/linalg/lapack/tmpl/ggev.c +138 -0
- data/ext/numo/linalg/lapack/tmpl/gqr.c +121 -0
- data/ext/numo/linalg/lapack/tmpl/init_class.c +20 -0
- data/ext/numo/linalg/lapack/tmpl/init_module.c +12 -0
- data/ext/numo/linalg/lapack/tmpl/lange.c +79 -0
- data/ext/numo/linalg/lapack/tmpl/lib.c +40 -0
- data/ext/numo/linalg/lapack/tmpl/module.c +9 -0
- data/ext/numo/linalg/lapack/tmpl/syev.c +91 -0
- data/ext/numo/linalg/lapack/tmpl/sygv.c +104 -0
- data/ext/numo/linalg/lapack/tmpl/trf.c +276 -0
- data/ext/numo/linalg/numo_linalg.h +115 -0
- data/lib/numo/linalg.rb +3 -0
- data/lib/numo/linalg/function.rb +1008 -0
- data/lib/numo/linalg/linalg.rb +7 -0
- data/lib/numo/linalg/loader.rb +174 -0
- data/lib/numo/linalg/use/atlas.rb +3 -0
- data/lib/numo/linalg/use/lapack.rb +3 -0
- data/lib/numo/linalg/use/mkl.rb +3 -0
- data/lib/numo/linalg/use/openblas.rb +3 -0
- data/lib/numo/linalg/version.rb +5 -0
- data/numo-linalg.gemspec +26 -0
- data/spec/lapack_spec.rb +13 -0
- 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,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
|