Reputation: 42228
I am not trying to optimize anything, so please don't tell me, that premature optimization is root of all evil. I am trying to solve a problem and I can't find the third solution.
The problem goes like this:
if (x)
y = a;
else
y = b;
x
can only be 0 or 1. How to write this condition without a jump?
One solution, with a data structure, is:
int temp[2] = {b, a};
y = temp[x];
Another arithmetic solution is:
y = x * a + (1 - x) * b;
There is supposed to be a third one, a logical solution. Do you know how it looks like? Please give a solution in C.
Upvotes: 4
Views: 591
Reputation: 6690
EDIT: I misread the question which states that the C code shouldn't use a jump at all.
I think I'd go with
y = b;
if (x)
y = a;
If I read the following disassembled code right, there should be only one jump:
0000000000400474 <main>:
400474: 55 push %rbp
400475: 48 89 e5 mov %rsp,%rbp
400478: 8b 45 fc mov -0x4(%rbp),%eax
40047b: 89 45 f8 mov %eax,-0x8(%rbp)
40047e: 83 7d f4 00 cmpl $0x0,-0xc(%rbp)
400482: 74 06 je 40048a <main+0x16>
400484: 8b 45 f0 mov -0x10(%rbp),%eax
400487: 89 45 f8 mov %eax,-0x8(%rbp)
40048a: c9 leaveq
40048b: c3 retq
40048c: 90 nop
40048d: 90 nop
40048e: 90 nop
40048f: 90 nop
Upvotes: -3
Reputation: 18727
This maybe isn't the best solution, but I think it is the bitwise equivalent without jumps:
y = (~(x*UINT_MAX) & a) | (~(1 - x) & b);
Upvotes: 2
Reputation: 57749
For processors that allow conditional execution of statements:
y = a;
if (x != 0) y = b;
On an ARM processor in 32 bit mode, this should translate into the following pseudo instructions:
mov y, a; move a into y.
test x; (or XOR X, X ; to set condition codes)
MOVNZ y, b ; move b into y if condition is non-zero.
No jumps involved here, at least at the assembly language level.
Note: platform specific solution, may not be valid for processors without conditional instruction execution capabilities.
Upvotes: 0
Reputation: 26164
The following code use the trick that, as x
is either 1 or 0, x-1
is either 0 or -1 (a.k.a. 0xFFFFFFFF, assuming 32 bit int:s). If x
is 1, the result of the &
is zero, so the result is a
. When x
is zero, the result of the &
will be b-a
, the total result will then be a+(b-a)
or simply b
.
int test(int x, int a, int b)
{
return a + ( (((unsigned int)x)-1) & (b - a) );
}
On a fictitious micro-controller (without any fancy conditional move instructions) this will result in four instructions:
ADD #-1 R12
SUB R13, R14
AND R14, R12
ADD R13, R12
Admittedly, this is very similar to the XOR solution posted by @6502.
Upvotes: 0
Reputation: 12339
I agree with Jens; a ternary operator will do the trick without a jump.
y = x ? a : b
BTW, there is a sister site, Code Golf, where people ask questions of the nature "How can I solve problem x with the shortest amount of code while maintaining constraint y?"
Upvotes: 0
Reputation: 30055
Something like the choose function here then?
#include <stdio.h>
int choose(unsigned int x, int a, int b)
{
unsigned int selector = -x;
return (a & selector) | (b & ~selector);
}
int main()
{
printf("%d\n", choose(0, 123, 200));
printf("%d\n", choose(1, 123, 200));
}
Upvotes: 0
Reputation: 2247
switch (x) {
case 1:
y = a;
break;
default:
y = b;
break;
}
EDIT: the original question said "with jumps" ... not "without"
Upvotes: -1
Reputation: 30055
Are you saying you don't want a jump in the source code or at the CPU level?
On my compiler
int choose(int x, int a, int b)
{
int y;
if (x)
y = a;
else
y = b;
return y;
}
compiles to this -
test ecx, ecx
cmovne r8d, edx
mov eax, r8d
ret 0
Although I've written a jump at the C code level there isn't one in the generated machine code as the compiler is able to use a conditional move instruction.
Upvotes: 4