narray 0.5.9.4

Sign up to get free protection for your applications and to get access to all the features.
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
+ }