2 * Copyright (C) <2016> Wim Taymans <wim.taymans@gmail.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
20 #if defined (HAVE_XMMINTRIN_H) && defined(__SSE__)
21 #include <xmmintrin.h>
24 inner_product_gfloat_full_1_sse (gfloat * o, const gfloat * a,
25 const gfloat * b, gint len, const gfloat * icoeff, gint bstride)
28 __m128 sum = _mm_setzero_ps ();
30 for (; i < len; i += 8) {
32 _mm_add_ps (sum, _mm_mul_ps (_mm_loadu_ps (a + i + 0),
33 _mm_load_ps (b + i + 0)));
35 _mm_add_ps (sum, _mm_mul_ps (_mm_loadu_ps (a + i + 4),
36 _mm_load_ps (b + i + 4)));
38 sum = _mm_add_ps (sum, _mm_movehl_ps (sum, sum));
39 sum = _mm_add_ss (sum, _mm_shuffle_ps (sum, sum, 0x55));
40 _mm_store_ss (o, sum);
44 inner_product_gfloat_linear_1_sse (gfloat * o, const gfloat * a,
45 const gfloat * b, gint len, const gfloat * icoeff, gint bstride)
49 const gfloat *c[2] = {(gfloat*)((gint8*)b + 0*bstride),
50 (gfloat*)((gint8*)b + 1*bstride)};
52 sum[0] = sum[1] = _mm_setzero_ps ();
54 for (; i < len; i += 8) {
55 t = _mm_loadu_ps (a + i + 0);
56 sum[0] = _mm_add_ps (sum[0], _mm_mul_ps (t, _mm_load_ps (c[0] + i + 0)));
57 sum[1] = _mm_add_ps (sum[1], _mm_mul_ps (t, _mm_load_ps (c[1] + i + 0)));
58 t = _mm_loadu_ps (a + i + 4);
59 sum[0] = _mm_add_ps (sum[0], _mm_mul_ps (t, _mm_load_ps (c[0] + i + 4)));
60 sum[1] = _mm_add_ps (sum[1], _mm_mul_ps (t, _mm_load_ps (c[1] + i + 4)));
62 sum[0] = _mm_mul_ps (_mm_sub_ps (sum[0], sum[1]), _mm_load1_ps (icoeff));
63 sum[0] = _mm_add_ps (sum[0], sum[1]);
64 sum[0] = _mm_add_ps (sum[0], _mm_movehl_ps (sum[0], sum[0]));
65 sum[0] = _mm_add_ss (sum[0], _mm_shuffle_ps (sum[0], sum[0], 0x55));
66 _mm_store_ss (o, sum[0]);
70 inner_product_gfloat_cubic_1_sse (gfloat * o, const gfloat * a,
71 const gfloat * b, gint len, const gfloat * icoeff, gint bstride)
75 __m128 t, f = _mm_loadu_ps(icoeff);
76 const gfloat *c[4] = {(gfloat*)((gint8*)b + 0*bstride),
77 (gfloat*)((gint8*)b + 1*bstride),
78 (gfloat*)((gint8*)b + 2*bstride),
79 (gfloat*)((gint8*)b + 3*bstride)};
81 sum[0] = sum[1] = sum[2] = sum[3] = _mm_setzero_ps ();
83 for (; i < len; i += 4) {
84 t = _mm_loadu_ps (a + i);
85 sum[0] = _mm_add_ps (sum[0], _mm_mul_ps (t, _mm_load_ps (c[0] + i)));
86 sum[1] = _mm_add_ps (sum[1], _mm_mul_ps (t, _mm_load_ps (c[1] + i)));
87 sum[2] = _mm_add_ps (sum[2], _mm_mul_ps (t, _mm_load_ps (c[2] + i)));
88 sum[3] = _mm_add_ps (sum[3], _mm_mul_ps (t, _mm_load_ps (c[3] + i)));
90 sum[0] = _mm_mul_ps (sum[0], _mm_shuffle_ps (f, f, 0x00));
91 sum[1] = _mm_mul_ps (sum[1], _mm_shuffle_ps (f, f, 0x55));
92 sum[2] = _mm_mul_ps (sum[2], _mm_shuffle_ps (f, f, 0xaa));
93 sum[3] = _mm_mul_ps (sum[3], _mm_shuffle_ps (f, f, 0xff));
94 sum[0] = _mm_add_ps (sum[0], sum[1]);
95 sum[2] = _mm_add_ps (sum[2], sum[3]);
96 sum[0] = _mm_add_ps (sum[0], sum[2]);
97 sum[0] = _mm_add_ps (sum[0], _mm_movehl_ps (sum[0], sum[0]));
98 sum[0] = _mm_add_ss (sum[0], _mm_shuffle_ps (sum[0], sum[0], 0x55));
99 _mm_store_ss (o, sum[0]);
102 MAKE_RESAMPLE_FUNC (gfloat, full, 1, sse);
103 MAKE_RESAMPLE_FUNC (gfloat, linear, 1, sse);
104 MAKE_RESAMPLE_FUNC (gfloat, cubic, 1, sse);
107 interpolate_gfloat_linear_sse (gpointer op, const gpointer ap,
108 gint len, const gpointer icp, gint astride)
111 gfloat *o = op, *a = ap, *ic = icp;
113 const gfloat *c[2] = {(gfloat*)((gint8*)a + 0*astride),
114 (gfloat*)((gint8*)a + 1*astride)};
116 f[0] = _mm_load1_ps (ic+0);
117 f[1] = _mm_load1_ps (ic+1);
119 for (i = 0; i < len; i += 8) {
120 t1 = _mm_mul_ps (_mm_load_ps (c[0] + i + 0), f[0]);
121 t2 = _mm_mul_ps (_mm_load_ps (c[1] + i + 0), f[1]);
122 _mm_store_ps (o + i + 0, _mm_add_ps (t1, t2));
124 t1 = _mm_mul_ps (_mm_load_ps (c[0] + i + 4), f[0]);
125 t2 = _mm_mul_ps (_mm_load_ps (c[1] + i + 4), f[1]);
126 _mm_store_ps (o + i + 4, _mm_add_ps (t1, t2));
131 interpolate_gfloat_cubic_sse (gpointer op, const gpointer ap,
132 gint len, const gpointer icp, gint astride)
135 gfloat *o = op, *a = ap, *ic = icp;
137 const gfloat *c[4] = {(gfloat*)((gint8*)a + 0*astride),
138 (gfloat*)((gint8*)a + 1*astride),
139 (gfloat*)((gint8*)a + 2*astride),
140 (gfloat*)((gint8*)a + 3*astride)};
142 f[0] = _mm_load1_ps (ic+0);
143 f[1] = _mm_load1_ps (ic+1);
144 f[2] = _mm_load1_ps (ic+2);
145 f[3] = _mm_load1_ps (ic+3);
147 for (i = 0; i < len; i += 4) {
148 t[0] = _mm_mul_ps (_mm_load_ps (c[0] + i + 0), f[0]);
149 t[1] = _mm_mul_ps (_mm_load_ps (c[1] + i + 0), f[1]);
150 t[2] = _mm_mul_ps (_mm_load_ps (c[2] + i + 0), f[2]);
151 t[3] = _mm_mul_ps (_mm_load_ps (c[3] + i + 0), f[3]);
152 t[0] = _mm_add_ps (t[0], t[1]);
153 t[2] = _mm_add_ps (t[2], t[3]);
154 _mm_store_ps (o + i + 0, _mm_add_ps (t[0], t[2]));
160 #if defined (HAVE_EMMINTRIN_H) && defined(__SSE2__)
161 #include <emmintrin.h>
164 inner_product_gint16_full_1_sse2 (gint16 * o, const gint16 * a,
165 const gint16 * b, gint len, const gint16 * icoeff, gint bstride)
170 sum = _mm_setzero_si128 ();
172 for (i = 0; i < len; i += 16) {
173 t = _mm_loadu_si128 ((__m128i *) (a + i));
174 sum = _mm_add_epi32 (sum, _mm_madd_epi16 (t, _mm_load_si128 ((__m128i *) (b + i + 0))));
176 t = _mm_loadu_si128 ((__m128i *) (a + i + 8));
177 sum = _mm_add_epi32 (sum, _mm_madd_epi16 (t, _mm_load_si128 ((__m128i *) (b + i + 8))));
179 sum = _mm_add_epi32 (sum, _mm_shuffle_epi32 (sum, _MM_SHUFFLE (2, 3, 2, 3)));
180 sum = _mm_add_epi32 (sum, _mm_shuffle_epi32 (sum, _MM_SHUFFLE (1, 1, 1, 1)));
182 sum = _mm_add_epi32 (sum, _mm_set1_epi32 (1 << (PRECISION_S16 - 1)));
183 sum = _mm_srai_epi32 (sum, PRECISION_S16);
184 sum = _mm_packs_epi32 (sum, sum);
185 *o = _mm_extract_epi16 (sum, 0);
189 inner_product_gint16_linear_1_sse2 (gint16 * o, const gint16 * a,
190 const gint16 * b, gint len, const gint16 * icoeff, gint bstride)
194 __m128i f = _mm_set_epi64x (0, *((gint64*)icoeff));
195 const gint16 *c[2] = {(gint16*)((gint8*)b + 0*bstride),
196 (gint16*)((gint8*)b + 1*bstride)};
198 sum[0] = sum[1] = _mm_setzero_si128 ();
199 f = _mm_unpacklo_epi16 (f, sum[0]);
201 for (; i < len; i += 16) {
202 t = _mm_loadu_si128 ((__m128i *) (a + i + 0));
203 sum[0] = _mm_add_epi32 (sum[0], _mm_madd_epi16 (t, _mm_load_si128 ((__m128i *) (c[0] + i + 0))));
204 sum[1] = _mm_add_epi32 (sum[1], _mm_madd_epi16 (t, _mm_load_si128 ((__m128i *) (c[1] + i + 0))));
206 t = _mm_loadu_si128 ((__m128i *) (a + i + 8));
207 sum[0] = _mm_add_epi32 (sum[0], _mm_madd_epi16 (t, _mm_load_si128 ((__m128i *) (c[0] + i + 8))));
208 sum[1] = _mm_add_epi32 (sum[1], _mm_madd_epi16 (t, _mm_load_si128 ((__m128i *) (c[1] + i + 8))));
210 sum[0] = _mm_srai_epi32 (sum[0], PRECISION_S16);
211 sum[1] = _mm_srai_epi32 (sum[1], PRECISION_S16);
213 sum[0] = _mm_madd_epi16 (sum[0], _mm_shuffle_epi32 (f, _MM_SHUFFLE (0, 0, 0, 0)));
214 sum[1] = _mm_madd_epi16 (sum[1], _mm_shuffle_epi32 (f, _MM_SHUFFLE (1, 1, 1, 1)));
215 sum[0] = _mm_add_epi32 (sum[0], sum[1]);
217 sum[0] = _mm_add_epi32 (sum[0], _mm_shuffle_epi32 (sum[0], _MM_SHUFFLE (2, 3, 2, 3)));
218 sum[0] = _mm_add_epi32 (sum[0], _mm_shuffle_epi32 (sum[0], _MM_SHUFFLE (1, 1, 1, 1)));
220 sum[0] = _mm_add_epi32 (sum[0], _mm_set1_epi32 (1 << (PRECISION_S16 - 1)));
221 sum[0] = _mm_srai_epi32 (sum[0], PRECISION_S16);
222 sum[0] = _mm_packs_epi32 (sum[0], sum[0]);
223 *o = _mm_extract_epi16 (sum[0], 0);
227 inner_product_gint16_cubic_1_sse2 (gint16 * o, const gint16 * a,
228 const gint16 * b, gint len, const gint16 * icoeff, gint bstride)
231 __m128i sum[4], t[4];
232 __m128i f = _mm_set_epi64x (0, *((long long*)icoeff));
233 const gint16 *c[4] = {(gint16*)((gint8*)b + 0*bstride),
234 (gint16*)((gint8*)b + 1*bstride),
235 (gint16*)((gint8*)b + 2*bstride),
236 (gint16*)((gint8*)b + 3*bstride)};
238 sum[0] = sum[1] = sum[2] = sum[3] = _mm_setzero_si128 ();
239 f = _mm_unpacklo_epi16 (f, sum[0]);
241 for (; i < len; i += 8) {
242 t[0] = _mm_loadu_si128 ((__m128i *) (a + i));
243 sum[0] = _mm_add_epi32 (sum[0], _mm_madd_epi16 (t[0], _mm_load_si128 ((__m128i *) (c[0] + i))));
244 sum[1] = _mm_add_epi32 (sum[1], _mm_madd_epi16 (t[0], _mm_load_si128 ((__m128i *) (c[1] + i))));
245 sum[2] = _mm_add_epi32 (sum[2], _mm_madd_epi16 (t[0], _mm_load_si128 ((__m128i *) (c[2] + i))));
246 sum[3] = _mm_add_epi32 (sum[3], _mm_madd_epi16 (t[0], _mm_load_si128 ((__m128i *) (c[3] + i))));
248 t[0] = _mm_unpacklo_epi32 (sum[0], sum[1]);
249 t[1] = _mm_unpacklo_epi32 (sum[2], sum[3]);
250 t[2] = _mm_unpackhi_epi32 (sum[0], sum[1]);
251 t[3] = _mm_unpackhi_epi32 (sum[2], sum[3]);
253 sum[0] = _mm_add_epi32 (_mm_unpacklo_epi64(t[0], t[1]), _mm_unpackhi_epi64(t[0], t[1]));
254 sum[2] = _mm_add_epi32 (_mm_unpacklo_epi64(t[2], t[3]), _mm_unpackhi_epi64(t[2], t[3]));
255 sum[0] = _mm_add_epi32 (sum[0], sum[2]);
257 sum[0] = _mm_srai_epi32 (sum[0], PRECISION_S16);
258 sum[0] = _mm_madd_epi16 (sum[0], f);
260 sum[0] = _mm_add_epi32 (sum[0], _mm_shuffle_epi32 (sum[0], _MM_SHUFFLE (2, 3, 2, 3)));
261 sum[0] = _mm_add_epi32 (sum[0], _mm_shuffle_epi32 (sum[0], _MM_SHUFFLE (1, 1, 1, 1)));
263 sum[0] = _mm_add_epi32 (sum[0], _mm_set1_epi32 (1 << (PRECISION_S16 - 1)));
264 sum[0] = _mm_srai_epi32 (sum[0], PRECISION_S16);
265 sum[0] = _mm_packs_epi32 (sum[0], sum[0]);
266 *o = _mm_extract_epi16 (sum[0], 0);
270 inner_product_gdouble_full_1_sse2 (gdouble * o, const gdouble * a,
271 const gdouble * b, gint len, const gdouble * icoeff, gint bstride)
274 __m128d sum = _mm_setzero_pd ();
276 for (; i < len; i += 8) {
278 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + i + 0),
279 _mm_load_pd (b + i + 0)));
281 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + i + 2),
282 _mm_load_pd (b + i + 2)));
284 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + i + 4),
285 _mm_load_pd (b + i + 4)));
287 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + i + 6),
288 _mm_load_pd (b + i + 6)));
290 sum = _mm_add_sd (sum, _mm_unpackhi_pd (sum, sum));
291 _mm_store_sd (o, sum);
295 inner_product_gdouble_linear_1_sse2 (gdouble * o, const gdouble * a,
296 const gdouble * b, gint len, const gdouble * icoeff, gint bstride)
300 const gdouble *c[2] = {(gdouble*)((gint8*)b + 0*bstride),
301 (gdouble*)((gint8*)b + 1*bstride)};
303 sum[0] = sum[1] = _mm_setzero_pd ();
305 for (; i < len; i += 4) {
306 t = _mm_loadu_pd (a + i + 0);
307 sum[0] = _mm_add_pd (sum[0], _mm_mul_pd (t, _mm_load_pd (c[0] + i + 0)));
308 sum[1] = _mm_add_pd (sum[1], _mm_mul_pd (t, _mm_load_pd (c[1] + i + 0)));
309 t = _mm_loadu_pd (a + i + 2);
310 sum[0] = _mm_add_pd (sum[0], _mm_mul_pd (t, _mm_load_pd (c[0] + i + 2)));
311 sum[1] = _mm_add_pd (sum[1], _mm_mul_pd (t, _mm_load_pd (c[1] + i + 2)));
313 sum[0] = _mm_mul_pd (_mm_sub_pd (sum[0], sum[1]), _mm_load1_pd (icoeff));
314 sum[0] = _mm_add_pd (sum[0], sum[1]);
315 sum[0] = _mm_add_sd (sum[0], _mm_unpackhi_pd (sum[0], sum[0]));
316 _mm_store_sd (o, sum[0]);
320 inner_product_gdouble_cubic_1_sse2 (gdouble * o, const gdouble * a,
321 const gdouble * b, gint len, const gdouble * icoeff, gint bstride)
324 __m128d f[2], sum[4], t;
325 const gdouble *c[4] = {(gdouble*)((gint8*)b + 0*bstride),
326 (gdouble*)((gint8*)b + 1*bstride),
327 (gdouble*)((gint8*)b + 2*bstride),
328 (gdouble*)((gint8*)b + 3*bstride)};
330 f[0] = _mm_loadu_pd (icoeff + 0);
331 f[1] = _mm_loadu_pd (icoeff + 2);
332 sum[0] = sum[1] = sum[2] = sum[3] = _mm_setzero_pd ();
334 for (i = 0; i < len; i += 2) {
335 t = _mm_loadu_pd (a + i + 0);
336 sum[0] = _mm_add_pd (sum[0], _mm_mul_pd (t, _mm_load_pd (c[0] + i)));
337 sum[1] = _mm_add_pd (sum[1], _mm_mul_pd (t, _mm_load_pd (c[1] + i)));
338 sum[2] = _mm_add_pd (sum[2], _mm_mul_pd (t, _mm_load_pd (c[2] + i)));
339 sum[3] = _mm_add_pd (sum[3], _mm_mul_pd (t, _mm_load_pd (c[3] + i)));
341 sum[0] = _mm_mul_pd (sum[0], _mm_shuffle_pd (f[0], f[0], _MM_SHUFFLE2 (0, 0)));
342 sum[1] = _mm_mul_pd (sum[1], _mm_shuffle_pd (f[0], f[0], _MM_SHUFFLE2 (1, 1)));
343 sum[2] = _mm_mul_pd (sum[2], _mm_shuffle_pd (f[1], f[1], _MM_SHUFFLE2 (0, 0)));
344 sum[3] = _mm_mul_pd (sum[3], _mm_shuffle_pd (f[1], f[1], _MM_SHUFFLE2 (1, 1)));
345 sum[0] = _mm_add_pd (sum[0], sum[1]);
346 sum[2] = _mm_add_pd (sum[2], sum[3]);
347 sum[0] = _mm_add_pd (sum[0], sum[2]);
348 sum[0] = _mm_add_sd (sum[0], _mm_unpackhi_pd (sum[0], sum[0]));
349 _mm_store_sd (o, sum[0]);
352 MAKE_RESAMPLE_FUNC (gint16, full, 1, sse2);
353 MAKE_RESAMPLE_FUNC (gint16, linear, 1, sse2);
354 MAKE_RESAMPLE_FUNC (gint16, cubic, 1, sse2);
356 MAKE_RESAMPLE_FUNC (gdouble, full, 1, sse2);
357 MAKE_RESAMPLE_FUNC (gdouble, linear, 1, sse2);
358 MAKE_RESAMPLE_FUNC (gdouble, cubic, 1, sse2);
361 interpolate_gint16_linear_sse2 (gpointer op, const gpointer ap,
362 gint len, const gpointer icp, gint astride)
365 gint16 *o = op, *a = ap, *ic = icp;
366 __m128i ta, tb, t1, t2;
367 __m128i f = _mm_set_epi64x (0, *((gint64*)ic));
368 const gint16 *c[2] = {(gint16*)((gint8*)a + 0*astride),
369 (gint16*)((gint8*)a + 1*astride)};
371 f = _mm_unpacklo_epi32 (f, f);
372 f = _mm_unpacklo_epi64 (f, f);
374 for (; i < len; i += 8) {
375 ta = _mm_load_si128 ((__m128i *) (c[0] + i));
376 tb = _mm_load_si128 ((__m128i *) (c[1] + i));
378 t1 = _mm_madd_epi16 (_mm_unpacklo_epi16 (ta, tb), f);
379 t2 = _mm_madd_epi16 (_mm_unpackhi_epi16 (ta, tb), f);
381 t1 = _mm_add_epi32 (t1, _mm_set1_epi32 (1 << (PRECISION_S16 - 1)));
382 t2 = _mm_add_epi32 (t2, _mm_set1_epi32 (1 << (PRECISION_S16 - 1)));
384 t1 = _mm_srai_epi32 (t1, PRECISION_S16);
385 t2 = _mm_srai_epi32 (t2, PRECISION_S16);
387 t1 = _mm_packs_epi32 (t1, t2);
388 _mm_store_si128 ((__m128i *) (o + i), t1);
393 interpolate_gint16_cubic_sse2 (gpointer op, const gpointer ap,
394 gint len, const gpointer icp, gint astride)
397 gint16 *o = op, *a = ap, *ic = icp;
398 __m128i ta, tb, tl1, tl2, th1, th2;
400 const gint16 *c[4] = {(gint16*)((gint8*)a + 0*astride),
401 (gint16*)((gint8*)a + 1*astride),
402 (gint16*)((gint8*)a + 2*astride),
403 (gint16*)((gint8*)a + 3*astride)};
405 f[0] = _mm_set_epi16 (ic[1], ic[0], ic[1], ic[0], ic[1], ic[0], ic[1], ic[0]);
406 f[1] = _mm_set_epi16 (ic[3], ic[2], ic[3], ic[2], ic[3], ic[2], ic[3], ic[2]);
408 for (; i < len; i += 8) {
409 ta = _mm_load_si128 ((__m128i *) (c[0] + i));
410 tb = _mm_load_si128 ((__m128i *) (c[1] + i));
412 tl1 = _mm_madd_epi16 (_mm_unpacklo_epi16 (ta, tb), f[0]);
413 th1 = _mm_madd_epi16 (_mm_unpackhi_epi16 (ta, tb), f[0]);
415 ta = _mm_load_si128 ((__m128i *) (c[2] + i));
416 tb = _mm_load_si128 ((__m128i *) (c[3] + i));
418 tl2 = _mm_madd_epi16 (_mm_unpacklo_epi16 (ta, tb), f[1]);
419 th2 = _mm_madd_epi16 (_mm_unpackhi_epi16 (ta, tb), f[1]);
421 tl1 = _mm_add_epi32 (tl1, tl2);
422 th1 = _mm_add_epi32 (th1, th2);
424 tl1 = _mm_add_epi32 (tl1, _mm_set1_epi32 (1 << (PRECISION_S16 - 1)));
425 th1 = _mm_add_epi32 (th1, _mm_set1_epi32 (1 << (PRECISION_S16 - 1)));
427 tl1 = _mm_srai_epi32 (tl1, PRECISION_S16);
428 th1 = _mm_srai_epi32 (th1, PRECISION_S16);
430 tl1 = _mm_packs_epi32 (tl1, th1);
431 _mm_store_si128 ((__m128i *) (o + i), tl1);
436 interpolate_gdouble_linear_sse2 (gpointer op, const gpointer ap,
437 gint len, const gpointer icp, gint astride)
440 gdouble *o = op, *a = ap, *ic = icp;
441 __m128d f[2], t1, t2;
442 const gdouble *c[2] = {(gdouble*)((gint8*)a + 0*astride),
443 (gdouble*)((gint8*)a + 1*astride)};
445 f[0] = _mm_load1_pd (ic+0);
446 f[1] = _mm_load1_pd (ic+1);
448 for (i = 0; i < len; i += 4) {
449 t1 = _mm_mul_pd (_mm_load_pd (c[0] + i + 0), f[0]);
450 t2 = _mm_mul_pd (_mm_load_pd (c[1] + i + 0), f[1]);
451 _mm_store_pd (o + i + 0, _mm_add_pd (t1, t2));
453 t1 = _mm_mul_pd (_mm_load_pd (c[0] + i + 2), f[0]);
454 t2 = _mm_mul_pd (_mm_load_pd (c[1] + i + 2), f[1]);
455 _mm_store_pd (o + i + 2, _mm_add_pd (t1, t2));
460 interpolate_gdouble_cubic_sse2 (gpointer op, const gpointer ap,
461 gint len, const gpointer icp, gint astride)
464 gdouble *o = op, *a = ap, *ic = icp;
466 const gdouble *c[4] = {(gdouble*)((gint8*)a + 0*astride),
467 (gdouble*)((gint8*)a + 1*astride),
468 (gdouble*)((gint8*)a + 2*astride),
469 (gdouble*)((gint8*)a + 3*astride)};
471 f[0] = _mm_load1_pd (ic+0);
472 f[1] = _mm_load1_pd (ic+1);
473 f[2] = _mm_load1_pd (ic+2);
474 f[3] = _mm_load1_pd (ic+3);
476 for (i = 0; i < len; i += 2) {
477 t[0] = _mm_mul_pd (_mm_load_pd (c[0] + i + 0), f[0]);
478 t[1] = _mm_mul_pd (_mm_load_pd (c[1] + i + 0), f[1]);
479 t[2] = _mm_mul_pd (_mm_load_pd (c[2] + i + 0), f[2]);
480 t[3] = _mm_mul_pd (_mm_load_pd (c[3] + i + 0), f[3]);
481 t[0] = _mm_add_pd (t[0], t[1]);
482 t[2] = _mm_add_pd (t[2], t[3]);
483 _mm_store_pd (o + i + 0, _mm_add_pd (t[0], t[2]));
491 #pragma GCC target("sse4.1")
494 #if defined (HAVE_SMMINTRIN_H) && defined(__SSE4_1__)
495 #include <smmintrin.h>
498 inner_product_gint32_full_1_sse41 (gint32 * o, const gint32 * a,
499 const gint32 * b, gint len, const gint32 * icoeff, gint bstride)
505 sum = _mm_setzero_si128 ();
507 for (; i < len; i += 8) {
508 ta = _mm_loadu_si128 ((__m128i *) (a + i));
509 tb = _mm_load_si128 ((__m128i *) (b + i));
512 _mm_add_epi64 (sum, _mm_mul_epi32 (_mm_unpacklo_epi32 (ta, ta),
513 _mm_unpacklo_epi32 (tb, tb)));
515 _mm_add_epi64 (sum, _mm_mul_epi32 (_mm_unpackhi_epi32 (ta, ta),
516 _mm_unpackhi_epi32 (tb, tb)));
518 ta = _mm_loadu_si128 ((__m128i *) (a + i + 4));
519 tb = _mm_load_si128 ((__m128i *) (b + i + 4));
522 _mm_add_epi64 (sum, _mm_mul_epi32 (_mm_unpacklo_epi32 (ta, ta),
523 _mm_unpacklo_epi32 (tb, tb)));
525 _mm_add_epi64 (sum, _mm_mul_epi32 (_mm_unpackhi_epi32 (ta, ta),
526 _mm_unpackhi_epi32 (tb, tb)));
528 sum = _mm_add_epi64 (sum, _mm_unpackhi_epi64 (sum, sum));
529 res = _mm_cvtsi128_si64 (sum);
531 res = (res + (1 << (PRECISION_S32 - 1))) >> PRECISION_S32;
532 *o = CLAMP (res, -(1L << 31), (1L << 31) - 1);
536 inner_product_gint32_linear_1_sse41 (gint32 * o, const gint32 * a,
537 const gint32 * b, gint len, const gint32 * icoeff, gint bstride)
541 __m128i sum[2], ta, tb;
542 __m128i f = _mm_loadu_si128 ((__m128i *)icoeff);
543 const gint32 *c[2] = {(gint32*)((gint8*)b + 0*bstride),
544 (gint32*)((gint8*)b + 1*bstride)};
546 sum[0] = sum[1] = _mm_setzero_si128 ();
548 for (; i < len; i += 4) {
549 ta = _mm_loadu_si128 ((__m128i *)(a + i));
551 tb = _mm_load_si128 ((__m128i *)(c[0] + i));
552 sum[0] = _mm_add_epi64 (sum[0], _mm_mul_epi32 (_mm_unpacklo_epi32 (ta, ta),
553 _mm_unpacklo_epi32 (tb, tb)));
554 sum[0] = _mm_add_epi64 (sum[0], _mm_mul_epi32 (_mm_unpackhi_epi32 (ta, ta),
555 _mm_unpackhi_epi32 (tb, tb)));
557 tb = _mm_load_si128 ((__m128i *)(c[1] + i));
558 sum[1] = _mm_add_epi64 (sum[1], _mm_mul_epi32 (_mm_unpacklo_epi32 (ta, ta),
559 _mm_unpacklo_epi32 (tb, tb)));
560 sum[1] = _mm_add_epi64 (sum[1], _mm_mul_epi32 (_mm_unpackhi_epi32 (ta, ta),
561 _mm_unpackhi_epi32 (tb, tb)));
563 sum[0] = _mm_srli_epi64 (sum[0], PRECISION_S32);
564 sum[1] = _mm_srli_epi64 (sum[1], PRECISION_S32);
565 sum[0] = _mm_mul_epi32 (sum[0], _mm_shuffle_epi32 (f, _MM_SHUFFLE (0, 0, 0, 0)));
566 sum[1] = _mm_mul_epi32 (sum[1], _mm_shuffle_epi32 (f, _MM_SHUFFLE (1, 1, 1, 1)));
567 sum[0] = _mm_add_epi64 (sum[0], sum[1]);
568 sum[0] = _mm_add_epi64 (sum[0], _mm_unpackhi_epi64 (sum[0], sum[0]));
569 res = _mm_cvtsi128_si64 (sum[0]);
571 res = (res + (1 << (PRECISION_S32 - 1))) >> PRECISION_S32;
572 *o = CLAMP (res, -(1L << 31), (1L << 31) - 1);
576 inner_product_gint32_cubic_1_sse41 (gint32 * o, const gint32 * a,
577 const gint32 * b, gint len, const gint32 * icoeff, gint bstride)
581 __m128i sum[4], ta, tb;
582 __m128i f = _mm_loadu_si128 ((__m128i *)icoeff);
583 const gint32 *c[4] = {(gint32*)((gint8*)b + 0*bstride),
584 (gint32*)((gint8*)b + 1*bstride),
585 (gint32*)((gint8*)b + 2*bstride),
586 (gint32*)((gint8*)b + 3*bstride)};
588 sum[0] = sum[1] = sum[2] = sum[3] = _mm_setzero_si128 ();
590 for (; i < len; i += 4) {
591 ta = _mm_loadu_si128 ((__m128i *)(a + i));
593 tb = _mm_load_si128 ((__m128i *)(c[0] + i));
594 sum[0] = _mm_add_epi64 (sum[0], _mm_mul_epi32 (_mm_unpacklo_epi32 (ta, ta),
595 _mm_unpacklo_epi32 (tb, tb)));
596 sum[0] = _mm_add_epi64 (sum[0], _mm_mul_epi32 (_mm_unpackhi_epi32 (ta, ta),
597 _mm_unpackhi_epi32 (tb, tb)));
599 tb = _mm_load_si128 ((__m128i *)(c[1] + i));
600 sum[1] = _mm_add_epi64 (sum[1], _mm_mul_epi32 (_mm_unpacklo_epi32 (ta, ta),
601 _mm_unpacklo_epi32 (tb, tb)));
602 sum[1] = _mm_add_epi64 (sum[1], _mm_mul_epi32 (_mm_unpackhi_epi32 (ta, ta),
603 _mm_unpackhi_epi32 (tb, tb)));
605 tb = _mm_load_si128 ((__m128i *)(c[2] + i));
606 sum[2] = _mm_add_epi64 (sum[2], _mm_mul_epi32 (_mm_unpacklo_epi32 (ta, ta),
607 _mm_unpacklo_epi32 (tb, tb)));
608 sum[2] = _mm_add_epi64 (sum[2], _mm_mul_epi32 (_mm_unpackhi_epi32 (ta, ta),
609 _mm_unpackhi_epi32 (tb, tb)));
611 tb = _mm_load_si128 ((__m128i *)(c[3] + i));
612 sum[3] = _mm_add_epi64 (sum[3], _mm_mul_epi32 (_mm_unpacklo_epi32 (ta, ta),
613 _mm_unpacklo_epi32 (tb, tb)));
614 sum[3] = _mm_add_epi64 (sum[3], _mm_mul_epi32 (_mm_unpackhi_epi32 (ta, ta),
615 _mm_unpackhi_epi32 (tb, tb)));
617 sum[0] = _mm_srli_epi64 (sum[0], PRECISION_S32);
618 sum[1] = _mm_srli_epi64 (sum[1], PRECISION_S32);
619 sum[2] = _mm_srli_epi64 (sum[2], PRECISION_S32);
620 sum[3] = _mm_srli_epi64 (sum[3], PRECISION_S32);
621 sum[0] = _mm_mul_epi32 (sum[0], _mm_shuffle_epi32 (f, _MM_SHUFFLE (0, 0, 0, 0)));
622 sum[1] = _mm_mul_epi32 (sum[1], _mm_shuffle_epi32 (f, _MM_SHUFFLE (1, 1, 1, 1)));
623 sum[2] = _mm_mul_epi32 (sum[2], _mm_shuffle_epi32 (f, _MM_SHUFFLE (2, 2, 2, 2)));
624 sum[3] = _mm_mul_epi32 (sum[3], _mm_shuffle_epi32 (f, _MM_SHUFFLE (3, 3, 3, 3)));
625 sum[0] = _mm_add_epi64 (sum[0], sum[1]);
626 sum[2] = _mm_add_epi64 (sum[2], sum[3]);
627 sum[0] = _mm_add_epi64 (sum[0], sum[2]);
628 sum[0] = _mm_add_epi64 (sum[0], _mm_unpackhi_epi64 (sum[0], sum[0]));
629 res = _mm_cvtsi128_si64 (sum[0]);
631 res = (res + (1 << (PRECISION_S32 - 1))) >> PRECISION_S32;
632 *o = CLAMP (res, -(1L << 31), (1L << 31) - 1);
635 MAKE_RESAMPLE_FUNC (gint32, full, 1, sse41);
636 MAKE_RESAMPLE_FUNC (gint32, linear, 1, sse41);
637 MAKE_RESAMPLE_FUNC (gint32, cubic, 1, sse41);
641 audio_resampler_check_x86 (const gchar *option)
643 if (!strcmp (option, "sse")) {
644 #if defined (HAVE_XMMINTRIN_H) && defined(__SSE__)
645 GST_DEBUG ("enable SSE optimisations");
646 resample_gfloat_full_1 = resample_gfloat_full_1_sse;
647 resample_gfloat_linear_1 = resample_gfloat_linear_1_sse;
648 resample_gfloat_cubic_1 = resample_gfloat_cubic_1_sse;
650 interpolate_gfloat_linear = interpolate_gfloat_linear_sse;
651 interpolate_gfloat_cubic = interpolate_gfloat_cubic_sse;
653 GST_DEBUG ("SSE optimisations not enabled");
655 } else if (!strcmp (option, "sse2")) {
656 #if defined (HAVE_EMMINTRIN_H) && defined(__SSE2__)
657 GST_DEBUG ("enable SSE2 optimisations");
658 resample_gint16_full_1 = resample_gint16_full_1_sse2;
659 resample_gint16_linear_1 = resample_gint16_linear_1_sse2;
660 resample_gint16_cubic_1 = resample_gint16_cubic_1_sse2;
662 interpolate_gint16_linear = interpolate_gint16_linear_sse2;
663 interpolate_gint16_cubic = interpolate_gint16_cubic_sse2;
665 resample_gdouble_full_1 = resample_gdouble_full_1_sse2;
666 resample_gdouble_linear_1 = resample_gdouble_linear_1_sse2;
667 resample_gdouble_cubic_1 = resample_gdouble_cubic_1_sse2;
669 interpolate_gdouble_linear = interpolate_gdouble_linear_sse2;
670 interpolate_gdouble_cubic = interpolate_gdouble_cubic_sse2;
672 GST_DEBUG ("SSE2 optimisations not enabled");
674 } else if (!strcmp (option, "sse41")) {
675 #if defined (HAVE_SMMINTRIN_H) && defined(__SSE4_1__)
676 GST_DEBUG ("enable SSE41 optimisations");
677 resample_gint32_full_1 = resample_gint32_full_1_sse41;
678 resample_gint32_linear_1 = resample_gint32_linear_1_sse41;
679 resample_gint32_cubic_1 = resample_gint32_cubic_1_sse41;
681 GST_DEBUG ("SSE41 optimisations not enabled");