Hi everyone,
can you please submit your most optimized functions for signum?
If anybody wonder it's defined this way:
if x>0 return 1
if x<0 return -1
if x=0 return 0
Hi everyone,
can you please submit your most optimized functions for signum?
If anybody wonder it's defined this way:
if x>0 return 1
if x<0 return -1
if x=0 return 0
I do:
template
type sign(type value) {
return type((value>0)-(value<0));
}
It is part of my Utility library.
Example:
#include <Utility.h>
void setup(){
Serial.begin(9600);int i = 0;
Serial.println( sign(i), DEC);char j = -1;
Serial.println( sign(j), DEC);double k = 3.14;
Serial.println( sign(k), DEC);
}void loop(){
}
This is probably not the most efficient way? But it is a way ![]()
Minor gotcha with that implementation because AFAIK the C language does not guarantee that expressions return 1 for "true" (they can return any non-zero value).
My favorite implementation is the one that's the clearest to read and lets the compiler do its own optimization (which is usually darned good):
static inline int8_t sgn(int val) {
if (val < 0) return -1;
if (val==0) return 0;
return 1;
}
I bet this will compile to something as efficient as any other method given the quality of GCC today!
Minor gotcha with that implementation because AFAIK the C language does not guarantee that expressions return 1 for "true" (they can return any non-zero value).
This might be the case, but Arduino is c++, yes?
In c++ I'm pretty sure a true will be explicitly promoted to the integral value 1.
I agree the version you present is cleaner though.
In c++ I'm pretty sure a true will be explicitly promoted to the integral value 1.
Yup (assuming the compiler is conformant). From conv...
4 An rvalue of type bool can be converted to an rvalue of type int, with
false becoming zero and true becoming one.
4 If the destination type is bool, see conv.bool. If the source type
is bool, the value false is converted to zero and the value true is
converted to one.
Personally, I would (and have) used both constructs regardless of the standard but it's good to know there shouldn't be any future problems.
Cool...learned something.
I think I was wrong about the compiler being super-optimal too. Here's what it came up with (version 4.4.0):
movw r18,r24
sbrc r25,7
rjmp .L7
ldi r24,lo8(0)
cp r18,__zero_reg__
cpc r19,__zero_reg__
brne .L8
ret
.L8:
ldi r24,lo8(1)
ret
.L7:
ldi r24,lo8(-1)
ret
And here's what I came up with, smaller and faster:
signed char sgn(int val) __attribute__((naked));
signed char sgn(int val)
{
asm (
" sbrc r25,7\n"
" rjmp sgn_isNegative\n"
" sbiw r24,1\n"
" brpl sgn_isPositive\n"
" clr r24\n"
" ret\n"
"sgn_isPositive:\n"
" ldi r24,lo8(1)\n"
" ret\n"
"sgn_isNegative:\n"
" ldi r24,lo8(-1)\n"
" ret\n"
);
}
Warning! Not tested....
Hi ,
can you please submit your functions for signum?
it's defined this way:
if ((x1 != 0) && (x2 != 0) && ( sign(x1) != sign(x2)))
{
p = x1 + x2 ;
}
else if
{
p = sign(x1) * min ( abs(v1), abs(v2));
}
else
{
i want repete until (x1 or / and x2 )!=0
thank you.
oups sorry it's p = sign(x1) * min ( abs(x1), abs(x2));