OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 // TODO(srdjan): fix limitations. | 5 // TODO(srdjan): fix limitations. |
6 // - shift amount must be a Smi. | 6 // - shift amount must be a Smi. |
7 class _IntegerImplementation extends _Num { | 7 class _IntegerImplementation extends _Num { |
8 // The Dart class _Bigint extending _IntegerImplementation requires a | 8 // The Dart class _Bigint extending _IntegerImplementation requires a |
9 // default constructor. | 9 // default constructor. |
10 | 10 |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 // Returns pow(this, e) % m. | 268 // Returns pow(this, e) % m. |
269 int modPow(int e, int m) { | 269 int modPow(int e, int m) { |
270 if (e is! int) throw new ArgumentError(e); | 270 if (e is! int) throw new ArgumentError(e); |
271 if (m is! int) throw new ArgumentError(m); | 271 if (m is! int) throw new ArgumentError(m); |
272 if (e < 0) throw new RangeError(e); | 272 if (e < 0) throw new RangeError(e); |
273 if (m <= 0) throw new RangeError(m); | 273 if (m <= 0) throw new RangeError(m); |
274 if (e == 0) return 1; | 274 if (e == 0) return 1; |
275 if (e is _Bigint || m is _Bigint) { | 275 if (e is _Bigint || m is _Bigint) { |
276 return _toBigint().modPow(e, m); | 276 return _toBigint().modPow(e, m); |
277 } | 277 } |
278 if (e < 1) return 1; | |
279 int b = this; | 278 int b = this; |
280 if (b < 0 || b > m) { | 279 if (b < 0 || b > m) { |
281 b %= m; | 280 b %= m; |
282 } | 281 } |
283 int r = 1; | 282 int r = 1; |
284 while (e > 0) { | 283 while (e > 0) { |
285 if (e.isOdd) { | 284 if (e.isOdd) { |
286 r = (r * b) % m; | 285 r = (r * b) % m; |
287 } | 286 } |
288 e >>= 1; | 287 e >>= 1; |
289 b = (b * b) % m; | 288 b = (b * b) % m; |
290 } | 289 } |
291 return r; | 290 return r; |
292 } | 291 } |
| 292 |
| 293 // Returns 1/this % m, with m > 0. |
| 294 int modInverse(int m) { |
| 295 if (m is! int) throw new ArgumentError(m); |
| 296 if (m <= 0) throw new RangeError(m); |
| 297 if (m is _Bigint) { |
| 298 return _toBigint().modInverse(m); |
| 299 } |
| 300 bool ac = m.isEven; |
| 301 int u = m; |
| 302 int v = this; |
| 303 int a = 1, |
| 304 b = 0, |
| 305 c = 0, |
| 306 d = 1; |
| 307 while (u != 0) { |
| 308 while (u.isEven) { |
| 309 u >>= 1; |
| 310 if (ac) { |
| 311 if (!a.isEven || !b.isEven) { |
| 312 a += this; |
| 313 b -= m; |
| 314 } |
| 315 a >>= 1; |
| 316 } else if (!b.isEven) { |
| 317 b -= m; |
| 318 } |
| 319 b >>= 1; |
| 320 } |
| 321 while (v.isEven) { |
| 322 v >>= 1; |
| 323 if (ac) { |
| 324 if (!c.isEven || !d.isEven) { |
| 325 c += this; |
| 326 d -= m; |
| 327 } |
| 328 c >>= 1; |
| 329 } else if (!d.isEven) { |
| 330 d -= m; |
| 331 } |
| 332 d >>= 1; |
| 333 } |
| 334 if (u >= v) { |
| 335 u -= v; |
| 336 if (ac) a -= c; |
| 337 b -= d; |
| 338 } else { |
| 339 v -= u; |
| 340 if (ac) c -= a; |
| 341 d -= b; |
| 342 } |
| 343 } |
| 344 if (v != 1) return 0; |
| 345 if (d > m) return d - m; |
| 346 if (d < 0) d += m; |
| 347 if (d < 0) d += m; |
| 348 return d; |
| 349 } |
293 } | 350 } |
294 | 351 |
295 class _Smi extends _IntegerImplementation implements int { | 352 class _Smi extends _IntegerImplementation implements int { |
296 factory _Smi._uninstantiable() { | 353 factory _Smi._uninstantiable() { |
297 throw new UnsupportedError( | 354 throw new UnsupportedError( |
298 "_Smi can only be allocated by the VM"); | 355 "_Smi can only be allocated by the VM"); |
299 } | 356 } |
300 int get _identityHashCode { | 357 int get _identityHashCode { |
301 return this; | 358 return this; |
302 } | 359 } |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 // Shift by mint exceeds range that can be handled by the VM. | 561 // Shift by mint exceeds range that can be handled by the VM. |
505 int _shrFromInt(int other) { | 562 int _shrFromInt(int other) { |
506 if (other < 0) { | 563 if (other < 0) { |
507 return -1; | 564 return -1; |
508 } else { | 565 } else { |
509 return 0; | 566 return 0; |
510 } | 567 } |
511 } | 568 } |
512 int _shlFromInt(int other) native "Mint_shlFromInt"; | 569 int _shlFromInt(int other) native "Mint_shlFromInt"; |
513 } | 570 } |
OLD | NEW |