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_index.c ADDED
@@ -0,0 +1,988 @@
1
+ /*
2
+ na_index.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
+ #define EXCL(r) (RTEST(rb_funcall((r),na_id_exclude_end,0)))
16
+
17
+ static int
18
+ na_index_range(VALUE obj, int size, struct slice *sl)
19
+ {
20
+ int beg,end,len,step;
21
+ VALUE vbeg, vend;
22
+
23
+ sl->idx = NULL;
24
+
25
+ /* Beginning */
26
+ vbeg = rb_funcall(obj, na_id_beg, 0);
27
+ if (vbeg==Qnil) /* First is nil */
28
+ beg = 0;
29
+ else
30
+ beg = NUM2INT(vbeg);
31
+ if (beg<0) beg += size;
32
+
33
+ /* End */
34
+ vend = rb_funcall(obj, na_id_end, 0);
35
+ if (vend==Qnil) { /* Last is nil */
36
+ sl->beg = beg;
37
+ sl->step = 1;
38
+ return sl->n = 0;
39
+ }
40
+ else
41
+ end = NUM2INT(vend);
42
+ if (end<0) end += size;
43
+
44
+ /* length */
45
+ len = end-beg;
46
+
47
+ /* direction */
48
+ if (len>0) {
49
+ step = 1;
50
+ if (EXCL(obj)) end--; else len++;
51
+ }
52
+ else if (len<0) {
53
+ len = -len;
54
+ step = -1;
55
+ if (EXCL(obj)) end++; else len++;
56
+ }
57
+ else /*if(len==0)*/ {
58
+ if (EXCL(obj))
59
+ rb_raise(rb_eIndexError, "empty range");
60
+ else {
61
+ len++;
62
+ step = 1; /* or 0 ? depend on whether removing rank */
63
+ }
64
+ }
65
+
66
+ if ( beg<0 || beg>=size || end<0 || end>=size )
67
+ rb_raise(rb_eIndexError, "index out of range");
68
+
69
+ sl->n = len;
70
+ sl->beg = beg;
71
+ sl->step = step;
72
+ return len;
73
+ }
74
+
75
+
76
+ static int
77
+ na_index_scalar(int idx, int size, struct slice *sl)
78
+ {
79
+ if (idx<0) idx+=size;
80
+ if (idx<0 || idx>=size)
81
+ rb_raise(rb_eIndexError, "index out of range");
82
+ sl->n = 1;
83
+ sl->beg = idx;
84
+ sl->step = 0;
85
+ sl->idx = NULL;
86
+ return 1;
87
+ }
88
+
89
+
90
+ static int
91
+ na_ary_to_index(struct NARRAY *a1, int size, struct slice *s)
92
+ {
93
+ int i;
94
+ na_index_t idx, *p;
95
+
96
+ /* Empty Array */
97
+ if (a1->total==0) {
98
+ s->n = 0;
99
+ s->beg = 0;
100
+ s->step = 1;
101
+ s->idx = NULL;
102
+ }
103
+ else
104
+ /* single element */
105
+ if (a1->total==1) {
106
+ SetFuncs[NA_LINT][a1->type](1, &idx, 0, a1->ptr, 0);
107
+ if ( idx<0 ) idx += size;
108
+ if ( idx<0 || idx>=size )
109
+ rb_raise(rb_eIndexError, "index %i out of range %i", idx, size);
110
+ s->n = 1;
111
+ s->beg = idx;
112
+ s->step = 1;
113
+ s->idx = NULL;
114
+ }
115
+ else {
116
+ /* Copy index array */
117
+ s->n = a1->total;
118
+ s->step = 1;
119
+ s->idx = p = ALLOC_N(na_index_t, a1->total);
120
+ SetFuncs[NA_LINT][a1->type]( s->n,
121
+ s->idx, na_sizeof[NA_LINT],
122
+ a1->ptr, na_sizeof[a1->type] );
123
+ for ( i=a1->total; i>0; i-- ) {
124
+ if ( *p<0 ) *p += size;
125
+ if ( *p<0 || *p>=size )
126
+ rb_raise(rb_eIndexError, "index %i out of range %i", *p, size);
127
+ p++;
128
+ }
129
+ s->beg = s->idx[0];
130
+ }
131
+
132
+ return s->n;
133
+ }
134
+
135
+
136
+ static struct NARRAY *
137
+ na_flatten_temporarily(struct NARRAY *dst, struct NARRAY *src)
138
+ {
139
+ /* Not normal construction !! Do not wrap as object ! */
140
+ dst->shape = &(dst->total);
141
+ dst->rank = 1;
142
+ dst->total = src->total;
143
+ dst->type = src->type;
144
+ dst->ptr = src->ptr;
145
+ dst->ref = src->ref;
146
+ return dst;
147
+ }
148
+ #define na_flatten_temp(ary) \
149
+ {ary = na_flatten_temporarily(ALLOCA_N(struct NARRAY,1), ary);}
150
+
151
+
152
+ /* free index memory */
153
+ static void na_free_slice_index(struct slice *s, int n)
154
+ {
155
+ while (n-->0)
156
+ if (s[n].idx != NULL) xfree(s[n].idx);
157
+ }
158
+
159
+
160
+ static int na_index_test(volatile VALUE idx, int shape, struct slice *sl)
161
+ {
162
+ int size;
163
+ struct NARRAY *na;
164
+
165
+ switch(TYPE(idx)) {
166
+
167
+ case T_FIXNUM:
168
+ /* scalar slice */
169
+ na_index_scalar(FIX2LONG(idx),shape,sl);
170
+ return 1;
171
+
172
+ case T_FLOAT:
173
+ /* scalar slice */
174
+ na_index_scalar(NUM2LONG(idx),shape,sl);
175
+ return 1;
176
+
177
+ case T_NIL:
178
+ case T_TRUE:
179
+ /* entire slice */
180
+ sl->n = shape;
181
+ sl->beg = 0;
182
+ sl->step = 1;
183
+ sl->idx = NULL;
184
+ return shape;
185
+
186
+ case T_ARRAY:
187
+ /* Array Index */
188
+ idx = na_cast_object(idx,NA_LINT);
189
+ GetNArray(idx,na);
190
+ size = na_ary_to_index(na,shape,sl);
191
+ //na_touch_object(idx);
192
+ return size;
193
+
194
+ default:
195
+ /* Range object */
196
+ if (rb_obj_is_kind_of(idx, rb_cRange)) {
197
+ size = na_index_range(idx,shape,sl);
198
+ }
199
+ else
200
+ /* NArray index */
201
+ if (NA_IsNArray(idx)) {
202
+ GetNArray(idx,na);
203
+ size = na_ary_to_index(na,shape,sl);
204
+ }
205
+ else
206
+ /* NO ALLOWED */
207
+ if (TYPE(idx)==T_BIGNUM) {
208
+ rb_raise(rb_eIndexError, "BigNum is not allowed");
209
+ }
210
+ else
211
+ rb_raise(rb_eIndexError, "not allowed type");
212
+ }
213
+ return size;
214
+ }
215
+
216
+
217
+ static int
218
+ na_index_analysis(int nidx, VALUE *idx, struct NARRAY *ary, struct slice *sl)
219
+ {
220
+ int i, j, k, total=1, size;
221
+ int multi_ellip=0;
222
+
223
+ for (i=j=0; i<nidx; i++) {
224
+ if (TYPE(idx[i])==T_FALSE) {
225
+ if (multi_ellip!=0)
226
+ rb_raise(rb_eIndexError, "multiple ellipsis-dimension is not allowd");
227
+ for (k=ary->rank-nidx+1; k>0; k--,j++) {
228
+ size = na_index_test( Qtrue, ary->shape[j], &sl[j] );
229
+ if (size != 1)
230
+ total *= size;
231
+ }
232
+ multi_ellip = 1;
233
+ } else {
234
+ size = na_index_test( idx[i], ary->shape[j], &sl[j] );
235
+ if (size != 1)
236
+ total *= size;
237
+ j++;
238
+ }
239
+ }
240
+ if (j != ary->rank)
241
+ rb_raise(rb_eIndexError, "# of index=%i != ary.dim=%i", j, ary->rank);
242
+
243
+ return total;
244
+ }
245
+
246
+
247
+ /* -------------------- Class Dimension -------------------- */
248
+ int
249
+ na_shrink_class(int class_dim, int *shrink)
250
+ {
251
+ int i;
252
+
253
+ for (i=0; i<class_dim; i++) {
254
+ if (shrink[i]==0) /* non-trim dimention */
255
+ return 0;
256
+ }
257
+ return 1; /* all trim */
258
+ }
259
+
260
+
261
+ /* remove single-element rank */
262
+ VALUE
263
+ na_shrink_rank(VALUE obj, int class_dim, int *shrink)
264
+ {
265
+ int i, j;
266
+ struct NARRAY *ary;
267
+
268
+ GetNArray(obj,ary);
269
+
270
+ if (ary->rank < class_dim)
271
+ return obj;
272
+
273
+ for (j=i=0; i<class_dim; i++) {
274
+ if (ary->shape[i]!=1 || shrink[i]==0) /* not trim */
275
+ j++;
276
+ }
277
+
278
+ if (j>0) /* if non-trim dimensions exist, */
279
+ j = class_dim; /* then do not trim class_dimension. */
280
+ /* if (j==0) then all trim. */
281
+
282
+ for (i=class_dim; i<ary->rank; i++) {
283
+ if (ary->shape[i]!=1 || shrink[i]==0) { /* not trim */
284
+ if (i>j) ary->shape[j] = ary->shape[i];
285
+ j++;
286
+ }
287
+ }
288
+ ary->rank = j;
289
+
290
+ if (j==0 && ary->total==1) {
291
+ SetFuncs[NA_ROBJ][ary->type](1, &obj, 0, ary->ptr, 0);
292
+ }
293
+ return obj;
294
+ }
295
+
296
+
297
+ /* ------------------- bracket methods ------------------ */
298
+ /*
299
+ [] -- Reference method
300
+ */
301
+
302
+ static VALUE
303
+ na_aref_slice(struct NARRAY *a2, struct slice *s2, VALUE klass, int flag)
304
+ {
305
+ int i, ndim, class_dim, *shape, *shrink;
306
+ VALUE extr;
307
+ struct NARRAY *a1;
308
+ struct slice *s1;
309
+
310
+ ndim = a2->rank;
311
+ shape = ALLOCA_N(int,ndim);
312
+ shrink = ALLOCA_N(int,ndim);
313
+
314
+ for (i=0; i<ndim; i++) {
315
+ shape[i] = s2[i].n;
316
+ if (shape[i]==1 && s2[i].step==0) /* shrink? */
317
+ shrink[i] = 1;
318
+ else
319
+ shrink[i] = 0;
320
+ }
321
+
322
+ class_dim = na_class_dim(klass);
323
+
324
+ if (ndim < class_dim)
325
+ rb_raise(rb_eRuntimeError,
326
+ "dimension(%i) is smaller than CLASS_DIMENSION(%i)",
327
+ ndim, class_dim);
328
+
329
+ if ((!flag) && class_dim>0 && na_shrink_class(class_dim,shrink))
330
+ klass = cNArray;
331
+
332
+ extr = na_make_object( a2->type, ndim, shape, klass );
333
+ GetNArray(extr,a1);
334
+
335
+ s1 = ALLOC_N(struct slice, ndim+1);
336
+ na_set_slice_1obj(ndim,s1,a1->shape);
337
+
338
+ na_init_slice( s1, ndim, shape, na_sizeof[a2->type] );
339
+ na_init_slice( s2, ndim, a2->shape, na_sizeof[a2->type] );
340
+ na_loop_index_ref( a1, a2, s1, s2, SetFuncs[a2->type][a2->type] );
341
+
342
+ xfree(s1);
343
+ if (!flag)
344
+ extr = na_shrink_rank(extr,class_dim,shrink);
345
+
346
+ return extr;
347
+ }
348
+
349
+
350
+
351
+ static VALUE
352
+ na_aref_single_dim_array(VALUE self, volatile VALUE vidx)
353
+ {
354
+ int total;
355
+ struct NARRAY *a1, *a2, *aidx;
356
+ struct slice *s1, *s2;
357
+ VALUE v;
358
+
359
+ GetNArray( self, a1 );
360
+ vidx = na_cast_object( vidx, NA_LINT );
361
+ GetNArray(vidx,aidx);
362
+
363
+ /* make Slice from index */
364
+ s1 = ALLOCA_N(struct slice, 2);
365
+ total = na_ary_to_index( aidx, a1->total, s1 );
366
+
367
+ if (total==0) {
368
+ return na_make_empty(a1->type,cNArray);
369
+ }
370
+ else {
371
+ /* create New NArray & 1-dimentionize */
372
+ v = na_make_object( a1->type, aidx->rank, aidx->shape, CLASS_OF(vidx) );
373
+ GetNArray(v,a2);
374
+ if (a2->rank>1) na_flatten_temp(a2);
375
+ if (a1->rank>1) na_flatten_temp(a1);
376
+
377
+ /* Slice for Destination array */
378
+ s2 = ALLOCA_N(struct slice, 2);
379
+ na_set_slice_1obj(1,s2,a2->shape);
380
+
381
+ /* Iteration */
382
+ na_init_slice( s2, 1, a2->shape, na_sizeof[a1->type] );
383
+ na_init_slice( s1, 1, a1->shape, na_sizeof[a1->type] );
384
+ na_loop_index_ref( a2, a1, s2, s1, SetFuncs[a1->type][a1->type] );
385
+ }
386
+
387
+ na_free_slice_index(s1,1);
388
+ //na_touch_object(vidx);
389
+ return v;
390
+ }
391
+
392
+
393
+ static VALUE
394
+ na_aref_single_dim(VALUE self, VALUE idx, int flag)
395
+ {
396
+ int size;
397
+ VALUE v;
398
+ struct NARRAY *ary, *arynew;
399
+ struct slice *sl;
400
+
401
+ GetNArray(self,ary);
402
+
403
+ sl = ALLOCA_N(struct slice, 2);
404
+ size = na_index_test(idx, ary->total, sl);
405
+
406
+ if ( size == 1 ) {
407
+ if (flag || sl->step!=0) {
408
+ /* single-element NArray */
409
+ v = na_make_object(ary->type,1,&size,cNArray);
410
+ GetNArray(v,arynew);
411
+ SetFuncs[ary->type][ary->type](1, arynew->ptr,0, NA_PTR(ary,sl->beg),0);
412
+ } else {
413
+ SetFuncs[NA_ROBJ][ary->type](1, &v,0, NA_PTR(ary,sl->beg),0);
414
+ }
415
+ }
416
+ else
417
+ if ( size > 1 ) {
418
+ if ( ary->rank > 1 ) /* 1-dimensional serial index */
419
+ na_flatten_temp(ary);
420
+ v = na_aref_slice(ary, sl, CLASS_OF(self), flag);
421
+ }
422
+ else /* size < 1 */ {
423
+ v = na_make_empty(ary->type,cNArray);
424
+ }
425
+ /* na_free_slice_index(sl,1); free index memory */
426
+ return v;
427
+ }
428
+
429
+
430
+ static VALUE
431
+ na_aref_multi_dim_single_elm(VALUE self, struct slice *sl, int flag)
432
+ {
433
+ int i, rank, pos, *shape;
434
+ struct NARRAY *ary, *arynew;
435
+ VALUE v;
436
+
437
+ ary = (struct NARRAY *)DATA_PTR(self); /* type is already checked */
438
+
439
+ /* check rank-shrink; whether return NArray or Element */
440
+ if (flag==0) {
441
+ rank = 0; /* [] */
442
+ for ( i=ary->rank; (i--)>0; ) {
443
+ if (sl[i].step!=0) rank++;
444
+ }
445
+ }
446
+ else {
447
+ rank = ary->rank; /* slice() */
448
+ }
449
+ /* get position */
450
+ pos = 0;
451
+ for ( i=ary->rank; i-->0; ) {
452
+ pos = pos * ary->shape[i] + sl[i].beg;
453
+ }
454
+ if (rank==0) {
455
+ SetFuncs[NA_ROBJ][ary->type](1, &v, 0, NA_PTR(ary,pos), 0);
456
+ } else {
457
+ VALUE klass;
458
+ int class_dim;
459
+ klass = CLASS_OF(self);
460
+ class_dim = na_class_dim(klass);
461
+ if (rank < class_dim) rank = class_dim;
462
+ shape = ALLOCA_N(int, rank);
463
+ for (i=0;i<rank;i++) shape[i]=1;
464
+ v = na_make_object(ary->type,rank,shape,klass);
465
+ GetNArray(v,arynew);
466
+ SetFuncs[ary->type][ary->type](1, arynew->ptr, 0, NA_PTR(ary,pos), 0);
467
+ }
468
+ return v;
469
+ }
470
+
471
+
472
+ static VALUE
473
+ na_aref_multi_dim(VALUE self, int nidx, VALUE *idx, int flag)
474
+ {
475
+ VALUE v;
476
+ int size;
477
+ struct NARRAY *ary;
478
+ struct slice *sl;
479
+
480
+ GetNArray(self,ary);
481
+
482
+ if (ary->rank==0)
483
+ rb_raise(rb_eIndexError, "Cannot extract from Empty NArray");
484
+
485
+ /* make Slice */
486
+ sl = ALLOC_N(struct slice, ary->rank+1);
487
+ size = na_index_analysis(nidx, idx, ary, sl);
488
+
489
+ if ( size == 1 ) { /* return Single Element */
490
+ v = na_aref_multi_dim_single_elm(self, sl, flag);
491
+ }
492
+ else
493
+ if ( size > 1 ) {
494
+ v = na_aref_slice(ary, sl, CLASS_OF(self), flag);
495
+ }
496
+ else /* size < 1 */ {
497
+ v = na_make_empty(ary->type,cNArray);
498
+ }
499
+ na_free_slice_index(sl,ary->rank); /* free index memory */
500
+ xfree(sl);
501
+ return v;
502
+ }
503
+
504
+
505
+ /* vvv mask vvv */
506
+ static int
507
+ na_count_true_body(VALUE self)
508
+ {
509
+ struct NARRAY *ary;
510
+ int n, count=0;
511
+ u_int8_t *ptr;
512
+
513
+ GetNArray(self,ary);
514
+
515
+ if ( ary->type == NA_BYTE ) {
516
+ ptr = (u_int8_t *)ary->ptr;
517
+ n = ary->total;
518
+ for (; n; n--) {
519
+ if (*ptr++) ++count;
520
+ }
521
+ } else
522
+ rb_raise(rb_eTypeError,"cannot count_true NArray except BYTE type");
523
+ return count;
524
+ }
525
+
526
+ VALUE
527
+ na_count_true(VALUE self)
528
+ {
529
+ return( INT2NUM(na_count_true_body(self)) );
530
+ }
531
+
532
+ static int
533
+ na_count_false_body(VALUE self)
534
+ {
535
+ struct NARRAY *ary;
536
+ int n, count=0;
537
+ u_int8_t *ptr;
538
+
539
+ GetNArray(self,ary);
540
+
541
+ if ( ary->type == NA_BYTE ) {
542
+ ptr = (u_int8_t *)ary->ptr;
543
+ n = ary->total;
544
+ for (; n; n--) {
545
+ if (!*ptr++) ++count;
546
+ }
547
+ } else
548
+ rb_raise(rb_eTypeError,"cannot count_false NArray except BYTE type");
549
+ return count;
550
+ }
551
+
552
+ VALUE
553
+ na_count_false(VALUE self)
554
+ {
555
+ return( INT2NUM(na_count_false_body(self)) );
556
+ }
557
+
558
+ VALUE
559
+ na_aref_mask(VALUE self, VALUE mask)
560
+ {
561
+ int total, i;
562
+ struct NARRAY *a1, *am, *a2;
563
+ VALUE v;
564
+
565
+ GetNArray( self, a1 );
566
+ GetNArray( mask, am );
567
+
568
+ if (a1->total != am->total)
569
+ rb_raise(rb_eTypeError,"self.size(=%i) != mask.size(=%i)",
570
+ a1->total, am->total);
571
+ if (a1->rank != am->rank)
572
+ rb_raise(rb_eTypeError,"self.rank(=%i) != mask.rank(=%i)",
573
+ a1->rank, am->rank);
574
+ for (i=0; i<a1->rank; i++)
575
+ if (a1->shape[i] != am->shape[i])
576
+ rb_raise(rb_eTypeError,"self.shape[%i](=%i) != mask.shape[%i](=%i)",
577
+ i, a1->shape[i], i, am->shape[i]);
578
+
579
+ total = na_count_true_body(mask);
580
+
581
+ v = na_make_object( a1->type, 1, &total, CLASS_OF(self) );
582
+ GetNArray(v,a2);
583
+
584
+ RefMaskFuncs[a1->type]
585
+ ( a1->total, a2->ptr, na_sizeof[a2->type], a1->ptr,
586
+ na_sizeof[a1->type], am->ptr, 1 );
587
+
588
+ return(v);
589
+ }
590
+
591
+ /* ^^^ mask ^^^ */
592
+
593
+
594
+ /* method: [](idx1,idx2,...,idxN) */
595
+ static VALUE
596
+ na_aref_body(int nidx, VALUE *idx, VALUE self, int flag)
597
+ {
598
+ if (nidx==0) {
599
+ return na_clone(self);
600
+ }
601
+ if (nidx==1) {
602
+ if ( NA_IsNArray(idx[0]) ) {
603
+ if( NA_TYPE(idx[0]) == NA_BYTE ) /* then supposed to be a mask */
604
+ return na_aref_mask(self, idx[0]);
605
+ }
606
+ if ( na_class_dim(CLASS_OF(self)) != 1 ) {
607
+ if ( NA_IsArray(idx[0]) ) /* Array Index ? */
608
+ return na_aref_single_dim_array( self, idx[0] );
609
+ else
610
+ return na_aref_single_dim( self, idx[0], flag );
611
+ }
612
+ }
613
+ /* if (nidx>1) */
614
+ return na_aref_multi_dim( self, nidx, idx, flag );
615
+ }
616
+
617
+ /* method: [](idx1,idx2,...,idxN) */
618
+ VALUE na_aref(int argc, VALUE *argv, VALUE self)
619
+ { return na_aref_body(argc, argv, self, 0); }
620
+
621
+ /* method: slice(idx1,idx2,...,idxN) */
622
+ VALUE na_slice(int argc, VALUE *argv, VALUE self)
623
+ { return na_aref_body(argc, argv, self, 1); }
624
+
625
+
626
+
627
+ /*
628
+ []= -- Set elements to specified indices
629
+ */
630
+
631
+ /* make slice for array-set: a[0..-1,1..2] = 1 */
632
+ static void
633
+ na_make_slice_aset_fill(int rank, struct NARRAY *src_ary,
634
+ struct slice *src_slc, int *src_shape,
635
+ struct slice *dst_slc)
636
+ {
637
+ int i;
638
+
639
+ for (i=0; i<rank; i++) {
640
+ src_shape[i] = 1; /* all 1 */
641
+ if ( (src_slc[i].n = dst_slc[i].n) < 1 )
642
+ rb_raise(rb_eIndexError, "dst_slice[%i].n=%i ???", i, dst_slc[i].n);
643
+ src_slc[i].beg = 0;
644
+ src_slc[i].idx = NULL;
645
+ src_slc[i].step = 0;
646
+ }
647
+ }
648
+
649
+
650
+ /* make slice for array-set */
651
+ static void
652
+ na_make_slice_aset(struct NARRAY *dst, struct NARRAY *src,
653
+ struct slice *s1, struct slice *s2, int *src_shape)
654
+ {
655
+ int i, j, idx_end;
656
+
657
+ /* count range index */
658
+ for (j=i=0; i<dst->rank; i++) {
659
+
660
+ if ( s1[i].step !=0 ) { /* Range index */
661
+
662
+ /* rank check */
663
+ if ( j >= src->rank )
664
+ rb_raise(rb_eIndexError, "dst.range-dim=%i > src.dim=%i",
665
+ j+1, src->rank);
666
+
667
+ if ( s1[i].n == 0 ) {
668
+ /* Size is NOT specified:
669
+ a[0..nil] = other_array
670
+ a[0] = other_array
671
+ */
672
+ s1[i].n = src->shape[j];
673
+
674
+ idx_end = s1[i].beg + (s1[i].n-1) * s1[i].step;
675
+ if ( idx_end < 0 || idx_end >= dst->shape[i] )
676
+ rb_raise(rb_eIndexError, "end-index=%i is out of dst.shape[%i]=%i",
677
+ idx_end, i, dst->shape[i]);
678
+
679
+ } else
680
+ /* Size is specified:
681
+ a[0..10] = other
682
+ */
683
+ if ( src->shape[j] >1 && s1[i].n != src->shape[j] ) {
684
+ rb_raise(rb_eIndexError, "dst.shape[%i]=%i != src.shape[%i]=%i",
685
+ i, s1[i].n, j, src->shape[j]);
686
+ }
687
+ /* copy source shape */
688
+ src_shape[i] = src->shape[j++];
689
+
690
+ }
691
+ else /* if ( s1[i].n==1 )
692
+ Scalar index:
693
+ a[0, 0..-1] = other --- first rank is skipped.
694
+ */
695
+ src_shape[i] = 1; /* insert dummy rank */
696
+
697
+ s2[i].beg = 0;
698
+ s2[i].idx = NULL;
699
+ s2[i].n = s1[i].n; /* repeate number is same as a1 index */
700
+
701
+ if ( s1[i].n >1 && src_shape[i]==1 ) /* Extensible index */
702
+ s2[i].step = 0;
703
+ else
704
+ s2[i].step = 1;
705
+ }
706
+
707
+ /* rank check */
708
+ if ( j != src->rank )
709
+ rb_raise(rb_eIndexError, "dst.range-dim=%i < src.dim=%i", j, src->rank);
710
+ }
711
+
712
+
713
+
714
+ /* Iterate with bifinc, src has extensible index */
715
+ void
716
+ na_aset_slice(struct NARRAY *dst, struct NARRAY *src, struct slice *dst_slc)
717
+ {
718
+ int rank = dst->rank;
719
+ int *src_shape;
720
+ struct slice *src_slc;
721
+
722
+ /* rank check */
723
+ if (rank < src->rank)
724
+ rb_raise(rb_eIndexError, "%i dst.ranks < %i src.ranks", rank, src->rank);
725
+
726
+ /* extend rank */
727
+ src_shape = ALLOCA_N(int, rank);
728
+ src_slc = ALLOC_N(struct slice, rank+1);
729
+
730
+ if (src->total==1)
731
+ na_make_slice_aset_fill( rank, src, src_slc, src_shape, dst_slc );
732
+ else
733
+ na_make_slice_aset( dst, src, dst_slc, src_slc, src_shape );
734
+
735
+ /* Iteration */
736
+ na_init_slice( dst_slc, rank, dst->shape, na_sizeof[dst->type] );
737
+ na_init_slice( src_slc, rank, src_shape, na_sizeof[src->type] );
738
+ na_loop_general( dst,src, dst_slc,src_slc, SetFuncs[dst->type][src->type] );
739
+ xfree(src_slc);
740
+ }
741
+
742
+
743
+ static void
744
+ na_aset_array_index( VALUE self, volatile VALUE idx, volatile VALUE val )
745
+ {
746
+ int i, total;
747
+ struct NARRAY *aidx, *src, *dst;
748
+ struct slice *sl;
749
+
750
+ GetNArray(self,dst);
751
+ idx = na_cast_object(idx,NA_LINT);
752
+ GetNArray(idx,aidx);
753
+ val = na_cast_unless_narray(val,dst->type);
754
+ GetNArray(val,src);
755
+
756
+ /* empty index -- do nothing */
757
+ if (aidx->total==0 && (src->total==0 || src->total==1))
758
+ return;
759
+
760
+ /* check rank */
761
+ if (aidx->rank != src->rank)
762
+ rb_raise( rb_eIndexError, "idx.rank=%i != src.rank=%i",
763
+ aidx->rank, src->rank );
764
+ /* check shape */
765
+ for (i=0;i<src->rank;i++)
766
+ if (aidx->shape[i] != src->shape[i] && src->shape[i] != 1)
767
+ rb_raise( rb_eIndexError, "idx.shape[%i]=%i != src.shape[%i]=%i",
768
+ i, aidx->shape[i], i, src->shape[i] );
769
+
770
+ /* make Slice from index */
771
+ sl = ALLOCA_N(struct slice,2);
772
+ total = na_ary_to_index( NA_STRUCT(idx), dst->total, sl );
773
+
774
+ /* 1-dimensionize */
775
+ if (dst->rank > 1) {
776
+ na_flatten_temp(dst);
777
+ }
778
+ if (src->rank > 1) {
779
+ na_flatten_temp(src);
780
+ }
781
+
782
+ na_aset_slice( dst, src, sl );
783
+ na_free_slice_index( sl, 1 ); /* free index memory */
784
+ //na_touch_object(idx,val);
785
+ }
786
+
787
+
788
+ static void
789
+ na_aset_single_dim(VALUE self, VALUE idx, volatile VALUE val)
790
+ {
791
+ int size;
792
+ struct NARRAY *src, *dst;
793
+ struct slice *sl;
794
+
795
+ GetNArray(self,dst);
796
+ if (dst->total==0)
797
+ rb_raise(rb_eRuntimeError, "cannot set value to empty array");
798
+
799
+ sl = ALLOCA_N(struct slice, 2);
800
+ size = na_index_test(idx, dst->total, sl);
801
+
802
+ if ( size == 1 ) {
803
+ if (NA_IsNArray(val)) {
804
+ GetNArray(val,src);
805
+ if ( src->total == 1 ) {
806
+ SetFuncs[dst->type][src->type](1, NA_PTR(dst,sl->beg),0, src->ptr,0);
807
+ return;
808
+ }
809
+ }
810
+ else if (TYPE(val)!=T_ARRAY) {
811
+ /* Storing single element:
812
+ a[1] = 1
813
+ */
814
+ SetFuncs[dst->type][NA_ROBJ](1, NA_PTR(dst,sl->beg),0, &val,0);
815
+ return;
816
+ }
817
+ /* Beginning index:
818
+ a[1] = [1,2,3]
819
+ */
820
+ sl[0].n = 0;
821
+ sl[0].step = 1;
822
+ }
823
+ else if ( size == 0 ) return; /* Empty index */
824
+
825
+ if ( dst->rank > 1 ) { /* 1-dimensionize */
826
+ na_flatten_temp(dst);
827
+ }
828
+ val = na_cast_unless_narray(val,dst->type);
829
+ GetNArray(val,src);
830
+ na_aset_slice( dst, src, sl );
831
+
832
+ na_free_slice_index(sl,1); /* free index memory */
833
+ //na_touch_object(val);
834
+ }
835
+
836
+
837
+ static void
838
+ na_aset_multi_dim(VALUE self, int nidx, VALUE *idx, volatile VALUE val)
839
+ {
840
+ int i, pos, size;
841
+ struct NARRAY *dst, *src;
842
+ struct slice *sl;
843
+
844
+ GetNArray(self,dst);
845
+ if (dst->total==0)
846
+ rb_raise(rb_eRuntimeError, "cannot set value to empty array");
847
+
848
+ /* make Slice from index-argv */
849
+ sl = ALLOC_N(struct slice, dst->rank+1);
850
+ size = na_index_analysis( nidx, idx, dst, sl );
851
+
852
+ if ( size == 0 ) { xfree(sl); return; } /* Empty index */
853
+ if ( size == 1 ) {
854
+ if (NA_IsArray(val)) {
855
+ /* Beginning index:
856
+ a[2,3,4] = other
857
+ */
858
+ val = na_cast_unless_narray(val,dst->type);
859
+ GetNArray(val,src);
860
+ if (src->total > 1)
861
+ for( i=0; i<src->rank; i++ ) {
862
+ sl[i].n = 0;
863
+ sl[i].step = 1;
864
+ }
865
+ }
866
+ else {
867
+ /* Single Element:
868
+ a[2,3,4] = 5
869
+ */
870
+ for ( pos=0, i=dst->rank; i-->0; )
871
+ pos = pos * dst->shape[i] + sl[i].beg;
872
+ SetFuncs[dst->type][NA_ROBJ](1, NA_PTR(dst,pos), 0, &val, 0 );
873
+ xfree(sl);
874
+ return;
875
+ }
876
+ }
877
+ else
878
+ val = na_cast_unless_narray(val,dst->type);
879
+ GetNArray(val,src);
880
+
881
+ /* if ( size>1 ) */
882
+ /* Range index:
883
+ a[0..9,0] = other
884
+ */
885
+ na_aset_slice( dst, src, sl );
886
+
887
+ na_free_slice_index(sl,nidx); /* free index memory */
888
+ xfree(sl);
889
+ //na_touch_object(val);
890
+ }
891
+
892
+
893
+
894
+ static void
895
+ na_aset_fill(VALUE self, volatile VALUE val)
896
+ {
897
+ struct NARRAY *dst, *src;
898
+ struct slice *sl;
899
+
900
+ GetNArray(self,dst);
901
+ if (dst->total==0)
902
+ rb_raise(rb_eRuntimeError, "cannot set value to empty array");
903
+
904
+ if ( NA_IsArray(val) ) { /* store Array? */
905
+ sl = ALLOC_N(struct slice, dst->rank+1);
906
+ na_set_slice_1obj(dst->rank,sl,dst->shape);
907
+
908
+ val = na_cast_unless_narray(val,dst->type);
909
+ GetNArray(val,src);
910
+ na_aset_slice( dst, src, sl );
911
+ xfree(sl);
912
+ }
913
+ else {
914
+ na_fill( self, val ); /* Simple filling */
915
+ }
916
+ //na_touch_object(val);
917
+ }
918
+
919
+
920
+ /* --- mask --- */
921
+ void
922
+ na_aset_mask(VALUE self, VALUE mask, VALUE val)
923
+ {
924
+ int size, step, i;
925
+ struct NARRAY *a1, *am, *a2;
926
+
927
+ GetNArray( self, a1 );
928
+ GetNArray( mask, am );
929
+
930
+ if (a1->total != am->total)
931
+ rb_raise(rb_eTypeError,"self.size(=%i) != mask.size(=%i)",
932
+ a1->total, am->total);
933
+ if (a1->rank != am->rank)
934
+ rb_raise(rb_eTypeError,"self.rank(=%i) != mask.rank(=%i)",
935
+ a1->rank, am->rank);
936
+ for (i=0; i<a1->rank; i++)
937
+ if (a1->shape[i] != am->shape[i])
938
+ rb_raise(rb_eTypeError,"self.shape[%i](=%i) != mask.shape[%i](=%i)",
939
+ i, a1->shape[i], i, am->shape[i]);
940
+
941
+ size = na_count_true_body(mask);
942
+
943
+ val = na_cast_object(val,a1->type);
944
+ GetNArray( val, a2 );
945
+ if (a2->total == 1) {
946
+ step = 0;
947
+ } else if (a2->total == size) {
948
+ step = na_sizeof[a2->type];
949
+ } else {
950
+ rb_raise(rb_eTypeError,"val.length != mask.count_true");
951
+ }
952
+
953
+ SetMaskFuncs[a1->type]
954
+ ( a1->total, a1->ptr, na_sizeof[a1->type],
955
+ a2->ptr, step, am->ptr, 1 );
956
+ }
957
+
958
+ /* method: []=(idx1,idx2,...,idxN,val) */
959
+ VALUE
960
+ na_aset(int nidx, VALUE *idx, VALUE self)
961
+ {
962
+ nidx--;
963
+
964
+ if (nidx==0) {
965
+ na_aset_fill( self, idx[0] );
966
+ }
967
+ else
968
+ if (nidx==1) {
969
+ if ( NA_IsNArray(idx[0]) ) {
970
+ if( NA_TYPE(idx[0]) == NA_BYTE ) { /* then supposed to be a mask */
971
+ na_aset_mask(self, idx[0], idx[1]);
972
+ return(idx[1]);
973
+ }
974
+ }
975
+ if ( NA_IsArray(idx[0]) ) /* Array Index ? */
976
+ na_aset_array_index( self, idx[0], idx[1] );
977
+ else
978
+ na_aset_single_dim( self, idx[0], idx[1] );
979
+ }
980
+ else
981
+ if (nidx>1) {
982
+ na_aset_multi_dim( self, nidx, idx, idx[nidx] );
983
+ }
984
+ else /* if (nidx<0) */
985
+ rb_raise( rb_eArgError, "No value specified" );
986
+
987
+ return idx[nidx];
988
+ }