numru-narray 1.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,733 @@
1
+ require "mknafunc"
2
+
3
+ fname = "na_op.c"
4
+ $> = open(fname,"w")
5
+
6
+ upcast_ary = $upcast.collect{|i| ' {'+i.join(", ")+'}'}.join(",\n")
7
+
8
+ print <<EOM
9
+ /*
10
+ #{fname}
11
+ Automatically generated code
12
+ Numerical Array Extention for Ruby
13
+ (C) Copyright 1999-2008 by Masahiro TANAKA
14
+
15
+ This program is free software.
16
+ You can distribute/modify this program
17
+ under the same terms as Ruby itself.
18
+ NO WARRANTY.
19
+ */
20
+ #include <ruby.h>
21
+ #include "narray.h"
22
+ #include "narray_local.h"
23
+ /* isalpha(3) etc. */
24
+ #include <ctype.h>
25
+
26
+ const int na_upcast[NA_NTYPES][NA_NTYPES] = {
27
+ #{upcast_ary} };
28
+
29
+ const int na_no_cast[NA_NTYPES] =
30
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
31
+ const int na_cast_real[NA_NTYPES] =
32
+ { 0, 1, 2, 3, 4, 5, 6, 5, 6, 9 };
33
+ const int na_cast_comp[NA_NTYPES] =
34
+ { 0, 7, 7, 7, 7, 7, 8, 7, 8, 9 };
35
+ const int na_cast_round[NA_NTYPES] =
36
+ { 0, 1, 2, 3, 4, 3, 3, 7, 8, 9 };
37
+ const int na_cast_byte[NA_NTYPES] =
38
+ { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
39
+
40
+
41
+ static void TpErr(void) {
42
+ rb_raise(rb_eTypeError,"illegal operation with this type");
43
+ }
44
+ static int TpErrI(void) {
45
+ rb_raise(rb_eTypeError,"illegal operation with this type");
46
+ return 0;
47
+ }
48
+ static void na_zerodiv() {
49
+ rb_raise(rb_eZeroDivError, "divided by 0");
50
+ }
51
+
52
+ static int notnanF(float *n)
53
+ {
54
+ return *n == *n;
55
+ }
56
+ static int notnanD(double *n)
57
+ {
58
+ return *n == *n;
59
+ }
60
+ EOM
61
+
62
+
63
+ #
64
+ # Set Fucs
65
+ #
66
+ data = [
67
+ [/[O]/,/[O]/, "*p1 = *p2;"],
68
+ [/[O]/,/[BI]/, "*p1 = INT2FIX(*p2);"],
69
+ [/[O]/,/[L]/, "*p1 = INT2NUM(*p2);"],
70
+ [/[O]/,/[G]/, "*p1 = LL2NUM(*p2);"],
71
+ [/[O]/,/[FD]/, "*p1 = rb_float_new(*p2);"],
72
+ [/[O]/,/[XC]/, "*p1 = rb_complex_new(p2.r,p2.i);"],
73
+ [/[BIL]/,/[O]/, "*p1 = NUM2INT(*p2);"],
74
+ [/[G]/,/[O]/, "*p1 = NUM2LL(*p2);"],
75
+ [/[FD]/,/[O]/, "*p1 = NUM2DBL(*p2);"],
76
+ [/[XC]/,/[O]/, "p1.r = NUM2REAL(*p2); p1.i = NUM2IMAG(*p2);"],
77
+ [/[BILFDG]/,/[BILFDG]/,"*p1 = *p2;"],
78
+ [/[BILFDG]/,/[XC]/, "*p1 = p2.r;"],
79
+ [/[XC]/,/[BILFDG]/, "p1.r = *p2; p1.i = 0;"],
80
+ [/[XC]/,/[XC]/, "p1.r = p2.r; p1.i = p2.i;"] ]
81
+
82
+ $func_body =
83
+ "static void #name#CC(na_shape_t n, char *p1, na_shape_t i1, char *p2, na_shape_t i2)
84
+ {
85
+ int i;
86
+ #pragma omp parallel for
87
+ for (i=0; i<n; i++) {
88
+ OPERATION
89
+ }
90
+ }
91
+ "
92
+ mksetfuncs('Set','','',data)
93
+
94
+
95
+
96
+ #
97
+ # Unary Funcs
98
+ #
99
+ $func_body =
100
+ "static void #name#C(na_shape_t n, char *p1, na_shape_t i1, char *p2, na_shape_t i2)
101
+ {
102
+ int i;
103
+ #pragma omp parallel for
104
+ for (i=0; i<n; i++) {
105
+ OPERATION
106
+ }
107
+ }
108
+ "
109
+
110
+
111
+ mkfuncs('Swp', $swap_types, $swap_types,
112
+ [nil] +
113
+ ["*p1 = *p2;"] +
114
+ ["na_size16_t x; swap16(x,*p2); *p1 = x;"] +
115
+ ["na_size32_t x; swap32(x,*p2); *p1 = x;"] +
116
+ ["na_size64_t x; swap64(x,*p2); *p1 = x;"] +
117
+ ["na_size32_t x; swap32(x,*p2); *p1 = x;"] +
118
+ ["na_size64_t x; swap64(x,*p2); *p1 = x;"] +
119
+ ["na_size64_t x; swap64c(x,*p2); *p1 = x;"] +
120
+ ["na_size128_t x; swap128c(x,*p2); *p1 = x;"] +
121
+ ["*p1 = *p2;"]
122
+ )
123
+
124
+ print <<EOM
125
+
126
+ /* ------------------------- H2N --------------------------- */
127
+ #ifdef WORDS_BIGENDIAN
128
+
129
+ na_func_t H2NFuncs =
130
+ { TpErr, SetBB, SetII, SetLL, SetGG, SetFF, SetDD, SetXX, SetCC, SetOO };
131
+
132
+ na_func_t H2VFuncs =
133
+ { TpErr, SetBB, SwpI, SwpL, SwpG, SwpF, SwpD, SwpX, SwpC, SetOO };
134
+
135
+ #else
136
+ #ifdef DYNAMIC_ENDIAN /* not supported yet */
137
+ #else /* LITTLE ENDIAN */
138
+
139
+ na_func_t H2NFuncs =
140
+ { TpErr, SetBB, SwpI, SwpL, SwpG, SwpF, SwpD, SwpX, SwpC, SetOO };
141
+
142
+ na_func_t H2VFuncs =
143
+ { TpErr, SetBB, SetII, SetLL, SetGG, SetFF, SetDD, SetXX, SetCC, SetOO };
144
+
145
+ #endif
146
+ #endif
147
+ EOM
148
+
149
+ mkfuncs('Neg', $data_types, $data_types,
150
+ [nil] +
151
+ ["*p1 = -*p2;"]*6 +
152
+ ["p1.r = -p2.r;
153
+ p1.i = -p2.i;"]*2 +
154
+ ["*p1 = rb_funcall(*p2,na_id_minus,0);"]
155
+ )
156
+
157
+ # method: imag=
158
+ mkfuncs('ImgSet',$data_types,$real_types,
159
+ [nil]*7 +
160
+ ["p1.i = *p2;"]*2 +
161
+ [nil]
162
+ )
163
+
164
+
165
+ mkfuncs('Floor',$int_types,$data_types,[nil] +
166
+ ['copy']*4 +
167
+ ["*p1 = (typec)floor(*p2);"]*2 +
168
+ [nil]*3
169
+ )
170
+
171
+ mkfuncs('Ceil',$int_types,$data_types,[nil] +
172
+ ['copy']*4 +
173
+ ["*p1 = (typec)ceil(*p2);"]*2 +
174
+ [nil]*3
175
+ )
176
+
177
+ mkfuncs('Round',$int_types,$data_types,[nil] +
178
+ ['copy']*4 +
179
+ # ["*p1 = floor(*p2+0.5);"]*2 +
180
+ ["if (*p2 >= 0) *p1 = (typec)floor(*p2+0.5);
181
+ else *p1 = (typec)ceil(*p2-0.5);"]*2 +
182
+ [nil]*3
183
+ )
184
+
185
+ mkfuncs('Abs',$real_types,$data_types,[nil] +
186
+ ["*p1 = *p2;"] +
187
+ ["*p1 = (*p2<0) ? -*p2 : *p2;"]*5 +
188
+ ["*p1 = (typec)hypot(p2.r, p2.i);"]*2 +
189
+ ["*p1 = rb_funcall(*p2,na_id_abs,0);"]
190
+ )
191
+
192
+
193
+ mkfuncs('Real',$real_types,$data_types,[nil] +
194
+ ['copy']*8 +
195
+ [nil]
196
+ )
197
+
198
+ mkfuncs('Imag',$real_types,$data_types,[nil] +
199
+ ["*p1 = 0;"]*6 +
200
+ ["*p1 = p2.i;"]*2 +
201
+ [nil]
202
+ )
203
+
204
+ mkfuncs('Angl',$real_types,$data_types,[nil] +
205
+ [nil]*6 +
206
+ ["*p1 = atan2(p2.i,p2.r);"]*2 +
207
+ [nil]
208
+ )
209
+
210
+ mkfuncs('ImagMul',$comp_types,$data_types,[nil] +
211
+ [nil]*4 +
212
+ ["p1.r = 0; p1.i = *p2;"]*2 +
213
+ ["p1.r = -p2.i; p1.i = p2.r;"]*2 +
214
+ [nil]
215
+ )
216
+
217
+ mkfuncs('Conj',$data_types,$data_types,[nil] +
218
+ ['copy']*6 +
219
+ ["p1.r = p2.r; p1.i = -p2.i;"]*2 +
220
+ [nil]
221
+ )
222
+
223
+ mkfuncs('Not', [$data_types[1]]*10, $data_types,
224
+ [nil] +
225
+ ["*p1 = (*p2==0) ? 1:0;"]*6 +
226
+ ["*p1 = (p2.r==0 && p2.i==0) ? 1:0;"]*2 +
227
+ ["*p1 = RTEST(*p2) ? 0:1;"]
228
+ )
229
+
230
+ mkfuncs('BRv', $data_types, $data_types, [nil] +
231
+ ["*p1 = ~(*p2);"]*4 +
232
+ [nil]*4 +
233
+ ["*p1 = rb_funcall(*p2,'~',0);"]
234
+ )
235
+
236
+
237
+ mksortfuncs('Sort', $data_types, $data_types, [nil] +
238
+ ["
239
+ { if (*p1 > *p2) return 1;
240
+ if (*p1 < *p2) return -1;
241
+ return 0; }"]*6 +
242
+ [nil]*2 +
243
+ ["
244
+ { VALUE r = rb_funcall(*p1, na_id_compare, 1, *p2);
245
+ return NUM2INT(r); }"]
246
+ )
247
+
248
+ mksortfuncs('SortIdx', $data_types, $data_types, [nil] +
249
+ ["
250
+ { if (**p1 > **p2) return 1;
251
+ if (**p1 < **p2) return -1;
252
+ return 0; }"]*6 +
253
+ [nil]*2 +
254
+ ["
255
+ { VALUE r = rb_funcall(**p1, na_id_compare, 1, **p2);
256
+ return NUM2INT(r); }"]
257
+ )
258
+
259
+ $func_body =
260
+ "static void #name#C(na_shape_t n, char *p1, na_shape_t i1, char *p2, na_shape_t i2)
261
+ {
262
+ int i;
263
+ if (i1 != 0) {
264
+ #pragma omp parallel for
265
+ for (i=0; i<n; i++) {
266
+ OPERATION
267
+ }
268
+ } else {
269
+ // #pragma omp parallel for reduction(+:p1)
270
+ for (i=0; i<n; i++) {
271
+ OPERATION
272
+ }
273
+ }
274
+ }
275
+ "
276
+
277
+ mkfuncs('AddU', $data_types, $data_types,
278
+ [nil] +
279
+ ["*p1 += *p2;"]*6 +
280
+ ["p1.r += p2.r;
281
+ p1.i += p2.i;"]*2 +
282
+ ["*p1 = rb_funcall(*p1,'+',1,*p2);"]
283
+ )
284
+
285
+ mkfuncs('SbtU', $data_types, $data_types,
286
+ [nil] +
287
+ ["*p1 -= *p2;"]*6 +
288
+ ["p1.r -= p2.r;
289
+ p1.i -= p2.i;"]*2 +
290
+ ["*p1 = rb_funcall(*p1,'-',1,*p2);"]
291
+ )
292
+
293
+ mkfuncs('Min', $data_types, $data_types, [nil] +
294
+ ["if (*p1>*p2) *p1=*p2;"]*4 +
295
+ ["if (notnan#C((type1*)p2) && *p1>*p2) *p1=*p2;"]*2 +
296
+ [nil]*2 +
297
+ ["if (FIX2INT(rb_funcall(*p1,na_id_compare,1,*p2))>0) *p1=*p2;"]
298
+ )
299
+
300
+ mkfuncs('Max', $data_types, $data_types, [nil] +
301
+ ["if (*p1<*p2) *p1=*p2;"]*4 +
302
+ ["if (notnan#C((type1*)p2) && *p1<*p2) *p1=*p2;"]*2 +
303
+ [nil]*2 +
304
+ ["if (FIX2INT(rb_funcall(*p1,na_id_compare,1,*p2))<0) *p1=*p2;"]
305
+ )
306
+ $func_body =
307
+ "static void #name#C(na_shape_t n, char *p1, na_shape_t i1, char *p2, na_shape_t i2)
308
+ {
309
+ int i;
310
+ if (i1 != 0) {
311
+ #pragma omp parallel for
312
+ for (i=0; i<n; i++) {
313
+ OPERATION
314
+ }
315
+ } else {
316
+ // #pragma omp parallel for reduction(*:p1)
317
+ for (i=0; i<n; i++) {
318
+ OPERATION
319
+ }
320
+ }
321
+ }
322
+ "
323
+
324
+ mkfuncs('MulU', $data_types, $data_types,
325
+ [nil] +
326
+ ["*p1 *= *p2;"]*6 +
327
+ ["type1 x = *p1;
328
+ p1.r = x.r*p2.r - x.i*p2.i;
329
+ p1.i = x.r*p2.i + x.i*p2.r;"]*2 +
330
+ ["*p1 = rb_funcall(*p1,'*',1,*p2);"]
331
+ )
332
+
333
+ $func_body =
334
+ "static void #name#C(na_shape_t n, char *p1, na_shape_t i1, char *p2, na_shape_t i2)
335
+ {
336
+ int i;
337
+ if (i1 != 0) {
338
+ #pragma omp parallel for
339
+ for (i=0; i<n; i++) {
340
+ OPERATION
341
+ }
342
+ } else {
343
+ // #pragma omp parallel for reduction(/:p1)
344
+ for (i=0; i<n; i++) {
345
+ OPERATION
346
+ }
347
+ }
348
+ }
349
+ "
350
+
351
+ mkfuncs('DivU', $data_types, $data_types,
352
+ [nil] +
353
+ ["if (*p2==0) {na_zerodiv();}
354
+ *p1 /= *p2;"]*4 +
355
+ ["*p1 /= *p2;"]*2 +
356
+ ["type1 x = *p1;
357
+ typef a = p2.r*p2.r + p2.i*p2.i;
358
+ p1.r = (x.r*p2.r + x.i*p2.i)/a;
359
+ p1.i = (x.i*p2.r - x.r*p2.i)/a;"]*2 +
360
+ ["*p1 = rb_funcall(*p1,'/',1,*p2);"]
361
+ )
362
+
363
+ mkfuncs('ModU', $data_types, $data_types,
364
+ [nil] +
365
+ ["if (*p2==0) {na_zerodiv();}
366
+ *p1 %= *p2;"]*4 +
367
+ ["*p1 = fmod(*p1, *p2);"]*2 +
368
+ [nil]*2 +
369
+ ["*p1 = rb_funcall(*p1,'%',1,*p2);"]
370
+ )
371
+
372
+
373
+ # indgen
374
+ $func_body =
375
+ "static void #name#C(na_shape_t n, char *p1, na_shape_t i1, int p2, na_shape_t i2)
376
+ {
377
+ int i;
378
+ #pragma omp parallel for
379
+ for (i=0; i<n; i++) {
380
+ OPERATION
381
+ }
382
+ }
383
+ "
384
+ mkfuncs('IndGen',$data_types,[$data_types[3]]*9,
385
+ [nil] +
386
+ ["*p1 = (typef)p2;"]*6 +
387
+ ["p1.r = (typef)p2;
388
+ p1.i = 0;"]*2 +
389
+ ["*p1 = INT2FIX(p2);"]
390
+ )
391
+
392
+
393
+
394
+ $func_body =
395
+ "static void #name#C(na_shape_t n, char *p1, na_shape_t i1, char *p2, na_shape_t i2)
396
+ {
397
+ OPERATION
398
+ }
399
+ "
400
+ mkfuncs('ToStr',['']+[$data_types[9]]*9,$data_types,
401
+ [nil] +
402
+ ["char buf[22];
403
+ int i;
404
+ #pragma omp parallel for
405
+ for (i=0; i<n; i++) {
406
+ sprintf(buf,\"%i\",(int)*p2);
407
+ *p1 = rb_str_new2(buf);
408
+ }"]*4 +
409
+ ["char buf[24];
410
+ int i;
411
+ #pragma omp parallel for
412
+ for (i=0; i<n; i++) {
413
+ sprintf(buf,\"%.5g\",(double)*p2);
414
+ *p1 = rb_str_new2(buf);
415
+ }"] +
416
+ ["char buf[24];
417
+ int i;
418
+ #pragma omp parallel for
419
+ for (i=0; i<n; i++) {
420
+ sprintf(buf,\"%.8g\",(double)*p2);
421
+ *p1 = rb_str_new2(buf);
422
+ }"] +
423
+ ["char buf[50];
424
+ int i;
425
+ #pragma omp parallel for
426
+ for (i=0; i<n; i++) {
427
+ sprintf(buf,\"%.5g%+.5gi\",(double)p2.r,(double)p2.i);
428
+ *p1 = rb_str_new2(buf);
429
+ }"] +
430
+ ["char buf[50];
431
+ int i;
432
+ #pragma omp parallel for
433
+ for (i=0; i<n; i++) {
434
+ sprintf(buf,\"%.8g%+.8gi\",(double)p2.r,(double)p2.i);
435
+ *p1 = rb_str_new2(buf);
436
+ }"] +
437
+ ["int i;
438
+ #pragma omp parallel for
439
+ for (i=0; i<n; i++) {
440
+ *p1 = rb_obj_as_string(*p2);
441
+ }"]
442
+ )
443
+
444
+
445
+ print <<EOM
446
+
447
+ /* from numeric.c */
448
+ static void na_str_append_fp(char *buf)
449
+ {
450
+ if (buf[0]=='-' || buf[0]=='+') ++buf;
451
+ if (ISALPHA(buf[0])) return; /* NaN or Inf */
452
+ if (strchr(buf, '.') == 0) {
453
+ int len = strlen(buf);
454
+ char *ind = strchr(buf, 'e');
455
+ if (ind) {
456
+ memmove(ind+2, ind, len-(ind-buf)+1);
457
+ ind[0] = '.';
458
+ ind[1] = '0';
459
+ } else {
460
+ strcat(buf, ".0");
461
+ }
462
+ }
463
+ }
464
+ EOM
465
+
466
+ $func_body =
467
+ "static void #name#C(char *p1, char *p2)
468
+ {
469
+ OPERATION
470
+ }
471
+ "
472
+ mkfuncs('Insp',['']+[$data_types[9]]*9,$data_types,
473
+ [nil] +
474
+ ["char buf[22];
475
+ sprintf(buf,\"%i\",(int)*p2);
476
+ *p1 = rb_str_new2(buf);"]*4 +
477
+ ["char buf[24];
478
+ sprintf(buf,\"%g\",(double)*p2);
479
+ na_str_append_fp(buf);
480
+ *p1 = rb_str_new2(buf);"] +
481
+ ["char buf[24];
482
+ sprintf(buf,\"%g\",(double)*p2);
483
+ na_str_append_fp(buf);
484
+ *p1 = rb_str_new2(buf);"] +
485
+ ["char buf[50], *b;
486
+ sprintf(buf,\"%g\",(double)p2.r);
487
+ na_str_append_fp(buf);
488
+ b = buf+strlen(buf);
489
+ sprintf(b,\"%+g\",(double)p2.i);
490
+ na_str_append_fp(b);
491
+ strcat(buf,\"i\");
492
+ *p1 = rb_str_new2(buf);"] +
493
+ ["char buf[50], *b;
494
+ sprintf(buf,\"%g\",(double)p2.r);
495
+ na_str_append_fp(buf);
496
+ b = buf+strlen(buf);
497
+ sprintf(b,\"%+g\",(double)p2.i);
498
+ na_str_append_fp(b);
499
+ strcat(buf,\"i\");
500
+ *p1 = rb_str_new2(buf);"] +
501
+ ["*p1 = rb_inspect(*p2);"]
502
+ )
503
+
504
+
505
+
506
+ #
507
+ # Binary Funcs
508
+ #
509
+
510
+ =begin
511
+ # Optimize experiment
512
+ $func_body =
513
+ "static void #name#C(na_shape_t n, char *p1, na_shape_t i1, char *p2, na_shape_t i2, char *p3, na_shape_t i3)
514
+ {
515
+ na_shape_t i;
516
+ if (i1==sizeof(type1) && i2==sizeof(type1) && i3==sizeof(type1)) {
517
+ type1 *a1=p1, *a2=p2, *a3=p3;
518
+ for (i=0; n; --n,++i) {
519
+ *a1 = *a2 * *a3; +++a1;++a2;++a3;
520
+ }
521
+ } else
522
+ for (; n; --n) {
523
+ OPERATION
524
+ p1+=i1; p2+=i2; p3+=i3;
525
+ }
526
+ }
527
+ "
528
+ mkfuncs('MulB', $data_types, $data_types,
529
+ [nil] +
530
+ ["*p1 = *p2 * *p3;"]*5 + [nil]*3
531
+ )
532
+ =end
533
+
534
+ $func_body =
535
+ "static void #name#C(na_shape_t n, char *p1, na_shape_t i1, char *p2, na_shape_t i2, char *p3, na_shape_t i3)
536
+ {
537
+ int i;
538
+ #pragma omp parallel for
539
+ for (i=0; i<n; i++) {
540
+ OPERATION
541
+ }
542
+ }
543
+ "
544
+
545
+ mkfuncs('AddB', $data_types, $data_types,
546
+ [nil] +
547
+ ["*p1 = *p2 + *p3;"]*6 +
548
+ ["p1.r = p2.r + p3.r;
549
+ p1.i = p2.i + p3.i;"]*2 +
550
+ ["*p1 = rb_funcall(*p2,'+',1,*p3);"]
551
+ )
552
+
553
+ mkfuncs('SbtB', $data_types, $data_types,
554
+ [nil] +
555
+ ["*p1 = *p2 - *p3;"]*6 +
556
+ ["p1.r = p2.r - p3.r;
557
+ p1.i = p2.i - p3.i;"]*2 +
558
+ ["*p1 = rb_funcall(*p2,'-',1,*p3);"]
559
+ )
560
+
561
+ mkfuncs('MulB', $data_types, $data_types,
562
+ [nil] +
563
+ ["*p1 = *p2 * *p3;"]*6 +
564
+ ["type1 x = *p2;
565
+ p1.r = x.r*p3.r - x.i*p3.i;
566
+ p1.i = x.r*p3.i + x.i*p3.r;"]*2 +
567
+ ["*p1 = rb_funcall(*p2,'*',1,*p3);"]
568
+ )
569
+
570
+ mkfuncs('DivB', $data_types, $data_types,
571
+ [nil] +
572
+ ["if (*p3==0) {na_zerodiv();};
573
+ *p1 = *p2 / *p3;"]*4 +
574
+ ["*p1 = *p2 / *p3;"]*2 +
575
+ ["type1 x = *p2;
576
+ typef a = p3.r*p3.r + p3.i*p3.i;
577
+ p1.r = (x.r*p3.r + x.i*p3.i)/a;
578
+ p1.i = (x.i*p3.r - x.r*p3.i)/a;"]*2 +
579
+ ["*p1 = rb_funcall(*p2,'/',1,*p3);"]
580
+ )
581
+
582
+ mkfuncs('ModB', $data_types, $data_types,
583
+ [nil] +
584
+ ["if (*p3==0) {na_zerodiv();};
585
+ *p1 = *p2 % *p3;"]*4 +
586
+ ["*p1 = fmod(*p2, *p3);"]*2 +
587
+ [nil]*2 +
588
+ ["*p1 = rb_funcall(*p2,'%',1,*p3);"]
589
+ )
590
+
591
+
592
+ $func_body =
593
+ "static void #name#C(na_shape_t n, char *p1, na_shape_t i1, char *p2, na_shape_t i2, char *p3, na_shape_t i3)
594
+ {
595
+ int i;
596
+ if (i1 != 0) {
597
+ #pragma omp parallel for
598
+ for (i=0; i<n; i++) {
599
+ OPERATION
600
+ }
601
+ } else {
602
+ // #pragma omp parallel for reduction(+:p1)
603
+ for (i=0; i<n; i++) {
604
+ OPERATION
605
+ }
606
+ }
607
+ }
608
+ "
609
+
610
+ mkfuncs('MulAdd', $data_types, $data_types,
611
+ [nil] +
612
+ ["*p1 += *p2 * *p3;"]*6 +
613
+ ["type1 x = *p2;
614
+ p1.r += x.r*p3.r - x.i*p3.i;
615
+ p1.i += x.r*p3.i + x.i*p3.r;"]*2 +
616
+ ["*p1 = rb_funcall(*p1,'+',1,
617
+ rb_funcall(*p2,'*',1,*p3));"]
618
+ )
619
+
620
+ mkfuncs('MulSbt', $data_types, $data_types,
621
+ [nil] +
622
+ ["*p1 -= *p2 * *p3;"]*6 +
623
+ ["type1 x = *p2;
624
+ p1.r -= x.r*p3.r - x.i*p3.i;
625
+ p1.i -= x.r*p3.i + x.i*p3.r;"]*2 +
626
+ ["*p1 = rb_funcall(*p1,'-',1,
627
+ rb_funcall(*p2,'*',1,*p3));"]
628
+ )
629
+
630
+
631
+ #
632
+ # Bit operator
633
+ #
634
+
635
+ mkfuncs('BAn', $data_types, $data_types,
636
+ [nil] +
637
+ ["*p1 = *p2 & *p3;"]*4 +
638
+ [nil]*4 +
639
+ ["*p1 = rb_funcall(*p2,'&',1,*p3);"]
640
+ )
641
+
642
+ mkfuncs('BOr', $data_types, $data_types,
643
+ [nil] +
644
+ ["*p1 = *p2 | *p3;"]*4 +
645
+ [nil]*4 +
646
+ ["*p1 = rb_funcall(*p2,'|',1,*p3);"]
647
+ )
648
+
649
+ mkfuncs('BXo', $data_types, $data_types,
650
+ [nil] +
651
+ ["*p1 = *p2 ^ *p3;"]*4 +
652
+ [nil]*4 +
653
+ ["*p1 = rb_funcall(*p2,'^',1,*p3);"]
654
+ )
655
+
656
+
657
+ #
658
+ # Comparison
659
+ #
660
+
661
+ mkfuncs('Eql', [$data_types[1]]*10, $data_types,
662
+ [nil] +
663
+ ["*p1 = (*p2==*p3) ? 1:0;"]*6 +
664
+ ["*p1 = (p2.r==p3.r) && (p2.i==p3.i) ? 1:0;"]*2 +
665
+ ["*p1 = RTEST(rb_equal(*p2, *p3)) ? 1:0;"]
666
+ )
667
+
668
+ mkfuncs('Cmp', [$data_types[1]]*10, $data_types,
669
+ [nil] +
670
+ ["if (*p2>*p3) *p1=1;
671
+ else if (*p2<*p3) *p1=2;
672
+ else *p1=0;"]*6 +
673
+ [nil]*2 +
674
+ ["int v = NUM2INT(rb_funcall(*p2,na_id_compare,1,*p3));
675
+ if (v>0) *p1=1; else if (v<0) *p1=2; else *p1=0;"]
676
+ )
677
+
678
+ mkfuncs('And', [$data_types[1]]*10, $data_types,
679
+ [nil] +
680
+ ["*p1 = (*p2!=0 && *p3!=0) ? 1:0;"]*6 +
681
+ ["*p1 = ((p2.r!=0||p2.i!=0) && (p3.r!=0||p3.i!=0)) ? 1:0;"]*2 +
682
+ ["*p1 = (RTEST(*p2) && RTEST(*p3)) ? 1:0;"]
683
+ )
684
+
685
+ mkfuncs('Or_', [$data_types[1]]*10, $data_types,
686
+ [nil] +
687
+ ["*p1 = (*p2!=0 || *p3!=0) ? 1:0;"]*6 +
688
+ ["*p1 = ((p2.r!=0||p2.i!=0) || (p3.r!=0||p3.i!=0)) ? 1:0;"]*2 +
689
+ ["*p1 = (RTEST(*p2) || RTEST(*p3)) ? 1:0;"]
690
+ )
691
+
692
+ mkfuncs('Xor', [$data_types[1]]*10, $data_types,
693
+ [nil] +
694
+ ["*p1 = ((*p2!=0) == (*p3!=0)) ? 0:1;"]*6 +
695
+ ["*p1 = ((p2.r!=0||p2.i!=0) == (p3.r!=0||p3.i!=0)) ? 0:1;"]*2 +
696
+ ["*p1 = (RTEST(*p2) == RTEST(*p3)) ? 0:1;"]
697
+ )
698
+
699
+
700
+ #
701
+ # Atan2
702
+ #
703
+
704
+ mkfuncs('atan2', $data_types, $data_types,
705
+ [nil]*5 +
706
+ ["*p1 = atan2(*p2, *p3);"]*2 +
707
+ [nil]*3
708
+ )
709
+
710
+
711
+ #
712
+ # Mask
713
+ #
714
+ $func_body =
715
+ "static void #name#C(na_shape_t n, char *p1, na_shape_t i1, char *p2, na_shape_t i2, char *p3, na_shape_t i3)
716
+ {
717
+ int i, j=0;
718
+ for (i=0; i<n; i++) {
719
+ OPERATION
720
+ }
721
+ }
722
+ "
723
+ mkfuncs('RefMask',$data_types,$data_types,
724
+ [nil] +
725
+ ["if (*(u_int8_t*)p3) { *p1=*p2; j+=1; }"]*9,
726
+ ["j","i","i"]
727
+ )
728
+
729
+ mkfuncs('SetMask',$data_types,$data_types,
730
+ [nil] +
731
+ ["if (*(u_int8_t*)p3) { *p1=*p2; j+=1; };"]*9,
732
+ ["i","j","i"]
733
+ )