Implementing absolute value function in cproblem with printing function return valueAbsolute address of a function in Microchip XC16Use of free() in PIC Microcontroller ProgrammingThe 4-wire resistive touch is connected to the ADC's input but it doesn't give correct valueXC32 optimizes vaiable used for register readingFunction not working probably like expected, using TM4C123 MCUPLC - get absolute value of number when the CPU has no “ABS” instructionDelay function for a STM32L152ADXL343 data readHow do you calculate average absolute value of a sum of sin functions with different amplitudes and frequencies?
How did Einstein know the speed of light was constant?
What's the big deal about the Nazgûl losing their horses?
Implementing absolute value function in c
Do intermediate subdomains need to exist?
How serious is plagiarism in a master’s thesis?
Why did C++11 make std::string::data() add a null terminating character?
Does a multiclassed wizard start with a spellbook?
Platform Event Design when Subscribers are Apex Triggers
Taking advantage when the HR forgets to communicate the rules
Should I increase my 401(k) contributions, or increase my mortgage payments
Machine Learning Golf: Multiplication
Motorcyle Chain needs to be cleaned every time you lube it?
What are the differences of checking a self-signed certificate vs ignore it?
Why did moving the mouse cursor cause Windows 95 to run more quickly?
Why does the Batman "crack his knuckles" in "Batman: Arkham Origins"?
How to calculate a conditional PDF in mathematica?
How can solar sailed ships be protected from space debris?
Do the 26 richest billionaires own as much wealth as the poorest 3.8 billion people?
How do both sides know the MTU
Is it possible to spoof an IP address to an exact number?
Speeding up thousands of string parses
Can 4 Joy cons connect to the same Switch?
Who pays for increased security measures on flights to the US?
Why did the "Orks" never develop better firearms than Firelances and Handcannons?
Implementing absolute value function in c
problem with printing function return valueAbsolute address of a function in Microchip XC16Use of free() in PIC Microcontroller ProgrammingThe 4-wire resistive touch is connected to the ADC's input but it doesn't give correct valueXC32 optimizes vaiable used for register readingFunction not working probably like expected, using TM4C123 MCUPLC - get absolute value of number when the CPU has no “ABS” instructionDelay function for a STM32L152ADXL343 data readHow do you calculate average absolute value of a sum of sin functions with different amplitudes and frequencies?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
$begingroup$
is implementing a function to find the absolute value like this:
uint16_t absolute_value(int16_t n)
int16_t mask = n >> 15;
return((n+mask)^mask);
Any quicker than just doing a simple multiply by -1 if less than 0? this code is on a microprocessor where speed is everything.
microcontroller c math
$endgroup$
add a comment |
$begingroup$
is implementing a function to find the absolute value like this:
uint16_t absolute_value(int16_t n)
int16_t mask = n >> 15;
return((n+mask)^mask);
Any quicker than just doing a simple multiply by -1 if less than 0? this code is on a microprocessor where speed is everything.
microcontroller c math
$endgroup$
1
$begingroup$
Multiplying by -1 is just bitwise inversion and adding 1. Any decent compiler will know this and generate this code instead of a multiply. Your code might be faster (depending on architecture) because it doesn't branch.
$endgroup$
– The Photon
10 hours ago
2
$begingroup$
Probably the most bang for the buck is making it a macro and not a function call, since the call overhead is bigger than the work you do in the function. That's what stdlib.h will typically take care off as well.
$endgroup$
– Hilmar
9 hours ago
4
$begingroup$
@Hilmar Preprocessor macros are evil. Much better would be an inline function, so the compiler can do type checking.
$endgroup$
– Elliot Alderson
9 hours ago
add a comment |
$begingroup$
is implementing a function to find the absolute value like this:
uint16_t absolute_value(int16_t n)
int16_t mask = n >> 15;
return((n+mask)^mask);
Any quicker than just doing a simple multiply by -1 if less than 0? this code is on a microprocessor where speed is everything.
microcontroller c math
$endgroup$
is implementing a function to find the absolute value like this:
uint16_t absolute_value(int16_t n)
int16_t mask = n >> 15;
return((n+mask)^mask);
Any quicker than just doing a simple multiply by -1 if less than 0? this code is on a microprocessor where speed is everything.
microcontroller c math
microcontroller c math
asked 10 hours ago
user9964422user9964422
433 bronze badges
433 bronze badges
1
$begingroup$
Multiplying by -1 is just bitwise inversion and adding 1. Any decent compiler will know this and generate this code instead of a multiply. Your code might be faster (depending on architecture) because it doesn't branch.
$endgroup$
– The Photon
10 hours ago
2
$begingroup$
Probably the most bang for the buck is making it a macro and not a function call, since the call overhead is bigger than the work you do in the function. That's what stdlib.h will typically take care off as well.
$endgroup$
– Hilmar
9 hours ago
4
$begingroup$
@Hilmar Preprocessor macros are evil. Much better would be an inline function, so the compiler can do type checking.
$endgroup$
– Elliot Alderson
9 hours ago
add a comment |
1
$begingroup$
Multiplying by -1 is just bitwise inversion and adding 1. Any decent compiler will know this and generate this code instead of a multiply. Your code might be faster (depending on architecture) because it doesn't branch.
$endgroup$
– The Photon
10 hours ago
2
$begingroup$
Probably the most bang for the buck is making it a macro and not a function call, since the call overhead is bigger than the work you do in the function. That's what stdlib.h will typically take care off as well.
$endgroup$
– Hilmar
9 hours ago
4
$begingroup$
@Hilmar Preprocessor macros are evil. Much better would be an inline function, so the compiler can do type checking.
$endgroup$
– Elliot Alderson
9 hours ago
1
1
$begingroup$
Multiplying by -1 is just bitwise inversion and adding 1. Any decent compiler will know this and generate this code instead of a multiply. Your code might be faster (depending on architecture) because it doesn't branch.
$endgroup$
– The Photon
10 hours ago
$begingroup$
Multiplying by -1 is just bitwise inversion and adding 1. Any decent compiler will know this and generate this code instead of a multiply. Your code might be faster (depending on architecture) because it doesn't branch.
$endgroup$
– The Photon
10 hours ago
2
2
$begingroup$
Probably the most bang for the buck is making it a macro and not a function call, since the call overhead is bigger than the work you do in the function. That's what stdlib.h will typically take care off as well.
$endgroup$
– Hilmar
9 hours ago
$begingroup$
Probably the most bang for the buck is making it a macro and not a function call, since the call overhead is bigger than the work you do in the function. That's what stdlib.h will typically take care off as well.
$endgroup$
– Hilmar
9 hours ago
4
4
$begingroup$
@Hilmar Preprocessor macros are evil. Much better would be an inline function, so the compiler can do type checking.
$endgroup$
– Elliot Alderson
9 hours ago
$begingroup$
@Hilmar Preprocessor macros are evil. Much better would be an inline function, so the compiler can do type checking.
$endgroup$
– Elliot Alderson
9 hours ago
add a comment |
3 Answers
3
active
oldest
votes
$begingroup$
The standard C library is providing the optimized solutions for many problems with considerations based on the architecture, compiler in use and others. The abs()
function defined in stdlib.h
is one of these, and it is used for your purpose exactly. To emphasize the point, here is ARM compiler result when using abs
vs a version of a homebrew abs
: https://arm.godbolt.org/z/aO7t1n
Paste:
#include <stdio.h>
#include <stdlib.h>
int main(void)
srand(111);
int x = rand() - 200;
printf("%dn", abs(x));
results in
main:
push r4, lr
mov r0, #111
bl srand
bl rand
sub r1, r0, #200
cmp r1, #0
rsblt r1, r1, #0
ldr r0, .L4
bl printf
mov r0, #0
pop r4, pc
.L4:
.word .LC0
.LC0:
.ascii "%d1200"
And
#include <stdio.h>
#include <stdlib.h>
int my_abs(int x)
return x < 0 ? -x : x;
int main(void)
srand(111);
int x = rand() - 200;
printf("%dn", my_abs(x));
results in
my_abs:
cmp r0, #0
rsblt r0, r0, #0
bx lr
main:
push r4, lr
mov r0, #111
bl srand
bl rand
sub r1, r0, #200
cmp r1, #0
rsblt r1, r1, #0
ldr r0, .L5
bl printf
mov r0, #0
pop r4, pc
.L5:
.word .LC0
.LC0:
.ascii "%d1200"
Notice that the main
code is almost identical in both codes as the my_abs
got inlined, and it's implementation is the same as the standard one.
$endgroup$
$begingroup$
Your final comment is perfect. Since the result is know at compile time, the codes do not actually calculate the abs.
$endgroup$
– vangelo
9 hours ago
$begingroup$
@vangelo Are you saying I have cheated? :) Well, let me get another example
$endgroup$
– Eugene Sh.
9 hours ago
$begingroup$
Of course not! I'm just pointing out that both codes already show the result in the assembly. :)
$endgroup$
– vangelo
9 hours ago
2
$begingroup$
@vangelo OK, then I will leave it to the reader :) Which is by the way another thing. Ifmy_abs
was defined in a separate translation unit (source file), the compiler would not know what it does and won't be able to optimize it to a compile-time result. But with standardabs
it always knows it.
$endgroup$
– Eugene Sh.
9 hours ago
$begingroup$
Oh well. Here it is: arm.godbolt.org/z/AIzLre One can notice there is no function call at all when usingabs
.
$endgroup$
– Eugene Sh.
9 hours ago
|
show 6 more comments
$begingroup$
The speed of a given solution will depend greatly on the architecture, but in C I would say
return (n > 0 ? n : -n);
and let the compiler figure out the best solution.
EDIT: @jonk points out correctly that this will fail for the most-negative possible value of n, assuming that two's-complement arithmetic is used.
Yes, my solution has a conditional branch, but yours has an arithmetic operator and two bitwise operators. Can your microcontroller shift 15 places in a single clock?
$endgroup$
2
$begingroup$
This is basically just to agree. If a fully portable solution is desirable, do it simple, as you suggested. If the best/shortest/fastest option is needed, it will depend on your processor/compiler and it is very likely that the standard (or non-standard) library will provide the best code.
$endgroup$
– vangelo
9 hours ago
$begingroup$
@vangelo Just one minor point...I think that the functions in stdlib are defined for int rather than int16_t or uint16_t. The size of an int may be 32 bits, which could influence speed. But you are correct that if an appropriate library function is available it is best to use it.
$endgroup$
– Elliot Alderson
9 hours ago
$begingroup$
I agree. This is why I also mentioned non-standard. It is not uncommon that "extensions" are available and in fact quite common with micro-controllers.
$endgroup$
– vangelo
9 hours ago
add a comment |
$begingroup$
There are a lot of subtle details in using C. Given your comment about speed, it is probably worth your time to try out various options and see which produces better assembly code results. Ask the compiler to generate assembly code and then read it. (This doesn't always catch the reality, though. Some compilers leave certain replacements to the linker step.) Or use the machine code and a disassembler and just look. (That always works.) It's not hard to do once you've worked out the steps in your situation.
Let me just suggest some options to consider. Perhaps that's the best I can do. (I'm assuming below that you don't want to take the absolute function of a constant, since there is an obvious "code time" solution for that case.)
- The abs() function that's available for your C compiler may very well be implemented in-line with the compiler. (Microsoft's x86 C compiler certainly does this.) If this is already handled within the compiler, looking at the machine code will tell you what you need to know. Sometimes, the assembly output isn't a sufficient test since some compilers will leave this optimization step to the linker process, instead. In those cases, you will have no choice but to examine the final machine code product.
- You can attempt to use the method you already mentioned (using an if statement or using the trinary ? operator.) Again, I've seen versions of Microsoft's C compiler that will eat these perfectly well and generate exactly the same case as if you'd used their in-line abs() version -- which for some targets will generate code without any branching involved and taking two or three instructions.
- You can use the method you've coded up (which is dependent on your word size.) You've coded one method: $left(n+maskright), text^, mask$.
- You could try: $left(n, text^, maskright)-mask$.
- You could try: $n-left(left[n << 1right], &: maskright)$ or $n-left(2,n, &: maskright)$ or $n-left(left[n+nright], &: maskright)$.
There are other options if you have a fast multiply for +1 or -1 (sometimes, that's easy.)
Be wary of, and follow, the C standards. Often, operations on negative signed values are undefined. They may behave as expected. But that behavior may not be portable or guaranteed.
As a final note, if you intend on writing a function in C it may pay to provide the compiler hint to make it an inline function.
$endgroup$
$begingroup$
@ThePhoton There's already a corner case in (n > 0 ? n : -n). The case where n is the maximal negative value (which that will return unchanged.) I was mostly trying to help list out as many different things to try with the compiler. By the way, which corner case are you considering?
$endgroup$
– jonk
9 hours ago
$begingroup$
I think shifting a signed datatype left (n << 1
) is undefined behavior for ANSI C. Multiplying a fixed-width datatype by 2 also risks silent integer overflow.
$endgroup$
– Elliot Alderson
9 hours ago
$begingroup$
@jonk good point on the maximal negative corner case. But this is the behavior even for the standard function right?
$endgroup$
– vangelo
9 hours ago
$begingroup$
@ElliotAlderson I just checked Harbison and Steele. In the left shift case C defines the behavior regardless of type and it is portable. However, you are right to be worried, in the right shift case, where the C compiler is permitted two different behaviors and it is not portable.
$endgroup$
– jonk
8 hours ago
$begingroup$
@jonk The left shift for negative value is undefined per the standard port70.net/~nsz/c/c11/n1570.html#6.5.7p4 . Worth noting that the standardabs
is undefined for the most negative value as well, so it is on par withx < 0 ? -x : x
solution.
$endgroup$
– Eugene Sh.
8 hours ago
|
show 5 more comments
Your Answer
StackExchange.ifUsing("editor", function ()
return StackExchange.using("schematics", function ()
StackExchange.schematics.init();
);
, "cicuitlab");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "135"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2felectronics.stackexchange.com%2fquestions%2f446457%2fimplementing-absolute-value-function-in-c%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
The standard C library is providing the optimized solutions for many problems with considerations based on the architecture, compiler in use and others. The abs()
function defined in stdlib.h
is one of these, and it is used for your purpose exactly. To emphasize the point, here is ARM compiler result when using abs
vs a version of a homebrew abs
: https://arm.godbolt.org/z/aO7t1n
Paste:
#include <stdio.h>
#include <stdlib.h>
int main(void)
srand(111);
int x = rand() - 200;
printf("%dn", abs(x));
results in
main:
push r4, lr
mov r0, #111
bl srand
bl rand
sub r1, r0, #200
cmp r1, #0
rsblt r1, r1, #0
ldr r0, .L4
bl printf
mov r0, #0
pop r4, pc
.L4:
.word .LC0
.LC0:
.ascii "%d1200"
And
#include <stdio.h>
#include <stdlib.h>
int my_abs(int x)
return x < 0 ? -x : x;
int main(void)
srand(111);
int x = rand() - 200;
printf("%dn", my_abs(x));
results in
my_abs:
cmp r0, #0
rsblt r0, r0, #0
bx lr
main:
push r4, lr
mov r0, #111
bl srand
bl rand
sub r1, r0, #200
cmp r1, #0
rsblt r1, r1, #0
ldr r0, .L5
bl printf
mov r0, #0
pop r4, pc
.L5:
.word .LC0
.LC0:
.ascii "%d1200"
Notice that the main
code is almost identical in both codes as the my_abs
got inlined, and it's implementation is the same as the standard one.
$endgroup$
$begingroup$
Your final comment is perfect. Since the result is know at compile time, the codes do not actually calculate the abs.
$endgroup$
– vangelo
9 hours ago
$begingroup$
@vangelo Are you saying I have cheated? :) Well, let me get another example
$endgroup$
– Eugene Sh.
9 hours ago
$begingroup$
Of course not! I'm just pointing out that both codes already show the result in the assembly. :)
$endgroup$
– vangelo
9 hours ago
2
$begingroup$
@vangelo OK, then I will leave it to the reader :) Which is by the way another thing. Ifmy_abs
was defined in a separate translation unit (source file), the compiler would not know what it does and won't be able to optimize it to a compile-time result. But with standardabs
it always knows it.
$endgroup$
– Eugene Sh.
9 hours ago
$begingroup$
Oh well. Here it is: arm.godbolt.org/z/AIzLre One can notice there is no function call at all when usingabs
.
$endgroup$
– Eugene Sh.
9 hours ago
|
show 6 more comments
$begingroup$
The standard C library is providing the optimized solutions for many problems with considerations based on the architecture, compiler in use and others. The abs()
function defined in stdlib.h
is one of these, and it is used for your purpose exactly. To emphasize the point, here is ARM compiler result when using abs
vs a version of a homebrew abs
: https://arm.godbolt.org/z/aO7t1n
Paste:
#include <stdio.h>
#include <stdlib.h>
int main(void)
srand(111);
int x = rand() - 200;
printf("%dn", abs(x));
results in
main:
push r4, lr
mov r0, #111
bl srand
bl rand
sub r1, r0, #200
cmp r1, #0
rsblt r1, r1, #0
ldr r0, .L4
bl printf
mov r0, #0
pop r4, pc
.L4:
.word .LC0
.LC0:
.ascii "%d1200"
And
#include <stdio.h>
#include <stdlib.h>
int my_abs(int x)
return x < 0 ? -x : x;
int main(void)
srand(111);
int x = rand() - 200;
printf("%dn", my_abs(x));
results in
my_abs:
cmp r0, #0
rsblt r0, r0, #0
bx lr
main:
push r4, lr
mov r0, #111
bl srand
bl rand
sub r1, r0, #200
cmp r1, #0
rsblt r1, r1, #0
ldr r0, .L5
bl printf
mov r0, #0
pop r4, pc
.L5:
.word .LC0
.LC0:
.ascii "%d1200"
Notice that the main
code is almost identical in both codes as the my_abs
got inlined, and it's implementation is the same as the standard one.
$endgroup$
$begingroup$
Your final comment is perfect. Since the result is know at compile time, the codes do not actually calculate the abs.
$endgroup$
– vangelo
9 hours ago
$begingroup$
@vangelo Are you saying I have cheated? :) Well, let me get another example
$endgroup$
– Eugene Sh.
9 hours ago
$begingroup$
Of course not! I'm just pointing out that both codes already show the result in the assembly. :)
$endgroup$
– vangelo
9 hours ago
2
$begingroup$
@vangelo OK, then I will leave it to the reader :) Which is by the way another thing. Ifmy_abs
was defined in a separate translation unit (source file), the compiler would not know what it does and won't be able to optimize it to a compile-time result. But with standardabs
it always knows it.
$endgroup$
– Eugene Sh.
9 hours ago
$begingroup$
Oh well. Here it is: arm.godbolt.org/z/AIzLre One can notice there is no function call at all when usingabs
.
$endgroup$
– Eugene Sh.
9 hours ago
|
show 6 more comments
$begingroup$
The standard C library is providing the optimized solutions for many problems with considerations based on the architecture, compiler in use and others. The abs()
function defined in stdlib.h
is one of these, and it is used for your purpose exactly. To emphasize the point, here is ARM compiler result when using abs
vs a version of a homebrew abs
: https://arm.godbolt.org/z/aO7t1n
Paste:
#include <stdio.h>
#include <stdlib.h>
int main(void)
srand(111);
int x = rand() - 200;
printf("%dn", abs(x));
results in
main:
push r4, lr
mov r0, #111
bl srand
bl rand
sub r1, r0, #200
cmp r1, #0
rsblt r1, r1, #0
ldr r0, .L4
bl printf
mov r0, #0
pop r4, pc
.L4:
.word .LC0
.LC0:
.ascii "%d1200"
And
#include <stdio.h>
#include <stdlib.h>
int my_abs(int x)
return x < 0 ? -x : x;
int main(void)
srand(111);
int x = rand() - 200;
printf("%dn", my_abs(x));
results in
my_abs:
cmp r0, #0
rsblt r0, r0, #0
bx lr
main:
push r4, lr
mov r0, #111
bl srand
bl rand
sub r1, r0, #200
cmp r1, #0
rsblt r1, r1, #0
ldr r0, .L5
bl printf
mov r0, #0
pop r4, pc
.L5:
.word .LC0
.LC0:
.ascii "%d1200"
Notice that the main
code is almost identical in both codes as the my_abs
got inlined, and it's implementation is the same as the standard one.
$endgroup$
The standard C library is providing the optimized solutions for many problems with considerations based on the architecture, compiler in use and others. The abs()
function defined in stdlib.h
is one of these, and it is used for your purpose exactly. To emphasize the point, here is ARM compiler result when using abs
vs a version of a homebrew abs
: https://arm.godbolt.org/z/aO7t1n
Paste:
#include <stdio.h>
#include <stdlib.h>
int main(void)
srand(111);
int x = rand() - 200;
printf("%dn", abs(x));
results in
main:
push r4, lr
mov r0, #111
bl srand
bl rand
sub r1, r0, #200
cmp r1, #0
rsblt r1, r1, #0
ldr r0, .L4
bl printf
mov r0, #0
pop r4, pc
.L4:
.word .LC0
.LC0:
.ascii "%d1200"
And
#include <stdio.h>
#include <stdlib.h>
int my_abs(int x)
return x < 0 ? -x : x;
int main(void)
srand(111);
int x = rand() - 200;
printf("%dn", my_abs(x));
results in
my_abs:
cmp r0, #0
rsblt r0, r0, #0
bx lr
main:
push r4, lr
mov r0, #111
bl srand
bl rand
sub r1, r0, #200
cmp r1, #0
rsblt r1, r1, #0
ldr r0, .L5
bl printf
mov r0, #0
pop r4, pc
.L5:
.word .LC0
.LC0:
.ascii "%d1200"
Notice that the main
code is almost identical in both codes as the my_abs
got inlined, and it's implementation is the same as the standard one.
edited 9 hours ago
answered 9 hours ago
Eugene Sh.Eugene Sh.
8,02119 silver badges31 bronze badges
8,02119 silver badges31 bronze badges
$begingroup$
Your final comment is perfect. Since the result is know at compile time, the codes do not actually calculate the abs.
$endgroup$
– vangelo
9 hours ago
$begingroup$
@vangelo Are you saying I have cheated? :) Well, let me get another example
$endgroup$
– Eugene Sh.
9 hours ago
$begingroup$
Of course not! I'm just pointing out that both codes already show the result in the assembly. :)
$endgroup$
– vangelo
9 hours ago
2
$begingroup$
@vangelo OK, then I will leave it to the reader :) Which is by the way another thing. Ifmy_abs
was defined in a separate translation unit (source file), the compiler would not know what it does and won't be able to optimize it to a compile-time result. But with standardabs
it always knows it.
$endgroup$
– Eugene Sh.
9 hours ago
$begingroup$
Oh well. Here it is: arm.godbolt.org/z/AIzLre One can notice there is no function call at all when usingabs
.
$endgroup$
– Eugene Sh.
9 hours ago
|
show 6 more comments
$begingroup$
Your final comment is perfect. Since the result is know at compile time, the codes do not actually calculate the abs.
$endgroup$
– vangelo
9 hours ago
$begingroup$
@vangelo Are you saying I have cheated? :) Well, let me get another example
$endgroup$
– Eugene Sh.
9 hours ago
$begingroup$
Of course not! I'm just pointing out that both codes already show the result in the assembly. :)
$endgroup$
– vangelo
9 hours ago
2
$begingroup$
@vangelo OK, then I will leave it to the reader :) Which is by the way another thing. Ifmy_abs
was defined in a separate translation unit (source file), the compiler would not know what it does and won't be able to optimize it to a compile-time result. But with standardabs
it always knows it.
$endgroup$
– Eugene Sh.
9 hours ago
$begingroup$
Oh well. Here it is: arm.godbolt.org/z/AIzLre One can notice there is no function call at all when usingabs
.
$endgroup$
– Eugene Sh.
9 hours ago
$begingroup$
Your final comment is perfect. Since the result is know at compile time, the codes do not actually calculate the abs.
$endgroup$
– vangelo
9 hours ago
$begingroup$
Your final comment is perfect. Since the result is know at compile time, the codes do not actually calculate the abs.
$endgroup$
– vangelo
9 hours ago
$begingroup$
@vangelo Are you saying I have cheated? :) Well, let me get another example
$endgroup$
– Eugene Sh.
9 hours ago
$begingroup$
@vangelo Are you saying I have cheated? :) Well, let me get another example
$endgroup$
– Eugene Sh.
9 hours ago
$begingroup$
Of course not! I'm just pointing out that both codes already show the result in the assembly. :)
$endgroup$
– vangelo
9 hours ago
$begingroup$
Of course not! I'm just pointing out that both codes already show the result in the assembly. :)
$endgroup$
– vangelo
9 hours ago
2
2
$begingroup$
@vangelo OK, then I will leave it to the reader :) Which is by the way another thing. If
my_abs
was defined in a separate translation unit (source file), the compiler would not know what it does and won't be able to optimize it to a compile-time result. But with standard abs
it always knows it.$endgroup$
– Eugene Sh.
9 hours ago
$begingroup$
@vangelo OK, then I will leave it to the reader :) Which is by the way another thing. If
my_abs
was defined in a separate translation unit (source file), the compiler would not know what it does and won't be able to optimize it to a compile-time result. But with standard abs
it always knows it.$endgroup$
– Eugene Sh.
9 hours ago
$begingroup$
Oh well. Here it is: arm.godbolt.org/z/AIzLre One can notice there is no function call at all when using
abs
.$endgroup$
– Eugene Sh.
9 hours ago
$begingroup$
Oh well. Here it is: arm.godbolt.org/z/AIzLre One can notice there is no function call at all when using
abs
.$endgroup$
– Eugene Sh.
9 hours ago
|
show 6 more comments
$begingroup$
The speed of a given solution will depend greatly on the architecture, but in C I would say
return (n > 0 ? n : -n);
and let the compiler figure out the best solution.
EDIT: @jonk points out correctly that this will fail for the most-negative possible value of n, assuming that two's-complement arithmetic is used.
Yes, my solution has a conditional branch, but yours has an arithmetic operator and two bitwise operators. Can your microcontroller shift 15 places in a single clock?
$endgroup$
2
$begingroup$
This is basically just to agree. If a fully portable solution is desirable, do it simple, as you suggested. If the best/shortest/fastest option is needed, it will depend on your processor/compiler and it is very likely that the standard (or non-standard) library will provide the best code.
$endgroup$
– vangelo
9 hours ago
$begingroup$
@vangelo Just one minor point...I think that the functions in stdlib are defined for int rather than int16_t or uint16_t. The size of an int may be 32 bits, which could influence speed. But you are correct that if an appropriate library function is available it is best to use it.
$endgroup$
– Elliot Alderson
9 hours ago
$begingroup$
I agree. This is why I also mentioned non-standard. It is not uncommon that "extensions" are available and in fact quite common with micro-controllers.
$endgroup$
– vangelo
9 hours ago
add a comment |
$begingroup$
The speed of a given solution will depend greatly on the architecture, but in C I would say
return (n > 0 ? n : -n);
and let the compiler figure out the best solution.
EDIT: @jonk points out correctly that this will fail for the most-negative possible value of n, assuming that two's-complement arithmetic is used.
Yes, my solution has a conditional branch, but yours has an arithmetic operator and two bitwise operators. Can your microcontroller shift 15 places in a single clock?
$endgroup$
2
$begingroup$
This is basically just to agree. If a fully portable solution is desirable, do it simple, as you suggested. If the best/shortest/fastest option is needed, it will depend on your processor/compiler and it is very likely that the standard (or non-standard) library will provide the best code.
$endgroup$
– vangelo
9 hours ago
$begingroup$
@vangelo Just one minor point...I think that the functions in stdlib are defined for int rather than int16_t or uint16_t. The size of an int may be 32 bits, which could influence speed. But you are correct that if an appropriate library function is available it is best to use it.
$endgroup$
– Elliot Alderson
9 hours ago
$begingroup$
I agree. This is why I also mentioned non-standard. It is not uncommon that "extensions" are available and in fact quite common with micro-controllers.
$endgroup$
– vangelo
9 hours ago
add a comment |
$begingroup$
The speed of a given solution will depend greatly on the architecture, but in C I would say
return (n > 0 ? n : -n);
and let the compiler figure out the best solution.
EDIT: @jonk points out correctly that this will fail for the most-negative possible value of n, assuming that two's-complement arithmetic is used.
Yes, my solution has a conditional branch, but yours has an arithmetic operator and two bitwise operators. Can your microcontroller shift 15 places in a single clock?
$endgroup$
The speed of a given solution will depend greatly on the architecture, but in C I would say
return (n > 0 ? n : -n);
and let the compiler figure out the best solution.
EDIT: @jonk points out correctly that this will fail for the most-negative possible value of n, assuming that two's-complement arithmetic is used.
Yes, my solution has a conditional branch, but yours has an arithmetic operator and two bitwise operators. Can your microcontroller shift 15 places in a single clock?
edited 9 hours ago
answered 10 hours ago
Elliot AldersonElliot Alderson
9,6812 gold badges12 silver badges22 bronze badges
9,6812 gold badges12 silver badges22 bronze badges
2
$begingroup$
This is basically just to agree. If a fully portable solution is desirable, do it simple, as you suggested. If the best/shortest/fastest option is needed, it will depend on your processor/compiler and it is very likely that the standard (or non-standard) library will provide the best code.
$endgroup$
– vangelo
9 hours ago
$begingroup$
@vangelo Just one minor point...I think that the functions in stdlib are defined for int rather than int16_t or uint16_t. The size of an int may be 32 bits, which could influence speed. But you are correct that if an appropriate library function is available it is best to use it.
$endgroup$
– Elliot Alderson
9 hours ago
$begingroup$
I agree. This is why I also mentioned non-standard. It is not uncommon that "extensions" are available and in fact quite common with micro-controllers.
$endgroup$
– vangelo
9 hours ago
add a comment |
2
$begingroup$
This is basically just to agree. If a fully portable solution is desirable, do it simple, as you suggested. If the best/shortest/fastest option is needed, it will depend on your processor/compiler and it is very likely that the standard (or non-standard) library will provide the best code.
$endgroup$
– vangelo
9 hours ago
$begingroup$
@vangelo Just one minor point...I think that the functions in stdlib are defined for int rather than int16_t or uint16_t. The size of an int may be 32 bits, which could influence speed. But you are correct that if an appropriate library function is available it is best to use it.
$endgroup$
– Elliot Alderson
9 hours ago
$begingroup$
I agree. This is why I also mentioned non-standard. It is not uncommon that "extensions" are available and in fact quite common with micro-controllers.
$endgroup$
– vangelo
9 hours ago
2
2
$begingroup$
This is basically just to agree. If a fully portable solution is desirable, do it simple, as you suggested. If the best/shortest/fastest option is needed, it will depend on your processor/compiler and it is very likely that the standard (or non-standard) library will provide the best code.
$endgroup$
– vangelo
9 hours ago
$begingroup$
This is basically just to agree. If a fully portable solution is desirable, do it simple, as you suggested. If the best/shortest/fastest option is needed, it will depend on your processor/compiler and it is very likely that the standard (or non-standard) library will provide the best code.
$endgroup$
– vangelo
9 hours ago
$begingroup$
@vangelo Just one minor point...I think that the functions in stdlib are defined for int rather than int16_t or uint16_t. The size of an int may be 32 bits, which could influence speed. But you are correct that if an appropriate library function is available it is best to use it.
$endgroup$
– Elliot Alderson
9 hours ago
$begingroup$
@vangelo Just one minor point...I think that the functions in stdlib are defined for int rather than int16_t or uint16_t. The size of an int may be 32 bits, which could influence speed. But you are correct that if an appropriate library function is available it is best to use it.
$endgroup$
– Elliot Alderson
9 hours ago
$begingroup$
I agree. This is why I also mentioned non-standard. It is not uncommon that "extensions" are available and in fact quite common with micro-controllers.
$endgroup$
– vangelo
9 hours ago
$begingroup$
I agree. This is why I also mentioned non-standard. It is not uncommon that "extensions" are available and in fact quite common with micro-controllers.
$endgroup$
– vangelo
9 hours ago
add a comment |
$begingroup$
There are a lot of subtle details in using C. Given your comment about speed, it is probably worth your time to try out various options and see which produces better assembly code results. Ask the compiler to generate assembly code and then read it. (This doesn't always catch the reality, though. Some compilers leave certain replacements to the linker step.) Or use the machine code and a disassembler and just look. (That always works.) It's not hard to do once you've worked out the steps in your situation.
Let me just suggest some options to consider. Perhaps that's the best I can do. (I'm assuming below that you don't want to take the absolute function of a constant, since there is an obvious "code time" solution for that case.)
- The abs() function that's available for your C compiler may very well be implemented in-line with the compiler. (Microsoft's x86 C compiler certainly does this.) If this is already handled within the compiler, looking at the machine code will tell you what you need to know. Sometimes, the assembly output isn't a sufficient test since some compilers will leave this optimization step to the linker process, instead. In those cases, you will have no choice but to examine the final machine code product.
- You can attempt to use the method you already mentioned (using an if statement or using the trinary ? operator.) Again, I've seen versions of Microsoft's C compiler that will eat these perfectly well and generate exactly the same case as if you'd used their in-line abs() version -- which for some targets will generate code without any branching involved and taking two or three instructions.
- You can use the method you've coded up (which is dependent on your word size.) You've coded one method: $left(n+maskright), text^, mask$.
- You could try: $left(n, text^, maskright)-mask$.
- You could try: $n-left(left[n << 1right], &: maskright)$ or $n-left(2,n, &: maskright)$ or $n-left(left[n+nright], &: maskright)$.
There are other options if you have a fast multiply for +1 or -1 (sometimes, that's easy.)
Be wary of, and follow, the C standards. Often, operations on negative signed values are undefined. They may behave as expected. But that behavior may not be portable or guaranteed.
As a final note, if you intend on writing a function in C it may pay to provide the compiler hint to make it an inline function.
$endgroup$
$begingroup$
@ThePhoton There's already a corner case in (n > 0 ? n : -n). The case where n is the maximal negative value (which that will return unchanged.) I was mostly trying to help list out as many different things to try with the compiler. By the way, which corner case are you considering?
$endgroup$
– jonk
9 hours ago
$begingroup$
I think shifting a signed datatype left (n << 1
) is undefined behavior for ANSI C. Multiplying a fixed-width datatype by 2 also risks silent integer overflow.
$endgroup$
– Elliot Alderson
9 hours ago
$begingroup$
@jonk good point on the maximal negative corner case. But this is the behavior even for the standard function right?
$endgroup$
– vangelo
9 hours ago
$begingroup$
@ElliotAlderson I just checked Harbison and Steele. In the left shift case C defines the behavior regardless of type and it is portable. However, you are right to be worried, in the right shift case, where the C compiler is permitted two different behaviors and it is not portable.
$endgroup$
– jonk
8 hours ago
$begingroup$
@jonk The left shift for negative value is undefined per the standard port70.net/~nsz/c/c11/n1570.html#6.5.7p4 . Worth noting that the standardabs
is undefined for the most negative value as well, so it is on par withx < 0 ? -x : x
solution.
$endgroup$
– Eugene Sh.
8 hours ago
|
show 5 more comments
$begingroup$
There are a lot of subtle details in using C. Given your comment about speed, it is probably worth your time to try out various options and see which produces better assembly code results. Ask the compiler to generate assembly code and then read it. (This doesn't always catch the reality, though. Some compilers leave certain replacements to the linker step.) Or use the machine code and a disassembler and just look. (That always works.) It's not hard to do once you've worked out the steps in your situation.
Let me just suggest some options to consider. Perhaps that's the best I can do. (I'm assuming below that you don't want to take the absolute function of a constant, since there is an obvious "code time" solution for that case.)
- The abs() function that's available for your C compiler may very well be implemented in-line with the compiler. (Microsoft's x86 C compiler certainly does this.) If this is already handled within the compiler, looking at the machine code will tell you what you need to know. Sometimes, the assembly output isn't a sufficient test since some compilers will leave this optimization step to the linker process, instead. In those cases, you will have no choice but to examine the final machine code product.
- You can attempt to use the method you already mentioned (using an if statement or using the trinary ? operator.) Again, I've seen versions of Microsoft's C compiler that will eat these perfectly well and generate exactly the same case as if you'd used their in-line abs() version -- which for some targets will generate code without any branching involved and taking two or three instructions.
- You can use the method you've coded up (which is dependent on your word size.) You've coded one method: $left(n+maskright), text^, mask$.
- You could try: $left(n, text^, maskright)-mask$.
- You could try: $n-left(left[n << 1right], &: maskright)$ or $n-left(2,n, &: maskright)$ or $n-left(left[n+nright], &: maskright)$.
There are other options if you have a fast multiply for +1 or -1 (sometimes, that's easy.)
Be wary of, and follow, the C standards. Often, operations on negative signed values are undefined. They may behave as expected. But that behavior may not be portable or guaranteed.
As a final note, if you intend on writing a function in C it may pay to provide the compiler hint to make it an inline function.
$endgroup$
$begingroup$
@ThePhoton There's already a corner case in (n > 0 ? n : -n). The case where n is the maximal negative value (which that will return unchanged.) I was mostly trying to help list out as many different things to try with the compiler. By the way, which corner case are you considering?
$endgroup$
– jonk
9 hours ago
$begingroup$
I think shifting a signed datatype left (n << 1
) is undefined behavior for ANSI C. Multiplying a fixed-width datatype by 2 also risks silent integer overflow.
$endgroup$
– Elliot Alderson
9 hours ago
$begingroup$
@jonk good point on the maximal negative corner case. But this is the behavior even for the standard function right?
$endgroup$
– vangelo
9 hours ago
$begingroup$
@ElliotAlderson I just checked Harbison and Steele. In the left shift case C defines the behavior regardless of type and it is portable. However, you are right to be worried, in the right shift case, where the C compiler is permitted two different behaviors and it is not portable.
$endgroup$
– jonk
8 hours ago
$begingroup$
@jonk The left shift for negative value is undefined per the standard port70.net/~nsz/c/c11/n1570.html#6.5.7p4 . Worth noting that the standardabs
is undefined for the most negative value as well, so it is on par withx < 0 ? -x : x
solution.
$endgroup$
– Eugene Sh.
8 hours ago
|
show 5 more comments
$begingroup$
There are a lot of subtle details in using C. Given your comment about speed, it is probably worth your time to try out various options and see which produces better assembly code results. Ask the compiler to generate assembly code and then read it. (This doesn't always catch the reality, though. Some compilers leave certain replacements to the linker step.) Or use the machine code and a disassembler and just look. (That always works.) It's not hard to do once you've worked out the steps in your situation.
Let me just suggest some options to consider. Perhaps that's the best I can do. (I'm assuming below that you don't want to take the absolute function of a constant, since there is an obvious "code time" solution for that case.)
- The abs() function that's available for your C compiler may very well be implemented in-line with the compiler. (Microsoft's x86 C compiler certainly does this.) If this is already handled within the compiler, looking at the machine code will tell you what you need to know. Sometimes, the assembly output isn't a sufficient test since some compilers will leave this optimization step to the linker process, instead. In those cases, you will have no choice but to examine the final machine code product.
- You can attempt to use the method you already mentioned (using an if statement or using the trinary ? operator.) Again, I've seen versions of Microsoft's C compiler that will eat these perfectly well and generate exactly the same case as if you'd used their in-line abs() version -- which for some targets will generate code without any branching involved and taking two or three instructions.
- You can use the method you've coded up (which is dependent on your word size.) You've coded one method: $left(n+maskright), text^, mask$.
- You could try: $left(n, text^, maskright)-mask$.
- You could try: $n-left(left[n << 1right], &: maskright)$ or $n-left(2,n, &: maskright)$ or $n-left(left[n+nright], &: maskright)$.
There are other options if you have a fast multiply for +1 or -1 (sometimes, that's easy.)
Be wary of, and follow, the C standards. Often, operations on negative signed values are undefined. They may behave as expected. But that behavior may not be portable or guaranteed.
As a final note, if you intend on writing a function in C it may pay to provide the compiler hint to make it an inline function.
$endgroup$
There are a lot of subtle details in using C. Given your comment about speed, it is probably worth your time to try out various options and see which produces better assembly code results. Ask the compiler to generate assembly code and then read it. (This doesn't always catch the reality, though. Some compilers leave certain replacements to the linker step.) Or use the machine code and a disassembler and just look. (That always works.) It's not hard to do once you've worked out the steps in your situation.
Let me just suggest some options to consider. Perhaps that's the best I can do. (I'm assuming below that you don't want to take the absolute function of a constant, since there is an obvious "code time" solution for that case.)
- The abs() function that's available for your C compiler may very well be implemented in-line with the compiler. (Microsoft's x86 C compiler certainly does this.) If this is already handled within the compiler, looking at the machine code will tell you what you need to know. Sometimes, the assembly output isn't a sufficient test since some compilers will leave this optimization step to the linker process, instead. In those cases, you will have no choice but to examine the final machine code product.
- You can attempt to use the method you already mentioned (using an if statement or using the trinary ? operator.) Again, I've seen versions of Microsoft's C compiler that will eat these perfectly well and generate exactly the same case as if you'd used their in-line abs() version -- which for some targets will generate code without any branching involved and taking two or three instructions.
- You can use the method you've coded up (which is dependent on your word size.) You've coded one method: $left(n+maskright), text^, mask$.
- You could try: $left(n, text^, maskright)-mask$.
- You could try: $n-left(left[n << 1right], &: maskright)$ or $n-left(2,n, &: maskright)$ or $n-left(left[n+nright], &: maskright)$.
There are other options if you have a fast multiply for +1 or -1 (sometimes, that's easy.)
Be wary of, and follow, the C standards. Often, operations on negative signed values are undefined. They may behave as expected. But that behavior may not be portable or guaranteed.
As a final note, if you intend on writing a function in C it may pay to provide the compiler hint to make it an inline function.
edited 8 hours ago
answered 9 hours ago
jonkjonk
37.5k1 gold badge31 silver badges80 bronze badges
37.5k1 gold badge31 silver badges80 bronze badges
$begingroup$
@ThePhoton There's already a corner case in (n > 0 ? n : -n). The case where n is the maximal negative value (which that will return unchanged.) I was mostly trying to help list out as many different things to try with the compiler. By the way, which corner case are you considering?
$endgroup$
– jonk
9 hours ago
$begingroup$
I think shifting a signed datatype left (n << 1
) is undefined behavior for ANSI C. Multiplying a fixed-width datatype by 2 also risks silent integer overflow.
$endgroup$
– Elliot Alderson
9 hours ago
$begingroup$
@jonk good point on the maximal negative corner case. But this is the behavior even for the standard function right?
$endgroup$
– vangelo
9 hours ago
$begingroup$
@ElliotAlderson I just checked Harbison and Steele. In the left shift case C defines the behavior regardless of type and it is portable. However, you are right to be worried, in the right shift case, where the C compiler is permitted two different behaviors and it is not portable.
$endgroup$
– jonk
8 hours ago
$begingroup$
@jonk The left shift for negative value is undefined per the standard port70.net/~nsz/c/c11/n1570.html#6.5.7p4 . Worth noting that the standardabs
is undefined for the most negative value as well, so it is on par withx < 0 ? -x : x
solution.
$endgroup$
– Eugene Sh.
8 hours ago
|
show 5 more comments
$begingroup$
@ThePhoton There's already a corner case in (n > 0 ? n : -n). The case where n is the maximal negative value (which that will return unchanged.) I was mostly trying to help list out as many different things to try with the compiler. By the way, which corner case are you considering?
$endgroup$
– jonk
9 hours ago
$begingroup$
I think shifting a signed datatype left (n << 1
) is undefined behavior for ANSI C. Multiplying a fixed-width datatype by 2 also risks silent integer overflow.
$endgroup$
– Elliot Alderson
9 hours ago
$begingroup$
@jonk good point on the maximal negative corner case. But this is the behavior even for the standard function right?
$endgroup$
– vangelo
9 hours ago
$begingroup$
@ElliotAlderson I just checked Harbison and Steele. In the left shift case C defines the behavior regardless of type and it is portable. However, you are right to be worried, in the right shift case, where the C compiler is permitted two different behaviors and it is not portable.
$endgroup$
– jonk
8 hours ago
$begingroup$
@jonk The left shift for negative value is undefined per the standard port70.net/~nsz/c/c11/n1570.html#6.5.7p4 . Worth noting that the standardabs
is undefined for the most negative value as well, so it is on par withx < 0 ? -x : x
solution.
$endgroup$
– Eugene Sh.
8 hours ago
$begingroup$
@ThePhoton There's already a corner case in (n > 0 ? n : -n). The case where n is the maximal negative value (which that will return unchanged.) I was mostly trying to help list out as many different things to try with the compiler. By the way, which corner case are you considering?
$endgroup$
– jonk
9 hours ago
$begingroup$
@ThePhoton There's already a corner case in (n > 0 ? n : -n). The case where n is the maximal negative value (which that will return unchanged.) I was mostly trying to help list out as many different things to try with the compiler. By the way, which corner case are you considering?
$endgroup$
– jonk
9 hours ago
$begingroup$
I think shifting a signed datatype left (
n << 1
) is undefined behavior for ANSI C. Multiplying a fixed-width datatype by 2 also risks silent integer overflow.$endgroup$
– Elliot Alderson
9 hours ago
$begingroup$
I think shifting a signed datatype left (
n << 1
) is undefined behavior for ANSI C. Multiplying a fixed-width datatype by 2 also risks silent integer overflow.$endgroup$
– Elliot Alderson
9 hours ago
$begingroup$
@jonk good point on the maximal negative corner case. But this is the behavior even for the standard function right?
$endgroup$
– vangelo
9 hours ago
$begingroup$
@jonk good point on the maximal negative corner case. But this is the behavior even for the standard function right?
$endgroup$
– vangelo
9 hours ago
$begingroup$
@ElliotAlderson I just checked Harbison and Steele. In the left shift case C defines the behavior regardless of type and it is portable. However, you are right to be worried, in the right shift case, where the C compiler is permitted two different behaviors and it is not portable.
$endgroup$
– jonk
8 hours ago
$begingroup$
@ElliotAlderson I just checked Harbison and Steele. In the left shift case C defines the behavior regardless of type and it is portable. However, you are right to be worried, in the right shift case, where the C compiler is permitted two different behaviors and it is not portable.
$endgroup$
– jonk
8 hours ago
$begingroup$
@jonk The left shift for negative value is undefined per the standard port70.net/~nsz/c/c11/n1570.html#6.5.7p4 . Worth noting that the standard
abs
is undefined for the most negative value as well, so it is on par with x < 0 ? -x : x
solution.$endgroup$
– Eugene Sh.
8 hours ago
$begingroup$
@jonk The left shift for negative value is undefined per the standard port70.net/~nsz/c/c11/n1570.html#6.5.7p4 . Worth noting that the standard
abs
is undefined for the most negative value as well, so it is on par with x < 0 ? -x : x
solution.$endgroup$
– Eugene Sh.
8 hours ago
|
show 5 more comments
Thanks for contributing an answer to Electrical Engineering Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2felectronics.stackexchange.com%2fquestions%2f446457%2fimplementing-absolute-value-function-in-c%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
$begingroup$
Multiplying by -1 is just bitwise inversion and adding 1. Any decent compiler will know this and generate this code instead of a multiply. Your code might be faster (depending on architecture) because it doesn't branch.
$endgroup$
– The Photon
10 hours ago
2
$begingroup$
Probably the most bang for the buck is making it a macro and not a function call, since the call overhead is bigger than the work you do in the function. That's what stdlib.h will typically take care off as well.
$endgroup$
– Hilmar
9 hours ago
4
$begingroup$
@Hilmar Preprocessor macros are evil. Much better would be an inline function, so the compiler can do type checking.
$endgroup$
– Elliot Alderson
9 hours ago