OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2007 Apple Inc. All rights reserved. | 2 * Copyright (C) 2007 Apple Inc. All rights reserved. |
3 * Copyright (C) 2012 Google Inc. All rights reserved. | 3 * Copyright (C) 2012 Google Inc. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * | 8 * |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
247 */ | 247 */ |
248 value: function() | 248 value: function() |
249 { | 249 { |
250 var keys = {}; | 250 var keys = {}; |
251 for (var i = 0; i < this.length; ++i) | 251 for (var i = 0; i < this.length; ++i) |
252 keys[this[i]] = true; | 252 keys[this[i]] = true; |
253 return keys; | 253 return keys; |
254 } | 254 } |
255 }); | 255 }); |
256 | 256 |
257 Object.defineProperty(Array.prototype, "upperBound", | |
258 { | |
259 /** | |
260 * @this {Array.<number>} | |
261 */ | |
262 value: function(value) | |
263 { | |
264 var first = 0; | |
265 var count = this.length; | |
266 while (count > 0) { | |
267 var step = count >> 1; | |
268 var middle = first + step; | |
269 if (value >= this[middle]) { | |
270 first = middle + 1; | |
271 count -= step + 1; | |
272 } else | |
273 count = step; | |
274 } | |
275 return first; | |
276 } | |
277 }); | |
278 | |
279 Object.defineProperty(Array.prototype, "rotate", | 257 Object.defineProperty(Array.prototype, "rotate", |
280 { | 258 { |
281 /** | 259 /** |
282 * @this {Array.<*>} | 260 * @this {Array.<*>} |
283 * @param {number} index | 261 * @param {number} index |
284 * @return {Array.<*>} | 262 * @return {Array.<*>} |
285 */ | 263 */ |
286 value: function(index) | 264 value: function(index) |
287 { | 265 { |
288 var result = []; | 266 var result = []; |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
383 if (pivotPosition === k) | 361 if (pivotPosition === k) |
384 return this[k]; | 362 return this[k]; |
385 else if (pivotPosition > k) | 363 else if (pivotPosition > k) |
386 high = pivotPosition - 1; | 364 high = pivotPosition - 1; |
387 else | 365 else |
388 low = pivotPosition + 1; | 366 low = pivotPosition + 1; |
389 } | 367 } |
390 } | 368 } |
391 }); | 369 }); |
392 | 370 |
393 /** | 371 Object.defineProperty(Array.prototype, "lowerBound", |
394 * @param {*} object | |
395 * @param {Array.<*>} array | |
396 * @param {function(*, *):number} comparator | |
397 */ | |
398 function binarySearch(object, array, comparator) | |
399 { | 372 { |
400 var first = 0; | 373 /** |
401 var last = array.length - 1; | 374 * Return index of the leftmost element that is equal or greater |
375 * than the specimen object. If there's no such element (i.e. all | |
376 * elements are smaller than the specimen) returns array.length. | |
377 * The function works for sorted array. | |
378 * | |
379 * @this {Array.<*>} | |
380 * @param {*} object | |
381 * @param {function(*, *): number=} comparator | |
382 * @return {number} | |
383 */ | |
384 value: function(object, comparator) | |
385 { | |
386 comparator = comparator || function(a, b) { return a - b; } | |
caseq
2013/07/08 13:32:16
nit: we don't inline non-empty anonymous functions
alph
2013/07/08 14:32:28
Done.
| |
387 var l = 0; | |
388 var r = this.length; | |
389 while (l < r) { | |
390 var m = (l + r) >> 1; | |
391 if (comparator(object, this[m]) > 0) | |
392 l = m + 1; | |
393 else | |
394 r = m; | |
395 } | |
396 return r; | |
397 } | |
398 }); | |
402 | 399 |
403 while (first <= last) { | 400 Object.defineProperty(Array.prototype, "upperBound", |
404 var mid = (first + last) >> 1; | 401 { |
405 var c = comparator(object, array[mid]); | 402 /** |
406 if (c > 0) | 403 * Return index of the leftmost element that is greater |
407 first = mid + 1; | 404 * than the specimen object. If there's no such element (i.e. all |
408 else if (c < 0) | 405 * elements are smaller than the specimen) returns array.length. |
409 last = mid - 1; | 406 * The function works for sorted array. |
410 else | 407 * |
411 return mid; | 408 * @this {Array.<*>} |
409 * @param {*} object | |
410 * @param {function(*, *): number=} comparator | |
411 * @return {number} | |
412 */ | |
413 value: function(object, comparator) | |
414 { | |
415 comparator = comparator || function(a, b) { return a - b; } | |
416 var l = 0; | |
417 var r = this.length; | |
418 while (l < r) { | |
419 var m = (l + r) >> 1; | |
420 if (comparator(object, this[m]) >= 0) | |
421 l = m + 1; | |
caseq
2013/07/08 13:32:16
This one looks wrong.
alph
2013/07/08 14:32:28
Looks correct to me. It the object is greater (or
caseq
2013/07/08 14:57:45
Sorry, I take it back. lgtm.
| |
422 else | |
423 r = m; | |
424 } | |
425 return r; | |
412 } | 426 } |
413 | 427 }); |
414 // Return the nearest lesser index negated minus 2, i.e.: | |
415 // "-1" means "-1", "-2" means "0, "-3" means "1", etc. | |
416 return -(first + 1); | |
417 } | |
418 | 428 |
419 Object.defineProperty(Array.prototype, "binaryIndexOf", | 429 Object.defineProperty(Array.prototype, "binaryIndexOf", |
420 { | 430 { |
421 /** | 431 /** |
422 * @this {Array.<*>} | 432 * @this {Array.<*>} |
423 * @param {function(*, *):number} comparator | 433 * @param {*} value |
434 * @param {function(*, *): number} comparator | |
435 * @return {number} | |
424 */ | 436 */ |
425 value: function(value, comparator) | 437 value: function(value, comparator) |
426 { | 438 { |
427 var result = binarySearch(value, this, comparator); | 439 var index = this.lowerBound(value, comparator); |
428 return result >= 0 ? result : -1; | 440 return index < this.length && comparator(value, this[index]) === 0 ? ind ex : -1; |
429 } | 441 } |
430 }); | 442 }); |
431 | 443 |
432 Object.defineProperty(Array.prototype, "select", | 444 Object.defineProperty(Array.prototype, "select", |
433 { | 445 { |
434 /** | 446 /** |
435 * @this {Array.<*>} | 447 * @this {Array.<*>} |
436 * @param {string} field | 448 * @param {string} field |
437 * @return {Array.<*>} | 449 * @return {Array.<*>} |
438 */ | 450 */ |
(...skipping 12 matching lines...) Expand all Loading... | |
451 * @this {Array.<*>} | 463 * @this {Array.<*>} |
452 * @return {*} | 464 * @return {*} |
453 */ | 465 */ |
454 value: function() | 466 value: function() |
455 { | 467 { |
456 return this[this.length - 1]; | 468 return this[this.length - 1]; |
457 } | 469 } |
458 }); | 470 }); |
459 | 471 |
460 /** | 472 /** |
461 * @param {*} anObject | 473 * @param {*} object |
462 * @param {Array.<*>} aList | 474 * @param {Array.<*>} list |
463 * @param {function(*, *)} aFunction | 475 * @param {function(*, *): number=} comparator |
464 * @param {boolean=} insertionIndexAfter | 476 * @param {boolean=} insertionIndexAfter |
477 * @return {number} | |
465 */ | 478 */ |
466 function insertionIndexForObjectInListSortedByFunction(anObject, aList, aFunctio n, insertionIndexAfter) | 479 function insertionIndexForObjectInListSortedByFunction(object, list, comparator, insertionIndexAfter) |
467 { | 480 { |
468 var index = binarySearch(anObject, aList, aFunction); | 481 if (insertionIndexAfter) |
469 if (index < 0) { | 482 return list.upperBound(object, comparator); |
470 // See binarySearch implementation. | 483 else |
471 return -index - 1; | 484 return list.lowerBound(object, comparator); |
472 } | |
473 | |
474 if (!insertionIndexAfter) { | |
475 // Return the first occurence of an item in the list. | |
476 while (index > 0 && aFunction(anObject, aList[index - 1]) === 0) | |
477 index--; | |
478 return index; | |
479 } | |
480 // Return the last occurence of an item in the list. | |
481 while (index < aList.length && aFunction(anObject, aList[index]) === 0) | |
482 index++; | |
483 return index; | |
484 } | 485 } |
485 | 486 |
486 /** | 487 /** |
487 * @param {string} format | 488 * @param {string} format |
488 * @param {...*} var_arg | 489 * @param {...*} var_arg |
489 */ | 490 */ |
490 String.sprintf = function(format, var_arg) | 491 String.sprintf = function(format, var_arg) |
491 { | 492 { |
492 return String.vsprintf(format, Array.prototype.slice.call(arguments, 1)); | 493 return String.vsprintf(format, Array.prototype.slice.call(arguments, 1)); |
493 } | 494 } |
(...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1189 console.assert(this._pendingIncomingCallbacksCount > 0); | 1190 console.assert(this._pendingIncomingCallbacksCount > 0); |
1190 if (userCallback) { | 1191 if (userCallback) { |
1191 var args = Array.prototype.slice.call(arguments, 1); | 1192 var args = Array.prototype.slice.call(arguments, 1); |
1192 userCallback.apply(null, args); | 1193 userCallback.apply(null, args); |
1193 } | 1194 } |
1194 if (!--this._pendingIncomingCallbacksCount && this._outgoingCallback) | 1195 if (!--this._pendingIncomingCallbacksCount && this._outgoingCallback) |
1195 this._outgoingCallback(); | 1196 this._outgoingCallback(); |
1196 } | 1197 } |
1197 } | 1198 } |
1198 | 1199 |
OLD | NEW |