AutoHotkey Community

It is currently May 25th, 2012, 6:29 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 14 posts ] 
Author Message
PostPosted: June 19th, 2007, 11:50 am 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8775
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! :roll:


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 19th, 2007, 12:29 pm 
Offline

Joined: July 6th, 2004, 10:07 am
Posts: 171
Location: Manchester, England.
@ 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


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 19th, 2007, 2:14 pm 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8775
@Dippy46

Thank you very much Sir! :D

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 ?

:roll:


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 19th, 2007, 3:19 pm 
Should be something like:
x &= 0x03FFFFFF


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: June 19th, 2007, 4:08 pm 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8775
It works! Many thanks Helpy! :D

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, :)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 19th, 2007, 4:20 pm 
Offline

Joined: April 19th, 2006, 1:02 pm
Posts: 386
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 19th, 2007, 4:29 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
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 June 19th, 2007, 4:36 pm, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 19th, 2007, 4:36 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 19th, 2007, 4:38 pm 
Offline
User avatar

Joined: August 11th, 2004, 1:47 am
Posts: 5346
Location: UK
Did everyone forget ToBin() lol. :/

_________________
GitHubScriptsIronAHK Contact by email not private message.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 19th, 2007, 4:46 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
...and all the other, better versions posted before that?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 19th, 2007, 5:12 pm 
Offline
User avatar

Joined: August 11th, 2004, 1:47 am
Posts: 5346
Location: UK
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.

_________________
GitHubScriptsIronAHK Contact by email not private message.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 19th, 2007, 6:03 pm 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8775
This help topic has reference to my code posted here : http://www.autohotkey.com/forum/viewtop ... 8203#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 :)

Am I missing something ? :roll:


Last edited by SKAN on November 9th, 2007, 12:51 am, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 19th, 2007, 8:32 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
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


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 1st, 2007, 2:16 am 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8775
Thank you Sir! I am writing XP specific code and this info was useful! :)


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 14 posts ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: Bing [Bot], BrandonHotkey, cmikaiti, dra, Maestr0, Ohnitiel, Pulover, rbrtryn, tomL, vsub and 7 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group