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,792 @@
1
+ require "mknafunc"
2
+
3
+ # File name
4
+ fname = "na_math.c"
5
+ $> = open(fname,"w")
6
+
7
+ print <<EOM
8
+ /*
9
+ #{fname}
10
+ Automatically generated code
11
+ Numerical Array Extention for Ruby
12
+ (C) Copyright 1999-2008 by Masahiro TANAKA
13
+
14
+ This program is free software.
15
+ You can distribute/modify this program
16
+ under the same terms as Ruby itself.
17
+ NO WARRANTY.
18
+ */
19
+ #include <ruby.h>
20
+ #include "narray.h"
21
+ #include "narray_local.h"
22
+
23
+ #ifndef M_LOG2E
24
+ #define M_LOG2E 1.4426950408889634074
25
+ #endif
26
+ #ifndef M_LOG10E
27
+ #define M_LOG10E 0.43429448190325182765
28
+ #endif
29
+
30
+ VALUE rb_mNMath;
31
+
32
+ static void TpErr(void) {
33
+ rb_raise(rb_eTypeError,"illegal operation with this type");
34
+ }
35
+
36
+ #if 0
37
+ void sincos(double x, double *s, double *c)
38
+ {
39
+ *s=sin(x); *c=cos(x);
40
+ }
41
+
42
+ #ifndef HAVE_ACOSH
43
+ static double rb_log1p (const double x)
44
+ {
45
+ double y;
46
+ y = 1+x;
47
+
48
+ if (y==1)
49
+ return x;
50
+ else
51
+ return log(y)*(x/(y-1));
52
+ }
53
+
54
+ static double zero=0;
55
+
56
+ static double acosh(double x)
57
+ {
58
+ /* acosh(x) = log(x+sqrt(x*x-1)) */
59
+ if (x>2) {
60
+ return log(2*x-1/(sqrt(x*x-1)+x));
61
+ } else if (x>=1) {
62
+ x-=1;
63
+ return rb_log1p(x+sqrt(2*x+x*x));
64
+ }
65
+ return zero/(x-x); /* x<1: NaN */
66
+ }
67
+
68
+ static double asinh(double x)
69
+ {
70
+ double a, x2;
71
+ int neg;
72
+
73
+ /* asinh(x) = log(x+sqrt(x*x+1)) */
74
+ neg = x<0;
75
+ if (neg) {x=-x;}
76
+ x2 = x*x;
77
+
78
+ if (x>2) {
79
+ a = log(2*x+1/(x+sqrt(x2+1)));
80
+ } else {
81
+ a = rb_log1p(x+x2/(1+sqrt(x2+1)));
82
+ }
83
+ if (neg) {a=-a;}
84
+ return a;
85
+ }
86
+
87
+ static double atanh(double x)
88
+ {
89
+ double a, x2;
90
+ int neg;
91
+
92
+ /* atanh(x) = 0.5*log((1+x)/(1-x)) */
93
+ neg = x<0;
94
+ if (neg) {x=-x;}
95
+ x2 = x*2;
96
+
97
+ if (x<0.5) {
98
+ a = 0.5*rb_log1p(x2+x2*x/(1-x));
99
+ } else if (x<1) {
100
+ a = 0.5*rb_log1p(x2/(1-x));
101
+ } else if (x==1) {
102
+ a = 1/zero; /* Infinity */
103
+ } else {
104
+ return zero/(x-x); /* x>1: NaN */
105
+ }
106
+ if (neg) {a=-a;}
107
+ return a;
108
+ }
109
+ #endif
110
+ #endif
111
+
112
+ static void squareX(scomplex *x) {
113
+ float r=x->r;
114
+ x->r = r*r - x->i*x->i;
115
+ x->i = 2*r*x->i;
116
+ }
117
+
118
+ static void squareC(dcomplex *x) {
119
+ double r=x->r;
120
+ x->r = r*r - x->i*x->i;
121
+ x->i = 2*r*x->i;
122
+ }
123
+
124
+
125
+ static void mulX(scomplex *x, scomplex *y) {
126
+ scomplex z=*x;
127
+ x->r = z.r*y->r - z.i*y->i;
128
+ x->i = z.r*y->i + z.i*y->r;
129
+ }
130
+
131
+ static void mulC(dcomplex *x, dcomplex *y) {
132
+ dcomplex z=*x;
133
+ x->r = z.r*y->r - z.i*y->i;
134
+ x->i = z.r*y->i + z.i*y->r;
135
+ }
136
+
137
+
138
+ static void divX(scomplex *p1, scomplex *p2) {
139
+ scomplex x = *p1;
140
+ float a = p2->r*p2->r + p2->i*p2->i;
141
+ p1->r = (x.r*p2->r + x.i*p2->i)/a;
142
+ p1->i = (x.i*p2->r - x.r*p2->i)/a;
143
+ }
144
+
145
+ static void divC(dcomplex *p1, dcomplex *p2) {
146
+ dcomplex x = *p1;
147
+ double a = p2->r*p2->r + p2->i*p2->i;
148
+ p1->r = (x.r*p2->r + x.i*p2->i)/a;
149
+ p1->i = (x.i*p2->r - x.r*p2->i)/a;
150
+ }
151
+
152
+
153
+ static scomplex recipX(scomplex z)
154
+ {
155
+ scomplex r;
156
+ float n;
157
+
158
+ if ( (z.r<0 ? -z.r:z.r) > (z.i<0 ? -z.i:z.i) ) {
159
+ r.i = z.i/z.r;
160
+ n = (1+r.i*r.i)*z.r;
161
+ r.r = 1/n;
162
+ r.i /= -n;
163
+ } else {
164
+ r.r = z.r/z.i;
165
+ n = (1+r.r*r.r)*z.i;
166
+ r.r /= n;
167
+ r.i = -1/n;
168
+ }
169
+ return r;
170
+ }
171
+
172
+ static dcomplex recipC(dcomplex z)
173
+ {
174
+ dcomplex r;
175
+ double n;
176
+
177
+ if ( (z.r<0 ? -z.r:z.r) > (z.i<0 ? -z.i:z.i) ) {
178
+ r.i = z.i/z.r;
179
+ n = (1+r.i*r.i)*z.r;
180
+ r.r = 1/n;
181
+ r.i /= -n;
182
+ } else {
183
+ r.r = z.r/z.i;
184
+ n = (1+r.r*r.r)*z.i;
185
+ r.r /= n;
186
+ r.i = -1/n;
187
+ }
188
+ return r;
189
+ }
190
+
191
+
192
+ static int powInt(int x, int p)
193
+ {
194
+ int r=1;
195
+
196
+ switch(p) {
197
+ case 2: return x*x;
198
+ case 3: return x*x*x;
199
+ case 1: return x;
200
+ case 0: return 1;
201
+ }
202
+ if (p<0) return 0;
203
+ /* if(p>3) */
204
+ while (p) {
205
+ if ( (p%2) == 1 ) r *= x;
206
+ x *= x;
207
+ p /= 2;
208
+ }
209
+ return r;
210
+ }
211
+
212
+
213
+ static float powFi(float x, int p)
214
+ {
215
+ float r=1;
216
+
217
+ switch(p) {
218
+ case 2: return x*x;
219
+ case 3: return x*x*x;
220
+ case 1: return x;
221
+ case 0: return 1;
222
+ }
223
+ if (p<0) return 1/powFi(x,-p);
224
+ /* if(p>3) */
225
+ while (p) {
226
+ if ( (p%2) == 1 ) r *= x;
227
+ x *= x;
228
+ p /= 2;
229
+ }
230
+ return r;
231
+ }
232
+
233
+
234
+ static double powDi(double x, int p)
235
+ {
236
+ double r=1;
237
+
238
+ switch(p) {
239
+ case 2: return x*x;
240
+ case 3: return x*x*x;
241
+ case 1: return x;
242
+ case 0: return 1;
243
+ }
244
+ if (p<0) return 1/powDi(x,-p);
245
+ /* if(p>3) */
246
+ while (p) {
247
+ if ( (p%2) == 1 ) r *= x;
248
+ x *= x;
249
+ p /= 2;
250
+ }
251
+ return r;
252
+ }
253
+
254
+
255
+ static scomplex powXi(scomplex *x, int p)
256
+ {
257
+ scomplex y=*x, r={1,0};
258
+
259
+ if (p==2) { squareX(&y); return y; }
260
+ if (p==1) { return y; }
261
+ if (p==0) { return r; }
262
+ if (p<0) {
263
+ y = powXi(x,-p);
264
+ return recipX(y);
265
+ }
266
+ /* if (p>2) */
267
+ while (p) {
268
+ if ( (p%2) == 1 ) mulX(&r,&y);
269
+ squareX(&y);
270
+ p /= 2;
271
+ }
272
+ return r;
273
+ }
274
+
275
+ static dcomplex powCi(dcomplex *x, int p)
276
+ {
277
+ dcomplex y=*x, r={1,0};
278
+
279
+ if (p==2) { squareC(&y); return y; }
280
+ if (p==1) { return y; }
281
+ if (p==0) { return r; }
282
+ if (p<0) {
283
+ y = powCi(x,-p);
284
+ return recipC(y);
285
+ }
286
+ /* if (p>2) */
287
+ while (p) {
288
+ if ( (p%2) == 1 ) mulC(&r,&y);
289
+ squareC(&y);
290
+ p /= 2;
291
+ }
292
+ return r;
293
+ }
294
+
295
+
296
+ EOM
297
+
298
+ data = [
299
+ ['sqrt',
300
+ [nil]*5 +
301
+ ["{ *p1 = sqrt(*p2); }"]*2 +
302
+ ["{
303
+ typer xr=p2->r/2, xi=p2->i/2, r=hypot(xr,xi);
304
+ if (xr>0) {
305
+ p1->r = sqrt(r+xr);
306
+ p1->i = xi/p1->r;
307
+ } else if ( (r-=xr) ) {
308
+ p1->i = (xi>=0) ? sqrt(r):-sqrt(r);
309
+ p1->r = xi/p1->i;
310
+ } else {
311
+ p1->r = p1->i = 0;
312
+ }
313
+ }"]*2 +
314
+ [nil] ],
315
+
316
+ ['sin',
317
+ [nil]*5 +
318
+ ["{ *p1 = sin(*p2); }"]*2 +
319
+ ["{
320
+ p1->r = sin(p2->r)*cosh(p2->i);
321
+ p1->i = cos(p2->r)*sinh(p2->i); }"]*2 +
322
+ [nil] ],
323
+
324
+ ['cos',
325
+ [nil]*5 +
326
+ ["{ *p1 = cos(*p2); }"]*2 +
327
+ ["{
328
+ p1->r = cos(p2->r)*cosh(p2->i);
329
+ p1->i = -sin(p2->r)*sinh(p2->i); }"]*2 +
330
+ [nil] ],
331
+
332
+ ['tan',
333
+ [nil]*5 +
334
+ ["{ *p1 = tan(*p2); }"]*2 +
335
+ ["{
336
+ typer d, th;
337
+ p1->i = th = tanh(2*p2->i);
338
+ p1->r = sqrt(1-th*th); /* sech */
339
+ d = 1 + cos(2*p2->r) * p1->r;
340
+ p1->r *= sin(2*p2->r)/d;
341
+ p1->i /= d;
342
+ }"]*2 +
343
+ [nil] ],
344
+
345
+ ['sinh',
346
+ [nil]*5 +
347
+ ["{ *p1 = sinh(*p2); }"]*2 +
348
+ ["{
349
+ p1->r = sinh(p2->r)*cos(p2->i);
350
+ p1->i = cosh(p2->r)*sin(p2->i);
351
+ }"]*2 +
352
+ [nil] ],
353
+
354
+ ['cosh',
355
+ [nil]*5 +
356
+ ["{ *p1 = cosh(*p2); }"]*2 +
357
+ ["{
358
+ p1->r = cosh(p2->r)*cos(p2->i);
359
+ p1->i = sinh(p2->r)*sin(p2->i);
360
+ }"]*2 +
361
+ [nil] ],
362
+
363
+ ['tanh',
364
+ [nil]*5 +
365
+ ["{ *p1 = tanh(*p2); }"]*2 +
366
+ ["{
367
+ typer d, th;
368
+ p1->r = th = tanh(2*p2->r);
369
+ p1->i = sqrt(1-th*th); /* sech */
370
+ d = 1 + cos(2*p2->i) * p1->i;
371
+ p1->r /= d;
372
+ p1->i *= sin(2*p2->i)/d;
373
+ }"]*2 +
374
+ [nil] ],
375
+
376
+ ['exp',
377
+ [nil]*5 +
378
+ ["{ *p1 = exp(*p2); }"]*2 +
379
+ ["{
380
+ typer a = exp(p2->r);
381
+ p1->r = a*cos(p2->i);
382
+ p1->i = a*sin(p2->i);
383
+ }"]*2 +
384
+ [nil] ],
385
+
386
+ ['log',
387
+ [nil]*5 +
388
+ ["{ *p1 = log(*p2); }"]*2 +
389
+ ["{
390
+ typed x = *p2;
391
+ p1->r = log(hypot(x.r, x.i));
392
+ p1->i = atan2(x.i, x.r);
393
+ }"]*2 +
394
+ [nil] ],
395
+
396
+ ['log10',
397
+ [nil]*5 +
398
+ ["{ *p1 = log10(*p2); }"]*2 +
399
+ ["{
400
+ log#code(p1,p2);
401
+ p1->r *= (typer)M_LOG10E;
402
+ p1->i *= (typer)M_LOG10E;
403
+ }"]*2 +
404
+ [nil] ],
405
+
406
+
407
+ ['log2',
408
+ [nil]*5 +
409
+ ["{ *p1 = log(*p2)*M_LOG2E; }"]*2 +
410
+ ["{
411
+ log#code(p1,p2);
412
+ p1->r *= (typer)M_LOG2E;
413
+ p1->i *= (typer)M_LOG2E;
414
+ }"]*2 +
415
+ [nil] ],
416
+
417
+
418
+ ['asin',
419
+ [nil]*5 +
420
+ ["{ *p1 = asin(*p2); }"]*2 +
421
+ # -i * log( sqrt(1-x**2) + x*i )
422
+ ["{
423
+ typed x = *p2;
424
+ square#code(&x);
425
+ x.r = 1 - x.r;
426
+ x.i = - x.i;
427
+ sqrt#code(&x,&x);
428
+ x.r -= p2->i;
429
+ x.i += p2->r;
430
+ log#code(&x,&x);
431
+ p1->r = x.i;
432
+ p1->i = -x.r;
433
+ }"]*2 +
434
+ [nil]*1 ],
435
+
436
+ ['asinh',
437
+ [nil]*5 +
438
+ ["{ *p1 = asinh(*p2); }"]*2 +
439
+ # log(sqrt(x**2+1)+x)
440
+ ["{
441
+ typed x = *p2;
442
+ square#code(&x);
443
+ x.r += 1;
444
+ sqrt#code(&x,&x);
445
+ x.r += p2->r;
446
+ x.i += p2->i;
447
+ log#code(p1,&x);
448
+ }"]*2 +
449
+ [nil]*1 ],
450
+
451
+ ['acos',
452
+ [nil]*5 +
453
+ ["{ *p1 = acos(*p2); }"]*2 +
454
+ # -i * log( sqrt(1-x**2)*i + x )
455
+ ["{
456
+ typed x = *p2;
457
+ typer tmp;
458
+ square#code(&x);
459
+ x.r = 1 - x.r;
460
+ x.i = - x.i;
461
+ sqrt#code(&x,&x);
462
+ tmp = x.r + p2->i;
463
+ x.r = -x.i + p2->r;
464
+ x.i = tmp;
465
+ log#code(&x,&x);
466
+ p1->r = x.i;
467
+ p1->i = -x.r;
468
+ }"]*2 +
469
+ [nil]*1 ],
470
+
471
+ ['acosh',
472
+ [nil]*5 +
473
+ ["{ *p1 = acosh(*p2); }"]*2 +
474
+ # log(x+sqrt(x**2-1))
475
+ ["{
476
+ typed x = *p2;
477
+ square#code(&x);
478
+ x.r -= 1;
479
+ sqrt#code(&x,&x);
480
+ x.r += p2->r;
481
+ x.i += p2->i;
482
+ log#code(p1,&x);
483
+ }"]*2 +
484
+ [nil]*1 ],
485
+
486
+ ['atan',
487
+ [nil]*5 +
488
+ ["{ *p1 = atan(*p2); }"]*2 +
489
+ # i/2 * log((i+x)/(i-x))
490
+ ["{
491
+ typed x,y;
492
+ x.r=-p2->r; x.i=1-p2->i;
493
+ y.r= p2->r; y.i=1+p2->i;
494
+ div#code((void*)&y,(void*)&x);
495
+ log#code((void*)&x,(void*)&y);
496
+ p1->r = -x.i/2;
497
+ p1->i = x.r/2;
498
+ }"]*2 +
499
+ [nil]*1 ],
500
+
501
+ ['atanh',
502
+ [nil]*5 +
503
+ ["{ *p1 = atanh(*p2); }"]*2 +
504
+ # 1/2 * log((1+x)/(1-x))
505
+ ["{
506
+ typed x,y;
507
+ x.r=1-p2->r; x.i=-p2->i;
508
+ y.r=1+p2->r; y.i= p2->i;
509
+ div#code((void*)&y,(void*)&x);
510
+ log#code((void*)&x,(void*)&y);
511
+ p1->r = x.r/2;
512
+ p1->i = x.i/2;
513
+ }"]*2 +
514
+ [nil]*1 ] ]
515
+
516
+
517
+
518
+ def mkmathfuncs(bsname,func)
519
+
520
+ print "
521
+ /* ------------------------- #{bsname} --------------------------- */\n"
522
+ c = $type_codes
523
+ tr = $real_types
524
+ td = $data_types
525
+ name = bsname
526
+
527
+ # Function Definition
528
+ head = "static void #{name}#code(void *p1, void *p2)"
529
+ for i in 0...c.size
530
+ if func[i] != nil && func[i]=~/^\{/
531
+ f = func[i].
532
+ gsub(/p1->/,"((#{td[i]}*)p1)->").
533
+ gsub(/p2->/,"((#{td[i]}*)p2)->").
534
+ gsub(/\*p1/,"*(#{td[i]}*)p1").
535
+ gsub(/\*p2/,"*(#{td[i]}*)p2").
536
+ gsub(/typer/, tr[i]).
537
+ gsub(/typed/, td[i])
538
+ puts( (head+f).gsub(/#code/,c[i]) )
539
+ end
540
+ end
541
+
542
+ # Function Array
543
+
544
+ print "\nna_mathfunc_t #{name}Funcs =\n{ "
545
+ m = []
546
+ for i in 0...c.size
547
+ if func[i] == nil
548
+ m += ['TpErr']
549
+ elsif func[i]=='copy'
550
+ m += ['Set'+c[i]*2]
551
+ elsif !( func[i] =~ /^\{/ )
552
+ m += [func[i]]
553
+ else
554
+ m += [name+c[i]]
555
+ end
556
+ end
557
+ print m.join(", ")+" };\n"
558
+
559
+ end
560
+
561
+
562
+ # Function Definitions
563
+ for i in data
564
+ mkmathfuncs( i[0], i[1] )
565
+ end
566
+
567
+
568
+ #
569
+ # Recip
570
+ #
571
+ $func_body =
572
+ "static void #name#C(int n, char *p1_0, int i1, char *p2_0, int i2)
573
+ {
574
+ type1* p1 = (type1*) p1_0;
575
+ typec* p2 = (typec*) p2_0;
576
+ int i;
577
+
578
+ #pragma omp parallel for
579
+ for (i=0; i<n; i++) {
580
+ OPERATION
581
+ }
582
+ }
583
+ "
584
+ mkfuncs('Rcp', $data_types, $data_types,
585
+ [nil] +
586
+ ["p1[i] = 1/(p2[i]);"]*6 +
587
+ ["p1[i] = recip#C(p2[i]);"]*2 +
588
+ ["p1[i] = rb_funcall(INT2FIX(1),na_id_div,1,p2[i]);"]
589
+ )
590
+
591
+
592
+ #
593
+ # Power
594
+ #
595
+ def mkpowfuncs(name,funcs)
596
+
597
+ print "
598
+ /* ------------------------- #{name} --------------------------- */\n"
599
+ c = $type_codes
600
+ n = $type_codes.size
601
+ td = $data_types
602
+ tr = $real_types
603
+
604
+ # Function Definition
605
+
606
+ for i in 0...n
607
+ for j in 0...n
608
+ funcs.each do |k|
609
+ if c[i]=~k[0] && c[j]=~k[1]
610
+ tu = $data_types[$upcast[i][j]]
611
+ f = k[2].
612
+ gsub(/p1->/,"((#{tu}*)p1)->").
613
+ gsub(/p2->/,"((#{td[i]}*)p2)->").
614
+ gsub(/p3->/,"((#{td[j]}*)p3)->").
615
+ gsub(/\*p1/,"*(#{tu}*)p1").
616
+ gsub(/\*p2/,"*(#{td[i]}*)p2").
617
+ gsub(/\*p3/,"*(#{td[j]}*)p3").
618
+ gsub(/typed/,td[i]).
619
+ gsub(/typef/,tr[i])
620
+ puts $func_body.
621
+ gsub(/#t1/,tu).
622
+ gsub(/#t2/,td[i]).
623
+ gsub(/#t3/,td[j]).
624
+ gsub(/#name/,name).
625
+ sub(/OPERATION/,f).
626
+ gsub(/#CC/,c[i]+c[j]).
627
+ gsub(/#C/, c[i])
628
+ end
629
+ end
630
+ end
631
+ end
632
+
633
+ # function pointer array
634
+ print "\nna_setfunc_t "+name+"Funcs = {\n"
635
+ m = []
636
+ for i in 0...n
637
+ l = []
638
+ for j in 0...n
639
+ f = true
640
+ for k in funcs
641
+ if c[i]=~k[0] && c[j]=~k[1]
642
+ l += [name+c[i]+c[j]]
643
+ f = false
644
+ break
645
+ end
646
+ end
647
+ if f
648
+ l += ['TpErr']
649
+ end
650
+ end
651
+ m += [' { '+l.join(', ')+' }']
652
+ end
653
+ print m.join(",\n")+"\n};\n"
654
+
655
+ end
656
+
657
+ $func_body =
658
+ "static void #name#CC(int n, char *p1, int i1, char *p2, int i2, char *p3, int i3)
659
+ {
660
+ for (; n; --n) {
661
+ OPERATION
662
+ p1+=i1; p2+=i2; p3+=i3;
663
+ }
664
+ }
665
+ "
666
+ mkpowfuncs('Pow',
667
+ [
668
+ [/[O]/,/[O]/, "*p1 = rb_funcall(*p2,na_id_power,1,*p3);"],
669
+ [/[BILG]/,/[BILG]/,"*p1 = powInt(*p2,*p3);"],
670
+ [/[FD]/,/[BILG]/, "*p1 = pow#Ci(*p2,*p3);"],
671
+ [/[BILGFD]/,/[FD]/,"*p1 = pow(*p2,*p3);"],
672
+ [/[XC]/,/[BILG]/, "*p1 = pow#Ci((typed*)p2,*p3);"],
673
+ [/[XC]/,/[FD]/,
674
+ "typed r;
675
+ if (*p3==0)
676
+ { p1->r=1; p1->i=0; } else
677
+ if (p2->r==0 && p2->i==0 && *p3>0)
678
+ { p1->r=0; p1->i=0; } else {
679
+ log#C(&r, p2);
680
+ r.r *= *p3;
681
+ r.i *= *p3;
682
+ exp#C(p1, &r); }"],
683
+ [/[XC]/,/[XC]/,
684
+ "typed l, r;
685
+ if (p3->r==0 && p3->i==0)
686
+ { p1->r=1; p1->i=0; } else
687
+ if (p2->r==0 && p2->i==0 && p3->r>0 && p3->i==0)
688
+ { p1->r=0; p1->i=0; } else {
689
+ log#C(&l, p2);
690
+ r.r = p3->r * l.r - p3->i * l.i;
691
+ r.i = p3->r * l.i + p3->i * l.r;
692
+ exp#C(p1, &r); }"]
693
+ ])
694
+
695
+
696
+ # Execution
697
+ print <<EOM
698
+
699
+
700
+ /* ------------------------- Execution -------------------------- */
701
+
702
+ static void
703
+ na_exec_math(struct NARRAY *a1, struct NARRAY *a2, void (*func)())
704
+ {
705
+ na_shape_t i;
706
+ int s1, s2;
707
+ char *p1, *p2;
708
+
709
+ s1 = na_sizeof[a1->type];
710
+ s2 = na_sizeof[a2->type];
711
+ p1 = a1->ptr;
712
+ p2 = a2->ptr;
713
+
714
+ #pragma omp parallel for
715
+ for (i=0;i<a1->total; i++) {
716
+ (*func)( p1+s1*i, p2+s2*i );
717
+ }
718
+ }
719
+
720
+
721
+ static VALUE
722
+ na_math_func(volatile VALUE self, na_mathfunc_t funcs)
723
+ {
724
+ struct NARRAY *a1, *a2;
725
+ VALUE ans;
726
+
727
+ if (TYPE(self) == T_ARRAY) {
728
+ self = na_ary_to_nary(self,cNArray);
729
+ } else
730
+ if (!IsNArray(self)) {
731
+ self = na_make_scalar(self,na_object_type(self));
732
+ }
733
+
734
+ GetNArray(self,a2);
735
+ if (NA_IsINTEGER(a2)) {
736
+ self = na_upcast_type(self,NA_DFLOAT);
737
+ GetNArray(self,a2);
738
+ }
739
+ ans = na_make_object(a2->type, a2->rank, a2->shape, CLASS_OF(self));
740
+ GetNArray(ans,a1);
741
+
742
+ na_exec_math(a1, a2, funcs[a2->type]);
743
+
744
+ if (CLASS_OF(self) == cNArrayScalar)
745
+ SetFuncs[NA_ROBJ][a1->type](1,&ans,0,a1->ptr,0);
746
+
747
+ return ans;
748
+ }
749
+ EOM
750
+
751
+
752
+ # Module Methods
753
+ print <<EOM
754
+
755
+ /* ------------------------- Module Methods -------------------------- */
756
+ EOM
757
+ for i in data
758
+ bsname=i[0]
759
+ name=bsname
760
+ print <<EOM
761
+
762
+ /*
763
+ * call-seq:
764
+ * NMath.#{name}(arg) -> narray
765
+ */
766
+ static VALUE na_math_#{bsname}(VALUE obj, VALUE x)
767
+ { return na_math_func(x,#{name}Funcs); }
768
+ EOM
769
+ end
770
+
771
+
772
+
773
+ # Initializer
774
+ print <<EOM
775
+
776
+
777
+ /* Initialization of NMath module */
778
+ void Init_nmath(void)
779
+ {
780
+ /* define ExtMath module */
781
+ rb_mNMath = rb_define_module("NMath");
782
+
783
+ /* methods */
784
+ EOM
785
+
786
+ for i in data
787
+ print " rb_define_module_function(rb_mNMath,\"#{i[0]}\",na_math_#{i[0]},1);\n"
788
+ end
789
+
790
+ print <<EOM
791
+ }
792
+ EOM