narray 0.5.9.4

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