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

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

Issue 1057053002: Cache the intermediate result of a div (or rem) operation on bigint and reuse if (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 8 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 | no next file » | 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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 static const int _MIN_INT64 = (-1) << 63; 58 static const int _MIN_INT64 = (-1) << 63;
59 static const int _MAX_INT64 = 0x7fffffffffffffff; 59 static const int _MAX_INT64 = 0x7fffffffffffffff;
60 60
61 // Bigint constant values. 61 // Bigint constant values.
62 // Note: Not declared as final in order to satisfy optimizer, which expects 62 // Note: Not declared as final in order to satisfy optimizer, which expects
63 // constants to be in canonical form (Smi). 63 // constants to be in canonical form (Smi).
64 static _Bigint _MINUS_ONE = new _Bigint._fromInt(-1); 64 static _Bigint _MINUS_ONE = new _Bigint._fromInt(-1);
65 static _Bigint _ZERO = new _Bigint._fromInt(0); 65 static _Bigint _ZERO = new _Bigint._fromInt(0);
66 static _Bigint _ONE = new _Bigint._fromInt(1); 66 static _Bigint _ONE = new _Bigint._fromInt(1);
67 67
68 // Result cache for last _divRem call.
69 static Uint32List _lastDividend_digits;
70 static int _lastDividend_used;
71 static Uint32List _lastDivisor_digits;
72 static int _lastDivisor_used;
73 static Uint32List _lastQuoRem_digits;
74 static int _lastQuoRem_used;
75 static int _lastRem_used;
76 static int _lastRem_nsh;
77
68 // Internal data structure. 78 // Internal data structure.
69 bool get _neg native "Bigint_getNeg"; 79 bool get _neg native "Bigint_getNeg";
70 int get _used native "Bigint_getUsed"; 80 int get _used native "Bigint_getUsed";
71 Uint32List get _digits native "Bigint_getDigits"; 81 Uint32List get _digits native "Bigint_getDigits";
72 82
73 // Factory returning an instance initialized with the given field values. 83 // Factory returning an instance initialized with the given field values.
74 // The 'digits' array is first clamped and 'used' is reduced accordingly. 84 // The 'digits' array is first clamped and 'used' is reduced accordingly.
75 // A leading zero digit may be initialized to guarantee that digit pairs can 85 // A leading zero digit may be initialized to guarantee that digit pairs can
76 // be processed as 64-bit values on 64-bit platforms. 86 // be processed as 64-bit values on 64-bit platforms.
77 factory _Bigint(bool neg, int used, Uint32List digits) 87 factory _Bigint(bool neg, int used, Uint32List digits)
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 return new _Bigint(_neg, r_used, r_digits); 195 return new _Bigint(_neg, r_used, r_digits);
186 } 196 }
187 197
188 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n*_DIGIT_BITS. 198 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n*_DIGIT_BITS.
189 // Return r_used. 199 // Return r_used.
190 static int _dlShiftDigits(Uint32List x_digits, int x_used, int n, 200 static int _dlShiftDigits(Uint32List x_digits, int x_used, int n,
191 Uint32List r_digits) { 201 Uint32List r_digits) {
192 if (x_used == 0) { 202 if (x_used == 0) {
193 return 0; 203 return 0;
194 } 204 }
195 if (n == 0 && r_digits == x_digits) { 205 if (n == 0 && identical(r_digits, x_digits)) {
196 return x_used; 206 return x_used;
197 } 207 }
198 final r_used = x_used + n; 208 final r_used = x_used + n;
199 assert(r_digits.length >= r_used + (r_used & 1)); 209 assert(r_digits.length >= r_used + (r_used & 1));
200 var i = x_used; 210 var i = x_used;
201 while (--i >= 0) { 211 while (--i >= 0) {
202 r_digits[i + n] = x_digits[i]; 212 r_digits[i + n] = x_digits[i];
203 } 213 }
204 i = n; 214 i = n;
205 while (--i >= 0) { 215 while (--i >= 0) {
(...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after
937 args[_QD] = _DIGIT_MASK; 947 args[_QD] = _DIGIT_MASK;
938 } else { 948 } else {
939 args[_QD] = qd; 949 args[_QD] = qd;
940 } 950 }
941 } 951 }
942 return 1; 952 return 1;
943 } 953 }
944 954
945 // Return trunc(this / a), a != 0. 955 // Return trunc(this / a), a != 0.
946 _Bigint _div(_Bigint a) { 956 _Bigint _div(_Bigint a) {
947 return _divRem(a, true); 957 assert(a._used > 0);
958 if (_used < a._used) {
959 return _ZERO;
960 }
961 _divRem(a);
962 // Return quotient, i.e.
963 // _lastQuoRem_digits[_lastRem_used.._lastQuoRem_used-1] with proper sign.
964 var lastQuo_used = _lastQuoRem_used - _lastRem_used;
965 var quo_digits = _cloneDigits(_lastQuoRem_digits,
966 _lastRem_used,
967 _lastQuoRem_used,
968 lastQuo_used);
969 var quo = new _Bigint(false, lastQuo_used, quo_digits);
970 if ((_neg != a._neg) && (quo._used > 0)) {
971 quo = quo._negate();
972 }
973 return quo;
948 } 974 }
949 975
950 // Return this - a * trunc(this / a), a != 0. 976 // Return this - a * trunc(this / a), a != 0.
951 _Bigint _rem(_Bigint a) { 977 _Bigint _rem(_Bigint a) {
952 return _divRem(a, false); 978 assert(a._used > 0);
979 if (_used < a._used) {
980 return this;
981 }
982 _divRem(a);
983 // Return remainder, i.e.
984 // denormalized _lastQuoRem_digits[0.._lastRem_used-1] with proper sign.
985 var rem_digits = _cloneDigits(_lastQuoRem_digits,
986 0,
987 _lastRem_used,
988 _lastRem_used);
989 var rem = new _Bigint(false, _lastRem_used, rem_digits);
990 if (_lastRem_nsh > 0) {
991 rem = rem._rShift(_lastRem_nsh); // Denormalize remainder.
992 }
993 if (_neg && (rem._used > 0)) {
994 rem = rem._negate();
995 }
996 return rem;
953 } 997 }
954 998
955 // Return trunc(this / a), a != 0, if div == true. 999 // Cache concatenated positive quotient and normalized positive remainder.
956 // Return this - a * trunc(this / a), a != 0, if div == false. 1000 void _divRem(_Bigint a) {
957 _Bigint _divRem(_Bigint a, bool div) { 1001 // Check if result is already cached (identical on Bigint is too expensive).
958 assert(a._used > 0); 1002 if ((this._used == _lastDividend_used) &&
959 if (_used < a._used) { 1003 (a._used == _lastDivisor_used) &&
960 return div ? _ZERO : this; 1004 identical(this._digits, _lastDividend_digits) &&
1005 identical(a._digits, _lastDivisor_digits)) {
1006 return;
961 } 1007 }
962 var nsh = _DIGIT_BITS - _nbits(a._digits[a._used - 1]); 1008 var nsh = _DIGIT_BITS - _nbits(a._digits[a._used - 1]);
963 // For 64-bit processing, make sure y has an even number of digits. 1009 // For 64-bit processing, make sure y has an even number of digits.
964 if (a._used.isOdd) { 1010 if (a._used.isOdd) {
965 nsh += _DIGIT_BITS; 1011 nsh += _DIGIT_BITS;
966 } 1012 }
967 // Concatenated positive quotient and normalized positive remainder. 1013 // Concatenated positive quotient and normalized positive remainder.
968 var r_digits; 1014 var r_digits;
969 var r_used; 1015 var r_used;
970 // Normalized positive divisor. 1016 // Normalized positive divisor.
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1042 if (yt_qd[_QD] == 0) { 1088 if (yt_qd[_QD] == 0) {
1043 --yt_qd[_QD_HI]; 1089 --yt_qd[_QD_HI];
1044 } 1090 }
1045 --yt_qd[_QD]; 1091 --yt_qd[_QD];
1046 assert(r_digits[i] <= yt_qd[_QD_HI]); 1092 assert(r_digits[i] <= yt_qd[_QD_HI]);
1047 } 1093 }
1048 } 1094 }
1049 } 1095 }
1050 i -= d0; 1096 i -= d0;
1051 } 1097 }
1052 if (div) { 1098 // Cache result.
1053 // Return quotient, i.e. r_digits[y_used..r_used-1] with proper sign. 1099 _lastDividend_digits = _digits;
1054 r_digits = _cloneDigits(r_digits, y_used, r_used, r_used - y_used); 1100 _lastDividend_used = _used;
1055 var r = new _Bigint(false, r_used - y_used, r_digits); 1101 _lastDivisor_digits = a._digits;
1056 if (_neg != a._neg && r._used > 0) { 1102 _lastDivisor_used = a._used;
1057 r = r._negate(); 1103 _lastQuoRem_digits = r_digits;
1058 } 1104 _lastQuoRem_used = r_used;
1059 return r; 1105 _lastRem_used = y_used;
1060 } 1106 _lastRem_nsh = nsh;
1061 // Return remainder, i.e. denormalized r_digits[0..y_used-1] with
1062 // proper sign.
1063 r_digits = _cloneDigits(r_digits, 0, y_used, y_used);
1064 var r = new _Bigint(false, y_used, r_digits);
1065 if (nsh > 0) {
1066 r = r._rShift(nsh); // Denormalize remainder.
1067 }
1068 if (_neg && r._used > 0) {
1069 r = r._negate();
1070 }
1071 return r;
1072 } 1107 }
1073 1108
1074 // Customized version of _rem() minimizing allocations for use in reduction. 1109 // Customized version of _rem() minimizing allocations for use in reduction.
1075 // Input: 1110 // Input:
1076 // x_digits[0..x_used-1]: positive dividend. 1111 // x_digits[0..x_used-1]: positive dividend.
1077 // y_digits[0..y_used-1]: normalized positive divisor. 1112 // y_digits[0..y_used-1]: normalized positive divisor.
1078 // ny_digits[0..y_used-1]: negated y_digits. 1113 // ny_digits[0..y_used-1]: negated y_digits.
1079 // nsh: normalization shift amount. 1114 // nsh: normalization shift amount.
1080 // yt_qd: top y digit(s) and place holder for estimated quotient digit(s). 1115 // yt_qd: top y digit(s) and place holder for estimated quotient digit(s).
1081 // t_digits: temp array of 2*y_used digits. 1116 // t_digits: temp array of 2*y_used digits.
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after
1762 1797
1763 int _mul(Uint32List x_digits, int x_used, 1798 int _mul(Uint32List x_digits, int x_used,
1764 Uint32List y_digits, int y_used, 1799 Uint32List y_digits, int y_used,
1765 Uint32List r_digits) { 1800 Uint32List r_digits) {
1766 var r_used = _Bigint._mulDigits(x_digits, x_used, 1801 var r_used = _Bigint._mulDigits(x_digits, x_used,
1767 y_digits, y_used, 1802 y_digits, y_used,
1768 r_digits); 1803 r_digits);
1769 return _reduce(r_digits, r_used); 1804 return _reduce(r_digits, r_used);
1770 } 1805 }
1771 } 1806 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698