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

Side by Side Diff: tool/input_sdk/private/js_number.dart

Issue 1952043002: Merge in JSNumber changes. (Closed) Base URL: https://github.com/dart-lang/dev_compiler@master
Patch Set: Created 4 years, 7 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
« no previous file with comments | « tool/input_sdk/lib/core/int.dart ('k') | 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 part of dart._interceptors; 5 part of dart._interceptors;
6 6
7 /** 7 /**
8 * The implementation of Dart's int & double methods. 8 * The implementation of Dart's int & double methods.
9 * These are made available as extension methods on `Number` in JS. 9 * These are made available as extension methods on `Number` in JS.
10 */ 10 */
(...skipping 22 matching lines...) Expand all
33 } else { 33 } else {
34 return -1; 34 return -1;
35 } 35 }
36 } 36 }
37 37
38 bool get isNegative => (this == 0) ? (1 / this) < 0 : this < 0; 38 bool get isNegative => (this == 0) ? (1 / this) < 0 : this < 0;
39 39
40 bool get isNaN => JS('bool', r'isNaN(#)', this); 40 bool get isNaN => JS('bool', r'isNaN(#)', this);
41 41
42 bool get isInfinite { 42 bool get isInfinite {
43 return JS('bool', r'# == Infinity', this) 43 return JS('bool', r'# == (1/0)', this)
44 || JS('bool', r'# == -Infinity', this); 44 || JS('bool', r'# == (-1/0)', this);
45 } 45 }
46 46
47 bool get isFinite => JS('bool', r'isFinite(#)', this); 47 bool get isFinite => JS('bool', r'isFinite(#)', this);
48 48
49 JSNumber remainder(num b) { 49 JSNumber remainder(num b) {
50 checkNull(b); // TODO(ngeoffray): This is not specified but co19 tests it. 50 if (b is! num) throw argumentErrorValue(b);
51 return JS('num', r'# % #', this, b); 51 return JS('num', r'# % #', this, b);
52 } 52 }
53 53
54 JSNumber abs() => JS('num', r'Math.abs(#)', this); 54 JSNumber abs() => JS('num', r'Math.abs(#)', this);
55 55
56 JSNumber get sign => this > 0 ? 1 : this < 0 ? -1 : this; 56 JSNumber get sign => this > 0 ? 1 : this < 0 ? -1 : this;
57 57
58 static const int _MIN_INT32 = -0x80000000; 58 static const int _MIN_INT32 = -0x80000000;
59 static const int _MAX_INT32 = 0x7FFFFFFF; 59 static const int _MAX_INT32 = 0x7FFFFFFF;
60 60
61 int toInt() { 61 int toInt() {
62 if (this >= _MIN_INT32 && this <= _MAX_INT32) { 62 if (this >= _MIN_INT32 && this <= _MAX_INT32) {
63 return JS('int', '# | 0', this); 63 return JS('int', '# | 0', this);
64 } 64 }
65 if (JS('bool', r'isFinite(#)', this)) { 65 if (JS('bool', r'isFinite(#)', this)) {
66 return JS('int', r'# + 0', truncateToDouble()); // Converts -0.0 to +0.0. 66 return JS('int', r'# + 0', truncateToDouble()); // Converts -0.0 to +0.0.
67 } 67 }
68 // This is either NaN, Infinity or -Infinity. 68 // This is either NaN, Infinity or -Infinity.
69 throw new UnsupportedError(JS("String", "''+#", this)); 69 throw new UnsupportedError(JS("String", '"" + #', this));
70 } 70 }
71 71
72 int truncate() => toInt(); 72 int truncate() => toInt();
73
73 int ceil() => ceilToDouble().toInt(); 74 int ceil() => ceilToDouble().toInt();
75
74 int floor() => floorToDouble().toInt(); 76 int floor() => floorToDouble().toInt();
75 int round() => roundToDouble().toInt(); 77
78 int round() {
79 if (this > 0) {
80 // This path excludes the special cases -0.0, NaN and -Infinity, leaving
81 // only +Infinity, for which a direct test is faster than [isFinite].
82 if (JS('bool', r'# !== (1/0)', this)) {
83 return JS('int', r'Math.round(#)', this);
84 }
85 } else if (JS('bool', '# > (-1/0)', this)) {
86 // This test excludes NaN and -Infinity, leaving only -0.0.
87 //
88 // Subtraction from zero rather than negation forces -0.0 to 0.0 so code
89 // inside Math.round and code to handle result never sees -0.0, which on
90 // some JavaScript VMs can be a slow path.
91 return JS('int', r'0 - Math.round(0 - #)', this);
92 }
93 // This is either NaN, Infinity or -Infinity.
94 throw new UnsupportedError(JS("String", '"" + #', this));
95 }
76 96
77 double ceilToDouble() => JS('num', r'Math.ceil(#)', this); 97 double ceilToDouble() => JS('num', r'Math.ceil(#)', this);
78 98
79 double floorToDouble() => JS('num', r'Math.floor(#)', this); 99 double floorToDouble() => JS('num', r'Math.floor(#)', this);
80 100
81 double roundToDouble() { 101 double roundToDouble() {
82 if (this < 0) { 102 if (this < 0) {
83 return JS('num', r'-Math.round(-#)', this); 103 return JS('num', r'-Math.round(-#)', this);
84 } else { 104 } else {
85 return JS('num', r'Math.round(#)', this); 105 return JS('num', r'Math.round(#)', this);
86 } 106 }
87 } 107 }
88 108
89 double truncateToDouble() => this < 0 ? ceilToDouble() : floorToDouble(); 109 double truncateToDouble() => this < 0 ? ceilToDouble() : floorToDouble();
90 110
91 num clamp(num lowerLimit, num upperLimit) { 111 num clamp(num lowerLimit, num upperLimit) {
92 if (lowerLimit.compareTo(upperLimit) > 0) { 112 if (lowerLimit.compareTo(upperLimit) > 0) {
93 throw new ArgumentError(lowerLimit); 113 throw argumentErrorValue(lowerLimit);
94 } 114 }
95 if (this.compareTo(lowerLimit) < 0) return lowerLimit; 115 if (this.compareTo(lowerLimit) < 0) return lowerLimit;
96 if (this.compareTo(upperLimit) > 0) return upperLimit; 116 if (this.compareTo(upperLimit) > 0) return upperLimit;
97 return this; 117 return this;
98 } 118 }
99 119
100 double toDouble() => this; 120 double toDouble() => this;
101 121
102 String toStringAsFixed(int fractionDigits) { 122 String toStringAsFixed(int fractionDigits) {
103 checkInt(fractionDigits); 123 checkInt(fractionDigits);
104 if (fractionDigits < 0 || fractionDigits > 20) { 124 if (fractionDigits < 0 || fractionDigits > 20) {
105 throw new RangeError(fractionDigits); 125 throw new RangeError.range(fractionDigits, 0, 20, "fractionDigits");
106 } 126 }
107 String result = JS('String', r'#.toFixed(#)', this, fractionDigits); 127 String result = JS('String', r'#.toFixed(#)', this, fractionDigits);
108 if (this == 0 && isNegative) return "-$result"; 128 if (this == 0 && isNegative) return "-$result";
109 return result; 129 return result;
110 } 130 }
111 131
112 String toStringAsExponential([int fractionDigits]) { 132 String toStringAsExponential([int fractionDigits]) {
113 String result; 133 String result;
114 if (fractionDigits != null) { 134 if (fractionDigits != null) {
115 checkInt(fractionDigits); 135 checkInt(fractionDigits);
116 if (fractionDigits < 0 || fractionDigits > 20) { 136 if (fractionDigits < 0 || fractionDigits > 20) {
117 throw new RangeError(fractionDigits); 137 throw new RangeError.range(fractionDigits, 0, 20, "fractionDigits");
118 } 138 }
119 result = JS('String', r'#.toExponential(#)', this, fractionDigits); 139 result = JS('String', r'#.toExponential(#)', this, fractionDigits);
120 } else { 140 } else {
121 result = JS('String', r'#.toExponential()', this); 141 result = JS('String', r'#.toExponential()', this);
122 } 142 }
123 if (this == 0 && isNegative) return "-$result"; 143 if (this == 0 && isNegative) return "-$result";
124 return result; 144 return result;
125 } 145 }
126 146
127 String toStringAsPrecision(int precision) { 147 String toStringAsPrecision(int precision) {
128 checkInt(precision); 148 checkInt(precision);
129 if (precision < 1 || precision > 21) { 149 if (precision < 1 || precision > 21) {
130 throw new RangeError(precision); 150 throw new RangeError.range(precision, 1, 21, "precision");
131 } 151 }
132 String result = JS('String', r'#.toPrecision(#)', 152 String result = JS('String', r'#.toPrecision(#)',
133 this, precision); 153 this, precision);
134 if (this == 0 && isNegative) return "-$result"; 154 if (this == 0 && isNegative) return "-$result";
135 return result; 155 return result;
136 } 156 }
137 157
138 String toRadixString(int radix) { 158 String toRadixString(int radix) {
139 checkInt(radix); 159 checkInt(radix);
140 if (radix < 2 || radix > 36) throw new RangeError(radix); 160 if (radix < 2 || radix > 36) {
161 throw new RangeError.range(radix, 2, 36, "radix");
162 }
141 String result = JS('String', r'#.toString(#)', this, radix); 163 String result = JS('String', r'#.toString(#)', this, radix);
142 const int rightParenCode = 0x29; 164 const int rightParenCode = 0x29;
143 if (result.codeUnitAt(result.length - 1) != rightParenCode) { 165 if (result.codeUnitAt(result.length - 1) != rightParenCode) {
144 return result; 166 return result;
145 } 167 }
146 return _handleIEtoString(result); 168 return _handleIEtoString(result);
147 } 169 }
148 170
149 static String _handleIEtoString(String result) { 171 static String _handleIEtoString(String result) {
150 // Result is probably IE's untraditional format for large numbers, 172 // Result is probably IE's untraditional format for large numbers,
(...skipping 21 matching lines...) Expand all
172 } else { 194 } else {
173 return JS('String', r'"" + (#)', this); 195 return JS('String', r'"" + (#)', this);
174 } 196 }
175 } 197 }
176 198
177 int get hashCode => JS('int', '# & 0x1FFFFFFF', this); 199 int get hashCode => JS('int', '# & 0x1FFFFFFF', this);
178 200
179 JSNumber operator -() => JS('num', r'-#', this); 201 JSNumber operator -() => JS('num', r'-#', this);
180 202
181 JSNumber operator +(num other) { 203 JSNumber operator +(num other) {
182 checkNull(other); 204 if (other is !num) throw argumentErrorValue(other);
183 return JS('num', '# + #', this, other); 205 return JS('num', '# + #', this, other);
184 } 206 }
185 207
186 JSNumber operator -(num other) { 208 JSNumber operator -(num other) {
187 checkNull(other); 209 if (other is !num) throw argumentErrorValue(other);
188 return JS('num', '# - #', this, other); 210 return JS('num', '# - #', this, other);
189 } 211 }
190 212
191 double operator /(num other) { 213 double operator /(num other) {
192 checkNull(other); 214 if (other is !num) throw argumentErrorValue(other);
193 return JS('double', '# / #', this, other); 215 return JS('num', '# / #', this, other);
194 } 216 }
195 217
196 JSNumber operator *(num other) { 218 JSNumber operator *(num other) {
197 checkNull(other); 219 if (other is !num) throw argumentErrorValue(other);
198 return JS('num', '# * #', this, other); 220 return JS('num', '# * #', this, other);
199 } 221 }
200 222
201 JSNumber operator %(num other) { 223 JSNumber operator %(num other) {
202 checkNull(other); 224 if (other is !num) throw argumentErrorValue(other);
203 // Euclidean Modulo. 225 // Euclidean Modulo.
204 num result = JS('num', r'# % #', this, other); 226 num result = JS('num', r'# % #', this, other);
205 if (result == 0) return (0 as JSNumber); // Make sure we don't return -0.0. 227 if (result == 0) return (0 as JSNumber); // Make sure we don't return -0.0.
206 if (result > 0) return result; 228 if (result > 0) return result;
207 if (JS('num', '#', other) < 0) { 229 if (JS('num', '#', other) < 0) {
208 return result - JS('num', '#', other); 230 return result - JS('num', '#', other);
209 } else { 231 } else {
210 return result + JS('num', '#', other); 232 return result + JS('num', '#', other);
211 } 233 }
212 } 234 }
213 235
214 bool _isInt32(value) => JS('bool', '(# | 0) === #', value, value); 236 bool _isInt32(value) => JS('bool', '(# | 0) === #', value, value);
215 237
216 int operator ~/(num other) { 238 int operator ~/(num other) {
217 if (_isInt32(this) && _isInt32(other) && 0 != other && -1 != other) { 239 if (_isInt32(this) && _isInt32(other) && 0 != other && -1 != other) {
218 return JS('int', r'(# / #) | 0', this, other); 240 return JS('int', r'(# / #) | 0', this, other);
219 } else { 241 } else {
220 return _tdivSlow(other); 242 return _tdivSlow(other);
221 } 243 }
222 } 244 }
223 245
224 int _tdivSlow(num other) { 246 int _tdivSlow(num other) {
225 checkNull(other); 247 if (other is !num) throw argumentErrorValue(other);
226 return (JS('num', r'# / #', this, other)).toInt(); 248 return (JS('num', r'# / #', this, other)).toInt();
227 } 249 }
228 250
229 // TODO(ngeoffray): Move the bit operations below to [JSInt] and 251 // TODO(ngeoffray): Move the bit operations below to [JSInt] and
230 // make them take an int. Because this will make operations slower, 252 // make them take an int. Because this will make operations slower,
231 // we define these methods on number for now but we need to decide 253 // we define these methods on number for now but we need to decide
232 // the grain at which we do the type checks. 254 // the grain at which we do the type checks.
233 255
234 int operator <<(num other) { 256 int operator <<(num other) {
235 if (other < 0) throw new ArgumentError(other); 257 if (other is !num) throw argumentErrorValue(other);
258 if (JS('num', '#', other) < 0) throw argumentErrorValue(other);
236 return _shlPositive(other); 259 return _shlPositive(other);
237 } 260 }
238 261
239 int _shlPositive(num other) { 262 int _shlPositive(num other) {
240 // JavaScript only looks at the last 5 bits of the shift-amount. Shifting 263 // JavaScript only looks at the last 5 bits of the shift-amount. Shifting
241 // by 33 is hence equivalent to a shift by 1. 264 // by 33 is hence equivalent to a shift by 1.
242 return JS('bool', r'# > 31', other) 265 return JS('bool', r'# > 31', other)
243 ? 0 266 ? 0
244 : JS('int', r'(# << #) >>> 0', this, other); 267 : JS('int', r'(# << #) >>> 0', this, other);
245 } 268 }
246 269
247 int operator >>(num other) { 270 int operator >>(num other) {
248 if (other < 0) throw new ArgumentError(other); 271 if (other is !num) throw argumentErrorValue(other);
272 if (JS('num', '#', other) < 0) throw argumentErrorValue(other);
249 return _shrOtherPositive(other); 273 return _shrOtherPositive(other);
250 } 274 }
251 275
252 int _shrOtherPositive(num other) { 276 int _shrOtherPositive(num other) {
253 return JS('num', '#', this) > 0 277 return JS('num', '#', this) > 0
254 ? _shrBothPositive(other) 278 ? _shrBothPositive(other)
255 // For negative numbers we just clamp the shift-by amount. 279 // For negative numbers we just clamp the shift-by amount.
256 // `this` could be negative but not have its 31st bit set. 280 // `this` could be negative but not have its 31st bit set.
257 // The ">>" would then shift in 0s instead of 1s. Therefore 281 // The ">>" would then shift in 0s instead of 1s. Therefore
258 // we cannot simply return 0xFFFFFFFF. 282 // we cannot simply return 0xFFFFFFFF.
259 : JS('int', r'(# >> #) >>> 0', this, other > 31 ? 31 : other); 283 : JS('int', r'(# >> #) >>> 0', this, other > 31 ? 31 : other);
260 } 284 }
261 285
262 int _shrBothPositive(num other) { 286 int _shrBothPositive(num other) {
263 return JS('bool', r'# > 31', other) 287 return JS('bool', r'# > 31', other)
264 // JavaScript only looks at the last 5 bits of the shift-amount. In JS 288 // JavaScript only looks at the last 5 bits of the shift-amount. In JS
265 // shifting by 33 is hence equivalent to a shift by 1. Shortcut the 289 // shifting by 33 is hence equivalent to a shift by 1. Shortcut the
266 // computation when that happens. 290 // computation when that happens.
267 ? 0 291 ? 0
268 // Given that `this` is positive we must not use '>>'. Otherwise a 292 // Given that `this` is positive we must not use '>>'. Otherwise a
269 // number that has the 31st bit set would be treated as negative and 293 // number that has the 31st bit set would be treated as negative and
270 // shift in ones. 294 // shift in ones.
271 : JS('int', r'# >>> #', this, other); 295 : JS('int', r'# >>> #', this, other);
272 } 296 }
273 297
274 int operator &(num other) { 298 int operator &(num other) {
275 checkNull(other); 299 if (other is !num) throw argumentErrorValue(other);
276 return JS('int', r'(# & #) >>> 0', this, other); 300 return JS('int', r'(# & #) >>> 0', this, other);
277 } 301 }
278 302
279 int operator |(num other) { 303 int operator |(num other) {
280 checkNull(other); 304 if (other is !num) throw argumentErrorValue(other);
281 return JS('int', r'(# | #) >>> 0', this, other); 305 return JS('int', r'(# | #) >>> 0', this, other);
282 } 306 }
283 307
284 int operator ^(num other) { 308 int operator ^(num other) {
285 checkNull(other); 309 if (other is !num) throw argumentErrorValue(other);
286 return JS('int', r'(# ^ #) >>> 0', this, other); 310 return JS('int', r'(# ^ #) >>> 0', this, other);
287 } 311 }
288 312
289 bool operator <(num other) { 313 bool operator <(num other) {
290 checkNull(other); 314 if (other is !num) throw argumentErrorValue(other);
291 return JS('bool', '# < #', this, other); 315 return JS('bool', '# < #', this, other);
292 } 316 }
293 317
294 bool operator >(num other) { 318 bool operator >(num other) {
295 checkNull(other); 319 if (other is !num) throw argumentErrorValue(other);
296 return JS('bool', '# > #', this, other); 320 return JS('bool', '# > #', this, other);
297 } 321 }
298 322
299 bool operator <=(num other) { 323 bool operator <=(num other) {
300 checkNull(other); 324 if (other is !num) throw argumentErrorValue(other);
301 return JS('bool', '# <= #', this, other); 325 return JS('bool', '# <= #', this, other);
302 } 326 }
303 327
304 bool operator >=(num other) { 328 bool operator >=(num other) {
305 checkNull(other); 329 if (other is !num) throw argumentErrorValue(other);
306 return JS('bool', '# >= #', this, other); 330 return JS('bool', '# >= #', this, other);
307 } 331 }
308 332
309 // int members. 333 // int members.
310 // TODO(jmesserly): all numbers will have these in dynamic dispatch. 334 // TODO(jmesserly): all numbers will have these in dynamic dispatch.
311 // We can fix by checking it at dispatch time but we'd need to structure them 335 // We can fix by checking it at dispatch time but we'd need to structure them
312 // differently. 336 // differently.
313 337
314 bool get isEven => (this & 1) == 0; 338 bool get isEven => (this & 1) == 0;
315 339
(...skipping 10 matching lines...) Expand all
326 350
327 int get bitLength { 351 int get bitLength {
328 int nonneg = this < 0 ? -this - 1 : this; 352 int nonneg = this < 0 ? -this - 1 : this;
329 if (nonneg >= 0x100000000) { 353 if (nonneg >= 0x100000000) {
330 nonneg = nonneg ~/ 0x100000000; 354 nonneg = nonneg ~/ 0x100000000;
331 return _bitCount(_spread(nonneg)) + 32; 355 return _bitCount(_spread(nonneg)) + 32;
332 } 356 }
333 return _bitCount(_spread(nonneg)); 357 return _bitCount(_spread(nonneg));
334 } 358 }
335 359
360 // Returns pow(this, e) % m.
361 int modPow(int e, int m) {
362 if (e is! int) {
363 throw new ArgumentError.value(e, "exponent", "not an integer");
364 }
365 if (m is! int) {
366 throw new ArgumentError.value(m, "modulus", "not an integer");
367 }
368 if (e < 0) throw new RangeError.range(e, 0, null, "exponent");
369 if (m <= 0) throw new RangeError.range(m, 1, null, "modulus");
370 if (e == 0) return 1;
371 int b = this;
372 if (b < 0 || b > m) {
373 b %= m;
374 }
375 int r = 1;
376 while (e > 0) {
377 if (e.isOdd) {
378 r = (r * b) % m;
379 }
380 e ~/= 2;
381 b = (b * b) % m;
382 }
383 return r;
384 }
385
386 // If inv is false, returns gcd(x, y).
387 // If inv is true and gcd(x, y) = 1, returns d, so that c*x + d*y = 1.
388 // If inv is true and gcd(x, y) != 1, throws Exception("Not coprime").
389 static int _binaryGcd(int x, int y, bool inv) {
390 int s = 1;
391 if (!inv) {
392 while (x.isEven && y.isEven) {
393 x ~/= 2;
394 y ~/= 2;
395 s *= 2;
396 }
397 if (y.isOdd) {
398 var t = x;
399 x = y;
400 y = t;
401 }
402 }
403 final bool ac = x.isEven;
404 int u = x;
405 int v = y;
406 int a = 1,
407 b = 0,
408 c = 0,
409 d = 1;
410 do {
411 while (u.isEven) {
412 u ~/= 2;
413 if (ac) {
414 if (!a.isEven || !b.isEven) {
415 a += y;
416 b -= x;
417 }
418 a ~/= 2;
419 } else if (!b.isEven) {
420 b -= x;
421 }
422 b ~/= 2;
423 }
424 while (v.isEven) {
425 v ~/= 2;
426 if (ac) {
427 if (!c.isEven || !d.isEven) {
428 c += y;
429 d -= x;
430 }
431 c ~/= 2;
432 } else if (!d.isEven) {
433 d -= x;
434 }
435 d ~/= 2;
436 }
437 if (u >= v) {
438 u -= v;
439 if (ac) a -= c;
440 b -= d;
441 } else {
442 v -= u;
443 if (ac) c -= a;
444 d -= b;
445 }
446 } while (u != 0);
447 if (!inv) return s*v;
448 if (v != 1) throw new Exception("Not coprime");
449 if (d < 0) {
450 d += x;
451 if (d < 0) d += x;
452 } else if (d > x) {
453 d -= x;
454 if (d > x) d -= x;
455 }
456 return d;
457 }
458
459 // Returns 1/this % m, with m > 0.
460 int modInverse(int m) {
461 if (m is! int) {
462 throw new ArgumentError.value(m, "modulus", "not an integer");
463 }
464 if (m <= 0) throw new RangeError.range(m, 1, null, "modulus");
465 if (m == 1) return 0;
466 int t = this;
467 if ((t < 0) || (t >= m)) t %= m;
468 if (t == 1) return 1;
469 if ((t == 0) || (t.isEven && m.isEven)) {
470 throw new Exception("Not coprime");
471 }
472 return _binaryGcd(m, t, true);
473 }
474
475 // Returns gcd of abs(this) and abs(other).
476 int gcd(int other) {
477 if (other is! int) {
478 throw new ArgumentError.value(other, "other", "not an integer");
479 }
480 int x = this.abs();
481 int y = other.abs();
482 if (x == 0) return y;
483 if (y == 0) return x;
484 if ((x == 1) || (y == 1)) return 1;
485 return _binaryGcd(x, y, false);
486 }
487
336 // Assumes i is <= 32-bit and unsigned. 488 // Assumes i is <= 32-bit and unsigned.
337 static int _bitCount(int i) { 489 static int _bitCount(int i) {
338 // See "Hacker's Delight", section 5-1, "Counting 1-Bits". 490 // See "Hacker's Delight", section 5-1, "Counting 1-Bits".
339 491
340 // The basic strategy is to use "divide and conquer" to 492 // The basic strategy is to use "divide and conquer" to
341 // add pairs (then quads, etc.) of bits together to obtain 493 // add pairs (then quads, etc.) of bits together to obtain
342 // sub-counts. 494 // sub-counts.
343 // 495 //
344 // A straightforward approach would look like: 496 // A straightforward approach would look like:
345 // 497 //
(...skipping 23 matching lines...) Expand all
369 i = _ors(i, _shrs(i, 1)); 521 i = _ors(i, _shrs(i, 1));
370 i = _ors(i, _shrs(i, 2)); 522 i = _ors(i, _shrs(i, 2));
371 i = _ors(i, _shrs(i, 4)); 523 i = _ors(i, _shrs(i, 4));
372 i = _ors(i, _shrs(i, 8)); 524 i = _ors(i, _shrs(i, 8));
373 i = _shru(_ors(i, _shrs(i, 16)), 0); 525 i = _shru(_ors(i, _shrs(i, 16)), 0);
374 return i; 526 return i;
375 } 527 }
376 528
377 int operator ~() => JS('int', r'(~#) >>> 0', this); 529 int operator ~() => JS('int', r'(~#) >>> 0', this);
378 } 530 }
OLDNEW
« no previous file with comments | « tool/input_sdk/lib/core/int.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698