narray-bigmem 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,444 @@
1
+ /*
2
+ na_random.c
3
+ Numerical Array Extention for Ruby
4
+ (C) Copyright 2003-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
+
12
+ /*
13
+ This is based on trimmed version of MT19937. To get the original version,
14
+ contact <http://www.math.keio.ac.jp/~matumoto/emt.html>.
15
+
16
+ The original copyright notice follows.
17
+
18
+ A C-program for MT19937, with initialization improved 2002/2/10.
19
+ Coded by Takuji Nishimura and Makoto Matsumoto.
20
+ This is a faster version by taking Shawn Cokus's optimization,
21
+ Matthe Bellew's simplification, Isaku Wada's real version.
22
+
23
+ Before using, initialize the state by using init_genrand(seed)
24
+ or init_by_array(init_key, key_length).
25
+
26
+ Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
27
+ All rights reserved.
28
+
29
+ Redistribution and use in source and binary forms, with or without
30
+ modification, are permitted provided that the following conditions
31
+ are met:
32
+
33
+ 1. Redistributions of source code must retain the above copyright
34
+ notice, this list of conditions and the following disclaimer.
35
+
36
+ 2. Redistributions in binary form must reproduce the above copyright
37
+ notice, this list of conditions and the following disclaimer in the
38
+ documentation and/or other materials provided with the distribution.
39
+
40
+ 3. The names of its contributors may not be used to endorse or promote
41
+ products derived from this software without specific prior written
42
+ permission.
43
+
44
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
45
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
46
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
47
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
48
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
49
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
50
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
51
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
52
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
53
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
54
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55
+
56
+
57
+ Any feedback is very welcome.
58
+ http://www.math.keio.ac.jp/matumoto/emt.html
59
+ email: matumoto@math.keio.ac.jp
60
+ */
61
+ #include "ruby.h"
62
+ #include "narray.h"
63
+ #include "narray_local.h"
64
+
65
+ /* Period parameters */
66
+ #define N 624
67
+ #define M 397
68
+ #define MATRIX_A 0x9908b0dfUL /* constant vector a */
69
+ #define UMASK 0x80000000UL /* most significant w-r bits */
70
+ #define LMASK 0x7fffffffUL /* least significant r bits */
71
+ #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
72
+ #define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL))
73
+
74
+ static u_int32_t state[N]; /* the array for the state vector */
75
+ static int left = 1;
76
+ static int initf = 0;
77
+ static u_int32_t *next;
78
+
79
+ /* initializes state[N] with a seed */
80
+ static void
81
+ init_genrand(u_int32_t s)
82
+ {
83
+ int j;
84
+ state[0]= s & 0xffffffffUL;
85
+ for (j=1; j<N; ++j) {
86
+ state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j);
87
+ /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
88
+ /* In the previous versions, MSBs of the seed affect */
89
+ /* only MSBs of the array state[]. */
90
+ /* 2002/01/09 modified by Makoto Matsumoto */
91
+ state[j] &= 0xffffffffUL; /* for >32 bit machines */
92
+ }
93
+ left = 1; initf = 1;
94
+ }
95
+
96
+ static void
97
+ next_state()
98
+ {
99
+ u_int32_t *p=state;
100
+ int j;
101
+
102
+ /* if init_genrand() has not been called, */
103
+ /* a default initial seed is used */
104
+ if (initf==0) init_genrand(5489UL);
105
+
106
+ left = N;
107
+ next = state;
108
+
109
+ for (j=N-M+1; --j; ++p)
110
+ *p = p[M] ^ TWIST(p[0], p[1]);
111
+
112
+ for (j=M; --j; ++p)
113
+ *p = p[M-N] ^ TWIST(p[0], p[1]);
114
+
115
+ *p = p[M-N] ^ TWIST(p[0], state[0]);
116
+ }
117
+
118
+ #undef N
119
+ #undef M
120
+
121
+ /* These real versions are due to Isaku Wada, 2002/01/09 added */
122
+
123
+ #ifdef HAVE_UNISTD_H
124
+ #include <unistd.h>
125
+ #endif
126
+ #include <time.h>
127
+ #ifdef HAVE_SYS_TIME_H
128
+ #include <sys/time.h>
129
+ #endif
130
+
131
+ static int first = 1;
132
+
133
+ static int
134
+ rand_init(seed)
135
+ u_int32_t seed;
136
+ {
137
+ static u_int32_t saved_seed;
138
+ u_int32_t old;
139
+
140
+ first = 0;
141
+ init_genrand(seed);
142
+ old = saved_seed;
143
+ saved_seed = seed;
144
+
145
+ return old;
146
+ }
147
+
148
+ static u_int32_t
149
+ random_seed()
150
+ {
151
+ static int n = 0;
152
+ struct timeval tv;
153
+
154
+ gettimeofday(&tv, 0);
155
+ return tv.tv_sec ^ tv.tv_usec ^ getpid() ^ n++;
156
+ }
157
+
158
+ static VALUE
159
+ na_s_srand(int argc, VALUE *argv, VALUE obj)
160
+ {
161
+ VALUE sd;
162
+ u_int32_t seed, old;
163
+
164
+ rb_secure(4);
165
+ if (rb_scan_args(argc, argv, "01", &sd) == 0) {
166
+ seed = random_seed();
167
+ }
168
+ else {
169
+ seed = NUM2ULONG(sd);
170
+ }
171
+ old = rand_init(seed);
172
+
173
+ return ULONG2NUM(old);
174
+ }
175
+
176
+ /* - end of the code from ruby/random.c - */
177
+
178
+ #define genrand(y) \
179
+ { if (--left == 0) next_state();\
180
+ (y) = *next++;\
181
+ (y) ^= ((y) >> 11);\
182
+ (y) ^= ((y) << 7) & 0x9d2c5680UL;\
183
+ (y) ^= ((y) << 15) & 0xefc60000UL;\
184
+ (y) ^= ((y) >> 18); }
185
+
186
+ #define rand_double(x,y) \
187
+ (((double)((x)>>5)+(double)((y)>>6)*(1.0/67108864.0)) * (1.0/134217728.0))
188
+
189
+ #define rand_single(y) \
190
+ ((double)(y) * (1.0/4294967296.0))
191
+
192
+ static int n_bits(int64_t a)
193
+ {
194
+ int i, x, xl, n=8;
195
+ // int i, x, xu, xl, n=8;
196
+ int64_t m;
197
+
198
+ if (a==0) return 0;
199
+ if (a<0) a=-a;
200
+
201
+ x = ((int64_t)1)<<n;
202
+ // xu = 1<<(n+1);
203
+ xl = 0;
204
+
205
+ for (i=n; i>=0; --i) {
206
+ m = ~((((int64_t)1)<<(x-1))-1);
207
+
208
+ if (m & a) {
209
+ xl = x;
210
+ x += 1<<(i-1);
211
+ } else {
212
+ // xu = x;
213
+ x -= 1<<(i-1);
214
+ }
215
+ /* printf("%3i, [%3i, %3i], %x\n", i, xu, xl, m1); */
216
+ }
217
+ /* if (xu-xl!=1) printf("*** erorr %d - %d != 1\n", xu, xl); */
218
+ return xl;
219
+ }
220
+
221
+ // max&limit must be integer
222
+ static u_int64_t size_check(double rmax, double limit)
223
+ {
224
+ u_int64_t max;
225
+
226
+ if ( rmax == 0 ) {
227
+ return (u_int64_t)(limit-1);
228
+ }
229
+ if ( rmax < 0 ) {
230
+ rmax = -rmax;
231
+ }
232
+ max = (u_int64_t)(rmax - 1);
233
+ if ( max >= limit ) {
234
+ rb_raise(rb_eArgError, "rand-max(%.0f) must be <= %.0f", rmax, limit);
235
+ }
236
+ return max;
237
+ }
238
+
239
+ static void TpErr(void) {
240
+ rb_raise(rb_eTypeError,"illegal operation with this type");
241
+ }
242
+
243
+ static void RndB(int n, char *p1, int i1, double rmax)
244
+ {
245
+ u_int32_t y;
246
+ u_int64_t max;
247
+ int shift;
248
+
249
+ if ( rmax < 0 ) {
250
+ rb_raise(rb_eArgError, "rand-max must be positive");
251
+ }
252
+ max = size_check(rmax,0x100);
253
+ shift = 32 - n_bits(max);
254
+
255
+ if (max<1) {
256
+ for (; n; --n) {
257
+ *(u_int8_t*)p1 = 0;
258
+ p1+=i1;
259
+ }
260
+ } else {
261
+ for (; n; --n) {
262
+ do {
263
+ genrand(y);
264
+ y >>= shift;
265
+ } while (y > max);
266
+ *(u_int8_t*)p1 = (u_int8_t)y;
267
+ p1+=i1;
268
+ }
269
+ }
270
+ }
271
+
272
+ static void RndI(int n, char *p1, int i1, double rmax)
273
+ {
274
+ u_int32_t y;
275
+ u_int64_t max;
276
+ int shift, sign=1;
277
+
278
+ if ( rmax < 0 ) { rmax = -rmax; sign = -1; }
279
+ max = size_check(rmax,0x8000);
280
+ shift = 32 - n_bits(max);
281
+
282
+ if (max<1) {
283
+ for (; n; --n) {
284
+ *(int16_t*)p1 = 0;
285
+ p1+=i1;
286
+ }
287
+ } else {
288
+ for (; n; --n) {
289
+ do {
290
+ genrand(y);
291
+ y >>= shift;
292
+ } while (y > max);
293
+ *(int16_t*)p1 = (int16_t)y*sign;
294
+ p1+=i1;
295
+ }
296
+ }
297
+ }
298
+
299
+ static void RndL(int n, char *p1, int i1, double rmax)
300
+ {
301
+ u_int32_t y;
302
+ u_int64_t max;
303
+ int shift, sign=1;
304
+
305
+ if ( rmax < 0 ) { rmax = -rmax; sign = -1; }
306
+ max = size_check(rmax,0x80000000);
307
+ shift = 64 - n_bits(max);
308
+
309
+ if (max<1) {
310
+ for (; n; --n) {
311
+ *(int32_t*)p1 = 0;
312
+ p1+=i1;
313
+ }
314
+ } else {
315
+ for (; n; --n) {
316
+ do {
317
+ genrand(y);
318
+ y >>= shift;
319
+ } while (y > max);
320
+ *(int32_t*)p1 = (int32_t)y*sign;
321
+ p1+=i1;
322
+ }
323
+ }
324
+ }
325
+
326
+ static void RndG(int n, char *p1, int i1, double rmax)
327
+ {
328
+ u_int64_t y;
329
+ u_int64_t max;
330
+ int shift, sign=1;
331
+
332
+ if ( rmax < 0 ) { rmax = -rmax; sign = -1; }
333
+ max = size_check(rmax,0x800000000000);
334
+ shift = 64 - n_bits(max);
335
+
336
+ if (max<1) {
337
+ for (; n; --n) {
338
+ *(int64_t*)p1 = 0;
339
+ p1+=i1;
340
+ }
341
+ } else {
342
+ for (; n; --n) {
343
+ do {
344
+ genrand(y);
345
+ y >>= shift;
346
+ } while (y > max);
347
+ *(int64_t*)p1 = (int64_t)y*sign;
348
+ p1+=i1;
349
+ }
350
+ }
351
+ }
352
+
353
+ static void RndF(int n, char *p1, int i1, double rmax)
354
+ {
355
+ u_int32_t y;
356
+
357
+ for (; n; --n) {
358
+ genrand(y);
359
+ *(float*)p1 = rand_single(y) * rmax;
360
+ p1+=i1;
361
+ }
362
+ }
363
+
364
+ static void RndD(int n, char *p1, int i1, double rmax)
365
+ {
366
+ u_int32_t x,y;
367
+
368
+ for (; n; --n) {
369
+ genrand(x);
370
+ genrand(y);
371
+ *(double*)p1 = rand_double(x,y) * rmax;
372
+ p1+=i1;
373
+ }
374
+ }
375
+
376
+ static void RndX(int n, char *p1, int i1, double rmax)
377
+ {
378
+ u_int32_t y;
379
+
380
+ for (; n; --n) {
381
+ genrand(y);
382
+ ((scomplex*)p1)->r = rand_single(y) * rmax;
383
+ ((scomplex*)p1)->i = 0;
384
+ p1+=i1;
385
+ }
386
+ }
387
+
388
+ static void RndC(int n, char *p1, int i1, double rmax)
389
+ {
390
+ u_int32_t x,y;
391
+
392
+ for (; n; --n) {
393
+ genrand(x);
394
+ genrand(y);
395
+ ((dcomplex*)p1)->r = rand_double(x,y) * rmax;
396
+ ((dcomplex*)p1)->i = 0;
397
+ p1+=i1;
398
+ }
399
+ }
400
+
401
+ na_func_t RndFuncs =
402
+ { TpErr, RndB, RndI, RndL, RndG, RndF, RndD, RndX, RndC, TpErr };
403
+
404
+
405
+ static VALUE
406
+ na_random_bang(int argc, VALUE *argv, VALUE self)
407
+ {
408
+ VALUE vmax;
409
+ struct NARRAY *ary;
410
+ double rmax;
411
+
412
+ rb_scan_args(argc, argv, "01", &vmax);
413
+ if (first) {
414
+ rand_init(random_seed());
415
+ }
416
+ if (NIL_P(vmax)) {
417
+ rmax = 1;
418
+ } else {
419
+ rmax = NUM2DBL(vmax);
420
+ }
421
+ if (isinf(rmax) || isnan(rmax)) {
422
+ rb_raise(rb_eArgError, "rand-max must be regular value");
423
+ }
424
+
425
+ GetNArray(self,ary);
426
+
427
+ (*RndFuncs[ary->type])( ary->total, ary->ptr, na_sizeof[ary->type], rmax );
428
+
429
+ return self;
430
+ }
431
+
432
+ static VALUE
433
+ na_random(int argc, VALUE *argv, VALUE self)
434
+ {
435
+ return na_random_bang(argc, argv, na_clone(self));
436
+ }
437
+
438
+ void
439
+ Init_na_random()
440
+ {
441
+ rb_define_singleton_method(cNArray,"srand",na_s_srand,-1);
442
+ rb_define_method(cNArray, "random!", na_random_bang,-1);
443
+ rb_define_method(cNArray, "random", na_random,-1);
444
+ }
@@ -0,0 +1,1341 @@
1
+ /*
2
+ narray.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
+ #define NARRAY_C
12
+ #include <ruby.h>
13
+ #include "narray.h"
14
+ #include "narray_local.h"
15
+
16
+ /* global variables within this module */
17
+ VALUE cNArray, cNArrayScalar, cComplex;
18
+
19
+ ID na_id_beg, na_id_end, na_id_exclude_end;
20
+ ID na_id_minus, na_id_abs, na_id_power;
21
+ ID na_id_compare, na_id_ne, na_id_and, na_id_or;
22
+ ID na_id_class_dim;
23
+ ID na_id_add, na_id_sbt, na_id_mul, na_id_div, na_id_mod;
24
+ ID na_id_real, na_id_imag;
25
+ ID na_id_coerce_rev;
26
+ ID na_id_new;
27
+ ID na_id_Complex;
28
+ static ID na_id_to_i, na_id_usec, na_id_now;
29
+
30
+ const int na_sizeof[NA_NTYPES+1] = {
31
+ 0,
32
+ sizeof(u_int8_t),
33
+ sizeof(int16_t),
34
+ sizeof(int32_t),
35
+ sizeof(int64_t),
36
+ sizeof(float),
37
+ sizeof(double),
38
+ sizeof(scomplex),
39
+ sizeof(dcomplex),
40
+ sizeof(VALUE),
41
+ 0
42
+ };
43
+
44
+ const char *na_typestring[] = {
45
+ "none",
46
+ "byte", /* 1 */
47
+ "sint", /* 2 */
48
+ "int", /* 3 */
49
+ "long", /* 4 */
50
+ "sfloat", /* 5 */
51
+ "float", /* 6 */
52
+ "scomplex", /* 7 */
53
+ "complex", /* 8 */
54
+ "object", /* 9 */
55
+ "ntypes" /* 10 */
56
+ };
57
+
58
+ #ifdef NARRAY_GC
59
+ static int mem_count = 0;
60
+ static int na_gc_freq = 2500000; /* Frequency of Garbage Collection */
61
+ #endif
62
+
63
+ void Init_na_array(void);
64
+ void Init_na_index(void);
65
+ void Init_nmath(void);
66
+ void Init_na_funcs(void);
67
+ void Init_na_linalg(void);
68
+ void Init_na_random(void);
69
+
70
+
71
+ #ifdef DEBUG
72
+ void na_xfree(void *ptr)
73
+ {
74
+ if (!ptr) abort();
75
+ free(ptr);
76
+ }
77
+ #endif
78
+
79
+ /* mark items */
80
+ static void
81
+ na_mark_obj(struct NARRAY *ary)
82
+ {
83
+ na_shape_t i;
84
+ VALUE *ptr;
85
+
86
+ ptr = (VALUE*) ary->ptr;
87
+ for (i=ary->total; i>0; --i)
88
+ rb_gc_mark(*ptr++);
89
+ }
90
+
91
+ static void
92
+ na_mark_ref(struct NARRAY *ary)
93
+ {
94
+ struct NARRAY *a2;
95
+
96
+ rb_gc_mark( ary->ref );
97
+
98
+ GetNArray(ary->ref,a2);
99
+ if (a2->type == NA_ROBJ) na_mark_obj(a2);
100
+ }
101
+
102
+
103
+ static void
104
+ na_free(struct NARRAY* ary)
105
+ {
106
+ if ( ary->total > 0 ) {
107
+ if (ary->ref == Qnil || ary->ref == Qtrue) { /* non reference */
108
+ xfree(ary->ptr);
109
+ }
110
+ xfree(ary->shape);
111
+ #ifdef DEBUG
112
+ ary->shape = NULL;
113
+ ary->ptr = NULL;
114
+ #endif
115
+ }
116
+ xfree(ary);
117
+ }
118
+
119
+
120
+ /* allocation of NARRAY */
121
+ struct NARRAY*
122
+ na_alloc_struct(int type, int rank, na_shape_t *shape)
123
+ {
124
+ na_shape_t total=1, total_bak;
125
+ int i;
126
+ na_shape_t memsz;
127
+ struct NARRAY *ary;
128
+
129
+ for (i=0; i<rank; ++i) {
130
+ if (shape[i] < 0) {
131
+ rb_raise(rb_eArgError, "negative array size");
132
+ } else if (shape[i] == 0) {
133
+ total = 0;
134
+ break;
135
+ }
136
+ total_bak = total;
137
+ total *= shape[i];
138
+ if (total < 1 || (total >> (sizeof(na_shape_t)*8-2)) > 0 || total/shape[i] != total_bak) {
139
+ rb_raise(rb_eArgError, "array size is too large");
140
+ }
141
+ }
142
+
143
+ if (rank<=0 || total<=0) {
144
+ /* empty array */
145
+ ary = ALLOC(struct NARRAY);
146
+ ary->rank =
147
+ ary->total = 0;
148
+ ary->shape = NULL;
149
+ ary->ptr = NULL;
150
+ ary->type = type;
151
+ }
152
+ else {
153
+ memsz = na_sizeof[type] * total;
154
+ if (memsz < 1 || (memsz >> (sizeof(na_shape_t)*8-2)) > 0 || memsz/na_sizeof[type] != total) {
155
+ rb_raise(rb_eArgError, "allocation size is too large");
156
+ }
157
+
158
+ /* Garbage Collection */
159
+ #ifdef NARRAY_GC
160
+ mem_count += memsz;
161
+ if ( mem_count > na_gc_freq ) { rb_gc(); mem_count=0; }
162
+ #endif
163
+
164
+ ary = ALLOC(struct NARRAY);
165
+ ary->shape = ALLOC_N(na_shape_t, rank);
166
+ ary->ptr = ALLOC_N(char, memsz);
167
+
168
+ ary->rank = rank;
169
+ ary->total = total;
170
+ ary->type = type;
171
+ for (i=0; i<rank; ++i)
172
+ ary->shape[i] = shape[i];
173
+ }
174
+ ary->ref = Qtrue;
175
+ return ary;
176
+ }
177
+
178
+ #if !defined RCLASS_SUPER
179
+ #define RCLASS_SUPER(v) (RCLASS(v)->super)
180
+ #endif
181
+
182
+ static void
183
+ na_check_class_narray(VALUE v)
184
+ {
185
+ if (TYPE(v) != T_CLASS) {
186
+ rb_raise(rb_eRuntimeError, "class required");
187
+ }
188
+
189
+ if (v == cNArray)
190
+ return;
191
+ if (RTEST(rb_funcall(v, rb_intern("<="), 1, cNArray)))
192
+ return;
193
+
194
+ rb_raise(rb_eRuntimeError, "need NArray or its subclass");
195
+ }
196
+
197
+
198
+ static VALUE
199
+ na_wrap_struct_class(struct NARRAY *ary, VALUE klass)
200
+ {
201
+ VALUE v;
202
+ int class_dim;
203
+
204
+ /* Extract element */
205
+ if (ary->rank==0 && ary->total==1) {
206
+ SetFuncs[NA_ROBJ][ary->type](1,&v,0,ary->ptr,0);
207
+ na_free(ary);
208
+ return v;
209
+ }
210
+
211
+ /* check NArray >= klass */
212
+ na_check_class_narray(klass);
213
+
214
+ /* Check dimension */
215
+ class_dim = NUM2INT(rb_const_get(klass, na_id_class_dim));
216
+ if (ary->rank < class_dim)
217
+ rb_raise(rb_eTypeError, "array.dim(=%i) < CLASS_DIMENSION(=%i)",
218
+ ary->rank, class_dim);
219
+
220
+ if (ary->ref == Qnil)
221
+ rb_raise(rb_eRuntimeError, "already wrapped object");
222
+
223
+ /* Turn on WRAPPED flag */
224
+ if (ary->ref == Qtrue) {
225
+ ary->ref = Qnil;
226
+ if (NA_IsROBJ(ary))
227
+ return Data_Wrap_Struct(klass, na_mark_obj, na_free, ary);
228
+ else
229
+ return Data_Wrap_Struct(klass, 0, na_free, ary);
230
+ }
231
+
232
+ /* reference to another NArray*/
233
+ return Data_Wrap_Struct(klass, na_mark_ref, na_free, ary);
234
+ }
235
+
236
+
237
+ static VALUE
238
+ na_wrap_struct(struct NARRAY *ary, VALUE obj)
239
+ {
240
+ return na_wrap_struct_class(ary,CLASS_OF(obj));
241
+ }
242
+
243
+
244
+ VALUE
245
+ na_make_object(int type, int rank, na_shape_t *shape, VALUE klass)
246
+ {
247
+ struct NARRAY *na;
248
+
249
+ na = na_alloc_struct(type, rank, shape);
250
+
251
+ if (type==NA_ROBJ) {
252
+ rb_mem_clear((VALUE*)(na->ptr), na->total);
253
+ }
254
+ return na_wrap_struct_class(na, klass);
255
+ }
256
+
257
+
258
+ /* restriction: Integer, Float, Complex === obj */
259
+ VALUE
260
+ na_make_scalar(VALUE obj, int type)
261
+ {
262
+ static na_shape_t shape=1;
263
+ VALUE v;
264
+ struct NARRAY *ary;
265
+
266
+ v = na_make_object(type,1,&shape,cNArrayScalar);
267
+ GetNArray(v,ary);
268
+ SetFuncs[ary->type][NA_ROBJ](1, ary->ptr,0, &obj,0);
269
+
270
+ return v;
271
+ }
272
+
273
+
274
+ VALUE
275
+ na_make_empty(int type, VALUE klass)
276
+ {
277
+ struct NARRAY *na;
278
+
279
+ na = na_alloc_struct(type, 0, NULL);
280
+ return na_wrap_struct_class(na, klass);
281
+ }
282
+
283
+
284
+ /* allocate reference to NArray */
285
+ struct NARRAY*
286
+ na_ref_alloc_struct(VALUE obj)
287
+ {
288
+ int i;
289
+ struct NARRAY *orig, *ary;
290
+
291
+ GetNArray(obj,orig);
292
+
293
+ if (orig->rank<=0)
294
+ rb_raise(rb_eRuntimeError, "cannot create NArrayRefer of Empty NArray");
295
+
296
+ ary = ALLOC(struct NARRAY);
297
+ ary->shape = ALLOC_N(na_shape_t, orig->rank);
298
+ ary->ptr = orig->ptr;
299
+ ary->rank = orig->rank;
300
+ ary->total = orig->total;
301
+ ary->type = orig->type;
302
+ for (i=0; i<orig->rank; ++i)
303
+ ary->shape[i] = orig->shape[i];
304
+ ary->ref = obj;
305
+
306
+ return ary;
307
+ }
308
+
309
+ /* method: self.refer */
310
+ static VALUE
311
+ na_refer(VALUE self)
312
+ {
313
+ return na_wrap_struct(na_ref_alloc_struct(self), self);
314
+ }
315
+
316
+ /* singleton method: NArray.refer( other ) */
317
+ static VALUE
318
+ na_s_refer(VALUE klass, VALUE self)
319
+ {
320
+ return na_wrap_struct_class(na_ref_alloc_struct(self), klass);
321
+ }
322
+
323
+ /* method: self.original */
324
+ static VALUE
325
+ na_original(VALUE self)
326
+ {
327
+ struct NARRAY *ary;
328
+
329
+ GetNArray(self,ary);
330
+ return ary->ref;
331
+ }
332
+
333
+
334
+ void
335
+ na_clear_data(struct NARRAY *ary)
336
+ {
337
+ if (NA_IsROBJ(ary))
338
+ rb_mem_clear((VALUE*)(ary->ptr), ary->total);
339
+ else
340
+ MEMZERO(ary->ptr, char, na_sizeof[ary->type]*ary->total);
341
+ }
342
+
343
+
344
+ /* local function for new array creation */
345
+ static VALUE
346
+ na_new2(int argc, VALUE *argv, int type, VALUE klass)
347
+ {
348
+ int i;
349
+ na_shape_t *shape;
350
+ struct NARRAY *ary;
351
+ VALUE v;
352
+
353
+ if (argc == 0)
354
+ rb_raise(rb_eArgError, "Argument required");
355
+
356
+ shape = ALLOCA_N(na_shape_t,argc);
357
+ for (i=0; i<argc; ++i) shape[i]=NUM2SHAPE(argv[i]);
358
+
359
+ v = na_make_object(type,argc,shape,klass);
360
+ GetNArray(v,ary);
361
+
362
+ if (ary->type != NA_ROBJ)
363
+ na_clear_data(ary);
364
+
365
+ /* rb_obj_call_init(v, 0, 0); */
366
+ return v;
367
+ }
368
+
369
+
370
+ /* Convert type arguments -> typecode */
371
+ int
372
+ na_get_typecode(VALUE v)
373
+ {
374
+ struct NARRAY *na;
375
+ int i;
376
+
377
+ if (v==rb_cFloat) return NA_DFLOAT;
378
+ if (v==rb_cInteger) return NA_LINT;
379
+ if (v==cComplex) return NA_DCOMPLEX;
380
+ if (v==rb_cObject) return NA_ROBJ;
381
+ if (FIXNUM_P(v)) {
382
+ i = NUM2INT(v);
383
+ if (i<=NA_NONE || i>=NA_NTYPES)
384
+ rb_raise(rb_eArgError, "Wrong type code");
385
+ return i;
386
+ }
387
+ if (NA_IsNArray(v)) {
388
+ GetNArray(v,na);
389
+ return na->type;
390
+ }
391
+ if (TYPE(v)==T_STRING) {
392
+ for (i=1; i<NA_NTYPES; ++i) {
393
+ if ( !strncmp( RSTRING_PTR(v), na_typestring[i], RSTRING_LEN(v)) )
394
+ return i;
395
+ }
396
+ }
397
+ rb_raise(rb_eArgError, "Unrecognized NArray type");
398
+ return 0;
399
+ }
400
+
401
+
402
+ /* class method: new(type, size1,size2,...,sizeN) */
403
+ static VALUE
404
+ na_s_new(int argc, VALUE *argv, VALUE klass)
405
+ {
406
+ if (argc == 0)
407
+ rb_raise(rb_eArgError, "Argument required");
408
+ return na_new2(argc-1, argv+1, na_get_typecode(argv[0]), klass);
409
+ }
410
+
411
+ /* class method: byte(size1,size2,...,sizeN) */
412
+ static VALUE
413
+ na_s_new_byte(int argc, VALUE *argv, VALUE klass)
414
+ { return na_new2(argc, argv, NA_BYTE, klass); }
415
+
416
+ /* class method: sint(size1,size2,...,sizeN) */
417
+ static VALUE
418
+ na_s_new_sint(int argc, VALUE *argv, VALUE klass)
419
+ { return na_new2(argc, argv, NA_SINT, klass); }
420
+
421
+ /* class method: int(size1,size2,...,sizeN) */
422
+ static VALUE
423
+ na_s_new_int(int argc, VALUE *argv, VALUE klass)
424
+ { return na_new2(argc, argv, NA_LINT, klass); }
425
+
426
+ /* class method: llint(size1,size2,...,sizeN) */
427
+ static VALUE
428
+ na_s_new_llint(int argc, VALUE *argv, VALUE klass)
429
+ { return na_new2(argc, argv, NA_LLINT, klass); }
430
+
431
+ /* class method: sfloat(size1,size2,...,sizeN) */
432
+ static VALUE
433
+ na_s_new_sfloat(int argc, VALUE *argv, VALUE klass)
434
+ { return na_new2(argc, argv, NA_SFLOAT, klass); }
435
+
436
+ /* class method: float(size1,size2,...,sizeN) */
437
+ static VALUE
438
+ na_s_new_float(int argc, VALUE *argv, VALUE klass)
439
+ { return na_new2(argc, argv, NA_DFLOAT, klass); }
440
+
441
+ /* class method: scomplex(size1,size2,...,sizeN) */
442
+ static VALUE
443
+ na_s_new_scomplex(int argc, VALUE *argv, VALUE klass)
444
+ { return na_new2(argc, argv, NA_SCOMPLEX, klass); }
445
+
446
+ /* class method: complex(size1,size2,...,sizeN) */
447
+ static VALUE
448
+ na_s_new_complex(int argc, VALUE *argv, VALUE klass)
449
+ { return na_new2(argc, argv, NA_DCOMPLEX, klass); }
450
+
451
+ /* class method: object(size1,size2,...,sizeN) */
452
+ static VALUE
453
+ na_s_new_object(int argc, VALUE *argv, VALUE klass)
454
+ { return na_new2(argc, argv, NA_ROBJ, klass); }
455
+
456
+
457
+
458
+ /* method: dup() */
459
+ VALUE
460
+ na_clone(VALUE self)
461
+ {
462
+ struct NARRAY *org, *cpy;
463
+
464
+ GetNArray(self,org);
465
+ cpy = na_alloc_struct(org->type,org->rank,org->shape);
466
+ memcpy(cpy->ptr, org->ptr, na_sizeof[org->type] * org->total);
467
+ return na_wrap_struct(cpy,self);
468
+ }
469
+
470
+
471
+ /* local function */
472
+ void
473
+ na_copy_nary(struct NARRAY *dst, struct NARRAY *src)
474
+ {
475
+ if (dst->total != src->total)
476
+ rb_raise(rb_eRuntimeError, "src and dst array sizes mismatch");
477
+
478
+ if (dst->type == src->type)
479
+ memcpy(dst->ptr, src->ptr, src->total*na_sizeof[src->type]);
480
+ else {
481
+ SetFuncs[dst->type][src->type]( src->total,
482
+ dst->ptr, na_sizeof[dst->type],
483
+ src->ptr, na_sizeof[src->type] );
484
+ }
485
+ }
486
+
487
+
488
+ /* method: to_type(type) */
489
+ static VALUE
490
+ na_to_type(VALUE self, VALUE vtype)
491
+ {
492
+ struct NARRAY *a1, *a2;
493
+ VALUE v;
494
+
495
+ GetNArray(self,a1);
496
+
497
+ v = na_make_object(na_get_typecode(vtype), a1->rank, a1->shape,
498
+ CLASS_OF(self));
499
+ GetNArray(v,a2);
500
+ na_copy_nary(a2,a1);
501
+ return v;
502
+ }
503
+
504
+
505
+ /* method: to_f() */
506
+ static VALUE
507
+ na_to_float(VALUE self)
508
+ {
509
+ struct NARRAY *a1, *a2;
510
+ VALUE v;
511
+
512
+ GetNArray(self,a1);
513
+
514
+ v = na_make_object(na_upcast[NA_SFLOAT][a1->type], a1->rank, a1->shape,
515
+ CLASS_OF(self));
516
+ GetNArray(v,a2);
517
+ na_copy_nary(a2,a1);
518
+ return v;
519
+ }
520
+
521
+
522
+ /* method: to_i() */
523
+ static VALUE
524
+ na_to_integer(VALUE self)
525
+ {
526
+ int type;
527
+ struct NARRAY *a1, *a2;
528
+ VALUE v;
529
+
530
+ GetNArray(self,a1);
531
+ if (!NA_IsINTEGER(a1))
532
+ type = NA_LINT;
533
+ else
534
+ type = a1->type;
535
+ v = na_make_object(type, a1->rank, a1->shape, CLASS_OF(self));
536
+ GetNArray(v,a2);
537
+ na_copy_nary(a2,a1);
538
+ return v;
539
+ }
540
+
541
+
542
+ /* method: shape() -- returns an array of shape of each rank */
543
+ static VALUE
544
+ na_shape(VALUE self)
545
+ {
546
+ struct NARRAY *ary;
547
+ VALUE *shape;
548
+ int i;
549
+
550
+ GetNArray(self,ary);
551
+ shape = ALLOCA_N(VALUE,ary->rank);
552
+ for (i = 0; i < ary->rank; ++i)
553
+ shape[i] = INT2FIX(ary->shape[i]);
554
+ return rb_ary_new4(ary->rank,shape);
555
+ }
556
+
557
+
558
+ /* method: rank() -- returns the rank of the array */
559
+ static VALUE
560
+ na_rank(VALUE self)
561
+ {
562
+ struct NARRAY *ary;
563
+ GetNArray(self,ary);
564
+ return INT2FIX(ary->rank);
565
+ }
566
+
567
+
568
+ /* method: size() -- returns the total number of elements */
569
+ static VALUE
570
+ na_size(VALUE self)
571
+ {
572
+ struct NARRAY *ary;
573
+ GetNArray(self,ary);
574
+ return INT2FIX(ary->total);
575
+ }
576
+
577
+
578
+ /* method: typecode -- returns the type of the array */
579
+ static VALUE
580
+ na_typecode(VALUE self)
581
+ {
582
+ struct NARRAY *ary;
583
+ GetNArray(self,ary);
584
+ return INT2FIX(ary->type);
585
+ }
586
+
587
+
588
+ /* method: element_size -- returns the element size of the array type */
589
+ static VALUE
590
+ na_element_size(VALUE self)
591
+ {
592
+ struct NARRAY *ary;
593
+ GetNArray(self,ary);
594
+ return INT2FIX(na_sizeof[ary->type]);
595
+ }
596
+
597
+
598
+ /* method: empty? -- returns true if empty array */
599
+ static VALUE
600
+ na_is_empty(VALUE self)
601
+ {
602
+ struct NARRAY *ary;
603
+ GetNArray(self,ary);
604
+ if (ary->total==0) return Qtrue;
605
+ return Qfalse;
606
+ }
607
+
608
+
609
+ /* Binary copy of String => NArray */
610
+ static VALUE
611
+ na_str_to_na(int argc, VALUE *argv, VALUE str)
612
+ {
613
+ struct NARRAY *ary;
614
+ VALUE v;
615
+ int i, type, rank=argc-1;
616
+ na_shape_t len=1, str_len, *shape;
617
+
618
+ if (argc < 1)
619
+ rb_raise(rb_eArgError, "Type and Size Arguments required");
620
+
621
+ type = na_get_typecode(argv[0]);
622
+
623
+ str_len = RSTRING_LEN(str);
624
+
625
+ if (argc == 1) {
626
+ rank = 1;
627
+ shape = ALLOCA_N(na_shape_t,rank);
628
+ if ( str_len % na_sizeof[type] != 0 )
629
+ rb_raise(rb_eArgError, "string size mismatch");
630
+ shape[0] = str_len / na_sizeof[type];
631
+ }
632
+ else {
633
+ shape = ALLOCA_N(na_shape_t,rank);
634
+ for (i=0; i<rank; ++i)
635
+ len *= shape[i] = NUM2SHAPE(argv[i+1]);
636
+ len *= na_sizeof[type];
637
+ if ( len != str_len )
638
+ rb_raise(rb_eArgError, "size mismatch");
639
+ }
640
+
641
+ v = na_make_object( type, rank, shape, cNArray );
642
+ GetNArray(v,ary);
643
+ memcpy( ary->ptr, RSTRING_PTR(str), ary->total*na_sizeof[type] );
644
+
645
+ return v;
646
+ }
647
+
648
+
649
+ /* method: to_s -- convert the data contents to a binary string */
650
+ static VALUE
651
+ na_to_s(VALUE self)
652
+ {
653
+ struct NARRAY *ary;
654
+ GetNArray(self,ary);
655
+ if (NA_IsROBJ(ary))
656
+ rb_raise(rb_eTypeError,"cannot convert object-type NArray");
657
+ return rb_str_new(ary->ptr,ary->total*na_sizeof[ary->type]);
658
+ }
659
+
660
+
661
+ /* method: to_binary -- convert the data contents to a BYTE type NArray */
662
+ static VALUE
663
+ na_to_binary(VALUE self)
664
+ {
665
+ struct NARRAY *a1, *a2;
666
+ int i, rank;
667
+ na_shape_t *shape;
668
+ VALUE v;
669
+
670
+ GetNArray(self,a1);
671
+
672
+ rank = a1->rank+1;
673
+ shape = ALLOCA_N(na_shape_t,rank);
674
+ shape[0] = na_sizeof[a1->type];
675
+ for (i=1; i<rank; ++i)
676
+ shape[i] = a1->shape[i-1];
677
+
678
+ v = na_make_object( NA_BYTE, rank, shape, cNArray );
679
+ GetNArray(v,a2);
680
+ MEMCPY(a2->ptr,a1->ptr,char,a2->total);
681
+
682
+ return v;
683
+ }
684
+
685
+
686
+ /* method: to_type_as_binary(type) */
687
+ static VALUE
688
+ na_to_type_as_binary(VALUE self, VALUE vtype)
689
+ {
690
+ struct NARRAY *a1, *a2;
691
+ na_shape_t size, total;
692
+ int type;
693
+ VALUE v;
694
+
695
+ type = na_get_typecode(vtype);
696
+ GetNArray(self,a1);
697
+
698
+ size = a1->total * na_sizeof[a1->type];
699
+ if ( size % na_sizeof[type] != 0 )
700
+ rb_raise(rb_eRuntimeError, "bina1 size mismatch");
701
+ total = size / na_sizeof[type];
702
+
703
+ v = na_make_object( type, 1, &total, cNArray );
704
+ GetNArray(v,a2);
705
+ MEMCPY(a2->ptr,a1->ptr,char,size);
706
+
707
+ return v;
708
+ }
709
+
710
+
711
+ static void
712
+ na_to_string_binary(na_shape_t n, char *p1, na_shape_t i1, char *p2, na_shape_t i2)
713
+ {
714
+ for (; n>0; --n) {
715
+ *(VALUE*)p1 = rb_str_new(p2,i2);
716
+ p1+=i1; p2+=i2;
717
+ }
718
+ }
719
+
720
+
721
+ /* method: to_string */
722
+ static VALUE
723
+ na_to_string(VALUE self)
724
+ {
725
+ VALUE v;
726
+ struct NARRAY *a1, *a2;
727
+
728
+ GetNArray(self,a1);
729
+
730
+ if (a1->total==0)
731
+ v = na_make_empty(NA_ROBJ, CLASS_OF(self));
732
+ else
733
+ if (a1->type==NA_BYTE) {
734
+ if (a1->rank==1)
735
+ return rb_str_new(a1->ptr,a1->shape[0]);
736
+ v = na_make_object(NA_ROBJ, a1->rank-1, a1->shape+1, cNArray);
737
+ GetNArray(v,a2);
738
+ na_to_string_binary( a2->total,
739
+ a2->ptr, sizeof(VALUE),
740
+ a1->ptr, a1->shape[0] );
741
+ } else {
742
+ v = na_make_object(NA_ROBJ, a1->rank, a1->shape, CLASS_OF(self));
743
+ GetNArray(v,a2);
744
+ ToStrFuncs[a1->type]( a2->total,
745
+ a2->ptr, sizeof(VALUE),
746
+ a1->ptr, na_sizeof[a1->type] );
747
+ }
748
+ return v;
749
+ }
750
+
751
+
752
+ /* singleton method:
753
+ NArray.to_na( string, type, size1,size2,...,sizeN )
754
+ NArray.to_na( array )
755
+ */
756
+ static VALUE
757
+ na_s_to_na(int argc, VALUE *argv, VALUE klass)
758
+ {
759
+ if (argc < 1) {
760
+ rb_raise(rb_eArgError, "Argument is required");
761
+ }
762
+ if (TYPE(argv[0]) == T_STRING) {
763
+ return na_str_to_na(argc-1,argv+1,argv[0]);
764
+ }
765
+ if (argc > 1) {
766
+ rb_raise(rb_eArgError, "Only one array argument must be provided");
767
+ }
768
+ if (TYPE(argv[0]) == T_ARRAY) {
769
+ return na_ary_to_nary( argv[0], klass );
770
+ }
771
+ if (NA_IsNArray(argv[0])) {
772
+ return argv[0];
773
+ }
774
+ rb_raise(rb_eTypeError, "Argument must be Array or String (or NArray)");
775
+ return Qnil;
776
+ }
777
+
778
+
779
+ /* singleton method:
780
+ NArray[object]
781
+ */
782
+ static VALUE
783
+ na_s_bracket(int argc, VALUE *argv, VALUE klass)
784
+ {
785
+ VALUE v = rb_ary_new4(argc, argv);
786
+ return na_ary_to_nary( v, klass );
787
+ }
788
+
789
+
790
+ /* method: coerce(other) */
791
+ static VALUE na_coerce(VALUE self, VALUE other)
792
+ {
793
+ struct NARRAY *a1;
794
+
795
+ GetNArray(self,a1);
796
+ return rb_assoc_new( na_cast_object(other,a1->type), self );
797
+ }
798
+
799
+
800
+ /* method: inspect() -- returns the inspect of the array */
801
+ static VALUE
802
+ na_inspect(VALUE self)
803
+ {
804
+ VALUE str;
805
+ struct NARRAY *ary;
806
+ int i;
807
+ char buf[256];
808
+ const char *classname;
809
+ const char *ref = "%s(ref).%s(%zd";
810
+ const char *org = "%s.%s(%zd";
811
+
812
+ GetNArray(self,ary);
813
+ classname = rb_class2name(CLASS_OF(self));
814
+
815
+ str = rb_str_new(0,0);
816
+ if (ary->rank < 1) {
817
+ sprintf(buf, "%s.%s(): []", classname, na_typestring[ary->type]);
818
+ rb_str_cat(str,buf,strlen(buf));
819
+ }
820
+ else {
821
+ sprintf(buf, (ary->ref==Qnil) ? org:ref,
822
+ classname, na_typestring[ary->type], ary->shape[0]);
823
+ rb_str_cat(str,buf,strlen(buf));
824
+ for (i=1; i<ary->rank; ++i) {
825
+ sprintf(buf,",%zd",ary->shape[i]);
826
+ rb_str_cat(str,buf,strlen(buf));
827
+ }
828
+ rb_str_cat(str,")",1);
829
+ rb_str_cat(str,": \n",3);
830
+ rb_str_concat(str, na_make_inspect(self));
831
+ }
832
+ return str;
833
+ }
834
+
835
+
836
+ /* private function for reshape */
837
+ static void
838
+ na_reshape(int argc, VALUE *argv, struct NARRAY *ary, VALUE self)
839
+ {
840
+ na_shape_t *shape, total=1;
841
+ int *shrink;
842
+ int i, class_dim, unfixed=-1;
843
+ VALUE klass;
844
+
845
+ if (ary->total==0)
846
+ rb_raise(rb_eRuntimeError, "cannot reshape empty array");
847
+
848
+ klass = CLASS_OF(self);
849
+ class_dim = NUM2INT(rb_const_get(klass, na_id_class_dim));
850
+
851
+ if (argc == 0) { /* trim ranks of size=1 */
852
+ shrink = ALLOCA_N(int,ary->rank+1);
853
+ for (i=0; i<class_dim; ++i) shrink[i]=0;
854
+ for ( ; i<ary->rank; ++i) shrink[i]=1;
855
+ na_shrink_rank( self, class_dim, shrink );
856
+ if (ary->rank==0) ary->rank=1;
857
+ return;
858
+ }
859
+
860
+ /* get shape from argument */
861
+ shape = ALLOC_N(na_shape_t,argc);
862
+ for (i=0; i<argc; ++i)
863
+ switch(TYPE(argv[i])) {
864
+ case T_FIXNUM:
865
+ total *= shape[i] = NUM2SHAPE(argv[i]);
866
+ break;
867
+ case T_TRUE:
868
+ unfixed = i;
869
+ break;
870
+ default:
871
+ rb_raise(rb_eArgError,"illegal type");
872
+ }
873
+
874
+ if (unfixed>=0) {
875
+ if (ary->total % total != 0)
876
+ rb_raise(rb_eArgError, "Total size size must be divisor");
877
+ shape[unfixed] = ary->total / total;
878
+ }
879
+ else if (total != ary->total)
880
+ rb_raise(rb_eArgError, "Total size must be same");
881
+
882
+ /* exchange */
883
+ xfree(ary->shape);
884
+ ary->shape = shape;
885
+ ary->rank = argc;
886
+ }
887
+
888
+
889
+ /* method: reshape!(size1,size2,...,sizeN) */
890
+ static VALUE
891
+ na_reshape_bang(int argc, VALUE *argv, VALUE self)
892
+ {
893
+ struct NARRAY *ary;
894
+
895
+ GetNArray(self,ary);
896
+ na_reshape(argc, argv, ary, self);
897
+ return self;
898
+ }
899
+
900
+
901
+ /* method: reshape(size1,size2,...,sizeN) */
902
+ static VALUE
903
+ na_reshape_ref(int argc, VALUE *argv, VALUE self)
904
+ {
905
+ struct NARRAY *ary;
906
+
907
+ GetNArray(self,ary);
908
+ ary = na_ref_alloc_struct(self);
909
+ na_reshape(argc, argv, ary, self);
910
+ return na_wrap_struct(ary,self);
911
+ }
912
+
913
+
914
+ /* method: flatten! */
915
+ static VALUE
916
+ na_flatten_bang(VALUE self)
917
+ {
918
+ struct NARRAY *ary;
919
+
920
+ GetNArray(self,ary);
921
+ if (ary->total==0 || ary->rank==0)
922
+ rb_raise(rb_eRuntimeError, "cannot reshape empty array");
923
+ ary->shape[0] = ary->total;
924
+ ary->rank = 1;
925
+ return self;
926
+ }
927
+
928
+
929
+ /* method: flatten */
930
+ static VALUE
931
+ na_flatten_ref(VALUE self)
932
+ {
933
+ return na_flatten_bang( na_wrap_struct( na_ref_alloc_struct(self), self ));
934
+ }
935
+
936
+
937
+ /* private function for newdim */
938
+ static void
939
+ na_newdim(int argc, VALUE *argv, struct NARRAY *ary)
940
+ {
941
+ na_shape_t *shape;
942
+ int *count;
943
+ int i, j;
944
+
945
+ if (argc==0)
946
+ rb_raise(rb_eArgError, "Argument required");
947
+ if (ary->rank + argc > NA_MAX_RANK-1)
948
+ rb_raise(rb_eArgError, "Exceed maximum ranks");
949
+ if (ary->total==0)
950
+ rb_raise(rb_eRuntimeError, "cannot extend empty array");
951
+
952
+ /* count new rank */
953
+ count = ALLOCA_N(int,ary->rank+1);
954
+ for (i=0; i<=ary->rank; ++i)
955
+ count[i]=0;
956
+ for (i=0; i<argc; ++i) {
957
+ j = NUM2INT(argv[i]);
958
+ if (j<0) /* negative rank : -1=>append after last rank */
959
+ j += ary->rank+1;
960
+ if (j<0 || j>ary->rank) /* range check */
961
+ rb_raise(rb_eArgError, "rank out of range");
962
+ ++count[j];
963
+ }
964
+ /* extend shape shape */
965
+ shape = ALLOC_N(na_shape_t,ary->rank+argc);
966
+ for (j=i=0; i<ary->rank; ++i) {
967
+ while (count[i]-->0) shape[j++] = 1;
968
+ shape[j++] = ary->shape[i];
969
+ }
970
+ while (count[i]-->0) shape[j++] = 1;
971
+
972
+ /* exchange shape */
973
+ xfree(ary->shape);
974
+ ary->shape = shape;
975
+ ary->rank += argc;
976
+ }
977
+
978
+
979
+ /* method: newdim!(size1,size2,...,sizeN) */
980
+ static VALUE
981
+ na_newdim_bang(int argc, VALUE *argv, VALUE self)
982
+ {
983
+ struct NARRAY *ary;
984
+
985
+ GetNArray(self,ary);
986
+ na_newdim(argc, argv, ary);
987
+ return self;
988
+ }
989
+
990
+
991
+ /* method: newdim(size1,size2,...,sizeN) */
992
+ VALUE
993
+ na_newdim_ref(int argc, VALUE *argv, VALUE self)
994
+ {
995
+ struct NARRAY *ary;
996
+
997
+ GetNArray(self,ary);
998
+ ary = na_ref_alloc_struct(self);
999
+ na_newdim(argc, argv, ary);
1000
+ return na_wrap_struct(ary,self);
1001
+ }
1002
+
1003
+
1004
+ /* method: fill!(val) */
1005
+ VALUE na_fill(VALUE self, volatile VALUE val)
1006
+ {
1007
+ struct NARRAY *a1, *a2;
1008
+
1009
+ GetNArray(self,a1);
1010
+ val = na_cast_unless_narray(val,a1->type);
1011
+ GetNArray(val,a2);
1012
+
1013
+ if (a2->total != 1)
1014
+ rb_raise(rb_eArgError, "single-element argument required");
1015
+
1016
+ SetFuncs[a1->type][a2->type]( a1->total,
1017
+ a1->ptr, na_sizeof[a1->type],
1018
+ a2->ptr, 0 );
1019
+ return self;
1020
+ }
1021
+
1022
+
1023
+ /* method: indgen!([start,[step]]) */
1024
+ VALUE
1025
+ na_indgen(int argc, VALUE *argv, VALUE self)
1026
+ {
1027
+ na_shape_t start=0, step=1;
1028
+ struct NARRAY *ary;
1029
+
1030
+ if (argc>0) {
1031
+ start = NUM2SHAPE(argv[0]);
1032
+ if (argc==2)
1033
+ step = NUM2SHAPE(argv[1]);
1034
+ else
1035
+ if (argc>2)
1036
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for <= 2)", argc);
1037
+ }
1038
+
1039
+ GetNArray(self,ary);
1040
+ IndGenFuncs[ary->type]( ary->total,
1041
+ ary->ptr, na_sizeof[ary->type],
1042
+ start, step );
1043
+ return self;
1044
+ }
1045
+
1046
+
1047
+ /* method: where2
1048
+ idx_true, idx_false = narray.where2 */
1049
+ static VALUE
1050
+ na_where2(volatile VALUE obj)
1051
+ {
1052
+ VALUE v1, v0;
1053
+ na_shape_t n, i, n1, n0;
1054
+ char *c;
1055
+ int32_t *idx1, *idx0;
1056
+ struct NARRAY *ary, *a1, *a0; /* a1=true, a0=false */
1057
+
1058
+ GetNArray(obj,ary);
1059
+ /* Convert to NA_BYTE by calling "obj.ne(0)", if needed */
1060
+ if(ary->type != NA_BYTE) {
1061
+ obj = rb_funcall(obj, na_id_ne, 1, INT2FIX(0));
1062
+ GetNArray(obj,ary);
1063
+ }
1064
+ n = ary->total;
1065
+
1066
+ /* Count true */
1067
+ c = ary->ptr;
1068
+ n1 = 0;
1069
+ for (i=0; i<n; ++i)
1070
+ if (*(c++)) ++n1;
1071
+
1072
+ n0 = n-n1;
1073
+
1074
+ /* partially true and false */
1075
+ v1 = na_make_object( NA_LINT, 1, &n1, cNArray );
1076
+ GetNArray(v1,a1);
1077
+ idx1 = (int32_t*) a1->ptr;
1078
+ v0 = na_make_object( NA_LINT, 1, &n0, cNArray );
1079
+ GetNArray(v0,a0);
1080
+ idx0 = (int32_t*) a0->ptr;
1081
+
1082
+ /* Get Indices */
1083
+ c = ary->ptr;
1084
+ for ( i=0; i<n; ++i ) {
1085
+ if (*(c++))
1086
+ *(idx1++) = i;
1087
+ else
1088
+ *(idx0++) = i;
1089
+ }
1090
+
1091
+ return rb_assoc_new( v1, v0 );
1092
+ }
1093
+
1094
+
1095
+ /* method: where
1096
+ idx_true = narray.where */
1097
+ static VALUE
1098
+ na_where(VALUE self)
1099
+ {
1100
+ return RARRAY_PTR( na_where2(self) )[0];
1101
+ }
1102
+
1103
+
1104
+ /* iterator: each() */
1105
+ static VALUE
1106
+ na_each(VALUE obj)
1107
+ {
1108
+ na_shape_t i;
1109
+ int sz;
1110
+ VALUE v;
1111
+ struct NARRAY *ary;
1112
+ char *p;
1113
+ void (*func)();
1114
+
1115
+ GetNArray(obj,ary);
1116
+
1117
+ p = ary->ptr;
1118
+ sz = na_sizeof[ary->type];
1119
+ func = SetFuncs[NA_ROBJ][ary->type];
1120
+
1121
+ for ( i=ary->total; i-->0; ) {
1122
+ (*func)( 1, &v, 0, p, 0 );
1123
+ rb_yield(v);
1124
+ p += sz;
1125
+ }
1126
+ return Qnil;
1127
+ }
1128
+
1129
+
1130
+ /* iterator: collect() */
1131
+ static VALUE
1132
+ na_collect(VALUE obj1)
1133
+ {
1134
+ na_shape_t i;
1135
+ int sz;
1136
+ VALUE v, obj2;
1137
+ struct NARRAY *a1, *a2;
1138
+ char *p1, *p2;
1139
+ void (*get)(), (*set)();
1140
+
1141
+ GetNArray(obj1,a1);
1142
+ obj2 = na_make_object(a1->type, a1->rank, a1->shape, CLASS_OF(obj1));
1143
+ GetNArray(obj2,a2);
1144
+
1145
+ p1 = a1->ptr;
1146
+ p2 = a2->ptr;
1147
+ sz = na_sizeof[a1->type];
1148
+ get = SetFuncs[NA_ROBJ][a1->type];
1149
+ set = SetFuncs[a1->type][NA_ROBJ];
1150
+
1151
+ for ( i=a1->total; i-->0; ) {
1152
+ (*get)( 1, &v, 0, p1, 0 );
1153
+ v = rb_yield(v);
1154
+ (*set)( 1, p2, 0, &v, 0 );
1155
+ p1 += sz;
1156
+ p2 += sz;
1157
+ }
1158
+ return obj2;
1159
+ }
1160
+
1161
+
1162
+ /* iterator: collect!() */
1163
+ static VALUE
1164
+ na_collect_bang(VALUE self)
1165
+ {
1166
+ na_shape_t i;
1167
+ int sz;
1168
+ VALUE v;
1169
+ struct NARRAY *a1;
1170
+ char *p1;
1171
+ void (*get)(), (*set)();
1172
+
1173
+ GetNArray(self,a1);
1174
+
1175
+ p1 = a1->ptr;
1176
+ sz = na_sizeof[a1->type];
1177
+ get = SetFuncs[NA_ROBJ][a1->type];
1178
+ set = SetFuncs[a1->type][NA_ROBJ];
1179
+
1180
+ for ( i=a1->total; i-->0; ) {
1181
+ (*get)( 1, &v, 0, p1, 0 );
1182
+ v = rb_yield(v);
1183
+ (*set)( 1, p1, 0, &v, 0 );
1184
+ p1 += sz;
1185
+ }
1186
+ return self;
1187
+ }
1188
+
1189
+
1190
+ /* initialization of NArray Class */
1191
+ void
1192
+ Init_narray()
1193
+ {
1194
+
1195
+ ID id_Complex = rb_intern("Complex");
1196
+
1197
+ if (!rb_const_defined( rb_cObject, id_Complex)) {
1198
+ /* require Complex class */
1199
+ rb_require("complex");
1200
+ }
1201
+ cComplex = rb_const_get( rb_cObject, rb_intern("Complex") );
1202
+
1203
+ /* define NArray class */
1204
+ cNArray = rb_define_class("NArray",rb_cObject);
1205
+
1206
+ /* class methods */
1207
+ rb_define_singleton_method(cNArray,"new",na_s_new,-1);
1208
+ rb_define_singleton_method(cNArray,"byte",na_s_new_byte,-1);
1209
+ rb_define_singleton_method(cNArray,"sint",na_s_new_sint,-1);
1210
+ rb_define_singleton_method(cNArray,"lint",na_s_new_int,-1);
1211
+ rb_define_singleton_method(cNArray,"llint",na_s_new_llint,-1);
1212
+ rb_define_singleton_method(cNArray,"int", na_s_new_int,-1);
1213
+ rb_define_singleton_method(cNArray,"sfloat",na_s_new_sfloat,-1);
1214
+ rb_define_singleton_method(cNArray,"dfloat",na_s_new_float,-1);
1215
+ rb_define_singleton_method(cNArray,"float", na_s_new_float,-1);
1216
+ rb_define_singleton_method(cNArray,"scomplex",na_s_new_scomplex,-1);
1217
+ rb_define_singleton_method(cNArray,"dcomplex",na_s_new_complex,-1);
1218
+ rb_define_singleton_method(cNArray,"complex", na_s_new_complex,-1);
1219
+ rb_define_singleton_method(cNArray,"object",na_s_new_object,-1);
1220
+
1221
+ rb_define_singleton_method(cNArray,"to_na",na_s_to_na,-1);
1222
+ rb_define_singleton_method(cNArray,"to_narray",na_s_to_na,-1);
1223
+ rb_define_singleton_method(cNArray,"[]",na_s_bracket,-1);
1224
+
1225
+ /* methods */
1226
+ rb_define_method(cNArray, "shape", na_shape,0);
1227
+ rb_define_alias(cNArray, "sizes","shape");
1228
+ rb_define_method(cNArray, "size", na_size,0);
1229
+ rb_define_alias(cNArray, "total","size");
1230
+ rb_define_alias(cNArray, "length","size");
1231
+ rb_define_method(cNArray, "rank", na_rank,0);
1232
+ rb_define_alias(cNArray, "dim","rank");
1233
+ rb_define_alias(cNArray, "dimension","rank");
1234
+ rb_define_method(cNArray, "typecode", na_typecode,0);
1235
+ rb_define_method(cNArray, "element_size", na_element_size,0);
1236
+ rb_define_method(cNArray, "empty?", na_is_empty,0);
1237
+ rb_define_method(cNArray, "clone", na_clone,0);
1238
+ rb_define_alias(cNArray, "dup","clone");
1239
+ rb_define_method(cNArray, "inspect", na_inspect,0);
1240
+ rb_define_method(cNArray, "coerce", na_coerce,1);
1241
+ rb_define_method(cNArray, "reshape", na_reshape_ref,-1);
1242
+ rb_define_method(cNArray, "reshape!", na_reshape_bang,-1);
1243
+ rb_define_alias(cNArray, "shape=","reshape!");
1244
+ rb_define_method(cNArray, "newdim", na_newdim_ref,-1);
1245
+ rb_define_alias(cNArray, "newrank","newdim");
1246
+ rb_define_method(cNArray, "newdim!", na_newdim_bang,-1);
1247
+ rb_define_alias(cNArray, "newdim=","newdim!");
1248
+ rb_define_alias(cNArray, "newrank!","newdim!");
1249
+ rb_define_alias(cNArray, "newrank=","newdim!");
1250
+ rb_define_method(cNArray, "flatten", na_flatten_ref,0);
1251
+ rb_define_method(cNArray, "flatten!", na_flatten_bang,0);
1252
+ rb_define_method(cNArray, "fill!", na_fill,1);
1253
+ rb_define_alias(cNArray, "fill","fill!");
1254
+ rb_define_method(cNArray, "indgen!", na_indgen,-1);
1255
+ rb_define_alias(cNArray, "indgen","indgen!");
1256
+ rb_define_method(cNArray, "where", na_where, 0);
1257
+ rb_define_method(cNArray, "where2", na_where2, 0);
1258
+ rb_define_method(cNArray, "each", na_each,0);
1259
+ rb_define_method(cNArray, "collect", na_collect,0);
1260
+ rb_define_method(cNArray, "collect!", na_collect_bang,0);
1261
+ rb_define_alias(cNArray, "map", "collect");
1262
+ rb_define_alias(cNArray, "map!", "collect!");
1263
+ rb_define_method(cNArray, "to_s", na_to_s, 0);
1264
+ rb_define_method(cNArray, "to_f", na_to_float, 0);
1265
+ rb_define_method(cNArray, "to_i", na_to_integer, 0);
1266
+ rb_define_method(cNArray, "to_type", na_to_type, 1);
1267
+ rb_define_method(cNArray, "to_binary", na_to_binary, 0);
1268
+ rb_define_method(cNArray, "to_type_as_binary", na_to_type_as_binary, 1);
1269
+ rb_define_method(cNArray, "to_string", na_to_string, 0);
1270
+
1271
+ rb_define_const(cNArray, "NARRAY_VERSION", rb_str_new2(NARRAY_VERSION));
1272
+ rb_define_const(cNArray, "SUPPORT_BIGMEM", Qtrue);
1273
+ rb_define_const(cNArray, "BYTE", INT2FIX(NA_BYTE));
1274
+ rb_define_const(cNArray, "SINT", INT2FIX(NA_SINT));
1275
+ rb_define_const(cNArray, "LINT", INT2FIX(NA_LINT));
1276
+ rb_define_const(cNArray, "LLINT", INT2FIX(NA_LLINT));
1277
+ rb_define_const(cNArray, "INT", INT2FIX(NA_LINT));
1278
+ rb_define_const(cNArray, "SFLOAT", INT2FIX(NA_SFLOAT));
1279
+ rb_define_const(cNArray, "DFLOAT", INT2FIX(NA_DFLOAT));
1280
+ rb_define_const(cNArray, "FLOAT", INT2FIX(NA_DFLOAT));
1281
+ rb_define_const(cNArray, "SCOMPLEX", INT2FIX(NA_SCOMPLEX));
1282
+ rb_define_const(cNArray, "DCOMPLEX", INT2FIX(NA_DCOMPLEX));
1283
+ rb_define_const(cNArray, "COMPLEX", INT2FIX(NA_DCOMPLEX));
1284
+ rb_define_const(cNArray, "ROBJ", INT2FIX(NA_ROBJ));
1285
+ rb_define_const(cNArray, "OBJECT", INT2FIX(NA_ROBJ));
1286
+ rb_define_const(cNArray, "NONE", INT2FIX(NA_NONE));
1287
+ rb_define_const(cNArray, "CLASS_DIMENSION", INT2FIX(0));
1288
+ #ifdef WORDS_BIGENDIAN
1289
+ rb_define_const(cNArray, "ENDIAN", INT2FIX(1));
1290
+ #else
1291
+ #ifdef DYNAMIC_ENDIAN /* not supported yet */
1292
+ rb_define_const(cNArray, "ENDIAN", INT2FIX(-1));
1293
+ #else /* LITTLE_ENDIAN */
1294
+ rb_define_const(cNArray, "ENDIAN", INT2FIX(0));
1295
+ #endif
1296
+ #endif
1297
+ /* Reference */
1298
+ rb_define_singleton_method(cNArray, "refer", na_s_refer,1);
1299
+ rb_define_singleton_method(cNArray, "ref", na_s_refer,1);
1300
+ rb_define_method(cNArray, "refer", na_refer,0);
1301
+ rb_define_method(cNArray, "original", na_original,0);
1302
+
1303
+ Init_na_array();
1304
+ Init_na_index();
1305
+ Init_nmath();
1306
+ Init_na_funcs();
1307
+ Init_na_random();
1308
+
1309
+ cNArrayScalar = rb_define_class("NArrayScalar", cNArray);
1310
+
1311
+ na_id_beg = rb_intern("begin");
1312
+ na_id_end = rb_intern("end");
1313
+ na_id_exclude_end = rb_intern("exclude_end?");
1314
+ na_id_real = rb_intern("real");
1315
+ na_id_imag = rb_intern("imag");
1316
+ na_id_new = rb_intern("new");
1317
+ na_id_to_i = rb_intern("to_i");
1318
+ na_id_usec = rb_intern("usec");
1319
+ na_id_now = rb_intern("now");
1320
+ na_id_compare = rb_intern("<=>");
1321
+ na_id_ne = rb_intern("ne");
1322
+ na_id_and = rb_intern("&&");
1323
+ na_id_or = rb_intern("||");
1324
+ na_id_minus = rb_intern("-@");
1325
+ na_id_abs = rb_intern("abs");
1326
+ na_id_power = rb_intern("**");
1327
+ na_id_add = rb_intern("+");
1328
+ na_id_sbt = rb_intern("-");
1329
+ na_id_mul = rb_intern("*");
1330
+ na_id_div = rb_intern("/");
1331
+ na_id_mod = rb_intern("%");
1332
+ na_id_coerce_rev = rb_intern("coerce_rev");
1333
+ na_id_Complex = rb_intern("Complex");
1334
+
1335
+ na_id_class_dim = rb_intern("CLASS_DIMENSION");
1336
+
1337
+ Init_na_linalg();
1338
+
1339
+ /* NArray extention script */
1340
+ rb_require("narray_ext.rb");
1341
+ }