narray-nmatrix 0.6.1.0.pre

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