/** * Digital-to-physical conversion. * * EDF defines the mapping by two calibration points, (digitalMin -> physicalMin) * and (digitalMax -> physicalMax), which the specification writes as: * * gain = (physicalMax - physicalMin) / (digitalMax - digitalMin) * physical = (digital - digitalMin) * gain + physicalMin * * That form is evaluated here in EDFlib's algebraically equivalent arrangement: * * offset = physicalMax / gain - digitalMax * physical = gain * (offset + digital) * * The rearrangement is not cosmetic. Written the first way, a channel spanning * +/-800 uV computes a value near 800 and then subtracts 800, and the cancellation * throws away low-order bits: digital 0 yields 0.19536019536019467 when the exact * value is 0.19536019536019536. EDFlib's form keeps the intermediate small * (offset + digital = 0.5 here) and returns the correctly rounded result. * * Both properties matter. The values are as accurate as a double can express, and * they are bit-identical to pyEDFlib and EDFbrowser, which share EDFlib's arithmetic, * so the test suite can assert exact equality against a reference implementation * rather than settling for a tolerance. */ import type { EdfSignal } from './header.js'; export type Scaler = (digital: number) => number; export declare function makeScaler(signal: EdfSignal): Scaler; /** * Smallest physical step this channel can express — one digital unit. * Used to choose a decimal precision that preserves every distinct sample value. */ export declare function quantizationStep(signal: EdfSignal): number; /** * Decimal places needed so that two adjacent digital codes never round to the same * string. Two places past the quantization step keep rounding error far below the * resolution the hardware actually recorded, without padding the file with digits * that carry no information. * * Ordinary channels land at three or four: a ±800 µV channel over 12 bits steps by * 0.39 µV and needs three. The ceiling is only reached by calibrations whose step is * below 1e-98, which an 8-character physical bound can still express — `1e-99` is five * characters. Those get VALUE_RESOLUTION rather than silence. */ export declare function decimalsForSignal(signal: EdfSignal, max?: number): number; /** * Whether this channel's step is finer than any precision the tool can print. * * Asked of the ceiling, not of the precision in use. `--decimals 2` on a channel needing 3 * is a trade the caller made knowingly and is not this warning's business — 0.5.10 fixed a * version of this that fired on every ordinary EEG at `--decimals 2` and made * `--decimals 2 --strict` impossible. But it fixed it by asking "did the caller choose the * precision", which suppressed the real case too: at `--decimals 20` a channel stepping by * 1e-106 printed every one of its codes as `0.00000000000000000000`, in silence. * * The question is whether anything the tool can print would separate consecutive codes. When * the answer is no, that is a ceiling nobody chose, and it holds whatever `--decimals` says. */ export declare function decimalsAreClamped(signal: EdfSignal): boolean;