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

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

Issue 786933009: Process two 32-bit digits as one 64-bit digit in all bigint intrinsics on x64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 11 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_x64.h » ('j') | no next file with comments »
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 1020 matching lines...) Expand 10 before | Expand all | Expand 10 after
1031 _lShiftTo(nsh, r); 1031 _lShiftTo(nsh, r);
1032 } 1032 }
1033 else { 1033 else {
1034 a._copyTo(y); 1034 a._copyTo(y);
1035 _copyTo(r); 1035 _copyTo(r);
1036 } 1036 }
1037 // We consider this and a positive. Ignore the copied sign. 1037 // We consider this and a positive. Ignore the copied sign.
1038 y._neg = false; 1038 y._neg = false;
1039 r._neg = false; 1039 r._neg = false;
1040 var y_used = y._used; 1040 var y_used = y._used;
1041 assert((y_used & 1) == 0);
1041 var y_digits = y._digits; 1042 var y_digits = y._digits;
1042 Uint32List args = new Uint32List(4); 1043 Uint32List args = new Uint32List(4);
1043 args[_YT_LO] = y_digits[y_used - 2]; 1044 args[_YT_LO] = y_digits[y_used - 2];
1044 args[_YT] = y_digits[y_used - 1]; 1045 args[_YT] = y_digits[y_used - 1];
1046 var r_digits = r._digits;
1045 var i = r._used; 1047 var i = r._used;
1048 if ((i & 1) == 1) {
1049 // For 64-bit processing, make sure r has an even number of digits.
1050 r_digits[i++] = 0;
1051 }
1046 var j = i - y_used; 1052 var j = i - y_used;
1047 _Bigint t = (q == null) ? new _Bigint() : q; 1053 _Bigint t = (q == null) ? new _Bigint() : q;
1048 y._dlShiftTo(j, t); 1054 y._dlShiftTo(j, t);
1049 var r_digits = r._digits;
1050 if (r._compareTo(t) >= 0) { 1055 if (r._compareTo(t) >= 0) {
1051 r_digits[r._used++] = 1; 1056 r_digits[r._used++] = 1;
1052 r_digits[r._used] = 0; // Set leading zero for 64-bit processing. 1057 r_digits[r._used] = 0; // Set leading zero for 64-bit processing.
1053 r._subTo(t, r); 1058 r._subTo(t, r);
1054 } 1059 }
1055 ONE._dlShiftTo(y_used, t); 1060 ONE._dlShiftTo(y_used, t);
1056 t._subTo(y, y); // Negate y so we can replace sub with _mulAdd later. 1061 t._subTo(y, y); // Negate y so we can replace sub with _mulAdd later.
1057 while (y._used < y_used) { 1062 while (y._used < y_used) {
1058 y_digits[y._used++] = 0; 1063 y_digits[y._used++] = 0;
1059 } 1064 }
1060 y_digits[y._used] = 0; // Set leading zero for 64-bit processing. 1065 y_digits[y._used] = 0; // Set leading zero for 64-bit processing.
1061 while (--j >= 0) { 1066 while (j > 0) {
1062 var d0 = _estQuotientDigit(args, r_digits, --i); 1067 var d0 = _estQuotientDigit(args, r_digits, --i);
1068 j -= d0;
1063 var d1 = _mulAdd(args, _QD, y_digits, 0, r_digits, j, y_used); 1069 var d1 = _mulAdd(args, _QD, y_digits, 0, r_digits, j, y_used);
1064 // _estQuotientDigit and _mulAdd must agree on the number of digits to 1070 // _estQuotientDigit and _mulAdd must agree on the number of digits to
1065 // process. 1071 // process.
1066 assert(d0 == d1); 1072 assert(d0 == d1);
1067 if (d0 == 1) { 1073 if (d0 == 1) {
1068 if (r_digits[i] < args[_QD]) { 1074 if (r_digits[i] < args[_QD]) {
1069 y._dlShiftTo(j, t); 1075 y._dlShiftTo(j, t);
1070 r._subTo(t, r); 1076 r._subTo(t, r);
1071 while (r_digits[i] < --args[_QD]) { 1077 while (r_digits[i] < --args[_QD]) {
1072 r._subTo(t, r); 1078 r._subTo(t, r);
1073 } 1079 }
1074 } 1080 }
1075 } else { 1081 } else {
1076 // TODO(regis): Is this necessary, since intrinsified estimation is more 1082 assert(d0 == 2);
1077 // accurate? 1083 assert(r_digits[i] <= args[_QD_HI]);
1078 if ((r_digits[i] < args[_QD_HI]) || 1084 if ((r_digits[i] < args[_QD_HI]) || (r_digits[i-1] < args[_QD])) {
1079 ((r_digits[i] == args[_QD_HI]) && (r_digits[i-1] < args[_QD]))) {
1080 y._dlShiftTo(j, t); 1085 y._dlShiftTo(j, t);
1081 r._subTo(t, r); 1086 r._subTo(t, r);
1082 assert(args[_QD] > 0); 1087 if (args[_QD] == 0) {
1083 while (r_digits[i] < --args[_QD]) { 1088 --args[_QD_HI];
1089 }
1090 --args[_QD];
1091 assert(r_digits[i] <= args[_QD_HI]);
1092 while ((r_digits[i] < args[_QD_HI]) || (r_digits[i-1] < args[_QD])) {
1084 r._subTo(t, r); 1093 r._subTo(t, r);
1094 if (args[_QD] == 0) {
1095 --args[_QD_HI];
1096 }
1097 --args[_QD];
1098 assert(r_digits[i] <= args[_QD_HI]);
1085 } 1099 }
1086 } 1100 }
1101 --i;
1087 } 1102 }
1088 } 1103 }
1089 if (q != null) { 1104 if (q != null) {
1090 r._drShiftTo(y_used, q); 1105 r._drShiftTo(y_used, q);
1091 if (_neg != a._neg && q._used > 0) { 1106 if (_neg != a._neg && q._used > 0) {
1092 q._neg = !q._neg; 1107 q._neg = !q._neg;
1093 } 1108 }
1094 } 1109 }
1095 r._used = y_used; 1110 r._used = y_used;
1096 r._clamp(); 1111 r._clamp();
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
1448 static const int _X_HI = 1; // Index of high 32-bits of x (64-bit only). 1463 static const int _X_HI = 1; // Index of high 32-bits of x (64-bit only).
1449 static const int _RHO = 2; // Index of rho. 1464 static const int _RHO = 2; // Index of rho.
1450 static const int _RHO_HI = 3; // Index of high 32-bits of rho (64-bit only). 1465 static const int _RHO_HI = 3; // Index of high 32-bits of rho (64-bit only).
1451 static const int _MU = 4; // Index of mu. 1466 static const int _MU = 4; // Index of mu.
1452 static const int _MU_HI = 5; // Index of high 32-bits of mu (64-bit only). 1467 static const int _MU_HI = 5; // Index of high 32-bits of mu (64-bit only).
1453 1468
1454 _Montgomery(m) { 1469 _Montgomery(m) {
1455 _m = m._toBigint(); 1470 _m = m._toBigint();
1456 _mused2 = 2*_m._used; 1471 _mused2 = 2*_m._used;
1457 _args = new Uint32List(6); 1472 _args = new Uint32List(6);
1473 // Determine if we can process digit pairs by calling an intrinsic.
1474 _digits_per_step = _mulMod(_args, _args, 0);
1458 _args[_X] = _m._digits[0]; 1475 _args[_X] = _m._digits[0];
1459 _args[_X_HI] = _m._digits[1]; 1476 if (_digits_per_step == 1) {
1460 _digits_per_step = _invDigit(_args); 1477 _invDigit(_args);
1478 } else {
1479 assert(_digits_per_step == 2);
1480 _args[_X_HI] = _m._digits[1];
1481 _invDigitPair(_args);
1482 }
1461 } 1483 }
1462 1484
1463 // Return -1/this % DIGIT_BASE, useful for Montgomery reduction. 1485 // Calculates -1/x % DIGIT_BASE, x is 32-bit digit.
1464 //
1465 // xy == 1 (mod m) 1486 // xy == 1 (mod m)
1466 // xy = 1+km 1487 // xy = 1+km
1467 // xy(2-xy) = (1+km)(1-km) 1488 // xy(2-xy) = (1+km)(1-km)
1468 // x(y(2-xy)) = 1-k^2 m^2 1489 // x(y(2-xy)) = 1-k^2 m^2
1469 // x(y(2-xy)) == 1 (mod m^2) 1490 // x(y(2-xy)) == 1 (mod m^2)
1470 // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 1491 // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
1471 // Should reduce x and y(2-xy) by m^2 at each step to keep size bounded. 1492 // Should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
1472 // 1493 //
1473 // TODO(regis): Intrinsify this method and provide a 64-bit inverse digit pair
1474 // on 64-bit platforms.
1475 //
1476 // Operation: 1494 // Operation:
1477 // args[_RHO] = 1/args[_X] mod DIGIT_BASE. 1495 // args[_RHO] = 1/args[_X] mod DIGIT_BASE.
1478 // return 1. 1496 static void _invDigit(Uint32List args) {
1479 // Note: intrinsics on 64-bit platform process a digit pair:
1480 // args[_RHO.._RHO_HI] = 1/args[_X.._X_HI] mod DIGIT_BASE^2.
1481 // return 2.
1482 static int _invDigit(Uint32List args) {
1483 var x = args[_X]; 1497 var x = args[_X];
1484 var y = x & 3; // y == 1/x mod 2^2 1498 var y = x & 3; // y == 1/x mod 2^2
1485 y = (y*(2 - (x & 0xf)*y)) & 0xf; // y == 1/x mod 2^4 1499 y = (y*(2 - (x & 0xf)*y)) & 0xf; // y == 1/x mod 2^4
1486 y = (y*(2 - (x & 0xff)*y)) & 0xff; // y == 1/x mod 2^8 1500 y = (y*(2 - (x & 0xff)*y)) & 0xff; // y == 1/x mod 2^8
1487 y = (y*(2 - (((x & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 1501 y = (y*(2 - (((x & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16
1488 // Last step - calculate inverse mod DIGIT_BASE directly; 1502 // Last step - calculate inverse mod DIGIT_BASE directly;
1489 // Assumes 16 < DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints. 1503 // Assumes 16 < DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints.
1490 y = (y*(2 - x*y % _Bigint.DIGIT_BASE)) % _Bigint.DIGIT_BASE; 1504 y = (y*(2 - x*y % _Bigint.DIGIT_BASE)) % _Bigint.DIGIT_BASE;
1491 // y == 1/x mod DIGIT_BASE 1505 // y == 1/x mod DIGIT_BASE
1492 // We really want the negative inverse, and - DIGIT_BASE < y < DIGIT_BASE. 1506 y = -y; // We really want the negative inverse.
1493 args[_RHO] = (y > 0) ? _Bigint.DIGIT_BASE - y : -y; 1507 args[_RHO] = y & _Bigint.DIGIT_MASK;
1494 return 1;
1495 } 1508 }
1496 1509
1510
1511 // Calculates -1/x % DIGIT_BASE^2, x is a pair of 32-bit digits.
1512 // Operation:
1513 // args[_RHO.._RHO_HI] = 1/args[_X.._X_HI] mod DIGIT_BASE^2.
1514 static void _invDigitPair(Uint32List args) {
1515 var xl = args[_X]; // Lower 32-bit digit of x.
1516 var y = xl & 3; // y == 1/x mod 2^2
1517 y = (y*(2 - (xl & 0xf)*y)) & 0xf; // y == 1/x mod 2^4
1518 y = (y*(2 - (xl & 0xff)*y)) & 0xff; // y == 1/x mod 2^8
1519 y = (y*(2 - (((xl & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16
1520 y = (y*(2 - ((xl*y) & 0xffffffff))) & 0xffffffff; // y == 1/x mod 2^32
1521 var x = (args[_X_HI] << _Bigint.DIGIT_BITS) | xl;
1522 y = (y*(2 - ((x*y) & 0xffffffffffffffff))) & 0xffffffffffffffff;
1523 // y == 1/x mod DIGIT_BASE^2
1524 y = -y; // We really want the negative inverse.
1525 args[_RHO] = y & _Bigint.DIGIT_MASK;
1526 args[_RHO_HI] = (y >> _Bigint.DIGIT_BITS) & _Bigint.DIGIT_MASK;
1527 }
1528
1529
1497 // Operation: 1530 // Operation:
1498 // args[_MU] = args[_RHO]*digits[i] mod DIGIT_BASE. 1531 // args[_MU] = args[_RHO]*digits[i] mod DIGIT_BASE.
1499 // return 1. 1532 // return 1.
1500 // Note: intrinsics on 64-bit platform may process a digit pair: 1533 // Note: intrinsics on 64-bit platform may process a digit pair:
1501 // args[_MU.._MU_HI] = args[_RHO.._RHO_HI]*digits[i..i+1] mod DIGIT_BASE^2. 1534 // args[_MU.._MU_HI] = args[_RHO.._RHO_HI]*digits[i..i+1] mod DIGIT_BASE^2.
1502 // return 2. 1535 // return 2.
1503 static int _mulMod(Uint32List args, Uint32List digits, int i) { 1536 static int _mulMod(Uint32List args, Uint32List digits, int i) {
1504 const int MU_MASK = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1; 1537 const int MU_MASK = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1;
1505 var rhol = args[_RHO] & _Bigint.DIGIT2_MASK; 1538 var rhol = args[_RHO] & _Bigint.DIGIT2_MASK;
1506 var rhoh = args[_RHO] >> _Bigint.DIGIT2_BITS; 1539 var rhoh = args[_RHO] >> _Bigint.DIGIT2_BITS;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1600 void _sqrTo(_Bigint x, _Bigint r) { 1633 void _sqrTo(_Bigint x, _Bigint r) {
1601 x._sqrTo(r); 1634 x._sqrTo(r);
1602 _reduce(r); 1635 _reduce(r);
1603 } 1636 }
1604 1637
1605 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { 1638 void _mulTo(_Bigint x, _Bigint y, _Bigint r) {
1606 x._mulTo(y, r); 1639 x._mulTo(y, r);
1607 _reduce(r); 1640 _reduce(r);
1608 } 1641 }
1609 } 1642 }
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/assembler_x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698