@@ -165,4 +165,122 @@ final class ArbitraryPrecisionIntegerTests: XCTestCase {
165
165
XCTAssertEqual ( try ArbitraryPrecisionInteger ( bytes: bytes) , integer)
166
166
}
167
167
}
168
+
169
+ func testMoudlo( ) throws {
170
+ typealias I = ArbitraryPrecisionInteger
171
+ typealias Vector = ( input: I , mod: I , expectedResult: ( standard: I , nonNegative: I ) )
172
+ for vector : Vector in [
173
+ ( input: 0 , mod: 2 , expectedResult: ( standard: 0 , nonNegative: 0 ) ) ,
174
+ ( input: 1 , mod: 2 , expectedResult: ( standard: 1 , nonNegative: 1 ) ) ,
175
+ ( input: 2 , mod: 2 , expectedResult: ( standard: 0 , nonNegative: 0 ) ) ,
176
+ ( input: 3 , mod: 2 , expectedResult: ( standard: 1 , nonNegative: 1 ) ) ,
177
+ ( input: 4 , mod: 2 , expectedResult: ( standard: 0 , nonNegative: 0 ) ) ,
178
+ ( input: 5 , mod: 2 , expectedResult: ( standard: 1 , nonNegative: 1 ) ) ,
179
+ ( input: 7 , mod: 5 , expectedResult: ( standard: 2 , nonNegative: 2 ) ) ,
180
+ ( input: 7 , mod: - 5 , expectedResult: ( standard: 2 , nonNegative: 2 ) ) ,
181
+ ( input: - 7 , mod: 5 , expectedResult: ( standard: - 2 , nonNegative: 3 ) ) ,
182
+ ( input: - 7 , mod: - 5 , expectedResult: ( standard: - 2 , nonNegative: 3 ) ) ,
183
+ ] {
184
+ XCTAssertEqual (
185
+ try vector. input. modulo ( vector. mod, nonNegative: false ) ,
186
+ vector. expectedResult. standard,
187
+ " \( vector. input) (mod \( vector. mod) ) "
188
+ )
189
+ XCTAssertEqual (
190
+ try vector. input. modulo ( vector. mod, nonNegative: true ) ,
191
+ vector. expectedResult. nonNegative,
192
+ " \( vector. input) (nnmod \( vector. mod) ) "
193
+ )
194
+ }
195
+ }
196
+
197
+ func testModularInverse( ) throws {
198
+ typealias I = ArbitraryPrecisionInteger
199
+ enum O { case ok( I ) , throwsError }
200
+ typealias Vector = ( a: I , mod: I , expectedResult: O )
201
+ for vector : Vector in [
202
+ ( a: 3 , mod: 7 , expectedResult: . ok( 5 ) ) ,
203
+ ( a: 10 , mod: 17 , expectedResult: . ok( 12 ) ) ,
204
+ ( a: 7 , mod: 26 , expectedResult: . ok( 15 ) ) ,
205
+ ( a: 7 , mod: 7 , expectedResult: . throwsError) ,
206
+ ] {
207
+ switch vector. expectedResult {
208
+ case . ok( let expectedValue) :
209
+ XCTAssertEqual ( try vector. a. inverse ( modulo: vector. mod) , expectedValue, " inverse( \( vector. a) , modulo: \( vector. mod) ) " )
210
+ case . throwsError:
211
+ XCTAssertThrowsError ( try vector. a. inverse ( modulo: vector. mod) , " inverse( \( vector. a) , modulo: \( vector. mod) " )
212
+ }
213
+ }
214
+ }
215
+
216
+ func testModularAddition( ) throws {
217
+ typealias I = ArbitraryPrecisionInteger
218
+ enum O { case ok( I ) , throwsError }
219
+ typealias Vector = ( a: I , b: I , mod: I , expectedResult: O )
220
+ for vector : Vector in [
221
+ ( a: 0 , b: 0 , mod: 0 , expectedResult: . throwsError) ,
222
+ ( a: 0 , b: 0 , mod: 2 , expectedResult: . ok( 0 ) ) ,
223
+ ( a: 1 , b: 0 , mod: 2 , expectedResult: . ok( 1 ) ) ,
224
+ ( a: 0 , b: 1 , mod: 2 , expectedResult: . ok( 1 ) ) ,
225
+ ( a: 1 , b: 1 , mod: 2 , expectedResult: . ok( 0 ) ) ,
226
+ ( a: 4 , b: 3 , mod: 5 , expectedResult: . ok( 2 ) ) ,
227
+ ( a: 4 , b: 3 , mod: - 5 , expectedResult: . ok( 2 ) ) ,
228
+ ( a: - 4 , b: - 3 , mod: 5 , expectedResult: . ok( 3 ) ) ,
229
+ ] {
230
+ switch vector. expectedResult {
231
+ case . ok( let expectedValue) :
232
+ XCTAssertEqual ( try vector. a. add ( vector. b, modulo: vector. mod) , expectedValue, " \( vector. a) + \( vector. b) (mod \( vector. mod) ) " )
233
+ case . throwsError:
234
+ XCTAssertThrowsError ( try vector. a. add ( vector. b, modulo: vector. mod) , " \( vector. a) + \( vector. b) (mod \( vector. mod) ) " )
235
+ }
236
+ }
237
+ }
238
+
239
+ func testModularSubtraction( ) throws {
240
+ typealias I = ArbitraryPrecisionInteger
241
+ enum O { case ok( I ) , throwsError }
242
+ typealias Vector = ( a: I , b: I , mod: I , expectedResult: O )
243
+ for vector : Vector in [
244
+ ( a: 0 , b: 0 , mod: 0 , expectedResult: . throwsError) ,
245
+ ( a: 0 , b: 0 , mod: 2 , expectedResult: . ok( 0 ) ) ,
246
+ ( a: 1 , b: 0 , mod: 2 , expectedResult: . ok( 1 ) ) ,
247
+ ( a: 0 , b: 1 , mod: 2 , expectedResult: . ok( 1 ) ) ,
248
+ ( a: 1 , b: 1 , mod: 2 , expectedResult: . ok( 0 ) ) ,
249
+ ( a: 4 , b: 3 , mod: 5 , expectedResult: . ok( 1 ) ) ,
250
+ ( a: 3 , b: 4 , mod: 5 , expectedResult: . ok( 4 ) ) ,
251
+ ( a: 3 , b: 4 , mod: - 5 , expectedResult: . ok( 4 ) ) ,
252
+ ( a: - 3 , b: 4 , mod: 5 , expectedResult: . ok( 3 ) ) ,
253
+ ( a: 3 , b: - 4 , mod: 5 , expectedResult: . ok( 2 ) ) ,
254
+ ] {
255
+ switch vector. expectedResult {
256
+ case . ok( let expectedValue) :
257
+ XCTAssertEqual ( try vector. a. sub ( vector. b, modulo: vector. mod) , expectedValue, " \( vector. a) - \( vector. b) (mod \( vector. mod) ) " )
258
+ case . throwsError:
259
+ XCTAssertThrowsError ( try vector. a. sub ( vector. b, modulo: vector. mod) , " \( vector. a) - \( vector. b) (mod \( vector. mod) ) " )
260
+ }
261
+ }
262
+ }
263
+
264
+ func testModularMultiplication( ) throws {
265
+ typealias I = ArbitraryPrecisionInteger
266
+ enum O { case ok( I ) , throwsError }
267
+ typealias Vector = ( a: I , b: I , mod: I , expectedResult: O )
268
+ for vector : Vector in [
269
+ ( a: 0 , b: 0 , mod: 0 , expectedResult: . throwsError) ,
270
+ ( a: 0 , b: 0 , mod: 2 , expectedResult: . ok( 0 ) ) ,
271
+ ( a: 1 , b: 0 , mod: 2 , expectedResult: . ok( 0 ) ) ,
272
+ ( a: 0 , b: 1 , mod: 2 , expectedResult: . ok( 0 ) ) ,
273
+ ( a: 1 , b: 1 , mod: 2 , expectedResult: . ok( 1 ) ) ,
274
+ ( a: 4 , b: 3 , mod: 5 , expectedResult: . ok( 2 ) ) ,
275
+ ( a: 4 , b: 3 , mod: - 5 , expectedResult: . ok( 2 ) ) ,
276
+ ( a: - 4 , b: - 3 , mod: 5 , expectedResult: . ok( 2 ) ) ,
277
+ ] {
278
+ switch vector. expectedResult {
279
+ case . ok( let expectedValue) :
280
+ XCTAssertEqual ( try vector. a. mul ( vector. b, modulo: vector. mod) , expectedValue, " \( vector. a) × \( vector. b) (mod \( vector. mod) ) " )
281
+ case . throwsError:
282
+ XCTAssertThrowsError ( try vector. a. mul ( vector. b, modulo: vector. mod) , " \( vector. a) × \( vector. b) (mod \( vector. mod) ) " )
283
+ }
284
+ }
285
+ }
168
286
}
0 commit comments