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 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 e >>= 1; | 287 e >>= 1; |
288 b = (b * b) % m; | 288 b = (b * b) % m; |
289 } | 289 } |
290 return r; | 290 return r; |
291 } | 291 } |
292 | 292 |
293 // Returns 1/this % m, with m > 0. | 293 // Returns 1/this % m, with m > 0. |
294 int modInverse(int m) { | 294 int modInverse(int m) { |
295 if (m is! int) throw new ArgumentError(m); | 295 if (m is! int) throw new ArgumentError(m); |
296 if (m <= 0) throw new RangeError(m); | 296 if (m <= 0) throw new RangeError(m); |
| 297 if (m == 1) return 0; |
297 if (m is _Bigint) { | 298 if (m is _Bigint) { |
298 return _toBigint().modInverse(m); | 299 return _toBigint().modInverse(m); |
299 } | 300 } |
300 if (this == 0) return 0; | 301 int t = this; |
301 bool ac = m.isEven; | 302 if ((t < 0) || (t >= m)) t %= m; |
| 303 if (t == 1) return 1; |
| 304 final bool ac = m.isEven; |
| 305 if ((t == 0) || (ac && t.isEven)) throw new RangeError("Not coprime"); |
302 int u = m; | 306 int u = m; |
303 int v = this; | 307 int v = t; |
304 int a = 1, | 308 int a = 1, |
305 b = 0, | 309 b = 0, |
306 c = 0, | 310 c = 0, |
307 d = 1; | 311 d = 1; |
308 while (u != 0) { | 312 do { |
309 while (u.isEven) { | 313 while (u.isEven) { |
310 u >>= 1; | 314 u >>= 1; |
311 if (ac) { | 315 if (ac) { |
312 if (!a.isEven || !b.isEven) { | 316 if (!a.isEven || !b.isEven) { |
313 a += this; | 317 a += t; |
314 b -= m; | 318 b -= m; |
315 } | 319 } |
316 a >>= 1; | 320 a >>= 1; |
317 } else if (!b.isEven) { | 321 } else if (!b.isEven) { |
318 b -= m; | 322 b -= m; |
319 } | 323 } |
320 b >>= 1; | 324 b >>= 1; |
321 } | 325 } |
322 while (v.isEven) { | 326 while (v.isEven) { |
323 v >>= 1; | 327 v >>= 1; |
324 if (ac) { | 328 if (ac) { |
325 if (!c.isEven || !d.isEven) { | 329 if (!c.isEven || !d.isEven) { |
326 c += this; | 330 c += t; |
327 d -= m; | 331 d -= m; |
328 } | 332 } |
329 c >>= 1; | 333 c >>= 1; |
330 } else if (!d.isEven) { | 334 } else if (!d.isEven) { |
331 d -= m; | 335 d -= m; |
332 } | 336 } |
333 d >>= 1; | 337 d >>= 1; |
334 } | 338 } |
335 if (u >= v) { | 339 if (u >= v) { |
336 u -= v; | 340 u -= v; |
337 if (ac) a -= c; | 341 if (ac) a -= c; |
338 b -= d; | 342 b -= d; |
339 } else { | 343 } else { |
340 v -= u; | 344 v -= u; |
341 if (ac) c -= a; | 345 if (ac) c -= a; |
342 d -= b; | 346 d -= b; |
343 } | 347 } |
| 348 } while (u != 0); |
| 349 if (v != 1) throw new RangeError("Not coprime"); |
| 350 if (d < 0) { |
| 351 d += m; |
| 352 if (d < 0) d += m; |
| 353 } else if (d > m) { |
| 354 d -= m; |
| 355 if (d > m) d -= m; |
344 } | 356 } |
345 if (v != 1) return 0; | |
346 if (d > m) return d - m; | |
347 if (d < 0) d += m; | |
348 if (d < 0) d += m; | |
349 return d; | 357 return d; |
350 } | 358 } |
351 } | 359 } |
352 | 360 |
353 class _Smi extends _IntegerImplementation implements int { | 361 class _Smi extends _IntegerImplementation implements int { |
354 factory _Smi._uninstantiable() { | 362 factory _Smi._uninstantiable() { |
355 throw new UnsupportedError( | 363 throw new UnsupportedError( |
356 "_Smi can only be allocated by the VM"); | 364 "_Smi can only be allocated by the VM"); |
357 } | 365 } |
358 int get _identityHashCode { | 366 int get _identityHashCode { |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 // Shift by mint exceeds range that can be handled by the VM. | 570 // Shift by mint exceeds range that can be handled by the VM. |
563 int _shrFromInt(int other) { | 571 int _shrFromInt(int other) { |
564 if (other < 0) { | 572 if (other < 0) { |
565 return -1; | 573 return -1; |
566 } else { | 574 } else { |
567 return 0; | 575 return 0; |
568 } | 576 } |
569 } | 577 } |
570 int _shlFromInt(int other) native "Mint_shlFromInt"; | 578 int _shlFromInt(int other) native "Mint_shlFromInt"; |
571 } | 579 } |
OLD | NEW |