mirror of
https://github.com/JasonYANG170/IOTConnect-Web.git
synced 2024-11-23 20:26:28 +00:00
77 lines
3.4 KiB
JavaScript
77 lines
3.4 KiB
JavaScript
|
(function (global, factory) {
|
||
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
||
|
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
||
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.fastUniqueNumbers = {}));
|
||
|
})(this, (function (exports) { 'use strict';
|
||
|
|
||
|
var createAddUniqueNumber = function createAddUniqueNumber(generateUniqueNumber) {
|
||
|
return function (set) {
|
||
|
var number = generateUniqueNumber(set);
|
||
|
set.add(number);
|
||
|
return number;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
var createCache = function createCache(lastNumberWeakMap) {
|
||
|
return function (collection, nextNumber) {
|
||
|
lastNumberWeakMap.set(collection, nextNumber);
|
||
|
return nextNumber;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* The value of the constant Number.MAX_SAFE_INTEGER equals (2 ** 53 - 1) but it
|
||
|
* is fairly new.
|
||
|
*/
|
||
|
var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER === undefined ? 9007199254740991 : Number.MAX_SAFE_INTEGER;
|
||
|
var TWO_TO_THE_POWER_OF_TWENTY_NINE = 536870912;
|
||
|
var TWO_TO_THE_POWER_OF_THIRTY = TWO_TO_THE_POWER_OF_TWENTY_NINE * 2;
|
||
|
var createGenerateUniqueNumber = function createGenerateUniqueNumber(cache, lastNumberWeakMap) {
|
||
|
return function (collection) {
|
||
|
var lastNumber = lastNumberWeakMap.get(collection);
|
||
|
/*
|
||
|
* Let's try the cheapest algorithm first. It might fail to produce a new
|
||
|
* number, but it is so cheap that it is okay to take the risk. Just
|
||
|
* increase the last number by one or reset it to 0 if we reached the upper
|
||
|
* bound of SMIs (which stands for small integers). When the last number is
|
||
|
* unknown it is assumed that the collection contains zero based consecutive
|
||
|
* numbers.
|
||
|
*/
|
||
|
var nextNumber = lastNumber === undefined ? collection.size : lastNumber < TWO_TO_THE_POWER_OF_THIRTY ? lastNumber + 1 : 0;
|
||
|
if (!collection.has(nextNumber)) {
|
||
|
return cache(collection, nextNumber);
|
||
|
}
|
||
|
/*
|
||
|
* If there are less than half of 2 ** 30 numbers stored in the collection,
|
||
|
* the chance to generate a new random number in the range from 0 to 2 ** 30
|
||
|
* is at least 50%. It's benifitial to use only SMIs because they perform
|
||
|
* much better in any environment based on V8.
|
||
|
*/
|
||
|
if (collection.size < TWO_TO_THE_POWER_OF_TWENTY_NINE) {
|
||
|
while (collection.has(nextNumber)) {
|
||
|
nextNumber = Math.floor(Math.random() * TWO_TO_THE_POWER_OF_THIRTY);
|
||
|
}
|
||
|
return cache(collection, nextNumber);
|
||
|
}
|
||
|
// Quickly check if there is a theoretical chance to generate a new number.
|
||
|
if (collection.size > MAX_SAFE_INTEGER) {
|
||
|
throw new Error('Congratulations, you created a collection of unique numbers which uses all available integers!');
|
||
|
}
|
||
|
// Otherwise use the full scale of safely usable integers.
|
||
|
while (collection.has(nextNumber)) {
|
||
|
nextNumber = Math.floor(Math.random() * MAX_SAFE_INTEGER);
|
||
|
}
|
||
|
return cache(collection, nextNumber);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
var LAST_NUMBER_WEAK_MAP = new WeakMap();
|
||
|
var cache = createCache(LAST_NUMBER_WEAK_MAP);
|
||
|
var generateUniqueNumber = createGenerateUniqueNumber(cache, LAST_NUMBER_WEAK_MAP);
|
||
|
var addUniqueNumber = createAddUniqueNumber(generateUniqueNumber);
|
||
|
|
||
|
exports.addUniqueNumber = addUniqueNumber;
|
||
|
exports.generateUniqueNumber = generateUniqueNumber;
|
||
|
|
||
|
}));
|