فهرست منبع

Adding fast exponentiation

Nathan Fallet 4 سال پیش
والد
کامیت
bdf22eba4e
2فایلهای تغییر یافته به همراه36 افزوده شده و 2 حذف شده
  1. 29 1
      Sources/CryptoSwift/GiantUInt.swift
  2. 7 1
      Tests/CryptoSwiftTests/GiantUIntTests.swift

+ 29 - 1
Sources/CryptoSwift/GiantUInt.swift

@@ -13,12 +13,21 @@
 //  - This notice may not be removed or altered from any source or binary distribution.
 //  - This notice may not be removed or altered from any source or binary distribution.
 //
 //
 
 
+precedencegroup PowerPrecedence { higherThan: MultiplicationPrecedence }
+infix operator ^^ : PowerPrecedence
+
 struct GiantUInt: Equatable {
 struct GiantUInt: Equatable {
   
   
   let bytes: Array<UInt8>
   let bytes: Array<UInt8>
   
   
   init(_ raw: Array<UInt8>) {
   init(_ raw: Array<UInt8>) {
-    self.bytes = raw
+    var bytes = raw
+    
+    while bytes.last == 0 {
+      bytes.removeLast()
+    }
+    
+    self.bytes = bytes
   }
   }
     
     
   // Equatable
   // Equatable
@@ -71,4 +80,23 @@ struct GiantUInt: Equatable {
     return sum.reduce(GiantUInt([]), +)
     return sum.reduce(GiantUInt([]), +)
   }
   }
   
   
+  static func ^^ (rhs: GiantUInt, lhs: GiantUInt) -> GiantUInt {
+    let count = lhs.bytes.count
+    var result = GiantUInt([1])
+    
+    for iByte in 0 ..< count {
+      let byte = lhs.bytes[iByte]
+      for i in 0 ..< 8 {
+        if iByte != count - 1 || byte >> i > 0 {
+          result = result * result
+          if (byte >> i) & 1 == 1 {
+            result = result * rhs
+          }
+        }
+      }
+    }
+    
+    return result
+  }
+  
 }
 }

+ 7 - 1
Tests/CryptoSwiftTests/GiantUIntTests.swift

@@ -41,13 +41,19 @@ final class GiantUIntTests: XCTestCase {
     XCTAssertEqual(c, GiantUInt([64, 28, 121, 157]), "multiplication with double retenue failed")
     XCTAssertEqual(c, GiantUInt([64, 28, 121, 157]), "multiplication with double retenue failed")
   }
   }
   
   
+  func testExponentiation() {
+    let a = GiantUInt([3]) ^^ GiantUInt([7])
+    XCTAssertEqual(a, GiantUInt([139, 8]), "simple exponentiation failed")
+  }
+  
 }
 }
 
 
 extension GiantUIntTests {
 extension GiantUIntTests {
   static func allTests() -> [(String, (GiantUIntTests) -> () -> Void)] {
   static func allTests() -> [(String, (GiantUIntTests) -> () -> Void)] {
     let tests = [
     let tests = [
       ("testAddition", testAddition),
       ("testAddition", testAddition),
-      ("testMultiplication", testMultiplication)
+      ("testMultiplication", testMultiplication),
+      ("testExponentiation", testExponentiation)
     ]
     ]
 
 
     return tests
     return tests