How can we take care of the overflow happening during swapping of two variables without using a third variable. I believe the XOR solution can be used only for integers. what about other variable types?
This isn't an answer but it doesn't fit in a comment.
Under what circumstances would you be running so close to the edge of your available stack storage that the additional use of a temporary variable for the swap is going to cause you difficulties?
I could see some embedded scenarios, but I'm hard pressed to imagine a scenario where you'd be so tight on stack space that this would matter (where you're not writing code in assembly language).
XOR will work for anything you can get your XOR operator to process; it's a property of binary data, not of binary data used to represent integers.
By not doing it at all. The XOR swap algorithm is cool hack. It shouldn't be used in production code.
The XOR solution works with any type that can be bitwise copied, not just integers. However, do not XOR a variable with itself: i.e.
int x = 10;
int *p1 = &x;
int *p2 = p1;
*p1 = *p1 ^ *p2;
*p2 = *p1 ^ *p2;
*p1 = *p1 ^ *p2;
/* now x == 0 :( */
What's wrong with XCHG? No stack needed, no overflow(carry flag)? set either :).
a = a + b;
b = a - b;
a = a - b;
This will work for integers and float.
Related
I tried the following code as a naive attempt to implement swapping of R and B bytes in an ABGR word
#include <stdio.h>
#include <stdint.h>
uint32_t ABGR_to_ARGB(uint32_t abgr)
{
return ((abgr ^= (abgr >> 16) & 0xFF) ^= (abgr & 0xFF) << 16) ^= (abgr >> 16) & 0xFF;
}
int main()
{
uint32_t tmp = 0x11223344;
printf("%x %x\n", tmp, ABGR_to_ARGB(tmp));
}
To my surprise this code "worked" in GCC in C++17 mode - the bytes were swapped
http://coliru.stacked-crooked.com/a/43d0fc47f5539746
But it is not supposed to swap bytes! C++17 clearly states that the RHS of assignment is supposed to be [fully] sequenced before the LHS, which applies to compound assignment as well. This means that in the above expression each RHS of each ^= is supposed to use the original value of abgr. Hence the ultimate result in abgr should simply have B byte XORed by R byte. This is what Clang appears to produce (amusingly, with a sequencing warning)
http://coliru.stacked-crooked.com/a/eb9bdc8ced1b5f13
A quick look at GCC assembly
https://godbolt.org/g/1hsW5a
reveals that it seems to sequence it backwards: LHS before RHS. Is this a bug? Or is this some sort of conscious decision on GCC's part? Or am I misunderstanding something?
The exact same behavior is exhibited by int a = 1; (a += a) += a;, for which GCC calculates a == 4 afterwards and clang a == 3.
The underlying ambiguity arises from this part of the standard (from working draft N4762):
[expr.ass]: 7.6.18 Assignment and compound assignment operators
Paragraph 1: The assignment operator (=) and the compound assignment operators all group right-to-left. All require a
modifiable lvalue as their left operand; their result is an lvalue referring to the left operand. The result in all
cases is a bit-field if the left operand is a bit-field. In all cases, the assignment is sequenced after the value
computation of the right and left operands, and before the value computation of the assignment expression.
The right operand is sequenced before the left operand. With respect to an indeterminately-sequenced
function call, the operation of a compound assignment is a single evaluation.
Paragraph 7: The behavior of an expression of the form E1 op = E2 is equivalent to E1 = E1 op E2 except that E1 is
evaluated only once. In += and -=, E1 shall either have arithmetic type or be a pointer to a possibly
cv-qualified completely-defined object type. In all other cases, E1 shall have arithmetic type.
GCC seems to be using this rule to internally transfrom (a += a) += a to (a = a + a) += a to a = (a = a + a) + a (since a = a + a has to be evaluated only once) - and for this expression the sequencing rules are correctly applied.
Clang however seems to do that last transformation step differently: auto temp = a + a; temp = temp + a; a = temp;
Both compilers give a warning about this, though (from the original code):
GCC: warning: operation on 'abgr' may be undefined [-Wsequence-point]
clang: warning: unsequenced modification and access to 'abgr' [-Wunsequenced]
So the compiler writers know about this ambiguity and decided to prioritize differently (GCC: Paragraph 7 > Paragraph 1; clang: Paragraph 1 > Paragraph 7).
This seems to be a defect in the standard.
Do not make things more complicated than necessary. You can swap the 2 components in a fairly straightforward way without painting yourself into dark corners of the language:
uint32_t ABGR_to_ARGB(uint32_t abgr) {
constexpr uint32_t mask = 0xff00ff00;
uint32_t grab = abgr >> 16 | abgr << 16;
return (abgr & mask) | (grab & ~mask);
}
It also generates much better assembly than the original version. On x86 it uses single rol instruction for the 3 bitwise operators to produce grab:
ABGR_to_ARGB(unsigned int):
mov eax, edi
and edi, -16711936
rol eax, 16
and eax, 16711935
or eax, edi
ret
I have some c# code that performs some bitwise operations on a byte. I am trying to do the same in golang but am having difficulties.
Example in c#
byte a, c;
byte[] data;
int j;
c = data[j];
c = (byte)(c + j);
c ^= a;
c ^= 0xFF;
c += 0x48;
I have read that golang cannot perform bitwise operations on the byte type. Therefore will I have to modify my code to a type uint8 to perform these operations? If so is there a clean and correct/standard way to implement this?
Go certainly can do bitwise operations on the byte type, which is simply an alias of uint8. The only changes I had to make to your code were:
Syntax of the variable declarations
Convert j to byte before adding it to c, since Go lacks (by design) integer promotion conversions when doing arithmetic.
Removing the semicolons.
Here you go
var a, c byte
var data []byte
var j int
c = data[j]
c = c + byte(j)
c ^= a
c ^= 0xFF
c += 0x48
If you're planning to do bitwise-not in Go, note that the operator for that is ^, not the ~ that is used in most other contemporary programming languages. This is the same operator that is used for xor, but the two are not ambiguous, since the compiler can tell which is which by determining whether the ^ is used as a unary or binary operator.
Simply,
X = Integer
Y = Another Integer
Z ( If used ,Integer Temp )
What's the most efficient method ?
Method I :
Z = X
X = Y
Y = Z
Method II :
X ^= Y
Y ^= X
X ^= Y
Edit I [ Assembly View ]
Method I :
MOV
MOV
MOV
Method II :
TEST ( AND )
JZ
XOR
XOR
XOR
Notes :
MOV is slower then XOR
TEST , JZ is used for XOR Equality Safe
`Method I uses extra register
In most cases, using a temporary variable (usually a register at assembly level) is the best choice, and the one that a compiler will tend to generate.
In most practical scenarios, the trivial swap algorithm using a
temporary register is more efficient. Limited situations in which XOR
swapping may be practical include: On a processor where the
instruction set encoding permits the XOR swap to be encoded in a
smaller number of bytes; In a region with high register pressure, it
may allow the register allocator to avoid spilling a register. In
microcontrollers where available RAM is very limited. Because these
situations are rare, most optimizing compilers do not generate XOR
swap code.
http://en.wikipedia.org/wiki/XOR_swap_algorithm
Also, your XOR Swap implementation fails if the same variable is passed as both arguments. A correct implementation (from the same link) would be:
void xorSwap (int *x, int *y) {
if (x != y) {
*x ^= *y;
*y ^= *x;
*x ^= *y;
}
}
Note that the code does not swap the integers passed immediately, but
first checks if their addresses are distinct. This is because, if the
addresses are equal, the algorithm will fold to a triple *x ^= *x
resulting in zero.
Try this way of swapping numbers
int a,b;
a=a+b-(b=a);
Not sure if this is possible, but is there an automatic way, using mod or something similiar, to automatically correct bad input values? For example:
If r>255, then set r=255 and
if r<0, then set r=0
So basically what I'm asking is whats a clever mathematical way to set this rather than using
if(r>255)
r=255;
if(r<0)
r=0;
How about:
r = std:max(0, std::min(r, 255));
The following function will output what you are looking for:
f(x) = (510*(1 + Sign[-255 + x]) + x*(1 + Sign[255 - x])*(1 + Sign[x]))/4
As shown here:
Could you do something like --
R = MIN(r, 255);
R = MAX(R, 0);
Depending on how your hardware and possibly how your interpreter deal with ints, you can do this:
Assuming that an unsigned int is 16 bits (to keep my masks short):
r = r & 0000000011111111;
If an int was 32 bits, you'd need 16 more zeros at the start of the bit mask.
After that bitwise AND, the maximum value r can have is 255. Depending on the hardware, an unsigned int might do something odd given a value below zero. I believe that case is already handled by the bitmask (at least on the hardware that I've used). If not, you can do r = min(r, 0); first.
I had similar problem when dealing with images. For some special values (like these ones, 0 and 255) you can use this nonportable method:
static inline int trim_8bit(unsigned i){
return 0xff & ((i | -!!(i & ~0xff))) + (i >> 31);
// where "0xff &" can be omitted if you return unsigned char
};
In real cases the clamping have to be performed rarely, so that you could write
static inline unsigned char trim_8bit_v2(unsigned i){
if (__builtin_expect(i & ~0xFF, 0)) // it's for gcc, use __assume for MSVC
return (i >> 31) - 1;
return i;
};
And to be sure which is fastest, measure.
how to swap two numbers inplace without using any additional space?
You can do it using XOR operator as:
if( x != y) { // this check is very important.
x ^= y;
y ^= x;
x ^= y;
}
EDIT:
Without the additional check the above logic fails to swap the number with itself.
Example:
int x = 10;
if I apply the above logic to swap x with itself, without the check I end up having x=0, which is incorrect.
Similarly if I put the logic without the check in a function and call the function to swap two references to the same variable, it fails.
If you have 2 variables a and b: (each variable occupies its own memory address)
a = a xor b
b = a xor b
a = a xor b
There are also some other variations to this problem but they will fail if there is overflow:
a=a+b
b=a-b
a=a-b
a=a*b
b=a/b
a=a/b
The plus and minus variation may work if you have custom types that have + and - operators that make sense.
Note: To avoid confusion, if you have only 1 variable, and 2 references or pointers to it, then all of the above will fail. A check should be made to avoid this.
Unlike a lot of people are saying it does not matter if you have 2 different numbers. It only matters that you have 2 distinct variables where the number exists in 2 different memory addresses.
I.e. this is perfectly valid:
int a = 3;
int b = 3;
a = a ^ b;
b = a ^ b;
a = a ^ b;
assert(a == b);
assert(a == 3);
The xor trick is the standard answer:
int x, y;
x ^= y;
y ^= x;
x ^= y;
xoring is considerably less clear than just using a temp, though, and it fails if x and y are the same location
Since no langauge was mentioned, in Python:
y, x = x, y