paddlec 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,28 @@
1
+ /* Copyright (C) 2019 Théotime Bollengier <theotime.bollengier@gmail.com>
2
+ *
3
+ * This file is part of PaddleC
4
+ *
5
+ * PaddleC is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * PaddleC is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with PaddleC. If not, see <https://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ #ifndef PADDLEC_FLOAT_BUFFER_H
20
+ #define PADDLEC_FLOAT_BUFFER_H
21
+
22
+ #include <ruby.h>
23
+ #include "libpaddlec.h"
24
+
25
+ void Init_paddlec_float_buffer();
26
+ pdlc_buffer_t* paddlec_float_buffer_get_struct(VALUE obj);
27
+
28
+ #endif /* PADDLEC_FLOAT_BUFFER_H */
@@ -0,0 +1,788 @@
1
+ /* Copyright (C) 2019 Théotime Bollengier <theotime.bollengier@gmail.com>
2
+ *
3
+ * This file is part of PaddleC
4
+ *
5
+ * PaddleC is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * PaddleC is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with PaddleC. If not, see <https://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ #include <ruby.h>
20
+ #include "paddlec_defs.h"
21
+ #include "libpaddlec.h"
22
+ #include "paddlec.h"
23
+ #include "float_buffer.h"
24
+ #include "complex_buffer.h"
25
+ #include "fir_filter.h"
26
+ #include "delay.h"
27
+ #ifdef HAVE_PULSEAUDIO_L
28
+ #include "pulseaudio.h"
29
+ #endif
30
+
31
+
32
+ /* Document-module: PaddleC
33
+ *
34
+ * PaddleC is an attempt to provide objects and methods to perform real-time processing in Ruby.
35
+ */
36
+
37
+
38
+ ID id_each;
39
+ ID id_collectI;
40
+ ID id_to_enum;
41
+ ID id_length;
42
+ ID id_real;
43
+ ID id_imag;
44
+ ID id_buffer;
45
+ ID id_delayed;
46
+ ID id_zip;
47
+ ID id_join;
48
+ ID id_to_s;
49
+ ID id_to_gplot;
50
+ ID id_acos;
51
+ ID id_acosh;
52
+ ID id_asin;
53
+ ID id_asinh;
54
+ ID id_atan;
55
+ ID id_atanh;
56
+ ID id_cbrt;
57
+ ID id_cos;
58
+ ID id_cosh;
59
+ ID id_erf;
60
+ ID id_erfc;
61
+ ID id_exp;
62
+ ID id_log;
63
+ ID id_log10;
64
+ ID id_log2;
65
+ ID id_sin;
66
+ ID id_sinh;
67
+ ID id_sqrt;
68
+ ID id_tan;
69
+ ID id_tanh;
70
+ ID id_u8;
71
+ ID id_s8;
72
+ ID id_u16;
73
+ ID id_s16;
74
+ ID id_u32;
75
+ ID id_s32;
76
+ ID id_f32;
77
+
78
+
79
+ VALUE m_PaddleC;
80
+
81
+ VALUE c_FFI_Pointer = Qundef;
82
+ VALUE o_FFI_Type_FLOAT = Qnil;
83
+
84
+
85
+
86
+ /* Allow the {https://rubygems.org/gems/gnuplot gnuplot} gem to draw {PaddleC::FloatBuffer}.
87
+ * @return [String]
88
+ */
89
+ static VALUE paddlec_array_to_gplot(VALUE self)
90
+ {
91
+ int len, i;
92
+ VALUE a, b, res, space, bn;
93
+ VALUE *splat;
94
+
95
+ if (rb_obj_is_kind_of(rb_ary_entry(self, 0), rb_cArray) || rb_obj_is_kind_of(rb_ary_entry(self, 0), c_FloatBuffer)) {
96
+ len = rb_array_len(self) - 1;
97
+ if (len < 0)
98
+ len = 0;
99
+ splat = malloc(len*sizeof(VALUE*));
100
+ for (i = 0; i < len; i++)
101
+ splat[i] = rb_ary_entry(self, i+1);
102
+ a = rb_funcallv(rb_ary_entry(self, 0), id_zip, len, splat);
103
+ free(splat);
104
+ len = rb_array_len(a);
105
+ b = rb_ary_new_capa(len + 1);
106
+ space = rb_str_new_cstr(" ");
107
+ for (i = 0; i < len; i++)
108
+ rb_ary_store(b, i, rb_funcallv(rb_ary_entry(a, i), id_join, 1, &space));
109
+ rb_ary_store(b, len, rb_str_new_cstr("e"));
110
+ bn = rb_str_new_cstr("\n");
111
+ res = rb_funcallv(b, id_join, 1, &bn);
112
+ }
113
+ else if (rb_obj_is_kind_of(rb_ary_entry(self, 0), rb_cNumeric)) {
114
+ len = rb_array_len(self);
115
+ res = rb_str_new_cstr("");
116
+ for (i = 0; i < len; i++) {
117
+ a = rb_funcallv(rb_ary_entry(self, i), id_to_s, 0, NULL);
118
+ a = rb_str_cat_cstr(a, "\n");
119
+ res = rb_str_append(res, a);
120
+ }
121
+ }
122
+ else {
123
+ len = rb_array_len(self) - 1;
124
+ if (len < 0)
125
+ len = 0;
126
+ splat = malloc(len*sizeof(VALUE*));
127
+ for (i = 0; i < len; i++)
128
+ splat[i] = rb_ary_entry(self, i+1);
129
+ a = rb_funcallv(rb_ary_entry(self, 0), id_zip, len, splat);
130
+ free(splat);
131
+ res = rb_funcallv(a, id_to_gplot, 0, NULL);
132
+ }
133
+
134
+ return res;
135
+ }
136
+
137
+
138
+ static void paddlec_check_if_FFI_is_defined()
139
+ {
140
+ VALUE mFFI;
141
+ VALUE cType;
142
+
143
+ if (rb_funcall(rb_cObject, rb_intern("const_defined?"), 1, ID2SYM(rb_intern("FFI"))) == Qtrue) {
144
+ mFFI = rb_const_get(rb_cObject, rb_intern("FFI"));
145
+ c_FFI_Pointer = rb_const_get(mFFI, rb_intern("Pointer"));
146
+ cType = rb_const_get(mFFI, rb_intern("Type"));
147
+ o_FFI_Type_FLOAT = rb_const_get(cType, rb_intern("FLOAT"));
148
+ }
149
+ }
150
+
151
+
152
+
153
+ /* @return [Symbol, nil]
154
+ */
155
+ static VALUE paddlec_paddlec_accelerator(VALUE self)
156
+ {
157
+ const char *acc = pdlc_accelerator();
158
+ if (acc[0] == '\0')
159
+ return Qnil;
160
+ return ID2SYM(rb_intern(acc));
161
+ }
162
+
163
+
164
+ /* @!group Mathematic functions. These are methods from the +Math+ module. They can operate on {PaddleC::FloatBuffer} and Float.
165
+ */
166
+
167
+
168
+ /* Computes the arc cosine of x. Returns 0..PI.
169
+ * @return [PaddleC::FloatBuffer, Float]
170
+ * @overload acos(x)
171
+ * @param x [PaddleC::FloatBuffer]
172
+ * @return [PaddleC::FloatBuffer]
173
+ * @overload acos(x)
174
+ * @param x [Float]
175
+ * @return [Float]
176
+ */
177
+ static VALUE paddlec_math_acos(VALUE self, VALUE x)
178
+ {
179
+ VALUE res;
180
+ float sf;
181
+
182
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
183
+ res = rb_funcallv(x, id_acos, 0, NULL);
184
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
185
+ sf = (float)NUM2DBL(x);
186
+ res = DBL2NUM((double)acosf(sf));
187
+ }
188
+ else
189
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
190
+
191
+ return res;
192
+ }
193
+
194
+
195
+ /* Computes the inverse hyperbolic cosine of x.
196
+ * @return [PaddleC::FloatBuffer, Float]
197
+ * @overload acosh(x)
198
+ * @param x [PaddleC::FloatBuffer]
199
+ * @return [PaddleC::FloatBuffer]
200
+ * @overload acosh(x)
201
+ * @param x [Float]
202
+ * @return [Float]
203
+ */
204
+ static VALUE paddlec_math_acosh(VALUE self, VALUE x)
205
+ {
206
+ VALUE res;
207
+ float sf;
208
+
209
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
210
+ res = rb_funcallv(x, id_acosh, 0, NULL);
211
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
212
+ sf = (float)NUM2DBL(x);
213
+ res = DBL2NUM((double)acoshf(sf));
214
+ }
215
+ else
216
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
217
+
218
+ return res;
219
+ }
220
+
221
+
222
+ /* Computes the arc sine of x. Returns -PI/2..PI/2.
223
+ * @return [PaddleC::FloatBuffer, Float]
224
+ * @overload asin(x)
225
+ * @param x [PaddleC::FloatBuffer]
226
+ * @return [PaddleC::FloatBuffer]
227
+ * @overload asin(x)
228
+ * @param x [Float]
229
+ * @return [Float]
230
+ */
231
+ static VALUE paddlec_math_asin(VALUE self, VALUE x)
232
+ {
233
+ VALUE res;
234
+ float sf;
235
+
236
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
237
+ res = rb_funcallv(x, id_asin, 0, NULL);
238
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
239
+ sf = (float)NUM2DBL(x);
240
+ res = DBL2NUM((double)asinf(sf));
241
+ }
242
+ else
243
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
244
+
245
+ return res;
246
+ }
247
+
248
+
249
+ /* Computes the inverse hyperbolic sine of x.
250
+ * @return [PaddleC::FloatBuffer, Float]
251
+ * @overload asinh(x)
252
+ * @param x [PaddleC::FloatBuffer]
253
+ * @return [PaddleC::FloatBuffer]
254
+ * @overload asinh(x)
255
+ * @param x [Float]
256
+ * @return [Float]
257
+ */
258
+ static VALUE paddlec_math_asinh(VALUE self, VALUE x)
259
+ {
260
+ VALUE res;
261
+ float sf;
262
+
263
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
264
+ res = rb_funcallv(x, id_asinh, 0, NULL);
265
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
266
+ sf = (float)NUM2DBL(x);
267
+ res = DBL2NUM((double)asinhf(sf));
268
+ }
269
+ else
270
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
271
+
272
+ return res;
273
+ }
274
+
275
+
276
+ /* Computes the arc tangent of x.
277
+ * @return [PaddleC::FloatBuffer, Float]
278
+ * @overload atan(x)
279
+ * @param x [PaddleC::FloatBuffer]
280
+ * @return [PaddleC::FloatBuffer]
281
+ * @overload atan(x)
282
+ * @param x [Float]
283
+ * @return [Float]
284
+ */
285
+ static VALUE paddlec_math_atan(VALUE self, VALUE x)
286
+ {
287
+ VALUE res;
288
+ float sf;
289
+
290
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
291
+ res = rb_funcallv(x, id_atan, 0, NULL);
292
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
293
+ sf = (float)NUM2DBL(x);
294
+ res = DBL2NUM((double)atanf(sf));
295
+ }
296
+ else
297
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
298
+
299
+ return res;
300
+ }
301
+
302
+
303
+ /* Computes the inverse hyperbolic tangent of x.
304
+ * @return [PaddleC::FloatBuffer, Float]
305
+ * @overload atanh(x)
306
+ * @param x [PaddleC::FloatBuffer]
307
+ * @return [PaddleC::FloatBuffer]
308
+ * @overload atanh(x)
309
+ * @param x [Float]
310
+ * @return [Float]
311
+ */
312
+ static VALUE paddlec_math_atanh(VALUE self, VALUE x)
313
+ {
314
+ VALUE res;
315
+ float sf;
316
+
317
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
318
+ res = rb_funcallv(x, id_atanh, 0, NULL);
319
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
320
+ sf = (float)NUM2DBL(x);
321
+ res = DBL2NUM((double)atanhf(sf));
322
+ }
323
+ else
324
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
325
+
326
+ return res;
327
+ }
328
+
329
+
330
+ /* Returns the cube root of x.
331
+ * @return [PaddleC::FloatBuffer, Float]
332
+ * @overload cbrt(x)
333
+ * @param x [PaddleC::FloatBuffer]
334
+ * @return [PaddleC::FloatBuffer]
335
+ * @overload cbrt(x)
336
+ * @param x [Float]
337
+ * @return [Float]
338
+ */
339
+ static VALUE paddlec_math_cbrt(VALUE self, VALUE x)
340
+ {
341
+ VALUE res;
342
+ float sf;
343
+
344
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
345
+ res = rb_funcallv(x, id_cbrt, 0, NULL);
346
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
347
+ sf = (float)NUM2DBL(x);
348
+ res = DBL2NUM((double)cbrtf(sf));
349
+ }
350
+ else
351
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
352
+
353
+ return res;
354
+ }
355
+
356
+
357
+ /* Computes the cosine of x (expressed in radians). Returns a Float in the range -1.0..1.0.
358
+ * @return [PaddleC::FloatBuffer, Float]
359
+ * @overload cos(x)
360
+ * @param x [PaddleC::FloatBuffer]
361
+ * @return [PaddleC::FloatBuffer]
362
+ * @overload cos(x)
363
+ * @param x [Float]
364
+ * @return [Float]
365
+ */
366
+ static VALUE paddlec_math_cos(VALUE self, VALUE x)
367
+ {
368
+ VALUE res;
369
+ float sf;
370
+
371
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
372
+ res = rb_funcallv(x, id_cos, 0, NULL);
373
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
374
+ sf = (float)NUM2DBL(x);
375
+ res = DBL2NUM((double)cosf(sf));
376
+ }
377
+ else
378
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
379
+
380
+ return res;
381
+ }
382
+
383
+
384
+ /* Computes the hyperbolic cosine of x.
385
+ * @return [PaddleC::FloatBuffer, Float]
386
+ * @overload cosh(x)
387
+ * @param x [PaddleC::FloatBuffer]
388
+ * @return [PaddleC::FloatBuffer]
389
+ * @overload cosh(x)
390
+ * @param x [Float]
391
+ * @return [Float]
392
+ */
393
+ static VALUE paddlec_math_cosh(VALUE self, VALUE x)
394
+ {
395
+ VALUE res;
396
+ float sf;
397
+
398
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
399
+ res = rb_funcallv(x, id_cosh, 0, NULL);
400
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
401
+ sf = (float)NUM2DBL(x);
402
+ res = DBL2NUM((double)coshf(sf));
403
+ }
404
+ else
405
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
406
+
407
+ return res;
408
+ }
409
+
410
+
411
+ /* Calculates the error function of x.
412
+ * @return [PaddleC::FloatBuffer, Float]
413
+ * @overload erf(x)
414
+ * @param x [PaddleC::FloatBuffer]
415
+ * @return [PaddleC::FloatBuffer]
416
+ * @overload erf(x)
417
+ * @param x [Float]
418
+ * @return [Float]
419
+ */
420
+ static VALUE paddlec_math_erf(VALUE self, VALUE x)
421
+ {
422
+ VALUE res;
423
+ float sf;
424
+
425
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
426
+ res = rb_funcallv(x, id_erf, 0, NULL);
427
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
428
+ sf = (float)NUM2DBL(x);
429
+ res = DBL2NUM((double)erff(sf));
430
+ }
431
+ else
432
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
433
+
434
+ return res;
435
+ }
436
+
437
+
438
+ /* Calculates the complementary error function of x.
439
+ * @return [PaddleC::FloatBuffer, Float]
440
+ * @overload erfc(x)
441
+ * @param x [PaddleC::FloatBuffer]
442
+ * @return [PaddleC::FloatBuffer]
443
+ * @overload erfc(x)
444
+ * @param x [Float]
445
+ * @return [Float]
446
+ */
447
+ static VALUE paddlec_math_erfc(VALUE self, VALUE x)
448
+ {
449
+ VALUE res;
450
+ float sf;
451
+
452
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
453
+ res = rb_funcallv(x, id_erfc, 0, NULL);
454
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
455
+ sf = (float)NUM2DBL(x);
456
+ res = DBL2NUM((double)erfcf(sf));
457
+ }
458
+ else
459
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
460
+
461
+ return res;
462
+ }
463
+
464
+
465
+ /* Calculates the value of e (the base of natural logarithms) raised to the power of x.
466
+ * @return [PaddleC::FloatBuffer, Float]
467
+ * @overload exp(x)
468
+ * @param x [PaddleC::FloatBuffer]
469
+ * @return [PaddleC::FloatBuffer]
470
+ * @overload exp(x)
471
+ * @param x [Float]
472
+ * @return [Float]
473
+ */
474
+ static VALUE paddlec_math_exp(VALUE self, VALUE x)
475
+ {
476
+ VALUE res;
477
+ float sf;
478
+
479
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
480
+ res = rb_funcallv(x, id_exp, 0, NULL);
481
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
482
+ sf = (float)NUM2DBL(x);
483
+ res = DBL2NUM((double)expf(sf));
484
+ }
485
+ else
486
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
487
+
488
+ return res;
489
+ }
490
+
491
+
492
+ /* Calculates the natural logarithm of x.
493
+ * @return [PaddleC::FloatBuffer, Float]
494
+ * @overload log(x)
495
+ * @param x [PaddleC::FloatBuffer]
496
+ * @return [PaddleC::FloatBuffer]
497
+ * @overload log(x)
498
+ * @param x [Float]
499
+ * @return [Float]
500
+ */
501
+ static VALUE paddlec_math_log(VALUE self, VALUE x)
502
+ {
503
+ VALUE res;
504
+ float sf;
505
+
506
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
507
+ res = rb_funcallv(x, id_log, 0, NULL);
508
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
509
+ sf = (float)NUM2DBL(x);
510
+ res = DBL2NUM((double)logf(sf));
511
+ }
512
+ else
513
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
514
+
515
+ return res;
516
+ }
517
+
518
+
519
+ /* Calculates the base 10 logarithm of x.
520
+ * @return [PaddleC::FloatBuffer, Float]
521
+ * @overload log10(x)
522
+ * @param x [PaddleC::FloatBuffer]
523
+ * @return [PaddleC::FloatBuffer]
524
+ * @overload log10(x)
525
+ * @param x [Float]
526
+ * @return [Float]
527
+ */
528
+ static VALUE paddlec_math_log10(VALUE self, VALUE x)
529
+ {
530
+ VALUE res;
531
+ float sf;
532
+
533
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
534
+ res = rb_funcallv(x, id_log10, 0, NULL);
535
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
536
+ sf = (float)NUM2DBL(x);
537
+ res = DBL2NUM((double)log10f(sf));
538
+ }
539
+ else
540
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
541
+
542
+ return res;
543
+ }
544
+
545
+
546
+ /* Calculate the base 2 logarithm of x.
547
+ * @return [PaddleC::FloatBuffer, Float]
548
+ * @overload log2(x)
549
+ * @param x [PaddleC::FloatBuffer]
550
+ * @return [PaddleC::FloatBuffer]
551
+ * @overload log2(x)
552
+ * @param x [Float]
553
+ * @return [Float]
554
+ */
555
+ static VALUE paddlec_math_log2(VALUE self, VALUE x)
556
+ {
557
+ VALUE res;
558
+ float sf;
559
+
560
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
561
+ res = rb_funcallv(x, id_log2, 0, NULL);
562
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
563
+ sf = (float)NUM2DBL(x);
564
+ res = DBL2NUM((double)log2f(sf));
565
+ }
566
+ else
567
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
568
+
569
+ return res;
570
+ }
571
+
572
+
573
+ /* Computes the sine of x (expressed in radians). Returns a Float in the range -1.0..1.0.
574
+ * @return [PaddleC::FloatBuffer, Float]
575
+ * @overload sin(x)
576
+ * @param x [PaddleC::FloatBuffer]
577
+ * @return [PaddleC::FloatBuffer]
578
+ * @overload sin(x)
579
+ * @param x [Float]
580
+ * @return [Float]
581
+ */
582
+ static VALUE paddlec_math_sin(VALUE self, VALUE x)
583
+ {
584
+ VALUE res;
585
+ float sf;
586
+
587
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
588
+ res = rb_funcallv(x, id_sin, 0, NULL);
589
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
590
+ sf = (float)NUM2DBL(x);
591
+ res = DBL2NUM((double)sinf(sf));
592
+ }
593
+ else
594
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
595
+
596
+ return res;
597
+ }
598
+
599
+
600
+ /* Computes the hyperbolic sine of x.
601
+ * @return [PaddleC::FloatBuffer, Float]
602
+ * @overload sinh(x)
603
+ * @param x [PaddleC::FloatBuffer]
604
+ * @return [PaddleC::FloatBuffer]
605
+ * @overload sinh(x)
606
+ * @param x [Float]
607
+ * @return [Float]
608
+ */
609
+ static VALUE paddlec_math_sinh(VALUE self, VALUE x)
610
+ {
611
+ VALUE res;
612
+ float sf;
613
+
614
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
615
+ res = rb_funcallv(x, id_sinh, 0, NULL);
616
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
617
+ sf = (float)NUM2DBL(x);
618
+ res = DBL2NUM((double)sinhf(sf));
619
+ }
620
+ else
621
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
622
+
623
+ return res;
624
+ }
625
+
626
+
627
+ /* Computes the non-negative square root of x.
628
+ * @return [PaddleC::FloatBuffer, Float]
629
+ * @overload sqrt(x)
630
+ * @param x [PaddleC::FloatBuffer]
631
+ * @return [PaddleC::FloatBuffer]
632
+ * @overload sqrt(x)
633
+ * @param x [Float]
634
+ * @return [Float]
635
+ */
636
+ static VALUE paddlec_math_sqrt(VALUE self, VALUE x)
637
+ {
638
+ VALUE res;
639
+ float sf;
640
+
641
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
642
+ res = rb_funcallv(x, id_sqrt, 0, NULL);
643
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
644
+ sf = (float)NUM2DBL(x);
645
+ res = DBL2NUM((double)sqrtf(sf));
646
+ }
647
+ else
648
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
649
+
650
+ return res;
651
+ }
652
+
653
+
654
+ /* Computes the tangent of x (expressed in radians).
655
+ * @return [PaddleC::FloatBuffer, Float]
656
+ * @overload tan(x)
657
+ * @param x [PaddleC::FloatBuffer]
658
+ * @return [PaddleC::FloatBuffer]
659
+ * @overload tan(x)
660
+ * @param x [Float]
661
+ * @return [Float]
662
+ */
663
+ static VALUE paddlec_math_tan(VALUE self, VALUE x)
664
+ {
665
+ VALUE res;
666
+ float sf;
667
+
668
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
669
+ res = rb_funcallv(x, id_tan, 0, NULL);
670
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
671
+ sf = (float)NUM2DBL(x);
672
+ res = DBL2NUM((double)tanf(sf));
673
+ }
674
+ else
675
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
676
+
677
+ return res;
678
+ }
679
+
680
+
681
+ /* Computes the hyperbolic tangent of x.
682
+ * @return [PaddleC::FloatBuffer, Float]
683
+ * @overload tanh(x)
684
+ * @param x [PaddleC::FloatBuffer]
685
+ * @return [PaddleC::FloatBuffer]
686
+ * @overload tanh(x)
687
+ * @param x [Float]
688
+ * @return [Float]
689
+ */
690
+ static VALUE paddlec_math_tanh(VALUE self, VALUE x)
691
+ {
692
+ VALUE res;
693
+ float sf;
694
+
695
+ if (rb_obj_is_kind_of(x, c_FloatBuffer))
696
+ res = rb_funcallv(x, id_tanh, 0, NULL);
697
+ else if (rb_obj_is_kind_of(x, rb_cNumeric) && !rb_obj_is_kind_of(x, rb_cComplex)) {
698
+ sf = (float)NUM2DBL(x);
699
+ res = DBL2NUM((double)tanhf(sf));
700
+ }
701
+ else
702
+ rb_raise(rb_eTypeError, "expecting a %"PRIsVALUE" or a non complex Numeric, not a %"PRIsVALUE, rb_class_name(c_FloatBuffer), rb_class_name(rb_class_of(x)));
703
+
704
+ return res;
705
+ }
706
+
707
+ /* @!endgroup
708
+ */
709
+
710
+ void Init_paddlec()
711
+ {
712
+ id_each = rb_intern("each");
713
+ id_collectI = rb_intern("collect!");
714
+ id_to_enum = rb_intern("to_enum");
715
+ id_length = rb_intern("length");
716
+ id_real = rb_intern("real");
717
+ id_imag = rb_intern("imag");
718
+ id_buffer = rb_intern("buffer");
719
+ id_delayed = rb_intern("delayed");
720
+ id_zip = rb_intern("zip");
721
+ id_join = rb_intern("join");
722
+ id_to_s = rb_intern("to_s");
723
+ id_to_gplot = rb_intern("to_gplot");
724
+ id_acos = rb_intern("acos");
725
+ id_acosh = rb_intern("acosh");
726
+ id_asin = rb_intern("asin");
727
+ id_asinh = rb_intern("asinh");
728
+ id_atan = rb_intern("atan");
729
+ id_atanh = rb_intern("atanh");
730
+ id_cbrt = rb_intern("cbrt");
731
+ id_cos = rb_intern("cos");
732
+ id_cosh = rb_intern("cosh");
733
+ id_erf = rb_intern("erf");
734
+ id_erfc = rb_intern("erfc");
735
+ id_exp = rb_intern("exp");
736
+ id_log = rb_intern("log");
737
+ id_log10 = rb_intern("log10");
738
+ id_log2 = rb_intern("log2");
739
+ id_sin = rb_intern("sin");
740
+ id_sinh = rb_intern("sinh");
741
+ id_sqrt = rb_intern("sqrt");
742
+ id_tan = rb_intern("tan");
743
+ id_tanh = rb_intern("tanh");
744
+ id_u8 = rb_intern("u8");
745
+ id_s8 = rb_intern("s8");
746
+ id_u16 = rb_intern("u16");
747
+ id_s16 = rb_intern("s16");
748
+ id_u32 = rb_intern("u32");
749
+ id_s32 = rb_intern("s32");
750
+ id_f32 = rb_intern("f32");
751
+
752
+ paddlec_check_if_FFI_is_defined();
753
+
754
+ m_PaddleC = rb_define_module("PaddleC");
755
+ rb_define_module_function(m_PaddleC, "accelerator", paddlec_paddlec_accelerator, 0);
756
+ rb_define_module_function(m_PaddleC, "acos", paddlec_math_acos, 1);
757
+ rb_define_module_function(m_PaddleC, "acosh", paddlec_math_acosh, 1);
758
+ rb_define_module_function(m_PaddleC, "asin", paddlec_math_asin, 1);
759
+ rb_define_module_function(m_PaddleC, "asinh", paddlec_math_asinh, 1);
760
+ rb_define_module_function(m_PaddleC, "atan", paddlec_math_atan, 1);
761
+ rb_define_module_function(m_PaddleC, "atanh", paddlec_math_atanh, 1);
762
+ rb_define_module_function(m_PaddleC, "cbrt", paddlec_math_cbrt, 1);
763
+ rb_define_module_function(m_PaddleC, "cos", paddlec_math_cos, 1);
764
+ rb_define_module_function(m_PaddleC, "cosh", paddlec_math_cosh, 1);
765
+ rb_define_module_function(m_PaddleC, "erf", paddlec_math_erf, 1);
766
+ rb_define_module_function(m_PaddleC, "erfc", paddlec_math_erfc, 1);
767
+ rb_define_module_function(m_PaddleC, "exp", paddlec_math_exp, 1);
768
+ rb_define_module_function(m_PaddleC, "log", paddlec_math_log, 1);
769
+ rb_define_module_function(m_PaddleC, "log10", paddlec_math_log10, 1);
770
+ rb_define_module_function(m_PaddleC, "log2", paddlec_math_log2, 1);
771
+ rb_define_module_function(m_PaddleC, "sin", paddlec_math_sin, 1);
772
+ rb_define_module_function(m_PaddleC, "sinh", paddlec_math_sinh, 1);
773
+ rb_define_module_function(m_PaddleC, "sqrt", paddlec_math_sqrt, 1);
774
+ rb_define_module_function(m_PaddleC, "tan", paddlec_math_tan, 1);
775
+ rb_define_module_function(m_PaddleC, "tanh", paddlec_math_tanh, 1);
776
+
777
+ Init_paddlec_float_buffer();
778
+ Init_paddlec_complex_buffer();
779
+ Init_paddlec_fir_filter();
780
+ Init_paddlec_delay();
781
+
782
+ #ifdef HAVE_PULSEAUDIO_L
783
+ Init_paddlec_pulseaudio();
784
+ #endif
785
+
786
+ rb_define_method(rb_cArray, "to_gplot", paddlec_array_to_gplot, 0);
787
+ }
788
+