UNPKG

@bazilio-san/af-stream

Version:
132 lines (126 loc) 3.47 kB
import { TSlot } from '../interfaces'; export const eq = (a: number, b: number, SIGMA: number) => Math.abs(a - b) <= SIGMA; export const gt = (a: number, b: number, SIGMA: number) => a > b + SIGMA; export const lt = (a: number, b: number, SIGMA: number) => a < b - SIGMA; export const gte = (a: number, b: number, SIGMA: number) => a >= b - SIGMA; export const lte = (a: number, b: number, SIGMA: number) => a <= b + SIGMA; export const findSlotFloatLEFT = (arr: number[], x: number, SIGMA: number): TSlot => { const lastIndex = arr.length - 1; if (lastIndex < 0) { return [null, null, null]; } const index = arr.findIndex((v) => gte(v, x, SIGMA)); if (index > -1) { if (eq(arr[index], x, SIGMA)) { return [ index === 0 ? null : index - 1, index, index === lastIndex ? null : index + 1, ]; } // x < arr[index] return [ index === 0 ? null : index - 1, null, index, ]; } // index === -1: X больше наибольшего return [lastIndex, null, null]; }; export const findSlotFloatRIGHT = (arr: number[], x: number, SIGMA: number): TSlot => { const { length } = arr; if (!length) { return [null, null, null]; } let pos = length; const lastIndex = length - 1; while (--pos >= 0) { const v = arr[pos]; if (eq(v, x, SIGMA)) { return [ pos === 0 ? null : pos - 1, pos, pos === lastIndex ? null : pos + 1, ]; } if (lt(v, x, SIGMA)) { return [ pos, null, pos === lastIndex ? null : pos + 1, ]; } } return [null, null, 0]; }; export const findSlotFloatBINARY = (arr: number[], x: number, SIGMA: number): TSlot => { const { length } = arr; if (!length) { return [null, null, null]; } const lastIndex = length - 1; let start = 0; let end = length; if (lt(x, arr[0], SIGMA)) { return [null, null, 0]; } if (eq(x, arr[0], SIGMA)) { return [null, 0, length > 1 ? 1 : null]; } if (gt(x, arr[lastIndex], SIGMA)) { return [lastIndex, null, null]; } if (eq(x, arr[lastIndex], SIGMA)) { return [lastIndex ? lastIndex - 1 : null, lastIndex, null]; } let mid = 0; while (start <= end) { mid = Math.floor((start + end) / 2); if (eq(arr[mid], x, SIGMA)) { return [ mid === 0 ? null : mid - 1, mid, mid === length - 1 ? null : mid + 1, ]; } if (gt(arr[mid], x, SIGMA)) { end = mid - 1; } else { start = mid + 1; } } if (lt(arr[mid], x, SIGMA)) { return [ mid, null, length > 1 ? mid + 1 : null, ]; } return [ length > 1 ? mid - 1 : null, null, mid, ]; }; /** * Searches for a place for a float number (x) in an array of float numbers (arr) sorted in ascending order. * Returns an array of 3 indices: [ <index of nearest smaller number | null>, <index of number equal to desired | null>, <index of nearest larger number | null> ] Numbers are compared using SIGMA: if the numbers differ by less than SIGMA, then they are considered equal. */ export const findSlotFloat = (arr: number[], x: number, SIGMA: number): TSlot => { const { length } = arr; if (!length) { return [null, null, null]; } if (length > 2000) { return findSlotFloatBINARY(arr, x, SIGMA); } return ((arr[length - 1] - arr[0]) / 2) < x ? findSlotFloatRIGHT(arr, x, SIGMA) : findSlotFloatLEFT(arr, x, SIGMA); };