Hi.
I wonder how to calculate absolute value of a 32-bit signed integer in C as fast as possible. I saw that there is a FPU instruction VABS.F32, which do that in one cycle (above the floats). I thought, if it is possible to use it also with integers (sign bit is in both cases MSB bit). Maybe in some way with inline or embedded assembly?
Or do you have any other advice how to get absolute value of an integer in C in the fastest way.
Not to forget - I am speaking regarding Cortex-M4 processor.
Thanks
If you don't want (or cannot afford) to treat absolute output as unsigned as @goodwin suggested, here is what I would do to perform Absolute function on signed integer keeping output as signed (i.e. saturating abs(-2^31) to -1+2^31)
if (val < 0) { val = __qsub(0, val); }
This would be translated to
cmp r0,#0 itt MI movMI r1,#0 qsubMI r0,r1,r0
This will take 4 cycles regardless input value (maybe 3 if you have some 0 constant already in your registers !) on a Cortex-M4 but requires that you use intrinsics (or inline assembly) from your compiler !
The trick with eor can be used to do the saturating abs in 3 cycles
asrs r1, r0, #31
eors r0, r1
qsub r0, r1
tmp = (int)src >> 31;
dst = __qsub(val^tmp, tmp);
Thanks. I like that solution most.
I write it as __QSUB(src^src >> 31, src >> 31) and it works well also with 0x80000000 input. Result (if signed) become 2147483647 (0x7FFFFFFF). So, perhaps it isn't necesary to compute intermediate "tmp" value as you did, is it? Therefor you avoid additional STR operation.
Also, is casting with (int) there necessary? Because, the dissasembly code and result are the same witout it. As in my example.
Looks that this solution is the most efficient, I would put some parenthesis though ....
Regarding the STR instruction, as long as tmp variable is local to your function, there is no reason a compiler with decent optimization would store this intermediate result !! Did you compile without optimization ? Or maybe, your tmp variable is declared as global ?
For the cast to int, it may not be necessary (if you declared src as an int), but this way you can make sure that compiler will use ASR (arithmetic shift) instead of LSR (logical shift). Also anyone that reads this C code will understand that your intention was to sign-fill your variable !