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

Unified Diff: sdk/lib/_internal/lib/js_number.dart

Issue 23645003: Esoteric bit operations. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/intrinsifier_x64.cc ('k') | sdk/lib/core/int.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/_internal/lib/js_number.dart
diff --git a/sdk/lib/_internal/lib/js_number.dart b/sdk/lib/_internal/lib/js_number.dart
index 445e927cbc5165db1d81c3c280129aee7f5a54e5..8dd89d8045e29ce8f0a74dd828a101e9d989961a 100644
--- a/sdk/lib/_internal/lib/js_number.dart
+++ b/sdk/lib/_internal/lib/js_number.dart
@@ -278,6 +278,65 @@ class JSInt extends JSNumber implements int, double {
bool get isOdd => (this & 1) == 1;
+ int toUnsigned(int width) {
+ return this & ((1 << width) - 1);
+ }
+
+ int toSigned(int width) {
+ int signMask = 1 << (width - 1);
+ return (this & (signMask - 1)) - (this & signMask);
+ }
+
+ int get bitLength {
+ int nonneg = this < 0 ? -this-1 : this;
+ if (nonneg >= 0x100000000) {
+ nonneg = nonneg ~/ 0x100000000;
+ return _bitCount(_spread(nonneg)) + 32;
+ }
+ return _bitCount(_spread(nonneg));
+ }
+
+ // Assumes i is <= 32-bit and unsigned.
+ static int _bitCount(int i) {
+ // See "Hacker's Delight", section 5-1, "Counting 1-Bits".
+
+ // The basic strategy is to use "divide and conquer" to
+ // add pairs (then quads, etc.) of bits together to obtain
+ // sub-counts.
+ //
+ // A straightforward approach would look like:
+ //
+ // i = (i & 0x55555555) + ((i >> 1) & 0x55555555);
+ // i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
+ // i = (i & 0x0F0F0F0F) + ((i >> 4) & 0x0F0F0F0F);
+ // i = (i & 0x00FF00FF) + ((i >> 8) & 0x00FF00FF);
+ // i = (i & 0x0000FFFF) + ((i >> 16) & 0x0000FFFF);
+ //
+ // The code below removes unnecessary &'s and uses a
+ // trick to remove one instruction in the first line.
+
+ i = _shru(i, 0) - (_shru(i, 1) & 0x55555555);
+ i = (i & 0x33333333) + (_shru(i, 2) & 0x33333333);
+ i = 0x0F0F0F0F & (i + _shru(i, 4));
+ i += _shru(i, 8);
+ i += _shru(i, 16);
+ return (i & 0x0000003F);
+ }
+
+ static _shru(int value, int shift) => JS('int', '# >>> #', value, shift);
+ static _shrs(int value, int shift) => JS('int', '# >> #', value, shift);
+ static _ors(int a, int b) => JS('int', '# | #', a, b);
+
+ // Assumes i is <= 32-bit
+ static int _spread(int i) {
+ i = _ors(i, _shrs(i, 1));
+ i = _ors(i, _shrs(i, 2));
+ i = _ors(i, _shrs(i, 4));
+ i = _ors(i, _shrs(i, 8));
+ i = _shru(_ors(i, _shrs(i, 16)), 0);
+ return i;
+ }
+
Type get runtimeType => int;
int operator ~() => JS('int', r'(~#) >>> 0', this);
« no previous file with comments | « runtime/vm/intrinsifier_x64.cc ('k') | sdk/lib/core/int.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698