narray-bigmem 0.0.0

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