Skip to content

Commit 4c41226

Browse files
author
Chris Cavalea
committed
update to use crypto when available
1 parent 171933e commit 4c41226

22 files changed

+76
-54
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
## 1.0.1
2+
* updated default engine to use native Crypto, with Math.random as fallback.
3+
4+
## 1.0.0
5+
Initial release.

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import { bool, intRange } from 'aimless.js'
3636

3737
## Using Custom PRNG
3838

39-
Aimless.js is compatible with any custom PRNG that returns a number between 0 and 1 inclusively. Every function accepts an `engine` to be used. Every function will default to using `Math.random` if no `engine` is provided.
39+
Aimless.js is compatible with any custom PRNG that returns a number `num >= 0` and `num < 1`. Every function accepts an `engine` to be used. Every function will default to using the provided `defaultEngine` if no `engine` is provided. The `defaultEngine` uses `crypto.getrandomvalues` when available, with a fallback of `Math.random`.
4040

4141
```es6
4242
import { bool } from 'aimless.js'
@@ -200,7 +200,7 @@ Returns either `-1` or `1`.
200200

201201
### uniqFuncIntRange(min, max, engine)
202202

203-
Returns a **unique** random number between `min` and `max`, using the provided `engine`. If no `engine` is passed, `Math.random` will be used. If there are no unique values left to return, `null` will be returned.
203+
Returns a **unique** random number between `min` and `max`, using the provided `engine`. If no `engine` is passed, the defaultEngine will be used. If there are no unique values left to return, `null` will be returned.
204204

205205
```es6
206206
const uniqueRNG = uniqFuncIntRange(1, 3)
@@ -212,7 +212,7 @@ uniqueRNG() // null
212212

213213
### uniqFuncSequence(array, engine)
214214

215-
Returns a **unique** random number from the provided `array`, using the provided `engine`. If no `engine` is passed, `Math.random` will be used. If there are no unique values left to return, `null` will be returned.
215+
Returns a **unique** random number from the provided `array`, using the provided `engine`. If no `engine` is passed, the defaultEngine will be used. If there are no unique values left to return, `null` will be returned.
216216

217217
```es6
218218
const uniqueRNG = uniqFuncSequence([10, 20, 30])
@@ -249,4 +249,4 @@ Aimless relies on ES5 array methods, and is supported in all modern browsers. S
249249

250250
## License
251251

252-
[MIT](https://opensource.org/licenses/MIT). © 2023 Christopher Cavalea
252+
[MIT](https://opensource.org/licenses/MIT). © 2023 Christopher Cavalea

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"main": "dist/aimless.js",
55
"module": "dist/aimless.module.js",
66
"jsnext:main": "dist/aimless.module.js",
7-
"version": "1.0.0",
7+
"version": "1.0.1",
88
"license": "MIT",
99
"repository": "ChrisCavs/aimless.js",
1010
"author": {

src/bool.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { intRange } from './int-range'
2-
import { generateCurry } from './utils'
2+
import { defaultEngine, generateCurry } from './utils'
33

44
/**
55
* Returns a random boolean (true or false)
66
* @param engine PRNG of choice
77
*/
8-
const bool = (engine = Math.random) => {
8+
const bool = (engine = defaultEngine) => {
99
return !!intRange(0, 1, engine)
1010
}
1111

src/char.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { intRange } from './int-range'
2-
import { generateCurry } from './utils'
2+
import { defaultEngine, generateCurry } from './utils'
33

44
/**
55
* Returns a random character from the provided array
66
* @param str String
77
* @param engine PRNG of choice
88
*/
9-
const char = (str, engine = Math.random) => {
9+
const char = (str, engine = defaultEngine) => {
1010
return str[intRange(0, str.length - 1, engine)]
1111
}
1212

src/custom-dist.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { generateCurry } from "./utils"
1+
import { defaultEngine, generateCurry } from "./utils"
22

33
/**
44
* Returns a random value that follows a custom distribution
55
* @param func Distribution function that accepts a random number between 0 and 1
66
* @param engine PRNG of choice
77
*/
8-
const customDist = (func, engine = Math.random) => {
8+
const customDist = (func, engine = defaultEngine) => {
99
return func(engine())
1010
}
1111

src/exponential-dist.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { generateCurry } from "./utils"
1+
import { defaultEngine, generateCurry } from "./utils"
22

33
/**
44
* Returns a random value that follows an exponential distribution
55
* @param lambda Lambda
66
* @param engine PRNG of choice
77
*/
8-
const exponentialDist = (lambda, engine = Math.random) => {
8+
const exponentialDist = (lambda, engine = defaultEngine) => {
99
return -Math.log(1 - engine()) / lambda
1010
}
1111

src/float-range.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { generateCurry } from "./utils"
1+
import { defaultEngine, generateCurry } from "./utils"
22

33
/**
44
* Returns a random number within the float range
55
* @param min Minimum value
66
* @param max Maximum value
77
* @param engine PRNG of choice
88
*/
9-
const floatRange = (min, max, engine = Math.random) => {
9+
const floatRange = (min, max, engine = defaultEngine) => {
1010
return engine() * (max - min) + min
1111
}
1212

src/int-range.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { generateCurry, randIntRange } from './utils'
1+
import { defaultEngine, generateCurry, randIntRange } from './utils'
22

33
/**
44
* Returns a random number within the integer range
55
* @param min Minimum integer
66
* @param max Maximum integer
77
* @param engine PRNG of choice
88
*/
9-
const intRange = (min, max, engine = Math.random) => {
9+
const intRange = (min, max, engine = defaultEngine) => {
1010
return randIntRange(min, max, engine)
1111
}
1212

src/int-sequence.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { generateCurry, generateListFromRange } from './utils'
1+
import { defaultEngine, generateCurry, generateListFromRange } from './utils'
22
import { sequence } from './sequence'
33

44
/**
@@ -7,7 +7,7 @@ import { sequence } from './sequence'
77
* @param max Maximum value
88
* @param engine PRNG of choice
99
*/
10-
const intSequence = (min, max, engine = Math.random) => {
10+
const intSequence = (min, max, engine = defaultEngine) => {
1111
return sequence(
1212
generateListFromRange(min, max),
1313
engine

src/normal-dist.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { generateCurry } from "./utils"
1+
import { defaultEngine, generateCurry } from "./utils"
22

33
/**
44
* Returns a random value that follows a normal distribution
55
* @param mean Mean
66
* @param stdDev Standard Deviation
77
* @param engine PRNG of choice
88
*/
9-
const normalDist = (mean, stdDev, engine = Math.random) => {
9+
const normalDist = (mean, stdDev, engine = defaultEngine) => {
1010
// Box-Muller transform
1111
let u, v, s
1212

src/normal-float.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { floatRange } from './float-range'
2-
import { generateCurry } from './utils'
2+
import { defaultEngine, generateCurry } from './utils'
33

44
/**
55
* Returns a random number between -1 and 1
66
* @param engine PRNG of choice
77
*/
8-
const normalFloat = (engine = Math.random) => {
8+
const normalFloat = (engine = defaultEngine) => {
99
return floatRange(-1, 1, engine)
1010
}
1111

src/one-of.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { intRange } from './int-range'
2-
import { generateCurry } from './utils'
2+
import { defaultEngine, generateCurry } from './utils'
33

44
/**
55
* Returns a random value from the provided array
66
* @param arr Array of values
77
* @param engine PRNG of choice
88
*/
9-
const oneOf = (arr, engine = Math.random) => {
9+
const oneOf = (arr, engine = defaultEngine) => {
1010
return arr[intRange(0, arr.length - 1, engine)]
1111
}
1212

src/sequence.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { intRange } from './int-range'
2-
import { generateCurry, sliceOut } from './utils'
2+
import { defaultEngine, generateCurry, sliceOut } from './utils'
33

44
/**
55
* Returns a new array with randomized order
66
* @param arr Array of values
77
* @param engine PRNG of choice
88
*/
9-
const sequence = (arr, engine = Math.random) => {
9+
const sequence = (arr, engine = defaultEngine) => {
1010
const result = []
1111

1212
let tempArr = arr

src/sign.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { bool } from './bool'
2-
import { generateCurry } from './utils'
2+
import { defaultEngine, generateCurry } from './utils'
33

44
/**
55
* Returns a random sign (-1 or 1)
66
* @param engine PRNG of choice
77
*/
8-
const sign = (engine = Math.random) => {
8+
const sign = (engine = defaultEngine) => {
99
return bool(engine) ? 1 : -1
1010
}
1111

src/uniq-func-int-range.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { generateListFromRange } from './utils'
1+
import { defaultEngine, generateListFromRange } from './utils'
22
import uniqFuncSequence from './uniq-func-sequence'
33

44
/**
@@ -7,7 +7,7 @@ import uniqFuncSequence from './uniq-func-sequence'
77
* @param max Maximum integer
88
* @param engine Engine to be used as PRNG
99
*/
10-
const uniqFuncIntRange = (min, max, engine = Math.random) => {
10+
const uniqFuncIntRange = (min, max, engine = defaultEngine) => {
1111
return uniqFuncSequence(
1212
generateListFromRange(min, max),
1313
engine

src/uniq-func-sequence.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { randIntRange, sliceOut } from './utils'
1+
import { defaultEngine, randIntRange, sliceOut } from './utils'
22

33
/**
44
* Returns a PRNG function that returns unique values from the provided array.
55
* @param arr Array of values to pull from
66
* @param engine Engine to be used as PRNG
77
*/
8-
const uniqFuncSequence = (arr, engine = Math.random) => {
8+
const uniqFuncSequence = (arr, engine = defaultEngine) => {
99
let tempArr = arr
1010

1111
return () => {

src/utils.js

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
const defaultEngine = () => {
2+
try {
3+
// Credit @ Tamás Sallai
4+
const crypto = window.crypto || window.msCrypto
5+
const buffer = new ArrayBuffer(8);
6+
const ints = new Int8Array(buffer);
7+
crypto.getRandomValues(ints);
8+
9+
ints[7] = 63;
10+
ints[6] |= 0xf0;
11+
12+
return new DataView(buffer).getFloat64(0, true) - 1;
13+
} catch (e) {
14+
return Math.random()
15+
}
16+
}
17+
118
const generateListFromRange = (min, max) => {
219
const result = []
320

@@ -8,29 +25,29 @@ const generateListFromRange = (min, max) => {
825
return result
926
}
1027

11-
export { generateListFromRange }
12-
13-
const randIntRange = (i, j, engine = Math.random) => {
28+
const randIntRange = (i, j, engine = defaultEngine) => {
1429
const min = Math.ceil(i)
1530
const max = Math.floor(j)
1631

1732
return Math.floor(engine() * (max - min + 1)) + min
1833
}
1934

20-
export { randIntRange }
21-
2235
const sliceOut = (arr, i) => {
2336
return arr.slice(0, i).concat(arr.slice(i + 1))
2437
}
2538

26-
export { sliceOut }
27-
2839
const generateCurry = (func) => {
29-
return (engine = Math.random) => {
40+
return (engine = defaultEngine) => {
3041
return (...args) => {
3142
return func(...args, engine)
3243
}
3344
}
3445
}
3546

36-
export { generateCurry }
47+
export {
48+
generateListFromRange,
49+
randIntRange,
50+
sliceOut,
51+
generateCurry,
52+
defaultEngine,
53+
}

src/uuid.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { generateCurry } from "./utils"
1+
import { defaultEngine, generateCurry } from "./utils"
22

33
/**
44
* Returns a valid RFC4122 version4 ID hex string, using the provided engine
55
* @param engine PRNG of choice
66
*/
7-
const uuid = (engine = Math.random) => {
7+
const uuid = (engine = defaultEngine) => {
88
// Credit @Alexey Silin from https://gist.github.com/1308368
99
var a = ''
1010
var b = ''

src/weighted.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { generateCurry } from "./utils"
1+
import { defaultEngine, generateCurry } from "./utils"
22

33
/**
44
* Returns a random value from the provided array, biased towards provided weights
55
* @param nums Array of numbers (integer or float)
66
* @param weights Array of weights (integer or float)
77
* @param engine PRNG of choice
88
*/
9-
const weighted = (nums, weights, engine = Math.random) => {
9+
const weighted = (nums, weights, engine = defaultEngine) => {
1010
if (nums.length !== weights.length) {
1111
throw new Error('Every provided number must have a corresponding weight.')
1212
}

0 commit comments

Comments
 (0)