1
/******************************************************
3
* zexy - implementation file
5
* copyleft (c) IOhannes m zm�lnig
7
* 1999:forum::f�r::uml�ute:2006
9
* institute of electronic music and acoustics (iem)
11
******************************************************
13
* license: GNU General Public License v.2
15
******************************************************/
18
finally :: some of the missing binops for signals :: &&~
20
1302:forum::f�r::uml�ute:2000
25
/* ------------------------ logical~ ----------------------------- */
27
/* ----------------------------- andand_tilde ----------------------------- */
28
static t_class *andand_tilde_class, *scalarandand_tilde_class;
30
typedef struct _andand_tilde
36
typedef struct _scalarandand_tilde
40
t_float x_g; /* inlet value */
41
} t_scalarandand_tilde;
43
static void *andand_tilde_new(t_symbol *s, int argc, t_atom *argv)
46
if (argc > 1) post("&&~: extra arguments ignored");
49
t_scalarandand_tilde *x = (t_scalarandand_tilde *)pd_new(scalarandand_tilde_class);
50
floatinlet_new(&x->x_obj, &x->x_g);
51
x->x_g = atom_getfloatarg(0, argc, argv);
52
outlet_new(&x->x_obj, &s_signal);
58
t_andand_tilde *x = (t_andand_tilde *)pd_new(andand_tilde_class);
59
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
60
outlet_new(&x->x_obj, &s_signal);
66
static t_int *andand_tilde_perform(t_int *w)
68
t_sample *in1 = (t_sample *)(w[1]);
69
t_sample *in2 = (t_sample *)(w[2]);
70
t_sample *out = (t_sample *)(w[3]);
80
static t_int *andand_tilde_perf8(t_int *w)
82
t_sample *in1 = (t_sample *)(w[1]);
83
t_sample *in2 = (t_sample *)(w[2]);
84
t_sample *out = (t_sample *)(w[3]);
86
for (; n; n -= 8, in1 += 8, in2 += 8, out += 8)
88
int f0 = in1[0], f1 = in1[1], f2 = in1[2], f3 = in1[3];
89
int f4 = in1[4], f5 = in1[5], f6 = in1[6], f7 = in1[7];
91
int g0 = in2[0], g1 = in2[1], g2 = in2[2], g3 = in2[3];
92
int g4 = in2[4], g5 = in2[5], g6 = in2[6], g7 = in2[7];
94
out[0] = f0 && g0; out[1] = f1 && g1; out[2] = f2 && g2; out[3] = f3 && g3;
95
out[4] = f4 && g4; out[5] = f5 && g5; out[6] = f6 && g6; out[7] = f7 && g7;
100
static t_int *scalarandand_tilde_perform(t_int *w)
102
t_sample *in = (t_sample *)(w[1]);
103
int f = *(t_float *)(w[2]);
104
t_sample *out = (t_sample *)(w[3]);
106
while (n--) *out++ = (int)*in++ && f;
110
static t_int *scalarandand_tilde_perf8(t_int *w)
112
t_sample *in = (t_sample *)(w[1]);
113
int g = *(t_float *)(w[2]);
114
t_sample *out = (t_sample *)(w[3]);
116
for (; n; n -= 8, in += 8, out += 8)
118
int f0 = in[0], f1 = in[1], f2 = in[2], f3 = in[3];
119
int f4 = in[4], f5 = in[5], f6 = in[6], f7 = in[7];
121
out[0] = f0 && g; out[1] = f1 && g; out[2] = f2 && g; out[3] = f3 && g;
122
out[4] = f4 && g; out[5] = f5 && g; out[6] = f6 && g; out[7] = f7 && g;
128
static int l_bitmask[]={0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};
130
static t_int *andand_tilde_performSSE(t_int *w)
132
__m128 *in1 = (__m128 *)(w[1]);
133
__m128 *in2 = (__m128 *)(w[2]);
134
__m128 *out = (__m128 *)(w[3]);
135
int n = (int)(w[4])>>4;
137
const __m128 bitmask= _mm_loadu_ps((float*)l_bitmask); /* for getting the absolute value */
138
const __m128 one = _mm_set1_ps(1.f);
141
__m128 xmm0, xmm1, xmm2;
142
xmm0 = _mm_and_ps (in1[0] , bitmask); /* =abs(f); */
143
xmm1 = _mm_and_ps (in2[0] , bitmask);
144
xmm0 = _mm_cmpge_ps(xmm0 , one); /* =(abs(f)>=1.0)=i (a weird cast to integer) */
145
xmm1 = _mm_cmpge_ps(xmm1 , one);
146
xmm2 = _mm_and_ps (xmm0 , xmm1); /* =(i0&&i1) */
147
out[0] = _mm_and_ps (xmm2 , one); /* 0xfffffff -> 1.0 */
149
xmm0 = _mm_and_ps (in1[1] , bitmask);
150
xmm1 = _mm_and_ps (in2[1] , bitmask);
151
xmm0 = _mm_cmpge_ps(xmm0 , one);
152
xmm1 = _mm_cmpge_ps(xmm1 , one);
153
xmm2 = _mm_and_ps (xmm0 , xmm1);
154
out[1] = _mm_and_ps (xmm2 , one);
156
xmm0 = _mm_and_ps (in1[2] , bitmask);
157
xmm1 = _mm_and_ps (in2[2] , bitmask);
158
xmm0 = _mm_cmpge_ps(xmm0 , one);
159
xmm1 = _mm_cmpge_ps(xmm1 , one);
160
xmm2 = _mm_and_ps (xmm0 , xmm1);
161
out[2] = _mm_and_ps (xmm2 , one);
163
xmm0 = _mm_and_ps (in1[3] , bitmask);
164
xmm1 = _mm_and_ps (in2[3] , bitmask);
165
xmm0 = _mm_cmpge_ps(xmm0 , one);
166
xmm1 = _mm_cmpge_ps(xmm1 , one);
167
xmm2 = _mm_and_ps (xmm0 , xmm1);
168
out[3] = _mm_and_ps (xmm2 , one);
177
static t_int *scalarandand_tilde_performSSE(t_int *w)
179
__m128 *in = (__m128 *)(w[1]);
180
__m128 *out = (__m128 *)(w[3]);
181
float f = *(t_float *)(w[2]);
182
__m128 scalar = _mm_set1_ps(f);
183
int n = (int)(w[4])>>4;
185
const __m128 bitmask= _mm_loadu_ps((float*)l_bitmask); /* for getting the absolute value */
186
const __m128 one = _mm_set1_ps(1.f);
188
scalar = _mm_and_ps (scalar, bitmask);
189
scalar = _mm_cmpge_ps(scalar, one );
194
xmm0 = _mm_and_ps (in[0], bitmask); /* =abs(f); */
195
xmm0 = _mm_cmpge_ps(xmm0 , one); /* =(abs(f)>=1.0)=i (a weird cast to integer) */
196
xmm0 = _mm_and_ps (xmm0 , scalar); /* =(i0&&i1) */
197
out[0] = _mm_and_ps (xmm0 , one); /* 0xfffffff -> 1.0 */
199
xmm1 = _mm_and_ps (in[1], bitmask);
200
xmm1 = _mm_cmpge_ps(xmm1 , one);
201
xmm1 = _mm_and_ps (xmm1 , scalar);
202
out[1] = _mm_and_ps (xmm1 , one);
204
xmm0 = _mm_and_ps (in[2], bitmask);
205
xmm0 = _mm_cmpge_ps(xmm0 , one);
206
xmm0 = _mm_and_ps (xmm0 , scalar);
207
out[2] = _mm_and_ps (xmm0 , one);
209
xmm1 = _mm_and_ps (in[3], bitmask);
210
xmm1 = _mm_cmpge_ps(xmm1 , one);
211
xmm1 = _mm_and_ps (xmm1 , scalar);
212
out[3] = _mm_and_ps (xmm1 , one);
221
static void andand_tilde_dsp(t_andand_tilde *x, t_signal **sp)
223
t_sample*in1=sp[0]->s_vec;
224
t_sample*in2=sp[1]->s_vec;
225
t_sample*out=sp[2]->s_vec;
231
Z_SIMD_CHKBLOCKSIZE(n)&&
232
Z_SIMD_CHKALIGN(in1)&&
233
Z_SIMD_CHKALIGN(in2)&&
234
Z_SIMD_CHKALIGN(out)&&
235
ZEXY_TYPE_EQUAL(t_sample, float)
238
dsp_add(andand_tilde_performSSE, 4, in1, in2, out, n);
242
dsp_add(andand_tilde_perform, 4, in1, in2, out, n);
244
dsp_add(andand_tilde_perf8, 4, in1, in2, out, n);
249
static void scalarandand_tilde_dsp(t_scalarandand_tilde *x, t_signal **sp)
251
t_sample*in =sp[0]->s_vec;
252
t_sample*out=sp[1]->s_vec;
257
Z_SIMD_CHKBLOCKSIZE(n)&&
258
Z_SIMD_CHKALIGN(in)&&
259
Z_SIMD_CHKALIGN(out)&&
260
ZEXY_TYPE_EQUAL(t_sample, float)
263
dsp_add(scalarandand_tilde_performSSE, 4, in, &x->x_g, out, n);
267
dsp_add(scalarandand_tilde_perform, 4, in, &x->x_g, out, n);
269
dsp_add(scalarandand_tilde_perf8, 4, in, &x->x_g, out, n);
272
static void andand_tilde_help(t_object*x)
274
post("\n%c &&~\t\t:: logical AND operation on 2 signals", HEARTSYMBOL);
277
void setup_0x260x260x7e(void)
279
andand_tilde_class = class_new(gensym("&&~"), (t_newmethod)andand_tilde_new, 0,
280
sizeof(t_andand_tilde), 0, A_GIMME, 0);
281
class_addmethod(andand_tilde_class, (t_method)andand_tilde_dsp, gensym("dsp"), 0);
282
CLASS_MAINSIGNALIN(andand_tilde_class, t_andand_tilde, x_f);
283
class_addmethod (andand_tilde_class, (t_method)andand_tilde_help, gensym("help"), A_NULL);
284
class_sethelpsymbol(andand_tilde_class, gensym("zigbinops"));
287
scalarandand_tilde_class = class_new(gensym("&&~"), 0, 0,
288
sizeof(t_scalarandand_tilde), 0, 0);
289
CLASS_MAINSIGNALIN(scalarandand_tilde_class, t_scalarandand_tilde, x_f);
290
class_addmethod(scalarandand_tilde_class, (t_method)scalarandand_tilde_dsp, gensym("dsp"),
292
class_addmethod (scalarandand_tilde_class, (t_method)andand_tilde_help, gensym("help"), A_NULL);
293
class_sethelpsymbol(scalarandand_tilde_class, gensym("zigbinops"));
295
zexy_register("&&~");