Sfoglia il codice sorgente

Added BigNum (very fist version).

Damian Kołakowski 9 anni fa
parent
commit
86b5031913
2 ha cambiato i file con 223 aggiunte e 0 eliminazioni
  1. 215 0
      Sources/Swifter/BigNum.swift
  2. 8 0
      XCode/Swifter.xcodeproj/project.pbxproj

+ 215 - 0
Sources/Swifter/BigNum.swift

@@ -0,0 +1,215 @@
+//
+//  BigNum.swift
+//  Swifter
+//
+//  Created by Damian Kolakowski on 08/08/16.
+//
+
+import Foundation
+
+public struct BigNum {
+    
+    // 
+    // Big Integer
+    //
+    // TODO/Improvments
+    //  - add init(...) for string literal
+    //  - switch to 'long division'
+    //  - fix '+' and '-' operators for negative numbers
+    
+    internal var digits = [UInt8]()
+    internal var signum = 0
+    
+    internal init(_ digits: [UInt8]) {
+        self.digits.append(contentsOf: digits)
+        self.signum = digits.isEmpty ? 0 : 1
+    }
+    
+    public init(_ text: String) {
+        self.signum = text.unicodeScalars.isEmpty ? 0 : 1
+        for c in text.unicodeScalars.reversed() {
+            switch c.value {
+            case 48...57:
+                self.digits.append(UInt8(c.value-48))
+            case 45:
+                self.signum = -1
+            default: break
+            }
+        }
+    }
+}
+
+infix operator == { }
+public func == (_ left: BigNum, right: BigNum) -> Bool {
+    return (left.digits == right.digits) && (left.signum == right.signum)
+}
+
+infix operator + { }
+public func + (_ left: BigNum, _ right: BigNum) -> BigNum {
+    var result = [UInt8]()
+    var carry: UInt8 = 0
+    for i in 0..<max(left.digits.count, right.digits.count) {
+        let leftDigit = (i < left.digits.count) ? left.digits[i] : 0
+        let rightDigit = (i < right.digits.count) ? right.digits[i] : 0
+        let sum = (leftDigit + rightDigit) + carry
+        if sum > 9 {
+            carry = 1
+            result.append(sum - 10)
+        } else {
+            carry = 0
+            result.append(sum)
+        }
+    }
+    if carry != 0 {
+        result.append(carry)
+    }
+    return BigNum(result)
+}
+
+infix operator - { }
+public func - (_ left: BigNum, _ right: BigNum) -> BigNum {
+    var result = [UInt8]()
+    var carry: Int = 0
+    for i in 0..<max(left.digits.count, right.digits.count) {
+        let leftDigit = (i < left.digits.count) ? left.digits[i] : 0
+        let rightDigit = (i < right.digits.count) ? right.digits[i] : 0
+        let diff = (Int(leftDigit) - Int(rightDigit)) + carry
+        if diff < 0 {
+            carry = -1
+            result.append(UInt8(10+diff))
+        } else {
+            carry = 0
+            result.append(UInt8(diff))
+        }
+    }
+    while let last = result.last, last == 0 { result.removeLast() }
+    return BigNum(result)
+}
+
+infix operator * { }
+public func * (_ left: BigNum, _ right: BigNum) -> BigNum {
+    var mulResults = Array<[UInt8]>()
+    for i in 0..<left.digits.count {
+        var row = [UInt8](repeating: 0, count: i)
+        var carry: UInt8 = 0
+        for j in 0..<right.digits.count {
+            let mul = (left.digits[i] * right.digits[j]) + carry
+            if mul > 9 {
+                carry = mul / 10
+                row.append(mul % 10)
+            } else {
+                carry = 0
+                row.append(mul)
+            }
+        }
+        if carry != 0 {
+            row.append(carry % 10)
+            if carry > 9 { row.append(carry / 10) }
+        }
+        mulResults.append(row)
+    }
+    var sum = mulResults.reduce(BigNum([0])) { $0.partialResult + BigNum($0.1) }
+    sum.signum = left.signum * right.signum
+    return sum
+}
+
+infix operator / { }
+public func / (_ left: BigNum, _ right: BigNum) -> BigNum {
+    if left < right {
+        return BigNum([0])
+    }
+    var quotient = BigNum([0])
+    var remainder = left
+    
+    while remainder >= right {
+        quotient = quotient + BigNum([1])
+        remainder = remainder - right
+    }
+    
+    quotient.signum = left.signum * right.signum
+    
+    return quotient
+}
+
+infix operator % { }
+public func % (_ left: BigNum, _ right: BigNum) -> BigNum {
+    if left < right {
+        return left
+    }
+    var quotient = BigNum([0])
+    var remainder = left
+    
+    while remainder >= right {
+        quotient = quotient + BigNum([1])
+        remainder = remainder - right
+    }
+    return remainder
+}
+
+infix operator > { }
+public func > (_ left: BigNum, _ right: BigNum) -> Bool {
+    if left.signum != right.signum {
+        return left.signum > right.signum
+    }
+    if left.digits.count != right.digits.count {
+        if left.signum < 0 {
+            return left.digits.count < right.digits.count
+        } else {
+            return left.digits.count > right.digits.count
+        }
+    }
+    for i in 0..<left.digits.count {
+        if left.digits[i] == right.digits[i] {
+            continue
+        }
+        if left.signum < 0 {
+            if left.digits[i] < right.digits[i] {
+                return true
+            }
+        } else {
+            if left.digits[i] > right.digits[i] {
+                return true
+            }
+        }
+    }
+    return false
+}
+
+infix operator < { }
+public func < (_ left: BigNum, _ right: BigNum) -> Bool {
+    if left.signum != right.signum {
+        return left.signum < right.signum
+    }
+    if right.digits.count != left.digits.count {
+        if left.signum < 0 {
+            return left.digits.count > right.digits.count
+        } else {
+            return left.digits.count < right.digits.count
+        }
+    }
+    for i in 0..<left.digits.count {
+        if left.digits[i] == right.digits[i] {
+            continue
+        }
+        if left.signum < 0 {
+            if right.digits[i] < left.digits[i] {
+                return true
+            }
+        } else {
+            if right.digits[i] > left.digits[i] {
+                return true
+            }
+        }
+    }
+    return false
+}
+
+infix operator >= { }
+public func >= (_ left: BigNum, _ right: BigNum) -> Bool {
+    return (left == right) || (left > right)
+}
+
+infix operator <= { }
+public func <= (_ left: BigNum, _ right: BigNum) -> Bool {
+    return (left == right) || (left < right)
+}

+ 8 - 0
XCode/Swifter.xcodeproj/project.pbxproj

@@ -15,6 +15,9 @@
 		7C11459B1D527545000DB965 /* AES128.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C1145981D527545000DB965 /* AES128.swift */; };
 		7C13B57C1C7B069500556443 /* SwifterTestsSQLite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C13B57B1C7B069500556443 /* SwifterTestsSQLite.swift */; };
 		7C13B57D1C7B069500556443 /* SwifterTestsSQLite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C13B57B1C7B069500556443 /* SwifterTestsSQLite.swift */; };
+		7C1CA77F1D59BC7100FD38A0 /* BigNum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C1CA77B1D589C2200FD38A0 /* BigNum.swift */; };
+		7C1CA7801D59BC7100FD38A0 /* BigNum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C1CA77B1D589C2200FD38A0 /* BigNum.swift */; };
+		7C1CA7811D59BC7200FD38A0 /* BigNum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C1CA77B1D589C2200FD38A0 /* BigNum.swift */; };
 		7C3195FB1CC2C68F00DF5406 /* sqlite.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C3195E31CC2C68F00DF5406 /* sqlite.h */; };
 		7C3195FC1CC2C68F00DF5406 /* sqlite.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C3195E31CC2C68F00DF5406 /* sqlite.h */; };
 		7C3195FD1CC2C68F00DF5406 /* sqlite.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C3195E31CC2C68F00DF5406 /* sqlite.h */; };
@@ -204,6 +207,7 @@
 		7AE8940C1C05151100A29F63 /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; };
 		7C1145981D527545000DB965 /* AES128.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AES128.swift; sourceTree = "<group>"; };
 		7C13B57B1C7B069500556443 /* SwifterTestsSQLite.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsSQLite.swift; sourceTree = "<group>"; };
+		7C1CA77B1D589C2200FD38A0 /* BigNum.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BigNum.swift; sourceTree = "<group>"; };
 		7C2C85901D50D83D00B32145 /* JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = "<group>"; };
 		7C3195E31CC2C68F00DF5406 /* sqlite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqlite.h; sourceTree = "<group>"; };
 		7C3195E41CC2C68F00DF5406 /* module.map */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.map; sourceTree = "<group>"; };
@@ -406,6 +410,7 @@
 				7C5F78F11D54C99200C514AA /* RC4.swift */,
 				7C5F78FB1D5520B000C514AA /* RSA.swift */,
 				7C5F790A1D56281200C514AA /* Errno.swift */,
+				7C1CA77B1D589C2200FD38A0 /* BigNum.swift */,
 			);
 			path = Swifter;
 			sourceTree = "<group>";
@@ -861,6 +866,7 @@
 				7C3196161CC2C68F00DF5406 /* HttpRequest.swift in Sources */,
 				7C5F79071D5627EE00C514AA /* Socket+Server.swift in Sources */,
 				7C3196221CC2C68F00DF5406 /* HttpServerIO.swift in Sources */,
+				7C1CA77F1D59BC7100FD38A0 /* BigNum.swift in Sources */,
 				7C31960A1CC2C68F00DF5406 /* Files.swift in Sources */,
 				7CB923CC1D50F11700899E2A /* JSON.swift in Sources */,
 				7C5F790B1D56281200C514AA /* Errno.swift in Sources */,
@@ -895,6 +901,7 @@
 				7C3196171CC2C68F00DF5406 /* HttpRequest.swift in Sources */,
 				7C5F79081D5627EE00C514AA /* Socket+Server.swift in Sources */,
 				7C3196231CC2C68F00DF5406 /* HttpServerIO.swift in Sources */,
+				7C1CA7801D59BC7100FD38A0 /* BigNum.swift in Sources */,
 				7C31960B1CC2C68F00DF5406 /* Files.swift in Sources */,
 				7CB923CD1D50F11800899E2A /* JSON.swift in Sources */,
 				7C5F790C1D56281200C514AA /* Errno.swift in Sources */,
@@ -955,6 +962,7 @@
 				7C3196181CC2C68F00DF5406 /* HttpRequest.swift in Sources */,
 				7C5F79091D5627EE00C514AA /* Socket+Server.swift in Sources */,
 				7C3196241CC2C68F00DF5406 /* HttpServerIO.swift in Sources */,
+				7C1CA7811D59BC7200FD38A0 /* BigNum.swift in Sources */,
 				7C31960C1CC2C68F00DF5406 /* Files.swift in Sources */,
 				7CB923CE1D50F11800899E2A /* JSON.swift in Sources */,
 				7C5F790D1D56281200C514AA /* Errno.swift in Sources */,