Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(22)

Side by Side Diff: runtime/lib/bigint.dart

Issue 570563004: Temporarily add a public modPow method to int interface. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | runtime/lib/integers.dart » ('j') | runtime/lib/integers.dart » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 // Copyright 2009 The Go Authors. All rights reserved. 5 // Copyright 2009 The Go Authors. All rights reserved.
6 // Use of this source code is governed by a BSD-style 6 // Use of this source code is governed by a BSD-style
7 // license that can be found in the LICENSE file. 7 // license that can be found in the LICENSE file.
8 8
9 /* 9 /*
10 * Copyright (c) 2003-2005 Tom Wu 10 * Copyright (c) 2003-2005 Tom Wu
(...skipping 1100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1111 y = (y*(2 - (x & 0xff)*y)) & 0xff; // y == 1/x mod 2^8 1111 y = (y*(2 - (x & 0xff)*y)) & 0xff; // y == 1/x mod 2^8
1112 y = (y*(2 - (((x & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 1112 y = (y*(2 - (((x & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16
1113 // Last step - calculate inverse mod DIGIT_BASE directly; 1113 // Last step - calculate inverse mod DIGIT_BASE directly;
1114 // Assumes 16 < DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints. 1114 // Assumes 16 < DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints.
1115 y = (y*(2 - x*y % DIGIT_BASE)) % DIGIT_BASE; // y == 1/x mod DIGIT_BASE 1115 y = (y*(2 - x*y % DIGIT_BASE)) % DIGIT_BASE; // y == 1/x mod DIGIT_BASE
1116 // We really want the negative inverse, and - DIGIT_BASE < y < DIGIT_BASE. 1116 // We really want the negative inverse, and - DIGIT_BASE < y < DIGIT_BASE.
1117 return (y > 0) ? DIGIT_BASE - y : -y; 1117 return (y > 0) ? DIGIT_BASE - y : -y;
1118 } 1118 }
1119 1119
1120 // TODO(regis): Make this method private once the plumbing to invoke it from 1120 // TODO(regis): Make this method private once the plumbing to invoke it from
1121 // dart:math is in place. 1121 // dart:math is in place. Move the argument checking to dart:math.
1122 // Return pow(this, e) % m. 1122 // Return pow(this, e) % m.
1123 int modPow(int e, int m) { 1123 int modPow(int e, int m) {
1124 // TODO(regis): Where/how do we handle values of e smaller than 256? 1124 if (e is! int) throw new ArgumentError(e);
1125 // TODO(regis): Where/how do we handle even values of m? 1125 if (m is! int) throw new ArgumentError(m);
1126 assert(e >= 256 && !m.isEven()); 1126 int i = e.bitLength;
1127 if (e is! _Bigint) { 1127 if (i <= 0) return 1;
1128 _Reduction z = new _Montgomery(m); 1128 if ((e is! _Bigint) || m.isEven) {
1129 _Reduction z = (i < 8 || m.isEven) ? new _Classic(m) : new _Montgomery(m);
1130 // TODO(regis): Should we use Barrett reduction for an even modulus?
1129 var r = new _Bigint(); 1131 var r = new _Bigint();
1130 var r2 = new _Bigint(); 1132 var r2 = new _Bigint();
1131 var g = z._convert(this); 1133 var g = z._convert(this);
1132 int i = _nbits(e) - 1; 1134 i--;
1133 g._copyTo(r); 1135 g._copyTo(r);
1134 while (--i >= 0) { 1136 while (--i >= 0) {
1135 z._sqrTo(r, r2); 1137 z._sqrTo(r, r2);
1136 if ((e & (1 << i)) > 0) { 1138 if ((e & (1 << i)) != 0) {
1137 z._mulTo(r2, g, r); 1139 z._mulTo(r2, g, r);
1138 } else { 1140 } else {
1139 var t = r; 1141 var t = r;
1140 r = r2; 1142 r = r2;
1141 r2 = t; 1143 r2 = t;
1142 } 1144 }
1143 } 1145 }
1144 return z._revert(r)._toValidInt(); 1146 return z._revert(r)._toValidInt();
1145 } 1147 }
1146 var i = e.bitLength;
1147 var k; 1148 var k;
1148 var r = new _Bigint()._setInt(1);
1149 if (i <= 0) return r;
1150 // TODO(regis): Are these values of k really optimal for our implementation? 1149 // TODO(regis): Are these values of k really optimal for our implementation?
1151 else if (i < 18) k = 1; 1150 if (i < 18) k = 1;
1152 else if (i < 48) k = 3; 1151 else if (i < 48) k = 3;
1153 else if (i < 144) k = 4; 1152 else if (i < 144) k = 4;
1154 else if (i < 768) k = 5; 1153 else if (i < 768) k = 5;
1155 else k = 6; 1154 else k = 6;
1156 _Reduction z = new _Montgomery(m); 1155 _Reduction z = new _Montgomery(m);
1157 var n = 3; 1156 var n = 3;
1158 var k1 = k - 1; 1157 var k1 = k - 1;
1159 var km = (1 << k) - 1; 1158 var km = (1 << k) - 1;
1160 List g = new List(km + 1); 1159 List g = new List(km + 1);
1161 g[1] = z._convert(this); 1160 g[1] = z._convert(this);
1162 if (k > 1) { 1161 if (k > 1) {
1163 var g2 = new _Bigint(); 1162 var g2 = new _Bigint();
1164 z._sqrTo(g[1], g2); 1163 z._sqrTo(g[1], g2);
1165 while (n <= km) { 1164 while (n <= km) {
1166 g[n] = new _Bigint(); 1165 g[n] = new _Bigint();
1167 z._mulTo(g2, g[n - 2], g[n]); 1166 z._mulTo(g2, g[n - 2], g[n]);
1168 n += 2; 1167 n += 2;
1169 } 1168 }
1170 } 1169 }
1171 var j = e._used - 1; 1170 var j = e._used - 1;
1172 var w; 1171 var w;
1173 var is1 = true; 1172 var is1 = true;
1173 var r = new _Bigint()._setInt(1);
1174 var r2 = new _Bigint(); 1174 var r2 = new _Bigint();
1175 var t; 1175 var t;
1176 i = _nbits(e._digits[j]) - 1; 1176 i = _nbits(e._digits[j]) - 1;
1177 while (j >= 0) { 1177 while (j >= 0) {
1178 if (i >= k1) { 1178 if (i >= k1) {
1179 w = (e._digits[j] >> (i - k1)) & km; 1179 w = (e._digits[j] >> (i - k1)) & km;
1180 } else { 1180 } else {
1181 w = (e._digits[j] & ((1 << (i + 1)) - 1)) << (k1 - i); 1181 w = (e._digits[j] & ((1 << (i + 1)) - 1)) << (k1 - i);
1182 if (j > 0) { 1182 if (j > 0) {
1183 w |= e._digits[j - 1] >> (DIGIT_BITS + i - k1); 1183 w |= e._digits[j - 1] >> (DIGIT_BITS + i - k1);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1220 if (--i < 0) { 1220 if (--i < 0) {
1221 i = DIGIT_BITS - 1; 1221 i = DIGIT_BITS - 1;
1222 --j; 1222 --j;
1223 } 1223 }
1224 } 1224 }
1225 } 1225 }
1226 return z._revert(r)._toValidInt(); 1226 return z._revert(r)._toValidInt();
1227 } 1227 }
1228 } 1228 }
1229 1229
1230 // New classes to support crypto (modPow method). 1230 // Interface for modular reduction.
1231
1232 class _Reduction { 1231 class _Reduction {
1233 const _Reduction(); 1232 _Bigint _convert(_Bigint x);
1234 _Bigint _convert(_Bigint x) => x; 1233 _Bigint _revert(_Bigint x);
1235 _Bigint _revert(_Bigint x) => x; 1234 void _mulTo(_Bigint x, _Bigint y, _Bigint r);
1236 1235 void _sqrTo(_Bigint x, _Bigint r);
1237 void _mulTo(_Bigint x, _Bigint y, _Bigint r) {
1238 x._mulTo(y, r);
1239 }
1240
1241 void _sqrTo(_Bigint x, _Bigint r) {
1242 x._sqrTo(r);
1243 }
1244 } 1236 }
1245 1237
1246 // Montgomery reduction on _Bigint. 1238 // Montgomery reduction on _Bigint.
1247 class _Montgomery implements _Reduction { 1239 class _Montgomery implements _Reduction {
1248 final _Bigint _m; 1240 _Bigint _m;
1249 var _mp; 1241 var _mp;
1250 var _mpl; 1242 var _mpl;
1251 var _mph; 1243 var _mph;
1252 var _um; 1244 var _um;
1253 var _mused2; 1245 var _mused2;
1254 1246
1255 _Montgomery(this._m) { 1247 _Montgomery(m) {
1248 _m = m._toBigint();
1256 _mp = _m._invDigit(); 1249 _mp = _m._invDigit();
1257 _mpl = _mp & _Bigint.DIGIT2_MASK; 1250 _mpl = _mp & _Bigint.DIGIT2_MASK;
1258 _mph = _mp >> _Bigint.DIGIT2_BITS; 1251 _mph = _mp >> _Bigint.DIGIT2_BITS;
1259 _um = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1; 1252 _um = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1;
1260 _mused2 = 2*_m._used; 1253 _mused2 = 2*_m._used;
1261 } 1254 }
1262 1255
1263 // Return x*R mod _m 1256 // Return x*R mod _m
1264 _Bigint _convert(_Bigint x) { 1257 _Bigint _convert(_Bigint x) {
1265 var r = new _Bigint(); 1258 var r = new _Bigint();
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1316 _reduce(r); 1309 _reduce(r);
1317 } 1310 }
1318 1311
1319 // r = x*y/R mod _m ; x, y != r 1312 // r = x*y/R mod _m ; x, y != r
1320 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { 1313 void _mulTo(_Bigint x, _Bigint y, _Bigint r) {
1321 x._mulTo(y, r); 1314 x._mulTo(y, r);
1322 _reduce(r); 1315 _reduce(r);
1323 } 1316 }
1324 } 1317 }
1325 1318
1319 // Modular reduction using "classic" algorithm.
1320 class _Classic implements _Reduction {
1321 _Bigint _m;
1322
1323 _Classic(int m) {
1324 _m = m._toBigint();
1325 }
1326
1327 _Bigint _convert(_Bigint x) {
1328 if (x._neg || x._compareTo(_m) >= 0) {
1329 var r = new _Bigint();
1330 x._divRemTo(_m, null, r);
1331 if (x._neg && !r._neg && r._used > 0) {
1332 _m._subTo(r, r);
1333 }
1334 return r;
1335 }
1336 return x;
1337 }
1338
1339 _Bigint _revert(_Bigint x) {
1340 return x;
1341 }
1342
1343 void _reduce(_Bigint x) {
1344 x._divRemTo(_m, null, x);
1345 }
1346
1347 void _sqrTo(_Bigint x, _Bigint r) {
1348 x._sqrTo(r);
1349 _reduce(r);
1350 }
1351
1352 void _mulTo(_Bigint x, _Bigint y, _Bigint r) {
1353 x._mulTo(y, r);
1354 _reduce(r);
1355 }
1356 }
OLDNEW
« no previous file with comments | « no previous file | runtime/lib/integers.dart » ('j') | runtime/lib/integers.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698