--- 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