Er, x != x
. I believe it should work.
assuming you mean movemask(x != x) == 0xF
, since just using x != x
gives you the familiar error about not able to convert to boolean, but I’m afraid that is also a no go.
same code works in float
, but of dropping to float
for any filter usage with this tight of a loop negates the use of simd
.
My first guess works. movemask(x == x) != 0xf
means “At least one element of x
is NAN.” x == x
itself returns a vector mask.
hm. movemask(x == x) != 0xf
isn’t working for me. behavior is that NaN
still passes through - same as when using float
and not having the isnan()
check.
editing to add:
the interesting thing is that when I add an fprintf
inside the result of the if (movemask(x != x) == 0xF)
then it correctly checks and enters that branch (the results of the if
), but without the fprintf
that branch is never executed.
I guess the compiler removes an empty branch. Try to disable the flags for optimization in compile.mk
.
the rest of the branch isn’t empty:
if (movemask(x != x) == 0xF) {
fprintf(stderr, "in branch\n");
filter.reset();
}
Filter::reset() {
foo = 0;
bar = 0;
fprintf(stderr, "in reset\n");
}
executes with output of:
in branch
in reset
if (movemask(x != x) == 0xF) {
filter.reset();
}
Filter::reset() {
foo = 0;
bar = 0;
fprintf(stderr, "in reset\n");
}
has no output whatsoever, and the filter itself isn’t reset - I’m very used to compilers removing empty branches, I’m not used to a branch not being empty and not being executed, so something else funky appears to be going on in this case.
Quick question: Is it ok to initialize to zero this way?
simd::float_4 out[4] = {};
Is it initialised?
simd::float_4 out[4] = {0.f};
Had an issue with poly channels before, using float[]
where there was noise on the empty channels initialised with = {};
Yes, that initializes the array of vectors with zeroes, just like if you did float out[16] = {}
.
In this case, = {0.f}
is functionally equivalent to = {}
.
Thanks!
Another question, not sure if I’m missing something. I’m trying to remove branching from my code:
int32_4 v = int32_4::load(...);
int32_4 mask = v == 0;
How can I use mask
for ifelse(float_4 mask, float_4 a, float_4 b)
?
Edit: It works this way but I’m not sure if it should be done this way?
int32_4 v = int32_4::load(...);
float_4 mask = float_4(v == 0) == -1.f;
There is no branching in that code.
Yeah, I posted the code that I’m working on. Before it was something like this with two branches inside the for-loop:
float_4 out[PORTS / 4];
...
for (int i = 0; i < PORTS; i++) {
float v = outputMode[i] == OUTPUTMODE::OM_OUT ? out[i / 4][i % 4] : 0.f;
if (outputClamp) v = clamp(v, -10.f, 10.f);
outputs[OUTPUT + i].setVoltage(v);
}
This is how I did it using SIMD:
float_4 out[PORTS / 4];
...
simd::float_4 c = outputClamp;
for (int j = 0; j < PORTS; j+=4) {
out[j / 4] = simd::ifelse(c == 1.f, simd::clamp(out[j / 4], -10.f, 10.f), out[j / 4]);
simd::int32_4 o1 = simd::int32_4::load((int32_t*)&outputMode[j]);
simd::float_4 o2 = simd::float_4(o1 != 0) == -1.f;
out[j / 4] = simd::ifelse(o2, out[j / 4], simd::float_4::zero());
}
for (int i = 0; i < PORTS; i++) {
outputs[OUTPUT + i].setVoltage(out[i / 4][i % 4]);
}