| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
| 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. | |
| 4 | |
| 5 library dart.pkg.math; | |
| 6 | |
| 7 /** | |
| 8 * Computes the greatest common divisor between [a] and [b]. | |
| 9 * | |
| 10 * The result is always positive even if either `a` or `b` is negative. | |
| 11 */ | |
| 12 int gcd(int a, int b) { | |
| 13 if (a == null) throw new ArgumentError(a); | |
| 14 if (b == null) throw new ArgumentError(b); | |
| 15 a = a.abs(); | |
| 16 b = b.abs(); | |
| 17 | |
| 18 // Iterative Binary GCD algorithm. | |
| 19 if (a == 0) return b; | |
| 20 if (b == 0) return a; | |
| 21 int powerOfTwo = 1; | |
| 22 while (((a | b) & 1) == 0) { | |
| 23 powerOfTwo *= 2; | |
| 24 a ~/= 2; | |
| 25 b ~/= 2; | |
| 26 } | |
| 27 | |
| 28 while (a.isEven) a ~/= 2; | |
| 29 | |
| 30 do { | |
| 31 while (b.isEven) b ~/= 2; | |
| 32 if (a > b) { | |
| 33 int temp = b; | |
| 34 b = a; | |
| 35 a = temp; | |
| 36 } | |
| 37 b -= a; | |
| 38 } while (b != 0); | |
| 39 | |
| 40 return a * powerOfTwo; | |
| 41 } | |
| 42 | |
| 43 /** | |
| 44 * Computes the greatest common divisor between [a] and [b], as well as [x] and | |
| 45 * [y] such that `ax+by == gcd(a,b)`. | |
| 46 * | |
| 47 * The return value is a List of three ints: the greatest common divisor, `x`, | |
| 48 * and `y`, in that order. | |
| 49 */ | |
| 50 List<int> gcdext(int a, int b) { | |
| 51 if (a == null) throw new ArgumentError(a); | |
| 52 if (b == null) throw new ArgumentError(b); | |
| 53 | |
| 54 if (a < 0) { | |
| 55 List<int> result = gcdext(-a, b); | |
| 56 result[1] = -result[1]; | |
| 57 return result; | |
| 58 } | |
| 59 if (b < 0) { | |
| 60 List<int> result = gcdext(a, -b); | |
| 61 result[2] = -result[2]; | |
| 62 return result; | |
| 63 } | |
| 64 | |
| 65 int r0 = a; | |
| 66 int r1 = b; | |
| 67 int x0, x1, y0, y1; | |
| 68 x0 = y1 = 1; | |
| 69 x1 = y0 = 0; | |
| 70 | |
| 71 while (r1 != 0) { | |
| 72 int q = r0 ~/ r1; | |
| 73 int tmp = r0; | |
| 74 r0 = r1; | |
| 75 r1 = tmp - q*r1; | |
| 76 | |
| 77 tmp = x0; | |
| 78 x0 = x1; | |
| 79 x1 = tmp - q*x1; | |
| 80 | |
| 81 tmp = y0; | |
| 82 y0 = y1; | |
| 83 y1 = tmp - q*y1; | |
| 84 } | |
| 85 | |
| 86 return new List<int>(3) | |
| 87 ..[0] = r0 | |
| 88 ..[1] = x0 | |
| 89 ..[2] = y0; | |
| 90 } | |
| 91 | |
| 92 /** | |
| 93 * Computes the inverse of [a] modulo [m]. | |
| 94 * | |
| 95 * Throws an [IntegerDivisionByZeroException] if `a` has no inverse modulo `m`: | |
| 96 * | |
| 97 * invert(4, 7); // 2 | |
| 98 * invert(4, 10); // throws IntegerDivisionByZeroException | |
| 99 */ | |
| 100 int invert(int a, int m) { | |
| 101 List<int> results = gcdext(a, m); | |
| 102 int g = results[0]; | |
| 103 int x = results[1]; | |
| 104 if (g != 1) { | |
| 105 throw new IntegerDivisionByZeroException(); | |
| 106 } | |
| 107 return x % m; | |
| 108 } | |
| 109 | |
| 110 /** | |
| 111 * Computes the least common multiple between [a] and [b]. | |
| 112 */ | |
| 113 int lcm(int a, int b) { | |
| 114 if (a == null) throw new ArgumentError(a); | |
| 115 if (b == null) throw new ArgumentError(b); | |
| 116 if (a == 0 && b == 0) return 0; | |
| 117 | |
| 118 return a.abs() ~/ gcd(a, b) * b.abs(); | |
| 119 } | |
| 120 | |
| 121 /** | |
| 122 * Computes [base] raised to [exp] modulo [mod]. | |
| 123 * | |
| 124 * The result is always positive, in keeping with the behavior of modulus | |
| 125 * operator (`%`). | |
| 126 * | |
| 127 * Throws an [IntegerDivisionByZeroException] if `exp` is negative and `base` | |
| 128 * has no inverse modulo `mod`. | |
| 129 */ | |
| 130 int powmod(int base, int exp, int mod) { | |
| 131 if (base == null) throw new ArgumentError(base); | |
| 132 if (exp == null) throw new ArgumentError(exp); | |
| 133 if (mod == null) throw new ArgumentError(mod); | |
| 134 | |
| 135 // Right-to-left binary method of modular exponentiation. | |
| 136 if (exp < 0) { | |
| 137 base = invert(base, mod); | |
| 138 exp = -exp; | |
| 139 } | |
| 140 if (exp == 0) { return 1; } | |
| 141 | |
| 142 int result = 1; | |
| 143 base = base % mod; | |
| 144 while (true) { | |
| 145 if (exp.isOdd) { | |
| 146 result = (result * base) % mod; | |
| 147 } | |
| 148 exp ~/= 2; | |
| 149 if (exp == 0) { | |
| 150 return result; | |
| 151 } | |
| 152 base = (base * base) % mod; | |
| 153 } | |
| 154 } | |
| OLD | NEW |