czardas Posted October 25, 2014 Share Posted October 25, 2014 (edited) Can anyone get this function to go faster? Hex digits go in, and all the bits are shifted 1 step to the right - as fast as possible. The input string can be any length. The final input digit will always be even => 0, 2, 4, 6, 8, A, C or E. ; $iTimer = TimerInit() For $i = 1 To 10000 BitShiftRight('FF777E3A9970F0B55FF99999999990F0F0065EA8546D8952') ; Final digit must be even Next ConsoleWrite(TimerDiff($iTimer) & @LF) ; Hex digits only [0-9A-F] Func BitShiftRight($dHex) ; Shift bits 1 step to the right. Local $aHexPart = StringRegExp($dHex, ".{1,7}", 3) Local $dShiftedHex = StringTrimLeft(Hex(BitShift(Dec($aHexPart[0]), 1), StringLen($aHexPart[0]) +1), 1), $iBound = UBound($aHexPart) If $iBound > 1 Then ; One time conditional. For $i = 1 To $iBound -2 ; Loop may or may not run. $dShiftedHex &= StringTrimLeft(Hex(BitShift(Dec(StringRight($aHexPart[$i -1], 1) & $aHexPart[$i]), 1)), 1) Next $dShiftedHex &= StringTrimLeft(Hex(BitShift(Dec(StringRight($aHexPart[$iBound -2], 1) & $aHexPart[$iBound -1]), 1), StringLen($aHexPart[$iBound -1]) +1), 1) EndIf Return $dShiftedHex EndFunc ; I was hoping someone might be able to improve performance with a different method. Edited October 29, 2014 by czardas operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
UEZ Posted October 25, 2014 Share Posted October 25, 2014 (edited) This code is although shorter but not faster: Func Half($sHex) Local $aHexPart = StringRegExp($sHex, ".{1,7}", 3), $i, $j, $sResult For $i = 0 To UBound($aHexPart) - 1 $sResult &= StringRegExpReplace(Hex(Int(Dec($aHexPart[$i]) / 2)), "0*([\d.]+)", "$1") Next Return $sResult EndFunc StringRegExpReplace takes too much time. expandcollapse popup#include <Array.au3> $sHex = '7FBBBF1D4CB8785A' ; -> 3FDDDF8EA65C3C2D $iRounds = 100000 $iTimer = TimerInit() For $i = 1 To $iRounds BitShiftRight($sHex) ; Final digit must be even Next ConsoleWrite(TimerDiff($iTimer) & @CRLF) ConsoleWrite(BitShiftRight($sHex) & @CRLF & @CRLF) $iTimer = TimerInit() For $i = 1 To $iRounds Half($sHex) ; Final digit must be even Next ConsoleWrite(TimerDiff($iTimer) & @CRLF) ConsoleWrite(Half($sHex) & @CRLF) ; Hex digits only [0-9A-F] Func BitShiftRight($dHex) ; Shift bits 1 step to the right. Local $aHexPart = StringRegExp($dHex, ".{1,7}", 3) Local $dShiftedHex = StringTrimLeft(Hex(BitShift(Dec('0' & $aHexPart[0]), 1), StringLen($aHexPart[0]) + 1), 1), $iBound = UBound($aHexPart) If $iBound > 1 Then ; One time conditional. For $i = 1 To $iBound - 2 ; Loop may or may not run. $dShiftedHex &= StringTrimLeft(Hex(BitShift(Dec(StringRight($aHexPart[$i - 1], 1) & $aHexPart[$i]), 1)), 1) Next $dShiftedHex &= StringTrimLeft(Hex(BitShift(Dec(StringRight($aHexPart[$iBound - 2], 1) & $aHexPart[$iBound - 1]), 1), StringLen($aHexPart[$iBound - 1]) + 1), 1) EndIf Return $dShiftedHex EndFunc ;==>BitShiftRight Func Half($sHex) Local $aHexPart = StringRegExp($sHex, ".{1,7}", 3), $i, $j, $sResult For $i = 0 To UBound($aHexPart) - 1 $sResult &= StringRegExpReplace(Hex(Int(Dec($aHexPart[$i]) / 2)), "0*([\d.]+)", "$1") ;remove leading zeros from the result Next Return $sResult EndFunc Br, UEZ Edited October 25, 2014 by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
czardas Posted October 25, 2014 Author Share Posted October 25, 2014 (edited) Thanks UEZ. BTW you forgot to carry any odd bits forward on subsequent loops after each division (7FBBBF1D4CB8785A ==> 3FDDDF8EA65C3C2D but your function gives 3FDDDF86A65C3C2D). That's partly why my code looks quite complicated. I was thinking a single regexp might be possible (perhaps for longer strings) or some dll call I don't know about. Using division might still be a good option. Edited October 25, 2014 by czardas operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
czardas Posted October 25, 2014 Author Share Posted October 25, 2014 (edited) I combined the two approaches. This gives a slight edge in performance so it helps a little. Thanks. ; Func Half($sHex) Local $aHexPart = StringRegExp($sHex, ".{1,7}", 3) Local $sResult = Hex(Int(Dec($aHexPart[0]) / 2), StringLen($aHexPart[0])), $iBound = UBound($aHexPart) -1 If $iBound > 0 Then ; One time conditional. For $i = 1 To $iBound - 1 ; Loop may or may not run. $sResult &= Hex(Int(Dec($aHexPart[$i]) / 2 + 0x8000000 * Mod(Dec($aHexPart[$i -1]), 2)), 7) Next $sResult &= Hex(Int(Dec($aHexPart[$iBound]) / 2 + Dec(StringLeft('8000000', StringLen($aHexPart[$iBound]))) * Mod(Dec($aHexPart[$iBound -1]), 2)), StringLen($aHexPart[$iBound])) EndIf Return $sResult EndFunc ; Anyone got any more ideas? Edited October 26, 2014 by czardas operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
UEZ Posted October 25, 2014 Share Posted October 25, 2014 Indeed, I forgot to check out the carry. I can confirm that combined Half function is now faster. Might be a good idea to look at BigNum UDF... Btw, what do you want to achieve with so many calls? I mean you really need so many calls or is it just a optimization challenge? Br, UEZ czardas 1 Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
czardas Posted October 25, 2014 Author Share Posted October 25, 2014 (edited) The reason is I'm trying to develop a method of obfuscation. I noticed that the frequency of hex numbers [0-9] in the ascii codes (particularly for numbers and letters) is wildly out of proportion with the frequency of letters [A-F]. Shifting by one bit in binary changes the balance in favour of more letters. I came up with the plan to make the hex case sensitive but that requires the letters [A-F] to actually occur. The hex for 'hello world' has a frequency ratio of 17 numbers to 5 letters. Random hex has a ratio of 5 : 3. 0x68656C6C6F20776F726C64 Shifting the bits to the left generally produces a lot more letters: 0xD0CAD8D8DE40EEDEE4D8C8 Incorporating case sensitive hex will tip the balance in some dependant way, but it's hardly worth pursuing if it introduces excessive latency. Edited October 25, 2014 by czardas operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
czardas Posted October 26, 2014 Author Share Posted October 26, 2014 (edited) I should have tried this earlier (ahem!): due to improvements made by trancexx some time ago, the hex can be parsed 12 characters at a time. I also found a bug in the earlier code. It's pretty obvious now. ; Func Half($sHex) Local $aHexPart = StringRegExp($sHex, ".{1,12}", 3) Local $sBatch = Dec($aHexPart[0], 2) Local $iBound = UBound($aHexPart) -1, $sResult = Hex(Int($sBatch / 2), StringLen($aHexPart[0])), $sCarry, $iLeftOver If $iBound > 0 Then ; One time conditional. $sCarry = $sBatch For $i = 1 To $iBound - 1 ; Loop may or may not run. $sBatch = Dec($aHexPart[$i], 2) $sResult &= Hex(Int($sBatch / 2 + 140737488355328 * Mod($sCarry, 2)), 12) $sCarry = $sBatch Next $iLeftOver = StringLen($aHexPart[$iBound]) $sResult &= Hex(Int(Dec($aHexPart[$iBound], 2) / 2 + Dec(StringLeft('8000000000000', $iLeftOver), 2) * Mod($sCarry, 2)), $iLeftOver) EndIf Return $sResult EndFunc ; The reason for the 12 hexadecimal character limit is that Dec('8000000000000') produces a 16 digit integer and decimals need to remain within 15 digits for the method to work. Edited October 26, 2014 by czardas operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
jchd Posted October 26, 2014 Share Posted October 26, 2014 How does code >using this compare to already posted solutions? Granted it isn't full native yet it can be made self-contained by making the few opcodes inline and invoking it, à la Ward or others. This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe hereRegExp tutorial: enough to get startedPCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta. SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt) Link to comment Share on other sites More sharing options...
czardas Posted October 26, 2014 Author Share Posted October 26, 2014 Thanks a lot jchd. It looks like a nice library you created. I'll let you know how I get on tomorrow after I get time to play around with it. operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
Gianni Posted October 29, 2014 Share Posted October 29, 2014 (edited) You could speedup a bit using StringMid() instead of StringRegExp() to split the hex input string expandcollapse popup$sHex = '123456789ABCDEF7FBBBF1D4CB8785A123456789ABCDEF7FBBBF1D4CB8785A123456789ABCDEF7FBBBF1D4CB8785A123456789ABCDEF7FBBBF1D4CB8785A' $iTimer = TimerInit() For $i = 1 To 10000 Half($sHex) Next ConsoleWrite(TimerDiff($iTimer) & @TAB & "Half() by czardas. (this uses StringRegExp to split $sHex)" & @LF) ConsoleWrite(Half($sHex) & @CRLF & @CRLF) $iTimer = TimerInit() For $i = 1 To 10000 Half_mod($sHex) Next ConsoleWrite(TimerDiff($iTimer) & @TAB & "Half_mod() modified to use StringMid* instead of StringRegExp to split $sHex" & @LF) ConsoleWrite(Half_mod($sHex) & @CRLF & @CRLF) Func Half($sHex) Local $aHexPart = StringRegExp($sHex, ".{1,12}", 3) Local $sBatch = Dec($aHexPart[0], 2) Local $iBound = UBound($aHexPart) - 1, $sResult = Hex(Int($sBatch / 2), StringLen($aHexPart[0])), $sCarry, $iLeftOver If $iBound > 0 Then ; One time conditional. $sCarry = $sBatch For $i = 1 To $iBound - 1 ; Loop may or may not run. $sBatch = Dec($aHexPart[$i], 2) $sResult &= Hex(Int($sBatch / 2 + 140737488355328 * Mod($sCarry, 2)), 12) $sCarry = $sBatch Next $iLeftOver = StringLen($aHexPart[$iBound]) $sResult &= Hex(Int(Dec($aHexPart[$iBound], 2) / 2 + Dec(StringLeft('8000000000000', $iLeftOver), 2) * Mod($sCarry, 2)), $iLeftOver) EndIf Return $sResult EndFunc ;==>Half Func Half_mod($sHex) ; it makes no use of StringRegExp Local $sBatch = Dec(StringMid($sHex, 1, 12), 2), $iLen = StringLen($sHex), $iLeftOver = Mod($iLen, 12), $sCarry Local $iBound = Int($iLen / 12), $sResult = Hex(Int($sBatch / 2), 12) ; ($iLeftOver * Not ($iBound)) + (12 * Not (Not ($iBound)))) If $iBound Then ; One time conditional. $sCarry = $sBatch For $i = 13 To $iLen - $iLeftOver Step 12 ; Loop may or may not run. $sBatch = Dec(StringMid($sHex, $i, 12), 2) $sResult &= Hex(Int($sBatch / 2 + 140737488355328 * Mod($sCarry, 2)), 12) $sCarry = $sBatch Next $sResult &= Hex(Int(Dec(StringRight($sHex, $iLeftOver), 2) / 2 + Dec(StringLeft('8000000000000', $iLeftOver), 2) * Mod($sCarry, 2)), $iLeftOver) EndIf Return $sResult EndFunc ;==>Half_mod edit: p.s. (this is just a marginal modification, not an improvement on the core of your function that is very fast as is. I attempted a different approach also, but achieved a bit slower speed of your, so I don't post here. I also tried to use jchd's dll from post #8 by passing 32bit hex strings to the functions, but the overall performance is worst, I think because the time spent to setup the call to the dll vanify the 32bit approach) Edited October 29, 2014 by Chimp Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
czardas Posted October 29, 2014 Author Share Posted October 29, 2014 (edited) I'm afraid my first attempt to integrate jchd's functions failed, but I haven't tried the logical BitShift option yet. Although not a problem, there is no 64-bit multiply function which is needed in both cases. Actually I know where I went wrong. I'll try again. Chimp: thanks for your suggestions. I think jchd's functions ought to give some improvement if implemeted correctly (using 14 or 15 character segments - at least one character must be held in reserve for the carry operation). I thought RegExp was meant to be fast. Anyway the following RegExp solution might look pretty, but it's the slowest method that I tried. The use of Execute() imposes a limit to the length of the input. The time taken to execute the expression also needs to be taken into consideration. ; Func Half_Method_2($sString) Local $0=0, $1=1, $2=2, $3=3, $4=4, $5=5, $6=6, $7=7, $8=8, $9=9, $A=10, $B=11, $C=12, $D=13, $E=14, $F=15 Local $aHx[32] = ['0','0','1','1','2','2','3','3','4','4','5','5','6','6','7','7','8','8','9','9','A','A','B','B','C','C','D','D','E','E','F','F'] $sString = StringRegExpReplace($sString, '(?i)[13579BDF]','\0,') $sString = StringTrimRight(StringRegExpReplace($sString,'(?i)(,)*([0-9A-F])', '$aHx[$\2+16*("\1"=",")]&'), 1) Return Execute($sString) EndFunc ; UPDATE Here's a working version using jchd's library. It has introduced quite a large regression. ; Func Half_64a($sHex) Local $aHexPart = StringRegExp($sHex, ".{1,14}", 3) Local $sBatch = Dec($aHexPart[0], 2) Local $iBound = UBound($aHexPart) -1, $sResult = Hex(Int(_Div($sBatch, 2)), StringLen($aHexPart[0])), $sCarry, $iLeftOver If $iBound > 0 Then ; One time conditional. $sCarry = $sBatch For $i = 1 To $iBound - 1 ; Loop may or may not run. $sBatch = Dec($aHexPart[$i], 2) $sResult &= Hex(Int(_BitOr(_Div($sBatch, 2), _MultByOne(Dec('800000000000000', 2), _Mod($sCarry, 2)))), 14) $sCarry = $sBatch Next $iLeftOver = StringLen($aHexPart[$iBound]) $sResult &= Hex(Int(_BitOr(_Div(Dec($aHexPart[$iBound], 2), 2) ,_MultByOne(Dec(StringLeft('800000000000000', $iLeftOver), 2), _Mod($sCarry, 2)))), $iLeftOver) EndIf Return $sResult EndFunc Func _MultByOne($vHex, $iOne = 1) If $iOne = 0 Then $vHex = 0 Return $vHex EndFunc Edited October 29, 2014 by czardas operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
Gianni Posted October 29, 2014 Share Posted October 29, 2014 .... I think jchd's functions ought to give some improvement if implemeted correctly (using 14 or 15 character segments - at least one character must be held in reserve for the carry operation). ..... in my attempt I elaborate all 16 (or 32) digits at a time. No need to reserve character for the carry, I just reserve 1 bit. Unfortunately, this approach results slower. p.s. it seems that your 64bit function gives wrong results as from the following test: expandcollapse popup;; Use DllOpen ... DllClose and pass the handle for heavy usage Local $AddOnDllPath = "addons.dll" ; see post #8 to get this DLL ; Local $nNrOfLoops = 1000 ; how many calls to the functions $input = 'BC4DEF123456789ABC4ABC4DEF123456789ABC4DEF123456789DEF123456789ABC' ; ---------------------------------------------------------------------- $iTimer = TimerInit() For $i = 1 To $nNrOfLoops Half($input) ; Final digit must be even Next ConsoleWrite(TimerDiff($iTimer) & @TAB & "Half by czardas. (this uses StringRegExp)" & @LF) ConsoleWrite(Half($input) & @CRLF & @CRLF) ; ---------------------------------------------------------------------- $iTimer = TimerInit() For $i = 1 To $nNrOfLoops Half2($input) ; Final digit must be even Next ConsoleWrite(TimerDiff($iTimer) & @TAB & "Half2 modified to use StringMid* instead of StringRegExp" & @LF) ConsoleWrite(Half2($input) & @CRLF & @CRLF) ; ---------------------------------------------------------------------- $iTimer = TimerInit() For $i = 1 To $nNrOfLoops HexShift_32bit($input) ; Final digit must be even Next ConsoleWrite(TimerDiff($iTimer) & @TAB & "Chimp's 32 bit attempt" & @LF) ConsoleWrite(HexShift_32bit($input) & @CRLF & @CRLF) ; ---------------------------------------------------------------------- $iTimer = TimerInit() For $i = 1 To $nNrOfLoops HexShift_64bit($input) ; Final digit must be even Next ConsoleWrite(TimerDiff($iTimer) & @TAB & "Chimp's 64 bit attempt" & @LF) ConsoleWrite(HexShift_64bit($input) & @CRLF & @CRLF) ; ---------------------------------------------------------------------- $iTimer = TimerInit() For $i = 1 To $nNrOfLoops Half_64a($input) ; Final digit must be even Next ConsoleWrite(TimerDiff($iTimer) & @TAB & "czardas 64 bit attempt" & @LF) ConsoleWrite(Half_64a($input) & @CRLF & @CRLF) ; ------------------------------------------------------------------------------------------------- Func HexShift_32bit($dHex0) ; uses native Bit* functions 32 bit Local $dShiftedHex = "", $Carry, $nDecPart, $Mod = Mod(StringLen($dHex0), 8), $dHex = StringMid("0000000", Mod(StringLen($dHex0), 8), 7) & $dHex0, $strLen = StringLen($dHex) For $i = 1 To $strLen Step 8 ; loop al digits 8 at time $nDecPart = Dec(StringMid($dHex, $i, 8)) ; peek next group of 8 digits $dShiftedHex &= Hex(BitOR(BitRotate(BitAND($nDecPart, -2), -1, 'D'), $Carry)) ; | | | ; | | BitAND($nDecPart, -2) ; turn off bit 1 ; | BitRotate(..) ; shift right & move bit 1 to bit 32 (this clear bit 32) ; BitOr( nn, $Carry) ; Turn bit 32 on or off according to $Carry (first shot is 0) ; $Carry = BitRotate(BitAND($nDecPart, 1), -1, 'D') ; save the Carry to be used on next group of 8 digits ; | | ; | BitAND($nDecPart, 1) ; turn off all bits but bit 1 (bit 1 remains unchanged) ; BitRotate(.., -1, 'D') ; move bit 1 to bit 32 Next If $Mod Then Return StringTrimLeft($dShiftedHex, 8 - $Mod) ; remove leading zeros (if any) Return $dShiftedHex EndFunc ;==>HexShift_32bit ; ------------------------------------------------------------------------------------------------- Func HexShift_64bit($dHex0) ; use 64 bit _Bit* functions from jchd DLL Local $dShiftedHex = "", $Carry = 0, $nDecPart = "", $Mod = Mod(StringLen($dHex0), 16), $dHex = StringMid("000000000000000", $Mod, 15) & $dHex0 Local $strLen = StringLen($dHex), $ret1, $ret2, $ret3, $ret4, $ret5 For $i = 1 To $strLen Step 16 $nDecPart = Dec(StringMid($dHex, $i, 16)) $ret1 = DllCall($AddOnDllPath, "uint64:cdecl", "BitAnd", "uint64", $nDecPart, "uint64", -2) ; turn off bit 1 $ret2 = DllCall($AddOnDllPath, "uint64:cdecl", "BitRotate", "uint64", $ret1[0], "int", 1) ; rotate right (bit 1 goes to bit 32) $ret3 = DllCall($AddOnDllPath, "uint64:cdecl", "BitOr", "uint64", $ret2[0], "uint64", $Carry) ; set bit 32 according to carry $dShiftedHex &= Hex($ret3[0]) $ret4 = DllCall($AddOnDllPath, "uint64:cdecl", "BitAnd", "uint64", $nDecPart, "uint64", 1) ; turn off all bits but bit 1 (bit 1 remains unchanged) $ret5 = DllCall($AddOnDllPath, "uint64:cdecl", "BitRotate", "uint64", $ret4[0], "int", 1) ; bitRotate move bit 1 to bit 32, it will be the carry $Carry = $ret5[0] Next If $Mod Then Return StringTrimLeft($dShiftedHex, 16 - $Mod) Return $dShiftedHex EndFunc ;==>HexShift_64bit ; ------------------------------------------------------------------------------------------------- Func Half($sHex) Local $aHexPart = StringRegExp($sHex, ".{1,12}", 3) ; _ArrayDisplay($aHexPart) Local $sBatch = Dec($aHexPart[0], 2) Local $iBound = UBound($aHexPart) - 1, $sResult = Hex(Int($sBatch / 2), StringLen($aHexPart[0])), $sCarry, $iLeftOver If $iBound > 0 Then ; One time conditional. $sCarry = $sBatch For $i = 1 To $iBound - 1 ; Loop may or may not run. $sBatch = Dec($aHexPart[$i], 2) $sResult &= Hex(Int($sBatch / 2 + 140737488355328 * Mod($sCarry, 2)), 12) $sCarry = $sBatch Next $iLeftOver = StringLen($aHexPart[$iBound]) $sResult &= Hex(Int(Dec($aHexPart[$iBound], 2) / 2 + Dec(StringLeft('8000000000000', $iLeftOver), 2) * Mod($sCarry, 2)), $iLeftOver) EndIf Return $sResult EndFunc ;==>Half ; ------------------------------------------------------------------------------------------------- Func Half2($sHex) ; it makes NO use of StringRegExp Local $sBatch = Dec(StringMid($sHex, 1, 12), 2), $iLen = StringLen($sHex), $iLeftOver = Mod($iLen, 12), $sCarry Local $iBound = Int($iLen / 12), $sResult = Hex(Int($sBatch / 2), 12) ; ($iLeftOver * Not ($iBound)) + (12 * Not (Not ($iBound)))) If $iBound > 0 Then ; One time conditional. $sCarry = $sBatch For $i = 13 To $iLen - $iLeftOver Step 12 ; Loop may or may not run. $sBatch = Dec(StringMid($sHex, $i, 12), 2) $sResult &= Hex(Int($sBatch / 2 + 140737488355328 * Mod($sCarry, 2)), 12) $sCarry = $sBatch Next ; $iLeftOver = Mod(StringLen($sHex), 12) $sResult &= Hex(Int(Dec(StringRight($sHex, $iLeftOver), 2) / 2 + Dec(StringLeft('8000000000000', $iLeftOver), 2) * Mod($sCarry, 2)), $iLeftOver) EndIf Return $sResult EndFunc ;==>Half2 ; ------------------------------------------------------------------------------------------------- Func Half_64a($sHex) Local $aHexPart = StringRegExp($sHex, ".{1,14}", 3) Local $sBatch = Dec($aHexPart[0], 2) Local $iBound = UBound($aHexPart) -1, $sResult = Hex(Int(_Div($sBatch, 2)), StringLen($aHexPart[0])), $sCarry, $iLeftOver If $iBound > 0 Then ; One time conditional. $sCarry = $sBatch For $i = 1 To $iBound - 1 ; Loop may or may not run. $sBatch = Dec($aHexPart[$i], 2) $sResult &= Hex(Int(_BitOr(_Div($sBatch, 2), _MultByOne(Dec('800000000000000', 2), _Mod($sCarry, 2)))), 14) $sCarry = $sBatch Next $iLeftOver = StringLen($aHexPart[$iBound]) $sResult &= Hex(Int(_BitOr(_Div(Dec($aHexPart[$iBound], 2), 2) ,_MultByOne(Dec(StringLeft('800000000000000', $iLeftOver), 2), _Mod($sCarry, 2)))), $iLeftOver) EndIf Return $sResult EndFunc Func _MultByOne($vHex, $iOne = 1) If $iOne = 0 Then $vHex = 0 Return $vHex EndFunc ; ------------------------ ; following stuff by jchd ; ----------------------- ;; Integer divide for 64-bit signed integers Func _Div($iNumerator, $iDenominator) If IsInt($iNumerator) And IsInt($iDenominator) Then If $iDenominator = 0 Then Return(1 / 0) ;; make it behaves like the built-in / operator Local $ret = DllCall($AddOnDllPath, "int64:cdecl", "Div", "int64", $iNumerator, "int64", $iDenominator) If @error Then Return(SetError(@error, 0, '')) Return($ret[0]) Else Return('') EndIf EndFunc ;; Modulus for 64-bit signed integers Func _Mod($iNumber, $iModulus) If IsInt($iNumber) And IsInt($iModulus) Then If $iModulus = 0 Then Return(1 / 0) ;; make it behaves like the built-in Mod() function Local $ret = DllCall($AddOnDllPath, "int64:cdecl", "Mod", "int64", $iNumber, "int64", $iModulus) If @error Then Return(SetError(@error, 0, '')) Return($ret[0]) Else Return('') EndIf EndFunc ;; Bitwise OR on 64-bit integers Func _BitOr($uiA, $uiB) If IsInt($uiA) And IsInt($uiB) Then Local $ret = DllCall($AddOnDllPath, "uint64:cdecl", "BitOr", "uint64", $uiA, "uint64", $uiB) Return($ret[0]) Else Return('') EndIf EndFunc Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
czardas Posted October 30, 2014 Author Share Posted October 30, 2014 (edited) No need to reserve character for the carry, I just reserve 1 bit. The reason I did that was because I am using addition with the carry. That won't work with the sign bit included, so a whole nibble must be reserved for the original method to work correctly. With BitOR this is indeed unecessary. it seems that your 64bit function gives wrong results as from the following test: I didn't do extensive testing. I'll check this out later. Thanks again for testing. Edited October 30, 2014 by czardas operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now