Jump to content

Recommended Posts

Posted

two further BigNum functions:

_BigNum_Pow()

_BigNum_n_root()

#Include <BigNum.au3>


; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_Pow
; Description ...: Exponentiation $n^$e
; Syntax.........: _BigNum_Pow($n [, $e = 2])
; Parameters ....: $n - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $e [optional] - Exponent (must be a positive 64-bit signed integer)
;                                  Default: $e = 2 means result = $n²
; Return values .: Success - Result $n^$e
;                  Failure - -1, sets @error to 1 if $n not valid StringNumber
;                            -1, sets @error to 2 if $e is not a positive Integer
; Author ........: jennicoattminusonlinedotde
; Date ..........: 9.12.09
; Remarks .......: Fractional exponents not allowed - use BigNum_n_root instead.
;                  _BigNum_Pow() offers a drastically better efficiency than looping _BigNum_Mul()
; Reference .....: http://en.wikipedia.org/wiki/Exponentiation_by_squaring
; ;===============================================================================================
Func _BigNum_Pow($n, $e = 2)
    $e = Number($e)
    If IsInt($e) = 0 Or $e < 0 Then Return SetError(2, 0, -1)
    ;If $e < -2147483648 Or $e > 2147483647 Then Return SetError(-2, 0, -1)
    If _BigNum_IsValid ($n, $n) Then Return SetError(1, 0, -1)

    Local $res = 1
    
    While $e
        ;If BitAND($e, 1) Then  ; bitoperation is not faster !
        If Mod($e, 2) Then
            $res = _BigNum_Mul ($res, $n)
            $e -= 1
        EndIf
        $n = _BigNum_Mul ($n, $n)
        ;$e = BitShift($e, 1)   ; bitoperation is not faster !
        $e /= 2
    WEnd
    
    Return $res
EndFunc   ;==>_BigNum_Pow



; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_n_Root
; Description ...: $e-th Root of $n
; Syntax.........: _n_Root($n [, $e=2])
; Parameters ....: $n - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $e - [optional] Multiplicity of root (power, exponent) (must be a positive 64-bit signed integer > 0)
;                            Default: $e = 2 (=SQRT)
;                  $p - [optional] Precision (Number of desired Decimalplaces) (must be positive Integer)
;                            Default: $p = -1 means automatic precision (stringlen of integer part of $n)
; Return values .: Success - Result $e-root($n)
;                            @extended = Number of Iterations
;                  Failure - -1 and sets @error to 1 if $n not valid StringNumber
;                            -1 and sets @error to 2 if $e out of valid range
;                            -1 and sets @error to 3 if $p out of valid range
; Author ........: jennicoattminusonlinedotde
; Date ..........: 9.12.09
; References ....: derived from "Newton's Method"
; ;===============================================================================================
Func _BigNum_n_Root($n, $e = 2, $p = -1)
    If _BigNum_IsValid ($n, $n) Then Return SetError(1, 0, -1)
    $e = Number($e)
    If IsInt($e) = 0 Or $e < 1 Then Return SetError(2, 0, -1)
    $p = Number($p)
    If IsInt($p) = 0 Or $p < -1 Then Return SetError(3, 0, -1)
    
    Local $l = StringInStr($n, ".") - 1
    If $l = -1 Then $l = StringLen($n)
    If $p < 0 Then $p = $l
    Local $g = 1, $last, $i = 0
    
    For $i = 3 To $l Step 2
        $g = _BigNum_Mul ($g, 10)
    Next
    
    While 1
        $i += 1
        $last = $g
        $g = _BigNum_Div (_BigNum_Add (_BigNum_Div ($n, _BigNum_Pow($g, $e - 1), $p), _BigNum_Mul ($g, $e - 1)), $e, $p)
        If $last = $g Then Return SetExtended($i, $g)
    WEnd
EndFunc   ;==>_BigNum_n_Root




_Example_1()    ;   calculates 2^5000 within half a second
_Example_2()

Func _Example_1()
    Local $timer = TimerInit()
    MsgBox(0, "BigNum_Pow Example 1:  2 ^5000 =", _BigNum_Pow(2, 5000) & @CRLF & @CRLF & TimerDiff($timer) / 1000)
EndFunc   ;==>_Example_1

Func _Example_2()
    While 1

        Local $n = InputBox("BigNum nth-root Example 2", "Enter any Number to calculate the nth Root")
        If @error Then Return
        Local $e = InputBox("BigNum nth-root Example 2", "Enter 'n'  (the multiplicity of the nth Root)")
        If @error Then Return
        
        Local $timer = TimerInit()

        Local $g = _BigNum_n_Root($n, $e)
        Local $i = @extended

        MsgBox(0, "Raw nth-root Example 2 Result:", $e & "th root of " & $n & " = " & $g & @CRLF & @CRLF & "Time: " & Round(TimerDiff($timer) / 1000, 10) & " sec" & @CRLF & "Error: " & _BigNum_Sub (_BigNum_Pow($g, $e), $n) & @CRLF & @TAB & "(" & Round(_BigNum_Div (_BigNum_Mul (_BigNum_Sub (_BigNum_Pow($g, $e), $n), 100), $n, 5), 6) & " %)" & @CRLF & "Iterations: " & $i)

    WEnd
EndFunc   ;==>_Example_2

i updated the UDF and put it in my first post here.

j.

Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Posted

i'm sure he could optimize my ideas.

j.

Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Posted

New function: _BigNum_Sum. The name might be a bit misleading, but ah well ;)

It seperates a sum into each individual operation, and then uses the BigNum functions to solve it. This is going to very useful to anyone writing a calculator, as it allows BigNums to do the sums. It is also very short for what it does, which usually means I missed something...

; #FUNCTION# ;====================================================================================
; Name...........: _BigNum_Sum
; Description ...: Parses a sum using bigNums
; Syntax.........: _BigNum_Sum($sSum)
; Parameters ....: $sSum - A String showing the sum e.g. "2342314-9073458320-4953425342535+432532453245324534*34524532452345"
; Return values .: Success - Result
;                  Failure - 0, and sets @Error. If @Error = 0xDEAD then there is a function missing.
; Remarks .......: Becouse this uses call, Internal functions are not supported.
; Author ........: Mat
; ;===============================================================================================

Func _BigNum_Sum($sIn)
    $sIn = StringStripWS($sIn, 8)
    Local $aReg = StringRegExp($sIn, "(?i)([0x;&H][0-9]*)", 3)
    If Not @error Then
        For $i = 0 To UBound($aReg) - 1
            $sIn = StringReplace($sIn, $aReg[$i], Dec(StringTrimLeft($aReg[$i], 2)))
        Next
    EndIf

    Local $aMatches = StringRegExp ($sIn, "(\w*\(.*?\))", 3), $aParts, $sRet
    If Not @Error Then
        For $i = 0 to UBound ($aMatches) - 1
            $aParts = StringSplit (StringRegExpReplace ($aMatches[$i], ".*?\((.*?)\)", "\1"), ",")
            $aParts[0] = "CallArgArray"
            $sRet = Call (StringRegExpReplace ($aMatches[$i], "\(.*", ""), $aParts)
            If @Error Then
                $sRet = Call ("_BigNum_" & StringRegExpReplace ($aMatches[$i], "\(.*", ""), $aParts)
                If @Error Then Return SetError (@Error, @extended, $sRet)
            EndIf
            $sIn = StringReplace ($sIn, $aMatches[$i], $sRet)
        Next
    EndIf

    ; Brackets
    Local $sNest, $res
    While StringInStr($sIn, "(")
        $sNest = StringRegExpReplace($sIn, ".*?\(([^\(]+?)\).*", "\1")
        $res = _BigNum_Sum($sNest)
        If @error Then Return SetError (@Error, @Extended, 0)

        $sIn = StringReplace($sIn, "(" & $sNest & ")", $res)
    WEnd

    Local $aOps[6][2] = [["\^", "_BigNum_Pow"], ["%", "_BigNum_Mod"],["/", "_BigNum_Div"],["\*", "_BigNum_Mul"],["\+", "_BigNum_Add"],["-", "_BigNum_Sub"]]

    For $i = 0 To 5
        $aMatches = StringRegExp($sIn, "(-?\d*" & $aOps[$i][0] & "\d*)", 3)
        If Not @error Then
            For $x = 0 To UBound($aMatches) - 1
                $aParts = StringSplit($aMatches[$x], StringRight($aOps[$i][0], 1))
                $aParts[0] = "CallArgArray"
                $sRet = Call($aOps[$i][1], $aParts)
                If @Error Then Return SetError (@Error, @Extended, 0)
                $sIn = StringReplace($sIn, $aMatches[$x], $sRet)
            Next
        EndIf
    Next

    Return $sIn
EndFunc   ;==>_BigNum_Sum

and the edited UDF:

#include-once

Global Const $BigNum_Debug = False

; #INDEX# =======================================================================================================================
; Title .........: BigNum
; AutoIt Version : 3.2.12.1
; Language ......: English
; Description ...: Perform calculations with big numbers
; ===============================================================================================================================

; #CURRENT# =====================================================================================================================
;_BigNum_Sum
;_BigNum_Add
;_BigNum_Sub
;_BigNum_Mul
;_BigNum_Div
;_BigNum_Pow
;_BigNum_SQRT
;_BigNum_n_Root
;_BigNum_Mod
;_BigNum_Round
;_BigNum_Compare
;_BigNum_Swap
; ===============================================================================================================================

; #INTERNAL_USE_ONLY#============================================================================================================
;_BigNum_CheckNegative
;_BigNum_DivAdd
;_BigNum_DivComp
;_BigNum_DivSub
;_BigNum_Div_DivisorGreater14
;_BigNum_Div_DivisorMaxLen14
;_BigNum_InsertDecimalSeparator
;_BigNum_StringIsDecimal
;_BigNum_IsValid
; ===============================================================================================================================

; #FUNCTION# ;====================================================================================
; Name...........: _BigNum_Sum
; Description ...: Parses a sum using bigNums
; Syntax.........: _BigNum_Sum($sSum)
; Parameters ....: $sSum - A String showing the sum e.g. "2342314-9073458320-4953425342535+432532453245324534*34524532452345"
; Return values .: Success - Result
;                  Failure - 0, and sets @Error. If @Error = 0xDEAD then there is a function missing.
; Remarks .......: Becouse this uses call, Internal functions are not supported.
; Author ........: Mat
; ;===============================================================================================

Func _BigNum_Sum($sIn)
    $sIn = StringStripWS($sIn, 8)
    Local $aReg = StringRegExp($sIn, "(?i)([0x;&H][0-9]*)", 3)
    If Not @error Then
        For $i = 0 To UBound($aReg) - 1
            $sIn = StringReplace($sIn, $aReg[$i], Dec(StringTrimLeft($aReg[$i], 2)))
        Next
    EndIf

    Local $aMatches = StringRegExp ($sIn, "(\w*\(.*?\))", 3), $aParts, $sRet
    If Not @Error Then
        For $i = 0 to UBound ($aMatches) - 1
            $aParts = StringSplit (StringRegExpReplace ($aMatches[$i], ".*?\((.*?)\)", "\1"), ",")
            $aParts[0] = "CallArgArray"
            $sRet = Call (StringRegExpReplace ($aMatches[$i], "\(.*", ""), $aParts)
            If @Error Then
                $sRet = Call ("_BigNum_" & StringRegExpReplace ($aMatches[$i], "\(.*", ""), $aParts)
                If @Error Then Return SetError (@Error, @extended, $sRet)
            EndIf
            $sIn = StringReplace ($sIn, $aMatches[$i], $sRet)
        Next
    EndIf

    ; Brackets
    Local $sNest, $res
    While StringInStr($sIn, "(")
        $sNest = StringRegExpReplace($sIn, ".*?\(([^\(]+?)\).*", "\1")
        $res = _BigNum_Sum($sNest)
        If @error Then Return SetError (@Error, @Extended, 0)

        $sIn = StringReplace($sIn, "(" & $sNest & ")", $res)
    WEnd

    Local $aOps[6][2] = [["\^", "_BigNum_Pow"], ["%", "_BigNum_Mod"],["/", "_BigNum_Div"],["\*", "_BigNum_Mul"],["\+", "_BigNum_Add"],["-", "_BigNum_Sub"]]

    For $i = 0 To 5
        $aMatches = StringRegExp($sIn, "(-?\d*" & $aOps[$i][0] & "\d*)", 3)
        If Not @error Then
            For $x = 0 To UBound($aMatches) - 1
                $aParts = StringSplit($aMatches[$x], StringRight($aOps[$i][0], 1))
                $aParts[0] = "CallArgArray"
                $sRet = Call($aOps[$i][1], $aParts)
                If @Error Then Return SetError (@Error, @Extended, 0)
                $sIn = StringReplace($sIn, $aMatches[$x], $sRet)
            Next
        EndIf
    Next

    Return $sIn
EndFunc   ;==>_BigNum_Sum

; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_Add
; Description ...: Addition $sX + $sY
; Syntax.........: _BigNum_Add($sX, $sY)
; Parameters ....: $sX - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $sY - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
; Return values .: Success - Result $sX + $sY
;                  Failure - 0, sets @error to 1 if $sX/$sY not valid StringNumber
; Author ........: Eukalyptus www.autoit.de
;
; ;===============================================================================================
Func _BigNum_Add($sX, $sY)
    If _BigNum_IsValid($sX, $sY) Then Return SetError(1, 0, 0)
    Local $iNeg = _BigNum_CheckNegative($sX, $sY), $sNeg = ""
    If $iNeg = 3 Then $sNeg = "-"
    If $iNeg = 1 Then Return _BigNum_Sub($sY, $sX)
    If $iNeg = 2 Then Return _BigNum_Sub($sX, $sY)
    If $BigNum_Debug Then Local $BN_File = FileOpen(@ScriptDir & "\BigNum_Debug.txt", 2)
    Local $iDec = _BigNum_StringIsDecimal($sX, $sY)
    Local $iTmp = StringLen($sX), $iLen = StringLen($sY), $iCar = 0, $sRet = ""
    If $BigNum_Debug Then FileWrite($BN_File, " " & _BigNum_DS($iLen - $iTmp, "0") & $sX & " + " & @CRLF & " " & _BigNum_DS($iTmp - $iLen, "0") & $sY & @CRLF)
    If $iLen < $iTmp Then $iLen = $iTmp
    If $BigNum_Debug Then FileWrite($BN_File, " " & _BigNum_DS($iLen, "-") & @CRLF)
    For $i = 1 To $iLen Step 18
        $iTmp = Int(StringRight($sX, 18)) + Int(StringRight($sY, 18)) + $iCar
        $sX = StringTrimRight($sX, 18)
        $sY = StringTrimRight($sY, 18)
        If ($iTmp > 999999999999999999) Then
            $iTmp = StringRight($iTmp, 18)
            $sRet = $iTmp & $sRet
            If $BigNum_Debug Then FileWrite($BN_File, _BigNum_DS($iLen - $i - StringLen($iTmp) + 2) & $iTmp & _BigNum_DS($i) & "+" & $iCar & @CRLF)
            $iCar = 1
        Else
            If $BigNum_Debug Then FileWrite($BN_File, _BigNum_DS($iLen - $i - StringLen($iTmp) + 2) & $iTmp & _BigNum_DS($i) & "+" & $iCar & @CRLF)
            $iTmp = StringRight("000000000000000000" & $iTmp, 18)
            $sRet = $iTmp & $sRet
            $iCar = 0
        EndIf
    Next
    $sRet = StringRegExpReplace($iCar & $sRet, "^0+([^0]|0$)", "\1", 1)
    If $iDec > 0 Then $sRet = _BigNum_InsertDecimalSeparator($sRet, $iDec, $iDec)
    If $sRet = "0"  Then $sNeg = ""
    If $BigNum_Debug Then
        FileWrite($BN_File, " " & _BigNum_DS($iLen, "-") & @CRLF)
        FileWrite($BN_File, _BigNum_DS($iLen - StringLen($sRet) + 1) & $sRet)
        FileClose($BN_File)
    EndIf
    Return $sNeg & $sRet
EndFunc   ;==>_BigNum_Add



; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_Sub
; Description ...: Subtraction $sX - $sY
; Syntax.........: _BigNum_Sub($sX, $sY)
; Parameters ....: $sX - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $sY - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
; Return values .: Success - Result $sX - $sY
;                  Failure - 0, sets @error to 1 if $sX/$sY not valid StringNumber
; Author ........: Eukalyptus www.autoit.de
;
; ;===============================================================================================
Func _BigNum_Sub($sX, $sY)
    If _BigNum_IsValid($sX, $sY) Then Return SetError(1, 0, 0)
    Local $iNeg = _BigNum_CheckNegative($sX, $sY), $bNeg = False
    If $iNeg = 3 Then Return _BigNum_Add("-" & $sX, $sY)
    If $iNeg = 1 Then Return "-" & _BigNum_Add($sX, $sY)
    If $iNeg = 2 Then Return _BigNum_Add($sX, $sY)
    If $BigNum_Debug Then Local $BN_File = FileOpen(@ScriptDir & "\BigNum_Debug.txt", 2)
    Local $iDec = _BigNum_StringIsDecimal($sX, $sY)
    If _BigNum_Compare($sX, $sY) = -1 Then $bNeg = _BigNum_Swap($sX, $sY)
    Local $iTmp = StringLen($sX), $iLen = StringLen($sY), $iCar = 0, $sRet = ""
    If $BigNum_Debug Then FileWrite($BN_File, " " & _BigNum_DS($iLen - $iTmp, "0") & $sX & " - " & @CRLF & " " & _BigNum_DS($iTmp - $iLen, "0") & $sY & @CRLF)
    If $iLen < $iTmp Then $iLen = $iTmp
    If $BigNum_Debug Then FileWrite($BN_File, " " & _BigNum_DS($iLen, "-") & @CRLF)
    For $i = 1 To $iLen Step 18
        $iTmp = Int(StringRight($sX, 18)) - Int(StringRight($sY, 18)) - $iCar
        $sX = StringTrimRight($sX, 18)
        $sY = StringTrimRight($sY, 18)
        If $iTmp < 0 Then
            $iTmp = 1000000000000000000 + $iTmp
            If $BigNum_Debug Then FileWrite($BN_File, _BigNum_DS($iLen - $i - StringLen($iTmp) + 2) & $iTmp & _BigNum_DS($i) & "-" & $iCar & @CRLF)
            $iCar = 1
        Else
            If $BigNum_Debug Then FileWrite($BN_File, _BigNum_DS($iLen - $i - StringLen($iTmp) + 2) & $iTmp & _BigNum_DS($i) & "-" & $iCar & @CRLF)
            $iCar = 0
        EndIf
        $sRet = StringRight("0000000000000000000" & $iTmp, 18) & $sRet
    Next
    $sRet = StringRegExpReplace($iCar & $sRet, "^0+([^0]|0$)", "\1", 1)
    If $iDec > 0 Then $sRet = _BigNum_InsertDecimalSeparator($sRet, $iDec, $iDec)
    If $BigNum_Debug Then
        FileWrite($BN_File, " " & _BigNum_DS($iLen, "-") & @CRLF)
        FileWrite($BN_File, _BigNum_DS($iLen - StringLen($sRet) + 1) & $sRet)
        FileClose($BN_File)
    EndIf
    If $bNeg = True And $sRet <> "0"  Then
        Return "-" & $sRet
    Else
        Return $sRet
    EndIf
EndFunc   ;==>_BigNum_Sub



; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_Mul
; Description ...: Multiplication $sX * $sY
; Syntax.........: _BigNum_Mul($sX, $sY)
; Parameters ....: $sX - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $sY - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
; Return values .: Success - Result $sX * $sY
;                  Failure - 0, sets @error to 1 if $sX/$sY not valid StringNumber
; Author ........: Eukalyptus www.autoit.de
;
; ;===============================================================================================
Func _BigNum_Mul($sX, $sY)
    If _BigNum_IsValid($sX, $sY) Then Return SetError(1, 0, 0)
    Local $iNeg = _BigNum_CheckNegative($sX, $sY), $sNeg = ""
    Local $iDec = _BigNum_StringIsDecimal($sX, $sY)
    If $BigNum_Debug Then
        Local $BN_File = FileOpen(@ScriptDir & "\BigNum_Debug.txt", 2), $BN_X = StringLen($sX)
        FileWrite($BN_File, " " & $sX & " * " & $sY & " = " & @CRLF)
        FileWrite($BN_File, " " & _BigNum_DS($BN_X + StringLen($sY) + 3, "-") & @CRLF)
    EndIf
    Local $aX = StringRegExp($sX, '\A.{' & 6 - (Ceiling(StringLen($sX) / 6) * 6 - StringLen($sX)) & '}|.{6}+', 3)
    Local $aY = StringRegExp($sY, '\A.{' & 6 - (Ceiling(StringLen($sY) / 6) * 6 - StringLen($sY)) & '}|.{6}+', 3)
    Local $aRet[UBound($aX) + UBound($aY) - 1]
    For $j = 0 To UBound($aX) - 1
        For $i = 0 To UBound($aY) - 1
            If $BigNum_Debug Then
                FileWrite($BN_File, " " & _BigNum_DS(StringLen($aX[0]) + $j * 6 - StringLen($aX[$j])) & $aX[$j] & _BigNum_DS($BN_X - (StringLen($aX[0]) + $j * 6)) & " * " & _BigNum_DS(StringLen($aY[0]) + $i * 6 - StringLen($aY[$i])) & $aY[$i])
                FileWrite($BN_File, "   " & _BigNum_DS(((UBound($aY) - 1 - $i) * 6) + ($i * 15 + $j * 15)) & $aX[$j] * $aY[$i] & @CRLF)
            EndIf
            $aRet[$j + $i] += $aX[$j] * $aY[$i]
        Next
    Next
    If $BigNum_Debug Then
        FileWrite($BN_File, " " & _BigNum_DS($BN_X + StringLen($sY) + 3) & _BigNum_DS($i * 15 + $j * 15, "-") & @CRLF)
        FileWrite($BN_File, " " & _BigNum_DS($BN_X + StringLen($sY) + 6))
        For $i = 0 To UBound($aRet) - 1
            FileWrite($BN_File, $aRet[$i] & _BigNum_DS(15 - StringLen($aRet[$i])))
        Next
        FileWrite($BN_File, @CRLF & @CRLF)
        For $i = 0 To UBound($aRet) - 1
            FileWrite($BN_File, _BigNum_DS($BN_X + StringLen($sY)) & _BigNum_DS($i * 6 + 15 - StringLen($aRet[$i])) & $aRet[$i] & @CRLF)
        Next
        FileWrite($BN_File, _BigNum_DS($BN_X + StringLen($sY)) & _BigNum_DS(15 - StringLen($aRet[0])) & _BigNum_DS($i * 6, "-") & @CRLF)
    EndIf
    Local $sRet = "", $iCar = 0, $iTmp
    For $i = UBound($aRet) - 1 To 0 Step - 1
        $aRet[$i] += $iCar
        $iCar = Floor($aRet[$i] / 1000000)
        $iTmp = Mod($aRet[$i], 1000000)
        If $iTmp <= 1000000 Then $iTmp = StringRight("000000" & $iTmp, 6)
        $sRet = $iTmp & $sRet
    Next
    If $iCar > 0 Then $sRet = $iCar & $sRet
    $sRet = StringRegExpReplace($sRet, "^0+([^0]|0$)", "\1", 1)
    If ($iNeg = 1 Or $iNeg = 2) And $sRet <> "0"  Then $sNeg = "-"
    If $iDec > 0 Then $sRet = _BigNum_InsertDecimalSeparator($sRet, $iDec * 2, $iDec * 2)
    If $BigNum_Debug Then
        FileWrite($BN_File, _BigNum_DS($BN_X + StringLen($sY)) & _BigNum_DS(15 - StringLen($aRet[0])) & $sRet)
        FileClose($BN_File)
    EndIf
    Return $sNeg & $sRet
EndFunc   ;==>_BigNum_Mul



; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_Div
; Description ...: Division $sX / $sY
; Syntax.........: _BigNum_Div($sX, $sY, [$iD = 0])
; Parameters ....: $sX - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $sY - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $iD [optional] - Number of Decimalplaces
; Return values .: Success - Result $sX / $sY
;                  Failure - 0, sets @error to 1 if $sX/$sY not valid StringNumber
; Author ........: Eukalyptus www.autoit.de
;
; ;===============================================================================================
Func _BigNum_Div($sX, $sY, $iD = 0)
    If _BigNum_IsValid($sX, $sY) Then Return SetError(1, 0, 0)
    Local $iNeg = _BigNum_CheckNegative($sX, $sY), $sNeg = ""
    Local $iDec = _BigNum_StringIsDecimal($sX, $sY), $sMod
    If $sX = 0 Or $sY = 0 Then Return "0"
    If $sY = "1"  Then Return $sNeg & $sX
    While StringLeft($sX, 1) = "0"
        $sX = StringTrimLeft($sX, 1)
        $iDec += 1
    WEnd
    While StringLeft($sY, 1) = "0"
        $sY = StringTrimLeft($sY, 1)
        $iDec += 1
    WEnd
    Local $sRet = "", $iLnX = StringLen($sX), $iLnY = StringLen($sY), $iTmp, $iCnt, $sTmp, $iDe1 = 0
    If $iD > 0 Then $iDe1 += $iD
    If $iNeg = 1 Or $iNeg = 2 Then $sNeg = "-"
    $iTmp = _BigNum_Compare($sX, $sY)
    If $iTmp = -1 Then
        For $iCnt = $iLnX To $iLnY
            $sX &= 0
            $iDe1 += 1
        Next
    EndIf
    If $iTmp = 0 Then Return $sNeg & "1"
    If $iD = -1 Then $iD = $iDec * 2
    For $iCnt = 1 To $iD
        $sX &= "0"
    Next
    If $iLnY > 14 Then
        $sRet = _BigNum_Div_DivisorGreater14($sX, $sY, $sMod)
    Else
        $sRet = _BigNum_Div_DivisorMaxLen14($sX, $sY, $sMod)
    EndIf
    If $iDe1 > 0 Then $sRet = _BigNum_InsertDecimalSeparator($sRet, $iDe1, $iD)
    If $sRet = "0"  Then
        Return "0"
    Else
        Return $sNeg & $sRet
    EndIf
EndFunc   ;==>_BigNum_Div


; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_Pow
; Description ...: Exponentiation $n^$e
; Syntax.........: _BigNum_Pow($n [, $e = 2])
; Parameters ....: $n - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $e [optional] - Exponent (must be a positive 64-bit signed integer)
;                                  Default: $e = 2 means result = $n²
; Return values .: Success - Result $n^$e
;                  Failure - -1, sets @error to 1 if $n not valid StringNumber
;                            -1, sets @error to 2 if $e is not a positive Integer
; Author ........: jennicoattminusonlinedotde
; Date ..........: 9.12.09
; Remarks .......: Fractional exponents not allowed - use BigNum_n_root instead.
;                  _BigNum_Pow() offers a drastically better efficiency than looping _BigNum_Mul()
; Reference .....: http://en.wikipedia.org/wiki/Exponentiation_by_squaring
; ;===============================================================================================
Func _BigNum_Pow($n, $e = 2)
    $e = Number($e)
    If IsInt($e) = 0 Or $e < 0 Then Return SetError(2, 0, -1)
    ;If $e < -2147483648 Or $e > 2147483647 Then Return SetError(-2, 0, -1)
    If _BigNum_IsValid($n, $n) Then Return SetError(1, 0, -1)

    Local $res = 1

    While $e
        ;If BitAND($e, 1) Then  ; bitoperation is not faster !
        If Mod($e, 2) Then
            $res = _BigNum_Mul($res, $n)
            $e -= 1
        EndIf
        $n = _BigNum_Mul($n, $n)
        ;$e = BitShift($e, 1)   ; bitoperation is not faster !
        $e /= 2
    WEnd

    Return $res
EndFunc   ;==>_BigNum_Pow


; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_SQRT
; Description ...: Square Root (BigNum)
; Syntax.........: _BigNum_SQRT($n [, $p = -1])
; Parameters ....: $n - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $p [optional] - Precision (Number of Decimalplaces) (must be positive Integer)
;                            Default: $p = -1 means automatic precision (stringlen of integer part of $n)
; Return values .: Success - Result SQRT($n)
;                            @extended = Precicion of result (if $p set to automatic precision)
;                            @error = Number of Iterations
;                  Failure - -1, sets @error to -1 if $n not valid StringNumber
;                            -1, sets @error to -2 if $p is out of valid range
;                            -1, sets @error to -3 if time-out (>100 iterations)
; Author ........: jennicoattminusonlinedotde
; Date ..........: 8.12.09
; Remarks .......: use Precision param when u want to obtain the square root of a small number with the desired decimal places.
; References ....: http://www.merriampark.com/bigsqrt.htm
;                  "Newton's Method" - before: Heron of Alexandria
; ;===============================================================================================
Func _BigNum_SQRT($n, $p = -1)
    If _BigNum_IsValid($n, $n) Then Return SetError(-1, 0, -1)
    $p = Number($p)
    If IsInt($p) = 0 Or $p < -1 Then Return SetError(-2, 0, -1)
    Local $l = StringInStr($n, ".") - 1
    If $l = -1 Then $l = StringLen($n)
    If $p < 0 Then $p = $l
    Local $g = 1, $last

    For $i = 3 To $l Step 2
        $g = _BigNum_Mul($g, 10)
    Next

    For $i = 1 To 100
        $last = $g
        $g = _BigNum_Div(_BigNum_Add(_BigNum_Div($n, $g, $p), $g), 2, $p)
        If $last = $g Then Return SetError($i, $p, $g)
    Next
    Return SetError(-3, 0, -1)
EndFunc   ;==>_BigNum_SQRT



; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_n_Root
; Description ...: $e-th Root of $n
; Syntax.........: _n_Root($n [, $e=2])
; Parameters ....: $n - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $e - [optional] Multiplicity of root (power, exponent) (must be a positive 64-bit signed integer > 0)
;                            Default: $e = 2 (=SQRT)
;                  $p - [optional] Precision (Number of desired Decimalplaces) (must be positive Integer)
;                            Default: $p = -1 means automatic precision (stringlen of integer part of $n)
; Return values .: Success - Result $e-root($n)
;                            @extended = Number of Iterations
;                  Failure - -1 and sets @error to 1 if $n not valid StringNumber
;                            -1 and sets @error to 2 if $e out of valid range
;                            -1 and sets @error to 3 if $p out of valid range
; Author ........: jennicoattminusonlinedotde
; Date ..........: 9.12.09
; References ....: derived from "Newton's Method"
; ;===============================================================================================
Func _BigNum_n_Root($n, $e = 2, $p = -1)
    If _BigNum_IsValid($n, $n) Then Return SetError(1, 0, -1)
    $e = Number($e)
    If IsInt($e) = 0 Or $e < 1 Then Return SetError(2, 0, -1)
    $p = Number($p)
    If IsInt($p) = 0 Or $p < -1 Then Return SetError(3, 0, -1)

    Local $l = StringInStr($n, ".") - 1
    If $l = -1 Then $l = StringLen($n)
    If $p < 0 Then $p = $l
    Local $g = 1, $last, $i = 0

    For $i = 3 To $l Step 2
        $g = _BigNum_Mul($g, 10)
    Next

    While 1
        $i += 1
        $last = $g
        $g = _BigNum_Div(_BigNum_Add(_BigNum_Div($n, _BigNum_Pow($g, $e - 1), $p), _BigNum_Mul($g, $e - 1)), $e, $p)
        If $last = $g Then Return SetExtended($i, $g)
    WEnd
EndFunc   ;==>_BigNum_n_Root



; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_Mod
; Description ...: Modulo Mod($sX, $sY)
; Syntax.........: _BigNum_Mod($sX, $sY)
; Parameters ....: $sX - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $sY - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
; Return values .: Success - Result Mod($sX, $sY)
;                  Failure - 0, sets @error to 1 if $sX/$sY not valid StringNumber
; Author ........: Eukalyptus www.autoit.de
;
; ;===============================================================================================
Func _BigNum_Mod($sX, $sY)
    If _BigNum_IsValid($sX, $sY) Then Return SetError(1, 0, 0)
    If $sY = 0 Or $sY = 1 Then Return "0"
    Local $sRes = $sX
    Local $iNeg = _BigNum_CheckNegative($sX, $sY)
    Local $iDec = _BigNum_StringIsDecimal($sX, $sY)
    If _BigNum_Compare($sX, $sY) < 0 Then Return $sRes
    Local $sRet = "", $iLnX = StringLen($sX), $iLnY = StringLen($sY)
    If $iLnY > 14 Then
        _BigNum_Div_DivisorGreater14($sX, $sY, $sRet)
    Else
        _BigNum_Div_DivisorMaxLen14($sX, $sY, $sRet)
    EndIf
    $sRet = _BigNum_InsertDecimalSeparator($sRet, $iDec, StringLen($sRet))
    If ($iNeg = 3 Or $iNeg = 1) And $sRet <> "0"  Then $sRet = "-" & $sRet
    Return $sRet
EndFunc   ;==>_BigNum_Mod



; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_Round
; Description ...: Round $sX to $iD Decimalplaces
; Syntax.........: _BigNum_Round($sX, $iD)
; Parameters ....: $sX - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $iD - Number of Decimalplaces
; Return values .: Success - Result Round($sX, $iD)
;                  Failure - 0, sets @error to 1 if $sX not valid StringNumber
; Author ........: Eukalyptus www.autoit.de
;
; ;===============================================================================================
Func _BigNum_Round($sX, $iD)
    If _BigNum_IsValid($sX, $sX) Then Return SetError(1, 0, 0)
    Local $sTmp = 0, $sRet, $sRes = $sX
    Local $iNeg = _BigNum_CheckNegative($sX, $sTmp)
    Local $iDec = _BigNum_StringIsDecimal($sX, $sTmp)
    If $iD > $iDec Or $iDec = 0 Then Return $sRes
    $sTmp = StringLeft(StringRight($sX, $iDec - $iD), 1)
    $sRet = StringTrimRight($sRes, $iDec - $iD)
    If $sTmp >= 5 And $iD > 0 Then
        If $iNeg = 1 Then
            $sRet = _BigNum_Add($sRet, "-0." & StringFormat("%0" & String($iD) & "u", "1"))
        Else
            $sRet = _BigNum_Add($sRet, "0." & StringFormat("%0" & String($iD) & "u", "1"))
        EndIf
    ElseIf $sTmp >= 5 And $iD = 0 Then
        If $iNeg = 1 Then
            $sRet = _BigNum_Add($sRet, "-1")
        Else
            $sRet = _BigNum_Add($sRet, "1")
        EndIf
    Else
        If StringRight($sRet, 1) = "."  Then $sRet = StringTrimRight($sRet, 1)
    EndIf
    Return $sRet
EndFunc   ;==>_BigNum_Round



; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_Compare
; Description ...: Compares $sX $sY
; Syntax.........: _BigNum_Compare($sX, $sY)
; Parameters ....: $sX - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $sY - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
; Return values .: Success - Return:
;                  |0  - $sX and $sY are equal
;                  |1  - $sX is greater than $sY
;                  |-1 - $sX is less than $sY
;                  Failure - sets @error to 1 if $sX/$sY not valid StringNumber
; Author ........: Eukalyptus www.autoit.de
;
; ;===============================================================================================
Func _BigNum_Compare($sX, $sY)
    Local $iNeg = _BigNum_CheckNegative($sX, $sY)
    If $iNeg = 1 Then Return -1
    If $iNeg = 2 Then Return 1
    Local $iLnX = StringLen($sX), $iLnY = StringLen($sY)
    If $iNeg = 3 Then
        If $iLnX > $iLnY Then
            Return -1
        ElseIf $iLnX < $iLnY Then
            Return 1
        Else
            If $sX > $sY Then
                Return -1
            ElseIf $sX < $sY Then
                Return 1
            Else
                Return 0
            EndIf
        EndIf
    Else
        If $iLnX > $iLnY Then
            Return 1
        ElseIf $iLnX < $iLnY Then
            Return -1
        Else
            If $sX > $sY Then
                Return 1
            ElseIf $sX < $sY Then
                Return -1
            Else
                Return 0
            EndIf
        EndIf
    EndIf
EndFunc   ;==>_BigNum_Compare

Func _BigNum_Swap(ByRef $sX, ByRef $sY)
    Local $sSwap = $sX
    $sX = $sY
    $sY = $sSwap
    Return True
EndFunc   ;==>_BigNum_Swap




; #INTERNAL_USE_ONLY#============================================================================================================



#region Internal Functions
Func _BigNum_Div_DivisorGreater14($sX, $sY, ByRef $sM)
    $sM = "0"
    If $sY = "1"  Then Return $sX
    If $sX = "0"  Or $sY = "0"  Or $sX = "" Or $sY = "" Then Return "0"
    If $BigNum_Debug Then
        Local $BN_File = FileOpen(@ScriptDir & "\BigNum_Debug.txt", 2), $BN_X = StringLen($sX)
        FileWrite($BN_File, " " & $sX & " / " & $sY & " = " & @CRLF)
        FileWrite($BN_File, " " & _BigNum_DS($BN_X + StringLen($sY) + 3, "-") & @CRLF)
    EndIf
    Local $iLnY = StringLen($sY), $bRed = False
    Local $sRet = "", $sRem = StringLeft($sX, $iLnY), $sTmp = "", $sTm2 = "", $iCnt, $iLen = 1
    $sX = StringTrimLeft($sX, $iLnY)
    Do
        If _BigNum_DivComp($sRem, $sY) = -1 Then
            $sTmp = StringLeft($sX, 1)
            $sRem &= $sTmp
            $sX = StringTrimLeft($sX, 1)
            If StringLen($sTmp) > 0 Then $iLen += 1
        EndIf
        $sTmp = $sY
        $sTm2 = "0"
        If _BigNum_DivComp($sRem, $sY) >= 0 Then
            For $iCnt = 1 To 9
                $sTm2 = $sTmp
                $sTmp = _BigNum_DivAdd($sTmp, $sY)
                If _BigNum_DivComp($sRem, $sTmp) < 0 Then ExitLoop
            Next
        Else
            $iCnt = 0
        EndIf
        If $BigNum_Debug Then FileWrite($BN_File, _BigNum_DS($BN_X - StringLen($sX) - StringLen($sRem) + 1) & $sRem & _BigNum_DS($BN_X + 10 - $iLen - $iLnY) & StringFormat("%0" & String($iLen) & "u", $iCnt) & @CRLF)
        If StringLen($sX) = 0 Then $bRed = True
        $sM = $sRem
        $sRem = _BigNum_DivSub($sRem, $sTm2)
        If $iCnt > 0 Then $sM = $sRem
        $sRet &= StringFormat("%0" & String($iLen) & "u", $iCnt)
        $iTrm = $iLnY - StringLen($sRem)
        $sTmp = StringLeft($sX, $iTrm)
        $sX = StringTrimLeft($sX, $iTrm)
        $iLen = StringLen($sTmp)
        $sRem &= $sTmp
    Until $bRed
    $sM = StringRegExpReplace($sM, "^0+([^0]|0$)", "\1", 1)
    If $BigNum_Debug Then
        FileWrite($BN_File, " " & _BigNum_DS($BN_X + 9 + StringRegExp($sRet, "^0+([^0]|0$)", "\1", 1)) & _BigNum_DS(StringLen(StringRegExpReplace($sRet, "^0+([^0]|0$)", "\1", 1)), "-") & @CRLF)
        FileWrite($BN_File, " " & _BigNum_DS($BN_X + 9 + StringRegExp($sRet, "^0+([^0]|0$)", "\1", 1)) & StringRegExpReplace($sRet, "^0+([^0]|0$)", "\1", 1))
        FileClose($BN_File)
    EndIf
    Return StringRegExpReplace($sRet, "^0+([^0]|0$)", "\1", 1)
EndFunc   ;==>_BigNum_Div_DivisorGreater14

Func _BigNum_Div_DivisorMaxLen14($sX, $sY, ByRef $sM)
    $sM = "0"
    If $sY = "1"  Then Return $sX
    If $sX = "0"  Or $sY = "0"  Or $sX = "" Or $sY = "" Then Return "0"
    If $BigNum_Debug Then
        Local $BN_File = FileOpen(@ScriptDir & "\BigNum_Debug.txt", 2), $BN_X = StringLen($sX)
        FileWrite($BN_File, " " & $sX & " / " & $sY & " = " & @CRLF)
        FileWrite($BN_File, " " & _BigNum_DS($BN_X + StringLen($sY) + 3, "-") & @CRLF)
    EndIf
    Local $sRet = "", $iRem = StringLeft($sX, 15), $iTmp = 0, $iTrm = 6, $iLen
    $sX = StringTrimLeft($sX, 15)
    $iTmp = Floor($iRem / $sY)
    $sRet &= $iTmp
    If $BigNum_Debug Then FileWrite($BN_File, " " & $iRem & _BigNum_DS(StringLen($sX) + 10) & $iTmp & @CRLF)
    $iRem -= $iTmp * $sY
    While StringLen($sX) > 0
        $iTrm = 15 - StringLen($iRem)
        $iTmp = StringLeft($sX, $iTrm)
        $iLen = StringLen($iTmp)
        $iRem &= $iTmp
        $sX = StringTrimLeft($sX, $iTrm)
        $iTmp = Floor($iRem / $sY)
        $iTmp = StringRight("000000000000000" & $iTmp, $iLen)
        If $BigNum_Debug Then FileWrite($BN_File, _BigNum_DS($BN_X - StringLen($sX) + 1 - StringLen($iRem)) & $iRem & _BigNum_DS(StringLen($sX) + 10 + StringLen($sRet)) & $iTmp & @CRLF)
        $sRet &= $iTmp
        $iRem -= $iTmp * $sY
    WEnd
    $sM = String($iRem)
    If $BigNum_Debug Then
        FileWrite($BN_File, " " & _BigNum_DS($BN_X + 10) & _BigNum_DS(StringLen(StringRegExpReplace($sRet, "^0+([^0]|0$)", "\1", 1)), "-") & @CRLF)
        FileWrite($BN_File, " " & _BigNum_DS($BN_X + 10) & StringRegExpReplace($sRet, "^0+([^0]|0$)", "\1", 1))
        FileClose($BN_File)
    EndIf
    Return StringRegExpReplace($sRet, "^0+([^0]|0$)", "\1", 1)
EndFunc   ;==>_BigNum_Div_DivisorMaxLen14

Func _BigNum_DivComp($sX, $sY)
    $sX = StringRegExpReplace($sX, "^0+([^0]|0$)", "\1", 1)
    $sY = StringRegExpReplace($sY, "^0+([^0]|0$)", "\1", 1)
    Local $iLnX = StringLen($sX), $iLnY = StringLen($sY)
    If $iLnX < $iLnY Then
        Return -1
    ElseIf $iLnX > $iLnY Then
        Return 1
    Else
        If $sX < $sY Then
            Return -1
        ElseIf $sX > $sY Then
            Return 1
        Else
            Return 0
        EndIf
    EndIf
EndFunc   ;==>_BigNum_DivComp

Func _BigNum_DivAdd($sX, $sY)
    Local $iTmp = StringLen($sX), $iLen = StringLen($sY), $iCar = 0, $sRet = ""
    If $iLen < $iTmp Then $iLen = $iTmp
    For $i = 1 To $iLen Step 18
        $iTmp = Int(StringRight($sX, 18)) + Int(StringRight($sY, 18)) + $iCar
        $sX = StringTrimRight($sX, 18)
        $sY = StringTrimRight($sY, 18)
        If ($iTmp > 999999999999999999) Then
            $sRet = StringRight($iTmp, 18) & $sRet
            $iCar = 1
        Else
            $iTmp = StringRight("000000000000000000" & $iTmp, 18)
            $sRet = $iTmp & $sRet
            $iCar = 0
        EndIf
    Next
    $sRet = StringRegExpReplace($iCar & $sRet, "^0+([^0]|0$)", "\1", 1)
    Return $sRet
EndFunc   ;==>_BigNum_DivAdd

Func _BigNum_DivSub($sX, $sY)
    Local $iTmp = StringLen($sX), $iLen = StringLen($sY), $iCar = 0, $sRet = ""
    If $iLen < $iTmp Then $iLen = $iTmp
    For $i = 1 To $iLen Step 18
        $iTmp = Int(StringRight($sX, 18)) - Int(StringRight($sY, 18)) - $iCar
        $sX = StringTrimRight($sX, 18)
        $sY = StringTrimRight($sY, 18)
        If $iTmp < 0 Then
            $iTmp = 1000000000000000000 + $iTmp
            $iCar = 1
        Else
            $iCar = 0
        EndIf
        $sRet = StringRight("0000000000000000000" & $iTmp, 18) & $sRet
    Next
    $sRet = StringRegExpReplace($iCar & $sRet, "^0+([^0]|0$)", "\1", 1)
    Return $sRet
EndFunc   ;==>_BigNum_DivSub

Func _BigNum_IsValid($sX, $sY)
    If StringRegExp($sX, "[^0-9.-]") <> 0 Or StringRegExp($sY, "[^0-9.-]") <> 0 Then Return True
    Return False
EndFunc   ;==>_BigNum_IsValid

Func _BigNum_InsertDecimalSeparator($sX, $iDec, $iD = 18)
    If $iD = 0 And $iDec = 0 Then Return $sX
    Local $sRet = StringRegExpReplace(StringRight(StringFormat("%0" & String($iDec) & "u", "") & $sX, $iDec), "0+$", "\1", 1)
    $sX = StringTrimRight($sX, $iDec)
    If $sX = "" Then $sX = "0"
    $sRet = StringLeft($sRet, $iD)
    If $sRet = "" Or $sRet = "0"  Then Return $sX
    Return $sX & "." & $sRet
EndFunc   ;==>_BigNum_InsertDecimalSeparator

Func _BigNum_StringIsDecimal(ByRef $sX, ByRef $sY)
    If StringLeft($sX, 1) = "."  Then $sX = "0" & $sX
    If StringLeft($sY, 1) = "."  Then $sY = "0" & $sY
    Local $iPsX = StringInStr($sX, ".", 0, 1) - 1, $iPsY = StringInStr($sY, ".", 0, 1) - 1
    $sX = StringRegExpReplace($sX, "\D", "")
    $sY = StringRegExpReplace($sY, "\D", "")
    Local $iLnX = StringLen($sX), $iLnY = StringLen($sY)
    If $iPsX <= 0 Then $iPsX = $iLnX
    If $iPsY <= 0 Then $iPsY = $iLnY
    If $iLnX - $iPsX > $iLnY - $iPsY Then
        For $iCnt = $iLnY - $iPsY To $iLnX - $iPsX - 1
            $sY &= "0"
        Next
        Return $iLnX - $iPsX
    ElseIf $iLnX - $iPsX < $iLnY - $iPsY Then
        For $iCnt = $iLnX - $iPsX To $iLnY - $iPsY - 1
            $sX &= "0"
        Next
        Return $iLnY - $iPsY
    EndIf
    Return $iLnX - $iPsX
EndFunc   ;==>_BigNum_StringIsDecimal

Func _BigNum_CheckNegative(ByRef $sX, ByRef $sY)
    Local $bNgX = False, $bNgY = False
    While StringLeft($sX, 1) = "-"
        $bNgX = Not $bNgX
        $sX = StringTrimLeft($sX, 1)
    WEnd
    While StringLeft($sY, 1) = "-"
        $bNgY = Not $bNgY
        $sY = StringTrimLeft($sY, 1)
    WEnd
    $sX = StringRegExpReplace($sX, "^0+([^0]|0$)", "\1", 1)
    $sY = StringRegExpReplace($sY, "^0+([^0]|0$)", "\1", 1)
    If $sX = "" Then $sX = "0"
    If $sY = "" Then $sY = "0"
    If $bNgX = True And $bNgY = True Then
        Return 3
    ElseIf $bNgX = True And $bNgY = False Then
        Return 1
    ElseIf $bNgX = False And $bNgY = True Then
        Return 2
    Else
        Return 0
    EndIf
EndFunc   ;==>_BigNum_CheckNegative

Func _BigNum_DS($iC, $sS = " ")
    Local $sRet = "", $iCnt
    For $iCnt = 1 To $iC
        $sRet &= $sS
    Next
    Return $sRet
EndFunc   ;==>_BigNum_DS
#endregion Internal Functions

Mat

  • 2 weeks later...
Posted (edited)

hi mat,

i don't want to annoy you, but this _BigNum_Sum does not work. try it with small numbers. it does not respect algebraic rules (e.g. mul & div before add & sub), does not work with leading negative terms and floating points.

maybe i misunderstood your udf then you might want to explain it better, or you really have to improve your code.

cheers j.

edit: okay it works with integers and veery simple oprations, but this is way too weak and not reliable. i think, what you want to do, is really a complicated thing and will be a big project if you want to make it work.

Edited by jennico
Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Posted

I don't see how it cannot do it in the correct order... I can understand floats though, and thats a pretty simple thing to implement. You are right it is quite something to implement in full, but one day hopefully ;)

Mat

  • 1 month later...
Posted (edited)

Very nice UDF eukalyptus.

It helped me big time and I'd like to thank you and all the contributors for releasing it.

Sorry guys, but seems like I can't give reputation point yet.

EDIT:

_BigNum_Compare() function is not working properly.

Example:

_BigNum_Compare("1001.2996","16") = 1 ??

1 means that 16 > 1001.2996 ???

I didn't have the time to follow the function step by step, but as it seems to me it uses autoit

string comparison which is to compare strings and not numbers. Autoit string somparison makes simple

mistakes when comparing numbers like that:

1001.2996 ? 16

1 = 1 -> 0

0 < 6 -> return 1

1001.2996 < 16 .... for us not true, but for autoit it is

I created another algorithm (shown below) that works. As you can see it is not optimized,

I just don't have the time to optimize it right now, so I will paste it and try opitimizing

it later.

EDIT 2: Added some comments for better understanding of the algorithm.

EDIT 3: Fixed return values!

NumbersCompare(X,Y) returns

-1 - Y>X

1 - X>Y

EDIT 4: Added Algorithm No.2 which has slightly better performace.

Func NumbersCompareOBS($sX,$sY) ;algorithm No.1 
    Local $sXSign = NumberGetSign($sX)
    Local $sYSign = NumberGetSign($sY)
    If $sXSign == "-" And $sYSign == "" Then
        Return -1
    ElseIf $sXSign == "" And $sYSign == "-" Then
        Return 1
    ElseIf $sXSign == "-" And $sYSign == "-" Then
        Local $sTemp = $sX
        $sX = $sY
        $sY = $sTemp
    EndIf
    ;Separates the number in Integer and Fraction parts.
    Local $sXSplit = StringSplit($sX,".")
    Local $sYSplit = StringSplit($sY,".")
    ;Compares the Integer parts
    Local $iRet = NumbersCompareInt($sXSplit[1],$sYSplit[1])
    ; if the Integer parts are not equal returns the result
    If $iRet <> 0 Then
        Return $iRet
    EndIf
    ; if there are no Fraction parts then StringSplit will return only 1 string.
    If $sXSplit[0]*$sYSplit[0] == 1 Then
        Return 0
    EndIf
    ; it is already proved that the Integer parts are equal so the algorithm is
    ;checking if any of the numbers has fraction part
    ; if X has fraction part it means it is bigger than Y
    If $sXSplit[0] > $sYSplit[0] Then
        Return 1
    ;if Y has fraction part then it is bigger than X
    ElseIf $sXSplit[0] < $sYSplit[0] Then
        Return -1
    EndIf
    ;Compares the fraction parts
    Local $iRet = NumbersCompareInt($sXSplit[2],$sYSplit[2],1)
    ;returns the rezilt
    Return $iRet
EndFunc

Func NumbersCompareInt($sX,$sY,$bFracPart=0) ;This funrction compares integer only
    ;Splits the numbers in digits
    Local $sXSplit = StringSplit($sX,"")
    Local $sYSplit = StringSplit($sY,"")
    ;Compares the length of the Integers
    ;if $bFracPart is set then it just equalizes them
    If $sXSplit[0] > $sYSplit[0] Then
        If Not $bFracPart Then Return 1
        ReDim $sYSplit[$sXSplit[0]+1]
    ElseIf $sXSplit[0] < $sYSplit[0] Then
        If Not $bFracPart Then Return -1
        ReDim $sXSplit[$sYSplit[0]+1]
        $sXSplit[0] = $sYSplit[0]
    EndIf
    Local $i = 1
    While $i <= $sXSplit[0]
        ;Compares the numbers digit by digit starting from
        ;the most significant one
        If $sXSplit[$i] > $sYSplit[$i] Then
            Return 1
        ElseIf $sXSplit[$i] < $sYSplit[$i] Then
            Return -1
        EndIf
        $i+=1
    WEnd
    ;If it gets here the Integers are equal
    Return 0
EndFunc

Func NumberGetSign(ByRef $sNum)
    Local $sRet = StringLeft($sNum,1)
    If $sRet == "-" Then
        $sNum = StringTrimLeft($sNum,1)
        Return $sRet
    ElseIf $sRet == "+" Then
        $sNum = StringTrimLeft($sNum,1)
    EndIf
    Return ""
EndFunc

Func NumbersCompare($sX,$sY) ;Algorithm No.2
    Local $sXSign = NumberGetSign($sX)
    Local $sYSign = NumberGetSign($sY)
    ;Compare Signs
    If $sXSign == "-" And $sYSign == "" Then
        Return -1
    ElseIf $sXSign == "" And $sYSign == "-" Then
        Return 1
    ElseIf $sXSign == "-" And $sYSign == "-" Then
        Local $sTemp = $sX
        $sX = $sY
        $sY = $sTemp
    EndIf
    NumbersEqualizeLength($sX,$sY)
;~  MsgBox(-1,"",$sX & " " & $sY)
    Return StringCompare($sX,$sY)
EndFunc

Func NumberGetSign(ByRef $sNum)
    Local $sRet = StringLeft($sNum,1)
    If $sRet == "-" Then
        $sNum = StringTrimLeft($sNum,1)
        Return $sRet
    ElseIf $sRet == "+" Then
        $sNum = StringTrimLeft($sNum,1)
    EndIf
    Return ""
EndFunc

Func NumbersEqualizeLength(ByRef $sX,ByRef $sY)
    Local $iXDotPos = StringInStr($sX,".")
    Local $iYDotPos = StringInStr($sY,".")
    Local $iXLen = StringLen($sX)
    Local $iYLen = StringLen($sY)
    Local $iLeading,$iTrailing
    ;Calculation leading and trailing zeroes
    If $iXDotPos == 0 And $iYDotPos <> 0 Then
        $iLeading = $iXLen - ($iYDotPos-1)
        $iTrailing = -1*($iYLen - $iYDotPos)
        $sX &= "."
    ElseIf $iXDotPos <> 0 And $iYDotPos == 0 Then
        $iLeading = ($iXDotPos-1) - $iYLen
        $iTrailing = $iXLen - $iXDotPos
        $sY &= "."
    ElseIf $iXDotPos == 0 And $iYDotPos == 0 Then
        $iLeading = $iXLen - $iYLen
    Else
        $iLeading = $iXDotPos - $iYDotPos
        $iTrailing = ($iXLen - $iXDotPos) - ($iYLen-$iYDotPos)
    EndIf
    ;adding leading and trailing zeroes
    If $iLeading < 0 Then
        $sX = StringAddZeroes($sX,-1*$iLeading,0,0)
    ElseIf $iLeading > 0 Then
        $sY = StringAddZeroes($sY,$iLeading,0,0)
    EndIf
    If $iTrailing < 0 Then
        $sX = StringAddZeroes($sX,-1*$iTrailing,1,0)
    ElseIf $iTrailing > 0 Then
        $sY = StringAddZeroes($sY,$iTrailing,1,0)
    EndIf
EndFunc

Func StringAddZeroes($sString,$iCount,$bTrailing=0,$bToLength=1)
    ;$bToLength is set when the user wants to add the nescessary amount
    ;of zeroes to the string so it is with length $iCount (Default)
    If $bToLength Then
        $iCount -= StringLen($sString)
    EndIf
    Local $i = 0
    Local $s = ""
    While $i < $iCount
        $s &= "0"
        $i+=1
    WEnd
    ;$bTrailing is set when the user wants the zeroes to be added at the
    ;right side of the string. By defaut zeroes are added at the left side of the string
    If $bTrailing Then
        Return $sString & $s
    EndIf
    Return $s & $sString
EndFunc
Edited by eXirrah
  • 5 months later...
Posted

; test
#include <BigNum.au3>
MsgBox(0, '1', _BigNum_Div(0.000000000000000001, 21))
MsgBox(0, '2', _BigNum_Div('0.000000000000000001', '21'))
MsgBox(0, '3', _BigNum_Mul(0.000000000000000001, 21))
MsgBox(0, '4', _BigNum_Mul('0.000000000000000001', '21'))
MsgBox(0, '5', _BigNum_Div(4564564564564, 21))
MsgBox(0, '6', _BigNum_Div('4564564564564', '21'))

1-3 = Error... =0

4-6 = no problems

  • 3 weeks later...
  • 2 years later...
Posted

I recreated Mat´s _BigNum_Sum and called it _BigNum_Parse:

#include <BigNum.au3>
MsgBox(0, '???', _BigNum_Parse('-0.05 / (0.125 + 0.05) * 7 / 2'))
-0.9999997

#include <BigNum.au3>
$sText = _BigNum_Add ( '0.125', '0.05' )
$sText = _BigNum_Div ( '-0.05', $sText, 100 )
$sText = _BigNum_Mul ( $sText, '7' )
$sText = _BigNum_Div ( $sText, '2', 100 )
MsgBox(0, '???', $sText)
-0.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999

Can you specify the precision of calculations for the function _BigNum_Parse!?

  • 2 months later...
Posted

I'm porting over something from java, which uses their BugNum functions. I need a way to do a XOR with BigNum variables. AutoIT's BitXOR won't work. Does anyone have any ideas?

Gerard J. Pinzonegpinzone AT yahoo.com
  • 4 months later...
Posted

Not sure if anybody uses this, but I have rewritten the Parse function and fixed the order of operations and it runs faster as well. It is in the GMP UDF located that you could easily copy and modify for this UDF.

  • 8 months later...
  • 10 years later...
Posted (edited)

Very like this UDF.

 

Share some math function.

 

Func _BigNum_EXP($a)
$Euler_number = "2.71828182845904523536028747135266249"
Return _BigNum_FastPow($Euler_number, $a)
EndFunc

Func _BigNum_FastPow($a, $b)
$check = StringSplit($b,".")
if $check[0] = "1" Then
    Local $ans = 1
    While $b > "0"
        If _BigNum_Mod($b, 2) = "1" Then
            $ans = _BigNum_Mul($ans, $a)
            $b = _BigNum_Sub($b, "1")
        Else
            $a = _BigNum_Mul($a, $a)
            $b = _BigNum_Div($b, "2", 0)
        EndIf
    WEnd
    Return StringLeft($ans,32)
Else
$Denominator = "1"&_StringRepeat("0", StringLen($check[2]))
$Numerator = _BigNum_add($check[2] ,_BigNum_mul(String($check[1]),$Denominator))
While 1
    $GCD = _BigNum_GCD($Denominator, $Numerator)
        if $GCD <> 1 Then
            $Denominator/= $GCD
            $Numerator/= $GCD
        Else
            ExitLoop
        EndIf
WEnd
$a = _BigNum_n_Root($a,$Denominator,"35")
$b = $Numerator
    Local $ans = 1
    While $b > "0"
        If _BigNum_Mod($b, 2) = "1" Then
            $ans = _BigNum_Mul($ans, $a)
            $b = _BigNum_Sub($b, "1")
        Else
            $a = _BigNum_Mul($a, $a)
            $b = _BigNum_Div($b, "2", 0)
        EndIf
    WEnd
    Return $ans

EndIf
EndFunc

Func _BigNum_LCM($a, $b)
    Local $result = 0, $c = $a , $d = $b
    While 1
        $result = _BigNum_Mod($a, $b)
        If $result <> 0 Then
            $a = $b
            $b = $result
        Else
            ExitLoop
        EndIf
    WEnd
    Return _BigNum_Mul(_BigNum_Div($c, $b), $d)
EndFunc

Func _BigNum_GCD($a, $b)
    $result = 0
    Local $array[0][2], $cc = 1
    While 1
        $result = _BigNum_Mod($a, $b)
        If $result <> 0 Then
            $a = $b
            $b = $result
        Else
            ExitLoop
        EndIf
    WEnd
    Return $b
EndFunc

Func _BigNum_PowerMod($n, $e, $k)
    Local $res = "1"
    While $e > "0"
        While _BigNum_Mod($e, 2) = "0"
            $n = _BigNum_Mod(_BigNum_Mul($n, $n), $k)
            $e = _BigNum_Div($e, "2", 0)
        WEnd
        $res = _BigNum_Mod(_BigNum_Mul($res, $n), $k)
        $e = _BigNum_Sub($e, "1")
    WEnd
    Return $res
EndFunc

Func _BigHex_ToBase_Fast($sDecimal, $iBase)
    Local $vDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!""#$%&'()*+,-./:;<=>?@[\]^_`{|}~"
    If $iBase > StringLen($vDigits) Then SetError(1, 0, 0)
    $vDigits = StringSplit($vDigits, '', 2)
    Local $sResult = 0
    For $i = 1 To StringLen($sDecimal)
        $nn = _ArraySearch($vDigits, StringMid($sDecimal, $i, 1))
        $sResult = _BigNum_Add(_BigNum_Mul($iBase, $sResult), $nn)
    Next
    Return $sResult
EndFunc

Func _BigNum_inverse($a, $b)
    $result = 0
    Local $array[0][2], $cc = 1
    While 1
        If Mod($cc, 2) = 1 Then
            _ArrayAdd($array, $b & "|" & $a)
        Else
            _ArrayAdd($array, $a & "|" & $b)
        EndIf
        $cc += 1
        $result = _BigNum_Mod($a, $b)
        If $result <> 0 Then
            $a = $b
            $b = $result
        Else
            ExitLoop
        EndIf
    WEnd
    $cc = 1
    Local $d = "", $k = ""
    For $i = UBound($array) - 1 To 0 Step -1

        If $cc = 1 Then
            If $array[$i][0] = 1 Then
                $d = 1
            Else
                $d = 1
                $k = $array[$i][0] - 1
            EndIf
        EndIf

        If $cc <> 1 Then
            If $k = "" Then
                $k = _BigNum_Div((_BigNum_Sub(_BigNum_Mul($array[$i][0], $d), 1)), $array[$i][1])
            Else
                $d = _BigNum_Div((_BigNum_Add(_BigNum_Mul($array[$i][1], $k), 1)), $array[$i][0])
                $k = ""
            EndIf
        EndIf
        $cc += 1
    Next
    Return $d
EndFunc

 

Edited by konya
Posted (edited)

Share fast power module usage table value.

 

1._BigNum_Calculate_Last_E($n, $e, $k) get last e value.

2._BigNum_PowerMod_Specified_ciphertext($c, $Last_c, $mod)

 

Func _BigNum_Calculate_Last_E($c, $e, $mod)
    if $mod = 1 then Return 0
    $e = _BigNum_Mod($e,_BigNum_Sub($mod,"1"))
    $c =  _BigNum_Mod($c, $mod)
    While $e > "0"
        While _BigNum_Mod($e, 2) = "0"
            $c = _BigNum_Mod(_BigNum_Mul($c, $c), $mod)
            $e = _BigNum_Div($e, "2", 0)
        WEnd
        $e = _BigNum_Sub($e, "1")
    WEnd
    Return $c
EndFunc


Func _BigNum_PowerMod_Specified_ciphertext($c, $Last_c, $mod)

        $res = _BigNum_Mod($c, $mod)
        $res = _BigNum_Mod(_BigNum_Mul($res, $Last_c), $mod)

    ConsoleWrite("Result = " & $res & @CRLF )
    Return $res
EndFunc

 

 

Edited by konya

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...