narray-nmatrix 0.6.1.0.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1705 @@
1
+ /*
2
+ na_func.c
3
+ Numerical Array Extention for Ruby
4
+ (C) Copyright 1999-2008 by Masahiro TANAKA
5
+
6
+ This program is free software.
7
+ You can distribute/modify this program
8
+ under the same terms as Ruby itself.
9
+ NO WARRANTY.
10
+ */
11
+ #include <ruby.h>
12
+ #include "narray.h"
13
+ #include "narray_local.h"
14
+
15
+ 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, ID2SYM(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
+ return obj3;
657
+ }
658
+
659
+
660
+ static VALUE
661
+ na_set_func(VALUE obj1, volatile VALUE obj2, na_ufunc_t funcs)
662
+ {
663
+ struct NARRAY *a1;
664
+
665
+ GetNArray(obj1,a1);
666
+ obj2 = na_cast_object(obj2,a1->type);
667
+
668
+ na_exec_unary( NA_STRUCT(obj1), NA_STRUCT(obj2), funcs[a1->type] );
669
+
670
+ return obj1;
671
+ }
672
+
673
+
674
+ static VALUE
675
+ na_imag_set(VALUE obj1, volatile VALUE obj2)
676
+ {
677
+ struct NARRAY *a1;
678
+
679
+ GetNArray(obj1,a1);
680
+ obj2 = na_cast_object(obj2, na_cast_real[a1->type]);
681
+
682
+ na_exec_unary( NA_STRUCT(obj1), NA_STRUCT(obj2), ImgSetFuncs[a1->type] );
683
+
684
+ return obj1;
685
+ }
686
+
687
+
688
+ static VALUE
689
+ na_unary_func(VALUE self, const int *cast, na_ufunc_t funcs)
690
+ {
691
+ VALUE ans;
692
+ struct NARRAY *a2;
693
+
694
+ GetNArray(self,a2);
695
+ ans = na_make_object(cast[a2->type], a2->rank, a2->shape, CLASS_OF(self));
696
+
697
+ na_exec_unary( NA_STRUCT(ans), a2, funcs[a2->type] );
698
+ return ans;
699
+ }
700
+
701
+
702
+
703
+ /* local function for comparison */
704
+ static VALUE
705
+ na_compare_func(VALUE self, VALUE other, na_bifunc_t funcs)
706
+ {
707
+ VALUE ans;
708
+ int type;
709
+
710
+ Check_Type(self, T_DATA);
711
+ /*if (NA_IsComplex(a1)) rb_raise();*/
712
+ other = na_upcast_object(other,NA_STRUCT(self)->type);
713
+ self = na_upcast_type(self,type=NA_STRUCT(other)->type);
714
+
715
+ ans = na_make_object_extend( NA_STRUCT(self), NA_STRUCT(other),
716
+ NA_BYTE, cNArray );
717
+
718
+ na_exec_binary( NA_STRUCT(ans), NA_STRUCT(self), NA_STRUCT(other),
719
+ funcs[type] );
720
+ return ans;
721
+ }
722
+
723
+
724
+ /* method: self + other */
725
+ static VALUE na_add(VALUE obj1, VALUE obj2)
726
+ { return na_bifunc( obj1, obj2, Qnil, AddBFuncs ); }
727
+
728
+ /* method: self - other */
729
+ static VALUE na_sbt(VALUE obj1, VALUE obj2)
730
+ { return na_bifunc( obj1, obj2, Qnil, SbtBFuncs ); }
731
+
732
+ /* method: self * other */
733
+ static VALUE na_mul(VALUE obj1, VALUE obj2)
734
+ { return na_bifunc( obj1, obj2, Qnil, MulBFuncs ); }
735
+
736
+ /* method: self / other */
737
+ static VALUE na_div(VALUE obj1, VALUE obj2)
738
+ { return na_bifunc( obj1, obj2, Qnil, DivBFuncs ); }
739
+
740
+ /* method: self / other */
741
+ static VALUE na_mod(VALUE obj1, VALUE obj2)
742
+ { return na_bifunc( obj1, obj2, Qnil, ModBFuncs ); }
743
+
744
+ /* method: self & other */
745
+ static VALUE na_bit_and(VALUE obj1, VALUE obj2)
746
+ { return na_bifunc( obj1, obj2, Qnil, BAnFuncs ); }
747
+
748
+ /* method: self | other */
749
+ static VALUE na_bit_or(VALUE obj1, VALUE obj2)
750
+ { return na_bifunc( obj1, obj2, Qnil, BOrFuncs ); }
751
+
752
+ /* method: self ^ other */
753
+ static VALUE na_bit_xor(VALUE obj1, VALUE obj2)
754
+ { return na_bifunc( obj1, obj2, Qnil, BXoFuncs ); }
755
+
756
+ /* method: atan2(y,x) */
757
+ static VALUE na_math_atan2(VALUE module, volatile VALUE y, volatile VALUE x)
758
+ {
759
+ VALUE ans;
760
+ struct NARRAY *ya, *xa, *aa;
761
+
762
+ if (TYPE(y) == T_ARRAY) {
763
+ y = na_ary_to_nary(y,cNArray);
764
+ } else
765
+ if (!IsNArray(y)) {
766
+ y = na_make_scalar(y,na_object_type(y));
767
+ }
768
+
769
+ if (TYPE(x) == T_ARRAY) {
770
+ x = na_ary_to_nary(x,cNArray);
771
+ } else
772
+ if (!IsNArray(x)) {
773
+ x = na_make_scalar(x,na_object_type(x));
774
+ }
775
+
776
+ GetNArray(y,ya);
777
+ GetNArray(x,xa);
778
+ if (NA_IsINTEGER(ya) && NA_IsINTEGER(xa)) {
779
+ y = na_upcast_type(y,NA_DFLOAT);
780
+ x = na_upcast_type(x,NA_DFLOAT);
781
+ }
782
+
783
+ ans = na_bifunc( y, x, Qnil, atan2Funcs );
784
+ GetNArray(ans,aa);
785
+
786
+ if (CLASS_OF(y) == cNArrayScalar && CLASS_OF(x) == cNArrayScalar)
787
+ SetFuncs[NA_ROBJ][aa->type](1,&ans,0,aa->ptr,0);
788
+
789
+ return ans;
790
+ }
791
+
792
+
793
+
794
+ /* singleton method: NArray.mul( obj1, obj2 ) */
795
+ static VALUE
796
+ na_s_mul(VALUE klass, VALUE obj1, VALUE obj2)
797
+ { return na_bifunc( obj1, obj2, klass, MulBFuncs ); }
798
+
799
+ /* singleton method: NArray.div( obj1, obj2 ) */
800
+ static VALUE
801
+ na_s_div(VALUE klass, VALUE obj1, VALUE obj2)
802
+ { return na_bifunc( obj1, obj2, klass, DivBFuncs ); }
803
+
804
+
805
+
806
+ /* method: self.add!(other) */
807
+ static VALUE na_add_bang(VALUE obj1, VALUE obj2)
808
+ { return na_set_func( obj1, obj2, AddUFuncs ); }
809
+
810
+ /* method: self.sbt!(other) */
811
+ static VALUE na_sbt_bang(VALUE obj1, VALUE obj2)
812
+ { return na_set_func( obj1, obj2, SbtUFuncs ); }
813
+
814
+ /* method: self.div!(other) */
815
+ static VALUE na_div_bang(VALUE obj1, VALUE obj2)
816
+ { return na_set_func( obj1, obj2, DivUFuncs ); }
817
+
818
+ /* method: self.mul!(other) */
819
+ static VALUE na_mul_bang(VALUE obj1, VALUE obj2)
820
+ { return na_set_func( obj1, obj2, MulUFuncs ); }
821
+
822
+ /* method: self.mod!(other) */
823
+ static VALUE na_mod_bang(VALUE obj1, VALUE obj2)
824
+ { return na_set_func( obj1, obj2, ModUFuncs ); }
825
+
826
+ /* method: self.conj! */
827
+ static VALUE na_conj_bang(VALUE self)
828
+ { return na_set_func( self, self, ConjFuncs ); }
829
+
830
+
831
+ /* method: self.swap_byte */
832
+ static VALUE na_swap_byte(VALUE self)
833
+ { return na_unary_func( self, na_no_cast, SwpFuncs ); }
834
+
835
+ /* method: self.hton , self.ntoh */
836
+ static VALUE na_hton(VALUE self)
837
+ { return na_unary_func( self, na_no_cast, H2NFuncs ); }
838
+
839
+ /* method: self.htov , self.vtoh */
840
+ static VALUE na_htov(VALUE self)
841
+ { return na_unary_func( self, na_no_cast, H2VFuncs ); }
842
+
843
+ /* method: ~self */
844
+ static VALUE na_bit_rev(VALUE self)
845
+ { return na_unary_func( self, na_no_cast, BRvFuncs ); }
846
+
847
+ /* method: -self */
848
+ static VALUE na_neg(VALUE self)
849
+ { return na_unary_func( self, na_no_cast, NegFuncs ); }
850
+
851
+ /* method: self.recip */
852
+ static VALUE na_recip(VALUE self)
853
+ { return na_unary_func( self, na_no_cast, RcpFuncs ); }
854
+
855
+ /* method: self.abs */
856
+ static VALUE na_abs(VALUE self)
857
+ { return na_unary_func( self, na_cast_real, AbsFuncs ); }
858
+
859
+ /* method: self.real */
860
+ static VALUE na_real(VALUE self)
861
+ { return na_unary_func( self, na_cast_real, RealFuncs ); }
862
+
863
+ /* method: self.imag */
864
+ static VALUE na_imag(VALUE self)
865
+ { return na_unary_func( self, na_cast_real, ImagFuncs ); }
866
+
867
+ /* method: self.imag */
868
+ static VALUE na_angle(VALUE self)
869
+ { return na_unary_func( self, na_cast_real, AnglFuncs ); }
870
+
871
+ /* method: self.im */
872
+ static VALUE na_imag_mul(VALUE self)
873
+ { return na_unary_func( self, na_cast_comp, ImagMulFuncs ); }
874
+
875
+ /* method: self.conj */
876
+ static VALUE na_conj(VALUE self)
877
+ { return na_unary_func( self, na_no_cast, ConjFuncs ); }
878
+
879
+ /* method: self.floor */
880
+ static VALUE na_floor(VALUE self)
881
+ { return na_unary_func( self, na_cast_round, FloorFuncs ); }
882
+
883
+ /* method: self.ceil */
884
+ static VALUE na_ceil(VALUE self)
885
+ { return na_unary_func( self, na_cast_round, CeilFuncs ); }
886
+
887
+ /* method: self.round */
888
+ static VALUE na_round(VALUE self)
889
+ { return na_unary_func( self, na_cast_round, RoundFuncs ); }
890
+
891
+ /* method: self.not */
892
+ static VALUE na_not(VALUE self)
893
+ { return na_unary_func( self, na_cast_byte, NotFuncs ); }
894
+
895
+
896
+ /* method: self.and other */
897
+ static VALUE
898
+ na_cond_and(VALUE obj1, VALUE obj2)
899
+ { return na_compare_func( obj1, obj2, AndFuncs ); }
900
+
901
+ /* method: self.or other */
902
+ static VALUE
903
+ na_cond_or(VALUE obj1, VALUE obj2)
904
+ { return na_compare_func( obj1, obj2, Or_Funcs ); }
905
+
906
+ /* method: self.xor other */
907
+ static VALUE
908
+ na_cond_xor(VALUE obj1, VALUE obj2)
909
+ { return na_compare_func( obj1, obj2, XorFuncs ); }
910
+
911
+
912
+
913
+ /* method: self <=> other */
914
+ static VALUE
915
+ na_compare(VALUE obj1, VALUE obj2)
916
+ { return na_compare_func( obj1, obj2, CmpFuncs ); }
917
+
918
+
919
+
920
+ /* method: self.eq(other) */
921
+ static VALUE
922
+ na_equal(VALUE obj1, VALUE obj2)
923
+ {
924
+ return na_compare_func( obj1, obj2, EqlFuncs );
925
+ }
926
+
927
+ /* method: self.ne(other) */
928
+ static VALUE
929
+ na_not_equal(VALUE obj1, VALUE obj2)
930
+ {
931
+ VALUE obj;
932
+ int i; char *p;
933
+ struct NARRAY *a;
934
+
935
+ obj = na_compare_func( obj1, obj2, EqlFuncs );
936
+ GetNArray(obj,a);
937
+ p = a->ptr;
938
+ for( i=a->total; i-->0; ) {
939
+ *p = *p==0 ? 1 : 0;
940
+ ++p;
941
+ }
942
+ return obj;
943
+ }
944
+
945
+ /* method: self > other */
946
+ static VALUE
947
+ na_greater_than(VALUE self, VALUE obj2)
948
+ {
949
+ int i; char *p;
950
+ struct NARRAY *a;
951
+
952
+ self = na_compare_func( self, obj2, CmpFuncs );
953
+ GetNArray(self,a);
954
+ p = a->ptr;
955
+ for( i=a->total; i-->0; ) {
956
+ if (*p!=1) *p=0;
957
+ ++p;
958
+ }
959
+ return self;
960
+ }
961
+
962
+ /* method: self >= other */
963
+ static VALUE
964
+ na_greater_equal(VALUE obj1, VALUE obj2)
965
+ {
966
+ VALUE obj;
967
+ int i; char *p;
968
+ struct NARRAY *a;
969
+
970
+ obj = na_compare_func( obj1, obj2, CmpFuncs );
971
+ GetNArray(obj,a);
972
+ p = a->ptr;
973
+ for( i=a->total; i-->0; ) {
974
+ if (*p==1 || *p==0) *p=1;
975
+ else *p=0;
976
+ ++p;
977
+ }
978
+ return obj;
979
+ }
980
+
981
+ /* method: self < other */
982
+ static VALUE
983
+ na_less_than(VALUE obj1, VALUE obj2)
984
+ {
985
+ VALUE obj;
986
+ int i; char *p;
987
+ struct NARRAY *a;
988
+
989
+ obj = na_compare_func( obj1, obj2, CmpFuncs );
990
+ GetNArray(obj,a);
991
+ p = a->ptr;
992
+ for( i=a->total; i-->0; ) {
993
+ if (*p==2) *p=1;
994
+ else *p=0;
995
+ ++p;
996
+ }
997
+ return obj;
998
+ }
999
+
1000
+ /* method: self <= other */
1001
+ static VALUE
1002
+ na_less_equal(VALUE obj1, VALUE obj2)
1003
+ {
1004
+ VALUE obj;
1005
+ int i; char *p;
1006
+ struct NARRAY *a;
1007
+
1008
+ obj = na_compare_func( obj1, obj2, CmpFuncs );
1009
+ GetNArray(obj,a);
1010
+ p = a->ptr;
1011
+ for( i=a->total; i-->0; ) {
1012
+ if (*p==2 || *p==0) *p=1;
1013
+ else *p=0;
1014
+ ++p;
1015
+ }
1016
+ return obj;
1017
+ }
1018
+
1019
+
1020
+
1021
+
1022
+ /*
1023
+ ------- Sum, Min, Max, Transpose --------
1024
+ */
1025
+ VALUE
1026
+ rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err );
1027
+
1028
+ static int
1029
+ na_arg_to_rank(int argc, VALUE *argv, int rankc, int *rankv, int flag)
1030
+ /* e.g.: argv=[1,3..5]
1031
+ if flag==0
1032
+ rankv = [0,1,0,1,1,1,0,..]
1033
+ else
1034
+ rankv = [1,3,4,5]
1035
+ */
1036
+ {
1037
+ int i, j, c=0;
1038
+ long r, n;
1039
+ VALUE v;
1040
+
1041
+ if (flag==0)
1042
+ MEMZERO(rankv,int,rankc);
1043
+
1044
+ for (i=0;i<argc;++i) {
1045
+ if ( c >= rankc )
1046
+ rb_raise(rb_eArgError, "too many ranks");
1047
+
1048
+ v = argv[i];
1049
+
1050
+ if (TYPE(v)==T_FIXNUM) {
1051
+ r = NUM2INT(v);
1052
+ if (r<0) r += rankc; /* negative for from end */
1053
+ if (r<0 || r>=rankc)
1054
+ rb_raise(rb_eArgError, "rank %ld out of range", r);
1055
+ if (flag)
1056
+ rankv[c] = r;
1057
+ else
1058
+ rankv[r] = 1;
1059
+ ++c;
1060
+ }
1061
+ else
1062
+ if (CLASS_OF(v)==rb_cRange) {
1063
+ rb_range_beg_len( v, &r, &n, rankc, 1 );
1064
+ if ( c+n > rankc )
1065
+ rb_raise(rb_eArgError, "too many ranks");
1066
+ if (flag) {
1067
+ for(j=0; j<n; ++j)
1068
+ rankv[c++] = r++;
1069
+ } else {
1070
+ for(j=0; j<n; ++j) {
1071
+ rankv[r++] = 1;
1072
+ ++c;
1073
+ }
1074
+ }
1075
+ }
1076
+ else
1077
+ rb_raise(rb_eArgError, "wrong type");
1078
+ }
1079
+ return c;
1080
+ }
1081
+
1082
+
1083
+
1084
+ /* Transpose procedure */
1085
+ static struct NARRAY *
1086
+ na_transpose_bifunc(struct NARRAY *a1, struct NARRAY *a2, int *trans)
1087
+ {
1088
+ int i, ndim=a2->rank;
1089
+ struct slice *s1, *s2;
1090
+
1091
+ s1 = ALLOC_N(struct slice, (ndim+1)*2);
1092
+ s2 = &s1[ndim+1];
1093
+
1094
+ /* for Source array -- s1 is temporarily used */
1095
+ na_set_slice_1obj(a2->rank,s1,a2->shape);
1096
+ na_init_slice( s1, ndim, a2->shape, na_sizeof[a2->type] );
1097
+
1098
+ /* Transpose Slice */
1099
+ for (i=0; i<ndim; ++i)
1100
+ s2[i] = s1[trans[i]];
1101
+ s2[ndim] = s1[ndim];
1102
+
1103
+ /* for Destination */
1104
+ na_set_slice_1obj(a1->rank,s1,a1->shape);
1105
+ na_init_slice( s1, ndim, a1->shape, na_sizeof[a1->type] );
1106
+
1107
+ /* Loop */
1108
+ na_do_loop_unary( ndim, a1->ptr, a2->ptr, s1, s2,
1109
+ SetFuncs[a1->type][a2->type] );
1110
+ xfree(s1);
1111
+ return a1;
1112
+ }
1113
+
1114
+
1115
+ /* method: self.transpose( ... ) */
1116
+ static VALUE
1117
+ na_transpose(int argc, VALUE *argv, VALUE self)
1118
+ {
1119
+ struct NARRAY *a2;
1120
+ int i, rankc, *rankv, *shape;
1121
+ VALUE obj;
1122
+
1123
+ GetNArray(self,a2);
1124
+
1125
+ /* Parse Argument */
1126
+ rankv = ALLOC_N( int, NA_MAX_RANK*2 );
1127
+ shape = &rankv[NA_MAX_RANK];
1128
+ rankc = na_arg_to_rank( argc, argv, a2->rank, rankv, 1 );
1129
+ if (rankc > a2->rank)
1130
+ rb_raise(rb_eArgError, "too many args");
1131
+ for ( ;rankc<a2->rank; ++rankc)
1132
+ rankv[rankc] = rankc;
1133
+
1134
+ /* Argument Check */
1135
+ MEMZERO(shape,int,rankc);
1136
+ for (i=0; i<rankc; ++i) {
1137
+ if (shape[rankv[i]] != 0)
1138
+ rb_raise(rb_eArgError,"rank doublebooking");
1139
+ shape[rankv[i]] = 1;
1140
+ }
1141
+
1142
+ for (i=0; i<a2->rank; ++i)
1143
+ shape[i] = a2->shape[rankv[i]];
1144
+
1145
+ obj = na_make_object(a2->type, a2->rank, shape, CLASS_OF(self));
1146
+
1147
+ na_transpose_bifunc( NA_STRUCT(obj), a2, rankv );
1148
+ xfree(rankv);
1149
+ return obj;
1150
+ }
1151
+
1152
+
1153
+
1154
+
1155
+ static void
1156
+ na_accum_set_shape(int *itr_shape, int rank, int *ary_shape,
1157
+ int rankc, int *rankv)
1158
+ {
1159
+ int i;
1160
+
1161
+ if (rankc==0) {
1162
+ /* Accumulate all elements */
1163
+ for (i=0; i<rank; ++i) {
1164
+ itr_shape[i] = 1;
1165
+ rankv[i] = 1;
1166
+ }
1167
+ } else {
1168
+ /* Select Accumulate ranks */
1169
+ for (i=0; i<rank; ++i) {
1170
+ if (rankv[i]==1)
1171
+ itr_shape[i] = 1;
1172
+ else
1173
+ itr_shape[i] = ary_shape[i];
1174
+ }
1175
+ }
1176
+ }
1177
+
1178
+
1179
+ static void
1180
+ na_zero_obj(struct NARRAY *ary)
1181
+ {
1182
+ int i;
1183
+ VALUE zero = INT2FIX(0);
1184
+ VALUE *v = (VALUE*)ary->ptr;
1185
+
1186
+ for (i=ary->total; i>0; --i)
1187
+ *(v++) = zero;
1188
+ }
1189
+
1190
+ static void
1191
+ na_zero_data(struct NARRAY *ary)
1192
+ {
1193
+ if (ary->type==NA_ROBJ)
1194
+ na_zero_obj(ary);
1195
+ else
1196
+ na_clear_data(ary);
1197
+ }
1198
+
1199
+ static VALUE
1200
+ na_sum_body(int argc, VALUE *argv, VALUE self, int flag)
1201
+ {
1202
+ int *shape, rankc, *rankv, cl_dim;
1203
+ struct NARRAY *a1, *a2;
1204
+ VALUE obj, klass;
1205
+
1206
+ GetNArray(self,a1);
1207
+
1208
+ rankv = ALLOC_N(int,a1->rank*2);
1209
+ rankc = na_arg_to_rank( argc, argv, a1->rank, rankv, 0 );
1210
+
1211
+ shape = &rankv[a1->rank];
1212
+ na_accum_set_shape( shape, a1->rank, a1->shape, rankc, rankv );
1213
+
1214
+ klass = CLASS_OF(self);
1215
+ cl_dim = na_class_dim(klass);
1216
+ if (flag==0 && cl_dim>0 && na_shrink_class(cl_dim,rankv))
1217
+ klass = cNArray;
1218
+
1219
+ obj = na_make_object(a1->type,a1->rank,shape,klass);
1220
+ GetNArray(obj,a2);
1221
+
1222
+ na_zero_data(a2);
1223
+ na_exec_unary( a2, a1, AddUFuncs[a1->type] );
1224
+
1225
+ if (flag==0)
1226
+ obj = na_shrink_rank(obj,cl_dim,rankv);
1227
+
1228
+ xfree(rankv);
1229
+ return obj;
1230
+ }
1231
+
1232
+ /* method: sum( rank, ... ) */
1233
+ static VALUE
1234
+ na_sum(int argc, VALUE *argv, VALUE self)
1235
+ { return na_sum_body(argc,argv,self,0); }
1236
+
1237
+ /* method: accum( rank, ... ) */
1238
+ static VALUE
1239
+ na_accum(int argc, VALUE *argv, VALUE self)
1240
+ { return na_sum_body(argc,argv,self,1); }
1241
+
1242
+
1243
+
1244
+ static VALUE
1245
+ na_prod_body(int argc, VALUE *argv, VALUE self, int flag)
1246
+ {
1247
+ int *shape, rankc, *rankv, cl_dim;
1248
+ struct NARRAY *a1, *a2;
1249
+ VALUE obj, klass;
1250
+ int32_t one = 1;
1251
+
1252
+ GetNArray(self,a1);
1253
+
1254
+ rankv = ALLOC_N(int,a1->rank*2);
1255
+ rankc = na_arg_to_rank( argc, argv, a1->rank, rankv, 0 );
1256
+
1257
+ shape = &rankv[a1->rank];
1258
+ na_accum_set_shape( shape, a1->rank, a1->shape, rankc, rankv );
1259
+
1260
+ klass = CLASS_OF(self);
1261
+ cl_dim = na_class_dim(klass);
1262
+ if (flag==0 && cl_dim>0 && na_shrink_class(cl_dim,rankv))
1263
+ klass = cNArray;
1264
+
1265
+ obj = na_make_object(a1->type,a1->rank,shape,klass);
1266
+ GetNArray(obj,a2);
1267
+
1268
+ SetFuncs[a2->type][NA_LINT](a2->total, a2->ptr, na_sizeof[a2->type], &one, 0);
1269
+
1270
+ na_exec_unary( a2, a1, MulUFuncs[a1->type] );
1271
+
1272
+ if (flag==0)
1273
+ obj = na_shrink_rank(obj,cl_dim,rankv);
1274
+
1275
+ xfree(rankv);
1276
+ return obj;
1277
+ }
1278
+
1279
+ /* method: prod( rank, ... ) */
1280
+ static VALUE
1281
+ na_prod(int argc, VALUE *argv, VALUE self)
1282
+ { return na_prod_body(argc,argv,self,0); }
1283
+
1284
+
1285
+ static VALUE
1286
+ na_mul_add_body(int argc, VALUE *argv, volatile VALUE self, volatile VALUE other,
1287
+ VALUE wrap_klass, int flag)
1288
+ {
1289
+ VALUE ans, op_klass;
1290
+ int rank, cl_dim;
1291
+ int *dst_shape, *max_shape;
1292
+ int rankc, *rankv;
1293
+ int type;
1294
+ struct NARRAY *a1, *a2;
1295
+
1296
+ GetNArray(self,a1);
1297
+ other = na_upcast_object(other,a1->type);
1298
+ GetNArray(other,a2);
1299
+ self = na_upcast_type(self,type=a2->type);
1300
+ GetNArray(self,a1);
1301
+
1302
+ rank = NA_MAX(a1->rank,a2->rank);
1303
+
1304
+ rankv = ALLOC_N(int,rank*3);
1305
+ rankc = na_arg_to_rank( argc, argv, rank, rankv, 0 );
1306
+
1307
+ max_shape = &rankv[rank];
1308
+ na_shape_max_2obj(rank,max_shape,a1,a2);
1309
+
1310
+ dst_shape = &max_shape[rank];
1311
+ na_accum_set_shape( dst_shape, rank, max_shape, rankc, rankv );
1312
+
1313
+ op_klass = na_bifunc_class(CLASS_OF(self),CLASS_OF(other));
1314
+ if (op_klass==Qnil) /* coerce_rev --- unsupported */
1315
+ op_klass = cNArray;
1316
+
1317
+ cl_dim = na_class_dim(op_klass);
1318
+ if (flag==0 && cl_dim>0 && na_shrink_class(cl_dim,rankv))
1319
+ op_klass = cNArray;
1320
+
1321
+ ans = na_make_object( type, rank, dst_shape,
1322
+ (wrap_klass==Qnil) ? op_klass : wrap_klass);
1323
+
1324
+ na_zero_data( NA_STRUCT(ans) );
1325
+ na_exec_binary( NA_STRUCT(ans), a1, a2, MulAddFuncs[type] );
1326
+
1327
+ if (flag==0)
1328
+ ans = na_shrink_rank(ans,cl_dim,rankv);
1329
+
1330
+ xfree(rankv);
1331
+ return ans;
1332
+ }
1333
+
1334
+
1335
+
1336
+ /* method: mul_add( other, rank, ... ) */
1337
+ static VALUE
1338
+ na_mul_add(int argc, VALUE *argv, VALUE self)
1339
+ {
1340
+ if (argc<2)
1341
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for >=2)", argc);
1342
+ return na_mul_add_body(argc-1,argv+1,self,argv[0],Qnil,0);
1343
+ }
1344
+
1345
+ /* method: mul_accum( other, rank, ... ) */
1346
+ static VALUE
1347
+ na_mul_accum(int argc, VALUE *argv, VALUE self)
1348
+ {
1349
+ if (argc<2)
1350
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for >=2)", argc);
1351
+ return na_mul_add_body(argc-1,argv+1,self,argv[0],Qnil,1);
1352
+ }
1353
+
1354
+ /* singleton method: NArray.mul_add( obj1, obj2, rank, ... ) */
1355
+ static VALUE
1356
+ na_s_mul_add(int argc, VALUE *argv, VALUE klass)
1357
+ {
1358
+ if (argc<3)
1359
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for >=3)", argc);
1360
+ return na_mul_add_body(argc-2,argv+2,argv[0],argv[1],klass,0);
1361
+ }
1362
+
1363
+
1364
+ /* cumsum!
1365
+ [1 2 3 4 5] -> [1 3 6 10 15]
1366
+ */
1367
+ static VALUE
1368
+ na_cumsum_bang(VALUE self)
1369
+ {
1370
+ struct NARRAY *a;
1371
+ int step;
1372
+
1373
+ GetNArray(self,a);
1374
+
1375
+ if ( a->rank != 1 )
1376
+ rb_raise( rb_eTypeError, "only for 1-dimensional array" );
1377
+ if ( a->total < 2 )
1378
+ return self; /* do nothing */
1379
+
1380
+ step = na_sizeof[a->type];
1381
+ AddUFuncs[a->type](a->total-1, a->ptr+step,step, a->ptr,step);
1382
+
1383
+ return self;
1384
+ }
1385
+
1386
+ /* cumsum */
1387
+ static VALUE
1388
+ na_cumsum(VALUE self)
1389
+ {
1390
+ return na_cumsum_bang(na_clone(self));
1391
+ }
1392
+
1393
+
1394
+ /* cumprod!
1395
+ [1 2 3 4 5] -> [1 3 6 10 15]
1396
+ */
1397
+ static VALUE
1398
+ na_cumprod_bang(VALUE self)
1399
+ {
1400
+ struct NARRAY *a;
1401
+ int step;
1402
+
1403
+ GetNArray(self,a);
1404
+
1405
+ if ( a->rank != 1 )
1406
+ rb_raise( rb_eTypeError, "only for 1-dimensional array" );
1407
+ if ( a->total < 2 )
1408
+ return self; /* do nothing */
1409
+
1410
+ step = na_sizeof[a->type];
1411
+ MulUFuncs[a->type](a->total-1, a->ptr+step,step, a->ptr,step);
1412
+
1413
+ return self;
1414
+ }
1415
+
1416
+ /* cumprod */
1417
+ static VALUE
1418
+ na_cumprod(VALUE self)
1419
+ {
1420
+ return na_cumprod_bang(na_clone(self));
1421
+ }
1422
+
1423
+
1424
+ /* Copy element of idx=0 from a2 to a1, as start of accumulation */
1425
+ /* a1->rank <= a2->rank is assumed */
1426
+ static void
1427
+ na_minmax_copy0(struct NARRAY *a1, struct NARRAY *a2)
1428
+ {
1429
+ int i, ndim=a2->rank; /* a2 has larger rank */
1430
+ struct slice *s1, *s2;
1431
+
1432
+ /* Allocate Structure */
1433
+ s1 = ALLOC_N(struct slice, (ndim+1)*2);
1434
+ s2 = &s1[ndim+1];
1435
+
1436
+ na_set_slice_1obj(a1->rank,s1,a1->shape);
1437
+ for (i=0; i<ndim; ++i) {
1438
+ s2[i].n = a1->shape[i]; /* no-repeat if a1->shape[i]==1 */
1439
+ s2[i].beg = 0; /* copy idx=0 */
1440
+ s2[i].step = 1;
1441
+ s2[i].idx = NULL;
1442
+ }
1443
+
1444
+ /* Initialize */
1445
+ na_init_slice(s1, ndim, a1->shape, na_sizeof[a1->type] );
1446
+ na_init_slice(s2, ndim, a2->shape, na_sizeof[a2->type] );
1447
+ /* Loop */
1448
+ na_do_loop_unary( ndim, a1->ptr, a2->ptr, s1, s2,
1449
+ SetFuncs[a1->type][a2->type] );
1450
+ xfree(s1);
1451
+ }
1452
+
1453
+
1454
+ static VALUE
1455
+ na_minmax_func(int argc, VALUE *argv, VALUE self, na_ufunc_t funcs)
1456
+ {
1457
+ VALUE obj, klass;
1458
+ int *shape, rankc, *rankv, cl_dim;
1459
+ struct NARRAY *a1, *a2;
1460
+
1461
+ GetNArray(self,a1);
1462
+
1463
+ rankv = ALLOC_N(int,a1->rank*2);
1464
+ rankc = na_arg_to_rank( argc, argv, a1->rank, rankv, 0 );
1465
+
1466
+ shape = &rankv[a1->rank];
1467
+ na_accum_set_shape( shape, a1->rank, a1->shape, rankc, rankv );
1468
+
1469
+ klass = CLASS_OF(self);
1470
+ cl_dim = na_class_dim(klass);
1471
+ if (na_shrink_class(cl_dim,rankv)) klass = cNArray;
1472
+
1473
+ obj = na_make_object(a1->type,a1->rank,shape,klass);
1474
+ GetNArray(obj,a2);
1475
+
1476
+ na_minmax_copy0( a2, a1 );
1477
+ na_exec_unary( a2, a1, funcs[a1->type] );
1478
+
1479
+ obj = na_shrink_rank(obj, cl_dim, rankv);
1480
+
1481
+ xfree(rankv);
1482
+ return obj;
1483
+ }
1484
+
1485
+
1486
+ /* method: min( rank, ... ) */
1487
+ static VALUE
1488
+ na_min(int argc, VALUE *argv, VALUE self)
1489
+ { return na_minmax_func(argc,argv,self,MinFuncs); }
1490
+
1491
+ /* method: max( rank, ... ) */
1492
+ static VALUE
1493
+ na_max(int argc, VALUE *argv, VALUE self)
1494
+ { return na_minmax_func(argc,argv,self,MaxFuncs); }
1495
+
1496
+
1497
+
1498
+ static int
1499
+ na_sort_number(int argc, VALUE *argv, struct NARRAY *a1)
1500
+ {
1501
+ int i, nsort, rank;
1502
+
1503
+ if (argc==0) {
1504
+ rank = a1->rank-1;
1505
+ } else {
1506
+ rank = NUM2INT(argv[0]);
1507
+ if (rank >= a1->rank || rank < -a1->rank)
1508
+ rb_raise(rb_eArgError,"illeagal rank:%i out of %i",rank,a1->rank);
1509
+ if (rank < 0) rank += a1->rank;
1510
+ }
1511
+
1512
+ nsort = 1;
1513
+ for (i=0; i<=rank; ++i)
1514
+ nsort *= a1->shape[i];
1515
+ return nsort;
1516
+ }
1517
+
1518
+
1519
+ /* method: sort([rank]) */
1520
+ static VALUE
1521
+ na_sort(int argc, VALUE *argv, VALUE self)
1522
+ {
1523
+ struct NARRAY *a1, *a2;
1524
+ VALUE obj;
1525
+ int (*func)(const void*, const void*);
1526
+ int i, size, step, nloop, nsort;
1527
+ char *ptr;
1528
+
1529
+ GetNArray(self,a1);
1530
+
1531
+ nsort = na_sort_number(argc,argv,a1);
1532
+ nloop = a1->total/nsort;
1533
+
1534
+ obj = na_make_object(a1->type,a1->rank,a1->shape,CLASS_OF(self));
1535
+ GetNArray(obj,a2);
1536
+ memcpy(a2->ptr, a1->ptr, a1->total*na_sizeof[a1->type]);
1537
+ func = SortFuncs[a2->type];
1538
+ size = na_sizeof[a2->type];
1539
+ ptr = a2->ptr;
1540
+ step = size * nsort;
1541
+
1542
+ for (i=0; i<nloop; ++i) {
1543
+ qsort( ptr, nsort, size, func );
1544
+ ptr += step;
1545
+ }
1546
+ return obj;
1547
+ }
1548
+
1549
+
1550
+ /* method: sort!([rank]) */
1551
+ static VALUE
1552
+ na_sort_bang(int argc, VALUE *argv, VALUE self)
1553
+ {
1554
+ struct NARRAY *a1;
1555
+ int (*func)(const void*, const void*);
1556
+ int i, size, step, nloop, nsort;
1557
+ char *ptr;
1558
+
1559
+ GetNArray(self,a1);
1560
+
1561
+ nsort = na_sort_number(argc,argv,a1);
1562
+ nloop = a1->total/nsort;
1563
+
1564
+ func = SortFuncs[a1->type];
1565
+ size = na_sizeof[a1->type];
1566
+ ptr = a1->ptr;
1567
+ step = size * nsort;
1568
+
1569
+ for (i=0; i<nloop; ++i) {
1570
+ qsort( ptr, nsort, size, func );
1571
+ ptr += step;
1572
+ }
1573
+ return self;
1574
+ }
1575
+
1576
+
1577
+ /* method: sort_index([rank]) */
1578
+ static VALUE
1579
+ na_sort_index(int argc, VALUE *argv, VALUE self)
1580
+ {
1581
+ struct NARRAY *a1, *a2;
1582
+ VALUE obj;
1583
+ int (*func)(const void*, const void*);
1584
+ int i, size, nloop, nsort;
1585
+ char **ptr_ptr, **ptr_p;
1586
+ char *ptr_ary, *ptr_a;
1587
+ int32_t *ptr_i;
1588
+
1589
+ GetNArray(self,a1);
1590
+
1591
+ nsort = na_sort_number(argc,argv,a1);
1592
+ nloop = a1->total/nsort;
1593
+
1594
+ size = na_sizeof[a1->type];
1595
+ ptr_p = ptr_ptr = ALLOC_N(char*, a1->total);
1596
+ ptr_a = ptr_ary = a1->ptr;
1597
+
1598
+ for (i=a1->total; i>0; --i) {
1599
+ *(ptr_p++) = ptr_a;
1600
+ ptr_a += size;
1601
+ }
1602
+
1603
+ func = SortIdxFuncs[a1->type];
1604
+ ptr_p = ptr_ptr;
1605
+
1606
+ for (i=0; i<nloop; ++i) {
1607
+ qsort( ptr_p, nsort, sizeof(char*), func );
1608
+ ptr_p += nsort;
1609
+ }
1610
+
1611
+ obj = na_make_object(NA_LINT,a1->rank,a1->shape,CLASS_OF(self));
1612
+ GetNArray(obj,a2);
1613
+ ptr_p = ptr_ptr;
1614
+ ptr_i = (int32_t*)(a2->ptr);
1615
+ for (i=a2->total; i>0; --i) {
1616
+ *(ptr_i++) = (int32_t)(*(ptr_p++)-ptr_ary)/size;
1617
+ }
1618
+ xfree(ptr_ptr);
1619
+ return obj;
1620
+ }
1621
+
1622
+
1623
+
1624
+ void Init_na_funcs(void)
1625
+ {
1626
+ rb_define_method(cNArray, "+", na_add, 1);
1627
+ rb_define_method(cNArray, "-", na_sbt, 1);
1628
+ rb_define_method(cNArray, "*", na_mul, 1);
1629
+ rb_define_method(cNArray, "/", na_div, 1);
1630
+ rb_define_method(cNArray, "%", na_mod, 1);
1631
+ rb_define_alias (cNArray, "mod", "%");
1632
+ rb_define_method(cNArray, "&", na_bit_and, 1);
1633
+ rb_define_method(cNArray, "|", na_bit_or, 1);
1634
+ rb_define_method(cNArray, "^", na_bit_xor, 1);
1635
+ rb_define_method(cNArray, "**", na_power, 1);
1636
+
1637
+ rb_define_method(cNArray, "add!", na_add_bang, 1);
1638
+ rb_define_method(cNArray, "sbt!", na_sbt_bang, 1);
1639
+ rb_define_method(cNArray, "mul!", na_mul_bang, 1);
1640
+ rb_define_method(cNArray, "div!", na_div_bang, 1);
1641
+ rb_define_method(cNArray, "mod!", na_mod_bang, 1);
1642
+ rb_define_method(cNArray, "imag=",na_imag_set, 1);
1643
+
1644
+ rb_define_method(cNArray, "swap_byte", na_swap_byte, 0);
1645
+ rb_define_method(cNArray, "hton", na_hton, 0);
1646
+ rb_define_alias (cNArray, "ntoh", "hton");
1647
+ rb_define_method(cNArray, "htov", na_htov, 0);
1648
+ rb_define_alias (cNArray, "vtoh", "htov");
1649
+ rb_define_method(cNArray, "-@", na_neg, 0);
1650
+ rb_define_method(cNArray, "recip",na_recip, 0);
1651
+ rb_define_method(cNArray, "abs", na_abs, 0);
1652
+ rb_define_method(cNArray, "real", na_real, 0);
1653
+ rb_define_method(cNArray, "imag", na_imag, 0);
1654
+ rb_define_alias (cNArray, "image", "imag");
1655
+ rb_define_method(cNArray, "angle", na_angle, 0);
1656
+ rb_define_alias (cNArray, "arg", "angle");
1657
+ rb_define_method(cNArray, "conj", na_conj, 0);
1658
+ rb_define_alias (cNArray, "conjugate", "conj");
1659
+ rb_define_method(cNArray, "conj!", na_conj_bang, 0);
1660
+ rb_define_alias (cNArray, "conjugate!", "conj!");
1661
+ rb_define_method(cNArray, "im", na_imag_mul, 0);
1662
+ rb_define_method(cNArray, "floor",na_floor, 0);
1663
+ rb_define_method(cNArray, "ceil", na_ceil, 0);
1664
+ rb_define_method(cNArray, "round",na_round, 0);
1665
+ rb_define_method(cNArray, "~", na_bit_rev, 0);
1666
+ rb_define_method(cNArray, "not", na_not, 0);
1667
+
1668
+ rb_define_method(cNArray, "<=>", na_compare, 1);
1669
+ rb_define_method(cNArray, "eq", na_equal, 1);
1670
+ rb_define_method(cNArray, "ne", na_not_equal, 1);
1671
+ rb_define_method(cNArray, "gt", na_greater_than, 1);
1672
+ rb_define_alias (cNArray, ">", "gt");
1673
+ rb_define_method(cNArray, "ge", na_greater_equal, 1);
1674
+ rb_define_alias (cNArray, ">=", "ge");
1675
+ rb_define_method(cNArray, "lt", na_less_than, 1);
1676
+ rb_define_alias (cNArray, "<", "lt");
1677
+ rb_define_method(cNArray, "le", na_less_equal, 1);
1678
+ rb_define_alias (cNArray, "<=", "le");
1679
+ rb_define_method(cNArray, "and", na_cond_and, 1);
1680
+ rb_define_method(cNArray, "or", na_cond_or, 1);
1681
+ rb_define_method(cNArray, "xor", na_cond_xor, 1);
1682
+
1683
+ rb_define_method(cNArray, "mul_add", na_mul_add, -1);
1684
+ rb_define_method(cNArray, "mul_accum", na_mul_accum, -1);
1685
+
1686
+ rb_define_method(cNArray, "sum", na_sum, -1);
1687
+ rb_define_method(cNArray, "accum", na_accum, -1);
1688
+ rb_define_method(cNArray, "prod", na_prod, -1);
1689
+ rb_define_method(cNArray, "min", na_min, -1);
1690
+ rb_define_method(cNArray, "max", na_max, -1);
1691
+ rb_define_method(cNArray, "cumsum!", na_cumsum_bang, 0);
1692
+ rb_define_method(cNArray, "cumsum", na_cumsum, 0);
1693
+ rb_define_method(cNArray, "cumprod!", na_cumprod_bang, 0);
1694
+ rb_define_method(cNArray, "cumprod", na_cumprod, 0);
1695
+ rb_define_method(cNArray, "sort", na_sort, -1);
1696
+ rb_define_method(cNArray, "sort!", na_sort_bang, -1);
1697
+ rb_define_method(cNArray, "sort_index", na_sort_index, -1);
1698
+ rb_define_method(cNArray, "transpose", na_transpose, -1);
1699
+
1700
+ rb_define_singleton_method(cNArray,"mul",na_s_mul,2);
1701
+ rb_define_singleton_method(cNArray,"div",na_s_div,2);
1702
+ rb_define_singleton_method(cNArray,"mul_add",na_s_mul_add,-1);
1703
+
1704
+ rb_define_module_function(rb_mNMath,"atan2",na_math_atan2,2);
1705
+ }