Reducing number of operations - c

I have a function to find the max of three numbers, but it uses 24 ops I want to reduce it to 20 ops. Only using bitwise operations.
int maxOfThree(int x, int y, int z) {
int a1 = (x+(~y+1))>>31;
int a2 = (x+(~z+1))>>31;
int a3 = (y+(~z+1))>>31;
return ((~a1&((a2&z)|(~a2&x))) | (a1& ((a3&z)|( ~a3&y)))) ;
}

Assuming that your code as written doesn't use any "illegal" operations (i.e. you are OK with +1), then you can write
#include <stdio.h>
int main(void) {
int x, y, z;
int mxy, mxyz;
x = 5;
y = 123;
z = 9;
mxy = x - ((x - y) & ((x - y) >> 31)); // max(x, y)
mxyz = mxy - ((mxy - z) & ((mxy - z) >> 31));
printf("max is %d\n", mxyz);
}
Only 10 operations. Every - can be replaced with a ~ and +1 adding a further 6 operations. I will leave that as an exercise. Point is - you don't need to evaluate max(x,y) and max(y,z) and max(x,z) separately. max(x,y,z) = max(max(x,y),z)... and that's where your savings come from.
UPDATE using only +1 and bitwise operators:
#include <stdio.h>
int main(void) {
unsigned int x, y, z, r;
unsigned int mxy, mxyz;
unsigned int xmy;
unsigned int mxymz;
x = 5;
y = 123;
z = 9;
xmy = x + (~y+1); // x minus y
mxy = x + ~(xmy & (xmy >> 31)) + 1; // max(x, y)
mxymz = mxy + (~z+1); // max(x,y) minus z
mxyz = mxy + (~(mxymz & (mxymz >> 31))+1); // max(x,y,z)
printf("max is %d\n", mxyz);
}
Total of 16 operations (plus 3 intermediate assignments to variables, if you're counting those). Using only + ~ >>. I think that counts.
A couple of points:
the hard-wired value 31 really should be sizeof(int) * CHAR_BIT - 1
You should be using unsigned integers since the >>31 operation is not recommended on signed integers (see https://www.securecoding.cert.org/confluence/display/seccode/INT13-C.+Use+bitwise+operators+only+on+unsigned+operands )

Related

Make a function to return 1 if x <= y, using only bitwise operators [duplicate]

This question already has answers here:
Bitwise Less than or Equal to
(6 answers)
Closed 4 years ago.
this is homework and I'm struggling with it along with at least the half of my class that I can see is here. Anyways. I need to make a function that returns 1 if x <= y else return 0.
We can only use: ! ~ & ^ | + << >> and the max ops count is: 24
All integers must be signed and there cannot be any calls made to any other functions that I've created or that C offers. We are allowed to assume all integers are 32 bits and they must be signed.
I'm unsure of where to begin with this function. so far I have the following:
int isLessOrEqual(int x, int y) {
int diff = (y+~x+1); //The same as y-x
int diffSign = (diff>>31) & 1; //if negative, this will be 1. Else it'll be 0.
return !diffSign;
}
This seems like it would work. But It doesn't work for certain inputs (according to the program that does the grading).
Here is a function that does work that I found online but I do not want to copy it. I would like to understand it and see why it works and mine does not. It seems that my code does not work when it overflows, and that needs to be handled.
int isLessOrEqual(int x, int y) {
int sign, isLess, dif, equal, isLessorEqual;
sign = x ^ y;
isLess = ~sign;
dif = y + (~x + 1);
equal = !dif;
sign = sign & x;
dif = ~dif;
isLess = isLess & dif;
isLess = isLess | sign;
isLess = isLess & (1 << 31);
isLessorEqual = (!!isLess) | (equal);
return isLessorEqual;
}
If someone could help me understand the differences or how these functions work and handle overflow, that would be greatly appreciated and is what I am asking for. I'm close, just can't figure out this overflow thing
People here seem to be doing your homework for you, instead of analyzing the working example as you asked.
This is not how I would write the function at all, and in fact seems like obfuscated code. It’s your homework, so I won’t give a complete solution. (ETA: Well, you’ve already seen the answer.)
Let’s rewrite a bit as static single assignments with less-misleading names:
#include <limits.h> // For CHAR_BIT
int isLessOrEqual(const int x, const int y) {
const int different_bits = x ^ y; // sign = x ^ y;
const int same_bits = ~different_bits; // isLess = ~sign;
const int y_minus_x = y + (~x + 1); // dif = y + (~x + 1);
const int x_equals_y = !y_minus_x; // equal = !dif;
const int bits_x_not_y = different_bits & x; // sign = sign & x;
const int y_minus_x_inverted = ~y_minus_x; // dif = ~dif;
const int same_bits_not_in_y_minus_x =
same_bits & y_minus_x_inverted // isLess = isLess & dif;
const int explained_below =
same_bits_not_in_y_minus_x | bits_x_not_y; // isLess = isLess | sign;
static const int sign_bit = 1 << (sizeof(y_minus_x)*CHAR_BIT - 1);
const int truthy_iff_less =
explained_below & sign_bit; // isLess = isLess & (1 << 31);
const int is_less_or_equal =
(!!truthy_iff_less) | x_equals_y; // isLessorEqual = (!!isLess) | (equal);
return is_less_or_equal;
}
I did make one fix: the posted code assumes that int is exactly 32 bits wide, which is not always true. I compute the correct mask for the sign bit at compile time.
De-obfuscating this way, we see that we could have skipped the operations to turn y_minus_x into explained_below. Looking more closely at explained_below, we see that each bit of it is set if any of the following is true: it is clear in all of x, y, and y-x, it is set in x and y but clear in y-x, or it is set in x but not y. Since we only care about the sign bit, we get a truthy value when: x and y are both positive and y-x >= 0, x and y are both negative and y-x >= 0, or x < 0 and y > 0.
So this code is different from yours in that it checks for overflows, when y-x appears to be negative although x is negative and y positive, or underflows when y-x appears to be positive although x is positive and y negative.
There are much simpler solutions to this. If you’re assuming x and y are only 32 bits long anyway, just cast them to long long int. It will take no longer on a 64-bit CPU and will never overflow or underflow. If you are working with your native word size, though, you could still shave off a few of those operations. You particularly don’t need to compute equality separately, and you could get by with fewer inversions. Remember De Morgan’s laws!
Spoiler
Since everyone else posted the answers for you anyway, and you’ve already seen the algorithm, I guess I might as well post one too. It’s similar except for coding style and some changes for portability (The type is not assumed to be exactly 32 bits wide, signed overflow is not assumed to behave like unsigned overflow, etc.), although it does still assume two’s-complement arithmetic.
#include <assert.h>
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
typedef int_fast32_t t;
typedef uint_fast32_t ut;
static const ut sign_bit = (ut)1 << (sizeof(ut)*CHAR_BIT - 1);
#define T_MIN INT_FAST32_MIN
#define T_MAX INT_FAST32_MAX
int lte( const t x, const t y )
{
const ut y_minus_x = (ut)y + ~(ut)x + 1; // Assumes two’s-complement math.
const ut different_bits = (ut)x ^ (ut)y;
const ut x_not_y = (ut)x & ~(ut)y;
const ut lte_without_overflow = ~(y_minus_x | different_bits);
const ut truthy_result = (lte_without_overflow | x_not_y) & sign_bit;
return !!truthy_result;
}
int print_testcase( const t x, const t y )
{
static const char op_lte[] = "<=";
static const char op_gt[] = ">";
assert( lte(x, y) == (x <= y) );
return printf( "%lld %s %lld.\n",
(long long int)x,
lte(x, y) ? op_lte : op_gt,
(long long int)y
);
}
int main(void)
{
static const t cases[][2] = {
{1,1}, {-1,-1}, {2,1}, {1,2}, {-2,-1}, {-1, -2}, {2, -1}, {1, -2},
{T_MAX, T_MIN}, {T_MIN, T_MAX}
};
static const ptrdiff_t ncases = sizeof(cases)/sizeof(cases[0]);
for ( ptrdiff_t i = 0; i < ncases; ++i ) {
print_testcase( cases[i][0], cases[i][1] );
}
return EXIT_SUCCESS;
}
Here is what I found to work. This accounts for overflow as well. Needed a second way to check.
int isLessOrEqual(int x, int y) {
int xSign, ySign, diffSign, answer;
xSign = (x >> 31) & 1; //1 if x < 0
ySign = (y>>31) & 1; //1 if y < 0
diffSign = ((y+~x+1)>>31)&1; //1 if y-x < 0
/*if xSign = 1, and y=0, then x must be less then y.
if x&y are both positive, and the difference is negative, then
y-x must be 0.*/
answer = ((!ySign) & xSign) | ((!(xSign^ySign)) & !diffSign);
return answer;
}
x-y can only overflow when x and y have opposite signs, so just handle those cases directly. Also no need to mask the sign bits with 1.
int isLessOrEqual(int x, int y) {
int diff = (y+~x+1);
int diffSign = diff>>31;
int xsign = x >> 31;
int ysign = y >> 31;
int forcetrue = xsign & ~ysign;
int forcefalse = xsign | ~ysign;
return !!(forcefalse&(forcetrue|~diffSign));
}
Of course this still has undefined behavior when the difference does overflow.
int isLessOrEqual(int x, int y) {
int diff = x + ~y + 1; // diff = x-y
int isNegative = (diff>>31) & 1; //if diff < 0, isNegative = 1
int isZero = !(diff & (~1+1)); // if diff == 0, isZero = 1
int xSign = (x>>31)&1;
int ySign = (y>>31)&1;
return isNegative | isZero | (xSign & (!ySign) & (!isNegative));
}

Why is the output of this expression different when the variable is replaced with what it is calculating anyways?

Here's the code segment. It's performing x/2^n, rounding towards 0. The first print statement calculates the correct value (-7 in this case), but the second statement, which is just the first statement with bias replaced with ((x>>31) & ((1<<n)+0xffffffff)) (what bias is calculating anyways) and produces 9. What's going on here?
#include <stdio.h>
int main(void) {
int x = 0x80000004;
int n = 0x1c;
int bias = ((x>>31) & ((1<<n)+0xffffffff));
printf("%d\n", (x + bias) >> n);
printf("%d\n", (x + ((x>>31) & ((1<<n)+0xffffffff))) >> n);
return 0;
}
The expressions x + bias and x + ((x>>31) & ((1<<n)+0xffffffff)) have different types; the first is an int, the second an unsigned int. The operator >> preserves the sign bit for ints, but not for unsigneds. (The compiler does not have to do this, but it may do this.) To see clearly what's going on, I have expanded the code a little:
#include <stdio.h>
int main(void) {
int x = 0x80000004;
int n = 0x1c;
int bias = ((x>>31) & ((1<<n)+0xffffffff));
printf("%d\n", (x + bias) >> n);
printf("%d\n", (x + ((x>>31) & ((1<<n)+0xffffffff))) >> n);
printf("%d\n", (x + (int)((x>>31) & ((1<<n)+0xffffffff))) >> n);
printf ("(int) %d\n", x + bias);
printf ("(unsigned) %u\n", x + ((x>>31) & ((1<<n)+0xffffffff)));
return 0;
}
The output is:
-7
9
-7
(int) -1879048189
(unsigned) 2415919107

Finding the greater number without conditional statements

I am trying to compare two numbers "a" and "b" and if a is greater than b, I would like to set another double c as 1 or else I would like to set c as 0.
The following is what I have done so far -
#include <stdio.h>
#include <math.h>
int main() {
double a = 0.01242;
double b = 0.04231;
double c = ceil(fmod(a,b));
//c should be 1 if a > b or else it should be 0
}
My problem here is it works for some numbers but usually ceil() would return something greater than 1.
I would like to do it without using any kind of operator that includes a boolean return type.
I think you can use following expression to find maximum of between a and b and use max(a, b) ^ b to find these are equal or not and then assign max(a, b) ^ b's result to c.(^ is bitwise xor)
max(a, b) = 1 / 2. * (a + b + sqrt((a - b) * (a - b)));
or
max(a, b) = 1 / 2. * (a + b + fabs(a-b));
we cannot use ^ operator on double so if you want use double following program maybe do your job :
#include <stdio.h>
#include <math.h>
double max(double a, double b)
{
return 1 / 2. * (a + b + fabs(a-b));
}
int main(int argc, char *argv[])
{
double b = 0.01242;
double a = 0.04231;
printf("%g\n", max(a, b));
int c = ceil(max(a, b) / b);
c = (c + 1) % c;
/* c should be 1 if a > b or else it should be 0 */
printf("%d\n", c);
}
Interesting problem I solved it like this:
//---------------------------------------------------------------------------
double fpu_cmp(double a,double b)
{
// a> b -> c=1
// a<=b -> c=0
double c; // a<=b a>=b
c=a-b; // c<=0.0 c>0.0
c/=fabs(c)+1e-323; // c={-1,0} c=+1.0
c+=fabs(c); // c=0.0 c=+2.0
c*=0.5; // c=0.0 c=+1.0
return c;
}
//---------------------------------------------------------------------------
work both on positive and negative values
how it works is explained in rems
first column is what is in c if a<=b
second column is what is in c if a>b
tested on interval a,b=<-3,+3> with step 0.01 and no errors
if you worry about the 1e-323 constant changing the 1.0 to 0.99999999...9
then you can still use return ceil(c); but I think in current state it is OK already
[notes]
fabs can be done with single bit operation
c*=0.5 is just exponent decrement (bit masked)
so the only slow operation is the FPU division
the 1e-323 is just to avoid division by zero (but can significantly change result if comparing very very close numbers) this constant is the minimal value avoiding division by zero. if you are computing on numbers at least 100 times bigger then that then you should be OK
In IEEE-754, you can compare the floating-point values as sign-magnitude integer values. So I'm using it here. The integer comparison is similar to the one I used in this answer, but unsigned version. Below is the raw version before converting to branchless
Here minus operator is not used either like the other question, but you can shorten the code by converting back to using minus.
int isGreaterI(uint64_t x, uint64_t y)
{
if ((x ^ y) >> 63) // never happens as we only pass absolute values as below
{
return (x >> 63) & 1;
}
else
{
uint64_t xm = ~x + 1ULL;
uint64_t diff = y + xm;
return diff >> 63;
}
}
int isGreaterF(double a, double b)
{
uint64_t ai = *((uint64_t*)(&a));
uint64_t bi = *((uint64_t*)(&b));
int result;
if ((ai ^ bi) >> 63) // different signs
{
result = bi >> 63; // bi < 0, ai > 0
}
else
{
uint64_t sign = ai >> 63;
result = isGreaterI(ai, bi);
if (sign)
result = !result;
}
return result;
}
After muxing the branches' results in the if blocks to remove conditionals and removing unneccessary branches we have the below final version
int isGreaterMagnitude(uint64_t x, uint64_t y)
{
uint64_t xm = ~x + 1ULL;
uint64_t diff = y + xm;
return diff >> 63;
}
int isGreaterF(double a, double b)
{
uint64_t ai = *((uint64_t*)(&a));
uint64_t bi = *((uint64_t*)(&b));
uint64_t mask = ((ai ^ bi) >> 63) + (~0ULL); // mask = 0 if a and b have different signs
uint64_t r1 = bi >> 63;
uint64_t sign = (int64_t)ai >> 63;
uint64_t r2 = isGreaterMagnitude(ai, bi);
r2 = (r2 & ~sign) | ((1 - r2) & sign);
return (r1 & ~mask) | (r2 & mask);
}

Byte swapping in bit wise operations

I have this function called byte swap I am supposed to implement. The idea is that the function takes 3 integers (int x, int y, int z) and the function will swap the y and z bytes of the int x. The restrictions are pretty much limited to bit wise operations (no loops, and no if statements or logical operators such as ==).
I don't believe that I presented this problem adequately so Im going to re attempt
I now understand that
byte 1 is referring to bits 0-7
byte 2 is referring to bits 8-15
byte 3 16-23
byte 4 24-31
My function is supposed to take 3 integer inputs, x, y and z. The y byte and z byte on the x then would have to get switched
int byteSwap(int x, int y, int z)
ex of the working function
byteSwap(0x12345678, 1, 3) = 0x56341278
byteSwap(0xDEADBEEF, 0, 2) = 0xDEEFBEAD
My original code had some huge errors in it, namely the fact that I was considering a byte to be 2 bits instead of 8. The main problem that I'm struggling with is that I do not know how to access the bits inside of the given byte. For example, when I'm given byte 4 and 5, how do I access their respected bits? As far as I can tell I can't find a mathematical relationship between the given byte, and its starting bit. I'm assuming I have to shift and then mask, and save those to variables.Though I cannot even get that far.
Extract the ith byte by using ((1ll << ((i + 1) * 8)) - 1) >> (i * 8). Swap using the XOR operator, and put the swapped bytes in their places.
int x, y, z;
y = 1, z = 3;
x = 0x12345678;
int a, b; /* bytes to swap */
a = (x & ((1ll << ((y + 1) * 8)) - 1)) >> (y * 8);
b = (x & ((1ll << ((z + 1) * 8)) - 1)) >> (z * 8);
/* swap */
a = a ^ b;
b = a ^ b;
a = a ^ b;
/* put zeros in bytes to swap */
x = x & (~((0xff << (y * 8))));
x = x & (~((0xff << (z * 8))));
/* put new bytes in place */
x = x | (a << (y * 8));
x = x | (b << (z * 8));
When you say the 'the y and z bytes of x' this implies x is an array of bytes, not an integer. If so:
x[z] ^= x[y];
x[y] ^= x[z];
x[z] ^= x[y];
will do the trick, by swapping x[y] and x[z]
After your edit, it appears you want to swap individual bytes of a 32 bit integer:
On a little-endian machine:
int
swapbytes (int x, int y, int z)
{
char *b = (char *)&x;
b[z] ^= b[y];
b[y] ^= b[z];
b[z] ^= b[y];
return x;
}
On a big-endian machine:
int
swapbytes (int x, int y, int z)
{
char *b = (char *)&x;
b[3-z] ^= b[3-y];
b[3-y] ^= b[3-z];
b[3-z] ^= b[3-y];
return x;
}
With a strict interpretation of the rules, you don't even need the xor trick:
int
swapbytes (int x, int y, int z)
{
char *b = (char *)&x;
char tmp = b[z];
b[z] = b[y];
b[y] = tmp;
return x;
}
On a big-endian machine:
int
swapbytes (int x, int y, int z)
{
char *b = (char *)&x;
char tmp = b[3-z];
b[3-z] = b[3-y];
b[3-y] = tmp;
return x;
}
If you want to do it using bit shifts (note <<3 multiplies by 8):
int
swapbytes (unsigned int x, int y, int z)
{
unsigned int masky = 0xff << (y<<3);
unsigned int maskz = 0xff << (z<<3);
unsigned int origy = (x & masky) >> (y<<3);
unsigned int origz = (x & maskz) >> (z<<3);
return (x & ~masky & ~maskz) | (origz << (y<<3)) | (origy << (z<<3));
}

Check if a number can be represented using n bits in 2’s complement

I'm working on a function that returns 1 when x can be represented as an n-bit, 2’s complement number and 0 if it can't. Right now my code works for some examples like (5, 3), (-4, 3). But I can't get it to work for instances where n is bigger than x like (2, 6). Any suggestions as to why?
I do have restrictions though which include casting, either explicit or implicit, relative comparison operators (<, >, <=, and >=), division, modulus, and multiplication, subtraction, conditionals (if or ? :), loops, switch statements, function calls, and macro invocations. Assume 1 < n < 32.
int problem2(int x, int n){
int temp = x;
uint32_t mask;
int maskco;
mask = 0xFFFFFFFF << n;
maskco = (mask | temp);
return (maskco) == x;
}
In your function, temp is just redundant, and maskco always have the top bit(s) set, so it won't work if x is a positive number where the top bit isn't set
The simple solution is to mask out the most significant bits of the absolute value, leaving only the low n bits and check if it's still equal to the original value. The absolute value can be calculated using this method
int fit_in_n_bits(int x, int n)
{
int maskabs = x >> (sizeof(int) * CHAR_BIT - 1);
int xabs = (x + maskabs) ^ maskabs; // xabs = |x|
int nm = ~n + 1U; // nm = -n
int mask = 0xFFFFFFFFU >> (32 + nm);
return (xabs & mask) == xabs;
}
Another way:
int fit_in_n_bits2(int x, int n)
{
int nm = ~n + 1U;
int shift = 32U + nm;
int masksign = x >> (shift + 1);
int maskzero = 0xFFFFFFFFU >> shift;
return ((x & maskzero) | masksign) == x;
}
You can also check out oon's way here
int check_bits_fit_in_2s_complement(signed int x, unsigned int n) {
int mask = x >> 31;
return !(((~x & mask) + (x & ~mask))>> (n + ~0));
}
One more way
/*
* fitsBits - return 1 if x can be represented as an
* n-bit, two's complement integer.
* 1 <= n <= 32
* Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 2
*/
int fitsBits(int x, int n) {
int r, c;
c = 33 + ~n;
r = !(((x << c)>>c)^x);
return r;
}
Related:
How to tell if a 32 bit int can fit in a 16 bit short
counting the number of bit required to represent an integer in 2's complement
int problem2_mj(int x, int n){
unsigned int r;
int const mask = (-x) >> sizeof(int) * CHAR_BIT - 1;
r = (-x + mask - (1 & mask)) ^ mask; // Converts +n -> n, -n -> (n-1)
return !(((1 << (n-1)) - r) >> sizeof(int) * CHAR_BIT - 1);
}
Find the absolute value and subtract 1 if the number was negative
Check if number is less than or equal to 2n-1
Check a working demo here
As per your updated request here is the code how to add two numbers:
int AddNums(int x, int y)
{
int carry;
// Iteration 1
carry = x & y;
x = x ^ y;
y = carry << 1;
// Iteration 2
carry = x & y;
x = x ^ y;
y = carry << 1;
...
// Iteration 31 (I am assuming the size of int is 32 bits)
carry = x & y;
x = x ^ y;
y = carry << 1;
return x;
}

Resources