diff options
| author | Shinigami <[email protected]> | 2022-10-30 09:03:26 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-10-30 08:03:26 +0000 |
| commit | 9abfcfb90cc73bfe961d446f5fb950976d5c2ccd (patch) | |
| tree | 1e76203a6cfd8bb6c2b83734fee4cebf56db5072 /src | |
| parent | 4da3d5eac3805f609f4e40385aee6a645fd93540 (diff) | |
| download | faker-9abfcfb90cc73bfe961d446f5fb950976d5c2ccd.tar.xz faker-9abfcfb90cc73bfe961d446f5fb950976d5c2ccd.zip | |
refactor(mersenne): rewrite internal mersenne (#1447)
Diffstat (limited to 'src')
| -rw-r--r-- | src/faker.ts | 11 | ||||
| -rw-r--r-- | src/internal/mersenne/mersenne.ts | 96 | ||||
| -rw-r--r-- | src/modules/datatype/index.ts | 11 |
3 files changed, 42 insertions, 76 deletions
diff --git a/src/faker.ts b/src/faker.ts index f8a46511..fd7ed522 100644 --- a/src/faker.ts +++ b/src/faker.ts @@ -1,7 +1,8 @@ import type { LocaleDefinition } from './definitions'; import { FakerError } from './errors/faker-error'; import { deprecated } from './internal/deprecated'; -import { MersenneModule } from './internal/mersenne/mersenne'; +import type { Mersenne } from './internal/mersenne/mersenne'; +import mersenne from './internal/mersenne/mersenne'; import type { KnownLocale } from './locales'; import { AnimalModule } from './modules/animal'; import { ColorModule } from './modules/color'; @@ -79,7 +80,7 @@ export class Faker { readonly definitions: LocaleDefinition = this.initDefinitions(); /** @internal */ - private readonly _mersenne: MersenneModule = new MersenneModule(); + private readonly _mersenne: Mersenne = mersenne(); readonly random: RandomModule = new RandomModule(this); @@ -286,11 +287,7 @@ export class Faker { seed( seed: number | number[] = Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER) ): number | number[] { - if (Array.isArray(seed) && seed.length) { - this._mersenne.seed_array(seed); - } else if (!Array.isArray(seed) && !isNaN(seed)) { - this._mersenne.seed(seed); - } + this._mersenne.seed(seed); return seed; } diff --git a/src/internal/mersenne/mersenne.ts b/src/internal/mersenne/mersenne.ts index 16019e29..e7c0355c 100644 --- a/src/internal/mersenne/mersenne.ts +++ b/src/internal/mersenne/mersenne.ts @@ -1,81 +1,49 @@ -import { FakerError } from '../../errors/faker-error'; -import Gen from './twister'; +import Twister from './twister'; /** - * Module to generate seed based random numbers. + * Generate seed based random numbers. * * @internal */ -export class MersenneModule { - private gen = new Gen(); - - constructor() { - this.gen.initGenrand(Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER)); - - // Bind `this` so namespaced is working correctly - for (const name of Object.getOwnPropertyNames(MersenneModule.prototype)) { - if (name === 'constructor' || typeof this[name] !== 'function') { - continue; - } - this[name] = this[name].bind(this); - } - } - +export interface Mersenne { /** - * Generates a random number between `[min, max)`. - * - * @param max The maximum number. Defaults to `32768`. - * @param min The minimum number. Defaults to `0`. + * Generates a random number between `[min, max)`. The result is already floored. * - * @example - * faker.mersenne.rand() // 15515 - * faker.mersenne.rand(1000, 500) // 578 - * - * @since 5.5.0 + * @param options The options to generate a random number. + * @param options.min The minimum number. + * @param options.max The maximum number. */ - rand(max = 32768, min = 0): number { - if (min > max) { - const temp = min; - min = max; - max = temp; - } - - return Math.floor(this.gen.genrandReal2() * (max - min) + min); - } + next(options: { max: number; min: number }): number; /** * Sets the seed to use. * - * @param S The seed to use. - * @throws If the seed is not a `number`. - * - * @since 5.5.0 + * @param seed The seed to use. */ - seed(S: number): void { - if (typeof S !== 'number') { - throw new FakerError( - `seed(S) must take numeric argument; is ${typeof S}` - ); - } + seed(seed: number | number[]): void; +} + +/** + * Generate seed based random numbers. + * + * @internal + */ +export default function mersenne(): Mersenne { + const twister = new Twister(); - this.gen.initGenrand(S); - } + twister.initGenrand(Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER)); - /** - * Sets the seed to use. - * - * @param A The seed to use. - * @throws If the seed is not a `number[]`. - * - * @since 5.5.0 - */ - seed_array(A: number[]): void { - if (typeof A !== 'object') { - throw new FakerError( - `seed_array(A) must take array of numbers; is ${typeof A}` - ); - } + return { + next({ min, max }): number { + return Math.floor(twister.genrandReal2() * (max - min) + min); + }, - this.gen.initByArray(A, A.length); - } + seed(seed: number | number[]): void { + if (typeof seed === 'number') { + twister.initGenrand(seed); + } else if (Array.isArray(seed)) { + twister.initByArray(seed, seed.length); + } + }, + }; } diff --git a/src/modules/datatype/index.ts b/src/modules/datatype/index.ts index 41c5c3e4..d4fcbbd6 100644 --- a/src/modules/datatype/index.ts +++ b/src/modules/datatype/index.ts @@ -1,7 +1,7 @@ import type { Faker } from '../..'; import { FakerError } from '../../errors/faker-error'; import { deprecated } from '../../internal/deprecated'; -import type { MersenneModule } from '../../internal/mersenne/mersenne'; +import type { Mersenne } from '../../internal/mersenne/mersenne'; /** * Module to generate various primitive values and data types. @@ -56,13 +56,14 @@ export class DatatypeModule { throw new FakerError(`Max ${max} should be greater than min ${min}.`); } - const mersenne: MersenneModule = + const mersenne: Mersenne = // @ts-expect-error: access private member field this.faker._mersenne; - const randomNumber = Math.floor( - mersenne.rand(max / precision + 1, min / precision) - ); + const randomNumber = mersenne.next({ + min: min / precision, + max: max / precision + 1, + }); // Workaround problem in float point arithmetics for e.g. 6681493 / 0.01 return randomNumber / (1 / precision); |
