UNPKG

flo-poly

Version:

A practical, root-focused JavaScript polynomial utility library.

276 lines (238 loc) 8.93 kB
import { fromRoots } from '../../roots/from-roots/double/from-roots.js'; /** * Arbitrary seed value for the simple random number generator. * * @internal */ const SEED = 123456789; /** * The range for the simple random number generator, i.e. the generated * numbers will be in [0,RANGE]. * * @internal */ const RANGE = 4294967296; /** * Creates a function from the given function with parameters similar * to flatRoots but with an extra parameter in the beginning indicating * the length of the array generated by the original function. * * @param f * * @internal */ function createArrFunction( f: (d: number, a?: number, b?: number, seed?: number, odds?: number) => { p: number[], seed: number }): (n: number, d: number, a?: number, b?: number, seed?: number, odds?: number) => number[][] { return function( n: number, d: number, a?: number, b?: number, seed = SEED, odds = 0) { const res: number[][] = []; for (let i=0; i<n; i++) { const v = f(d, a, b, seed, odds); const p = v.p; seed = v.seed; res.push(p); } return res; } } /** * Generates and returns an array of polynomials with random **roots** (with coefficients * given densely as an array of double floating point numbers from highest to * lowest power, e.g. `[5,-3,0]` represents the polynomial `5x^2 - 3x`). * * * all roots will approximate real values so is not at all representative of * a natural random root distribution * * * the exact same polynomials will be created on each call to this function * if the same seed is used; this is by design to improve testing. * * @param n the number of polynomials to generate. * @param d the degree of the polynomials * @param a defaults to 0; the lower bound of the coefficients * @param b defaults to 1; the upper bound of the coefficients * @param seed defaults to 123456789; a seed value in [0,4294967296] * @param odds defaults to 0; the odds that a root will be doubled (applied * recursively so that some roots could be tripled, etc. * * @example * ```typescript * flatRootsArr(2,3,0,10); //=> [[1, -17.27247918024659, 97.33487287168995, -179.34094494147305], [1, -14.934967160224915, 57.624514485645406, -14.513933300587215]] * flatRootsArr(2,3,0,10); //=> [[1, -17.27247918024659, 97.33487287168995, -179.34094494147305], [1, -14.934967160224915, 57.624514485645406, -14.513933300587215]] * ``` * * @doc */ const flatRootsArr = createArrFunction(flatRoots); /** * Generates and returns an array of polynomials with random **coefficients** (with coefficients * given densely as an array of double floating point numbers from highest to * lowest power, e.g. `[5,-3,0]` represents the polynomial `5x^2 - 3x`). * * * the exact same polynomials will be created on each call to this function * if the same seed is used; this is by design to improve testing. * * @param n the number of polynomials to generate. * @param d the length of the polynomial coefficients array * @param a defaults to 0; the lower bound of the coefficients * @param b defaults to 1; the upper bound of the coefficients * @param seed defaults to 123456789; a seed value in [0,4294967296] * @param odds defaults to 0; the odds that a root will be doubled (applied * recursively so that some roots could be tripled, etc. * * @example * ```typescript * flatCoefficientsArr(2,3,-2,2); //=> [[0.1749166026711464, -0.20349335670471191, 0.9375684261322021], [1.0617692470550537, -1.8918039798736572, 0.8040215969085693]] * flatCoefficientsArr(2,3,-2,2); //=> [[0.1749166026711464, -0.20349335670471191, 0.9375684261322021], [1.0617692470550537, -1.8918039798736572, 0.8040215969085693]] * ``` * * @doc */ const flatCoefficientsArr = createArrFunction(flatCoefficients); /** * Returns a quasi-random number to be used as the next input to this function. * * * see [stackoverflow](https://stackoverflow.com/questions/3062746/special-simple-random-number-generator) * * @param seed * * @internal */ function predictiveRandom(seed: number): number { const a = 134775813; return (a * seed + 1) % RANGE; } /** * Generates a random array of numbers picked from a bounded flat * distribution (i.e. a rectangular distribution) with specified odds of * duplication of consecutive values. * * @param n the number of values to generate * @param a defaults to 0; the lower bound of the distribution * @param b defaults to 1; the upper bound of the distribution * @param seed defaults to 123456789; a seed * @param odds defaults to 0; the odds that a number will be doubled (applied * recursively so that some numbers will be tripled, etc. * * @internal */ function randomArray( n: number, a: number, b: number, seed: number, odds = 0): { vs: number[], seed: number } { let vs: number[] = []; for (let i=0; i<n; i++) { seed = predictiveRandom(seed); const v = ((seed/RANGE) * (b-a)) + a; seed = push(seed, vs, v, odds); } vs = vs.slice(0,n); return { vs, seed }; } /** * Helper function that will add more numbers to the passed array - modifies the * values parameter. * * @param seed * @param values an existing array of values - will be modified! * @param x the number that will be added (possibly multiple times) * @param odds the odds that the number will be added again (recursively). * * @internal */ function push(seed: number, values: number[], x: number, odds: number): number { seed = predictiveRandom(seed); values.push(x); if ((seed/RANGE) < odds) { seed = push(seed, values, x, odds); } return seed; } /** * Generates and returns an array of polynomials with random **roots** (with coefficients * given densely as an array of double floating point numbers from highest to * lowest power, e.g. `[5,-3,0]` represents the polynomial `5x^2 - 3x`). * * * also returns a new seed value that can be used as the input to the next * call to a predictive random function * * * all roots will approximate real values so is not at all representative of * a natural random root distribution * * * the exact same polynomial will be created on each call to this function * if the same seed is used; this is by design to improve testing. * * @param d the degree of the polynomials * @param a defaults to 0; the lower bound of the coefficients * @param b defaults to 1; the upper bound of the coefficients * @param seed defaults to 123456789; a seed value in [0,4294967296] * @param odds defaults to 0; the odds that a root will be doubled (applied * recursively so that some roots could be tripled, etc. * * @example * ```typescript * flatRoots(3,0,10); //=> { p: [1, -17.27247918024659, 97.33487287168995, -179.34094494147305], seed: 939629312 } * ``` * * @doc */ function flatRoots( d: number, a = 0, b = 1, seed = SEED, odds = 0): { p: number[], seed: number } { const randArr = randomArray(d, a, b, seed, odds); seed = randArr.seed; const p = fromRoots(randArr.vs); return { p, seed }; } /** * Generates and returns an array of polynomials with random **coefficients** (with coefficients * given densely as an array of double floating point numbers from highest to * lowest power, e.g. `[5,-3,0]` represents the polynomial `5x^2 - 3x`). * * * also returns a new seed value that can be used as the input to the next * call to a predictive random function * * * the exact same polynomial will be created on each call to this function * if the same seed is used; this is by design to improve testing. * * @param d the length of the polynomial coefficients array * @param a defaults to 0; the lower bound of the coefficients * @param b defaults to 1; the upper bound of the coefficients * @param seed defaults to 123456789; a seed value in [0,4294967296] * @param odds defaults to 0; the odds that a root will be doubled (applied * recursively so that some roots could be tripled, etc. * * @example * ```typescript * flatCoefficients(3,-5,5); //=> { p: [0.437291506677866, -0.5087333917617798, 2.3439210653305054], seed: 939629312 } * ``` * * @doc */ function flatCoefficients( d: number, a = -1, b = +1, seed = SEED): { p: number[], seed: number } { const randArr = randomArray(d, a, b, seed); seed = randArr.seed; const p = randArr.vs; return { p, seed }; } export { flatRoots, flatRootsArr, flatCoefficients, flatCoefficientsArr, predictiveRandom }