There seems to be some kind of misconception that this is for a contest.
I'm trying to work through an assignment and I've been stuck on this for an hour now.
/*
* isLessOrEqual - if x <= y then return 1, else return 0
* Example: isLessOrEqual(4,5) = 1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 24
* Rating: 3
*/
int isLessOrEqual(int x, int y)
{
int greater = (x + (~y + 1))>>31 & 1;
return !(greater)|(!(x^y));
}
I'm only able to use bitwise operators, as instructed in the comments.
I cannot figure out how to solve x <= y;
My thought process is that I can set x as its two's complement (~x +1) and add it with Y. If it is negative, X is greater than Y. Therefore, by negating that I can get the opposite effect.
Similarly, I know that !(x^y) is equivalent to x==y.
However,
doing !(greater)|(!(x^y)) does not return the proper value.
Where am I messing up? I feel like I'm missing a small bit of logic.
Those functions don't fully work because of the overflow, so that's how I solved the problem. Eh...
int isLessOrEqual(int x, int y) {
int diff_sgn = !(x>>31)^!(y>>31); //is 1 when signs are different
int a = diff_sgn & (x>>31); //diff signs and x is neg, gives 1
int b = !diff_sgn & !((y+(~x+1))>>31); //same signs and difference is pos or = 0, gives 1
int f = a | b;
return f;
}
If x > y, then y - x or (y + (~x + 1)) will be negative, hence the high bit will be 1, otherwise it will be 0. But we want x <= y, which is the negation of this.
/*
* isLessOrEqual - if x <= y then return 1, else return 0
* Example: isLessOrEqual(4,5) = 1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 24
* Rating: 3
*/
int isLessOrEqual(int x, int y)
{
return !(((y + (~x + 1)) >> 31) & 1);
}
Even better, drop the shift operator and use a bit mask on the high bit:
int isLessOrEqual(int x, int y)
{
return !((y + (~x + 1)) & 0x80000000);
}
EDIT:
As a commenter pointer out, the above version is susceptible to arithmetic overflow errors. Here is another version that covers the edge cases.
#include <limits>
int isLessOrEqual(int x, int y)
{
static int const vm = std::numeric_limits<int>::max();
static int const sm = ~vm;
return !! ((x & ~y | ~(x ^ y) & ~((y & vm) + ~(x & vm) + 1)) & sm);
}
Explanation: the overall strategy is to treat the sign bit of the inputs as logically distinct from the rest of the bits, the "value bits," and perform the subtraction as in the previous example on just the value bits. In this case, we need only perform the subtraction where the two inputs are either both negative or both non-negative. This avoids the arithmetic overflow condition.
Since the size of int strictly speaking is unknown at run time, we use std::numeric_limits<int>::max() as a convenient mask for the value bits. The mask of the sign bit is simply the bit-wise negation of the value bits.
Turning to the actual expression for <=, we factor out the bit-wise mask sm of the sign bit in each of the sub-expressions and push the operation to the outside of the expression. The first term of the logical expression x & ~y is true when x is negative and y is non-negative. The first factor of the next term ~(x ^ Y) is true when both are negative or both are non-negative. The second factor ~((y & vm) + ~(x & vm) + 1)) is true when y - x is non-negative, in other words x <= y, ignoring the sign bit. The two terms are or'd, so using c++ logical expression syntax we have:
x < 0 && y >= 0 || (x < 0 && y < 0 || x >= 0 && y >= 0) && y - x >= 0
The !! outermost operators convert the raised sign bit to a 1. Finally, here is the Modern C++ templated constexpr version:
template<typename T>
constexpr T isLessOrEqual(T x, T y)
{
using namespace std;
// compile time check that type T makes sense for this function
static_assert(is_integral<T>::value && is_signed<T>::value, "isLessOrEqual requires signed integral params");
T vm = numeric_limits<T>::max();
T sm = ~vm;
return !! ((x & ~y | ~(x ^ y) & ~((y & vm) + ~(x & vm) + 1)) & sm);
}
Really enjoyed Yanagar1's answer, which is very easy to understand.
Actually we can remove those shift operators and use De Morgan's laws, which reduce the number of operators from 15 to 11.
long isLessOrEqual(long x, long y) {
long sign = (x ^ y); // highest bit will be 1 if different sign
long diff = sign & x; // highest bit will be 1 if diff sign and neg x
long same = sign | (y + (~x + 1)); // De Morgan's Law with the following ~same
// highest bit will be 0 if same sign and y >= x
long result = !!((diff | ~same) & 0x8000000000000000L); // take highest bit(sign) here
return result;
}
Here is my implementation(spend around 3 hours...)
int
isLessOrEqual(int x, int y)
{
int a = y + ~x + 1;
int b = a & 1 << 31 & a; // !b => y >= x, but maybe overflow
int c = !!(x & (1 << 31)) & !(y & (1 << 31)); // y > 0, x < 0
int d = !(x & (1 << 31)) & !!(y & (1 << 31)); // x > 0, y < 0
int mask1 = !c + ~0;
// if y > 0 && x < 0, return 1. else return !b
int ans = ~mask1 & !b | mask1 & 1;
int mask2 = !d + ~0;
// if y < 0 && x > 0, return 0, else return ans
return ~mask2 & ans | mask2 & 0;
}
y - x == y + ~x + 1
a & 1 << 31 & a is simplify from !(!(a & (1 << 31)) | !a)
The logic is:
if `y > 0 && x < 0`
return true
if `x > 0 && y < 0`
return false
return y >= x
Why not just y >= x directly? because overflow may happen. So I have to early return to avoid overflow.
Inspired by Yanagar1's answer, here's my implementation:
int isLessOrEqual(int x, int y) {
int indicator = !((y + (~x + 1)) >> 31); // negation of the result of y - x, 0 when y < x, -1 when y >= x
int xsign = x >> 31; // -1 when x < 0, 0 when x >= 0
int ysign = y >> 31; // -1 when y < 0, 0 when y >= 0
int xbool = !xsign; // 0 when x < 0, 1 when x >= 0
int ybool = !ysign; // 0 when y < 0, 1 when y >= 0
int result = (!(xbool ^ ybool)) & indicator;
return result | (ybool & !xbool);
}
Explanation: Adding 2's complement negation of x (~x + 1) to y is essentially calculating y - x, then logical negate the sign bit of the result, we can have 0 when y < x, and 1 when y >= x. But there are potential overflow cases (overflow cannot happen when y and -x have opposite signs, that is, when y and x have same signs):
|-----------|------------------------|------------------------|
| | y > 0 | y < 0 |
|-----------|------------------------|------------------------|
| x > 0 | ok | overflow when y = TMin |
|-----------|------------------------|------------------------|
| x < 0 | overflow when x = TMin | ok |
|-----------|------------------------|------------------------|
so we need to be careful when the signs are different.
Might my solution is stupid.
int isLessOrEqual(int x, int y) {
/*
* A: sign bit of x B: sign bit of y C:A == B Result Rearrange the result(Expeced)
* 0 0 1 y - x >= 0 (y + (~x+1) >= 0) & 1 | 0 => (y + (~x+1) >= 0) & C | !(B | C)
* 0 1 0 0 (y + (~x+1) >= 0) & 0 | 0 => (y + (~x+1) >= 0) & C | !(B | C)
* 1 0 0 1 (y + (~x+1) >= 0) & 0 | 1 => (y + (~x+1) >= 0) & C | !(B | C)
* 1 1 1 y - x >= 0 (y + (~x+1) >= 0) & 1 | 0 => (y + (~x+1) >= 0) & C | !(B | C)
* But, minus operator is illegal. So (y - x) placed by (y + (-x)).
* You know -x == (~x + 1).
* If we know *x* and *y* have different sign bits, the answer is determinated and the (y-x >= 0) was useless.
* finally, the work like designing digital circuit. produce a final expression.
*/
int A = (x >> 31) & 1;
int B = (y >> 31) & 1;
int C = !(A ^ B);
int greatOrEqual0 = (!(((y + (~x + 1)) >> 31) ^ 0));
return (greatOrEqual0 & C) | !(B | C);
}
Related
I have a square matrix, 40 x 40, and a draw circle function that uses this formula.
I have another function that reads input from a file, the point itself (x0, y0) and the type of circle (0 or 1) and the radius.
void cerc(int x0, int y0, int r, int** matriceHarta, int tip, int n, int m)
{
if (r == 0)
return;
int x, y, xx, rr;
for (rr = r * r, x = -r; x <= r; x++)
for (xx = x * x, y = -r; y <= r; y++)
if (xx + (y * y) <= rr && matriceHarta[x0 + x][y0 + y] == 0)
{
if (tip == 0)
matriceHarta[x0 + x][y0 + y] = -5;
else if (tip == 1)
matriceHarta[x0 + x][y0 + y] = -6;
}
}
N and M are the rows and columns, but right now they are both equal.
The matrix is allocated dynamically and is transmitted via the int** matriceHarta parameter.
If I put the point on (39, 39) and I give it the radius 5, the program returns a negative exit code, which I found out is an out of bounds related error. I looked over the for loops and it makes sense that that'd be the error and tried to create the condition if((x0 + x) < n && (y0 + y) < m) to check the bounds, but it still gives the error.
Question is, what am I doing wrong? For contrast, point(37, 4) with radius = 2 is OK, but point(38, 4) with radius = 2 is not OK
This is the attempted fix:
for (rr = r * r, x = -r; x <= r; x++)
for (xx = x * x, y = -r; y <= r; y++)
if (xx + (y * y) <= rr && matriceHarta[x0 + x][y0 + y] == 0
&& (((x0+x) < n) && ((y0+y) < m)) )
//^^^^^ this is the condition i was talking about
{
if (tip == 0)
matriceHarta[x0 + x][y0 + y] = -5;
else if (tip == 1)
matriceHarta[x0 + x][y0 + y] = -6;
}
The issue is that you are testing for the out-of-bounds condition after you have already accessed potential out-of-bounds elements.
Let's break it down into separate lines:
if (xx + (y * y) <= rr && matriceHarta[x0 + x][y0 + y] == 0
&& // <-- This binds the conditions
(((x0+x) < n) && ((y0+y) < m)))
The line above the && marked with <-- is evaluated before the line below the <--.
In summary, the logical && is always evaluated from left-to-right, where the right side will not be evaluated if the left side evaluates to false (short-circuit boolean evaluation).
Thus the fix is to test the bounds condition first (swap the lines in the code above).
However, to make this a little more clear, you could break up the statement into two if statements:
if (x0+x < n && y0+y < m)
{
if (xx + (y * y) <= rr && matriceHarta[x0 + x][y0 + y] == 0)
{
...
}
}
I'm trying to reverse engineer a game function, which takes an integer and returns a 64-bit integer, by writing a function which returns the original value before it was put through the game function. How do I achieve this?
I have only managed to reverse these steps:
x = ((1 - x) << 16)
I'm not sure how to reverse the addition without the original value.
Here is the game function:
int64_t convert(int x) {
if (x <= 0)
return (1 - ((((x + 1) >> 31) + x + 1) >> 16));
else
return 0;
}
For example, if the original value was -5175633 then the converted value would be 80, I need to get the original value from 80.
I don't think this is possible. When you right-shift an integer, bits are lost. This means there are multiple input values that would return the same output value.
Sorry Victor, but your solution doesn't work. You ought to be comparing r and i, not c and cc.
Let's assume, with the step (1 - ((((x + 1) >> 31) + x + 1) >> 16)), x has converted to y, the we get:
y = 1 - ((((x + 1) >> 31) + x + 1) >> 16)
1 - y = (((x + 1) >> 31) + x + 1) >> 16
(1 - y) << 16 = (x + 1) >> 31 + x + 1
If x <= 0, then x + 1 <= 1. However this can't decide the sign bit. So we should assume once more.
if x + 1 < 0, then (x + 1) >> 31 is -1, which x < -1, y which is 1 - ((((x + 1) >> 31) + x + 1) >> 16), is 1 - (x >> 16)
(1 - y) << 16 = -1 + x + 1
(1 - y) << 16 = x
if x + 1 >= 0, then (x + 1) >> 31 is 0, which x >= -1, and y, which is 1 - ((((x + 1) >> 31) + x + 1) >> 16), is 1. (Note: now x can only be 0 or -1)
(1 - y) << 16 = x + 1
(1 - y) << 16 - 1 = x
So, include these two results together, we can get:
int reverse_convert(int64_t y) {
if (y == 1)
return (1 - y) << 16 - 1; // However, either x = 0 or x = 1 can produce this result.
else
return (1 - y) << 16;
// the condition of y == 0, corresponding to the original "else return 0;", is ignored.
}
Besides, the convert function is a Surjective-only function, which means multiple input can get the same output, then it is impossible to reverse precise output into input.
I will assume sizeof(int) is 4. And all the operations are done on 32 bits.
#include <iostream>
using namespace std;
int64_t convert(int32_t x) {
if (x <= 0)
return (1 - ((((x + 1) >> 31) + x + 1) >> 16));
else
return 0;
}
int32_t revconvert(int64_t r) {
if (r == 0) return 0;
if (r == 1) return -1;
return (1-r) << 16;
}
int main()
{
int32_t i;
for (i=0;i>-10000000;--i) {
auto c = convert(i);
auto r = revconvert(c);
auto cc = convert(r);
if( c!=cc) break;
}
cout << i << endl; // just to see if we got to the end
cout << convert(-5175633) << endl; // Will give 80
cout << revconvert(80) << endl; // Will give -5177344
cout << convert(-5177344) << endl; // Will give 80
return 0;
}
How to encode/decode morton codes(z-order) given [x, y] as 32bit unsigned integers producing 64bit morton code, and vice verse ?
I do have xy2d and d2xy but only for coordinates that are 16bits wide producing 32bit morton number. Searched a lot in net, but couldn't find. Please help.
If it is possible for you to use architecture specific instructions you'll likely be able to accelerate the operation beyond what is possible using bit-twiddeling hacks:
For example if you write code for the Intel Haswell and later CPUs you can use the BMI2 instruction set which contains the pext and pdep instructions. These can (among other great things) be used to build your functions.
Here is a complete example (tested with GCC):
#include <immintrin.h>
#include <stdint.h>
// on GCC, compile with option -mbmi2, requires Haswell or better.
uint64_t xy_to_morton(uint32_t x, uint32_t y)
{
return _pdep_u32(x, 0x55555555) | _pdep_u32(y,0xaaaaaaaa);
}
void morton_to_xy(uint64_t m, uint32_t *x, uint32_t *y)
{
*x = _pext_u64(m, 0x5555555555555555);
*y = _pext_u64(m, 0xaaaaaaaaaaaaaaaa);
}
If you have to support earlier CPUs or the ARM platform not all is lost. You may still get at least get help for the xy_to_morton function from instructions specific for cryptography.
A lot of CPUs have support for carry-less multiplication these days. On ARM that'll be vmul_p8 from the NEON instruction set. On X86 you'll find it as PCLMULQDQ from the CLMUL instruction set (available since 2010).
The trick here is, that a carry-less multiplication of a number with itself will return a bit-pattern that contains the original bits of the argument with zero-bits interleaved. So it is identical to the _pdep_u32(x,0x55555555) shown above. E.g. it turns the following byte:
+----+----+----+----+----+----+----+----+
| b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
+----+----+----+----+----+----+----+----+
Into:
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| 0 | b7 | 0 | b6 | 0 | b5 | 0 | b4 | 0 | b3 | 0 | b2 | 0 | b1 | 0 | b0 |
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
Now you can build the xy_to_morton function as (here shown for CLMUL instruction set):
#include <wmmintrin.h>
#include <stdint.h>
// on GCC, compile with option -mpclmul
uint64_t carryless_square (uint32_t x)
{
uint64_t val[2] = {x, 0};
__m128i *a = (__m128i * )val;
*a = _mm_clmulepi64_si128 (*a,*a,0);
return val[0];
}
uint64_t xy_to_morton (uint32_t x, uint32_t y)
{
return carryless_square(x)|(carryless_square(y) <<1);
}
_mm_clmulepi64_si128 generates a 128 bit result of which we only use the lower 64 bits. So you can even improve upon the version above and use a single _mm_clmulepi64_si128 do do the job.
That is as good as you can get on mainstream platforms (e.g. modern ARM with NEON and x86). Unfortunately I don't know of any trick to speed up the morton_to_xy function using the cryptography instructions and I tried really hard for several month.
void xy2d_morton(uint64_t x, uint64_t y, uint64_t *d)
{
x = (x | (x << 16)) & 0x0000FFFF0000FFFF;
x = (x | (x << 8)) & 0x00FF00FF00FF00FF;
x = (x | (x << 4)) & 0x0F0F0F0F0F0F0F0F;
x = (x | (x << 2)) & 0x3333333333333333;
x = (x | (x << 1)) & 0x5555555555555555;
y = (y | (y << 16)) & 0x0000FFFF0000FFFF;
y = (y | (y << 8)) & 0x00FF00FF00FF00FF;
y = (y | (y << 4)) & 0x0F0F0F0F0F0F0F0F;
y = (y | (y << 2)) & 0x3333333333333333;
y = (y | (y << 1)) & 0x5555555555555555;
*d = x | (y << 1);
}
// morton_1 - extract even bits
uint32_t morton_1(uint64_t x)
{
x = x & 0x5555555555555555;
x = (x | (x >> 1)) & 0x3333333333333333;
x = (x | (x >> 2)) & 0x0F0F0F0F0F0F0F0F;
x = (x | (x >> 4)) & 0x00FF00FF00FF00FF;
x = (x | (x >> 8)) & 0x0000FFFF0000FFFF;
x = (x | (x >> 16)) & 0x00000000FFFFFFFF;
return (uint32_t)x;
}
void d2xy_morton(uint64_t d, uint64_t &x, uint64_t &y)
{
x = morton_1(d);
y = morton_1(d >> 1);
}
The naïve code would be the same irregardless of the bit count. If you don't need super fast bit twiddling version, this will do
uint32_t x;
uint32_t y;
uint64_t z = 0;
for (int i = 0; i < sizeof(x) * 8; i++)
{
z |= (x & (uint64_t)1 << i) << i | (y & (uint64_t)1 << i) << (i + 1);
}
If you need faster bit twiddling, then this one should work. Note that x and y have to be 64bit variables.
uint64_t x;
uint64_t y;
uint64_t z = 0;
x = (x | (x << 16)) & 0x0000FFFF0000FFFF;
x = (x | (x << 8)) & 0x00FF00FF00FF00FF;
x = (x | (x << 4)) & 0x0F0F0F0F0F0F0F0F;
x = (x | (x << 2)) & 0x3333333333333333;
x = (x | (x << 1)) & 0x5555555555555555;
y = (y | (y << 16)) & 0x0000FFFF0000FFFF;
y = (y | (y << 8)) & 0x00FF00FF00FF00FF;
y = (y | (y << 4)) & 0x0F0F0F0F0F0F0F0F;
y = (y | (y << 2)) & 0x3333333333333333;
y = (y | (y << 1)) & 0x5555555555555555;
z = x | (y << 1);
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I need to divide number of 256 and round it to closer value, for example, if input 255 I want to get 1, not 0. Now I'm using
int x = 150;
int z = MulDiv(x, 1, 256);
But I think it is not optimal way to reach my goal, can someone advice better way.
Use this:
unsigned int x = 150;
unsigned int z = (x + 128) >> 8;
128 is middle value, so it after adding this your rounding works, and 256=2^8 so you can use bit shift operation instead of division.
NOTE: this way works for only positive values.
If you need this for positive and negative values you will need this:
int x = -150;
int z = (x >= 0 ? (x + 128) : (x - 128)) / 256;
NOTE: bit-shifting for signed values has some specific and not always can be trusted so you cannot use this: int z = (x < 0) ? (x - 128) / 256 : (x + 128) >> 8;
This will work for both positive and negative integers (and zero too):
int eps = x < 0 ? -128 : 128
int y = (x + eps) / 256;
The obligatory -pedantic and f[oo|ai]lsafe version:
if (x < INT_MIN + 128 || x > INT_MAX - 128) {
fputs("nasal demons!\n", stderr);
abort();
}
int eps = x < 0 ? -128 : 128;
int y = (x + eps) / 256;
For correct rounding to nearest of signed values you can do this:
y = (x >= 0 ? (x + 128) : (x - 128)) / 256;
To properly handle extremely large and small values you could use
int divideAndRound256(int x)
{
if(x > INT_MAX - 128)
return (x - 128) / 256 + 1;
else if(x < INT_MIN + 128)
return (x + 128) / 256 - 1;
else if(x < 0)
return (x - 128) / 256;
else
return (x + 128) / 256;
}
Or for just unsigned values
unsigned int divideAndRound256(unsigned int x)
{
if(x > UINT_MAX - 128)
return ((x - 128) >> 8) + 1;
else
return (x + 128) >> 8;
}
Here is code which returns number of leading zeros from Hacker's Delight book:
#include <iostream>
using namespace std;
int nlz(unsigned x) {
int n;
if (x == 0) return(32);
n = 1;
if ((x >> 16) == 0) {n = n +16; x = x <<16;}
if ((x >> 24) == 0) {n = n + 8; x = x << 8;}
if ((x >> 28) == 0) {n = n + 4; x = x << 4;}
if ((x >> 30) == 0) {n = n + 2; x = x << 2;}
n = n - (x >> 31);
return n;
}
int main(){
int x;
cin>>x;
cout<<nlz(x)<<endl;
return 0;
}
and when I enter number 8 it return 8 and is it correct maybe it should return 3 yes?
8//1000
It returns the number of leading bits that is zero in an unsigned integer , and it assumes an integer is 32 bits.
8 is 0000 0000 0000 0000 0000 0000 0000 1000 binary, and it should return 28 for that, as there's 28 leading bits zero before the first 1 bit. If you're running this on something where an integer is not 32 bits, it won't work.
This algorithm will return the number of leading zero bits from a 32-bit value. I don't see how it would return 8 for an input of 8.