Integer.st
changeset 25215 9bbaac312afe
parent 25149 663805b3e3ef
--- a/Integer.st	Wed Jan 29 18:17:34 2020 +0100
+++ b/Integer.st	Wed Jan 29 18:22:17 2020 +0100
@@ -934,6 +934,8 @@
     "Modified: / 15.11.1999 / 20:35:20 / cg"
 ! !
 
+
+
 !Integer class methodsFor:'class initialization'!
 
 initialize
@@ -990,6 +992,7 @@
     "Modified: 18.7.1996 / 12:26:38 / cg"
 ! !
 
+
 !Integer class methodsFor:'prime numbers'!
 
 flushPrimeCache
@@ -1365,6 +1368,7 @@
     ^ self == Integer
 ! !
 
+
 !Integer methodsFor:'Compatibility-Dolphin'!
 
 highWord
@@ -1650,6 +1654,7 @@
 ! !
 
 
+
 !Integer methodsFor:'bcd conversion'!
 
 decodeFromBCD
@@ -2432,6 +2437,16 @@
     "Modified (comment): / 20-06-2018 / 14:47:55 / Claus Gittinger"
 !
 
+bitXored:anInteger
+    "subclasses may redefine this to possibly change the receiver
+     and return an possibly unnormalized Integer.
+     Use to speed up cryptographic computations."
+
+    ^ self bitXor:anInteger
+
+    "Created: / 29-01-2020 / 17:54:19 / Stefan Vogel"
+!
+
 changeMask:mask to:aBooleanOrNumber
     "return a new number where the specified mask-bit is on or off,
      depending on aBooleanOrNumber.
@@ -2639,15 +2654,15 @@
              defined in the language standard (since the implementation
              is free to choose any internal representation for integers)"
 
-    |i "{Class: SmallInteger}"|
+    |i "{Class: SmallInteger}" 
+     d "{Class: SmallInteger}"|
 
     i := index - 1.
-    i < 0 ifTrue:[
-        ^ SubscriptOutOfBoundsError
-                raiseRequestWith:index
-                errorString:'index out of bounds'
+    d := self digitAt:(i // 8 + 1).     "/ #digitAt: raises an error if i < 0
+    d == 0 ifTrue:[
+        ^ 0.
     ].
-    ^ (self digitAt:(i // 8 + 1)) bitAt:(i \\ 8 + 1)
+    ^ d bitAt:(i \\ 8 + 1)
 
     "
      1 bitAt:1                     => 1
@@ -2655,6 +2670,7 @@
      1 bitAt:0                     index error
      2r1000100010001000100010001000100010001000100010001000 bitAt:48 => 1
      2r1000100010001000100010001000100010001000100010001000 bitAt:47 => 0
+     2r1000000000000000000000000000000000000000000000000000 bitAt:1  => 0
 
      (1 bitShift:1000) bitAt:1000  => 0
      (1 bitShift:1000) bitAt:1001  => 1
@@ -2673,6 +2689,8 @@
      (1 bitShift:64) bitAt:65
      (1 bitShift:64) bitAt:66
     "
+
+    "Modified (comment): / 29-01-2020 / 18:21:17 / Stefan Vogel"
 !
 
 bitAt:anIntegerIndex put:aBit
@@ -4303,6 +4321,61 @@
     "Modified: / 25.10.1997 / 16:08:45 / cg"
 !
 
+gfMul2_128:factorIn
+    "Galoise multiplication inf GF(2^128). This is defined by 1 + a + a^2 + a^7 + a^128.
+     Candidate for faste implementation - especially for Intel processors:
+        https://www.intel.cn/content/dam/www/public/us/en/documents/white-papers/carry-less-multiplication-instruction-in-gcm-mode-paper.pdf"
+
+    |factor result|
+
+    factor := factorIn.
+    result := 0.
+
+    128 to:1 by:-1 do:[:i|
+        (self bitAt:i) == 1 ifTrue:[
+            result := result bitXored:factor.
+        ].
+        factor odd ifTrue:[
+            factor := (factor rightShift:1) bitXored:16rE1000000000000000000000000000000.
+        ] ifFalse:[
+            factor := factor rightShift:1.
+        ]
+    ].
+    ^ result compressed.
+
+    "<<EOC
+        #(
+            (16r0388DACE60B6A392F328C2B971B2FE78 16r66E94BD4EF8A2C3B884CFA59CA342B2E 16r5E2EC746917062882C85B0685353DEB7)
+        ) triplesDo:[:x :y :result|
+            |square|
+            self assert:(x gfMul2_128:y) = result.
+            self assert:(y gfMul2_128:x) = result.
+            "/ check distributive law (#bitXor is addition in GF):
+            self assert:(x gfMul2_128:(y bitXor:result)) = ((x gfMul2_128:y) bitXor:(x gfMul2_128:result)).
+
+            "/ check, that order is 2^128-1: 
+            square := x.
+            128 timesRepeat:[
+                square := square gfMul2_128:square.
+            ].
+            self assert:square = x.
+        ].
+
+        #(
+            (1 2 3)
+            (111 333 444)
+            (555777 888999 33333333333333333333333333333333333)
+        ) triplesDo:[:x :y :z|
+            self assert:(x gfMul2_128:y) = (y gfMul2_128:x).
+            "/ check distributive law (#bitXor is addition in GF):
+            self assert:(x gfMul2_128:(y bitXor:z)) = ((x gfMul2_128:y) bitXor:(x gfMul2_128:z))
+        ].
+EOC"
+
+    "Created: / 29-01-2020 / 15:16:49 / Stefan Vogel"
+    "Modified: / 29-01-2020 / 17:57:15 / Stefan Vogel"
+!
+
 integerLog10
     "return the floor of log10 of the receiver.
      This is the same as (self log:10) floor.
@@ -5844,6 +5917,7 @@
     "Created: / 09-01-2012 / 17:18:06 / cg"
 ! !
 
+
 !Integer methodsFor:'special modulo arithmetic'!
 
 add_32:anInteger