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

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

Issue 620553002: Provide ia32 intrinsics for bigint add, sub, quotient digit estimation, and (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 2 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/vm/assembler_ia32.h » ('j') | runtime/vm/intrinsifier_ia32.cc » ('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 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 r = -r; 405 r = -r;
406 } 406 }
407 } else if (_neg) { 407 } else if (_neg) {
408 r = -1; 408 r = -1;
409 } else { 409 } else {
410 r = 1; 410 r = 1;
411 } 411 }
412 return r; 412 return r;
413 } 413 }
414 414
415 // r_digits[0..used] = digits[0..used-1] + a_digits[0..a_used-1].
416 // used >= a_used > 0.
417 static void _add(Uint32List digits, int used,
418 Uint32List a_digits, int a_used,
419 Uint32List r_digits) {
420 var c = 0;
421 for (var i = 0; i < a_used; i++) {
422 c += digits[i] + a_digits[i];
423 r_digits[i] = c & DIGIT_MASK;
424 c >>= DIGIT_BITS;
425 }
426 for (var i = a_used; i < used; i++) {
427 c += digits[i];
428 r_digits[i] = c & DIGIT_MASK;
429 c >>= DIGIT_BITS;
430 }
431 r_digits[used] = c;
432 }
433
434 // r_digits[0..used-1] = digits[0..used-1] - a_digits[0..a_used-1].
435 // used >= a_used > 0.
436 static void _sub(Uint32List digits, int used,
437 Uint32List a_digits, int a_used,
438 Uint32List r_digits) {
439 var c = 0;
440 for (var i = 0; i < a_used; i++) {
441 c += digits[i] - a_digits[i];
442 r_digits[i] = c & DIGIT_MASK;
443 c >>= DIGIT_BITS;
444 }
445 for (var i = a_used; i < used; i++) {
446 c += digits[i];
447 r_digits[i] = c & DIGIT_MASK;
448 c >>= DIGIT_BITS;
449 }
450 }
451
415 // r = abs(this) + abs(a). 452 // r = abs(this) + abs(a).
416 void _absAddTo(_Bigint a, _Bigint r) { 453 void _absAddTo(_Bigint a, _Bigint r) {
417 var used = _used; 454 var used = _used;
418 var a_used = a._used; 455 var a_used = a._used;
419 if (used < a_used) { 456 if (used < a_used) {
420 a._absAddTo(this, r); 457 a._absAddTo(this, r);
421 return; 458 return;
422 } 459 }
423 if (used == 0) { 460 if (used == 0) {
424 // Set r to 0. 461 // Set r to 0.
425 r._neg = false; 462 r._neg = false;
426 r._used = 0; 463 r._used = 0;
427 return; 464 return;
428 } 465 }
429 if (a_used == 0) { 466 if (a_used == 0) {
430 _copyTo(r); 467 _copyTo(r);
431 return; 468 return;
432 } 469 }
433 r._ensureLength(used + 1); 470 r._ensureLength(used + 1);
434 var digits = _digits; 471 _add(_digits, used, a._digits, a_used, r._digits);
435 var a_digits = a._digits;
436 var r_digits = r._digits;
437 var c = 0;
438 for (var i = 0; i < a_used; i++) {
439 c += digits[i] + a_digits[i];
440 r_digits[i] = c & DIGIT_MASK;
441 c >>= DIGIT_BITS;
442 }
443 for (var i = a_used; i < used; i++) {
444 c += digits[i];
445 r_digits[i] = c & DIGIT_MASK;
446 c >>= DIGIT_BITS;
447 }
448 r_digits[used] = c;
449 r._used = used + 1; 472 r._used = used + 1;
450 r._clamp(); 473 r._clamp();
451 } 474 }
452 475
453 // r = abs(this) - abs(a), with abs(this) >= abs(a). 476 // r = abs(this) - abs(a), with abs(this) >= abs(a).
454 void _absSubTo(_Bigint a, _Bigint r) { 477 void _absSubTo(_Bigint a, _Bigint r) {
455 assert(_absCompareTo(a) >= 0); 478 assert(_absCompareTo(a) >= 0);
456 var used = _used; 479 var used = _used;
457 if (used == 0) { 480 if (used == 0) {
458 // Set r to 0. 481 // Set r to 0.
459 r._neg = false; 482 r._neg = false;
460 r._used = 0; 483 r._used = 0;
461 return; 484 return;
462 } 485 }
463 var a_used = a._used; 486 var a_used = a._used;
464 if (a_used == 0) { 487 if (a_used == 0) {
465 _copyTo(r); 488 _copyTo(r);
466 return; 489 return;
467 } 490 }
468 r._ensureLength(used); 491 r._ensureLength(used);
469 var digits = _digits; 492 _sub(_digits, used, a._digits, a_used, r._digits);
470 var a_digits = a._digits;
471 var r_digits = r._digits;
472 var c = 0;
473 for (var i = 0; i < a_used; i++) {
474 c += digits[i] - a_digits[i];
475 r_digits[i] = c & DIGIT_MASK;
476 c >>= DIGIT_BITS;
477 }
478 for (var i = a_used; i < used; i++) {
479 c += digits[i];
480 r_digits[i] = c & DIGIT_MASK;
481 c >>= DIGIT_BITS;
482 }
483 r._used = used; 493 r._used = used;
484 r._clamp(); 494 r._clamp();
485 } 495 }
486 496
487 // r = abs(this) & abs(a). 497 // r = abs(this) & abs(a).
488 void _absAndTo(_Bigint a, _Bigint r) { 498 void _absAndTo(_Bigint a, _Bigint r) {
489 var r_used = (_used < a._used) ? _used : a._used; 499 var r_used = (_used < a._used) ? _used : a._used;
490 r._ensureLength(r_used); 500 r._ensureLength(r_used);
491 var digits = _digits; 501 var digits = _digits;
492 var a_digits = a._digits; 502 var a_digits = a._digits;
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
889 _sqrAdd(digits, i, r_digits, used); 899 _sqrAdd(digits, i, r_digits, used);
890 } 900 }
891 if (r_used > 0) { 901 if (r_used > 0) {
892 _mulAdd(digits, i, digits, i, r_digits, 2*i, 1); 902 _mulAdd(digits, i, digits, i, r_digits, 2*i, 1);
893 } 903 }
894 r._used = r_used; 904 r._used = r_used;
895 r._neg = false; 905 r._neg = false;
896 r._clamp(); 906 r._clamp();
897 } 907 }
898 908
909 // Indices of the arguments of _estQuotientDigit.
910 static const int _YT = 0; // Index of top digit of divisor y in args array.
911 static const int _QD = 1; // Index of estimated quotient digit in args array.
912
913 // Estimate args[_QD] = digits[i]:digits[i-1] ~/ args[_YT].
914 static void _estQuotientDigit(Uint32List args, Uint32List digits, int i) {
915 if (digits[i] == args[_YT]) {
916 args[_QD] = DIGIT_MASK;
917 } else {
918 // Chop off one bit, since a Mint cannot hold 2 DIGITs.
919 var qd = ((digits[i] << (DIGIT_BITS - 1)) | (digits[i - 1] >> 1))
920 ~/ (args[_YT] >> 1);
921 if (qd > DIGIT_MASK) {
922 args[_QD] = DIGIT_MASK;
923 } else {
924 args[_QD] = qd;
925 }
926 }
927 }
928
929
899 // Truncating division and remainder. 930 // Truncating division and remainder.
900 // If q != null, q = trunc(this / a). 931 // If q != null, q = trunc(this / a).
901 // If r != null, r = this - a * trunc(this / a). 932 // If r != null, r = this - a * trunc(this / a).
902 void _divRemTo(_Bigint a, _Bigint q, _Bigint r) { 933 void _divRemTo(_Bigint a, _Bigint q, _Bigint r) {
903 if (a._used == 0) return; 934 if (a._used == 0) return;
904 if (_used < a._used) { 935 if (_used < a._used) {
905 if (q != null) { 936 if (q != null) {
906 // Set q to 0. 937 // Set q to 0.
907 q._neg = false; 938 q._neg = false;
908 q._used = 0; 939 q._used = 0;
(...skipping 14 matching lines...) Expand all
923 } 954 }
924 else { 955 else {
925 a._copyTo(y); 956 a._copyTo(y);
926 _copyTo(r); 957 _copyTo(r);
927 } 958 }
928 // We consider this and a positive. Ignore the copied sign. 959 // We consider this and a positive. Ignore the copied sign.
929 y._neg = false; 960 y._neg = false;
930 r._neg = false; 961 r._neg = false;
931 var y_used = y._used; 962 var y_used = y._used;
932 var y_digits = y._digits; 963 var y_digits = y._digits;
933 var y0 = y_digits[y_used - 1]; 964 var yt = y_digits[y_used - 1];
934 if (y0 == 0) return; 965 if (yt == 0) return;
935 var yt = y0 >> 1; // Chop off one bit, see below. y is normalized: yt != 0.
936 var i = r._used; 966 var i = r._used;
937 var j = i - y_used; 967 var j = i - y_used;
938 _Bigint t = (q == null) ? new _Bigint() : q; 968 _Bigint t = (q == null) ? new _Bigint() : q;
939 y._dlShiftTo(j, t); 969 y._dlShiftTo(j, t);
940 var r_digits = r._digits; 970 var r_digits = r._digits;
941 if (r._compareTo(t) >= 0) { 971 if (r._compareTo(t) >= 0) {
942 r_digits[r._used++] = 1; 972 r_digits[r._used++] = 1;
943 r._subTo(t, r); 973 r._subTo(t, r);
944 } 974 }
945 ONE._dlShiftTo(y_used, t); 975 ONE._dlShiftTo(y_used, t);
946 t._subTo(y, y); // Negate y so we can replace sub with _mulAdd later. 976 t._subTo(y, y); // Negate y so we can replace sub with _mulAdd later.
947 while (y._used < y_used) { 977 while (y._used < y_used) {
948 y_digits[y._used++] = 0; 978 y_digits[y._used++] = 0;
949 } 979 }
950 var qd_digit = new Uint32List(1); 980 Uint32List args = new Uint32List(2);
Cutch 2014/09/30 17:52:54 Can you cache this Uint32List somewhere so we don'
regis 2014/09/30 18:35:58 There is no optimal place to cache this array, and
981 args[_YT] = yt;
951 while (--j >= 0) { 982 while (--j >= 0) {
952 // Estimate quotient digit. 983 _estQuotientDigit(args, r_digits, --i);
953 // TODO(regis): Move the expensive mint division below to a function that 984 _mulAdd(args, _QD, y_digits, 0, r_digits, j, y_used);
954 // can be intrinsified using an uint64_t by uint32_t division instruction, 985 if (r_digits[i] < args[_QD]) {
955 // e.g. qd = _estqd(r_digits, --i, y0).
956 if (r_digits[--i] == y0) {
957 qd_digit[0] = DIGIT_MASK;
958 } else {
959 // Chop off one bit, since a Mint cannot hold 2 DIGITs.
960 var qd =
961 ((r_digits[i] << (DIGIT_BITS - 1)) | (r_digits[i - 1] >> 1)) ~/ yt;
962 if (qd > DIGIT_MASK) {
963 qd_digit[0] = DIGIT_MASK;
964 } else {
965 qd_digit[0] = qd;
966 }
967 }
968 _mulAdd(qd_digit, 0, y_digits, 0, r_digits, j, y_used);
969 if (r_digits[i] < qd_digit[0]) {
970 y._dlShiftTo(j, t); 986 y._dlShiftTo(j, t);
971 r._subTo(t, r); 987 r._subTo(t, r);
972 while (r_digits[i] < --qd_digit[0]) { 988 while (r_digits[i] < --args[_QD]) {
973 r._subTo(t, r); 989 r._subTo(t, r);
974 } 990 }
975 } 991 }
976 } 992 }
977 if (q != null) { 993 if (q != null) {
978 r._drShiftTo(y_used, q); 994 r._drShiftTo(y_used, q);
979 if (_neg != a._neg) { 995 if (_neg != a._neg) {
980 ZERO._subTo(q, q); 996 ZERO._subTo(q, q);
981 } 997 }
982 } 998 }
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
1311 class _Reduction { 1327 class _Reduction {
1312 _Bigint _convert(_Bigint x); 1328 _Bigint _convert(_Bigint x);
1313 _Bigint _revert(_Bigint x); 1329 _Bigint _revert(_Bigint x);
1314 void _mulTo(_Bigint x, _Bigint y, _Bigint r); 1330 void _mulTo(_Bigint x, _Bigint y, _Bigint r);
1315 void _sqrTo(_Bigint x, _Bigint r); 1331 void _sqrTo(_Bigint x, _Bigint r);
1316 } 1332 }
1317 1333
1318 // Montgomery reduction on _Bigint. 1334 // Montgomery reduction on _Bigint.
1319 class _Montgomery implements _Reduction { 1335 class _Montgomery implements _Reduction {
1320 _Bigint _m; 1336 _Bigint _m;
1321 int _mp;
1322 int _mpl;
1323 int _mph;
1324 int _um;
1325 int _mused2; 1337 int _mused2;
1326 Uint32List _u0digit; 1338 Uint32List _rho_mu;
1339 static const int _RHO = 0; // Index of rho in _rho_mu array.
1340 static const int _MU = 1; // Index of mu in _rho_mu array.
1327 1341
1328 _Montgomery(m) { 1342 _Montgomery(m) {
1329 _m = m._toBigint(); 1343 _m = m._toBigint();
1330 _mp = _m._invDigit();
1331 _mpl = _mp & _Bigint.DIGIT2_MASK;
1332 _mph = _mp >> _Bigint.DIGIT2_BITS;
1333 _um = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1;
1334 _mused2 = 2*_m._used; 1344 _mused2 = 2*_m._used;
1335 _u0digit = new Uint32List(1); 1345 _rho_mu = new Uint32List(2);
1346 _rho_mu[_RHO] = _m._invDigit();
1347 }
1348
1349 // args[_MU] = args[_RHO]*digits[i] mod DIGIT_BASE.
1350 static void _mulMod(Uint32List args, Uint32List digits, int i) {
1351 const int MU_MASK = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1;
1352 var rhol = args[_RHO] & _Bigint.DIGIT2_MASK;
1353 var rhoh = args[_RHO] >> _Bigint.DIGIT2_BITS;
1354 var dh = digits[i] >> _Bigint.DIGIT2_BITS;
1355 var dl = digits[i] & _Bigint.DIGIT2_MASK;
1356 args[_MU] =
1357 (dl*rhol + (((dl*rhoh + dh*rhol) & MU_MASK) << _Bigint.DIGIT2_BITS))
1358 & _Bigint.DIGIT_MASK;
1336 } 1359 }
1337 1360
1338 // Return x*R mod _m 1361 // Return x*R mod _m
1339 _Bigint _convert(_Bigint x) { 1362 _Bigint _convert(_Bigint x) {
1340 var r = new _Bigint(); 1363 var r = new _Bigint();
1341 x.abs()._dlShiftTo(_m._used, r); 1364 x.abs()._dlShiftTo(_m._used, r);
1342 r._divRemTo(_m, null, r); 1365 r._divRemTo(_m, null, r);
1343 if (x._neg && !r._neg && r._used > 0) { 1366 if (x._neg && !r._neg && r._used > 0) {
1344 _m._subTo(r, r); 1367 _m._subTo(r, r);
1345 } 1368 }
(...skipping 11 matching lines...) Expand all
1357 // x = x/R mod _m 1380 // x = x/R mod _m
1358 void _reduce(_Bigint x) { 1381 void _reduce(_Bigint x) {
1359 x._ensureLength(_mused2 + 1); 1382 x._ensureLength(_mused2 + 1);
1360 var x_digits = x._digits; 1383 var x_digits = x._digits;
1361 while (x._used <= _mused2) { // Pad x so _mulAdd has enough room later. 1384 while (x._used <= _mused2) { // Pad x so _mulAdd has enough room later.
1362 x_digits[x._used++] = 0; 1385 x_digits[x._used++] = 0;
1363 } 1386 }
1364 var m_used = _m._used; 1387 var m_used = _m._used;
1365 var m_digits = _m._digits; 1388 var m_digits = _m._digits;
1366 for (var i = 0; i < m_used; ++i) { 1389 for (var i = 0; i < m_used; ++i) {
1367 // Faster way of calculating u0 = x[i]*mp mod DIGIT_BASE. 1390 _mulMod(_rho_mu, x_digits, i);
1368 var j = x_digits[i] & _Bigint.DIGIT2_MASK; 1391 _Bigint._mulAdd(_rho_mu, _MU, m_digits, 0, x_digits, i, m_used);
1369 _u0digit[0] = (j*_mpl + (((j*_mph + (x_digits[i] >> _Bigint.DIGIT2_BITS)
1370 *_mpl) & _um) << _Bigint.DIGIT2_BITS)) & _Bigint.DIGIT_MASK;
1371 // Use _mulAdd to combine the multiply-shift-add into one call.
1372 _Bigint._mulAdd(_u0digit, 0, m_digits, 0, x_digits, i, m_used);
1373 } 1392 }
1374 x._clamp(); 1393 x._clamp();
1375 x._drShiftTo(m_used, x); 1394 x._drShiftTo(m_used, x);
1376 if (x._compareTo(_m) >= 0) { 1395 if (x._compareTo(_m) >= 0) {
1377 x._subTo(_m, x); 1396 x._subTo(_m, x);
1378 } 1397 }
1379 } 1398 }
1380 1399
1381 // r = x^2/R mod _m ; x != r 1400 // r = x^2/R mod _m ; x != r
1382 void _sqrTo(_Bigint x, _Bigint r) { 1401 void _sqrTo(_Bigint x, _Bigint r) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1422 void _sqrTo(_Bigint x, _Bigint r) { 1441 void _sqrTo(_Bigint x, _Bigint r) {
1423 x._sqrTo(r); 1442 x._sqrTo(r);
1424 _reduce(r); 1443 _reduce(r);
1425 } 1444 }
1426 1445
1427 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { 1446 void _mulTo(_Bigint x, _Bigint y, _Bigint r) {
1428 x._mulTo(y, r); 1447 x._mulTo(y, r);
1429 _reduce(r); 1448 _reduce(r);
1430 } 1449 }
1431 } 1450 }
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/assembler_ia32.h » ('j') | runtime/vm/intrinsifier_ia32.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698