AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Help required on Bitwise operation

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
SKAN



Joined: 26 Dec 2005
Posts: 5882

PostPosted: Tue Jun 19, 2007 11:50 am    Post subject: Help required on Bitwise operation Reply with quote

I have a situation where I expect an Integer value of 128 but getting a wrong value of 2147483776 instead!

When I inspect the bits, I find that the Most Significant Bit is ON ( for me it is wrongly signed?! ) .
How to set the Most Significant Bit OFF if it is ON ?

Code:
cInt := 128         ; Correct
wInt := 2147483776  ; Wrong

MsgBox, % "Correct:`t" NumToBits( cInt, 32 )
        . "`nWrong:`t" NumToBits( wInt, 32 )

NumToBits( Num=0, bits=32 ) {
 Loop %bits%
      bin := bin ( Num >> ( bits - A_Index) & 1)
Return bin
}


Please help! Rolling Eyes
Back to top
View user's profile Send private message
Dippy46



Joined: 06 Jul 2004
Posts: 171
Location: Manchester, England.

PostPosted: Tue Jun 19, 2007 12:29 pm    Post subject: Reply with quote

@ Skan

The short answer is any of the following:

Code:


 no1 := 2147483776 ^ 0x80000000 ; hex way
 no2 := 2147483776 ^ 2**31      ; use bit position
 no3 := 2147483776 ^ 2147483648 ; decimal way

 msgbox % no1 " " no2 " " no3



though obviously for clarity it's better to use the bit position.

If you're using this in a situation where you are defining the variable type
then make sure you're using UINT instead of INT because INT is always
going to return a signed result !

Regards Dave.
_________________
Simple ideas lie within reach, only of complex minds
Back to top
View user's profile Send private message
SKAN



Joined: 26 Dec 2005
Posts: 5882

PostPosted: Tue Jun 19, 2007 2:14 pm    Post subject: Reply with quote

@Dippy46

Thank you very much Sir! Very Happy

Quote:
though obviously for clarity it's better to use the bit position


One more related question: How to turn OFF first 6 bits from the left ?

Rolling Eyes
Back to top
View user's profile Send private message
Helpy
Guest





PostPosted: Tue Jun 19, 2007 3:19 pm    Post subject: Reply with quote

Should be something like:
x &= 0x03FFFFFF
Back to top
SKAN



Joined: 26 Dec 2005
Posts: 5882

PostPosted: Tue Jun 19, 2007 4:08 pm    Post subject: Reply with quote

It works! Many thanks Helpy! Very Happy

Code:
Int1 := 0xFFFFFFFF         ; Set all bits ON
Int2 := Int1 & 0x03FFFFFF  ; Set first 6 bits OFF

MsgBox, % NumToBits(Int1) "`n" NumToBits(Int2)


NumToBits( Num=0, bits=32 ) {
 Loop %bits%
      bin := bin ( Num >> ( bits - A_Index) & 1)
Return bin
}


Regards, Smile
Back to top
View user's profile Send private message
foom



Joined: 19 Apr 2006
Posts: 386

PostPosted: Tue Jun 19, 2007 4:20 pm    Post subject: Reply with quote

You could have done x:=(x<<6)>>6 but the & methond is faster and enables you to clear bytes in any range you like. Btw if you are unsure about how to convert a bitchain to the dezimal/hex value. You can use calc.exe in scientific mode to do this. Run calc, select scientific mode from the view menupoint, click the Bin radiobutton, type your bitchain, click the Hex radiobutton, and voila.
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4015
Location: Pittsburgh

PostPosted: Tue Jun 19, 2007 4:29 pm    Post subject: Reply with quote

Instead of Dippy46's XOR solution, bitwise AND is safer, as Helpy described. It clears the desired bits, while the XOR version flips them (if they were not set, they will be, afterwards).

To get the desired mask from a few bit positions to clear, do this
Code:
MsgBox % MakeMask(32-6)

MakeMask(bit1="",bit2="",bit3="",bit4="",bit5="") {
   mask = 0xFFFFFFFF ; -1 for 64-bit masks
   Loop {
      i := SubStr(A_Index,0) ; needed with SetFormat Integer, Hex
      IfEqual bit%i%,, Break
      mask ^= 1 << bit%i%
   }
   Return mask
}
To clear only bit6 from the left of 32-bit integers, the mask is 0xFBFFFFFF.

Last edited by Laszlo on Tue Jun 19, 2007 4:36 pm; edited 1 time in total
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4015
Location: Pittsburgh

PostPosted: Tue Jun 19, 2007 4:36 pm    Post subject: Reply with quote

foom wrote:
You could have done x:=(x<<6)>>6
It works only for 64-bit numbers, and only if bit58 was 0 originally. This technique is a clever way to do 64-bit sign extension.
Back to top
View user's profile Send private message
Titan



Joined: 11 Aug 2004
Posts: 5068
Location: imaginationland

PostPosted: Tue Jun 19, 2007 4:38 pm    Post subject: Reply with quote

Did everyone forget ToBin() lol. :/
_________________

RegExReplace("irc.freenode.net/ahk", "^(?=(.(?=[\0-r\[]*((?<=\.).))))(?:[c-\x73]{2,8}(\S))+((2)|\b[^\2-]){2}\D++$", "$u3$1$3$4$2")
Back to top
View user's profile Send private message Visit poster's website
Laszlo



Joined: 14 Feb 2005
Posts: 4015
Location: Pittsburgh

PostPosted: Tue Jun 19, 2007 4:46 pm    Post subject: Reply with quote

...and all the other, better versions posted before that?
Back to top
View user's profile Send private message
Titan



Joined: 11 Aug 2004
Posts: 5068
Location: imaginationland

PostPosted: Tue Jun 19, 2007 5:12 pm    Post subject: Reply with quote

I got the idea from Jon (the first) and posted on his thread. More specifically, my function does the bit shifting Skan needed to know.
_________________

RegExReplace("irc.freenode.net/ahk", "^(?=(.(?=[\0-r\[]*((?<=\.).))))(?:[c-\x73]{2,8}(\S))+((2)|\b[^\2-]){2}\D++$", "$u3$1$3$4$2")
Back to top
View user's profile Send private message Visit poster's website
SKAN



Joined: 26 Dec 2005
Posts: 5882

PostPosted: Tue Jun 19, 2007 6:03 pm    Post subject: Reply with quote

This help topic has reference to my code posted here : http://www.autohotkey.com/forum/viewtopic.php?p=98203#98203

When A CD/DVD is inserted in a drive, WM_DEVICECHANGE is broadcast with with wParam as 0x8000 ( DBT_DEVICEARRIVAL ) and lParam will be a pointer to DEV_BROADCAST_VOLUME stucture.

The 4th member of DEV_BROADCAST_VOLUME stucture is dbcv_unitmask, a DWord whose bits have to be evaluated to ascertain the CD/DVD drive letter.

dbcv_unitmask should contain integers for respective drive letters as follows:

Code:
A = 00000000000000000000000000000001 = 1
B = 00000000000000000000000000000010 = 2
C = 00000000000000000000000000000100 = 4
D = 00000000000000000000000000001000 = 8
E = 00000000000000000000000000010000 = 16
F = 00000000000000000000000000100000 = 32
G = 00000000000000000000000001000000 = 64
H = 00000000000000000000000010000000 = 128
I = 00000000000000000000000100000000 = 256
J = 00000000000000000000001000000000 = 512
K = 00000000000000000000010000000000 = 1024
L = 00000000000000000000100000000000 = 2048
M = 00000000000000000001000000000000 = 4096
N = 00000000000000000010000000000000 = 8192
O = 00000000000000000100000000000000 = 16384
P = 00000000000000001000000000000000 = 32768
Q = 00000000000000010000000000000000 = 65536
R = 00000000000000100000000000000000 = 131072
S = 00000000000001000000000000000000 = 262144
T = 00000000000010000000000000000000 = 524288
U = 00000000000100000000000000000000 = 1048576
V = 00000000001000000000000000000000 = 2097152
W = 00000000010000000000000000000000 = 4194304
X = 00000000100000000000000000000000 = 8388608
Y = 00000001000000000000000000000000 = 16777216
Z = 00000010000000000000000000000000 = 33554432
[ = 00000100000000000000000000000000 = 67108864
\ = 00001000000000000000000000000000 = 134217728
] = 00010000000000000000000000000000 = 268435456
^ = 00100000000000000000000000000000 = 536870912
_ = 01000000000000000000000000000000 = 1073741824
` = 10000000000000000000000000000000 = 2147483648


My DVD-Writer shows as H: in explorer so I expect dbcv_unitmask to be 128, whereas it is 2147483776 for me in Windows 2000 SP4. Inspecting the bits, I find the MSB is ON making it a signed integer!

My previous code runs flawlessly in Windows 98 SE and Windows XP Pro ( SP 2) but troubles me with the said effect in Windows 2000

To workaround this effect, I have the choice of

1) Setting the first 6 bits of dbcv_unitmask to be zero
2) Scan bits of dbcv_unitmask from LSB to MSB, find the first bit ON and ignore the rest.

I opted for the 2nd and here is the code: ( requires 1.0.47+ )

Ascertaining drive letter on CD/DVD insert notification:

Code:
OnMessage( 0x219, "WM_DEVICECHANGE" )
Return

WM_DEVICECHANGE( wParam, lParam ) { ; http://msdn2.microsoft.com/en-us/library/aa363480.aspx
 Global Drv
 Static DBT_DEVICEARRIVAL := 0x8000 ; http://msdn2.microsoft.com/en-us/library/aa363205.aspx
 Static DBT_DEVTYP_VOLUME := 0x2    ; http://msdn2.microsoft.com/en-us/library/aa363246.aspx

 /*
    When wParam is DBT_DEVICEARRIVAL lParam will be a pointer to a structure identifying the
    device inserted. The structure consists of an event-independent header,followed by event
    -dependent members that describe the device. To use this structure,  treat the structure
    as a DEV_BROADCAST_HDR structure, then check its dbch_devicetype member to determine the
    device type.
 */

 dbch_devicetype := NumGet(lParam+4) ; dbch_devicetype is member 2 of DEV_BROADCAST_HDR

 If ( wParam = DBT_DEVICEARRIVAL AND dbch_devicetype = DBT_DEVTYP_VOLUME )
 {
 
 ; Confirmed lParam is a pointer to DEV_BROADCAST_VOLUME and should retrieve Member 4
 ; which is dbcv_unitmask

   dbcv_unitmask := NumGet(lParam+12 )
 
 ; The logical unit mask identifying one or more logical units. Each bit in the mask corres
 ; ponds to one logical drive.Bit 0 represents drive A, Bit 1 represents drive B, and so on
 
   Loop 32                                           ; Scan Bits from LSB to MSB
     If ( ( dbcv_unitmask >> (A_Index-1) & 1) = 1 )  ; If Bit is "ON"
      {
        Drv := Chr(64+A_Index)                       ; Set Drive letter
        Break
      }
   SetTimer, DriveData, -1           
 }
Return TRUE
}

DriveData:
 DriveGet, Type  , Type  , %Drv%:
 DriveGet, Label , Label , %Drv%:
 DriveGet, Serial, Serial, %Drv%:
 MsgBox, 262144, Media Insert Notification [ Drive %Drv%: ]
       , Type:`t%Type%`nLabel:`t%Label%`nSerial:`t%Serial%
Return


The above now works in all the 3 OS' flawlessly but still I am a bit uncomfortable Smile

Am I missing something ? Rolling Eyes


Last edited by SKAN on Fri Nov 09, 2007 12:51 am; edited 1 time in total
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4015
Location: Pittsburgh

PostPosted: Tue Jun 19, 2007 8:32 pm    Post subject: Reply with quote

Finding the least- and most significant set (and clear) bit is such a common task, that there are runtime library functions for it, at least in WinNT, 2K and later:
Code:
MsgBox % DllCall("ntdll\RtlFindLeastSignificantBit",Int64,100) ; LS bit is at pos 2
MsgBox % DllCall("ntdll\RtlFindMostSignificantBit", Int64,100) ; MS bit is at pos 6
Back to top
View user's profile Send private message
SKAN



Joined: 26 Dec 2005
Posts: 5882

PostPosted: Sat Sep 01, 2007 2:16 am    Post subject: Reply with quote

Thank you Sir! I am writing XP specific code and this info was useful! Smile
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group