numru-narray 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ )