narray-bigmem 0.0.0
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/ChangeLog +602 -0
- data/MANIFEST +54 -0
- data/README +41 -0
- data/README_NARRAY.en +49 -0
- data/README_NARRAY.ja +52 -0
- data/SPEC.en +327 -0
- data/SPEC.ja +307 -0
- data/ext/narray/depend +14 -0
- data/ext/narray/extconf.rb +123 -0
- data/ext/narray/mkmath.rb +792 -0
- data/ext/narray/mknafunc.rb +212 -0
- data/ext/narray/mkop.rb +734 -0
- data/ext/narray/na_array.c +659 -0
- data/ext/narray/na_func.c +1709 -0
- data/ext/narray/na_index.c +1021 -0
- data/ext/narray/na_linalg.c +635 -0
- data/ext/narray/na_random.c +444 -0
- data/ext/narray/narray.c +1341 -0
- data/ext/narray/narray.def +29 -0
- data/ext/narray/narray.h +231 -0
- data/ext/narray/narray_local.h +218 -0
- data/lib/narray.rb +4 -0
- data/lib/narray_ext.rb +362 -0
- data/lib/nmatrix.rb +248 -0
- metadata +94 -0
@@ -0,0 +1,1709 @@
|
|
1
|
+
/*
|
2
|
+
na_func.c
|
3
|
+
Numerical Array Extention for Ruby
|
4
|
+
(C) Copyright 1999-2008 by Masahiro TANAKA
|
5
|
+
|
6
|
+
This program is free software.
|
7
|
+
You can distribute/modify this program
|
8
|
+
under the same terms as Ruby itself.
|
9
|
+
NO WARRANTY.
|
10
|
+
*/
|
11
|
+
#include <ruby.h>
|
12
|
+
#include "narray.h"
|
13
|
+
#include "narray_local.h"
|
14
|
+
|
15
|
+
void
|
16
|
+
na_shape_max3(int ndim, na_shape_t *max_shp, na_shape_t *shp1, na_shape_t *shp2, na_shape_t *shp3)
|
17
|
+
{
|
18
|
+
int i;
|
19
|
+
|
20
|
+
for (i=0; i<ndim; ++i) {
|
21
|
+
max_shp[i] = NA_MAX3(shp1[i], shp2[i], shp3[i]);
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
|
26
|
+
/* initialize slice structure */
|
27
|
+
void na_init_slice( struct slice *s, int rank, na_shape_t *shape, int elmsz )
|
28
|
+
{
|
29
|
+
int r, b;
|
30
|
+
na_shape_t i, *idx;
|
31
|
+
|
32
|
+
/*
|
33
|
+
if (rank<1)
|
34
|
+
rb_raise(rb_eRuntimeError,"cannot execute for empty array");
|
35
|
+
*/
|
36
|
+
|
37
|
+
/* set strides and clear index */
|
38
|
+
s[0].stride = 1;
|
39
|
+
for (r=1; r<rank; ++r)
|
40
|
+
s[r].stride = s[r-1].stride * shape[r-1];
|
41
|
+
|
42
|
+
for (r=0; r<rank; ++r) {
|
43
|
+
if ( s[r].idx == NULL )
|
44
|
+
/* regular interval */
|
45
|
+
s[r].pstep = s[r].step * s[r].stride * elmsz;
|
46
|
+
else {
|
47
|
+
/* index */
|
48
|
+
s[r].pstep = b = s[r].stride * elmsz;
|
49
|
+
/* convert index to byte-unit */
|
50
|
+
for (i=0; i<16; ++i)
|
51
|
+
if ( (1<<i) == b ) { b=i; break; }
|
52
|
+
if (i==16)
|
53
|
+
for (idx=s[r].idx,i=s[r].n; i-->0; ) { *(idx++)*=b; }
|
54
|
+
else
|
55
|
+
for (idx=s[r].idx,i=s[r].n; i-->0; ) { *(idx++)<<=b; }
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
/* set termination mark */
|
60
|
+
s[rank].n = 0;
|
61
|
+
s[rank].idx = NULL;
|
62
|
+
|
63
|
+
for (r=rank-1;r>=0;--r) {
|
64
|
+
/* set beginning pointers */
|
65
|
+
if ( s[r].idx == NULL )
|
66
|
+
s[r].pbeg = s[r].stride * s[r].beg * elmsz;
|
67
|
+
else
|
68
|
+
s[r].pbeg = s[r].idx[0];
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
|
73
|
+
static void
|
74
|
+
na_do_loop_unary( int nd, char *p1, char *p2,
|
75
|
+
struct slice *s1, struct slice *s2, void (*func)() )
|
76
|
+
{
|
77
|
+
int *si;
|
78
|
+
int i;
|
79
|
+
na_shape_t ps1 = s1[0].pstep;
|
80
|
+
na_shape_t ps2 = s2[0].pstep;
|
81
|
+
|
82
|
+
i = nd;
|
83
|
+
si = ALLOCA_N(int,nd);
|
84
|
+
s1[i].p = p1;
|
85
|
+
s2[i].p = p2;
|
86
|
+
|
87
|
+
for(;;) {
|
88
|
+
/* set pointers */
|
89
|
+
while (i > 0) {
|
90
|
+
--i;
|
91
|
+
s2[i].p = s2[i].pbeg + s2[i+1].p;
|
92
|
+
s1[i].p = s1[i].pbeg + s1[i+1].p;
|
93
|
+
si[i] = s1[i].n;
|
94
|
+
}
|
95
|
+
(*func)(s2[0].n, s1[0].p, ps1, s2[0].p, ps2);
|
96
|
+
/* rank up */
|
97
|
+
do {
|
98
|
+
if ( ++i >= nd ) return;
|
99
|
+
} while ( --si[i] == 0 );
|
100
|
+
/* next point */
|
101
|
+
s1[i].p += s1[i].pstep;
|
102
|
+
s2[i].p += s2[i].pstep;
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
|
107
|
+
static void
|
108
|
+
na_do_loop_binary( int nd, char *p1, char *p2, char *p3,
|
109
|
+
struct slice *s1, struct slice *s2, struct slice *s3,
|
110
|
+
void (*func)() )
|
111
|
+
{
|
112
|
+
int i;
|
113
|
+
na_shape_t ps1 = s1[0].pstep;
|
114
|
+
na_shape_t ps2 = s2[0].pstep;
|
115
|
+
na_shape_t ps3 = s3[0].pstep;
|
116
|
+
int *si;
|
117
|
+
|
118
|
+
si = ALLOCA_N(int,nd);
|
119
|
+
i = nd;
|
120
|
+
s1[i].p = p1;
|
121
|
+
s2[i].p = p2;
|
122
|
+
s3[i].p = p3;
|
123
|
+
|
124
|
+
for(;;) {
|
125
|
+
/* set pointers */
|
126
|
+
while (i > 0) {
|
127
|
+
--i;
|
128
|
+
s3[i].p = s3[i].pbeg + s3[i+1].p;
|
129
|
+
s2[i].p = s2[i].pbeg + s2[i+1].p;
|
130
|
+
s1[i].p = s1[i].pbeg + s1[i+1].p;
|
131
|
+
si[i] = s1[i].n;
|
132
|
+
}
|
133
|
+
/* rank 0 loop */
|
134
|
+
(*func)(s2[0].n, s1[0].p, ps1, s2[0].p, ps2, s3[0].p, ps3);
|
135
|
+
/* rank up */
|
136
|
+
do {
|
137
|
+
if ( ++i >= nd ) return;
|
138
|
+
} while ( --si[i] == 0 );
|
139
|
+
/* next point */
|
140
|
+
s1[i].p += s1[i].pstep;
|
141
|
+
s2[i].p += s2[i].pstep;
|
142
|
+
s3[i].p += s3[i].pstep;
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
void na_loop_index_ref( struct NARRAY *a1, struct NARRAY *a2,
|
149
|
+
struct slice *s1, struct slice *s2, void (*func)() )
|
150
|
+
{
|
151
|
+
char *p1, *p2;
|
152
|
+
int nr, i;
|
153
|
+
na_shape_t ii;
|
154
|
+
na_shape_t ps1 = s1[0].pstep;
|
155
|
+
na_shape_t ps2 = s2[0].pstep;
|
156
|
+
int *si;
|
157
|
+
na_shape_t *idx;
|
158
|
+
|
159
|
+
/*
|
160
|
+
int copy;
|
161
|
+
if (a1->type==a2->type && s1[0].step==1 && s2[0].step==1)
|
162
|
+
copy = s1[0].n * na_sizeof[a1->type];
|
163
|
+
else
|
164
|
+
copy = 0;
|
165
|
+
*/
|
166
|
+
|
167
|
+
/* Initialize */
|
168
|
+
nr = i = a1->rank;
|
169
|
+
si = ALLOCA_N(int,nr);
|
170
|
+
s1[i].p = a1->ptr;
|
171
|
+
s2[i].p = a2->ptr;
|
172
|
+
|
173
|
+
for(;;) {
|
174
|
+
/* set pointers */
|
175
|
+
while (i > 0) {
|
176
|
+
--i;
|
177
|
+
s2[i].p = s2[i].pbeg + s2[i+1].p;
|
178
|
+
s1[i].p = s1[i].pbeg + s1[i+1].p;
|
179
|
+
si[i] = 0;
|
180
|
+
}
|
181
|
+
|
182
|
+
/* rank 0 loop */
|
183
|
+
if ( s2[0].idx == NULL ) {
|
184
|
+
/* regular interval */
|
185
|
+
/*
|
186
|
+
if (copy) {
|
187
|
+
memcpy(s1[0].p, s2[0].p, copy);
|
188
|
+
} else
|
189
|
+
*/
|
190
|
+
(*func)(s2[0].n, s1[0].p, ps1, s2[0].p, ps2);
|
191
|
+
} else {
|
192
|
+
/* a2 has index */
|
193
|
+
p1 = s1[0].p;
|
194
|
+
p2 = s2[1].p;
|
195
|
+
for ( idx=s2[0].idx, ii=s2[0].n; ii-->0;) {
|
196
|
+
(*func)( 1, p1, 0, p2+*(idx++), 0 );
|
197
|
+
p1 += ps1;
|
198
|
+
}
|
199
|
+
}
|
200
|
+
/* rank up */
|
201
|
+
do {
|
202
|
+
if ( ++i >= nr ) return;
|
203
|
+
} while ( ++si[i] == s1[i].n );
|
204
|
+
/* next point */
|
205
|
+
s1[i].p += s1[i].pstep;
|
206
|
+
/* array2 may have index */
|
207
|
+
if ( s2[i].idx == NULL )
|
208
|
+
s2[i].p += s2[i].pstep;
|
209
|
+
else
|
210
|
+
s2[i].p = s2[i+1].p + s2[i].idx[si[i]]; /* * s2[i].pstep; */
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
|
215
|
+
void na_loop_general( struct NARRAY *a1, struct NARRAY *a2,
|
216
|
+
struct slice *s1, struct slice *s2, void (*func)() )
|
217
|
+
{
|
218
|
+
char *p1, *p2;
|
219
|
+
int nr, i, ii;
|
220
|
+
na_shape_t ps1 = s1[0].pstep;
|
221
|
+
na_shape_t ps2 = s2[0].pstep;
|
222
|
+
int *si;
|
223
|
+
na_shape_t *idx1, *idx2;
|
224
|
+
|
225
|
+
/* Initialize */
|
226
|
+
nr = i = a1->rank;
|
227
|
+
si = ALLOCA_N(int,nr);
|
228
|
+
s1[i].p = a1->ptr;
|
229
|
+
s2[i].p = a2->ptr;
|
230
|
+
|
231
|
+
for(;;) {
|
232
|
+
/* set pointers */
|
233
|
+
while (i > 0) {
|
234
|
+
--i;
|
235
|
+
s2[i].p = s2[i].pbeg + s2[i+1].p;
|
236
|
+
s1[i].p = s1[i].pbeg + s1[i+1].p;
|
237
|
+
si[i] = 0;
|
238
|
+
}
|
239
|
+
|
240
|
+
/* rank 0 loop */
|
241
|
+
if ( s1[0].idx == NULL ) {
|
242
|
+
if ( s2[0].idx == NULL ) {
|
243
|
+
/* normal interval */
|
244
|
+
(*func)(s2[0].n, s1[0].p, ps1, s2[0].p, ps2);
|
245
|
+
} else {
|
246
|
+
/* s2 has index */
|
247
|
+
p1 = s1[0].p;
|
248
|
+
p2 = s2[1].p;
|
249
|
+
for ( idx2=s2[0].idx, ii=s2[0].n; ii-->0; ) {
|
250
|
+
(*func)( 1, p1, 0, p2+*(idx2++), 0 );
|
251
|
+
p1 += ps1;
|
252
|
+
}
|
253
|
+
}
|
254
|
+
} else {
|
255
|
+
if ( s2[0].idx == NULL ) {
|
256
|
+
/* s1 has index */
|
257
|
+
p1 = s1[1].p;
|
258
|
+
p2 = s2[0].p;
|
259
|
+
for ( idx1=s1[0].idx, ii=s2[0].n; ii-->0; ) {
|
260
|
+
(*func)( 1, p1+*(idx1++), 0, p2, 0 );
|
261
|
+
p2 += ps2;
|
262
|
+
}
|
263
|
+
} else {
|
264
|
+
/* s1 & s2 has index */
|
265
|
+
p1 = s1[1].p;
|
266
|
+
p2 = s2[1].p;
|
267
|
+
for ( idx1=s1[0].idx, idx2=s2[0].idx, ii=s2[0].n; ii-->0; ) {
|
268
|
+
(*func)( 1, p1+*(idx1++), 0, p2+*(idx2++), 0 );
|
269
|
+
}
|
270
|
+
}
|
271
|
+
}
|
272
|
+
|
273
|
+
/* rank up */
|
274
|
+
do {
|
275
|
+
if ( ++i >= nr ) return;
|
276
|
+
} while ( ++si[i] == s1[i].n );
|
277
|
+
|
278
|
+
/* next point for a1 */
|
279
|
+
if ( s1[i].idx == NULL )
|
280
|
+
s1[i].p += s1[i].pstep;
|
281
|
+
else
|
282
|
+
s1[i].p = s1[i+1].p + s1[i].idx[si[i]];
|
283
|
+
/* next point for a2 */
|
284
|
+
if ( s2[i].idx == NULL )
|
285
|
+
s2[i].p += s2[i].pstep;
|
286
|
+
else
|
287
|
+
s2[i].p = s2[i+1].p + s2[i].idx[si[i]];
|
288
|
+
}
|
289
|
+
}
|
290
|
+
|
291
|
+
|
292
|
+
void
|
293
|
+
na_shape_copy( int ndim, na_shape_t *shape, struct NARRAY *a )
|
294
|
+
{
|
295
|
+
int i;
|
296
|
+
|
297
|
+
for (i=0; i<a->rank; ++i)
|
298
|
+
shape[i] = a->shape[i];
|
299
|
+
for ( ; i<ndim; ++i)
|
300
|
+
shape[i] = 1;
|
301
|
+
}
|
302
|
+
|
303
|
+
|
304
|
+
void
|
305
|
+
na_set_slice_1obj( int ndim, struct slice *slc, na_shape_t *shape )
|
306
|
+
{
|
307
|
+
int i;
|
308
|
+
|
309
|
+
/* for normal access */
|
310
|
+
for (i=0; i<ndim; ++i) {
|
311
|
+
slc[i].n = shape[i];
|
312
|
+
slc[i].beg = 0;
|
313
|
+
slc[i].step = 1;
|
314
|
+
slc[i].idx = NULL;
|
315
|
+
}
|
316
|
+
}
|
317
|
+
|
318
|
+
|
319
|
+
|
320
|
+
static int
|
321
|
+
na_set_slice_2obj( int ndim, struct slice *s1, struct slice *s2,
|
322
|
+
na_shape_t *shp1, na_shape_t *shp2 )
|
323
|
+
{
|
324
|
+
int i, j;
|
325
|
+
|
326
|
+
for (i=j=0; i<ndim; ++i) {
|
327
|
+
|
328
|
+
if ( shp1[i]==1 && shp2[i]>1 ) {
|
329
|
+
s1[j].n =
|
330
|
+
s2[j].n = shp2[i];
|
331
|
+
s1[j].step = 0;
|
332
|
+
s2[j].step = 1;
|
333
|
+
} else
|
334
|
+
if ( shp2[i]==1 && shp1[i]>1 ) {
|
335
|
+
s1[j].n =
|
336
|
+
s2[j].n = shp1[i];
|
337
|
+
s1[j].step = 1;
|
338
|
+
s2[j].step = 0;
|
339
|
+
} else
|
340
|
+
if ( shp1[i] == shp2[i] ) {
|
341
|
+
s1[j].n =
|
342
|
+
s2[j].n = shp1[i];
|
343
|
+
s1[j].step = 1;
|
344
|
+
s2[j].step = 1;
|
345
|
+
} else
|
346
|
+
rb_raise(rb_eRuntimeError, "Array size mismatch: %zd != %zd in %i-th dim",
|
347
|
+
shp1[i], shp2[i], i);
|
348
|
+
|
349
|
+
if (j<i) {
|
350
|
+
shp1[j] = shp1[i];
|
351
|
+
shp2[j] = shp2[i];
|
352
|
+
}
|
353
|
+
|
354
|
+
if (j>0)
|
355
|
+
if ( s1[j].step == s1[j-1].step &&
|
356
|
+
s2[j].step == s2[j-1].step ) { /* contract dimension */
|
357
|
+
s1[j-1].n =
|
358
|
+
s2[j-1].n *= s2[j].n;
|
359
|
+
shp1[j-1] *= shp1[j];
|
360
|
+
shp2[j-1] *= shp2[j];
|
361
|
+
continue;
|
362
|
+
}
|
363
|
+
s1[j].beg =
|
364
|
+
s2[j].beg = 0;
|
365
|
+
s1[j].idx =
|
366
|
+
s2[j].idx = NULL;
|
367
|
+
++j;
|
368
|
+
}
|
369
|
+
|
370
|
+
return j;
|
371
|
+
}
|
372
|
+
|
373
|
+
|
374
|
+
static int
|
375
|
+
na_set_slice_check(na_shape_t ary_sz, na_shape_t itr_sz, int i)
|
376
|
+
{
|
377
|
+
if ( ary_sz == itr_sz )
|
378
|
+
return 1;
|
379
|
+
else if ( ary_sz == 1 )
|
380
|
+
return 0;
|
381
|
+
else
|
382
|
+
rb_raise(rb_eRuntimeError, "Array size mismatch: %zd != %zd at %i-th dim",
|
383
|
+
ary_sz, itr_sz, i);
|
384
|
+
}
|
385
|
+
|
386
|
+
|
387
|
+
int
|
388
|
+
na_set_slice_3obj( int ndim,
|
389
|
+
struct slice *s1, struct slice *s2, struct slice *s3,
|
390
|
+
na_shape_t *shp1, na_shape_t *shp2, na_shape_t *shp3, na_shape_t *shape )
|
391
|
+
{
|
392
|
+
int i, j;
|
393
|
+
|
394
|
+
/* for repetitous access */
|
395
|
+
for (i=j=0; i<ndim; ++i) {
|
396
|
+
|
397
|
+
s1[j].step = na_set_slice_check(shp1[i],shape[i],i);
|
398
|
+
s2[j].step = na_set_slice_check(shp2[i],shape[i],i);
|
399
|
+
s3[j].step = na_set_slice_check(shp3[i],shape[i],i);
|
400
|
+
|
401
|
+
if (j<i) {
|
402
|
+
shp1[j] = shp1[i];
|
403
|
+
shp2[j] = shp2[i];
|
404
|
+
shp3[j] = shp3[i];
|
405
|
+
}
|
406
|
+
|
407
|
+
if (j>0) {
|
408
|
+
if ( s1[j].step == s1[j-1].step &&
|
409
|
+
s2[j].step == s2[j-1].step &&
|
410
|
+
s3[j].step == s3[j-1].step ) /* contract dimension */
|
411
|
+
{
|
412
|
+
s1[j-1].n =
|
413
|
+
s2[j-1].n =
|
414
|
+
s3[j-1].n *= shape[i];
|
415
|
+
|
416
|
+
shp1[j-1] *= shp1[j];
|
417
|
+
shp2[j-1] *= shp2[j];
|
418
|
+
shp3[j-1] *= shp3[j];
|
419
|
+
continue;
|
420
|
+
}
|
421
|
+
}
|
422
|
+
|
423
|
+
s1[j].n =
|
424
|
+
s2[j].n =
|
425
|
+
s3[j].n = shape[i];
|
426
|
+
|
427
|
+
s1[j].beg =
|
428
|
+
s2[j].beg =
|
429
|
+
s3[j].beg = 0;
|
430
|
+
|
431
|
+
s1[j].idx =
|
432
|
+
s2[j].idx =
|
433
|
+
s3[j].idx = NULL;
|
434
|
+
|
435
|
+
++j;
|
436
|
+
}
|
437
|
+
|
438
|
+
return j;
|
439
|
+
}
|
440
|
+
|
441
|
+
|
442
|
+
static void
|
443
|
+
na_exec_unary(struct NARRAY *a1, struct NARRAY *a2, void (*func)())
|
444
|
+
{
|
445
|
+
int ndim;
|
446
|
+
na_shape_t *shp1, *shp2;
|
447
|
+
struct slice *s1, *s2;
|
448
|
+
|
449
|
+
/* empty check */
|
450
|
+
if ( a1->total==0 || a2->total==0 )
|
451
|
+
/* rb_raise( rb_eTypeError, "cannot execute for empty array" ); */
|
452
|
+
return; /* do nothing */
|
453
|
+
|
454
|
+
ndim = NA_MAX(a1->rank,a2->rank);
|
455
|
+
|
456
|
+
NA_ALLOC_SLICE(s1,(ndim+1)*2,shp1,ndim*2);
|
457
|
+
shp2 = &shp1[ndim];
|
458
|
+
s2 = &s1[ndim+1];
|
459
|
+
|
460
|
+
na_shape_copy( ndim, shp1, a1 );
|
461
|
+
na_shape_copy( ndim, shp2, a2 );
|
462
|
+
|
463
|
+
ndim = na_set_slice_2obj( ndim, s1, s2, shp1, shp2 );
|
464
|
+
na_init_slice( s1, ndim, shp1, na_sizeof[a1->type] );
|
465
|
+
na_init_slice( s2, ndim, shp2, na_sizeof[a2->type] );
|
466
|
+
|
467
|
+
na_do_loop_unary( ndim, a1->ptr, a2->ptr, s1, s2, func );
|
468
|
+
|
469
|
+
xfree(s1);
|
470
|
+
}
|
471
|
+
|
472
|
+
|
473
|
+
/* a1 and/or a2 and/or a3 have extensible index */
|
474
|
+
static void
|
475
|
+
na_exec_binary( struct NARRAY *a1, struct NARRAY *a2,
|
476
|
+
struct NARRAY *a3, void (*func)() )
|
477
|
+
{
|
478
|
+
int ndim;
|
479
|
+
na_shape_t *itr, *shp1, *shp2, *shp3;
|
480
|
+
struct slice *s1, *s2, *s3;
|
481
|
+
|
482
|
+
/* empty check */
|
483
|
+
if (a1->total==0) return; /* do nothing */
|
484
|
+
|
485
|
+
ndim = NA_MAX3(a1->rank, a2->rank, a3->rank);
|
486
|
+
|
487
|
+
NA_ALLOC_SLICE(s1,(ndim+1)*3,shp1,ndim*4);
|
488
|
+
shp2 = &shp1[ndim];
|
489
|
+
shp3 = &shp2[ndim];
|
490
|
+
itr = &shp3[ndim];
|
491
|
+
s2 = &s1[ndim+1];
|
492
|
+
s3 = &s2[ndim+1];
|
493
|
+
|
494
|
+
na_shape_copy( ndim, shp1, a1 );
|
495
|
+
na_shape_copy( ndim, shp2, a2 );
|
496
|
+
na_shape_copy( ndim, shp3, a3 );
|
497
|
+
na_shape_max3( ndim, itr, shp1, shp2, shp3 );
|
498
|
+
|
499
|
+
ndim = na_set_slice_3obj( ndim, s1, s2, s3, shp1, shp2, shp3, itr );
|
500
|
+
|
501
|
+
na_init_slice(s1, ndim, shp1, na_sizeof[a1->type] );
|
502
|
+
na_init_slice(s2, ndim, shp2, na_sizeof[a2->type] );
|
503
|
+
na_init_slice(s3, ndim, shp3, na_sizeof[a3->type] );
|
504
|
+
|
505
|
+
na_do_loop_binary( ndim, a1->ptr, a2->ptr, a3->ptr, s1, s2, s3, func );
|
506
|
+
xfree(s1);
|
507
|
+
}
|
508
|
+
|
509
|
+
|
510
|
+
static void
|
511
|
+
na_shape_max_2obj(int ndim, na_shape_t *shape, struct NARRAY *a1, struct NARRAY *a2)
|
512
|
+
{
|
513
|
+
struct NARRAY *tmp;
|
514
|
+
int i;
|
515
|
+
|
516
|
+
/* empty check */
|
517
|
+
if ( a1->total==0 || a2->total==0 )
|
518
|
+
rb_raise( rb_eTypeError, "cannot execute for empty array" );
|
519
|
+
|
520
|
+
if (a1->rank < a2->rank) {
|
521
|
+
NA_SWAP(a1,a2,tmp);
|
522
|
+
}
|
523
|
+
|
524
|
+
for (i=0; i<a2->rank; ++i) {
|
525
|
+
shape[i] = NA_MAX(a1->shape[i],a2->shape[i]);
|
526
|
+
}
|
527
|
+
for ( ; i<a1->rank; ++i) {
|
528
|
+
shape[i] = a1->shape[i];
|
529
|
+
}
|
530
|
+
for ( ; i<ndim; ++i) {
|
531
|
+
shape[i] = 1;
|
532
|
+
}
|
533
|
+
}
|
534
|
+
|
535
|
+
|
536
|
+
static VALUE
|
537
|
+
na_make_object_extend(struct NARRAY *a1, struct NARRAY *a2,
|
538
|
+
int type, VALUE klass)
|
539
|
+
{
|
540
|
+
int ndim;
|
541
|
+
na_shape_t *shape;
|
542
|
+
|
543
|
+
/* empty check */
|
544
|
+
if ( a1->total==0 || a2->total==0 )
|
545
|
+
return na_make_empty(type, klass); /* return empty */
|
546
|
+
|
547
|
+
ndim = NA_MAX(a1->rank, a2->rank);
|
548
|
+
shape = ALLOCA_N(na_shape_t, ndim);
|
549
|
+
na_shape_max_2obj( ndim, shape, a1, a2 );
|
550
|
+
|
551
|
+
return na_make_object( type, ndim, shape, klass );
|
552
|
+
}
|
553
|
+
|
554
|
+
|
555
|
+
static ID na_bifunc_to_id(na_bifunc_t funcs)
|
556
|
+
{
|
557
|
+
if (funcs==AddBFuncs) return na_id_add;
|
558
|
+
if (funcs==SbtBFuncs) return na_id_sbt;
|
559
|
+
if (funcs==MulBFuncs) return na_id_mul;
|
560
|
+
if (funcs==DivBFuncs) return na_id_div;
|
561
|
+
if (funcs==ModBFuncs) return na_id_mod;
|
562
|
+
return 0;
|
563
|
+
/* if (funcs==PowFuncs) return na_id_power;
|
564
|
+
rb_raise(rb_eRuntimeError, "coerce_rev: function not soppurted");
|
565
|
+
*/
|
566
|
+
}
|
567
|
+
|
568
|
+
|
569
|
+
static VALUE
|
570
|
+
na_bifunc_class(VALUE klass1, VALUE klass2)
|
571
|
+
{
|
572
|
+
if ( klass2==cNArray || klass2==cNArrayScalar ) {
|
573
|
+
if ( klass1==cNArrayScalar ) return cNArray;
|
574
|
+
else return klass1;
|
575
|
+
}
|
576
|
+
return Qnil;
|
577
|
+
}
|
578
|
+
|
579
|
+
|
580
|
+
static VALUE
|
581
|
+
na_bifunc(VALUE obj1, VALUE obj2, VALUE klass, na_bifunc_t funcs)
|
582
|
+
{
|
583
|
+
VALUE obj3;
|
584
|
+
ID id;
|
585
|
+
int type;
|
586
|
+
|
587
|
+
Check_Type(obj1, T_DATA);
|
588
|
+
obj2 = na_upcast_object(obj2,NA_STRUCT(obj1)->type);
|
589
|
+
obj1 = na_upcast_type(obj1,type=NA_STRUCT(obj2)->type);
|
590
|
+
|
591
|
+
if (klass==Qnil) {
|
592
|
+
klass = na_bifunc_class(CLASS_OF(obj1),CLASS_OF(obj2));
|
593
|
+
|
594
|
+
if (klass==Qnil) { /* coerce_rev */
|
595
|
+
if ((id=na_bifunc_to_id(funcs))!=0)
|
596
|
+
return rb_funcall( obj2, na_id_coerce_rev, 2, obj1, ID2SYM(id) );
|
597
|
+
else
|
598
|
+
klass = cNArray;
|
599
|
+
}
|
600
|
+
}
|
601
|
+
|
602
|
+
obj3 = na_make_object_extend(NA_STRUCT(obj1),NA_STRUCT(obj2),type,klass);
|
603
|
+
|
604
|
+
na_exec_binary( NA_STRUCT(obj3), NA_STRUCT(obj1), NA_STRUCT(obj2),
|
605
|
+
funcs[type] );
|
606
|
+
|
607
|
+
return obj3;
|
608
|
+
}
|
609
|
+
|
610
|
+
|
611
|
+
static VALUE
|
612
|
+
na_power(VALUE val1, VALUE val2)
|
613
|
+
{
|
614
|
+
volatile VALUE obj1, obj2, obj3;
|
615
|
+
struct NARRAY *a1, *a2;
|
616
|
+
|
617
|
+
obj1 = val1;
|
618
|
+
obj2 = val2;
|
619
|
+
GetNArray(obj1,a1);
|
620
|
+
obj2 = na_to_narray(obj2);
|
621
|
+
GetNArray(obj2,a2);
|
622
|
+
|
623
|
+
if (a1->type==NA_ROBJ && a2->type!=NA_ROBJ) {
|
624
|
+
obj2 = na_change_type(obj2,NA_ROBJ);
|
625
|
+
GetNArray(obj2,a2);
|
626
|
+
} else
|
627
|
+
if (a2->type==NA_ROBJ && a1->type!=NA_ROBJ) {
|
628
|
+
obj1 = na_change_type(obj1,NA_ROBJ);
|
629
|
+
GetNArray(obj1,a1);
|
630
|
+
} else
|
631
|
+
if (!NA_IsCOMPLEX(a1) && NA_IsCOMPLEX(a2)) {
|
632
|
+
obj1 = na_upcast_type(obj1,a2->type);
|
633
|
+
GetNArray(obj1,a1);
|
634
|
+
}
|
635
|
+
|
636
|
+
obj3 = na_make_object_extend( a1, a2, na_upcast[a1->type][a2->type],
|
637
|
+
CLASS_OF(obj1) );
|
638
|
+
|
639
|
+
na_exec_binary( NA_STRUCT(obj3), a1, a2,
|
640
|
+
PowFuncs[a1->type][a2->type] );
|
641
|
+
|
642
|
+
return obj3;
|
643
|
+
}
|
644
|
+
|
645
|
+
|
646
|
+
static VALUE
|
647
|
+
na_set_func(VALUE obj1, volatile VALUE obj2, na_ufunc_t funcs)
|
648
|
+
{
|
649
|
+
struct NARRAY *a1;
|
650
|
+
|
651
|
+
GetNArray(obj1,a1);
|
652
|
+
obj2 = na_cast_object(obj2,a1->type);
|
653
|
+
|
654
|
+
na_exec_unary( NA_STRUCT(obj1), NA_STRUCT(obj2), funcs[a1->type] );
|
655
|
+
|
656
|
+
return obj1;
|
657
|
+
}
|
658
|
+
|
659
|
+
|
660
|
+
static VALUE
|
661
|
+
na_imag_set(VALUE obj1, volatile VALUE obj2)
|
662
|
+
{
|
663
|
+
struct NARRAY *a1;
|
664
|
+
|
665
|
+
GetNArray(obj1,a1);
|
666
|
+
obj2 = na_cast_object(obj2, na_cast_real[a1->type]);
|
667
|
+
|
668
|
+
na_exec_unary( NA_STRUCT(obj1), NA_STRUCT(obj2), ImgSetFuncs[a1->type] );
|
669
|
+
|
670
|
+
return obj1;
|
671
|
+
}
|
672
|
+
|
673
|
+
|
674
|
+
static VALUE
|
675
|
+
na_unary_func(VALUE self, const int *cast, na_ufunc_t funcs)
|
676
|
+
{
|
677
|
+
VALUE ans;
|
678
|
+
struct NARRAY *a2;
|
679
|
+
|
680
|
+
GetNArray(self,a2);
|
681
|
+
ans = na_make_object(cast[a2->type], a2->rank, a2->shape, CLASS_OF(self));
|
682
|
+
|
683
|
+
na_exec_unary( NA_STRUCT(ans), a2, funcs[a2->type] );
|
684
|
+
return ans;
|
685
|
+
}
|
686
|
+
|
687
|
+
|
688
|
+
|
689
|
+
/* local function for comparison */
|
690
|
+
static VALUE
|
691
|
+
na_compare_func(VALUE self, VALUE other, na_bifunc_t funcs)
|
692
|
+
{
|
693
|
+
VALUE ans;
|
694
|
+
int type;
|
695
|
+
|
696
|
+
Check_Type(self, T_DATA);
|
697
|
+
/*if (NA_IsComplex(a1)) rb_raise();*/
|
698
|
+
other = na_upcast_object(other,NA_STRUCT(self)->type);
|
699
|
+
self = na_upcast_type(self,type=NA_STRUCT(other)->type);
|
700
|
+
|
701
|
+
ans = na_make_object_extend( NA_STRUCT(self), NA_STRUCT(other),
|
702
|
+
NA_BYTE, cNArray );
|
703
|
+
|
704
|
+
na_exec_binary( NA_STRUCT(ans), NA_STRUCT(self), NA_STRUCT(other),
|
705
|
+
funcs[type] );
|
706
|
+
return ans;
|
707
|
+
}
|
708
|
+
|
709
|
+
|
710
|
+
/* method: self + other */
|
711
|
+
static VALUE na_add(VALUE obj1, VALUE obj2)
|
712
|
+
{ return na_bifunc( obj1, obj2, Qnil, AddBFuncs ); }
|
713
|
+
|
714
|
+
/* method: self - other */
|
715
|
+
static VALUE na_sbt(VALUE obj1, VALUE obj2)
|
716
|
+
{ return na_bifunc( obj1, obj2, Qnil, SbtBFuncs ); }
|
717
|
+
|
718
|
+
/* method: self * other */
|
719
|
+
static VALUE na_mul(VALUE obj1, VALUE obj2)
|
720
|
+
{ return na_bifunc( obj1, obj2, Qnil, MulBFuncs ); }
|
721
|
+
|
722
|
+
/* method: self / other */
|
723
|
+
static VALUE na_div(VALUE obj1, VALUE obj2)
|
724
|
+
{ return na_bifunc( obj1, obj2, Qnil, DivBFuncs ); }
|
725
|
+
|
726
|
+
/* method: self / other */
|
727
|
+
static VALUE na_mod(VALUE obj1, VALUE obj2)
|
728
|
+
{ return na_bifunc( obj1, obj2, Qnil, ModBFuncs ); }
|
729
|
+
|
730
|
+
/* method: self & other */
|
731
|
+
static VALUE na_bit_and(VALUE obj1, VALUE obj2)
|
732
|
+
{ return na_bifunc( obj1, obj2, Qnil, BAnFuncs ); }
|
733
|
+
|
734
|
+
/* method: self | other */
|
735
|
+
static VALUE na_bit_or(VALUE obj1, VALUE obj2)
|
736
|
+
{ return na_bifunc( obj1, obj2, Qnil, BOrFuncs ); }
|
737
|
+
|
738
|
+
/* method: self ^ other */
|
739
|
+
static VALUE na_bit_xor(VALUE obj1, VALUE obj2)
|
740
|
+
{ return na_bifunc( obj1, obj2, Qnil, BXoFuncs ); }
|
741
|
+
|
742
|
+
/* method: atan2(y,x) */
|
743
|
+
static VALUE na_math_atan2(VALUE module, volatile VALUE y, volatile VALUE x)
|
744
|
+
{
|
745
|
+
VALUE ans;
|
746
|
+
struct NARRAY *ya, *xa, *aa;
|
747
|
+
|
748
|
+
if (TYPE(y) == T_ARRAY) {
|
749
|
+
y = na_ary_to_nary(y,cNArray);
|
750
|
+
} else
|
751
|
+
if (!IsNArray(y)) {
|
752
|
+
y = na_make_scalar(y,na_object_type(y));
|
753
|
+
}
|
754
|
+
|
755
|
+
if (TYPE(x) == T_ARRAY) {
|
756
|
+
x = na_ary_to_nary(x,cNArray);
|
757
|
+
} else
|
758
|
+
if (!IsNArray(x)) {
|
759
|
+
x = na_make_scalar(x,na_object_type(x));
|
760
|
+
}
|
761
|
+
|
762
|
+
GetNArray(y,ya);
|
763
|
+
GetNArray(x,xa);
|
764
|
+
if (NA_IsINTEGER(ya) && NA_IsINTEGER(xa)) {
|
765
|
+
y = na_upcast_type(y,NA_DFLOAT);
|
766
|
+
x = na_upcast_type(x,NA_DFLOAT);
|
767
|
+
}
|
768
|
+
|
769
|
+
ans = na_bifunc( y, x, Qnil, atan2Funcs );
|
770
|
+
GetNArray(ans,aa);
|
771
|
+
|
772
|
+
if (CLASS_OF(y) == cNArrayScalar && CLASS_OF(x) == cNArrayScalar)
|
773
|
+
SetFuncs[NA_ROBJ][aa->type](1,&ans,0,aa->ptr,0);
|
774
|
+
|
775
|
+
return ans;
|
776
|
+
}
|
777
|
+
|
778
|
+
|
779
|
+
|
780
|
+
/* singleton method: NArray.mul( obj1, obj2 ) */
|
781
|
+
static VALUE
|
782
|
+
na_s_mul(VALUE klass, VALUE obj1, VALUE obj2)
|
783
|
+
{ return na_bifunc( obj1, obj2, klass, MulBFuncs ); }
|
784
|
+
|
785
|
+
/* singleton method: NArray.div( obj1, obj2 ) */
|
786
|
+
static VALUE
|
787
|
+
na_s_div(VALUE klass, VALUE obj1, VALUE obj2)
|
788
|
+
{ return na_bifunc( obj1, obj2, klass, DivBFuncs ); }
|
789
|
+
|
790
|
+
|
791
|
+
|
792
|
+
/* method: self.add!(other) */
|
793
|
+
static VALUE na_add_bang(VALUE obj1, VALUE obj2)
|
794
|
+
{ return na_set_func( obj1, obj2, AddUFuncs ); }
|
795
|
+
|
796
|
+
/* method: self.sbt!(other) */
|
797
|
+
static VALUE na_sbt_bang(VALUE obj1, VALUE obj2)
|
798
|
+
{ return na_set_func( obj1, obj2, SbtUFuncs ); }
|
799
|
+
|
800
|
+
/* method: self.div!(other) */
|
801
|
+
static VALUE na_div_bang(VALUE obj1, VALUE obj2)
|
802
|
+
{ return na_set_func( obj1, obj2, DivUFuncs ); }
|
803
|
+
|
804
|
+
/* method: self.mul!(other) */
|
805
|
+
static VALUE na_mul_bang(VALUE obj1, VALUE obj2)
|
806
|
+
{ return na_set_func( obj1, obj2, MulUFuncs ); }
|
807
|
+
|
808
|
+
/* method: self.mod!(other) */
|
809
|
+
static VALUE na_mod_bang(VALUE obj1, VALUE obj2)
|
810
|
+
{ return na_set_func( obj1, obj2, ModUFuncs ); }
|
811
|
+
|
812
|
+
/* method: self.conj! */
|
813
|
+
static VALUE na_conj_bang(VALUE self)
|
814
|
+
{ return na_set_func( self, self, ConjFuncs ); }
|
815
|
+
|
816
|
+
|
817
|
+
/* method: self.swap_byte */
|
818
|
+
static VALUE na_swap_byte(VALUE self)
|
819
|
+
{ return na_unary_func( self, na_no_cast, SwpFuncs ); }
|
820
|
+
|
821
|
+
/* method: self.hton , self.ntoh */
|
822
|
+
static VALUE na_hton(VALUE self)
|
823
|
+
{ return na_unary_func( self, na_no_cast, H2NFuncs ); }
|
824
|
+
|
825
|
+
/* method: self.htov , self.vtoh */
|
826
|
+
static VALUE na_htov(VALUE self)
|
827
|
+
{ return na_unary_func( self, na_no_cast, H2VFuncs ); }
|
828
|
+
|
829
|
+
/* method: ~self */
|
830
|
+
static VALUE na_bit_rev(VALUE self)
|
831
|
+
{ return na_unary_func( self, na_no_cast, BRvFuncs ); }
|
832
|
+
|
833
|
+
/* method: -self */
|
834
|
+
static VALUE na_neg(VALUE self)
|
835
|
+
{ return na_unary_func( self, na_no_cast, NegFuncs ); }
|
836
|
+
|
837
|
+
/* method: self.recip */
|
838
|
+
static VALUE na_recip(VALUE self)
|
839
|
+
{ return na_unary_func( self, na_no_cast, RcpFuncs ); }
|
840
|
+
|
841
|
+
/* method: self.abs */
|
842
|
+
static VALUE na_abs(VALUE self)
|
843
|
+
{ return na_unary_func( self, na_cast_real, AbsFuncs ); }
|
844
|
+
|
845
|
+
/* method: self.real */
|
846
|
+
static VALUE na_real(VALUE self)
|
847
|
+
{ return na_unary_func( self, na_cast_real, RealFuncs ); }
|
848
|
+
|
849
|
+
/* method: self.imag */
|
850
|
+
static VALUE na_imag(VALUE self)
|
851
|
+
{ return na_unary_func( self, na_cast_real, ImagFuncs ); }
|
852
|
+
|
853
|
+
/* method: self.imag */
|
854
|
+
static VALUE na_angle(VALUE self)
|
855
|
+
{ return na_unary_func( self, na_cast_real, AnglFuncs ); }
|
856
|
+
|
857
|
+
/* method: self.im */
|
858
|
+
static VALUE na_imag_mul(VALUE self)
|
859
|
+
{ return na_unary_func( self, na_cast_comp, ImagMulFuncs ); }
|
860
|
+
|
861
|
+
/* method: self.conj */
|
862
|
+
static VALUE na_conj(VALUE self)
|
863
|
+
{ return na_unary_func( self, na_no_cast, ConjFuncs ); }
|
864
|
+
|
865
|
+
/* method: self.floor */
|
866
|
+
static VALUE na_floor(VALUE self)
|
867
|
+
{ return na_unary_func( self, na_cast_round, FloorFuncs ); }
|
868
|
+
|
869
|
+
/* method: self.ceil */
|
870
|
+
static VALUE na_ceil(VALUE self)
|
871
|
+
{ return na_unary_func( self, na_cast_round, CeilFuncs ); }
|
872
|
+
|
873
|
+
/* method: self.round */
|
874
|
+
static VALUE na_round(VALUE self)
|
875
|
+
{ return na_unary_func( self, na_cast_round, RoundFuncs ); }
|
876
|
+
|
877
|
+
/* method: self.not */
|
878
|
+
static VALUE na_not(VALUE self)
|
879
|
+
{ return na_unary_func( self, na_cast_byte, NotFuncs ); }
|
880
|
+
|
881
|
+
|
882
|
+
/* method: self.and other */
|
883
|
+
static VALUE
|
884
|
+
na_cond_and(VALUE obj1, VALUE obj2)
|
885
|
+
{ return na_compare_func( obj1, obj2, AndFuncs ); }
|
886
|
+
|
887
|
+
/* method: self.or other */
|
888
|
+
static VALUE
|
889
|
+
na_cond_or(VALUE obj1, VALUE obj2)
|
890
|
+
{ return na_compare_func( obj1, obj2, Or_Funcs ); }
|
891
|
+
|
892
|
+
/* method: self.xor other */
|
893
|
+
static VALUE
|
894
|
+
na_cond_xor(VALUE obj1, VALUE obj2)
|
895
|
+
{ return na_compare_func( obj1, obj2, XorFuncs ); }
|
896
|
+
|
897
|
+
|
898
|
+
|
899
|
+
/* method: self <=> other */
|
900
|
+
static VALUE
|
901
|
+
na_compare(VALUE obj1, VALUE obj2)
|
902
|
+
{ return na_compare_func( obj1, obj2, CmpFuncs ); }
|
903
|
+
|
904
|
+
|
905
|
+
|
906
|
+
/* method: self.eq(other) */
|
907
|
+
static VALUE
|
908
|
+
na_equal(VALUE obj1, VALUE obj2)
|
909
|
+
{
|
910
|
+
return na_compare_func( obj1, obj2, EqlFuncs );
|
911
|
+
}
|
912
|
+
|
913
|
+
/* method: self.ne(other) */
|
914
|
+
static VALUE
|
915
|
+
na_not_equal(VALUE obj1, VALUE obj2)
|
916
|
+
{
|
917
|
+
VALUE obj;
|
918
|
+
na_shape_t i; char *p;
|
919
|
+
struct NARRAY *a;
|
920
|
+
|
921
|
+
obj = na_compare_func( obj1, obj2, EqlFuncs );
|
922
|
+
GetNArray(obj,a);
|
923
|
+
p = a->ptr;
|
924
|
+
for( i=a->total; i-->0; ) {
|
925
|
+
*p = *p==0 ? 1 : 0;
|
926
|
+
++p;
|
927
|
+
}
|
928
|
+
return obj;
|
929
|
+
}
|
930
|
+
|
931
|
+
/* method: self > other */
|
932
|
+
static VALUE
|
933
|
+
na_greater_than(VALUE self, VALUE obj2)
|
934
|
+
{
|
935
|
+
na_shape_t i; char *p;
|
936
|
+
struct NARRAY *a;
|
937
|
+
|
938
|
+
self = na_compare_func( self, obj2, CmpFuncs );
|
939
|
+
GetNArray(self,a);
|
940
|
+
p = a->ptr;
|
941
|
+
for( i=a->total; i-->0; ) {
|
942
|
+
if (*p!=1) *p=0;
|
943
|
+
++p;
|
944
|
+
}
|
945
|
+
return self;
|
946
|
+
}
|
947
|
+
|
948
|
+
/* method: self >= other */
|
949
|
+
static VALUE
|
950
|
+
na_greater_equal(VALUE obj1, VALUE obj2)
|
951
|
+
{
|
952
|
+
VALUE obj;
|
953
|
+
na_shape_t i; char *p;
|
954
|
+
struct NARRAY *a;
|
955
|
+
|
956
|
+
obj = na_compare_func( obj1, obj2, CmpFuncs );
|
957
|
+
GetNArray(obj,a);
|
958
|
+
p = a->ptr;
|
959
|
+
for( i=a->total; i-->0; ) {
|
960
|
+
if (*p==1 || *p==0) *p=1;
|
961
|
+
else *p=0;
|
962
|
+
++p;
|
963
|
+
}
|
964
|
+
return obj;
|
965
|
+
}
|
966
|
+
|
967
|
+
/* method: self < other */
|
968
|
+
static VALUE
|
969
|
+
na_less_than(VALUE obj1, VALUE obj2)
|
970
|
+
{
|
971
|
+
VALUE obj;
|
972
|
+
na_shape_t i; char *p;
|
973
|
+
struct NARRAY *a;
|
974
|
+
|
975
|
+
obj = na_compare_func( obj1, obj2, CmpFuncs );
|
976
|
+
GetNArray(obj,a);
|
977
|
+
p = a->ptr;
|
978
|
+
for( i=a->total; i-->0; ) {
|
979
|
+
if (*p==2) *p=1;
|
980
|
+
else *p=0;
|
981
|
+
++p;
|
982
|
+
}
|
983
|
+
return obj;
|
984
|
+
}
|
985
|
+
|
986
|
+
/* method: self <= other */
|
987
|
+
static VALUE
|
988
|
+
na_less_equal(VALUE obj1, VALUE obj2)
|
989
|
+
{
|
990
|
+
VALUE obj;
|
991
|
+
na_shape_t i; char *p;
|
992
|
+
struct NARRAY *a;
|
993
|
+
|
994
|
+
obj = na_compare_func( obj1, obj2, CmpFuncs );
|
995
|
+
GetNArray(obj,a);
|
996
|
+
p = a->ptr;
|
997
|
+
for( i=a->total; i-->0; ) {
|
998
|
+
if (*p==2 || *p==0) *p=1;
|
999
|
+
else *p=0;
|
1000
|
+
++p;
|
1001
|
+
}
|
1002
|
+
return obj;
|
1003
|
+
}
|
1004
|
+
|
1005
|
+
|
1006
|
+
|
1007
|
+
|
1008
|
+
/*
|
1009
|
+
------- Sum, Min, Max, Transpose --------
|
1010
|
+
*/
|
1011
|
+
VALUE
|
1012
|
+
rb_range_beg_len(VALUE range, na_shape_t *begp, na_shape_t *lenp, na_shape_t len, int err );
|
1013
|
+
|
1014
|
+
static int
|
1015
|
+
na_arg_to_rank(int argc, VALUE *argv, int rankc, int *rankv, int flag)
|
1016
|
+
/* e.g.: argv=[1,3..5]
|
1017
|
+
if flag==0
|
1018
|
+
rankv = [0,1,0,1,1,1,0,..]
|
1019
|
+
else
|
1020
|
+
rankv = [1,3,4,5]
|
1021
|
+
*/
|
1022
|
+
{
|
1023
|
+
int i, j, c=0;
|
1024
|
+
na_shape_t r, n;
|
1025
|
+
VALUE v;
|
1026
|
+
|
1027
|
+
if (flag==0)
|
1028
|
+
MEMZERO(rankv,int,rankc);
|
1029
|
+
|
1030
|
+
for (i=0;i<argc;++i) {
|
1031
|
+
if ( c >= rankc )
|
1032
|
+
rb_raise(rb_eArgError, "too many ranks");
|
1033
|
+
|
1034
|
+
v = argv[i];
|
1035
|
+
|
1036
|
+
if (TYPE(v)==T_FIXNUM) {
|
1037
|
+
r = NUM2SHAPE(v);
|
1038
|
+
if (r<0) r += rankc; /* negative for from end */
|
1039
|
+
if (r<0 || r>=rankc)
|
1040
|
+
rb_raise(rb_eArgError, "rank %ld out of range", r);
|
1041
|
+
if (flag)
|
1042
|
+
rankv[c] = r;
|
1043
|
+
else
|
1044
|
+
rankv[r] = 1;
|
1045
|
+
++c;
|
1046
|
+
}
|
1047
|
+
else
|
1048
|
+
if (CLASS_OF(v)==rb_cRange) {
|
1049
|
+
rb_range_beg_len( v, &r, &n, rankc, 1 );
|
1050
|
+
if ( c+n > rankc )
|
1051
|
+
rb_raise(rb_eArgError, "too many ranks");
|
1052
|
+
if (flag) {
|
1053
|
+
for(j=0; j<n; ++j)
|
1054
|
+
rankv[c++] = r++;
|
1055
|
+
} else {
|
1056
|
+
for(j=0; j<n; ++j) {
|
1057
|
+
rankv[r++] = 1;
|
1058
|
+
++c;
|
1059
|
+
}
|
1060
|
+
}
|
1061
|
+
}
|
1062
|
+
else
|
1063
|
+
rb_raise(rb_eArgError, "wrong type");
|
1064
|
+
}
|
1065
|
+
return c;
|
1066
|
+
}
|
1067
|
+
|
1068
|
+
|
1069
|
+
|
1070
|
+
/* Transpose procedure */
|
1071
|
+
static struct NARRAY *
|
1072
|
+
na_transpose_bifunc(struct NARRAY *a1, struct NARRAY *a2, int *trans)
|
1073
|
+
{
|
1074
|
+
int i, ndim=a2->rank;
|
1075
|
+
struct slice *s1, *s2;
|
1076
|
+
|
1077
|
+
s1 = ALLOC_N(struct slice, (ndim+1)*2);
|
1078
|
+
s2 = &s1[ndim+1];
|
1079
|
+
|
1080
|
+
/* for Source array -- s1 is temporarily used */
|
1081
|
+
na_set_slice_1obj(a2->rank,s1,a2->shape);
|
1082
|
+
na_init_slice( s1, ndim, a2->shape, na_sizeof[a2->type] );
|
1083
|
+
|
1084
|
+
/* Transpose Slice */
|
1085
|
+
for (i=0; i<ndim; ++i)
|
1086
|
+
s2[i] = s1[trans[i]];
|
1087
|
+
s2[ndim] = s1[ndim];
|
1088
|
+
|
1089
|
+
/* for Destination */
|
1090
|
+
na_set_slice_1obj(a1->rank,s1,a1->shape);
|
1091
|
+
na_init_slice( s1, ndim, a1->shape, na_sizeof[a1->type] );
|
1092
|
+
|
1093
|
+
/* Loop */
|
1094
|
+
na_do_loop_unary( ndim, a1->ptr, a2->ptr, s1, s2,
|
1095
|
+
SetFuncs[a1->type][a2->type] );
|
1096
|
+
xfree(s1);
|
1097
|
+
return a1;
|
1098
|
+
}
|
1099
|
+
|
1100
|
+
|
1101
|
+
/* method: self.transpose( ... ) */
|
1102
|
+
static VALUE
|
1103
|
+
na_transpose(int argc, VALUE *argv, VALUE self)
|
1104
|
+
{
|
1105
|
+
struct NARRAY *a2;
|
1106
|
+
int i, rankc, *rankv;
|
1107
|
+
na_shape_t *shape;
|
1108
|
+
VALUE obj;
|
1109
|
+
|
1110
|
+
GetNArray(self,a2);
|
1111
|
+
|
1112
|
+
/* Parse Argument */
|
1113
|
+
rankv = ALLOC_N( int, NA_MAX_RANK);
|
1114
|
+
shape = ALLOC_N( na_shape_t, NA_MAX_RANK);
|
1115
|
+
rankc = na_arg_to_rank( argc, argv, a2->rank, rankv, 1 );
|
1116
|
+
if (rankc > a2->rank)
|
1117
|
+
rb_raise(rb_eArgError, "too many args");
|
1118
|
+
for ( ;rankc<a2->rank; ++rankc)
|
1119
|
+
rankv[rankc] = rankc;
|
1120
|
+
|
1121
|
+
/* Argument Check */
|
1122
|
+
MEMZERO(shape,na_shape_t,rankc);
|
1123
|
+
for (i=0; i<rankc; ++i) {
|
1124
|
+
if (shape[rankv[i]] != 0)
|
1125
|
+
rb_raise(rb_eArgError,"rank doublebooking");
|
1126
|
+
shape[rankv[i]] = 1;
|
1127
|
+
}
|
1128
|
+
|
1129
|
+
for (i=0; i<a2->rank; ++i)
|
1130
|
+
shape[i] = a2->shape[rankv[i]];
|
1131
|
+
|
1132
|
+
obj = na_make_object(a2->type, a2->rank, shape, CLASS_OF(self));
|
1133
|
+
|
1134
|
+
na_transpose_bifunc( NA_STRUCT(obj), a2, rankv );
|
1135
|
+
xfree(rankv);
|
1136
|
+
xfree(shape);
|
1137
|
+
return obj;
|
1138
|
+
}
|
1139
|
+
|
1140
|
+
|
1141
|
+
|
1142
|
+
|
1143
|
+
static void
|
1144
|
+
na_accum_set_shape(na_shape_t *itr_shape, int rank, na_shape_t *ary_shape,
|
1145
|
+
int rankc, int *rankv)
|
1146
|
+
{
|
1147
|
+
int i;
|
1148
|
+
|
1149
|
+
if (rankc==0) {
|
1150
|
+
/* Accumulate all elements */
|
1151
|
+
for (i=0; i<rank; ++i) {
|
1152
|
+
itr_shape[i] = 1;
|
1153
|
+
rankv[i] = 1;
|
1154
|
+
}
|
1155
|
+
} else {
|
1156
|
+
/* Select Accumulate ranks */
|
1157
|
+
for (i=0; i<rank; ++i) {
|
1158
|
+
if (rankv[i]==1)
|
1159
|
+
itr_shape[i] = 1;
|
1160
|
+
else
|
1161
|
+
itr_shape[i] = ary_shape[i];
|
1162
|
+
}
|
1163
|
+
}
|
1164
|
+
}
|
1165
|
+
|
1166
|
+
|
1167
|
+
static void
|
1168
|
+
na_zero_obj(struct NARRAY *ary)
|
1169
|
+
{
|
1170
|
+
na_shape_t i;
|
1171
|
+
VALUE zero = INT2FIX(0);
|
1172
|
+
VALUE *v = (VALUE*)ary->ptr;
|
1173
|
+
|
1174
|
+
for (i=ary->total; i>0; --i)
|
1175
|
+
*(v++) = zero;
|
1176
|
+
}
|
1177
|
+
|
1178
|
+
static void
|
1179
|
+
na_zero_data(struct NARRAY *ary)
|
1180
|
+
{
|
1181
|
+
if (ary->type==NA_ROBJ)
|
1182
|
+
na_zero_obj(ary);
|
1183
|
+
else
|
1184
|
+
na_clear_data(ary);
|
1185
|
+
}
|
1186
|
+
|
1187
|
+
static VALUE
|
1188
|
+
na_sum_body(int argc, VALUE *argv, VALUE self, int flag)
|
1189
|
+
{
|
1190
|
+
na_shape_t *shape;
|
1191
|
+
int rankc, *rankv, cl_dim;
|
1192
|
+
struct NARRAY *a1, *a2;
|
1193
|
+
VALUE obj, klass;
|
1194
|
+
|
1195
|
+
GetNArray(self,a1);
|
1196
|
+
|
1197
|
+
rankv = ALLOC_N(int,a1->rank);
|
1198
|
+
rankc = na_arg_to_rank( argc, argv, a1->rank, rankv, 0 );
|
1199
|
+
|
1200
|
+
shape = ALLOC_N(na_shape_t,a1->rank);
|
1201
|
+
na_accum_set_shape( shape, a1->rank, a1->shape, rankc, rankv );
|
1202
|
+
|
1203
|
+
klass = CLASS_OF(self);
|
1204
|
+
cl_dim = na_class_dim(klass);
|
1205
|
+
if (flag==0 && cl_dim>0 && na_shrink_class(cl_dim,rankv))
|
1206
|
+
klass = cNArray;
|
1207
|
+
|
1208
|
+
obj = na_make_object(a1->type,a1->rank,shape,klass);
|
1209
|
+
GetNArray(obj,a2);
|
1210
|
+
|
1211
|
+
na_zero_data(a2);
|
1212
|
+
na_exec_unary( a2, a1, AddUFuncs[a1->type] );
|
1213
|
+
|
1214
|
+
if (flag==0)
|
1215
|
+
obj = na_shrink_rank(obj,cl_dim,rankv);
|
1216
|
+
|
1217
|
+
xfree(rankv);
|
1218
|
+
xfree(shape);
|
1219
|
+
return obj;
|
1220
|
+
}
|
1221
|
+
|
1222
|
+
/* method: sum( rank, ... ) */
|
1223
|
+
static VALUE
|
1224
|
+
na_sum(int argc, VALUE *argv, VALUE self)
|
1225
|
+
{ return na_sum_body(argc,argv,self,0); }
|
1226
|
+
|
1227
|
+
/* method: accum( rank, ... ) */
|
1228
|
+
static VALUE
|
1229
|
+
na_accum(int argc, VALUE *argv, VALUE self)
|
1230
|
+
{ return na_sum_body(argc,argv,self,1); }
|
1231
|
+
|
1232
|
+
|
1233
|
+
|
1234
|
+
static VALUE
|
1235
|
+
na_prod_body(int argc, VALUE *argv, VALUE self, int flag)
|
1236
|
+
{
|
1237
|
+
na_shape_t *shape;
|
1238
|
+
int rankc, *rankv, cl_dim;
|
1239
|
+
struct NARRAY *a1, *a2;
|
1240
|
+
VALUE obj, klass;
|
1241
|
+
int32_t one = 1;
|
1242
|
+
|
1243
|
+
GetNArray(self,a1);
|
1244
|
+
|
1245
|
+
rankv = ALLOC_N(int,a1->rank);
|
1246
|
+
rankc = na_arg_to_rank( argc, argv, a1->rank, rankv, 0 );
|
1247
|
+
|
1248
|
+
shape = ALLOC_N(na_shape_t,a1->rank);
|
1249
|
+
na_accum_set_shape( shape, a1->rank, a1->shape, rankc, rankv );
|
1250
|
+
|
1251
|
+
klass = CLASS_OF(self);
|
1252
|
+
cl_dim = na_class_dim(klass);
|
1253
|
+
if (flag==0 && cl_dim>0 && na_shrink_class(cl_dim,rankv))
|
1254
|
+
klass = cNArray;
|
1255
|
+
|
1256
|
+
obj = na_make_object(a1->type,a1->rank,shape,klass);
|
1257
|
+
GetNArray(obj,a2);
|
1258
|
+
|
1259
|
+
SetFuncs[a2->type][NA_SIZE](a2->total, a2->ptr, na_sizeof[a2->type], &one, 0);
|
1260
|
+
|
1261
|
+
na_exec_unary( a2, a1, MulUFuncs[a1->type] );
|
1262
|
+
|
1263
|
+
if (flag==0)
|
1264
|
+
obj = na_shrink_rank(obj,cl_dim,rankv);
|
1265
|
+
|
1266
|
+
xfree(rankv);
|
1267
|
+
xfree(shape);
|
1268
|
+
return obj;
|
1269
|
+
}
|
1270
|
+
|
1271
|
+
/* method: prod( rank, ... ) */
|
1272
|
+
static VALUE
|
1273
|
+
na_prod(int argc, VALUE *argv, VALUE self)
|
1274
|
+
{ return na_prod_body(argc,argv,self,0); }
|
1275
|
+
|
1276
|
+
|
1277
|
+
static VALUE
|
1278
|
+
na_mul_add_body(int argc, VALUE *argv, volatile VALUE self, volatile VALUE other,
|
1279
|
+
VALUE wrap_klass, int flag)
|
1280
|
+
{
|
1281
|
+
VALUE ans, op_klass;
|
1282
|
+
int rank, cl_dim;
|
1283
|
+
na_shape_t *dst_shape, *max_shape;
|
1284
|
+
int rankc, *rankv;
|
1285
|
+
int type;
|
1286
|
+
struct NARRAY *a1, *a2;
|
1287
|
+
|
1288
|
+
GetNArray(self,a1);
|
1289
|
+
other = na_upcast_object(other,a1->type);
|
1290
|
+
GetNArray(other,a2);
|
1291
|
+
self = na_upcast_type(self,type=a2->type);
|
1292
|
+
GetNArray(self,a1);
|
1293
|
+
|
1294
|
+
rank = NA_MAX(a1->rank,a2->rank);
|
1295
|
+
|
1296
|
+
rankv = ALLOC_N(int,rank);
|
1297
|
+
rankc = na_arg_to_rank( argc, argv, rank, rankv, 0 );
|
1298
|
+
|
1299
|
+
max_shape = ALLOC_N(na_shape_t,rank*2);
|
1300
|
+
na_shape_max_2obj(rank,max_shape,a1,a2);
|
1301
|
+
|
1302
|
+
dst_shape = &max_shape[rank];
|
1303
|
+
na_accum_set_shape( dst_shape, rank, max_shape, rankc, rankv );
|
1304
|
+
|
1305
|
+
op_klass = na_bifunc_class(CLASS_OF(self),CLASS_OF(other));
|
1306
|
+
if (op_klass==Qnil) /* coerce_rev --- unsupported */
|
1307
|
+
op_klass = cNArray;
|
1308
|
+
|
1309
|
+
cl_dim = na_class_dim(op_klass);
|
1310
|
+
if (flag==0 && cl_dim>0 && na_shrink_class(cl_dim,rankv))
|
1311
|
+
op_klass = cNArray;
|
1312
|
+
|
1313
|
+
ans = na_make_object( type, rank, dst_shape,
|
1314
|
+
(wrap_klass==Qnil) ? op_klass : wrap_klass);
|
1315
|
+
|
1316
|
+
na_zero_data( NA_STRUCT(ans) );
|
1317
|
+
na_exec_binary( NA_STRUCT(ans), a1, a2, MulAddFuncs[type] );
|
1318
|
+
|
1319
|
+
if (flag==0)
|
1320
|
+
ans = na_shrink_rank(ans,cl_dim,rankv);
|
1321
|
+
|
1322
|
+
xfree(rankv);
|
1323
|
+
xfree(max_shape);
|
1324
|
+
return ans;
|
1325
|
+
}
|
1326
|
+
|
1327
|
+
|
1328
|
+
|
1329
|
+
/* method: mul_add( other, rank, ... ) */
|
1330
|
+
static VALUE
|
1331
|
+
na_mul_add(int argc, VALUE *argv, VALUE self)
|
1332
|
+
{
|
1333
|
+
if (argc<2)
|
1334
|
+
rb_raise(rb_eArgError, "wrong # of arguments (%d for >=2)", argc);
|
1335
|
+
return na_mul_add_body(argc-1,argv+1,self,argv[0],Qnil,0);
|
1336
|
+
}
|
1337
|
+
|
1338
|
+
/* method: mul_accum( other, rank, ... ) */
|
1339
|
+
static VALUE
|
1340
|
+
na_mul_accum(int argc, VALUE *argv, VALUE self)
|
1341
|
+
{
|
1342
|
+
if (argc<2)
|
1343
|
+
rb_raise(rb_eArgError, "wrong # of arguments (%d for >=2)", argc);
|
1344
|
+
return na_mul_add_body(argc-1,argv+1,self,argv[0],Qnil,1);
|
1345
|
+
}
|
1346
|
+
|
1347
|
+
/* singleton method: NArray.mul_add( obj1, obj2, rank, ... ) */
|
1348
|
+
static VALUE
|
1349
|
+
na_s_mul_add(int argc, VALUE *argv, VALUE klass)
|
1350
|
+
{
|
1351
|
+
if (argc<3)
|
1352
|
+
rb_raise(rb_eArgError, "wrong # of arguments (%d for >=3)", argc);
|
1353
|
+
return na_mul_add_body(argc-2,argv+2,argv[0],argv[1],klass,0);
|
1354
|
+
}
|
1355
|
+
|
1356
|
+
|
1357
|
+
/* cumsum!
|
1358
|
+
[1 2 3 4 5] -> [1 3 6 10 15]
|
1359
|
+
*/
|
1360
|
+
static VALUE
|
1361
|
+
na_cumsum_bang(VALUE self)
|
1362
|
+
{
|
1363
|
+
struct NARRAY *a;
|
1364
|
+
int step;
|
1365
|
+
|
1366
|
+
GetNArray(self,a);
|
1367
|
+
|
1368
|
+
if ( a->rank != 1 )
|
1369
|
+
rb_raise( rb_eTypeError, "only for 1-dimensional array" );
|
1370
|
+
if ( a->total < 2 )
|
1371
|
+
return self; /* do nothing */
|
1372
|
+
|
1373
|
+
step = na_sizeof[a->type];
|
1374
|
+
AddUFuncs[a->type](a->total-1, a->ptr+step,step, a->ptr,step);
|
1375
|
+
|
1376
|
+
return self;
|
1377
|
+
}
|
1378
|
+
|
1379
|
+
/* cumsum */
|
1380
|
+
static VALUE
|
1381
|
+
na_cumsum(VALUE self)
|
1382
|
+
{
|
1383
|
+
return na_cumsum_bang(na_clone(self));
|
1384
|
+
}
|
1385
|
+
|
1386
|
+
|
1387
|
+
/* cumprod!
|
1388
|
+
[1 2 3 4 5] -> [1 3 6 10 15]
|
1389
|
+
*/
|
1390
|
+
static VALUE
|
1391
|
+
na_cumprod_bang(VALUE self)
|
1392
|
+
{
|
1393
|
+
struct NARRAY *a;
|
1394
|
+
int step;
|
1395
|
+
|
1396
|
+
GetNArray(self,a);
|
1397
|
+
|
1398
|
+
if ( a->rank != 1 )
|
1399
|
+
rb_raise( rb_eTypeError, "only for 1-dimensional array" );
|
1400
|
+
if ( a->total < 2 )
|
1401
|
+
return self; /* do nothing */
|
1402
|
+
|
1403
|
+
step = na_sizeof[a->type];
|
1404
|
+
MulUFuncs[a->type](a->total-1, a->ptr+step,step, a->ptr,step);
|
1405
|
+
|
1406
|
+
return self;
|
1407
|
+
}
|
1408
|
+
|
1409
|
+
/* cumprod */
|
1410
|
+
static VALUE
|
1411
|
+
na_cumprod(VALUE self)
|
1412
|
+
{
|
1413
|
+
return na_cumprod_bang(na_clone(self));
|
1414
|
+
}
|
1415
|
+
|
1416
|
+
|
1417
|
+
/* Copy element of idx=0 from a2 to a1, as start of accumulation */
|
1418
|
+
/* a1->rank <= a2->rank is assumed */
|
1419
|
+
static void
|
1420
|
+
na_minmax_copy0(struct NARRAY *a1, struct NARRAY *a2)
|
1421
|
+
{
|
1422
|
+
int i, ndim=a2->rank; /* a2 has larger rank */
|
1423
|
+
struct slice *s1, *s2;
|
1424
|
+
|
1425
|
+
/* Allocate Structure */
|
1426
|
+
s1 = ALLOC_N(struct slice, (ndim+1)*2);
|
1427
|
+
s2 = &s1[ndim+1];
|
1428
|
+
|
1429
|
+
na_set_slice_1obj(a1->rank,s1,a1->shape);
|
1430
|
+
for (i=0; i<ndim; ++i) {
|
1431
|
+
s2[i].n = a1->shape[i]; /* no-repeat if a1->shape[i]==1 */
|
1432
|
+
s2[i].beg = 0; /* copy idx=0 */
|
1433
|
+
s2[i].step = 1;
|
1434
|
+
s2[i].idx = NULL;
|
1435
|
+
}
|
1436
|
+
|
1437
|
+
/* Initialize */
|
1438
|
+
na_init_slice(s1, ndim, a1->shape, na_sizeof[a1->type] );
|
1439
|
+
na_init_slice(s2, ndim, a2->shape, na_sizeof[a2->type] );
|
1440
|
+
/* Loop */
|
1441
|
+
na_do_loop_unary( ndim, a1->ptr, a2->ptr, s1, s2,
|
1442
|
+
SetFuncs[a1->type][a2->type] );
|
1443
|
+
xfree(s1);
|
1444
|
+
}
|
1445
|
+
|
1446
|
+
|
1447
|
+
static VALUE
|
1448
|
+
na_minmax_func(int argc, VALUE *argv, VALUE self, na_ufunc_t funcs)
|
1449
|
+
{
|
1450
|
+
VALUE obj, klass;
|
1451
|
+
na_shape_t *shape;
|
1452
|
+
int rankc, *rankv, cl_dim;
|
1453
|
+
struct NARRAY *a1, *a2;
|
1454
|
+
|
1455
|
+
GetNArray(self,a1);
|
1456
|
+
|
1457
|
+
rankv = ALLOC_N(int,a1->rank);
|
1458
|
+
rankc = na_arg_to_rank( argc, argv, a1->rank, rankv, 0 );
|
1459
|
+
|
1460
|
+
shape = ALLOC_N(na_shape_t,a1->rank);
|
1461
|
+
na_accum_set_shape( shape, a1->rank, a1->shape, rankc, rankv );
|
1462
|
+
|
1463
|
+
klass = CLASS_OF(self);
|
1464
|
+
cl_dim = na_class_dim(klass);
|
1465
|
+
if (na_shrink_class(cl_dim,rankv)) klass = cNArray;
|
1466
|
+
|
1467
|
+
obj = na_make_object(a1->type,a1->rank,shape,klass);
|
1468
|
+
GetNArray(obj,a2);
|
1469
|
+
|
1470
|
+
na_minmax_copy0( a2, a1 );
|
1471
|
+
na_exec_unary( a2, a1, funcs[a1->type] );
|
1472
|
+
|
1473
|
+
obj = na_shrink_rank(obj, cl_dim, rankv);
|
1474
|
+
|
1475
|
+
xfree(rankv);
|
1476
|
+
xfree(shape);
|
1477
|
+
return obj;
|
1478
|
+
}
|
1479
|
+
|
1480
|
+
|
1481
|
+
/* method: min( rank, ... ) */
|
1482
|
+
static VALUE
|
1483
|
+
na_min(int argc, VALUE *argv, VALUE self)
|
1484
|
+
{ return na_minmax_func(argc,argv,self,MinFuncs); }
|
1485
|
+
|
1486
|
+
/* method: max( rank, ... ) */
|
1487
|
+
static VALUE
|
1488
|
+
na_max(int argc, VALUE *argv, VALUE self)
|
1489
|
+
{ return na_minmax_func(argc,argv,self,MaxFuncs); }
|
1490
|
+
|
1491
|
+
|
1492
|
+
|
1493
|
+
static int
|
1494
|
+
na_sort_number(int argc, VALUE *argv, struct NARRAY *a1)
|
1495
|
+
{
|
1496
|
+
int i, rank;
|
1497
|
+
na_shape_t nsort;
|
1498
|
+
|
1499
|
+
if (argc==0) {
|
1500
|
+
rank = a1->rank-1;
|
1501
|
+
} else {
|
1502
|
+
rank = NUM2INT(argv[0]);
|
1503
|
+
if (rank >= a1->rank || rank < -a1->rank)
|
1504
|
+
rb_raise(rb_eArgError,"illeagal rank:%i out of %i",rank,a1->rank);
|
1505
|
+
if (rank < 0) rank += a1->rank;
|
1506
|
+
}
|
1507
|
+
|
1508
|
+
nsort = 1;
|
1509
|
+
for (i=0; i<=rank; ++i)
|
1510
|
+
nsort *= a1->shape[i];
|
1511
|
+
return nsort;
|
1512
|
+
}
|
1513
|
+
|
1514
|
+
|
1515
|
+
/* method: sort([rank]) */
|
1516
|
+
static VALUE
|
1517
|
+
na_sort(int argc, VALUE *argv, VALUE self)
|
1518
|
+
{
|
1519
|
+
struct NARRAY *a1, *a2;
|
1520
|
+
VALUE obj;
|
1521
|
+
int (*func)(const void*, const void*);
|
1522
|
+
na_shape_t i, size, step, nloop, nsort;
|
1523
|
+
char *ptr;
|
1524
|
+
|
1525
|
+
GetNArray(self,a1);
|
1526
|
+
|
1527
|
+
nsort = na_sort_number(argc,argv,a1);
|
1528
|
+
nloop = a1->total/nsort;
|
1529
|
+
|
1530
|
+
obj = na_make_object(a1->type,a1->rank,a1->shape,CLASS_OF(self));
|
1531
|
+
GetNArray(obj,a2);
|
1532
|
+
memcpy(a2->ptr, a1->ptr, a1->total*na_sizeof[a1->type]);
|
1533
|
+
func = SortFuncs[a2->type];
|
1534
|
+
size = na_sizeof[a2->type];
|
1535
|
+
ptr = a2->ptr;
|
1536
|
+
step = size * nsort;
|
1537
|
+
|
1538
|
+
for (i=0; i<nloop; ++i) {
|
1539
|
+
qsort( ptr, nsort, size, func );
|
1540
|
+
ptr += step;
|
1541
|
+
}
|
1542
|
+
return obj;
|
1543
|
+
}
|
1544
|
+
|
1545
|
+
|
1546
|
+
/* method: sort!([rank]) */
|
1547
|
+
static VALUE
|
1548
|
+
na_sort_bang(int argc, VALUE *argv, VALUE self)
|
1549
|
+
{
|
1550
|
+
struct NARRAY *a1;
|
1551
|
+
int (*func)(const void*, const void*);
|
1552
|
+
na_shape_t i, size, step, nloop, nsort;
|
1553
|
+
char *ptr;
|
1554
|
+
|
1555
|
+
GetNArray(self,a1);
|
1556
|
+
|
1557
|
+
nsort = na_sort_number(argc,argv,a1);
|
1558
|
+
nloop = a1->total/nsort;
|
1559
|
+
|
1560
|
+
func = SortFuncs[a1->type];
|
1561
|
+
size = na_sizeof[a1->type];
|
1562
|
+
ptr = a1->ptr;
|
1563
|
+
step = size * nsort;
|
1564
|
+
|
1565
|
+
for (i=0; i<nloop; ++i) {
|
1566
|
+
qsort( ptr, nsort, size, func );
|
1567
|
+
ptr += step;
|
1568
|
+
}
|
1569
|
+
return self;
|
1570
|
+
}
|
1571
|
+
|
1572
|
+
|
1573
|
+
/* method: sort_index([rank]) */
|
1574
|
+
static VALUE
|
1575
|
+
na_sort_index(int argc, VALUE *argv, VALUE self)
|
1576
|
+
{
|
1577
|
+
struct NARRAY *a1, *a2;
|
1578
|
+
VALUE obj;
|
1579
|
+
int (*func)(const void*, const void*);
|
1580
|
+
na_shape_t i, size, nloop, nsort;
|
1581
|
+
char **ptr_ptr, **ptr_p;
|
1582
|
+
char *ptr_ary, *ptr_a;
|
1583
|
+
|
1584
|
+
GetNArray(self,a1);
|
1585
|
+
|
1586
|
+
nsort = na_sort_number(argc,argv,a1);
|
1587
|
+
nloop = a1->total/nsort;
|
1588
|
+
|
1589
|
+
size = na_sizeof[a1->type];
|
1590
|
+
ptr_p = ptr_ptr = ALLOC_N(char*, a1->total);
|
1591
|
+
ptr_a = ptr_ary = a1->ptr;
|
1592
|
+
|
1593
|
+
for (i=a1->total; i>0; --i) {
|
1594
|
+
*(ptr_p++) = ptr_a;
|
1595
|
+
ptr_a += size;
|
1596
|
+
}
|
1597
|
+
|
1598
|
+
func = SortIdxFuncs[a1->type];
|
1599
|
+
ptr_p = ptr_ptr;
|
1600
|
+
|
1601
|
+
for (i=0; i<nloop; ++i) {
|
1602
|
+
qsort( ptr_p, nsort, sizeof(char*), func );
|
1603
|
+
ptr_p += nsort;
|
1604
|
+
}
|
1605
|
+
|
1606
|
+
obj = na_make_object(NA_SIZE,a1->rank,a1->shape,CLASS_OF(self));
|
1607
|
+
GetNArray(obj,a2);
|
1608
|
+
ptr_p = ptr_ptr;
|
1609
|
+
if ( NA_SIZE == NA_LINT ) {
|
1610
|
+
int32_t *ptr_i;
|
1611
|
+
ptr_i = (int32_t*)(a2->ptr);
|
1612
|
+
for (i=a2->total; i>0; --i) {
|
1613
|
+
*(ptr_i++) = (int32_t)(*(ptr_p++)-ptr_ary)/size;
|
1614
|
+
}
|
1615
|
+
} else if ( NA_SIZE == NA_LLINT ) {
|
1616
|
+
int64_t *ptr_i;
|
1617
|
+
ptr_i = (int64_t*)(a2->ptr);
|
1618
|
+
for (i=a2->total; i>0; --i) {
|
1619
|
+
*(ptr_i++) = (int64_t)(*(ptr_p++)-ptr_ary)/size;
|
1620
|
+
}
|
1621
|
+
}
|
1622
|
+
xfree(ptr_ptr);
|
1623
|
+
return obj;
|
1624
|
+
}
|
1625
|
+
|
1626
|
+
|
1627
|
+
|
1628
|
+
void Init_na_funcs(void)
|
1629
|
+
{
|
1630
|
+
rb_define_method(cNArray, "+", na_add, 1);
|
1631
|
+
rb_define_method(cNArray, "-", na_sbt, 1);
|
1632
|
+
rb_define_method(cNArray, "*", na_mul, 1);
|
1633
|
+
rb_define_method(cNArray, "/", na_div, 1);
|
1634
|
+
rb_define_method(cNArray, "%", na_mod, 1);
|
1635
|
+
rb_define_alias (cNArray, "mod", "%");
|
1636
|
+
rb_define_method(cNArray, "&", na_bit_and, 1);
|
1637
|
+
rb_define_method(cNArray, "|", na_bit_or, 1);
|
1638
|
+
rb_define_method(cNArray, "^", na_bit_xor, 1);
|
1639
|
+
rb_define_method(cNArray, "**", na_power, 1);
|
1640
|
+
|
1641
|
+
rb_define_method(cNArray, "add!", na_add_bang, 1);
|
1642
|
+
rb_define_method(cNArray, "sbt!", na_sbt_bang, 1);
|
1643
|
+
rb_define_method(cNArray, "mul!", na_mul_bang, 1);
|
1644
|
+
rb_define_method(cNArray, "div!", na_div_bang, 1);
|
1645
|
+
rb_define_method(cNArray, "mod!", na_mod_bang, 1);
|
1646
|
+
rb_define_method(cNArray, "imag=",na_imag_set, 1);
|
1647
|
+
|
1648
|
+
rb_define_method(cNArray, "swap_byte", na_swap_byte, 0);
|
1649
|
+
rb_define_method(cNArray, "hton", na_hton, 0);
|
1650
|
+
rb_define_alias (cNArray, "ntoh", "hton");
|
1651
|
+
rb_define_method(cNArray, "htov", na_htov, 0);
|
1652
|
+
rb_define_alias (cNArray, "vtoh", "htov");
|
1653
|
+
rb_define_method(cNArray, "-@", na_neg, 0);
|
1654
|
+
rb_define_method(cNArray, "recip",na_recip, 0);
|
1655
|
+
rb_define_method(cNArray, "abs", na_abs, 0);
|
1656
|
+
rb_define_method(cNArray, "real", na_real, 0);
|
1657
|
+
rb_define_method(cNArray, "imag", na_imag, 0);
|
1658
|
+
rb_define_alias (cNArray, "image", "imag");
|
1659
|
+
rb_define_method(cNArray, "angle", na_angle, 0);
|
1660
|
+
rb_define_alias (cNArray, "arg", "angle");
|
1661
|
+
rb_define_method(cNArray, "conj", na_conj, 0);
|
1662
|
+
rb_define_alias (cNArray, "conjugate", "conj");
|
1663
|
+
rb_define_method(cNArray, "conj!", na_conj_bang, 0);
|
1664
|
+
rb_define_alias (cNArray, "conjugate!", "conj!");
|
1665
|
+
rb_define_method(cNArray, "im", na_imag_mul, 0);
|
1666
|
+
rb_define_method(cNArray, "floor",na_floor, 0);
|
1667
|
+
rb_define_method(cNArray, "ceil", na_ceil, 0);
|
1668
|
+
rb_define_method(cNArray, "round",na_round, 0);
|
1669
|
+
rb_define_method(cNArray, "~", na_bit_rev, 0);
|
1670
|
+
rb_define_method(cNArray, "not", na_not, 0);
|
1671
|
+
|
1672
|
+
rb_define_method(cNArray, "<=>", na_compare, 1);
|
1673
|
+
rb_define_method(cNArray, "eq", na_equal, 1);
|
1674
|
+
rb_define_method(cNArray, "ne", na_not_equal, 1);
|
1675
|
+
rb_define_method(cNArray, "gt", na_greater_than, 1);
|
1676
|
+
rb_define_alias (cNArray, ">", "gt");
|
1677
|
+
rb_define_method(cNArray, "ge", na_greater_equal, 1);
|
1678
|
+
rb_define_alias (cNArray, ">=", "ge");
|
1679
|
+
rb_define_method(cNArray, "lt", na_less_than, 1);
|
1680
|
+
rb_define_alias (cNArray, "<", "lt");
|
1681
|
+
rb_define_method(cNArray, "le", na_less_equal, 1);
|
1682
|
+
rb_define_alias (cNArray, "<=", "le");
|
1683
|
+
rb_define_method(cNArray, "and", na_cond_and, 1);
|
1684
|
+
rb_define_method(cNArray, "or", na_cond_or, 1);
|
1685
|
+
rb_define_method(cNArray, "xor", na_cond_xor, 1);
|
1686
|
+
|
1687
|
+
rb_define_method(cNArray, "mul_add", na_mul_add, -1);
|
1688
|
+
rb_define_method(cNArray, "mul_accum", na_mul_accum, -1);
|
1689
|
+
|
1690
|
+
rb_define_method(cNArray, "sum", na_sum, -1);
|
1691
|
+
rb_define_method(cNArray, "accum", na_accum, -1);
|
1692
|
+
rb_define_method(cNArray, "prod", na_prod, -1);
|
1693
|
+
rb_define_method(cNArray, "min", na_min, -1);
|
1694
|
+
rb_define_method(cNArray, "max", na_max, -1);
|
1695
|
+
rb_define_method(cNArray, "cumsum!", na_cumsum_bang, 0);
|
1696
|
+
rb_define_method(cNArray, "cumsum", na_cumsum, 0);
|
1697
|
+
rb_define_method(cNArray, "cumprod!", na_cumprod_bang, 0);
|
1698
|
+
rb_define_method(cNArray, "cumprod", na_cumprod, 0);
|
1699
|
+
rb_define_method(cNArray, "sort", na_sort, -1);
|
1700
|
+
rb_define_method(cNArray, "sort!", na_sort_bang, -1);
|
1701
|
+
rb_define_method(cNArray, "sort_index", na_sort_index, -1);
|
1702
|
+
rb_define_method(cNArray, "transpose", na_transpose, -1);
|
1703
|
+
|
1704
|
+
rb_define_singleton_method(cNArray,"mul",na_s_mul,2);
|
1705
|
+
rb_define_singleton_method(cNArray,"div",na_s_div,2);
|
1706
|
+
rb_define_singleton_method(cNArray,"mul_add",na_s_mul_add,-1);
|
1707
|
+
|
1708
|
+
rb_define_module_function(rb_mNMath,"atan2",na_math_atan2,2);
|
1709
|
+
}
|