Is there a non-branching bitwise solution to determine the "odd one out of 3" number if two are equal, else the first one? - c

int64_t foo(int64_t a, int64_t b, int64_t c){
return a == b ? c : a == c ? b : a;
}
Is there any non-branching bitwise hack that implements the function above?

yes, the are:
return ((!(a-b))*(c^a))^((!(a-c))*(b^a))^a;
if a=b=c: (1*(c^a))^(1*(b^a))^a = a^b^c= a
if a=b != c: then (1*(c^a))^0^a= c^a^a= c
the same for a=c != b
if a != b != c: (0*(a^c))^(0*(a^b))^a = 0^0^a=a
it is questionable if this way is faster, but try it.
UB-Warning.
if a-b or a-c result in a over or underflow, it is undefined behavior. may use unsigned variables.

Related

What does b = a && b mean in C?

a=5; b=0; c=1;
if(b=2) c = a++ & b;
else a=4;
b = a && b;
Code is in C. How will this code work? What will a, b, c have values? What
does b = a && b mean in C?
In C, && is the logical AND operator. Therefore a && b is the result of the logical operation "a AND b". Since C originally had no boolean type you often see int being "abused" as an substitute. An int is "true", if it has a non-zero value - and "false" if it is zero. (I think C99 added some boolean type called _Bool, but I'm not exactly sure on that one.) So the result of the expression a && b is either 1, if both a and b are non-zero, or zero if (at least) one of them is zero. That also is what gets assigned to b in b = a && b; then.
However, there also is the binary & operator in C, which is the bitwise AND and does something different than &&. This can also be a source of confusion and unintended errors/bugs in C code, because accidentally missing a & in && changes the behaviour of the compiled code.

What happens when we arbitrarily use ==?

I tried running the following code in C:
#include <stdio.h>
int main() {
int a = 10, b = 5, c = 5;
int d;
d = b + c == a;
printf("%d", d);
}
I got the output as d = 1. Can someone please explain to me what happens when we use == like this?
§6.5.9 (== and !=)-http://c0x.coding-guidelines.com/6.5.9.html
The == (equal to) and != (not equal to) operators are analogous to the relational operators except for their lower precedence.)Each of the operators yields 1 if the specified relation is true and 0 if it is false. The result has type int.
For any pair of operands, exactly one of the relations is true.
So here as b+c is equal to a as both has value 10 therefore it yields 1.
Because b + c is executed first, and after is evaluate comparison with == operator.
In c, addition has higher precedence than ==, so it adds b and c before comparing the result to a, since it is true it results in 1, if it was false it would result in 0.
== is the equal-to operator. It returns 1 if the two sides are equal and 0 otherwise.

C programming: How could you compare two types without ==

I was wondering how the C compiler would handle the comparison operator '=='
I wish to create a function (in C) that compares two things without using the ==. I think it can be done some how by using bitwise operators ( &, |, ^, >>) however I can't seem to think of how to do it.
Anyone have ideas?
Thanks!
Here's a simple way to check if two ints are equal without using ==:
int x = 3;
int y = 3;
if(x < y || y < x)
printf("Not equal");
else
printf("Equal");
For integral types, if (!(a - b)) will work.
You might run into some funny problems with other types.
Maybe if (!(a ^ b))?
Without using ==:
int is_a_equal_to_b(int a, int b)
{
if (a > b || a < b) return 0; /* Not equal. */
return 1; /* Equal. */
}
What if you invert every bit of one of the values and then "&" the two values together. If the result is zero, then they should be equal.
int x=5;
int y=5;
int z=(~x)&y;
if(!(y>0||y<0)){
//Values are equal.
}
Why don't you want to use the "==" operator?
Since you're wondering how the compiler does it, it translates == into machine code that contains a cmp instruction. This instruction compares two operands, and stores the result of the comparison. The result can be checked to see if the operands were equal, not equal, less than, greater than, etc.
In the case of using == in an if statement, it would probably generate something like this:
cmp op1, op2
jne else_address
which basically means 'Compare the two values. If they are not equal, skip to the else block.'
Other answers are good, but if you want only bitwise operators, do something like:
int is_equal(int a,int b) {
int bit=1;
while(bit) {
if ((a&bit)^(b&bit)) return 0;
bit<<=1;
}
return 1;
}

Connection between ternary logic and mux logic?

I'm implementing a computer simulator in C with the challenge not to use conditionals (ie no if/else, switch/case, while/for, etc.). There are a lot of muxes in the hardware I'm simulating, so it would be nice if I could use the conditional ternary logic operators. So, my question: do C compilers create MUX logic from ternary logic operators, or do they create branches?
Example:
int a, b, q, r;
/* Ternary logic */
r = q ? a : b;
/* MUX equivalent logic */
r = ( q & a ) | ( (~q) & b )
/* Branch equivalent logic */
if (q) r = a; else r = b;
The ternary operator is equivalent to a branch: i.e. the value not returned is not evaluated.
I don't know how much you are constrained, so note that boolean operators && and || don't evaluate their second argument is the result can be determined from the first.
(And note that you line "MUX" doesn't something very different from the other two expressions: it select bits from a or b depending on the value of corresponding bit in q, it doesn't select a or b depending if q is null or not; Edit: it is worse: you are using !q and not ~q...).
C compilers create branches out of ternary statements.
Using Freescale's Codewarrior IDE, I compiled the following C program:
int a, b, q, r;
void main(void) {
a = 0;
b = 1;
q = 0;
r = q ? a : b;
..
..
}
The assembly corresponding to the ternary statement is as follows:
...
LDX 0x1104 ; load val[q] into register x
BNE *+4 ; branch to abs addr 0xC016 if val[q]==a
BRA *+5 ; branch to abs addr 0xC019 if val[q]!=a
...
Often, branching logic is created, but is very possible to do ternary operation without any kind of branch if you're fine with both values being evaluated. Consider this:
#include <stdio.h>
static inline int isel(int cond, int a, int b)
{
int mask = cond | (-cond);
mask >>= 31;
return (b & mask) | (a & ~mask);
}
int main(void)
{
printf("1 ? 3 : 4 => %d\n", isel(1, 3, 4));
printf("0 ? 3 : 4 => %d\n", isel(0, 3, 4));
printf("-1 ? 3 : 4 => %d\n", isel(-1, 3, 4));
return 0;
}
This code assumes that right-shifting of signed numbers will sign-extend, and that sizeof(int) == 4.
Some processors can do isel() as an assembly instruction. However, both values will be evaluated, which the ternary ?: doesn't do.
Depending on the situation, the compiler will generally try to do the fastest thing, either branching to avoid redundant calculation, or doing this kind of logic if values in the ternary expression are simple.

C: Implicit casting and integer overflowing in the evaluation of expressions

Let's take the code
int a, b, c;
...
if ((a + b) > C)
If we add the values of a and b and the sum exceeds the maximum value of an int, will the integrity of the comparison be compromised? I was thinking that there might be an implicit up cast or overflow bit check and that will be factored into the evaluation of this expression.
C will do no such thing. It will silently overflow and lead to a possibly incorrect comparison. You can up-cast yourself, but it will not be done automatically.
A test confirms that GCC 4.2.3 will simply compare with the overflowed result:
#include <stdio.h>
int main()
{
int a, b, c;
a = 2000000000;
b = 2000000000;
c = 2100000000;
printf("%d + %d = %d\n", a, b, a+b);
if ((a + b) > c)
{
printf("%d + %d > %d\n", a, b, c);
}
else
{
printf("%d + %d < %d\n", a, b, c);
}
return 0;
}
Displays the following:
2000000000 + 2000000000 = -294967296
2000000000 + 2000000000 < 2100000000
I believe this might be platform specific. Check the C documentation on how overflows are handled...
Ah, yes, and the upcast will not happen automatically...
See section 2.7, Type Conversions in the K&R book
If upcasting doesn't gain you any bits (there's no guarantee that sizeof(long)>sizeof(int) in C), you can use conditions like the ones below to compare and check for overflow—upcasting is almost certainly faster if you can use it, though.
#if !defined(__GNUC__) || __GNUC__<2 || (__GNUC__==2 && __GNUC_MINOR__<96)
# define unlikely(x) (x)
#else
# define unlikely(x) (__extension__ (__builtin_expect(!!(x), 0)))
#endif
/* ----------
* Signed comparison (signed char, short, int, long, long long)
* Checks for overflow off the top end of the range, in which case a+b must
* be >c. If it overflows off the bottom, a+b < everything in the range. */
if(a+b>c || unlikely(a>=0 && b>=0 && unlikely(a+b<0)))
...
/* ----------
* Unsigned comparison (unsigned char, unsigned short, unsigned, etc.)
* Checks to see if the sum wrapped around, since the sum of any two natural
* numbers must be >= both numbers. */
if(a+b>c || unlikely(a+b<a))
...
/* ----------
* To generate code for the above only when necessary: */
if(sizeof(long)>sizeof(int) ? ((long)a+b>c)
: (a+b>c || unlikely(a>=0 && b>=0 && unlikely(a+b<0)))
...
Great candidates for macros or inline functions. You can pull the "unlikely"s if you want, but they can help shrink and speed up the code GCC generates.

Resources