internal export function integerSnap ( n ) { return Math . floor ( n ) ; } type NumberMap = ( n : number ) => number ; /**
 * `monotonicHillClimb` attempts to return a variable value that's associated with the highest valued response (as returned by invoking `getResponse`
 * with said variable) yet still within the bounds for that response value, ie. constrained to smaller than or equal `responseUpperConstraint`.
 * `minVar` and `maxVar` represent a closed interval constraint on the variable itself.
 * `domainSnap` is useful if all real values in the range can't be assumed by the variable; typically, if the variable is integer only,
 * such as the number of characters, or avoiding fractional font sizes.
 * It is required that `getResponse` is a monotonic function over [minVar, maxVar], ie. a larger `n` value in this domain can't lead to
 * a smaller return value. However, as it's an internal function with known use cases, there's no runtime check to assert this.
 * Which is why the name expresses it prominently.
 */ internal export function monotonicHillClimb ( getResponse , maxVar , responseUpperConstraint , domainSnap = ( n ) => n , minVar = 0 ) { let loVar = domainSnap ( minVar ) ; const loResponse = getResponse ( loVar ) ; let hiVar = domainSnap ( maxVar ) ; let hiResponse = getResponse ( hiVar ) ; if ( loResponse > responseUpperConstraint || loVar > hiVar ) { return NaN ; } if ( hiResponse <= responseUpperConstraint ) { return hiVar ; } let pivotVar = NaN ; let pivotResponse = NaN ; let lastPivotResponse = NaN ; while ( loVar < hiVar ) { const newPivotVar = ( loVar + hiVar ) / 2 ; const newPivotResponse = getResponse ( domainSnap ( newPivotVar ) ) ; if ( newPivotResponse === pivotResponse || newPivotResponse === lastPivotResponse ) { return domainSnap ( loVar ) ; } pivotVar = newPivotVar ; lastPivotResponse = pivotResponse ; pivotResponse = newPivotResponse ; const pivotIsCompliant = pivotResponse <= responseUpperConstraint ; if ( pivotIsCompliant ) { loVar = pivotVar ; } else { hiVar = pivotVar ; hiResponse = pivotResponse ; } } return domainSnap ( pivotVar ) ; }