|
YongSheng Li wrote:
when two operands(integer) XORed together, the outcome is the sum of them
No, It's not. XORing is different from SUMming. Let's take the example of your second line:
YongSheng Li wrote:
(4)00000100^(6)00000110 = (2)00000010
As I told in the previous post, the last bit in the result is OFF (as both are OFF in operands), the second last bit is ON (as the second last bit of one operand is OFF and that of the other is ON), again the 3rd last bit is OFF(as they both are ON in operands), remaining bits of the result are OFF as they are same (OFF) in both the operands.
If you apply the same logic to all your results, you'll find that there are no exceptions.
P.S. That's why "a^a" is zero, but "a+a" is not.
Regards,
Pravin
|
|
|
|
|
Hello,
I don't think that you know how the XOR works. Take a look at the following table and you'll see the problem:
-----------------------------------
| Param1 | Param2 | Result of XOR |
-----------------------------------
| true | false | true |
| true | true | false |
| false | true | true |
| false | false | false |
-----------------------------------
Hope this helps
Behind every great black man...
... is the police. - Conspiracy brother
Blog[^]
|
|
|
|
|
Later I found out that
doing swap without the temporary object with
void inplace_swap(int *x, int *y)<br />
{<br />
*x = *x ^ *y; <br />
*y = *x ^ *y; <br />
*x = *x ^ *y; <br />
}
is exactly the same with the three statements above that were commented!
So the question is boil down to when will '^' do the subtraction and when addition!
...always look on the <blink>bright
side of life...
(Whistle)
|
|
|
|
|
Why doing such an easy operation so difficult?
Try the following:
void inplace_swap(int* pX, int *pY)
{
*x = *x + *y;
*y = *x - *y;
}
This solution is not perfect in the sense that it can cause integer overflow problems. My assembler is rusty, but you could get around this problem by substracting with carry or something..
Behind every great black man...
... is the police. - Conspiracy brother
Blog[^]
|
|
|
|
|
If I believe that I'm correct, the version with the temporary object, generates less assembler instructions than this version.
If you take a look at the generated machine code, you'll see that what you are trying to do results in less optimal code!
Behind every great black man...
... is the police. - Conspiracy brother
Blog[^]
|
|
|
|
|
why don't you do it that way :
void inplace_swap(int *x, int *y) {
int tmp = *x;
*x = *y;
*y = tmp;
}
TOXCCT >>> GEII power [toxcct][VisualCalc]
|
|
|
|
|
He doesn't want to use the temporary object. I think that the most efficient way is to use the temporary object, but for some reasons, he doesn't want it..
Behind every great black man...
... is the police. - Conspiracy brother
Blog[^]
|
|
|
|
|
I think he just wanted the theory[^] behind the XOR swap.
On smaller processors the XOR swap would actually be faster than a temp variable or having to use a 3rd register if registers were already limited. However, you are correct that the optimization of a temp variable can be faster than the generated XOR swap from a C compiler (and using a modern processor).
void SwapXor(UINT *a, UINT *b)
{
*a = *a ^ *b;
*b = *a ^ *b;
*a = *a ^ *b;
}
image00400000+0x1000:
00401000 8b4c2408 mov ecx,[esp+0x8] ; ecx = b
00401004 8b442404 mov eax,[esp+0x4] ; eax = a
00401008 56 push esi
00401009 8b11 mov edx,[ecx] ; edx = *b
0040100b 8b30 mov esi,[eax] ; esi = *a
0040100d 33f2 xor esi,edx ; temp = *a ^ *b
0040100f 8930 mov [eax],esi ; *a = esi(temp)
00401011 8bd6 mov edx,esi ; edx = *a
00401013 8b31 mov esi,[ecx] ; esi = *b
00401015 33f2 xor esi,edx ; temp = *b ^ *a
00401017 8931 mov [ecx],esi ; *b = esi (temp)
00401019 8b10 mov edx,[eax] ; edx = *a
0040101b 8bce mov ecx,esi ; ecx = *b
0040101d 5e pop esi
0040101e 33d1 xor edx,ecx ; temp = *a ^ *b
00401020 8910 mov [eax],edx ; *a = edx(temp)
00401022 c3 ret
void SwapTemp(UINT *a, UINT *b)
{
UINT Temp;
Temp = *a;
*a = *b;
*b = Temp;
}
00401030 8b542408 mov edx,[esp+0x8] ; edx = b
00401034 8b442404 mov eax,[esp+0x4] ; eax = a
00401038 56 push esi
00401039 8b32 mov esi,[edx] ; esi = *b
0040103b 8b08 mov ecx,[eax] ; ecx = *a
0040103d 8930 mov [eax],esi ; *a = esi
0040103f 890a mov [edx],ecx ; *b = ecx
00401041 5e pop esi
00401042 c3 ret
1 million XOR Swap = Milliseconds = 10.569012
1 million Temp Swap = Milliseconds = 4.846916
Generally, it's not the number of instructions that make the difference it's how the assembly is structured. This has no bearing in this case though because you get more instructions and you get slower code as well.
You notice that the memory is read multiple times as well as saved multiple times unnesscarily in the code path. You also notice that there was no "true" temp variable ever generated for the other code so even if you eliminate most of the code it's still not an optimal solution.
So, yes while it may look in C that you are being optimal by not using a "temp" variable, if your compiler is smart enough this doesn't matter and does generate faster code as Bob said. If you are working with embedded systems and are coding the direct assembly, an "xor" approach may work better depending on the situation. It could also work if you hand code assembly for different pipelines where 2 instructions may be executed at the same time. This depends though on if a simple "XCHG" instruction would cause a problem with a pipe "stall" or not.
However, in C I think you can rely on the compiler to optimize with the temp variable rather than atempting to do what is considered a lower level optimization in a higher level language (This is not to say that an "xor" swap is always nessecary in smaller CPUs at all, it's just a possible consideration for certain code optimizations which may or may not be useful. Generally XOR is faster to "set a register to 0" as the most common optimization, XOR EAX, EAX back when a "mov" "MOV EAX, 0" was considered a slow operation. I don't think that's the case any more on newer processors).
8bc7c0ec02c0e404c0cc0680f7018827ebee
|
|
|
|
|
After step 1, *x contains (*x ^ *y) . After step 2, *y contains (*y ^ (*x ^ *y)) , which is just *x . After step 3, *x contains ((*x ^ *y) ^ *x) , which is *y . Make sense? Any number XORed with itself is 0.
"Ideas are a dime a dozen. People who put them into action are priceless." - Unknown
|
|
|
|
|
The logic is this:
A = A (operation) B
B = A (operation Inverse) B
A = A (operation Inverse) B
If you do one operation and then two inverse operations you will have swapped the numbers. The "xor" operator is actually the inverse of itself, so that's why it works the way it does.
For example if you use +, - is the inverse:
A = 10, B = 20
A = A + B (10 + 20 = 30)
B = A - B (30 - 20 = 10)
A = A - B (30 - 10 = 20)
A = 20, B = 10
A = 10, B = 20
A = A * B (10*20 = 200)
B = A / B (200/20 = 10)
A = A / B (200/10 = 20)
A = 20, B = 10
A = 10, B = 20
A = A ^ B (10 ^ 20 = 30)
B = A ^ B (30 ^ 20 = 10)
A = A ^ B (30 ^ 10 = 20)
A = 20, B = 10
xor is also communiative, so it didn't matter the order you have A or B when doing ^. This XOR swap was generally used by small processors which memory operations were slow, so 3 XOR instructions could be faster. That actually used to be the method of setting registers to 0 as well, XOR reg, reg as it was faster than a MOV reg, 0.
8bc7c0ec02c0e404c0cc0680f7018827ebee
|
|
|
|
|
So you can think of it as:
1. Combine the numbers together and store in one of the values.
Combined = A + B for example 10 + 20 = 30. In +. But any operation will combine numbers.
2. Inverse, thus if two numbers are combined you will get the opposite number of what you inverse.
Original1 = Combined - B, for example, 30 - 20 = 10. You get the original number.
3. Using the opposite number, now you use the combined number to get the original.
Original2 = Combined - Original1 So you do the inverse again on the new number to get the original.
You can see that if you combine two numbers, you can use those numbers in inverse operations to get the original numbers.
8bc7c0ec02c0e404c0cc0680f7018827ebee
|
|
|
|
|
The Stupid XOR Trick[^]
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
"Obviously ??? You're definitely a superstar!!!" - mYkel - 21 Jun '04
"There's not enough blatant self-congratulatory backslapping in the world today..." - HumblePie - 21 Jun '05
Within you lies the power for good - Use it!
|
|
|
|
|
Is there any method found in the IDE of Visual C++ 2003 to remove functions seen in "Class View"? (other than manually delete text in .cpp and .h.)
Thanks!
Maxwell Chen
|
|
|
|
|
Hii alll
how can i change the background of my form????in vc++
thanks
|
|
|
|
|
You can read up on WM_CTLCOLORDLG[^] or you can set it when you register the window class.
Alex Korchemniy
|
|
|
|
|
Look in the CFrame, CMDIFrame, CView, or a class derived from one of these, for some methods to do this. Those classes perform the drawing of the windows and their background. There may be some public members that can be directly set also. My personal guess is a CFrame derived class. I don't remember completely, but you may have to use some API functions to get the pointers to the objects that would need to be changed.
The form background should not be in the App class or the Doc class, since these have to do with running the program and storing the data. I know this does not provide all the answer, but just gives somewhere to start.
David Spain, C++ Applications Programmer
|
|
|
|
|
Hi,
I want add a context menu on a tree (hosted in MFC Dialog), everything wotrk fine unless I do not get the menu draw (only a little strip).
So what's wrong in my code :
CMenu menu;
POINT pp;
GetCursorPos(&pp);
if (menu.LoadMenu(IDR_MENU_TREE))
{
menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
pp.x, pp.y,
AfxGetMainWnd()); // use main window for cmds
}
Thanks in advance ...
|
|
|
|
|
You are trying to show a top-level menu as a popup menu which is not possible.
You will need to get a submenu of IDR_MENU_TREE, like this:
menu.LoadMenu(IDR_MENU_TREE);
CMenu* pSubMenu = menu.GetSubmenu(0);
if (pSubMenu != NULL)
{
pSubMenu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
pp.x, pp.y, AfxGetMainWnd());
}
Hope this helps
|
|
|
|
|
hello,
i need to know steps to create a modeless dialog box in a parent SDI application.I know that a CreateDialog function is to be used;but how?
please guide
thanks
|
|
|
|
|
m_pDlg = new CMyDialog;
m_pDlg->Create (IDD_MYDIALOG);
m_pDlg->ShowWindow (SW_SHOW);
Note:Modeless dialog boxes are dismissed by calling DestroyWindow, not End-Dialog. You mustn't allow CDialog::OnOK or CDialog::OnCancel to be called on a modeless dialog box, because both call EndDialog.
Also create it on the heap always.
suhredayan There is no spoon.
|
|
|
|
|
It is a little long to explain how to use moldeless dialogs so I'll point you to an article: here[^] is a good article that explains the basis of modeless dialogs.
And, BTW, what do you mean by 'dialog box in a parent SDI application' ? The difference between modal and modeless dialogs is just that the dialog isn't 'blocking' (that means the parent window will still be active with a modeless dialog). The modeless dialog is not 'embedded' in the parent window.
|
|
|
|
|
cedric moonen wrote:
And, BTW, what do you mean by 'dialog box in a parent SDI application' ?
I think the second parameter below was meant by the parent.
explicit CDialog(
LPCTSTR lpszTemplateName,
CWnd* pParentWnd = NULL
);
suhredayan There is no spoon.
|
|
|
|
|
Yes of course I know that you can set a parent to a modeless dialog but I think what he really wants to do (as seen also in his previous post) is a dialog which is 'included' in the parent. So, that is a dialog that has no title bar and that is pasted on the parent. But I'm not sure so that's why I asked for some details.
|
|
|
|
|
thanks,
i was successful in creating a modeless dialog box.But i am still not able to use the Ondestroy() function.Kindly tell me the same.As you said that modeless dialog can't be opened in mdi window(which is exactly what i was trying).Then it means we will have to display it as child window.The properties section of dialog editor offers similar option.Is it correct?
thanks
|
|
|
|
|
Hello!
I need to show CPropertySheet object with not first page opened.
SetActivePage in OnInitDialog doesn't work. Can anybody help?
Oleg Chebotar
|
|
|
|