import type { Interval } from '../interval/interval.ts'; import type { Pipeable } from '../utils.ts'; /** * A `Solution` represents the result of an operation that may produce * between zero and three values of `T`. It generalizes the zoo of "0 or 1", * "0 to 2", "0 to 3" return shapes used throughout curvy under one type, and * provides a small namespace of operations (`value`, `last`, `min`, `max`, * `filter`, `map`, `match`, …) for working with the result. * * Each variant carries a `_tag` discriminator and a `length` field, is * iterable via `Symbol.iterator` (so existing `for..of` and spread patterns * keep working), and is `Pipeable` (so a `Solution` value can be the head of * a `pipe` chain). * * Variant-specific accessors: * - `One`, `Two`, and `Three` all expose `.value: T` (the first / * primary value). * - `Two` and `Three` additionally expose `.values: readonly [T, ...]` * for explicit positional access. * * Operations that return narrower cardinalities (e.g. inverse-solving a * monotonic polynomial) use the `AtMost{One,Two,Three}` aliases to express * "this could be empty, but it'll have at most N values." * * @since 2.0.0 */ export type Solution = None | One | Two | Three; /** * The empty solution. * * @since 2.0.0 */ export interface None extends Pipeable, Iterable { readonly _tag: 'none'; readonly length: 0; } /** @since 2.0.0 */ export interface One extends Pipeable, Iterable { readonly _tag: 'one'; readonly length: 1; readonly value: T; } /** @since 2.0.0 */ export interface Two extends Pipeable, Iterable { readonly _tag: 'two'; readonly length: 2; readonly value: T; readonly values: readonly [T, T]; } /** @since 2.0.0 */ export interface Three extends Pipeable, Iterable { readonly _tag: 'three'; readonly length: 3; readonly value: T; readonly values: readonly [T, T, T]; } /** * Any non-empty solution. All `Some` values expose `.value: T` directly — * no narrowing required to read the primary value. * * @since 2.0.0 */ export type Some = One | Two | Three; /** * `None | One` — return type of operations that produce at most one value * (e.g. inverse-solving a strictly monotonic polynomial). * * @since 2.0.0 */ export type AtMostOne = None | One; /** * `None | One | Two` — return type of operations that produce at most * two values (e.g. inverse-solving an unrestricted quadratic polynomial). * * @since 2.0.0 */ export type AtMostTwo = None | One | Two; /** * `None | One | Two | Three` — equivalent to `Solution`. * * @since 2.0.0 */ export type AtMostThree = Solution; /** * The empty solution. Reused across calls — never reallocated. * * @since 2.0.0 */ export declare const none: None; /** * Constructs a single-value solution. * * @since 2.0.0 */ export declare const one: (value: T) => One; /** * Constructs a two-value solution. * * @since 2.0.0 */ export declare const two: (a: T, b: T) => Two; /** * Constructs a three-value solution. * * @since 2.0.0 */ export declare const three: (a: T, b: T, c: T) => Three; /** * Constructs a `Solution` from a runtime array. Throws if the array has * more than three elements. * * @since 2.0.0 */ export declare const fromArray: (arr: ReadonlyArray) => Solution; /** * Type-narrowing predicate: refines `Solution` to `None`. * * @since 2.0.0 */ export declare const isNone: (s: Solution) => s is None; /** * Type-narrowing predicate: refines `Solution` to `Some` (non-empty). * After narrowing, `.value` is directly accessible without further checks. * * @since 2.0.0 */ export declare const isSome: (s: Solution) => s is Some; /** * Returns the primary (first) value if the solution is non-empty, or * `undefined` if empty. Pair with `.value` access on `Some`-narrowed * inputs to avoid the `undefined` possibility. * * @since 2.0.0 */ export declare const valueOrUndefined: (s: Solution) => T | undefined; /** * Returns the last value in the solution, or `undefined` if empty. When * called on a `Some`, the result is guaranteed to be `T`. * * @since 2.0.0 */ export declare const last: { (s: Some): T; (s: Solution): T | undefined; }; /** * Returns the smallest numeric value in the solution, or `undefined` if empty. * When called on a `Some`, the result is guaranteed to be `number`. * * @since 2.0.0 */ export declare const min: { (s: Some): number; (s: Solution): number | undefined; }; /** * Returns the largest numeric value in the solution, or `undefined` if empty. * When called on a `Some`, the result is guaranteed to be `number`. * * @since 2.0.0 */ export declare const max: { (s: Some): number; (s: Solution): number | undefined; }; /** * Returns the primary value of the solution (i.e. `s.value`). Throws on * `None`, optionally with a caller-provided message. * * Useful when the type system can't prove non-emptiness but you have a domain * reason to assert it — e.g. inverting a polynomial you know to be monotonic * without going through the trait refiner first: * * ```ts * const x = CubicPolynomial.solveInverse(p, y).pipe( * Solution.unsafeValue('expected a monotonic inverse'), * ) * ``` * * @since 2.0.0 */ export declare const unsafeValue: { (s: Solution, message?: string): T; (message: string): (s: Solution) => T; }; /** * Returns the last value in the solution. Throws if empty. * * @since 2.0.0 */ export declare const unsafeLast: (s: Solution) => T; /** * Returns the smallest numeric value in the solution. Throws on empty. * * @since 2.0.0 */ export declare const unsafeMin: (s: Solution) => number; /** * Returns the largest numeric value in the solution. Throws on empty. * * @since 2.0.0 */ export declare const unsafeMax: (s: Solution) => number; /** * Filters the solution by a predicate. Result cardinality is at most that of * the input. * * @since 2.0.0 */ export declare const filter: (s: Solution, predicate: (v: T) => boolean) => Solution; /** * Restricts the solution to values contained within an interval. Endpoint * inclusivity follows the interval's `kind` — pass an open variant (e.g. * `Interval.makeOpen(0, 1)` or `Interval.unitOpen`) for strict containment. * * @param s - The solution to clip. * @param i - The interval to retain values within. * @since 2.0.0 */ export declare const clip: { (i: Interval): (s: Solution) => Solution; (s: Solution, i: Interval): Solution; }; /** * Maps every value in the solution to a new value. Result cardinality matches * the input. * * @since 2.0.0 */ export declare const map: { (s: Solution, f: (v: A) => B): Solution; (f: (v: A) => B): (s: Solution) => Solution; }; type SomeOf = S extends None ? never : S; /** * Pattern matches on a solution, calling `onNone` for the empty case and * `onSome` for any non-empty case. The `onSome` parameter is typed against * the input's narrowed shape — for an `AtMostOne` input, `onSome` receives * `One` and can read `.value` directly. * * @example * ```ts * const result = polynomial.pipe( * LinearPolynomial.solveInverse(0), * Solution.match({ * onNone: () => null, * onSome: ({ value }) => Math.abs(value), * }), * ) * ``` * * @since 2.0.0 */ export declare const match: { , A, B>(self: S, matcher: { readonly onNone: () => A; readonly onSome: (s: SomeOf) => B; }): A | B; , A, B>(matcher: { readonly onNone: () => A; readonly onSome: (s: SomeOf) => B; }): (self: S) => A | B; }; export {};