paddlec 0.0.1
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.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +56 -0
- data/ext/libpaddlec/arithmetic.c +2486 -0
- data/ext/libpaddlec/comparison.c +683 -0
- data/ext/libpaddlec/complex.c +349 -0
- data/ext/libpaddlec/delay.c +240 -0
- data/ext/libpaddlec/fir_filter.c +724 -0
- data/ext/libpaddlec/fir_filter_avx.c +2645 -0
- data/ext/libpaddlec/fir_filter_neon.c +1767 -0
- data/ext/libpaddlec/fir_filter_sse.c +1677 -0
- data/ext/libpaddlec/libpaddlec.c +933 -0
- data/ext/libpaddlec/libpaddlec.h +473 -0
- data/ext/libpaddlec/math.c +563 -0
- data/ext/libpaddlec/no_fast_math.c +955 -0
- data/ext/libpaddlec/rounding.c +503 -0
- data/ext/paddlec/complex_buffer.c +3555 -0
- data/ext/paddlec/complex_buffer.h +28 -0
- data/ext/paddlec/delay.c +214 -0
- data/ext/paddlec/delay.h +29 -0
- data/ext/paddlec/extconf.rb +106 -0
- data/ext/paddlec/fir_filter.c +892 -0
- data/ext/paddlec/fir_filter.h +28 -0
- data/ext/paddlec/float_buffer.c +4770 -0
- data/ext/paddlec/float_buffer.h +28 -0
- data/ext/paddlec/paddlec.c +788 -0
- data/ext/paddlec/paddlec.h +76 -0
- data/ext/paddlec/pulseaudio.c +6767 -0
- data/ext/paddlec/pulseaudio.h +30 -0
- data/lib/paddlec.rb +26 -0
- data/lib/paddlec/version.rb +3 -0
- data/paddlec.gemspec +55 -0
- data/samples/fmdemod.rb +121 -0
- data/samples/fmdemod_chunk.rb +120 -0
- data/samples/fmdemod_chunk_buffer.rb +144 -0
- data/samples/stereo_chunk.rb +161 -0
- metadata +99 -0
@@ -0,0 +1,933 @@
|
|
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 <stdlib.h>
|
20
|
+
#include <stdio.h>
|
21
|
+
#include <string.h>
|
22
|
+
#include <math.h>
|
23
|
+
#include "libpaddlec.h"
|
24
|
+
|
25
|
+
|
26
|
+
const char* pdlc_accelerator()
|
27
|
+
{
|
28
|
+
#if defined __AVX__
|
29
|
+
#if !(defined __FMA__ || defined __FMA4__)
|
30
|
+
return "AVX";
|
31
|
+
#else
|
32
|
+
return "AVX-FMA";
|
33
|
+
#endif
|
34
|
+
#elif defined __SSE__
|
35
|
+
return "SSE";
|
36
|
+
#elif (defined __ARM_NEON) && ((__ARM_NEON_FP & 4) == 4)
|
37
|
+
#ifndef __FP_FAST_FMA
|
38
|
+
return "NEON";
|
39
|
+
#else
|
40
|
+
return "NEON-VFPv4";
|
41
|
+
#endif
|
42
|
+
#else
|
43
|
+
return "";
|
44
|
+
#endif
|
45
|
+
}
|
46
|
+
|
47
|
+
|
48
|
+
pdlc_buffer_t* pdlc_buffer_new(size_t length)
|
49
|
+
{
|
50
|
+
pdlc_buffer_t *res;
|
51
|
+
|
52
|
+
res = malloc(sizeof(pdlc_buffer_t));
|
53
|
+
res->capacity = 0;
|
54
|
+
res->length = 0;
|
55
|
+
res->data = NULL;
|
56
|
+
|
57
|
+
pdlc_buffer_resize(res, length, 1);
|
58
|
+
|
59
|
+
return res;
|
60
|
+
}
|
61
|
+
|
62
|
+
|
63
|
+
void pdlc_buffer_free(pdlc_buffer_t *buf)
|
64
|
+
{
|
65
|
+
if (buf == NULL)
|
66
|
+
return;
|
67
|
+
if (buf->data)
|
68
|
+
free(buf->data);
|
69
|
+
free(buf);
|
70
|
+
}
|
71
|
+
|
72
|
+
|
73
|
+
pdlc_buffer_t* pdlc_buffer_copy(const pdlc_buffer_t *orig)
|
74
|
+
{
|
75
|
+
pdlc_buffer_t *res = pdlc_buffer_new(orig->length);
|
76
|
+
memcpy(res->data, orig->data, orig->length*sizeof(float));
|
77
|
+
return res;
|
78
|
+
}
|
79
|
+
|
80
|
+
|
81
|
+
void pdlc_buffer_resize(pdlc_buffer_t *buf, size_t new_length, int copy_old_and_zero_excess)
|
82
|
+
{
|
83
|
+
float *new_data;
|
84
|
+
size_t new_capacity;
|
85
|
+
|
86
|
+
if (new_length <= buf->capacity) {
|
87
|
+
if (copy_old_and_zero_excess != 0 && new_length > buf->length)
|
88
|
+
memset(buf->data + buf->length, 0, (new_length - buf->length)*sizeof(float));
|
89
|
+
buf->length = new_length;
|
90
|
+
return;
|
91
|
+
}
|
92
|
+
|
93
|
+
new_capacity = new_length + (new_length >> 2);
|
94
|
+
new_data = malloc(new_capacity*sizeof(float));
|
95
|
+
if (new_data == NULL) {
|
96
|
+
fprintf(stderr, "ERROR: libpaddlec: Cannot allocate %lu bytes of buffer!\n", new_capacity*sizeof(float));
|
97
|
+
exit(EXIT_FAILURE);
|
98
|
+
}
|
99
|
+
if (buf->data != NULL) {
|
100
|
+
if (copy_old_and_zero_excess != 0 && buf->length > 0)
|
101
|
+
memcpy(new_data, buf->data, buf->length*sizeof(float));
|
102
|
+
free(buf->data);
|
103
|
+
}
|
104
|
+
if (copy_old_and_zero_excess != 0 && new_length > buf->length)
|
105
|
+
memset(new_data + buf->length, 0, (new_length - buf->length)*sizeof(float));
|
106
|
+
buf->data = new_data;
|
107
|
+
buf->capacity = new_capacity;
|
108
|
+
buf->length = new_length;
|
109
|
+
}
|
110
|
+
|
111
|
+
|
112
|
+
void pdlc_buffer_set(pdlc_buffer_t *buf, float val)
|
113
|
+
{
|
114
|
+
size_t i;
|
115
|
+
|
116
|
+
for (i = 0; i < buf->length; i++)
|
117
|
+
buf->data[i] = val;
|
118
|
+
}
|
119
|
+
|
120
|
+
|
121
|
+
pdlc_complex_buffer_t* pdlc_complex_buffer_new(size_t length)
|
122
|
+
{
|
123
|
+
pdlc_complex_buffer_t *res;
|
124
|
+
|
125
|
+
res = malloc(sizeof(pdlc_complex_buffer_t));
|
126
|
+
res->capacity = 0;
|
127
|
+
res->length = 0;
|
128
|
+
res->data = NULL;
|
129
|
+
|
130
|
+
pdlc_complex_buffer_resize(res, length, 1);
|
131
|
+
|
132
|
+
return res;
|
133
|
+
}
|
134
|
+
|
135
|
+
|
136
|
+
void pdlc_complex_buffer_free(pdlc_complex_buffer_t *buf)
|
137
|
+
{
|
138
|
+
if (buf == NULL)
|
139
|
+
return;
|
140
|
+
if (buf->data)
|
141
|
+
free(buf->data);
|
142
|
+
free(buf);
|
143
|
+
}
|
144
|
+
|
145
|
+
|
146
|
+
pdlc_complex_buffer_t* pdlc_complex_buffer_copy(const pdlc_complex_buffer_t *orig)
|
147
|
+
{
|
148
|
+
pdlc_complex_buffer_t *res = pdlc_complex_buffer_new(orig->length);
|
149
|
+
memcpy(res->data, orig->data, orig->length*sizeof(pdlc_complex_t));
|
150
|
+
return res;
|
151
|
+
}
|
152
|
+
|
153
|
+
|
154
|
+
void pdlc_complex_buffer_resize(pdlc_complex_buffer_t *buf, size_t new_length, int copy_old_and_zero_excess)
|
155
|
+
{
|
156
|
+
pdlc_complex_t *new_data;
|
157
|
+
size_t new_capacity;
|
158
|
+
|
159
|
+
if (new_length <= buf->capacity) {
|
160
|
+
if (copy_old_and_zero_excess != 0 && new_length > buf->length)
|
161
|
+
memset(buf->data + buf->length, 0, (new_length - buf->length)*sizeof(pdlc_complex_t));
|
162
|
+
buf->length = new_length;
|
163
|
+
return;
|
164
|
+
}
|
165
|
+
|
166
|
+
new_capacity = new_length + (new_length >> 2);
|
167
|
+
new_data = malloc(new_capacity*sizeof(pdlc_complex_t));
|
168
|
+
if (new_data == NULL) {
|
169
|
+
fprintf(stderr, "ERROR: libpaddlec: Cannot allocate %lu bytes of buffer!\n", new_capacity*sizeof(pdlc_complex_t));
|
170
|
+
exit(EXIT_FAILURE);
|
171
|
+
}
|
172
|
+
if (buf->data != NULL) {
|
173
|
+
if (copy_old_and_zero_excess != 0 && buf->length > 0)
|
174
|
+
memcpy(new_data, buf->data, buf->length*sizeof(pdlc_complex_t));
|
175
|
+
free(buf->data);
|
176
|
+
}
|
177
|
+
if (copy_old_and_zero_excess != 0 && new_length > buf->length)
|
178
|
+
memset(new_data + buf->length, 0, (new_length - buf->length)*sizeof(pdlc_complex_t));
|
179
|
+
buf->data = new_data;
|
180
|
+
buf->capacity = new_capacity;
|
181
|
+
buf->length = new_length;
|
182
|
+
}
|
183
|
+
|
184
|
+
|
185
|
+
void pdlc_complex_buffer_set(pdlc_complex_buffer_t *buf, pdlc_complex_t val)
|
186
|
+
{
|
187
|
+
size_t i;
|
188
|
+
|
189
|
+
for (i = 0; i < buf->length; i++)
|
190
|
+
buf->data[i] = val;
|
191
|
+
}
|
192
|
+
|
193
|
+
|
194
|
+
pdlc_buffer_t* pdlc_buffer_reverse(const pdlc_buffer_t *fbuf, pdlc_buffer_t *res)
|
195
|
+
{
|
196
|
+
const size_t len = fbuf->length;
|
197
|
+
size_t i;
|
198
|
+
|
199
|
+
if (!res)
|
200
|
+
res = pdlc_buffer_new(len);
|
201
|
+
else
|
202
|
+
pdlc_buffer_resize(res, len, 0);
|
203
|
+
|
204
|
+
for (i = 0; i < len; i++)
|
205
|
+
res->data[i] = fbuf->data[len - 1 - i];
|
206
|
+
|
207
|
+
return res;
|
208
|
+
}
|
209
|
+
|
210
|
+
|
211
|
+
pdlc_buffer_t* pdlc_buffer_reverse_inplace(pdlc_buffer_t *fbuf)
|
212
|
+
{
|
213
|
+
const size_t lenmone = fbuf->length - 1;
|
214
|
+
const size_t half_len = fbuf->length / 2;
|
215
|
+
size_t i;
|
216
|
+
float tmp;
|
217
|
+
|
218
|
+
for (i = 0; i < half_len; i++) {
|
219
|
+
tmp = fbuf->data[lenmone - i];
|
220
|
+
fbuf->data[lenmone - i] = fbuf->data[i];
|
221
|
+
fbuf->data[i] = tmp;
|
222
|
+
}
|
223
|
+
|
224
|
+
return fbuf;
|
225
|
+
}
|
226
|
+
|
227
|
+
|
228
|
+
pdlc_complex_buffer_t* pdlc_complex_buffer_reverse(const pdlc_complex_buffer_t *cbuf, pdlc_complex_buffer_t *res)
|
229
|
+
{
|
230
|
+
const size_t len = cbuf->length;
|
231
|
+
size_t i;
|
232
|
+
|
233
|
+
if (!res)
|
234
|
+
res = pdlc_complex_buffer_new(len);
|
235
|
+
else
|
236
|
+
pdlc_complex_buffer_resize(res, len, 0);
|
237
|
+
|
238
|
+
for (i = 0; i < len; i++)
|
239
|
+
res->data[i] = cbuf->data[len - 1 - i];
|
240
|
+
|
241
|
+
return res;
|
242
|
+
}
|
243
|
+
|
244
|
+
|
245
|
+
pdlc_complex_buffer_t* pdlc_complex_buffer_reverse_inplace(pdlc_complex_buffer_t *cbuf)
|
246
|
+
{
|
247
|
+
const size_t lenmone = cbuf->length - 1;
|
248
|
+
const size_t half_len = cbuf->length / 2;
|
249
|
+
size_t i;
|
250
|
+
pdlc_complex_t tmp;
|
251
|
+
|
252
|
+
for (i = 0; i < half_len; i++) {
|
253
|
+
tmp = cbuf->data[lenmone - i];
|
254
|
+
cbuf->data[lenmone - i] = cbuf->data[i];
|
255
|
+
cbuf->data[i] = tmp;
|
256
|
+
}
|
257
|
+
|
258
|
+
return cbuf;
|
259
|
+
}
|
260
|
+
|
261
|
+
|
262
|
+
float pdlc_buffer_sum(const pdlc_buffer_t *fbuf)
|
263
|
+
{
|
264
|
+
const size_t len = fbuf->length;
|
265
|
+
size_t alen = len;
|
266
|
+
size_t i, hlen;
|
267
|
+
float *copy;
|
268
|
+
float res = 0.0f;
|
269
|
+
|
270
|
+
if (len < 1)
|
271
|
+
return 0.0f;
|
272
|
+
|
273
|
+
copy = malloc(len*sizeof(float));
|
274
|
+
memcpy(copy, fbuf->data, len*sizeof(float));
|
275
|
+
|
276
|
+
while (alen > 1) {
|
277
|
+
hlen = alen / 2;
|
278
|
+
for (i = 0; i < hlen; i++)
|
279
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
280
|
+
if (alen % 2) {
|
281
|
+
copy[i] = copy[2*i];
|
282
|
+
alen = hlen + 1;
|
283
|
+
}
|
284
|
+
else
|
285
|
+
alen = hlen;
|
286
|
+
}
|
287
|
+
|
288
|
+
res = copy[0];
|
289
|
+
|
290
|
+
free(copy);
|
291
|
+
|
292
|
+
return res;
|
293
|
+
}
|
294
|
+
|
295
|
+
|
296
|
+
pdlc_complex_t pdlc_complex_buffer_sum(const pdlc_complex_buffer_t *cbuf)
|
297
|
+
{
|
298
|
+
const size_t len = cbuf->length;
|
299
|
+
size_t alen, hlen, i;
|
300
|
+
float *copy;
|
301
|
+
pdlc_complex_t res = {0.0f, 0.0f};
|
302
|
+
|
303
|
+
if (len < 1)
|
304
|
+
return res;
|
305
|
+
|
306
|
+
copy = malloc(len*sizeof(float));
|
307
|
+
|
308
|
+
alen = len;
|
309
|
+
for (i = 0; i < len; i++)
|
310
|
+
copy[i] = cbuf->data[i].real;
|
311
|
+
while (alen > 1) {
|
312
|
+
hlen = alen / 2;
|
313
|
+
for (i = 0; i < hlen; i++)
|
314
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
315
|
+
if (alen % 2) {
|
316
|
+
copy[i] = copy[2*i];
|
317
|
+
alen = hlen + 1;
|
318
|
+
}
|
319
|
+
else
|
320
|
+
alen = hlen;
|
321
|
+
}
|
322
|
+
res.real = copy[0];
|
323
|
+
|
324
|
+
alen = len;
|
325
|
+
for (i = 0; i < len; i++)
|
326
|
+
copy[i] = cbuf->data[i].imag;
|
327
|
+
while (alen > 1) {
|
328
|
+
hlen = alen / 2;
|
329
|
+
for (i = 0; i < hlen; i++)
|
330
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
331
|
+
if (alen % 2) {
|
332
|
+
copy[i] = copy[2*i];
|
333
|
+
alen = hlen + 1;
|
334
|
+
}
|
335
|
+
else
|
336
|
+
alen = hlen;
|
337
|
+
}
|
338
|
+
res.imag = copy[0];
|
339
|
+
|
340
|
+
free(copy);
|
341
|
+
|
342
|
+
return res;
|
343
|
+
}
|
344
|
+
|
345
|
+
|
346
|
+
float pdlc_buffer_mean(const pdlc_buffer_t *fbuf)
|
347
|
+
{
|
348
|
+
const float sum = pdlc_buffer_sum(fbuf);
|
349
|
+
return sum / (float)fbuf->length;
|
350
|
+
}
|
351
|
+
|
352
|
+
|
353
|
+
pdlc_complex_t pdlc_complex_buffer_mean(const pdlc_complex_buffer_t *cbuf)
|
354
|
+
{
|
355
|
+
pdlc_complex_t res = pdlc_complex_buffer_sum(cbuf);
|
356
|
+
res.real = res.real / (float)cbuf->length;
|
357
|
+
res.imag = res.imag / (float)cbuf->length;
|
358
|
+
return res;
|
359
|
+
}
|
360
|
+
|
361
|
+
|
362
|
+
float pdlc_buffer_variance(const pdlc_buffer_t *fbuf)
|
363
|
+
{
|
364
|
+
const size_t len = fbuf->length;
|
365
|
+
size_t i, hlen, alen;
|
366
|
+
float *copy;
|
367
|
+
float res = 0.0f;
|
368
|
+
|
369
|
+
if (len < 1)
|
370
|
+
return 0.0f;
|
371
|
+
|
372
|
+
copy = malloc(len*sizeof(float));
|
373
|
+
|
374
|
+
/* Compute mean */
|
375
|
+
memcpy(copy, fbuf->data, len*sizeof(float));
|
376
|
+
alen = len;
|
377
|
+
while (alen > 1) {
|
378
|
+
hlen = alen / 2;
|
379
|
+
for (i = 0; i < hlen; i++)
|
380
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
381
|
+
if (alen % 2) {
|
382
|
+
copy[i] = copy[2*i];
|
383
|
+
alen = hlen + 1;
|
384
|
+
}
|
385
|
+
else
|
386
|
+
alen = hlen;
|
387
|
+
}
|
388
|
+
res = copy[0] / (float)len;
|
389
|
+
|
390
|
+
/* Compute variance */
|
391
|
+
for (i = 0; i < len; i++)
|
392
|
+
copy[i] = fbuf->data[i] * fbuf->data[i];
|
393
|
+
alen = len;
|
394
|
+
while (alen > 1) {
|
395
|
+
hlen = alen / 2;
|
396
|
+
for (i = 0; i < hlen; i++)
|
397
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
398
|
+
if (alen % 2) {
|
399
|
+
copy[i] = copy[2*i];
|
400
|
+
alen = hlen + 1;
|
401
|
+
}
|
402
|
+
else
|
403
|
+
alen = hlen;
|
404
|
+
}
|
405
|
+
res = copy[0] / (float)len - res*res;
|
406
|
+
|
407
|
+
free(copy);
|
408
|
+
|
409
|
+
return res;
|
410
|
+
}
|
411
|
+
|
412
|
+
|
413
|
+
float pdlc_buffer_standard_deviation(const pdlc_buffer_t *fbuf)
|
414
|
+
{
|
415
|
+
return sqrtf(pdlc_buffer_variance(fbuf));
|
416
|
+
}
|
417
|
+
|
418
|
+
|
419
|
+
float pdlc_buffer_prod(const pdlc_buffer_t *fbuf)
|
420
|
+
{
|
421
|
+
const size_t len = fbuf->length;
|
422
|
+
size_t i;
|
423
|
+
float res = 1.0f;
|
424
|
+
|
425
|
+
for (i = 0; i < len; i++)
|
426
|
+
res *= fbuf->data[i];
|
427
|
+
|
428
|
+
return res;
|
429
|
+
}
|
430
|
+
|
431
|
+
|
432
|
+
pdlc_complex_t pdlc_complex_buffer_prod(const pdlc_complex_buffer_t *cbuf)
|
433
|
+
{
|
434
|
+
const size_t len = cbuf->length;
|
435
|
+
size_t i;
|
436
|
+
pdlc_complex_t tmp;
|
437
|
+
pdlc_complex_t res = {1.0f, 0.0f};
|
438
|
+
|
439
|
+
for (i = 0; i < len; i++) {
|
440
|
+
tmp.real = res.real * cbuf->data[i].real - res.imag * cbuf->data[i].imag;
|
441
|
+
tmp.imag = res.real * cbuf->data[i].imag + res.imag * cbuf->data[i].real;
|
442
|
+
res = tmp;
|
443
|
+
}
|
444
|
+
|
445
|
+
return res;
|
446
|
+
}
|
447
|
+
|
448
|
+
|
449
|
+
pdlc_complex_t pdlc_complex_buffer_eprod(const pdlc_complex_buffer_t *cbuf)
|
450
|
+
{
|
451
|
+
const size_t len = cbuf->length;
|
452
|
+
size_t i;
|
453
|
+
pdlc_complex_t res = {1.0f, 1.0f};
|
454
|
+
|
455
|
+
for (i = 0; i < len; i++) {
|
456
|
+
res.real *= cbuf->data[i].real;
|
457
|
+
res.imag *= cbuf->data[i].imag;
|
458
|
+
}
|
459
|
+
|
460
|
+
return res;
|
461
|
+
}
|
462
|
+
|
463
|
+
|
464
|
+
float pdlc_buffer_fb_fs_sad(const pdlc_buffer_t *fbuf, float other)
|
465
|
+
{
|
466
|
+
const size_t len = fbuf->length;
|
467
|
+
size_t alen = len;
|
468
|
+
size_t i, hlen;
|
469
|
+
float *copy;
|
470
|
+
float res = 0.0f;
|
471
|
+
|
472
|
+
if (len < 1)
|
473
|
+
return 0.0f;
|
474
|
+
|
475
|
+
copy = malloc(len*sizeof(float));
|
476
|
+
for (i = 0; i < len; i++)
|
477
|
+
copy[i] = fabsf(fbuf->data[i] - other);
|
478
|
+
|
479
|
+
while (alen > 1) {
|
480
|
+
hlen = alen / 2;
|
481
|
+
for (i = 0; i < hlen; i++)
|
482
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
483
|
+
if (alen % 2) {
|
484
|
+
copy[i] = copy[2*i];
|
485
|
+
alen = hlen + 1;
|
486
|
+
}
|
487
|
+
else
|
488
|
+
alen = hlen;
|
489
|
+
}
|
490
|
+
|
491
|
+
res = copy[0];
|
492
|
+
|
493
|
+
free(copy);
|
494
|
+
|
495
|
+
return res;
|
496
|
+
}
|
497
|
+
|
498
|
+
|
499
|
+
float pdlc_buffer_fb_fb_sad(const pdlc_buffer_t *fbuf, const pdlc_buffer_t *other)
|
500
|
+
{
|
501
|
+
size_t len = fbuf->length;
|
502
|
+
size_t alen = len;
|
503
|
+
size_t i, hlen;
|
504
|
+
float *copy;
|
505
|
+
float res = 0.0f;
|
506
|
+
|
507
|
+
if (len > other->length)
|
508
|
+
len = other->length;
|
509
|
+
|
510
|
+
if (len < 1)
|
511
|
+
return 0.0f;
|
512
|
+
|
513
|
+
copy = malloc(len*sizeof(float));
|
514
|
+
for (i = 0; i < len; i++)
|
515
|
+
copy[i] = fabsf(fbuf->data[i] - other->data[i]);
|
516
|
+
|
517
|
+
while (alen > 1) {
|
518
|
+
hlen = alen / 2;
|
519
|
+
for (i = 0; i < hlen; i++)
|
520
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
521
|
+
if (alen % 2) {
|
522
|
+
copy[i] = copy[2*i];
|
523
|
+
alen = hlen + 1;
|
524
|
+
}
|
525
|
+
else
|
526
|
+
alen = hlen;
|
527
|
+
}
|
528
|
+
|
529
|
+
res = copy[0];
|
530
|
+
|
531
|
+
free(copy);
|
532
|
+
|
533
|
+
return res;
|
534
|
+
}
|
535
|
+
|
536
|
+
|
537
|
+
pdlc_complex_t pdlc_complex_buffer_cb_cs_sad(const pdlc_complex_buffer_t *cbuf, pdlc_complex_t other)
|
538
|
+
{
|
539
|
+
const size_t len = cbuf->length;
|
540
|
+
size_t alen, hlen, i;
|
541
|
+
float *copy;
|
542
|
+
pdlc_complex_t res = {0.0f, 0.0f};
|
543
|
+
|
544
|
+
if (len < 1)
|
545
|
+
return res;
|
546
|
+
|
547
|
+
copy = malloc(len*sizeof(float));
|
548
|
+
|
549
|
+
alen = len;
|
550
|
+
for (i = 0; i < len; i++)
|
551
|
+
copy[i] = fabsf(cbuf->data[i].real - other.real);
|
552
|
+
while (alen > 1) {
|
553
|
+
hlen = alen / 2;
|
554
|
+
for (i = 0; i < hlen; i++)
|
555
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
556
|
+
if (alen % 2) {
|
557
|
+
copy[i] = copy[2*i];
|
558
|
+
alen = hlen + 1;
|
559
|
+
}
|
560
|
+
else
|
561
|
+
alen = hlen;
|
562
|
+
}
|
563
|
+
res.real = copy[0];
|
564
|
+
|
565
|
+
alen = len;
|
566
|
+
for (i = 0; i < len; i++)
|
567
|
+
copy[i] = fabsf(cbuf->data[i].imag - other.imag);
|
568
|
+
while (alen > 1) {
|
569
|
+
hlen = alen / 2;
|
570
|
+
for (i = 0; i < hlen; i++)
|
571
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
572
|
+
if (alen % 2) {
|
573
|
+
copy[i] = copy[2*i];
|
574
|
+
alen = hlen + 1;
|
575
|
+
}
|
576
|
+
else
|
577
|
+
alen = hlen;
|
578
|
+
}
|
579
|
+
res.imag = copy[0];
|
580
|
+
|
581
|
+
free(copy);
|
582
|
+
|
583
|
+
return res;
|
584
|
+
}
|
585
|
+
|
586
|
+
|
587
|
+
pdlc_complex_t pdlc_complex_buffer_cb_cb_sad(const pdlc_complex_buffer_t *cbuf, const pdlc_complex_buffer_t *other)
|
588
|
+
{
|
589
|
+
size_t len = cbuf->length;
|
590
|
+
size_t alen, hlen, i;
|
591
|
+
float *copy;
|
592
|
+
pdlc_complex_t res = {0.0f, 0.0f};
|
593
|
+
|
594
|
+
if (len > other->length)
|
595
|
+
len = other->length;
|
596
|
+
|
597
|
+
if (len < 1)
|
598
|
+
return res;
|
599
|
+
|
600
|
+
copy = malloc(len*sizeof(float));
|
601
|
+
|
602
|
+
alen = len;
|
603
|
+
for (i = 0; i < len; i++)
|
604
|
+
copy[i] = fabsf(cbuf->data[i].real - other->data[i].real);
|
605
|
+
while (alen > 1) {
|
606
|
+
hlen = alen / 2;
|
607
|
+
for (i = 0; i < hlen; i++)
|
608
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
609
|
+
if (alen % 2) {
|
610
|
+
copy[i] = copy[2*i];
|
611
|
+
alen = hlen + 1;
|
612
|
+
}
|
613
|
+
else
|
614
|
+
alen = hlen;
|
615
|
+
}
|
616
|
+
res.real = copy[0];
|
617
|
+
|
618
|
+
alen = len;
|
619
|
+
for (i = 0; i < len; i++)
|
620
|
+
copy[i] = fabsf(cbuf->data[i].imag - other->data[i].imag);
|
621
|
+
while (alen > 1) {
|
622
|
+
hlen = alen / 2;
|
623
|
+
for (i = 0; i < hlen; i++)
|
624
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
625
|
+
if (alen % 2) {
|
626
|
+
copy[i] = copy[2*i];
|
627
|
+
alen = hlen + 1;
|
628
|
+
}
|
629
|
+
else
|
630
|
+
alen = hlen;
|
631
|
+
}
|
632
|
+
res.imag = copy[0];
|
633
|
+
|
634
|
+
free(copy);
|
635
|
+
|
636
|
+
return res;
|
637
|
+
}
|
638
|
+
|
639
|
+
|
640
|
+
float pdlc_buffer_fb_fs_ssd(const pdlc_buffer_t *fbuf, float other)
|
641
|
+
{
|
642
|
+
const size_t len = fbuf->length;
|
643
|
+
size_t alen = len;
|
644
|
+
size_t i, hlen;
|
645
|
+
float *copy;
|
646
|
+
float res = 0.0f;
|
647
|
+
|
648
|
+
if (len < 1)
|
649
|
+
return 0.0f;
|
650
|
+
|
651
|
+
copy = malloc(len*sizeof(float));
|
652
|
+
for (i = 0; i < len; i++)
|
653
|
+
copy[i] = (fbuf->data[i] - other)*(fbuf->data[i] - other);
|
654
|
+
|
655
|
+
while (alen > 1) {
|
656
|
+
hlen = alen / 2;
|
657
|
+
for (i = 0; i < hlen; i++)
|
658
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
659
|
+
if (alen % 2) {
|
660
|
+
copy[i] = copy[2*i];
|
661
|
+
alen = hlen + 1;
|
662
|
+
}
|
663
|
+
else
|
664
|
+
alen = hlen;
|
665
|
+
}
|
666
|
+
|
667
|
+
res = copy[0];
|
668
|
+
|
669
|
+
free(copy);
|
670
|
+
|
671
|
+
return res;
|
672
|
+
}
|
673
|
+
|
674
|
+
|
675
|
+
float pdlc_buffer_fb_fb_ssd(const pdlc_buffer_t *fbuf, const pdlc_buffer_t *other)
|
676
|
+
{
|
677
|
+
size_t len = fbuf->length;
|
678
|
+
size_t alen = len;
|
679
|
+
size_t i, hlen;
|
680
|
+
float *copy;
|
681
|
+
float res = 0.0f;
|
682
|
+
|
683
|
+
if (len > other->length)
|
684
|
+
len = other->length;
|
685
|
+
|
686
|
+
if (len < 1)
|
687
|
+
return 0.0f;
|
688
|
+
|
689
|
+
copy = malloc(len*sizeof(float));
|
690
|
+
for (i = 0; i < len; i++)
|
691
|
+
copy[i] = (fbuf->data[i] - other->data[i])*(fbuf->data[i] - other->data[i]);
|
692
|
+
|
693
|
+
while (alen > 1) {
|
694
|
+
hlen = alen / 2;
|
695
|
+
for (i = 0; i < hlen; i++)
|
696
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
697
|
+
if (alen % 2) {
|
698
|
+
copy[i] = copy[2*i];
|
699
|
+
alen = hlen + 1;
|
700
|
+
}
|
701
|
+
else
|
702
|
+
alen = hlen;
|
703
|
+
}
|
704
|
+
|
705
|
+
res = copy[0];
|
706
|
+
|
707
|
+
free(copy);
|
708
|
+
|
709
|
+
return res;
|
710
|
+
}
|
711
|
+
|
712
|
+
|
713
|
+
pdlc_complex_t pdlc_complex_buffer_cb_cs_essd(const pdlc_complex_buffer_t *cbuf, pdlc_complex_t other)
|
714
|
+
{
|
715
|
+
const size_t len = cbuf->length;
|
716
|
+
size_t alen, hlen, i;
|
717
|
+
float *copy;
|
718
|
+
pdlc_complex_t res = {0.0f, 0.0f};
|
719
|
+
|
720
|
+
if (len < 1)
|
721
|
+
return res;
|
722
|
+
|
723
|
+
copy = malloc(len*sizeof(float));
|
724
|
+
|
725
|
+
alen = len;
|
726
|
+
for (i = 0; i < len; i++)
|
727
|
+
copy[i] = (cbuf->data[i].real - other.real)*(cbuf->data[i].real - other.real);
|
728
|
+
while (alen > 1) {
|
729
|
+
hlen = alen / 2;
|
730
|
+
for (i = 0; i < hlen; i++)
|
731
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
732
|
+
if (alen % 2) {
|
733
|
+
copy[i] = copy[2*i];
|
734
|
+
alen = hlen + 1;
|
735
|
+
}
|
736
|
+
else
|
737
|
+
alen = hlen;
|
738
|
+
}
|
739
|
+
res.real = copy[0];
|
740
|
+
|
741
|
+
alen = len;
|
742
|
+
for (i = 0; i < len; i++)
|
743
|
+
copy[i] = (cbuf->data[i].imag - other.imag)*(cbuf->data[i].imag - other.imag);
|
744
|
+
while (alen > 1) {
|
745
|
+
hlen = alen / 2;
|
746
|
+
for (i = 0; i < hlen; i++)
|
747
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
748
|
+
if (alen % 2) {
|
749
|
+
copy[i] = copy[2*i];
|
750
|
+
alen = hlen + 1;
|
751
|
+
}
|
752
|
+
else
|
753
|
+
alen = hlen;
|
754
|
+
}
|
755
|
+
res.imag = copy[0];
|
756
|
+
|
757
|
+
free(copy);
|
758
|
+
|
759
|
+
return res;
|
760
|
+
}
|
761
|
+
|
762
|
+
|
763
|
+
pdlc_complex_t pdlc_complex_buffer_cb_cb_essd(const pdlc_complex_buffer_t *cbuf, const pdlc_complex_buffer_t *other)
|
764
|
+
{
|
765
|
+
size_t len = cbuf->length;
|
766
|
+
size_t alen, hlen, i;
|
767
|
+
float *copy;
|
768
|
+
pdlc_complex_t res = {0.0f, 0.0f};
|
769
|
+
|
770
|
+
if (len > other->length)
|
771
|
+
len = other->length;
|
772
|
+
|
773
|
+
if (len < 1)
|
774
|
+
return res;
|
775
|
+
|
776
|
+
copy = malloc(len*sizeof(float));
|
777
|
+
|
778
|
+
alen = len;
|
779
|
+
for (i = 0; i < len; i++)
|
780
|
+
copy[i] = (cbuf->data[i].real - other->data[i].real)*(cbuf->data[i].real - other->data[i].real);
|
781
|
+
while (alen > 1) {
|
782
|
+
hlen = alen / 2;
|
783
|
+
for (i = 0; i < hlen; i++)
|
784
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
785
|
+
if (alen % 2) {
|
786
|
+
copy[i] = copy[2*i];
|
787
|
+
alen = hlen + 1;
|
788
|
+
}
|
789
|
+
else
|
790
|
+
alen = hlen;
|
791
|
+
}
|
792
|
+
res.real = copy[0];
|
793
|
+
|
794
|
+
alen = len;
|
795
|
+
for (i = 0; i < len; i++)
|
796
|
+
copy[i] = (cbuf->data[i].imag - other->data[i].imag)*(cbuf->data[i].imag - other->data[i].imag);
|
797
|
+
while (alen > 1) {
|
798
|
+
hlen = alen / 2;
|
799
|
+
for (i = 0; i < hlen; i++)
|
800
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
801
|
+
if (alen % 2) {
|
802
|
+
copy[i] = copy[2*i];
|
803
|
+
alen = hlen + 1;
|
804
|
+
}
|
805
|
+
else
|
806
|
+
alen = hlen;
|
807
|
+
}
|
808
|
+
res.imag = copy[0];
|
809
|
+
|
810
|
+
free(copy);
|
811
|
+
|
812
|
+
return res;
|
813
|
+
}
|
814
|
+
|
815
|
+
|
816
|
+
pdlc_complex_t pdlc_complex_buffer_cb_cs_ssd(const pdlc_complex_buffer_t *cbuf, pdlc_complex_t other)
|
817
|
+
{
|
818
|
+
const size_t len = cbuf->length;
|
819
|
+
size_t alen, hlen, i;
|
820
|
+
float *copy;
|
821
|
+
pdlc_complex_t tmp;
|
822
|
+
pdlc_complex_t res = {0.0f, 0.0f};
|
823
|
+
|
824
|
+
if (len < 1)
|
825
|
+
return res;
|
826
|
+
|
827
|
+
copy = malloc(len*sizeof(float));
|
828
|
+
|
829
|
+
alen = len;
|
830
|
+
for (i = 0; i < len; i++) {
|
831
|
+
tmp.real = cbuf->data[i].real - other.real;
|
832
|
+
tmp.imag = cbuf->data[i].imag - other.imag;
|
833
|
+
copy[i] = tmp.real * tmp.real - tmp.imag * tmp.imag;
|
834
|
+
}
|
835
|
+
while (alen > 1) {
|
836
|
+
hlen = alen / 2;
|
837
|
+
for (i = 0; i < hlen; i++)
|
838
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
839
|
+
if (alen % 2) {
|
840
|
+
copy[i] = copy[2*i];
|
841
|
+
alen = hlen + 1;
|
842
|
+
}
|
843
|
+
else
|
844
|
+
alen = hlen;
|
845
|
+
}
|
846
|
+
res.real = copy[0];
|
847
|
+
|
848
|
+
alen = len;
|
849
|
+
for (i = 0; i < len; i++) {
|
850
|
+
tmp.real = cbuf->data[i].real - other.real;
|
851
|
+
tmp.imag = cbuf->data[i].imag - other.imag;
|
852
|
+
copy[i] = 2.0f * tmp.real * tmp.imag;
|
853
|
+
}
|
854
|
+
while (alen > 1) {
|
855
|
+
hlen = alen / 2;
|
856
|
+
for (i = 0; i < hlen; i++)
|
857
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
858
|
+
if (alen % 2) {
|
859
|
+
copy[i] = copy[2*i];
|
860
|
+
alen = hlen + 1;
|
861
|
+
}
|
862
|
+
else
|
863
|
+
alen = hlen;
|
864
|
+
}
|
865
|
+
res.imag = copy[0];
|
866
|
+
|
867
|
+
free(copy);
|
868
|
+
|
869
|
+
return res;
|
870
|
+
}
|
871
|
+
|
872
|
+
|
873
|
+
pdlc_complex_t pdlc_complex_buffer_cb_cb_ssd(const pdlc_complex_buffer_t *cbuf, const pdlc_complex_buffer_t *other)
|
874
|
+
{
|
875
|
+
size_t len = cbuf->length;
|
876
|
+
size_t alen, hlen, i;
|
877
|
+
float *copy;
|
878
|
+
pdlc_complex_t tmp;
|
879
|
+
pdlc_complex_t res = {0.0f, 0.0f};
|
880
|
+
|
881
|
+
if (len > other->length)
|
882
|
+
len = other->length;
|
883
|
+
|
884
|
+
if (len < 1)
|
885
|
+
return res;
|
886
|
+
|
887
|
+
copy = malloc(len*sizeof(float));
|
888
|
+
|
889
|
+
alen = len;
|
890
|
+
for (i = 0; i < len; i++) {
|
891
|
+
tmp.real = cbuf->data[i].real - other->data[i].real;
|
892
|
+
tmp.imag = cbuf->data[i].imag - other->data[i].imag;
|
893
|
+
copy[i] = tmp.real * tmp.real - tmp.imag * tmp.imag;
|
894
|
+
}
|
895
|
+
while (alen > 1) {
|
896
|
+
hlen = alen / 2;
|
897
|
+
for (i = 0; i < hlen; i++)
|
898
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
899
|
+
if (alen % 2) {
|
900
|
+
copy[i] = copy[2*i];
|
901
|
+
alen = hlen + 1;
|
902
|
+
}
|
903
|
+
else
|
904
|
+
alen = hlen;
|
905
|
+
}
|
906
|
+
res.real = copy[0];
|
907
|
+
|
908
|
+
alen = len;
|
909
|
+
for (i = 0; i < len; i++)
|
910
|
+
for (i = 0; i < len; i++) {
|
911
|
+
tmp.real = cbuf->data[i].real - other->data[i].real;
|
912
|
+
tmp.imag = cbuf->data[i].imag - other->data[i].imag;
|
913
|
+
copy[i] = 2.0f * tmp.real * tmp.imag;
|
914
|
+
}
|
915
|
+
while (alen > 1) {
|
916
|
+
hlen = alen / 2;
|
917
|
+
for (i = 0; i < hlen; i++)
|
918
|
+
copy[i] = copy[2*i] + copy[2*i+1];
|
919
|
+
if (alen % 2) {
|
920
|
+
copy[i] = copy[2*i];
|
921
|
+
alen = hlen + 1;
|
922
|
+
}
|
923
|
+
else
|
924
|
+
alen = hlen;
|
925
|
+
}
|
926
|
+
res.imag = copy[0];
|
927
|
+
|
928
|
+
free(copy);
|
929
|
+
|
930
|
+
return res;
|
931
|
+
}
|
932
|
+
|
933
|
+
|