dtl-js
Version:
Data Transformation Language - JSON templates and data transformation
79 lines (66 loc) • 2.59 kB
JavaScript
/* =================================================
* Copyright (c) 2015-2024 Jay Kuri
*
* This file is part of DTL.
*
* DTL is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* DTL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with DTL; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* =================================================
*/
// This module provides crypto-compatible randomness
let our_crypto;
if (typeof window === 'undefined' && typeof crypto === 'undefined') {
our_crypto = require('crypto').webcrypto;
} else {
our_crypto = crypto;
}
const getRandomValues = our_crypto.getRandomValues.bind(our_crypto);
// note that a Uint8Array is not strictly an Array
// if you need to push/pop/shift, etc. You should
// use Array.from() on the return value of random_bytes.
function random_bytes(len) {
let byte_array = new Uint8Array(len);
getRandomValues(byte_array);
return byte_array;
}
function random_number_up_to(max) {
let result;
let value_array = new Uint32Array(1);
// this looks odd, but is necessary to remove bias that creeps in
// when our random value is greater than the maximum multiple of max.
// This cleans that up.
const max_acceptable_value = Math.floor((0xFFFFFFFF + 1) / max) * max - 1;
do {
getRandomValues(value_array);
result = value_array[0];
} while (result > max_acceptable_value);
return result % max;
}
function random_float() {
const array = new Uint32Array(2);
getRandomValues(array);
// Use bitwise operations to combine the two 32-bit integers
const high = array[0] & 0x1FFFFF; // 21 bits for high part (keeping within 53 bits)
const low = array[1];
const combined = (high * 2 ** 32) + low;
// Normalize to a floating-point number between 0 and 1
const float = combined / 2 ** 53;
return float;
}
let random_stuff = {
"random_number_up_to": random_number_up_to,
"random_bytes": random_bytes,
"random_float": random_float
};
module.exports = random_stuff;