Explorar o código

Added 'Equatable' and 'Comparable' to BigNum.
Added long division.

Damian Kołakowski %!s(int64=9) %!d(string=hai) anos
pai
achega
fcafe32c21

+ 74 - 62
Sources/Swifter/BigNum.swift

@@ -2,27 +2,32 @@
 //  BigNum.swift
 //  Swifter
 //
-//  Created by Damian Kolakowski on 08/08/16.
+//  Copyright © 2016 Damian Kołakowski. All rights reserved.
 //
 
 import Foundation
 
-public struct BigNum {
+public struct BigNum: Equatable, Comparable {
     
-    // 
+    //
     // Big Integer
     //
     // TODO/Improvments
     //  - add init(...) for string literal
-    //  - switch to 'long division'
+    //  - add powmod operation
     //  - fix '+' and '-' operators for negative numbers
     
     internal var digits = [UInt8]()
     internal var signum = 0
     
-    internal init(_ digits: [UInt8]) {
+    internal init(_ digits: [UInt8], _ signum: Int) {
+        self.digits.append(contentsOf: digits)
+        self.signum = signum
+    }
+    
+    internal init(_ digits: ArraySlice<UInt8>, _ signum: Int) {
         self.digits.append(contentsOf: digits)
-        self.signum = digits.isEmpty ? 0 : 1
+        self.signum = signum
     }
     
     public init(_ text: String) {
@@ -44,16 +49,20 @@ public func == (_ left: BigNum, right: BigNum) -> Bool {
     return (left.digits == right.digits) && (left.signum == right.signum)
 }
 
+infix operator != { }
+public func != (_ left: BigNum, right: BigNum) -> Bool {
+    return !(left.digits == right.digits)
+}
+
 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
+        let sum = (((i < left.digits.count) ? left.digits[i] : 0) +
+            ((i < right.digits.count) ? right.digits[i] : 0)) + carry
+        if sum >= 10 {
+            carry = sum / 10
             result.append(sum - 10)
         } else {
             carry = 0
@@ -63,7 +72,7 @@ public func + (_ left: BigNum, _ right: BigNum) -> BigNum {
     if carry != 0 {
         result.append(carry)
     }
-    return BigNum(result)
+    return BigNum(result, 1)
 }
 
 infix operator - { }
@@ -71,23 +80,25 @@ 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 {
+        let sub = (Int((i < left.digits.count) ? left.digits[i] : 0) -
+            Int((i < right.digits.count) ? right.digits[i] : 0)) + carry
+        if sub < 0 {
             carry = -1
-            result.append(UInt8(10+diff))
+            result.append(UInt8(10+sub))
         } else {
             carry = 0
-            result.append(UInt8(diff))
+            result.append(UInt8(sub))
         }
     }
     while let last = result.last, last == 0 { result.removeLast() }
-    return BigNum(result)
+    return BigNum(result, 1)
 }
 
 infix operator * { }
 public func * (_ left: BigNum, _ right: BigNum) -> BigNum {
+    if (left.signum == 0) || (right.signum == 0) {
+        return BigNum([], 0)
+    }
     var mulResults = Array<[UInt8]>()
     for i in 0..<left.digits.count {
         var row = [UInt8](repeating: 0, count: i)
@@ -108,42 +119,53 @@ public func * (_ left: BigNum, _ right: BigNum) -> BigNum {
         }
         mulResults.append(row)
     }
-    var sum = mulResults.reduce(BigNum([0])) { $0.partialResult + BigNum($0.1) }
+    var sum = mulResults.reduce(BigNum([0], 1)) { $0.partialResult + BigNum($0.1, 1) }
     sum.signum = left.signum * right.signum
     return sum
 }
 
 infix operator / { }
-public func / (_ left: BigNum, _ right: BigNum) -> BigNum {
+public func / (_ left: BigNum, _ right: BigNum) -> (quotient: BigNum, reminder: BigNum) {
+    
     if left < right {
-        return BigNum([0])
+        return (BigNum([0], 0), left)
     }
-    var quotient = BigNum([0])
-    var remainder = left
     
-    while remainder >= right {
-        quotient = quotient + BigNum([1])
-        remainder = remainder - right
+    if left.digits == right.digits {
+        return (BigNum([1], left.signum * right.signum), BigNum([0], 0))
     }
     
-    quotient.signum = left.signum * right.signum
+    var shiftIndex = left.digits.count - right.digits.count
+    var tmp = BigNum(left.digits[shiftIndex..<left.digits.count], 1)
     
-    return quotient
+    while tmp < right {
+        shiftIndex = shiftIndex - 1
+        tmp = BigNum(left.digits[shiftIndex..<left.digits.count], 1)
+    }
+    
+    var quotient = [UInt8]()
+    var rest = BigNum([0], 0)
+    
+    while shiftIndex >= 0 {
+        var i: UInt8 = 1
+        while (right * BigNum([i], 1)) < tmp {
+            i = i + 1
+        }
+        quotient.append(i-1)
+        rest = tmp - (right * BigNum([i-1], 1))
+        shiftIndex = shiftIndex - 1
+        if shiftIndex < 0 {
+            break
+        }
+        tmp = BigNum([left.digits[shiftIndex]] + rest.digits, 1)
+    }
+    
+    return (BigNum(quotient.reversed(), left.signum * right.signum), rest)
 }
 
 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
+    return (left / right).reminder
 }
 
 infix operator > { }
@@ -158,17 +180,12 @@ public func > (_ left: BigNum, _ right: BigNum) -> Bool {
             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
+    for i in (0..<left.digits.count).reversed() {
+        if left.digits[i] != right.digits[i] {
+            if left.signum < 0 {
+                return left.digits[i] < right.digits[i]
+            } else {
+                return left.digits[i] > right.digits[i]
             }
         }
     }
@@ -187,17 +204,12 @@ public func < (_ left: BigNum, _ right: BigNum) -> Bool {
             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
+    for i in (0..<left.digits.count).reversed() {
+        if left.digits[i] != right.digits[i] {
+            if left.signum < 0 {
+                return right.digits[i] < left.digits[i]
+            } else {
+                return right.digits[i] > left.digits[i]
             }
         }
     }

+ 0 - 1
Sources/Swifter/Errno.swift

@@ -2,7 +2,6 @@
 //  Errno.swift
 //  Swifter
 //
-//  Created by Damian Kolakowski on 13/07/16.
 //  Copyright © 2016 Damian Kołakowski. All rights reserved.
 //
 

+ 6 - 6
XCode/Swifter.xcodeproj/project.pbxproj

@@ -15,9 +15,6 @@
 		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 */; };
@@ -140,6 +137,9 @@
 		7CDAB8131BE2A1D400C8A977 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7CDAB80D1BE2A1D400C8A977 /* Main.storyboard */; };
 		7CDAB8141BE2A1D400C8A977 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7CDAB80F1BE2A1D400C8A977 /* Images.xcassets */; };
 		7CDAB8161BE2A1D400C8A977 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CDAB8111BE2A1D400C8A977 /* ViewController.swift */; };
+		7CE0B9E31D5AFF560070D292 /* BigNum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C1CA77B1D589C2200FD38A0 /* BigNum.swift */; };
+		7CE0B9E41D5AFF570070D292 /* BigNum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C1CA77B1D589C2200FD38A0 /* BigNum.swift */; };
+		7CE0B9E51D5AFF570070D292 /* BigNum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C1CA77B1D589C2200FD38A0 /* BigNum.swift */; };
 		98630C071A1C9A9D00478D08 /* login.html in Resources */ = {isa = PBXBuildFile; fileRef = 98630C061A1C9A9D00478D08 /* login.html */; };
 /* End PBXBuildFile section */
 
@@ -866,7 +866,7 @@
 				7C3196161CC2C68F00DF5406 /* HttpRequest.swift in Sources */,
 				7C5F79071D5627EE00C514AA /* Socket+Server.swift in Sources */,
 				7C3196221CC2C68F00DF5406 /* HttpServerIO.swift in Sources */,
-				7C1CA77F1D59BC7100FD38A0 /* BigNum.swift in Sources */,
+				7CE0B9E31D5AFF560070D292 /* BigNum.swift in Sources */,
 				7C31960A1CC2C68F00DF5406 /* Files.swift in Sources */,
 				7CB923CC1D50F11700899E2A /* JSON.swift in Sources */,
 				7C5F790B1D56281200C514AA /* Errno.swift in Sources */,
@@ -901,7 +901,7 @@
 				7C3196171CC2C68F00DF5406 /* HttpRequest.swift in Sources */,
 				7C5F79081D5627EE00C514AA /* Socket+Server.swift in Sources */,
 				7C3196231CC2C68F00DF5406 /* HttpServerIO.swift in Sources */,
-				7C1CA7801D59BC7100FD38A0 /* BigNum.swift in Sources */,
+				7CE0B9E41D5AFF570070D292 /* BigNum.swift in Sources */,
 				7C31960B1CC2C68F00DF5406 /* Files.swift in Sources */,
 				7CB923CD1D50F11800899E2A /* JSON.swift in Sources */,
 				7C5F790C1D56281200C514AA /* Errno.swift in Sources */,
@@ -962,7 +962,7 @@
 				7C3196181CC2C68F00DF5406 /* HttpRequest.swift in Sources */,
 				7C5F79091D5627EE00C514AA /* Socket+Server.swift in Sources */,
 				7C3196241CC2C68F00DF5406 /* HttpServerIO.swift in Sources */,
-				7C1CA7811D59BC7200FD38A0 /* BigNum.swift in Sources */,
+				7CE0B9E51D5AFF570070D292 /* BigNum.swift in Sources */,
 				7C31960C1CC2C68F00DF5406 /* Files.swift in Sources */,
 				7CB923CE1D50F11800899E2A /* JSON.swift in Sources */,
 				7C5F790D1D56281200C514AA /* Errno.swift in Sources */,