• Earn real money by being active: Hello Guest, earn real money by simply being active on the forum — post quality content, get reactions, and help the community. Once you reach the minimum credit amount, you’ll be able to withdraw your balance directly. Learn how it works.

AutoIT Operator 64

Status
Not open for further replies.

DDoSer

The Real DDoSer
User
Joined
Oct 9, 2013
Messages
352
Reputation
0
Reaction score
4,578
Points
243
Credits
0
‎11 Years of Service‎
51%
[HIDE-THANKS]UDF:

Code:
>; #INDEX# ======================================================================================================================
; Title .........: operator64
; AutoIt Version : 3.3.14.0
; Language ......: English
; Description ...: Helper functions for basic maths operations to be used with Int-32 and Int-64 numeric data types.
; Notes .........: Tests for integer overflow and attempts to correct for small inaccuracies affecting certain calculations.
;                  Return values are cast as Int-32 or Int-64 when possible, otherwise the result will be returned as a double.
;                  If it is not possible to return an Int-64 data type, the @Extended flag is always set to non zero.
;                  Extended return values in this library simply indicate that 100% accuracy cannot be guaranteed.
;                  When an error occurs, the @Extended flag is always set to non zero and a value returned regardless.
; Author(s) .....: czardas
; ==============================================================================================================================


; #CURRENT# ====================================================================================================================
; _Abs64
; _Add64
; _Divide64
; _Multiply64
; _Power64
; _Subtract64
; ==============================================================================================================================


; #INTERNAL_USE_ONLY#===========================================================================================================
; __DoubleTo64
; __Integer64
; __OverflowDetect
; __Product64
; __WholeNumberDivision
; ==============================================================================================================================


; #FUNCTION# ===================================================================================================================
; Name...........: _Abs64
; Description ...: Returns the absolute value of an integer.
; Syntax.........: _Abs64($iInteger)
; Parameters.....; $iInteger - The integer to operate on.
; Return values .: Returns an Int-32, or Int-64, value.
;                  Failure returns the executed expression and sets @error as follows:
;                  |@error = 1 The input parameter is niether Int-32 nor Int-64.
;                  |@error = 2 This absolute value (2^63) is out of range for Int-64.
; Author.........: czardas
; ==============================================================================================================================

Func _Abs64($iInteger)
   $iInteger = __Integer64($iInteger)
   If @error Then Return SetError(1, 1, Abs($iInteger))
   If $iInteger = 0x8000000000000000 Then Return SetError(2, 1, Abs($iInteger))
   Return $iInteger < 0 ? $iInteger *-1 : $iInteger
EndFunc ;==> _Abs64


; #FUNCTION# ===================================================================================================================
; Name...........: _Add64
; Description ...: Adds two integers together.
; Syntax.........: _Add64($iOperand_1, $iOperand_2)
; Parameters.....; $iOperand_1 - The first operand.
;                  $iOperand_2 - The second operand.
; Return values .: Returns an Int-32, or Int-64, value.
;                  Failure returns the executed expression and sets @error as follows:
;                  |@error = 1 The first parameter is not an integer.
;                  |@error = 2 The second parameter is not an integer.
; Author.........: czardas
; ==============================================================================================================================

Func _Add64($iOperand_1, $iOperand_2)
   $iOperand_1 = __Integer64($iOperand_1)
   If @error Then Return SetError(1, 1, __DoubleTo64($iOperand_1 + $iOperand_2)) ; may still return an integer
   $iOperand_2 = __Integer64($iOperand_2)
   If @error Then Return SetError(2, 1, __DoubleTo64($iOperand_1 + $iOperand_2)) ; ditto

   Local $bOverflow, $nResult
   $bOverflow = __OverflowDetect('+', $iOperand_1, $iOperand_2, $nResult)
   Return SetExtended($bOverflow, $nResult)
EndFunc ;==> _Add64


; #FUNCTION# ===================================================================================================================
; Name...........: _Divide64
; Description ...: Divides two integers.
; Syntax.........: _Divide64($iOperand_1, $iOperand_2)
; Parameters.....; $iOperand_1 - The first operand.
;                  $iOperand_2 - The second operand.
;                  Failure returns the executed expression and sets @error as follows:
;                  |@error = 1 The first parameter is not an integer.
;                  |@error = 2 The second parameter is not an integer.
;                  |@error = 3 The divisor cannot be zero.
;                  |@error = 4 Input range exceeded.
;                  |@error = 5 Parameters are not divisible.
; Author.........: czardas
; ==============================================================================================================================

Func _Divide64($iOperand_1, $iOperand_2)
   $iOperand_1 = __Integer64($iOperand_1)
   If @error Then Return SetError(1, 1, __DoubleTo64($iOperand_1 / $iOperand_2)) ; may still return an integer
   $iOperand_2 = __Integer64($iOperand_2)
   If @error Then Return SetError(2, 1, __DoubleTo64($iOperand_1 / $iOperand_2)) ; as above

   If $iOperand_1 = 0x8000000000000000 Then ; this is not dealt with by the internal function
       If $iOperand_2 = 0x8000000000000000 Then Return 1 ; $iOperand_1 is divided by itself

       ; divide both values by 2 to remain within the specified range of the function __WholeNumberDivision()
       $iOperand_1 = 0xC000000000000000 ; -4611686018427387904
       $iOperand_2 = __WholeNumberDivision($iOperand_2, 2)
       If @error Then Return SetExtended(1, $iOperand_1 / $iOperand_2)
   EndIf

   Local $nResult = __WholeNumberDivision($iOperand_1, $iOperand_2)
   Return SetError(@error, @error ? 1 : 0, $nResult)
EndFunc ;==> _Divide64


; #FUNCTION# ===================================================================================================================
; Name...........: _Multiply64
; Description ...: Multiplies two integers together.
; Syntax.........: _Multiply64($iOperand_1, $iOperand_2)
; Parameters.....; $iOperand_1 - The first operand.
;                  $iOperand_2 - The second operand.
; Return values .: Returns an Int-32, or Int-64, value.
;                  Failure returns the executed expression and sets @error as follows:
;                  |@error = 1 The first parameter is not an integer.
;                  |@error = 2 The second parameter is not an integer.
; Author.........: czardas
; ==============================================================================================================================

Func _Multiply64($iOperand_1, $iOperand_2)
   $iOperand_1 = __Integer64($iOperand_1)
   If @error Then Return SetError(1, 1, $iOperand_1 * $iOperand_2)
   $iOperand_2 = __Integer64($iOperand_2)
   If @error Then Return SetError(2, 1, $iOperand_1 * $iOperand_2)

   Local $iProduct = __Product64($iOperand_1, $iOperand_2)
   Return SetExtended(@extended, $iProduct)
EndFunc ;==> _Multiply64


; #FUNCTION# ===================================================================================================================
; Name...........: _Power64
; Description ...: Raises an integer to the power of a second integer.
; Syntax.........: _Power64($iInteger, $iPower)
; Parameters.....; $iInteger - The integer to operate on.
;                  $iPower - The power to raise the integer to.
; Return values .: Returns an Int-32, or Int-64, value.
;                  Failure returns the executed expression and sets @error as follows:
;                  |@error = 1 The first parameter is not an integer.
;                  |@error = 2 The second parameter is not an integer.
; Author.........: czardas
; ==============================================================================================================================

Func _Power64($iInteger, $iPower)
   $iInteger = __Integer64($iInteger)
   If @error Then Return SetError(1, 1, $iInteger ^ $iPower)
   $iPower = __Integer64($iPower)
   If @error Then Return SetError(2, 1, $iInteger ^ $iPower)

   If $iInteger = 1 Or $iPower = 0 Then Return 1
   If $iPower < 0 Or $iPower > 63 Then Return SetExtended(1, $iInteger ^ $iPower)

   Local $iTriggers = 0, $iCount = 0, $iPow = $iPower

   While $iPow > 1
       If Mod($iPow, 2) Then
           $iPow -= 1
       Else ; to reduce calls to __Product64()
           ; triggers indicate the product should be squared (see next loop)
           $iTriggers += 2 ^ $iCount ; set trigger
           $iPow /= 2
       EndIf
       $iCount += 1
   WEnd

   Local $iOperand, $iResult = $iInteger

   For $i = $iCount -1 To 0 Step -1
       ; multiply the product either by itself or the original value
       $iOperand = BitAND($iTriggers, 2^$i) ? $iResult : $iInteger
       $iResult = __Product64($iResult, $iOperand)
       If @extended Then Return SetExtended(1, $iInteger ^ $iPower)
   Next

   Return $iResult
EndFunc ;==> _Power64


; #FUNCTION# ===================================================================================================================
; Name...........: _Subtract64
; Description ...: Subtracts one integer from another.
; Syntax.........: _Subtract64($iOperand_1, $iOperand_2)
; Parameters.....; $iOperand_1 - The first operand.
;                  $iOperand_2 - The second operand.
; Return values .: Returns an Int-32, or Int-64, value.
;                  Failure returns the executed expression and sets @error as follows:
;                  |@error = 1 The first parameter is not an integer.
;                  |@error = 2 The second parameter is not an integer.
; Author.........: czardas
; ==============================================================================================================================

Func _Subtract64($iOperand_1, $iOperand_2)
   $iOperand_1 = __Integer64($iOperand_1)
   If @error Then Return SetError(1, 1, __DoubleTo64($iOperand_1 - $iOperand_2)) ; may still return an integer
   $iOperand_2 = __Integer64($iOperand_2)
   If @error Then Return SetError(2, 1, __DoubleTo64($iOperand_1 - $iOperand_2)) ; ditto

   Local $bOverflow, $nResult
   $bOverflow = __OverflowDetect('-', $iOperand_1, $iOperand_2, $nResult)
   Return SetExtended($bOverflow, $nResult)
EndFunc ;==> _Subtract64


#Region - Internal Functions

; #INTERNAL_USE_ONLY# ==========================================================================================================
; Name...........: __DoubleTo64
; Description ...: Helper function - converts an integer value double to Int-32 or Int-64.
; Syntax.........: __DoubleTo64($nValue)
; Parameters.....; $nValue - The double to convert
; Return values .: Success returns an Int-32 or Int-64 when the interpreter evaluates the return value equal to the input.
;                  Failure returns the input parameter without any modification and sets @error as follows:
;                  |@error = 1 The input has to be a number.
;                  |@error = 2 The input is a float and conversion to an integer failed.
; Author ........: czardas
; Comments ......; Doubles representing integer values greater than 15 digits cannot be relied on for accuracy.
; ==============================================================================================================================

Func __DoubleTo64($nValue)
   If Not IsNumber($nValue) Then Return SetError(1, 0, $nValue) ; limited to numeric input
   If $nValue > -1.0e+015 And $nValue < 1.0e+015 Then
       Local $iVal64 = Number($nValue, 2) ; Int-64
       If $iVal64 = $nValue Then ; check to see if conversion was a success [expected range +/- 5.62949953421311e+014]
           Return ($iVal64 > 2147483647 Or $iVal64 < -2147483648) ? $iVal64 : Number($iVal64, 1) ; Int-64 or Int-32
       ElseIf $iVal64 -1 = $nValue Then ; attempt to adjust for inaccuracies [subject to possible change]
           Return $iVal64 -1
       ElseIf $iVal64 +1 = $nValue Then ; as above
           Return $iVal64 +1
       EndIf
   EndIf

   Return SetError(2, 0, $nValue) ; conversion failed
EndFunc ;==> __DoubleTo64


; #INTERNAL_USE_ONLY# ==========================================================================================================
; Name...........: __Integer64
; Description ...: Checks if a number is an integer and converts doubles to Int-32 or Int-64 if the result appears unambiguous.
; Syntax.........: __Integer64($nParam)
; Parameters.....; $nParam - The number to test
; Return values .: Success returns an Int-32 or Int-64 when the interpreter evaluates the return value equal to the input.
;                  Failure returns the input parameter without any modification and sets @error as follows:
;                  |@error = 1 The input could not be converted to an exact integer.
; Author ........: czardas
; Comments ......; Doubles representing integer values greater than 15 digits cannot be relied on for accuracy.
; ==============================================================================================================================

Func __Integer64($nParam)
   If Not StringInStr(VarGetType($nParam), 'Int') Then
       Local $iInt64 = __DoubleTo64($nParam) ; attempt conversion
       If @error Then Return SetError(1, 0, $nParam) ; $fParam <> $iInt64
       $nParam = $iInt64 ; float was compared as being equal to an integer
   EndIf
   Return $nParam
EndFunc ;==> __Integer64


; #INTERNAL_USE_ONLY# ==========================================================================================================
; Name...........: __OverflowDetect
; Description ...: Checks for integer overflow on execution of the expression.
; Syntax.........: __OverflowDetect($sOperator, $iOperand_1, $iOperand_2, $nResult)
; Parameters.....; $sOperator - May be +, - or *.
;                  $iOperand_1 - The first operand.
;                  $iOperand_2 - The second operand.
;                  $nResult - [byRef] Result of executed expression.
; Return values .: Returns 1 if integer overflow occurs - otherwise returns 0. Returns $nResult ByRef.
; Author ........: czardas
; Comments ......; Int-32 or Int-64 only. No error checks!
; ==============================================================================================================================

Func __OverflowDetect($sOperator, $iOperand_1, $iOperand_2, ByRef $nResult)
   Local $iExecute, $fCompare

   Switch $sOperator
       Case '+' ; execute the expression
           $iExecute = $iOperand_1 + $iOperand_2
           ; execute the expression with the operands converted to doubles
           $fCompare = Number($iOperand_1, 3) + Number($iOperand_2, 3)
       Case '-' ; as above
           $iExecute = $iOperand_1 - $iOperand_2
           $fCompare = Number($iOperand_1, 3) - Number($iOperand_2, 3)
       Case '*' ; as above
           $iExecute = $iOperand_1 * $iOperand_2
           $fCompare = Number($iOperand_1, 3) * Number($iOperand_2, 3)
   EndSwitch

   ; the results should be approximately equal
   Local $bReturn = StringFormat('%.14e', $iExecute) <> StringFormat('%.14e', $fCompare) ; %.15e is too sensitive

   $nResult = $bReturn ? $fCompare : $iExecute
   Return $bReturn *1 ; covert to a number
EndFunc ;==> __OverflowDetect


; #INTERNAL_USE_ONLY# ==========================================================================================================
; Name...........: __Product64($iOperand_1, $iOperand_2)
; Description ...: Helper function - multiplies two Int-32 or Int-64 values together.
; Syntax.........: __Product64($iOperand_1, $iOperand_2)
; Parameters.....; $iOperand_1 - The first integer.
;                  $iOperand_2 - The second integer.
; Return values .: Returns an Int-32, or Int-64, value.
; Author.........: czardas
; Comments ......; Int-32 or Int-64 only. No error checks!
; ==============================================================================================================================

Func __Product64($iOperand_1, $iOperand_2)
   Local $bOverflow, $nResult
   $bOverflow = __OverflowDetect('*', $iOperand_1, $iOperand_2, $nResult)
   Return SetExtended($bOverflow, $nResult)
EndFunc ;==> __Product64


; #INTERNAL_USE_ONLY# ==========================================================================================================
; Name...........: __WholeNumberDivision
; Description ...: Divides two integers.
; Syntax.........: __WholeNumberDivision($iDividend, $iDivisor)
; Parameters.....; $iDividend - The first operand.
;                  $iDivisor - The second operand.
; Return values .: Returns an Int-64 value.
;                  Failure sets @error as follows:
;                  |@error = 3 The divisor cannot be zero.
;                  |@error = 4 Input range exceeded.
;                  |@error = 5 parameters are not divisible.
; Author ........: czardas
; Comments ......; Input is limited to +/- 9223372036854775807 for both consitency and compatibility with future libraries.
; ==============================================================================================================================

Func __WholeNumberDivision($iDividend, $iDivisor) ; Input ranges -9223372036854775807 To 9223372036854775807
   If $iDivisor = 0 Then Return SetError(3, 0, $iDividend / $iDivisor) ; division by zero

   Local $aDiv = [$iDividend, $iDivisor], _
   $iSign = 1

   For $i = 0 To 1
       If $aDiv[$i] > 0x7FFFFFFFFFFFFFFF Or $aDiv[$i] < 0x8000000000000001 Then Return SetError(4, 0, $iDividend / $iDivisor) ; input range exceeded
       If VarGetType($aDiv[$i]) = "Double" Then $aDiv[$i] = Number($aDiv[$i], 2) ; convert to Int-64

       If $aDiv[$i] < 0 Then ; force positive integers
           $aDiv[$i] *= -1
           $iSign *= -1 ; to add back later
       EndIf
   Next

   If Mod($aDiv[0], $aDiv[1]) Then Return SetError(5, 0, $iDividend / $iDivisor) ; not divisible
   If $aDiv[0] = 0 Then Return 0
   If $aDiv[1] = 1 Then Return $aDiv[0] * $iSign

   Local $iDivision = Floor($aDiv[0] / $aDiv[1]), $iDifference, $iIntegral

   While $iDivision * $aDiv[1] > $aDiv[0] ; division is overstated
       $iDifference = ($aDiv[1] * $iDivision) - $aDiv[0]
       $iIntegral = Floor($iDifference / $aDiv[1]) ; avoid shooting beyond the target
       If $iIntegral = 0 Then $iIntegral = 1 ; prevents hanging in an infinite loop
       $iDivision -= $iIntegral
   WEnd

   While $iDivision * $aDiv[1] < $aDiv[0] ; division is understated
       $iDifference = $aDiv[0] - ($aDiv[1] * $iDivision)
       $iIntegral = Floor($iDifference / $aDiv[1]) ; as above
       If $iIntegral = 0 Then $iIntegral = 1 ; prevents hanging
       $iDivision += $iIntegral
   WEnd

   Return $iDivision * $iSign
EndFunc ;==> __WholeNumberDivision

#EndRegion
Examples:

Code:
>#include 'operator64.au3'

ConsoleWrite("Testing _Abs64()" & @LF)                       ; ==> Err  Ext Result
$test = _Abs64(0xC000000000000000)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    0   4611686018427387904
$test = _Abs64(0x8000000000000000)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 2    1   9.22337203685478e+018
$test = _Abs64(0x8000000000000001)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    0   9223372036854775807
$test = _Abs64(-0.123)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 1    1   0.123
;===========================================================

ConsoleWrite(@LF & "Testing _Add64()" & @LF)
$test = _Add64(0x7FFFFFFFFFFFFFFF, 1)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    1   9.22337203685478e+018
$test = _Add64(0x7FFFFFFFFFFFFFFF, 0)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    0   9223372036854775807
$test = _Add64(0x7FFFFFFFFFFFFFFF, -1)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    0   9223372036854775806
$test = _Add64(33, 15)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    0   48
;===========================================================

ConsoleWrite(@LF & "Testing _Divide64()" & @LF)
$test = _Divide64(0x7FFFFFFFFFFFFFFF, -1)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    0   -9223372036854775807
$test = _Divide64(0x8000000000000000, -2)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    0   4611686018427387904
$test = _Divide64(10.0, 2)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    0   5
$test = _Divide64(9223372036854775552, -2)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    0   -4611686018427387776
$test = _Divide64(9223372036854775552, 0)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 2    1   1.#INF
$test = _Divide64(675432.0097, -987)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 1    1   -684.328277304965
$test = _Divide64(6922337, 15)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 4    1   461489.133333333
;===========================================================

ConsoleWrite(@LF & "Testing _Multiply64()" & @LF)
$test = _Multiply64(9223372036854775552, -2)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    1   -1.84467440737096e+019
$test = _Multiply64(223372036854775552, 9)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    0   2010348331692979968
$test = _Multiply64(1.01, -1)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 1    1   -1.01
;===========================================================

ConsoleWrite(@LF & "Testing _Power64()" & @LF)
$test = _Power64(-2.0, 63)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    0   -9223372036854775808
$test = _Power64(37, 12.0)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    0   6582952005840035281
$test = _Power64(17, 19)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    1   2.39072435685151e+023
;===========================================================

ConsoleWrite(@LF & "Testing _Subtract64()" & @LF)
$test = _Subtract64(1.0, 1)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    0   0
$test = _Subtract64(0x8000000000000000, -1)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    0   -9223372036854775807
$test = _Subtract64(0x8000000000000000, 0)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    0   -9223372036854775808
$test = _Subtract64(0x8000000000000000, 1)
ConsoleWrite(@Error & @TAB & @Extended & @TAB & $test & @LF) ; ==> 0    1   -9.22337203685478e+018
[/HIDE-THANKS]

 
Status
Not open for further replies.
Back
Top