kmat 0.0.3
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/.gitattributes +3 -0
- data/.gitignore +15 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile +4 -0
- data/LICENSE.md +675 -0
- data/README.md +224 -0
- data/Rakefile +26 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ext/kmat/arith/binary.c +1121 -0
- data/ext/kmat/arith/logical.c +332 -0
- data/ext/kmat/arith/math.c +34 -0
- data/ext/kmat/arith/statistics.c +173 -0
- data/ext/kmat/arith/unary.c +165 -0
- data/ext/kmat/auto_collect.rb +118 -0
- data/ext/kmat/elementwise_function.rb +149 -0
- data/ext/kmat/extconf.rb +75 -0
- data/ext/kmat/id.txt +80 -0
- data/ext/kmat/id_sym.rb +40 -0
- data/ext/kmat/km_util.h +97 -0
- data/ext/kmat/kmat.h +96 -0
- data/ext/kmat/lapack_headers/blas.h +354 -0
- data/ext/kmat/lapack_headers/lapacke.h +19455 -0
- data/ext/kmat/lapack_headers/lapacke_config.h +119 -0
- data/ext/kmat/lapack_headers/lapacke_mangling.h +17 -0
- data/ext/kmat/lapack_headers/lapacke_utils.h +579 -0
- data/ext/kmat/linalg/dla.c +1629 -0
- data/ext/kmat/linalg/linalg.c +267 -0
- data/ext/kmat/linalg/norm.c +727 -0
- data/ext/kmat/linalg/vla.c +102 -0
- data/ext/kmat/linalg/working.c +240 -0
- data/ext/kmat/main.c +95 -0
- data/ext/kmat/smat/accessor.c +719 -0
- data/ext/kmat/smat/array.c +108 -0
- data/ext/kmat/smat/boxmuller.c +72 -0
- data/ext/kmat/smat/constructer.c +302 -0
- data/ext/kmat/smat/convert.c +375 -0
- data/ext/kmat/smat/elem.c +171 -0
- data/ext/kmat/smat/fund.c +702 -0
- data/ext/kmat/smat/share.c +427 -0
- data/ext/kmat/smat/smat.c +530 -0
- data/ext/kmat/smat/sort.c +1156 -0
- data/ext/kmat/sym.txt +34 -0
- data/kmat.gemspec +46 -0
- data/lib/kmat.rb +20 -0
- data/lib/kmat/accessor.rb +164 -0
- data/lib/kmat/arith.rb +189 -0
- data/lib/kmat/linalg.rb +279 -0
- data/lib/kmat/logical.rb +150 -0
- data/lib/kmat/misc.rb +122 -0
- data/lib/kmat/random.rb +106 -0
- data/lib/kmat/statistics.rb +98 -0
- data/lib/kmat/version.rb +3 -0
- metadata +156 -0
@@ -0,0 +1,427 @@
|
|
1
|
+
#include "../kmat.h"
|
2
|
+
|
3
|
+
// freeze `self' and all submatricies of `self'
|
4
|
+
// `self' must be a full-matrix (can't deep_freeze submatrix)
|
5
|
+
static void
|
6
|
+
km_mat_deep_freeze_func(VALUE *ent, void *null)
|
7
|
+
{
|
8
|
+
if ( rb_respond_to(*ent, id_deep_freeze) ) {
|
9
|
+
rb_funcall(*ent, id_deep_freeze, 0);
|
10
|
+
} else {
|
11
|
+
rb_obj_freeze(*ent);
|
12
|
+
}
|
13
|
+
}
|
14
|
+
static void
|
15
|
+
km_mat_deep_freeze0(VALUE self)
|
16
|
+
{
|
17
|
+
SMAT *smat = km_mat2smat(self);
|
18
|
+
if ( smat->vtype == VT_VALUE ) {
|
19
|
+
km_smat_each_v(smat, km_mat_deep_freeze_func, NULL);
|
20
|
+
}
|
21
|
+
}
|
22
|
+
VALUE
|
23
|
+
kmm_mat_deep_freeze(VALUE self)
|
24
|
+
{
|
25
|
+
SMAT *smat = km_mat2smat(self);
|
26
|
+
if ( smat->stype != ST_FULL ) {
|
27
|
+
rb_raise(km_eShare, "can't deep_freeze submatricies directory. deep_freeze supermatrix instead");
|
28
|
+
}
|
29
|
+
if ( smat->may_have_sub ) {
|
30
|
+
VALUE subs = kmm_mat_submatricies(self);
|
31
|
+
for ( long i=0; i<RARRAY_LEN(subs); i++ ) {
|
32
|
+
km_mat_deep_freeze0(rb_ary_entry(subs, i));
|
33
|
+
}
|
34
|
+
}
|
35
|
+
km_mat_deep_freeze0(self);
|
36
|
+
return self;
|
37
|
+
}
|
38
|
+
|
39
|
+
typedef int each_obj_callback(void *, void *, size_t, void *);
|
40
|
+
void rb_objspace_each_objects(each_obj_callback *callback, void *data);
|
41
|
+
int rb_objspace_internal_object_p(VALUE obj);
|
42
|
+
|
43
|
+
// return true if `self' has at least one submatrix, otherwise, return false
|
44
|
+
struct km_have_sub {
|
45
|
+
bool found;
|
46
|
+
VALUE target;
|
47
|
+
};
|
48
|
+
static int
|
49
|
+
km_have_sub_p(void *vstart, void *vend, size_t stride, void *data)
|
50
|
+
{
|
51
|
+
struct km_have_sub *have_sub = (struct km_have_sub *)data;
|
52
|
+
for (VALUE v = (VALUE)vstart; v != (VALUE)vend; v += stride) {
|
53
|
+
if (!rb_objspace_internal_object_p(v)) {
|
54
|
+
if (rb_obj_is_kind_of(v, km_cMat)) {
|
55
|
+
SMAT *smat = km_mat2smat(v);
|
56
|
+
if ( have_sub->target == smat->parent ) {
|
57
|
+
have_sub->found = true;
|
58
|
+
return 1;
|
59
|
+
}
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
return 0;
|
64
|
+
}
|
65
|
+
VALUE
|
66
|
+
kmm_mat_have_submatrix_p(VALUE self)
|
67
|
+
{
|
68
|
+
SMAT *smat = km_mat2smat(self);
|
69
|
+
if ( smat->may_have_sub ) {
|
70
|
+
struct km_have_sub data = {false, self};
|
71
|
+
rb_objspace_each_objects(km_have_sub_p, (void *)&data);
|
72
|
+
if ( data.found ) {
|
73
|
+
return Qtrue;
|
74
|
+
} else {
|
75
|
+
smat->may_have_sub = false;
|
76
|
+
return Qfalse;
|
77
|
+
}
|
78
|
+
} else {
|
79
|
+
return Qfalse;
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
// the SMAT version of above
|
84
|
+
bool
|
85
|
+
km_smat_have_submatrix_p(SMAT *smat)
|
86
|
+
{
|
87
|
+
if ( smat->may_have_sub ) {
|
88
|
+
VALUE v = km_smat_find_value(smat);
|
89
|
+
if ( v == Qnil ) {
|
90
|
+
rb_raise(km_eInternal, "km_smat_have_submatrix_p has been called with out-of-ruby-controlled Mat struct");
|
91
|
+
} else {
|
92
|
+
return (kmm_mat_have_submatrix_p(v) != Qfalse);
|
93
|
+
}
|
94
|
+
} else {
|
95
|
+
return false;
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
// find VALUE of `smat' from ObjectSpace.each_object
|
100
|
+
// return Qnil if not found
|
101
|
+
struct km_find_value {
|
102
|
+
SMAT *target;
|
103
|
+
VALUE out;
|
104
|
+
};
|
105
|
+
static int
|
106
|
+
km_find_value(void *vstart, void *vend, size_t stride, void *data)
|
107
|
+
{
|
108
|
+
struct km_find_value *fv = (struct km_find_value *)data;
|
109
|
+
for (VALUE v = (VALUE)vstart; v != (VALUE)vend; v += stride) {
|
110
|
+
if (!rb_objspace_internal_object_p(v)) {
|
111
|
+
if ( rb_obj_is_kind_of(v, km_cMat) && km_mat2smat(v) == fv->target ) {
|
112
|
+
fv->out = v;
|
113
|
+
return 1;
|
114
|
+
}
|
115
|
+
}
|
116
|
+
}
|
117
|
+
return 0;
|
118
|
+
}
|
119
|
+
VALUE
|
120
|
+
km_smat_find_value(SMAT *smat)
|
121
|
+
{
|
122
|
+
struct km_find_value data = {smat, Qnil};
|
123
|
+
rb_objspace_each_objects(km_find_value, (void *)&data);
|
124
|
+
return data.out;
|
125
|
+
}
|
126
|
+
|
127
|
+
// return an Array submatricies of `self'
|
128
|
+
// the return will be nil if `self' is a submatrix (submatrix cannot have a submatrix of itself)
|
129
|
+
// the return will be an empty Array ([]) if `self' is full-matrix but does not have any submatricies
|
130
|
+
struct km_submx {
|
131
|
+
VALUE parent;
|
132
|
+
VALUE list;
|
133
|
+
};
|
134
|
+
static int
|
135
|
+
km_mat_submx(void *vstart, void *vend, size_t stride, void *data)
|
136
|
+
{
|
137
|
+
struct km_submx *sm = (struct km_submx *)data;
|
138
|
+
for ( VALUE v = (VALUE)vstart; v != (VALUE)vend; v += stride ) {
|
139
|
+
if (!rb_objspace_internal_object_p(v)) {
|
140
|
+
if ( rb_obj_is_kind_of(v, km_cMat) && km_mat2smat(v)->parent == sm->parent ) {
|
141
|
+
rb_ary_push(sm->list, v);
|
142
|
+
}
|
143
|
+
}
|
144
|
+
}
|
145
|
+
return 0;
|
146
|
+
}
|
147
|
+
VALUE
|
148
|
+
kmm_mat_submatricies(VALUE self)
|
149
|
+
{
|
150
|
+
SMAT *smat = km_mat2smat(self);
|
151
|
+
if ( smat->stype != ST_FULL ) {
|
152
|
+
return Qnil;
|
153
|
+
} else if ( !smat->may_have_sub ) {
|
154
|
+
return rb_ary_new();
|
155
|
+
}
|
156
|
+
struct km_submx data = {self, rb_ary_new()};
|
157
|
+
rb_objspace_each_objects(km_mat_submx, (void *)&data);
|
158
|
+
if ( RARRAY_LEN(data.list) == 0 ) {
|
159
|
+
smat->may_have_sub = false;
|
160
|
+
}
|
161
|
+
return data.list;
|
162
|
+
}
|
163
|
+
|
164
|
+
// return supermatrix of `self'
|
165
|
+
// the return will be nil if `self' is full-matrix
|
166
|
+
VALUE
|
167
|
+
kmm_mat_supermatrix(VALUE self)
|
168
|
+
{
|
169
|
+
SMAT *data = km_mat2smat(self);
|
170
|
+
return data->parent;
|
171
|
+
}
|
172
|
+
|
173
|
+
// if `self' is a supermatrix of some submatricies, detach all the submatricies by replacing them by copied full-matrix
|
174
|
+
// if `self' is a submatrix of a supermatrix, replace `self' by a copied full-matrix of 'self'
|
175
|
+
// return self if at least a matrix is replaced, otherwise, return nil
|
176
|
+
VALUE
|
177
|
+
kmm_mat_detach(int argc, VALUE *argv, VALUE self)
|
178
|
+
{
|
179
|
+
rb_check_arity(argc, 0, 1);
|
180
|
+
bool check_other = ( ( argc == 1 ) && RTEST(argv[0]) );
|
181
|
+
SMAT *smat = km_mat2smat(self);
|
182
|
+
if ( smat->stype == ST_FULL ) {
|
183
|
+
VALUE list = kmm_mat_submatricies(self);
|
184
|
+
if ( !smat->may_have_sub ) {
|
185
|
+
return Qnil;
|
186
|
+
}
|
187
|
+
for (long i=0; i<RARRAY_LEN(list); i++) {
|
188
|
+
VALUE elm = rb_ary_entry(list, i);
|
189
|
+
kmm_mat_replace(elm, rb_obj_dup(elm));
|
190
|
+
}
|
191
|
+
smat->may_have_sub = false;
|
192
|
+
return self;
|
193
|
+
} else {
|
194
|
+
VALUE old_parent = smat->parent;
|
195
|
+
kmm_mat_replace(self, rb_obj_dup(self));
|
196
|
+
if ( check_other ) {
|
197
|
+
kmm_mat_submatricies(old_parent);
|
198
|
+
}
|
199
|
+
return self;
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
203
|
+
// if `self' is a supermatrix of some submatricies, detach all the submatricies by replacing them by (0, 0)-matrix
|
204
|
+
// if `self' is a submatrix of a supermatrix, detach from the supermatrix
|
205
|
+
// in any case, `self' is replaced by (0, 0)-matrix, and return `self'
|
206
|
+
static VALUE
|
207
|
+
km_kill_func(VALUE elm, VALUE nil, VALUE self)
|
208
|
+
{
|
209
|
+
SMAT *ssub = km_mat2smat(elm);
|
210
|
+
if ( ssub->stype != ST_SSUB ) {
|
211
|
+
ruby_xfree(ssub->body);
|
212
|
+
}
|
213
|
+
ssub->stype = ST_FULL;
|
214
|
+
ssub->body = NULL;
|
215
|
+
ssub->m = 0; ssub->n = 0; ssub->ld = 0;
|
216
|
+
ssub->parent = Qnil;
|
217
|
+
return elm;
|
218
|
+
}
|
219
|
+
VALUE
|
220
|
+
kmm_mat__kill(VALUE self)
|
221
|
+
{
|
222
|
+
km_check_frozen(self);
|
223
|
+
SMAT *smat = km_mat2smat(self);
|
224
|
+
if ( smat->stype == ST_FULL ) {
|
225
|
+
VALUE list = kmm_mat_submatricies(self);
|
226
|
+
rb_iterate(rb_ary_each, list, km_kill_func, Qnil);
|
227
|
+
}
|
228
|
+
if ( smat->stype != ST_SSUB ) {
|
229
|
+
ruby_xfree(smat->body);
|
230
|
+
}
|
231
|
+
smat->stype = ST_FULL;
|
232
|
+
smat->body = NULL;
|
233
|
+
smat->m = 0; smat->n = 0; smat->ld = 0;
|
234
|
+
smat->may_have_sub = false; smat->parent = Qnil;
|
235
|
+
return self;
|
236
|
+
}
|
237
|
+
|
238
|
+
// replace the substance of `self' by `val'
|
239
|
+
// if `val' is a submatrix, `self' is a submatrix of the same supermatrix
|
240
|
+
// if `val' is a full-matrix, `self' is a copy of it (submatricies are not succeeded)
|
241
|
+
VALUE
|
242
|
+
kmm_mat_replace(VALUE self, VALUE val)
|
243
|
+
{
|
244
|
+
km_check_frozen(self);
|
245
|
+
SMAT *dest = km_mat2smat(self);
|
246
|
+
SMAT *src = km_mat2smat(val);
|
247
|
+
if ( kmm_mat_have_submatrix_p(self) ) {
|
248
|
+
rb_raise(km_eShare, "can't replace supermatrix. try detach before replacing");
|
249
|
+
}
|
250
|
+
if ( src->stype == ST_FULL ) {
|
251
|
+
switch ( dest->stype ) {
|
252
|
+
case ST_RSUB:
|
253
|
+
ruby_xfree(dest->body);
|
254
|
+
// FALL THROUGH
|
255
|
+
case ST_SSUB:
|
256
|
+
dest->vtype = VT_END;
|
257
|
+
dest->stype = ST_FULL;
|
258
|
+
dest->parent = Qnil;
|
259
|
+
dest->may_have_sub = false;
|
260
|
+
dest->body = NULL;
|
261
|
+
break;
|
262
|
+
default:
|
263
|
+
break;
|
264
|
+
}
|
265
|
+
km_smat_copy(dest, src);
|
266
|
+
} else if ( src->stype == ST_SSUB ) {
|
267
|
+
if ( dest->stype != ST_SSUB ) {
|
268
|
+
ruby_xfree(dest->body);
|
269
|
+
}
|
270
|
+
dest->body = src->body;
|
271
|
+
dest->ld = src->ld; dest->m = src->m; dest->n = src->n;
|
272
|
+
dest->vtype = src->vtype; dest->stype = ST_SSUB;
|
273
|
+
dest->trans = src->trans;
|
274
|
+
dest->parent = src->parent;
|
275
|
+
} else if ( src->stype == ST_RSUB ) {
|
276
|
+
if ( dest->stype != ST_RSUB || LENGTH(dest) != LENGTH(src) ) {
|
277
|
+
if ( dest->stype != ST_SSUB ) {
|
278
|
+
ruby_xfree(dest->body);
|
279
|
+
}
|
280
|
+
dest->body = ruby_xcalloc(LENGTHs(src), sizeof(void*));
|
281
|
+
}
|
282
|
+
memcpy(dest->body, src->body, sizeof(void*)*LENGTHs(src));
|
283
|
+
dest->ld = src->ld; dest->m = src->m; dest->n = src->n;
|
284
|
+
dest->vtype = src->vtype; dest->stype = ST_RSUB;
|
285
|
+
dest->trans = src->trans;
|
286
|
+
dest->parent = src->parent;
|
287
|
+
} else {
|
288
|
+
rb_raise(km_eInternal, "unknown storage type");
|
289
|
+
}
|
290
|
+
return self;
|
291
|
+
}
|
292
|
+
|
293
|
+
VALUE
|
294
|
+
km_Mat_ssub(int i, int j, int m, int n, VALUE super)
|
295
|
+
{
|
296
|
+
SMAT *ssup = km_mat2smat(super);
|
297
|
+
if ( ssup->m < i+m || ssup->n < j+n ) {
|
298
|
+
rb_raise(rb_eIndexError, "given index+size (%d+%d, %d+%d) is out of range (%d, %d)", i, m, j, n, ssup->m, ssup->n);
|
299
|
+
}
|
300
|
+
SMAT *sret;
|
301
|
+
if ( ssup->stype == ST_FULL ) {
|
302
|
+
VT_SWITCH( ssup->vtype,
|
303
|
+
sret = km_smat_alloc_with(m, n, VT_DOUBLE, ssup->dbody+INDEX(ssup, i, j));,
|
304
|
+
sret = km_smat_alloc_with(m, n, VT_COMPLEX, ssup->zbody+INDEX(ssup, i, j));,
|
305
|
+
sret = km_smat_alloc_with(m, n, VT_INT, ssup->ibody+INDEX(ssup, i, j));,
|
306
|
+
sret = km_smat_alloc_with(m, n, VT_BOOL, ssup->bbody+INDEX(ssup, i, j));,
|
307
|
+
sret = km_smat_alloc_with(m, n, VT_VALUE, ssup->vbody+INDEX(ssup, i, j));
|
308
|
+
);
|
309
|
+
sret->parent = super;
|
310
|
+
ssup->may_have_sub = true;
|
311
|
+
} else if ( ssup->stype == ST_SSUB ) {
|
312
|
+
VT_SWITCH( ssup->vtype,
|
313
|
+
sret = km_smat_alloc_with(m, n, VT_DOUBLE, ssup->dbody+INDEX(ssup, i, j));,
|
314
|
+
sret = km_smat_alloc_with(m, n, VT_COMPLEX, ssup->zbody+INDEX(ssup, i, j));,
|
315
|
+
sret = km_smat_alloc_with(m, n, VT_INT, ssup->ibody+INDEX(ssup, i, j));,
|
316
|
+
sret = km_smat_alloc_with(m, n, VT_BOOL, ssup->bbody+INDEX(ssup, i, j));,
|
317
|
+
sret = km_smat_alloc_with(m, n, VT_VALUE, ssup->vbody+INDEX(ssup, i, j));
|
318
|
+
);
|
319
|
+
sret->parent = ssup->parent;
|
320
|
+
} else if ( ssup->stype == ST_RSUB ) {
|
321
|
+
int is[m]; int js[n];
|
322
|
+
for ( int k=0; k<m; k++ ) { is[k] = i+k; }
|
323
|
+
for ( int k=0; k<n; k++ ) { js[k] = j+k; }
|
324
|
+
return km_Mat_rsub1(m, n, is, js, super);
|
325
|
+
} else {
|
326
|
+
rb_raise(km_eInternal, "unknown storage type");
|
327
|
+
}
|
328
|
+
sret->trans=ssup->trans; sret->ld = ssup->ld; sret->stype = ST_SSUB;
|
329
|
+
VALUE ret = TypedData_Wrap_Struct(km_cMat, &km_mat_data_type, sret);
|
330
|
+
km_infect_frozen(super, ret);
|
331
|
+
return ret;
|
332
|
+
}
|
333
|
+
|
334
|
+
static void
|
335
|
+
km_rsub_check_range(SMAT *ssup, int ii, int jj)
|
336
|
+
{
|
337
|
+
if ( ii < 0 || ssup->m <= ii || jj < 0 || ssup->n <= jj ) {
|
338
|
+
rb_raise(rb_eIndexError, "given index (%d, %d) is out of range (%d, %d)", ii, jj, ssup->m, ssup->n);
|
339
|
+
}
|
340
|
+
}
|
341
|
+
#define RSUB1_LOOPr(id) for ( int i=0; i<m; i++ ) { for ( int j=0; j<n; j++ ) { \
|
342
|
+
km_rsub_check_range(ssup, is[i], js[j]); \
|
343
|
+
sret->id##pbody[i+j*m] = ssup->id##pbody[INDEX(ssup, is[i], js[j])]; \
|
344
|
+
} }
|
345
|
+
#define RSUB1_LOOP(id) for ( int i=0; i<m; i++ ) { for ( int j=0; j<n; j++ ) { \
|
346
|
+
km_rsub_check_range(ssup, is[i], js[j]); \
|
347
|
+
sret->id##pbody[i+j*m] = ssup->id##body + INDEX(ssup, is[i], js[j]); \
|
348
|
+
} }
|
349
|
+
VALUE
|
350
|
+
km_Mat_rsub1(int m, int n, int *is, int *js, VALUE super)
|
351
|
+
{
|
352
|
+
km_check_positive(m, n);
|
353
|
+
VALUE ret = km_Mat_alloc(km_cMat);
|
354
|
+
SMAT *ssup = km_mat2smat(super);
|
355
|
+
SMAT *sret = km_mat2smat(ret);
|
356
|
+
km_smat_alloc_pbody(sret, m, n, ssup->vtype);
|
357
|
+
if ( ssup->stype == ST_RSUB ) {
|
358
|
+
VT_SWITCH( ssup->vtype,
|
359
|
+
RSUB1_LOOPr(d);,
|
360
|
+
RSUB1_LOOPr(z);,
|
361
|
+
RSUB1_LOOPr(i);,
|
362
|
+
RSUB1_LOOPr(b);,
|
363
|
+
RSUB1_LOOPr(v);
|
364
|
+
);
|
365
|
+
sret->parent = ssup->parent;
|
366
|
+
} else {
|
367
|
+
VT_SWITCH( ssup->vtype,
|
368
|
+
RSUB1_LOOP(d);,
|
369
|
+
RSUB1_LOOP(z);,
|
370
|
+
RSUB1_LOOP(i);,
|
371
|
+
RSUB1_LOOP(b);,
|
372
|
+
RSUB1_LOOP(v);
|
373
|
+
);
|
374
|
+
if ( ssup->stype == ST_FULL ) {
|
375
|
+
sret->parent = super;
|
376
|
+
ssup->may_have_sub = true;
|
377
|
+
} else {
|
378
|
+
sret->parent = ssup->parent;
|
379
|
+
}
|
380
|
+
}
|
381
|
+
km_infect_frozen(super, ret);
|
382
|
+
return ret;
|
383
|
+
}
|
384
|
+
|
385
|
+
#define RSUB2_LOOPr(id) for( int i=0; i<m; i++ ) { for ( int j=0; j<n; j++ ) { \
|
386
|
+
km_rsub_check_range(ssup, is[i+j*m], js[i+j*m]); \
|
387
|
+
sret->id##pbody[i+j*m] = ssup->id##pbody[INDEX(ssup, is[i+j*m], js[i+j*m])]; \
|
388
|
+
} }
|
389
|
+
#define RSUB2_LOOP(id) for( int i=0; i<m; i++ ) { for ( int j=0; j<n; j++ ) { \
|
390
|
+
km_rsub_check_range(ssup, is[i+j*m], js[i+j*m]); \
|
391
|
+
sret->id##pbody[i+j*m] = ssup->id##body+INDEX(ssup, is[i+j*m], js[i+j*m]); \
|
392
|
+
} }
|
393
|
+
VALUE
|
394
|
+
km_Mat_rsub2(int m, int n, int *is, int *js, VALUE super)
|
395
|
+
{
|
396
|
+
km_check_positive(m, n);
|
397
|
+
VALUE ret = km_Mat_alloc(km_cMat);
|
398
|
+
SMAT *ssup = km_mat2smat(super);
|
399
|
+
SMAT *sret = km_mat2smat(ret);
|
400
|
+
km_smat_alloc_pbody(sret, m, n, ssup->vtype);
|
401
|
+
if ( ssup->stype == ST_RSUB ) {
|
402
|
+
VT_SWITCH( ssup->vtype,
|
403
|
+
RSUB2_LOOPr(d);,
|
404
|
+
RSUB2_LOOPr(z);,
|
405
|
+
RSUB2_LOOPr(i);,
|
406
|
+
RSUB2_LOOPr(b);,
|
407
|
+
RSUB2_LOOPr(v);
|
408
|
+
);
|
409
|
+
sret->parent = ssup->parent;
|
410
|
+
} else {
|
411
|
+
VT_SWITCH( ssup->vtype,
|
412
|
+
RSUB2_LOOP(d);,
|
413
|
+
RSUB2_LOOP(z);,
|
414
|
+
RSUB2_LOOP(i);,
|
415
|
+
RSUB2_LOOP(b);,
|
416
|
+
RSUB2_LOOP(v);
|
417
|
+
);
|
418
|
+
if ( ssup->stype == ST_FULL ) {
|
419
|
+
sret->parent = super;
|
420
|
+
ssup->may_have_sub = true;
|
421
|
+
} else {
|
422
|
+
sret->parent = ssup->parent;
|
423
|
+
}
|
424
|
+
}
|
425
|
+
km_infect_frozen(super, ret);
|
426
|
+
return ret;
|
427
|
+
}
|
@@ -0,0 +1,530 @@
|
|
1
|
+
#include "../kmat.h"
|
2
|
+
|
3
|
+
static void
|
4
|
+
km_rb_gc_mark_wrap(VALUE *obj, void *null)
|
5
|
+
{
|
6
|
+
rb_gc_mark(*obj);
|
7
|
+
}
|
8
|
+
static void
|
9
|
+
km_smat_mark(void *_data)
|
10
|
+
{
|
11
|
+
SMAT *data = (SMAT *)_data;
|
12
|
+
rb_gc_mark(data->parent);
|
13
|
+
if ( data->vtype == VT_VALUE && data->body != NULL ) {
|
14
|
+
km_smat_each_v(data, km_rb_gc_mark_wrap, NULL);
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
static void
|
19
|
+
km_smat_free(void *_data)
|
20
|
+
{
|
21
|
+
SMAT *data = (SMAT *)_data;
|
22
|
+
if ( data != NULL ) {
|
23
|
+
if ( data->stype != ST_SSUB && data->body != NULL ) {
|
24
|
+
ruby_xfree(data->body);
|
25
|
+
}
|
26
|
+
ruby_xfree(data);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
static size_t
|
31
|
+
km_smat_size(const void *_data)
|
32
|
+
{
|
33
|
+
const SMAT *data = (const SMAT *)_data;
|
34
|
+
if ( data != NULL ) {
|
35
|
+
size_t ret = sizeof(SMAT);
|
36
|
+
if ( data->body != NULL ) {
|
37
|
+
if ( data->stype == ST_FULL ) {
|
38
|
+
ret += km_sizeof_vt(data->vtype)*int2size_t(data->m*data->n);
|
39
|
+
} else if ( data->stype == ST_RSUB ) {
|
40
|
+
ret += sizeof(void *)*int2size_t(data->m*data->n);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
return ret;
|
44
|
+
} else {
|
45
|
+
return (size_t)0;
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
// functions for allocation
|
50
|
+
const rb_data_type_t km_mat_data_type = {
|
51
|
+
"kmat-Mat",
|
52
|
+
{
|
53
|
+
km_smat_mark,
|
54
|
+
km_smat_free,
|
55
|
+
km_smat_size,
|
56
|
+
{ (void *)0, (void *)0 }
|
57
|
+
},
|
58
|
+
(rb_data_type_t *)0,
|
59
|
+
(void *)0,
|
60
|
+
(VALUE)0
|
61
|
+
};
|
62
|
+
VALUE
|
63
|
+
km_Mat_alloc(VALUE klass)
|
64
|
+
{
|
65
|
+
return TypedData_Wrap_Struct(klass, &km_mat_data_type, km_smat_alloc_with(0, 0, VT_END, NULL));
|
66
|
+
}
|
67
|
+
|
68
|
+
// calloc a side of SMAT
|
69
|
+
// return->body is the argument `body'
|
70
|
+
SMAT *
|
71
|
+
km_smat_alloc_with(int m, int n, VTYPE vt, void *body)
|
72
|
+
{
|
73
|
+
km_check_positive(m, n);
|
74
|
+
SMAT *data = ZALLOC(SMAT);
|
75
|
+
data->body = body; data->ld = data->m = m; data->n = n;
|
76
|
+
data->vtype = vt; data->stype = ST_FULL; data->trans = false;
|
77
|
+
data->may_have_sub = false; data->parent = Qnil;
|
78
|
+
return data;
|
79
|
+
}
|
80
|
+
|
81
|
+
SMAT *
|
82
|
+
km_smat_alloc(int m, int n, VTYPE vt)
|
83
|
+
{
|
84
|
+
km_check_positive(m, n);
|
85
|
+
void *body = ruby_xcalloc(int2size_t(n*m), km_sizeof_vt(vt));
|
86
|
+
return km_smat_alloc_with(m, n, vt, body);
|
87
|
+
}
|
88
|
+
|
89
|
+
// calloc a SMAT of (m, n)-matrix
|
90
|
+
// return->body will be calloc-ed
|
91
|
+
void
|
92
|
+
km_smat_alloc_body(SMAT *data, int m, int n, VTYPE vt)
|
93
|
+
{
|
94
|
+
km_check_positive(m, n);
|
95
|
+
if ( data->stype != ST_FULL ) {
|
96
|
+
rb_raise(km_eShare, "can't re-alloc submatrix body");
|
97
|
+
} else if ( km_smat_have_submatrix_p(data) ) {
|
98
|
+
rb_raise(km_eShare, "can't re-alloc supermatrix body");
|
99
|
+
}
|
100
|
+
data->ld = data->m = m; data->n = n; data->vtype = vt; data->stype = ST_FULL;
|
101
|
+
ruby_xfree(data->body);
|
102
|
+
data->body = ruby_xcalloc(int2size_t(n*m), km_sizeof_vt(vt));
|
103
|
+
}
|
104
|
+
void
|
105
|
+
km_smat_alloc_pbody(SMAT *data, int m, int n, VTYPE vt)
|
106
|
+
{
|
107
|
+
km_check_positive(m, n);
|
108
|
+
if ( data->stype != ST_FULL ) {
|
109
|
+
rb_raise(km_eShare, "can't re-alloc submatrix body");
|
110
|
+
} else if ( km_smat_have_submatrix_p(data) ) {
|
111
|
+
rb_raise(km_eShare, "can't re-alloc supermatrix body");
|
112
|
+
}
|
113
|
+
data->ld = data->m = m; data->n = n; data->vtype = vt; data->stype = ST_RSUB;
|
114
|
+
ruby_xfree(data->body);
|
115
|
+
data->body = ruby_xcalloc(int2size_t(n*m), sizeof(void*));
|
116
|
+
}
|
117
|
+
|
118
|
+
|
119
|
+
// extract and return SMAT from mat_obj
|
120
|
+
SMAT *
|
121
|
+
km_mat2smat(VALUE mat_obj)
|
122
|
+
{
|
123
|
+
SMAT *data;
|
124
|
+
if ( !rb_obj_is_kind_of(mat_obj, km_cMat) ) {
|
125
|
+
rb_raise(rb_eTypeError, "Mat is expected, not %s", rb_obj_classname(mat_obj));
|
126
|
+
}
|
127
|
+
TypedData_Get_Struct(mat_obj, SMAT, &km_mat_data_type, data);
|
128
|
+
return data;
|
129
|
+
}
|
130
|
+
|
131
|
+
// copy the content of SMAT
|
132
|
+
// if the size are not same, calloc before copying
|
133
|
+
#define DEFINE_SMAT_COPY(id, type) static void \
|
134
|
+
km_smat_copy_##id(type *ed, const type *es, void *null) \
|
135
|
+
{ \
|
136
|
+
*ed = *es; \
|
137
|
+
}
|
138
|
+
DEFINE_SMAT_COPY(d, double)
|
139
|
+
DEFINE_SMAT_COPY(z, COMPLEX)
|
140
|
+
DEFINE_SMAT_COPY(i, int)
|
141
|
+
DEFINE_SMAT_COPY(b, bool)
|
142
|
+
DEFINE_SMAT_COPY(v, VALUE)
|
143
|
+
void
|
144
|
+
km_smat_copy(SMAT *dest, const SMAT *src)
|
145
|
+
{
|
146
|
+
if ( src->body == NULL ) {
|
147
|
+
ruby_xfree(dest->body);
|
148
|
+
dest->body = NULL;
|
149
|
+
} else {
|
150
|
+
if ( dest->vtype != src->vtype || LENGTH(dest) != LENGTH(src) ) { // re-calloc
|
151
|
+
if ( dest->stype != ST_FULL ) { // the destination must not be a submatrix
|
152
|
+
rb_raise(km_eShare, "can't copy to value-type mismatched or dimension mismatched submatrix");
|
153
|
+
}
|
154
|
+
ruby_xfree(dest->body);
|
155
|
+
dest->body = ruby_xcalloc(LENGTHs(src), km_sizeof_vt(src->vtype));
|
156
|
+
dest->ld = src->m; dest->vtype = src->vtype;
|
157
|
+
} else if ( dest->m != src->m ) { // need not to resize but reshape is needed
|
158
|
+
if ( dest->stype != ST_FULL ) { // the destination must not be a submatrix
|
159
|
+
rb_raise(km_eShare, "can't reshape submatrix");
|
160
|
+
}
|
161
|
+
dest->ld = src->m;
|
162
|
+
}
|
163
|
+
dest->m = src->m; dest->n = src->n;
|
164
|
+
if ( dest->stype==ST_FULL && src->stype==ST_FULL ) {
|
165
|
+
dest->ld = src->ld; dest->trans = src->trans;
|
166
|
+
memcpy(dest->body, src->body, km_sizeof_vt(src->vtype)*LENGTHs(src));
|
167
|
+
} else {
|
168
|
+
VT_SWITCH( dest->vtype,
|
169
|
+
km_smat_each2_dcd(dest, src, km_smat_copy_d, NULL);,
|
170
|
+
km_smat_each2_zcz(dest, src, km_smat_copy_z, NULL);,
|
171
|
+
km_smat_each2_ici(dest, src, km_smat_copy_i, NULL);,
|
172
|
+
km_smat_each2_bcb(dest, src, km_smat_copy_b, NULL);,
|
173
|
+
km_smat_each2_vcv(dest, src, km_smat_copy_v, NULL);
|
174
|
+
);
|
175
|
+
}
|
176
|
+
}
|
177
|
+
}
|
178
|
+
|
179
|
+
// Mat#marhsal_dump/load for Marshal.dump/load
|
180
|
+
// return an Array with 2 elements
|
181
|
+
// the first element is a bytes (String) which contains shape and value type
|
182
|
+
// the second element is `self'.to_ary if the value type is ruby-object
|
183
|
+
// otherwise, the second element is a bytes (String) which is the same as `self'->body
|
184
|
+
// the supermatrix-submatrix information will not be saved
|
185
|
+
VALUE
|
186
|
+
kmm_mat_marshal_dump(VALUE self)
|
187
|
+
{
|
188
|
+
SMAT *smat = km_mat2smat(self);
|
189
|
+
if ( smat->stype != ST_FULL ) {
|
190
|
+
smat = km_mat2smat(rb_obj_dup(self));
|
191
|
+
}
|
192
|
+
VALUE headder = rb_str_new((char *)&(smat->vtype), sizeof(VTYPE));
|
193
|
+
VALUE body;
|
194
|
+
if ( smat->vtype == VT_VALUE ) {
|
195
|
+
body = kmm_mat_to_ary(self);
|
196
|
+
} else {
|
197
|
+
rb_str_cat(headder, (char *)&(smat->m), sizeof(int));
|
198
|
+
rb_str_cat(headder, (char *)&(smat->n), sizeof(int));
|
199
|
+
rb_str_cat(headder, (char *)&(smat->trans), sizeof(bool));
|
200
|
+
body = rb_str_new((char *)(smat->body), (long)km_sizeof_vt(smat->vtype)*LENGTH(smat));
|
201
|
+
}
|
202
|
+
return rb_ary_new3(2, headder, body);
|
203
|
+
}
|
204
|
+
VALUE
|
205
|
+
kmm_mat_marshal_load(VALUE self, VALUE dump)
|
206
|
+
{
|
207
|
+
SMAT *smat = km_mat2smat(self);
|
208
|
+
char *hptr = RSTRING_PTR(rb_ary_entry(dump, 0));
|
209
|
+
VALUE body = rb_ary_entry(dump, 1);
|
210
|
+
memcpy(&(smat->vtype), hptr, sizeof(VTYPE));
|
211
|
+
if ( smat->vtype == VT_VALUE ) {
|
212
|
+
km_smat_copy(smat, km_mat2smat(kmm_ary_to_omat(body)));
|
213
|
+
} else {
|
214
|
+
hptr += sizeof(VTYPE);
|
215
|
+
int m, n; bool t;
|
216
|
+
memcpy(&m, hptr, sizeof(int)); hptr += sizeof(int);
|
217
|
+
memcpy(&n, hptr, sizeof(int)); hptr += sizeof(int);
|
218
|
+
memcpy(&t, hptr, sizeof(bool)); hptr += sizeof(bool);
|
219
|
+
km_smat_alloc_body(smat, m, n, smat->vtype);
|
220
|
+
smat->trans = t;
|
221
|
+
size_t sb = km_sizeof_vt(smat->vtype)*LENGTHs(smat);
|
222
|
+
if ( RSTRING_LEN(body) != (long)sb ) {
|
223
|
+
rb_raise(rb_eArgError, "wrong object given");
|
224
|
+
}
|
225
|
+
memcpy(smat->body, RSTRING_PTR(body), sb);
|
226
|
+
}
|
227
|
+
return self;
|
228
|
+
}
|
229
|
+
|
230
|
+
// call `func'(&element, `data') for each elements of `smat'
|
231
|
+
#define DEFINE_KM_SMAT_EACH_ID(id, type) void \
|
232
|
+
km_smat_each_##id(SMAT *smat, void (*func)(type *, void *), void *data) \
|
233
|
+
{ \
|
234
|
+
if ( smat->stype == ST_RSUB ) { \
|
235
|
+
if ( smat->trans ) { \
|
236
|
+
for ( int i=0; i<smat->m; i++ ) { for ( int j=0; j<smat->n; j++ ) { \
|
237
|
+
func(smat->id##pbody[j+i*(smat->ld)], data); \
|
238
|
+
} } \
|
239
|
+
} else { \
|
240
|
+
for ( int i=0; i<smat->m; i++ ) { for ( int j=0; j<smat->n; j++ ) { \
|
241
|
+
func(smat->id##pbody[i+j*(smat->ld)], data); \
|
242
|
+
} } \
|
243
|
+
} \
|
244
|
+
} else { \
|
245
|
+
if ( smat->trans ) { \
|
246
|
+
for ( int i=0; i<smat->m; i++ ) { for ( int j=0; j<smat->n; j++ ) { \
|
247
|
+
func(&(smat->id##body[j+i*(smat->ld)]), data); \
|
248
|
+
} } \
|
249
|
+
} else { \
|
250
|
+
for ( int i=0; i<smat->m; i++ ) { for ( int j=0; j<smat->n; j++ ) { \
|
251
|
+
func(&(smat->id##body[i+j*(smat->ld)]), data); \
|
252
|
+
} } \
|
253
|
+
} \
|
254
|
+
} \
|
255
|
+
}
|
256
|
+
DEFINE_KM_SMAT_EACH_ID(d, double)
|
257
|
+
DEFINE_KM_SMAT_EACH_ID(z, COMPLEX)
|
258
|
+
DEFINE_KM_SMAT_EACH_ID(i, int)
|
259
|
+
DEFINE_KM_SMAT_EACH_ID(b, bool)
|
260
|
+
DEFINE_KM_SMAT_EACH_ID(v, VALUE)
|
261
|
+
|
262
|
+
// call `func'(&element, `data', i, j) for each elements of `smat'
|
263
|
+
#define DEFINE_KM_SMAT_EACH_WI_ID(id, type) void \
|
264
|
+
km_smat_each_with_index_##id(SMAT *smat, void (*func)(type *, int, int, void *), void *data) \
|
265
|
+
{ \
|
266
|
+
if ( smat->stype == ST_RSUB ) { \
|
267
|
+
if ( smat->trans ) { \
|
268
|
+
for ( int i=0; i<smat->m; i++ ) { for ( int j=0; j<smat->n; j++ ) { \
|
269
|
+
func(smat->id##pbody[j+i*(smat->ld)], i, j, data); \
|
270
|
+
} } \
|
271
|
+
} else { \
|
272
|
+
for ( int i=0; i<smat->m; i++ ) { for ( int j=0; j<smat->n; j++ ) { \
|
273
|
+
func(smat->id##pbody[i+j*(smat->ld)], i, j, data); \
|
274
|
+
} } \
|
275
|
+
} \
|
276
|
+
} else { \
|
277
|
+
if ( smat->trans ) { \
|
278
|
+
for ( int i=0; i<smat->m; i++ ) { for ( int j=0; j<smat->n; j++ ) { \
|
279
|
+
func(&(smat->id##body[j+i*(smat->ld)]), i, j, data); \
|
280
|
+
} } \
|
281
|
+
} else { \
|
282
|
+
for ( int i=0; i<smat->m; i++ ) { for ( int j=0; j<smat->n; j++ ) { \
|
283
|
+
func(&(smat->id##body[i+j*(smat->ld)]), i, j, data); \
|
284
|
+
} } \
|
285
|
+
} \
|
286
|
+
} \
|
287
|
+
}
|
288
|
+
DEFINE_KM_SMAT_EACH_WI_ID(d, double)
|
289
|
+
DEFINE_KM_SMAT_EACH_WI_ID(z, COMPLEX)
|
290
|
+
DEFINE_KM_SMAT_EACH_WI_ID(i, int)
|
291
|
+
DEFINE_KM_SMAT_EACH_WI_ID(b, bool)
|
292
|
+
DEFINE_KM_SMAT_EACH_WI_ID(v, VALUE)
|
293
|
+
|
294
|
+
// call `func'(&(element of sa), &(element of sb), `data') for each elements of `sa'
|
295
|
+
// you must check the shape of `sb' is the same as that of `sa'
|
296
|
+
// SEGV will occur if `sb' is smaller than `sa'
|
297
|
+
#define KM_SMAT_EACH2_BLOOP(elma, id) if ( sb->stype == ST_RSUB ) { \
|
298
|
+
if ( sb->trans ) { \
|
299
|
+
for ( int i=0; i<sa->m; i++ ) { for ( int j=0; j<sa->n; j++ ) { \
|
300
|
+
func(elma, sb->id##pbody[j+i*(sb->ld)], data); \
|
301
|
+
} } \
|
302
|
+
} else { \
|
303
|
+
for ( int i=0; i<sa->m; i++ ) { for ( int j=0; j<sa->n; j++ ) { \
|
304
|
+
func(elma, sb->id##pbody[i+j*(sb->ld)], data); \
|
305
|
+
} } \
|
306
|
+
} \
|
307
|
+
} else { \
|
308
|
+
if ( sb->trans ) { \
|
309
|
+
for ( int i=0; i<sa->m; i++ ) { for ( int j=0; j<sa->n; j++ ) { \
|
310
|
+
func(elma, &(sb->id##body[j+i*(sb->ld)]), data); \
|
311
|
+
} } \
|
312
|
+
} else { \
|
313
|
+
for ( int i=0; i<sa->m; i++ ) { for ( int j=0; j<sa->n; j++ ) { \
|
314
|
+
func(elma, &(sb->id##body[i+j*(sb->ld)]), data); \
|
315
|
+
} } \
|
316
|
+
} \
|
317
|
+
}
|
318
|
+
#define DEFINE_KM_SMAT_EACH2_ID(id, type) void \
|
319
|
+
km_smat_each2_##id(SMAT *sa, SMAT *sb, void (*func)(type *, type *, void *), void *data) \
|
320
|
+
{ \
|
321
|
+
if ( sa->stype == ST_RSUB ) { \
|
322
|
+
if ( sa->trans ) { \
|
323
|
+
KM_SMAT_EACH2_BLOOP(sa->id##pbody[j+i*(sa->ld)], id) \
|
324
|
+
} else { \
|
325
|
+
KM_SMAT_EACH2_BLOOP(sa->id##pbody[i+j*(sa->ld)], id) \
|
326
|
+
} \
|
327
|
+
} else { \
|
328
|
+
if ( sa->trans ) { \
|
329
|
+
KM_SMAT_EACH2_BLOOP(&(sa->id##body[j+i*(sa->ld)]), id) \
|
330
|
+
} else { \
|
331
|
+
KM_SMAT_EACH2_BLOOP(&(sa->id##body[i+j*(sa->ld)]), id) \
|
332
|
+
} \
|
333
|
+
} \
|
334
|
+
}
|
335
|
+
#define DEFINE_KM_SMAT_EACH2_ID_CONST_ID(id, type, id2, type2) void \
|
336
|
+
km_smat_each2_##id##c##id2(SMAT *sa, const SMAT *sb, void (*func)(type *, const type2 *, void *), void *data) \
|
337
|
+
{ \
|
338
|
+
if ( sa->stype == ST_RSUB ) { \
|
339
|
+
if ( sa->trans ) { \
|
340
|
+
KM_SMAT_EACH2_BLOOP(sa->id##pbody[j+i*(sa->ld)], id2) \
|
341
|
+
} else { \
|
342
|
+
KM_SMAT_EACH2_BLOOP(sa->id##pbody[i+j*(sa->ld)], id2) \
|
343
|
+
} \
|
344
|
+
} else { \
|
345
|
+
if ( sa->trans ) { \
|
346
|
+
KM_SMAT_EACH2_BLOOP(&(sa->id##body[j+i*(sa->ld)]), id2) \
|
347
|
+
} else { \
|
348
|
+
KM_SMAT_EACH2_BLOOP(&(sa->id##body[i+j*(sa->ld)]), id2) \
|
349
|
+
} \
|
350
|
+
} \
|
351
|
+
}
|
352
|
+
DEFINE_KM_SMAT_EACH2_ID(d, double)
|
353
|
+
DEFINE_KM_SMAT_EACH2_ID(z, COMPLEX)
|
354
|
+
DEFINE_KM_SMAT_EACH2_ID(i, int)
|
355
|
+
DEFINE_KM_SMAT_EACH2_ID(b, bool)
|
356
|
+
DEFINE_KM_SMAT_EACH2_ID(v, VALUE)
|
357
|
+
DEFINE_KM_SMAT_EACH2_ID_CONST_ID(d, double, d, double)
|
358
|
+
DEFINE_KM_SMAT_EACH2_ID_CONST_ID(z, COMPLEX, z, COMPLEX)
|
359
|
+
DEFINE_KM_SMAT_EACH2_ID_CONST_ID(i, int, i, int)
|
360
|
+
DEFINE_KM_SMAT_EACH2_ID_CONST_ID(b, bool, b, bool)
|
361
|
+
DEFINE_KM_SMAT_EACH2_ID_CONST_ID(v, VALUE, v, VALUE)
|
362
|
+
DEFINE_KM_SMAT_EACH2_ID_CONST_ID(d, double, b, bool)
|
363
|
+
DEFINE_KM_SMAT_EACH2_ID_CONST_ID(z, COMPLEX, b, bool)
|
364
|
+
DEFINE_KM_SMAT_EACH2_ID_CONST_ID(i, int, b, bool)
|
365
|
+
DEFINE_KM_SMAT_EACH2_ID_CONST_ID(v, VALUE, b, bool)
|
366
|
+
DEFINE_KM_SMAT_EACH2_ID_CONST_ID(d, double, z, COMPLEX)
|
367
|
+
|
368
|
+
// call `func'(&(element of sa), &(element of sb), &(element of sc), `data') for each elements of `sa'
|
369
|
+
// you must check the shape of `sb' and that of `sc' are the same as that of `sa'
|
370
|
+
// SEGV will occur if `sb' or `sc' is smaller than `sa'
|
371
|
+
#define KM_SMAT_EACH3_CLOOP(elma, elmb, id) if ( sc->stype == ST_RSUB ) { \
|
372
|
+
if ( sc->trans ) { \
|
373
|
+
for ( int i=0; i<sa->m; i++ ) { for ( int j=0; j<sa->n; j++ ) { \
|
374
|
+
func(elma, elmb, sc->id##pbody[j+i*(sc->ld)], data); \
|
375
|
+
} } \
|
376
|
+
} else { \
|
377
|
+
for ( int i=0; i<sa->m; i++ ) { for ( int j=0; j<sa->n; j++ ) { \
|
378
|
+
func(elma, elmb, sc->id##pbody[i+j*(sc->ld)], data); \
|
379
|
+
} } \
|
380
|
+
} \
|
381
|
+
} else { \
|
382
|
+
if ( sc->trans ) { \
|
383
|
+
for ( int i=0; i<sa->m; i++ ) { for ( int j=0; j<sa->n; j++ ) { \
|
384
|
+
func(elma, elmb, &(sc->id##body[j+i*(sc->ld)]), data); \
|
385
|
+
} } \
|
386
|
+
} else { \
|
387
|
+
for ( int i=0; i<sa->m; i++ ) { for ( int j=0; j<sa->n; j++ ) { \
|
388
|
+
func(elma, elmb, &(sc->id##body[i+j*(sc->ld)]), data); \
|
389
|
+
} } \
|
390
|
+
} \
|
391
|
+
}
|
392
|
+
#define KM_SMAT_EACH3_BLOOP(elma, id) if ( sb->stype == ST_RSUB ) { \
|
393
|
+
if ( sb->trans ) { \
|
394
|
+
KM_SMAT_EACH3_CLOOP(elma, sb->id##pbody[j+i*(sb->ld)], id) \
|
395
|
+
} else { \
|
396
|
+
KM_SMAT_EACH3_CLOOP(elma, sb->id##pbody[i+j*(sb->ld)], id) \
|
397
|
+
} \
|
398
|
+
} else { \
|
399
|
+
if ( sb->trans ) { \
|
400
|
+
KM_SMAT_EACH3_CLOOP(elma, &(sb->id##body[j+i*(sb->ld)]), id) \
|
401
|
+
} else { \
|
402
|
+
KM_SMAT_EACH3_CLOOP(elma, &(sb->id##body[i+j*(sb->ld)]), id) \
|
403
|
+
} \
|
404
|
+
}
|
405
|
+
#define DEFINE_KM_SMAT_EACH3_ID(id, type) void \
|
406
|
+
km_smat_each3_##id(SMAT *sa, SMAT *sb, SMAT *sc, void (*func)(type *, type *, type *, void *), void *data) \
|
407
|
+
{ \
|
408
|
+
if ( sa->stype == ST_RSUB ) { \
|
409
|
+
if ( sa->trans ) { \
|
410
|
+
KM_SMAT_EACH3_BLOOP(sa->id##pbody[j+i*(sa->ld)], id) \
|
411
|
+
} else { \
|
412
|
+
KM_SMAT_EACH3_BLOOP(sa->id##pbody[i+j*(sa->ld)], id) \
|
413
|
+
} \
|
414
|
+
} else { \
|
415
|
+
if ( sa->trans ) { \
|
416
|
+
KM_SMAT_EACH3_BLOOP(&(sa->id##body[j+i*(sa->ld)]), id) \
|
417
|
+
} else { \
|
418
|
+
KM_SMAT_EACH3_BLOOP(&(sa->id##body[i+j*(sa->ld)]), id) \
|
419
|
+
} \
|
420
|
+
} \
|
421
|
+
}
|
422
|
+
// DEFINE_KM_SMAT_EACH3_ID(d, double)
|
423
|
+
// DEFINE_KM_SMAT_EACH3_ID(z, COMPLEX)
|
424
|
+
// DEFINE_KM_SMAT_EACH3_ID(i, int)
|
425
|
+
// DEFINE_KM_SMAT_EACH3_ID(b, bool)
|
426
|
+
// DEFINE_KM_SMAT_EACH3_ID(v, VALUE)
|
427
|
+
void
|
428
|
+
km_smat_each3_zcdcd(SMAT *sa, const SMAT *sb, const SMAT *sc, void (*func)(COMPLEX *, const double *, const double *, void *), void *data)
|
429
|
+
{
|
430
|
+
if ( sa->stype == ST_RSUB ) {
|
431
|
+
if ( sa->trans ) {
|
432
|
+
KM_SMAT_EACH3_BLOOP(sa->zpbody[j+i*(sa->ld)], d)
|
433
|
+
} else {
|
434
|
+
KM_SMAT_EACH3_BLOOP(sa->zpbody[i+j*(sa->ld)], d)
|
435
|
+
}
|
436
|
+
} else {
|
437
|
+
if ( sa->trans ) {
|
438
|
+
KM_SMAT_EACH3_BLOOP(&(sa->zbody[j+i*(sa->ld)]), d)
|
439
|
+
} else {
|
440
|
+
KM_SMAT_EACH3_BLOOP(&(sa->zbody[i+j*(sa->ld)]), d)
|
441
|
+
}
|
442
|
+
}
|
443
|
+
}
|
444
|
+
|
445
|
+
void
|
446
|
+
km_smat_each3_bcdcd(SMAT *sa, const SMAT *sb, const SMAT *sc, void (*func)(bool *, const double *, const double *, void *), void *data)
|
447
|
+
{
|
448
|
+
if ( sa->stype == ST_RSUB ) {
|
449
|
+
if ( sa->trans ) {
|
450
|
+
KM_SMAT_EACH3_BLOOP(sa->bpbody[j+i*(sa->ld)], d)
|
451
|
+
} else {
|
452
|
+
KM_SMAT_EACH3_BLOOP(sa->bpbody[i+j*(sa->ld)], d)
|
453
|
+
}
|
454
|
+
} else {
|
455
|
+
if ( sa->trans ) {
|
456
|
+
KM_SMAT_EACH3_BLOOP(&(sa->bbody[j+i*(sa->ld)]), d)
|
457
|
+
} else {
|
458
|
+
KM_SMAT_EACH3_BLOOP(&(sa->bbody[i+j*(sa->ld)]), d)
|
459
|
+
}
|
460
|
+
}
|
461
|
+
}
|
462
|
+
void
|
463
|
+
km_smat_each3_bczcz(SMAT *sa, const SMAT *sb, const SMAT *sc, void (*func)(bool *, const COMPLEX *, const COMPLEX *, void *), void *data)
|
464
|
+
{
|
465
|
+
if ( sa->stype == ST_RSUB ) {
|
466
|
+
if ( sa->trans ) {
|
467
|
+
KM_SMAT_EACH3_BLOOP(sa->bpbody[j+i*(sa->ld)], z)
|
468
|
+
} else {
|
469
|
+
KM_SMAT_EACH3_BLOOP(sa->bpbody[i+j*(sa->ld)], z)
|
470
|
+
}
|
471
|
+
} else {
|
472
|
+
if ( sa->trans ) {
|
473
|
+
KM_SMAT_EACH3_BLOOP(&(sa->bbody[j+i*(sa->ld)]), z)
|
474
|
+
} else {
|
475
|
+
KM_SMAT_EACH3_BLOOP(&(sa->bbody[i+j*(sa->ld)]), z)
|
476
|
+
}
|
477
|
+
}
|
478
|
+
}
|
479
|
+
void
|
480
|
+
km_smat_each3_bcici(SMAT *sa, const SMAT *sb, const SMAT *sc, void (*func)(bool *, const int *, const int *, void *), void *data)
|
481
|
+
{
|
482
|
+
if ( sa->stype == ST_RSUB ) {
|
483
|
+
if ( sa->trans ) {
|
484
|
+
KM_SMAT_EACH3_BLOOP(sa->bpbody[j+i*(sa->ld)], i)
|
485
|
+
} else {
|
486
|
+
KM_SMAT_EACH3_BLOOP(sa->bpbody[i+j*(sa->ld)], i)
|
487
|
+
}
|
488
|
+
} else {
|
489
|
+
if ( sa->trans ) {
|
490
|
+
KM_SMAT_EACH3_BLOOP(&(sa->bbody[j+i*(sa->ld)]), i)
|
491
|
+
} else {
|
492
|
+
KM_SMAT_EACH3_BLOOP(&(sa->bbody[i+j*(sa->ld)]), i)
|
493
|
+
}
|
494
|
+
}
|
495
|
+
}
|
496
|
+
void
|
497
|
+
km_smat_each3_bcbcb(SMAT *sa, const SMAT *sb, const SMAT *sc, void (*func)(bool *, const bool *, const bool *, void *), void *data)
|
498
|
+
{
|
499
|
+
if ( sa->stype == ST_RSUB ) {
|
500
|
+
if ( sa->trans ) {
|
501
|
+
KM_SMAT_EACH3_BLOOP(sa->bpbody[j+i*(sa->ld)], b)
|
502
|
+
} else {
|
503
|
+
KM_SMAT_EACH3_BLOOP(sa->bpbody[i+j*(sa->ld)], b)
|
504
|
+
}
|
505
|
+
} else {
|
506
|
+
if ( sa->trans ) {
|
507
|
+
KM_SMAT_EACH3_BLOOP(&(sa->bbody[j+i*(sa->ld)]), b)
|
508
|
+
} else {
|
509
|
+
KM_SMAT_EACH3_BLOOP(&(sa->bbody[i+j*(sa->ld)]), b)
|
510
|
+
}
|
511
|
+
}
|
512
|
+
}
|
513
|
+
void
|
514
|
+
km_smat_each3_bcvcv(SMAT *sa, const SMAT *sb, const SMAT *sc, void (*func)(bool *, const VALUE *, const VALUE *, void *), void *data)
|
515
|
+
{
|
516
|
+
if ( sa->stype == ST_RSUB ) {
|
517
|
+
if ( sa->trans ) {
|
518
|
+
KM_SMAT_EACH3_BLOOP(sa->bpbody[j+i*(sa->ld)], v)
|
519
|
+
} else {
|
520
|
+
KM_SMAT_EACH3_BLOOP(sa->bpbody[i+j*(sa->ld)], v)
|
521
|
+
}
|
522
|
+
} else {
|
523
|
+
if ( sa->trans ) {
|
524
|
+
KM_SMAT_EACH3_BLOOP(&(sa->bbody[j+i*(sa->ld)]), v)
|
525
|
+
} else {
|
526
|
+
KM_SMAT_EACH3_BLOOP(&(sa->bbody[i+j*(sa->ld)]), v)
|
527
|
+
}
|
528
|
+
}
|
529
|
+
}
|
530
|
+
|