import type { Type as $Type, ICopy, IEqualsDelta, IEquiv, ILength, IRelease, Maybe, NumericArray } from "@thi.ng/api";
export interface TensorData<T = number> extends Iterable<T>, ILength {
    [id: number]: T;
    fill(x: T, start?: number, end?: number): TensorData<T>;
}
export type Type = $Type | "num" | "str";
export type NumType = $Type | "num";
export type Shape0 = [];
export type Shape1 = [number];
export type Shape2 = [number, number];
export type Shape3 = [number, number, number];
export type Shape4 = [number, number, number, number];
export type Shape = Shape0 | Shape1 | Shape2 | Shape3 | Shape4;
export type ShapeTensor<S extends Shape, T> = S extends Shape4 ? ITensor4<T> : S extends Shape3 ? ITensor3<T> : S extends Shape2 ? ITensor2<T> : S extends Shape1 ? ITensor1<T> : ITensor0<T>;
export type Nested<T> = T[] | T[][] | T[][][] | T[][][][];
export type NestedTensor<N extends Nested<T>, T> = N extends T[][][][] ? ITensor4<T> : N extends T[][][] ? ITensor3<T> : N extends T[][] ? ITensor2<T> : ITensor1<T>;
export interface TypeMap {
    u8: number;
    u8c: number;
    i8: number;
    u16: number;
    i16: number;
    u32: number;
    i32: number;
    f32: number;
    f64: number;
    num: number;
    str: string;
}
export interface TensorOpts<T, S extends Shape> {
    /**
     * Tensor data. Unless {@link TensorOpts.copy} is false, by default will be
     * copied to memory obtained from configured storage.
     */
    data?: TensorData<T>;
    /**
     * Optionally configured storage provider. By default uses the
     * datatype-specific implementation from global {@link STORAGE} registry.
     */
    storage?: ITensorStorage<T>;
    /**
     * Optionally configured stride tuple. By default the strides will be
     * obtained from the tensor shape and will be in row-major order.
     */
    stride?: S;
    /**
     * Optional start index of the data values (only inteded to be used if
     * {@link TensorOpts.data} is given).
     */
    offset?: number;
    /**
     * Only used if {@link TensorOpts.data} is given. If true (default), the
     * data will be copied to memory obtained from configured storage.
     */
    copy?: boolean;
}
export interface TensorFromArrayOpts<T extends Type, V> {
    type: T;
    storage?: ITensorStorage<V>;
}
/**
 * Source data type for tensor conversion via {@link asTensor}.
 */
export interface TensorLike<T extends Type, S extends Shape> {
    /** Data type */
    type: T;
    /** Tensor data/values (MUST match `type`) */
    data: TensorData<TypeMap[T]>;
    /** Tensor shape */
    shape: S;
    /** Stride/layout information of data */
    stride: S;
    /** Start index (default: 0) */
    offset?: number;
}
export interface ITensor<T = number> extends ICopy<ITensor<T>>, IEquiv, IEqualsDelta<ITensor<T>>, IRelease {
    readonly type: Type;
    readonly storage: ITensorStorage<T>;
    readonly data: TensorData<T>;
    readonly shape: number[];
    readonly stride: number[];
    readonly offset: number;
    readonly length: number;
    readonly dim: number;
    readonly order: number[];
    orderedShape: number[];
    orderedStride: number[];
    [Symbol.iterator](): IterableIterator<T>;
    /**
     * Internal use only. Creates a shallow view used for broadcasting
     * operators. See {@link broadcast} for details.
     *
     * @param shape
     * @param stride
     *
     * @internal
     */
    broadcast<S extends Shape>(shape: S, stride: S): ShapeTensor<S, T>;
    /**
     * Returns a new tensor of same shape, but all values zeroed. Unless
     * `storage` is given, the new data will be allocated using this tensor's
     * storage provider.
     *
     * @param storage
     */
    empty(storage?: ITensorStorage<T>): this;
    fill(x: T): this;
    /**
     * Computes linear array index from given grid position. Reverse-op of
     * {@link ITensor.position}.
     *
     * @remarks
     * The given `pos` is assumed to be integral and valid. No bounds checking
     * performed.
     *
     * @param pos
     */
    index(pos: NumericArray): number;
    /**
     * Returns an iterator of array indices used by this tensor
     */
    indices(): IterableIterator<number>;
    /**
     * Computes nD grid position for given linear array index. Reverse-op of
     * {@link ITensor.index}.
     *
     * @remarks
     * The given `index` is assumed to be valid. No bounds checking performed.
     *
     * **CAUTION:** Currently only supports tensors with positive strides,
     * otherwise will yield incorrect results! Tensors with negative strides
     * (aka flipped axes in reverse order) need to be first packed via
     * {@link ITensor.pack}.
     *
     * @param index
     */
    position(index: number): number[];
    /**
     * Returns value at given grid position. No bounds checking.
     *
     * @param pos
     */
    get(pos: NumericArray): T;
    /**
     * Sets value at given grid position. No bounds checking.
     *
     * @param pos
     * @param value
     */
    set(pos: NumericArray, value: T): this;
    /**
     * Returns a new tensor of the bottom-right region starting from given
     * `pos`. View transform only, no data will be copied.
     *
     * @remarks
     * Also see {@link Itensor.hi}, {@link ITensor.crop}.
     *
     * @example
     * ```ts tangle:../export/itensor-lo.ts
     * import { print, range } from "@thi.ng/tensors";
     *
     * const a = range(16).reshape([4, 4]);
     * print(a);
     * //        0    1.0000    2.0000    3.0000
     * //   4.0000    5.0000    6.0000    7.0000
     * //   8.0000    9.0000   10.0000   11.0000
     * //  12.0000   13.0000   14.0000   15.0000
     *
     * const b = a.lo([2, 1]);
     * print(b);
     * //   9.0000   10.0000   11.0000
     * //  13.0000   14.0000   15.0000
     * ```
     *
     * @param pos
     */
    lo(pos: NumericArray): this;
    /**
     * Returns a new tensor of the top-left region until given `pos` (excluded).
     * View transform only, no data will be copied.
     *
     * @remarks
     * Also see {@link Itensor.lo}, {@link ITensor.crop}.
     *
     * @example
     * ```ts tangle:../export/itensor-hi.ts
     * import { print, range } from "@thi.ng/tensors";
     *
     * const a = range(16).reshape([4, 4]);
     * print(a);
     * //        0    1.0000    2.0000    3.0000
     * //   4.0000    5.0000    6.0000    7.0000
     * //   8.0000    9.0000   10.0000   11.0000
     * //  12.0000   13.0000   14.0000   15.0000
     *
     * const b = a.hi([2, 3]);
     * print(b);
     * //        0    1.0000    2.0000
     * //   4.0000    5.0000    6.0000
     * ```
     *
     * @param pos
     */
    hi(pos: NumericArray): this;
    /**
     * Returns a new tensor of the extracted region defined by `pos` and `size`.
     * This op is a combination of {@link ITensor.lo} and {@link ITensor.hi}.
     * View transform only, no data will be copied.
     *
     * @example
     * ```ts tangle:../export/itensor-crop.ts
     * import { print, range } from "@thi.ng/tensors";
     *
     * const a = range(16).reshape([4, 4]);
     * print(a);
     * //        0    1.0000    2.0000    3.0000
     * //   4.0000    5.0000    6.0000    7.0000
     * //   8.0000    9.0000   10.0000   11.0000
     * //  12.0000   13.0000   14.0000   15.0000
     *
     * const b = a.crop([1, 1], [2, 2]);
     * print(b);
     * //   5.0000    6.0000
     * //   9.0000   10.0000
     * ```
     *
     * @param pos
     * @param size
     */
    crop(pos: NumericArray, size: NumericArray): this;
    /**
     * Returns a new tensor with step sizes adjusted for selected axes (Using
     * zero for an axis will keep its current step size). View transform only,
     * no data will be copied.
     *
     * @example
     * ```ts tangle:../export/itensor-step.ts
     * import { print, range } from "@thi.ng/tensors";
     *
     * const a = range(16).reshape([4, 4]);
     * print(a);
     * //        0    1.0000    2.0000    3.0000
     * //   4.0000    5.0000    6.0000    7.0000
     * //   8.0000    9.0000   10.0000   11.0000
     * //  12.0000   13.0000   14.0000   15.0000
     *
     * // only select every 2nd row
     * const b = a.step([2, 1]);
     * print(b);
     * //        0    1.0000    2.0000    3.0000
     * //   8.0000    9.0000   10.0000   11.0000
     *
     * // keep rows as is (zero), only select every 2nd column
     * print(b.step([0, 2]));
     * //        0    2.0000
     * //   8.0000   10.0000
     * ```
     *
     * @param select
     */
    step(select: NumericArray): this;
    /**
     * Returns a new tensor with only the `select`ed axes. A -1 will select all
     * value in that axis. View transform only, no data will be copied.
     *
     * @example
     * ```ts tangle:../export/itensor-pick.ts
     * import { print, range } from "@thi.ng/tensors";
     *
     * // 3D 4x4x4 tensor with values in [0,64) range
     * const a = range(64).reshape([4, 4, 4]);
     *
     * // pick entire slice #2
     * print(a.pick([2]));
     * //  32.0000   33.0000   34.0000   35.0000
     * //  36.0000   37.0000   38.0000   39.0000
     * //  40.0000   41.0000   42.0000   43.0000
     * //  44.0000   45.0000   46.0000   47.0000
     *
     * // pick slice #2, row #2 (1D tensor)
     * print(a.pick([2, 2]));
     * //  40.0000   41.0000   42.0000   43.0000
     *
     * // pick slice #2, column #2 (1D tensor)
     * print(a.pick([2, -1, 2]));
     * //  34.0000   38.0000   42.0000   46.0000
     * ```
     *
     * @param select
     */
    pick(select: NumericArray): ITensor<T>;
    /**
     * Creates a "packed" copy of this tensor with dense striding and the new
     * data array only holding the values actually referenced by this tensor.
     * Unless `storage` is given, the new data will be allocated using this
     * tensor's storage provider.
     *
     * @remarks
     * Since most other `ITensor` ops are zero-copy, view-only transforms, often
     * resulting in "sparse" views which are only addressing a subset of the
     * values stored, using `.pack()` is useful to extract data into a dense
     * tensor/buffer.
     *
     * @example
     * ```ts tangle:../export/itensor-pack.ts
     * import { range } from "@thi.ng/tensors";
     *
     * const a = range(16).reshape([4, 4]);
     * console.log("a data", a.data);
     * // a data [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ]
     *
     * // only select every 2nd row & column
     * const b = a.step([2, 2]);
     * console.log("b values", [...b]);
     * // b values [ 0, 2, 8, 10 ]
     * console.log("b data", b.data);
     * // b data [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ]
     *
     * // create packed version of `b`
     * const c = b.pack();
     * console.log("c data", c.data);
     * // c data [ 0, 2, 8, 10 ]
     * ```
     *
     * @param storage
     */
    pack(storage?: ITensorStorage<T>): this;
    /**
     * Returns a new tensor with same data but given new shape (and optionally
     * new strides). The total number of elements of the new shape MUST match
     * that of the current shape (otherwise an error will be thrown).
     *
     * @remarks
     * **IMPORTANT:** If no `newStride` is given, only "dense" tensors can be
     * reshaped reliably (if in doubt, use {@link ITensor.pack} prior to
     * reshaping).
     *
     * @remarks
     * Also see {@link ITensor.crop} and {@link ITensor.resize}
     *
     * @example
     * ```ts tangle:../export/itensor-reshape.ts
     * import { print, range } from "@thi.ng/tensors";
     *
     * // 1D tensor
     * const a = range(16);
     *
     * // reshape as 2D tensor
     * print(a.reshape([4, 4]));
     * //         0    1.0000    2.0000    3.0000
     * //    4.0000    5.0000    6.0000    7.0000
     * //    8.0000    9.0000   10.0000   11.0000
     * //   12.0000   13.0000   14.0000   15.0000
     *
     * // reshape as 3D tensor
     * print(a.reshape([2, 2, 4]));
     * // --- 0: ---
     * //         0    1.0000    2.0000    3.0000
     * //    4.0000    5.0000    6.0000    7.0000
     * // --- 1: ---
     * //    8.0000    9.0000   10.0000   11.0000
     * //   12.0000   13.0000   14.0000   15.0000
     * ```
     *
     * @param newShape
     * @param newStride
     */
    reshape<S extends Shape>(newShape: S, newStride?: S): ShapeTensor<S, T>;
    /**
     * Returns a copy of the tensor resized to `newShape`. If the new shape is
     * larger than the current shape, the extra data values will be initialized
     * to `fill` (default: zero). Values will be copied in current iteration
     * order (same logic as numpy). Unless `storage` is given, the new data will
     * be allocated using this tensor's storage provider.
     *
     * @remarks
     * Also see {@link ITensor.crop}, {@link ITensor.reshape}.
     *
     * @example
     * ```ts tangle:../export/itensor-resize.ts
     * import { print, range } from "@thi.ng/tensors";
     *
     * // 2D 4x4 tensor with values in [0,16) range
     * const a = range(16).reshape([4, 4]);
     *
     * print(a.resize([4, 8]));
     * //        0    1.0000    2.0000    3.0000    4.0000    5.0000    6.0000    7.0000
     * //   8.0000    9.0000   10.0000   11.0000   12.0000   13.0000   14.0000   15.0000
     * //        0         0         0         0         0         0         0         0
     * //        0         0         0         0         0         0         0         0
     * ```
     *
     * @param newShape
     * @param fill
     * @param storage
     */
    resize<S extends Shape>(newShape: S, fill?: T, storage?: ITensorStorage<T>): ShapeTensor<S, T>;
    /**
     * Returns a new tensor with the given new axis `order`. View transform
     * only, no data will be copied.
     *
     * @example
     * ```ts tangle:../export/itensor-transpose.ts
     * import { print, range } from "@thi.ng/tensors";
     *
     * const a = range(12).reshape([3, 4]);
     * print(a);
     * //        0    1.0000    2.0000    3.0000
     * //   4.0000    5.0000    6.0000    7.0000
     * //   8.0000    9.0000   10.0000   11.0000
     *
     * // swap row & column order
     * const b = a.transpose([1, 0]);
     * print(b);
     * //        0    4.0000    8.0000
     * //   1.0000    5.0000    9.0000
     * //   2.0000    6.0000   10.0000
     * //   3.0000    7.0000   11.0000
     * ```
     *
     * @param order
     */
    transpose(order: NumericArray): this;
    toJSON(): any;
}
export type ITensor0<T = number> = ITensor<T> & {
    dim: 0;
};
export type ITensor1<T = number> = ITensor<T> & {
    dim: 1;
};
export type ITensor2<T = number> = ITensor<T> & {
    dim: 2;
};
export type ITensor3<T = number> = ITensor<T> & {
    dim: 3;
};
export type ITensor4<T = number> = ITensor<T> & {
    dim: 4;
};
export interface TensorCtor<T = number> {
    new (type: Type, storage: ITensorStorage<T>, data: TensorData<T>, shape: number[], stride: number[], offset?: number): ITensor<T>;
}
export interface ITensorStorage<T> {
    /**
     * Attempts to allocate/create an array for given number of items. Throws an
     * error if unsuccessful.
     *
     * @param size
     */
    alloc(size: number): TensorData<T>;
    /**
     * Attempts to allocate/create an array for given iterable. Throws an
     * error if unsuccessful.
     *
     * @param iter
     */
    from(iter: Iterable<T>): TensorData<T>;
    /**
     * Attempts to release the array/memory used by given buffer. Returns true
     * if successful.
     *
     * @param buf
     */
    release(buf: TensorData<T>): boolean;
}
export type StorageRegistry = Record<Type, ITensorStorage<any>>;
export interface TensorOpT<T = number> {
    (out: ITensor0<T> | null, a: ITensor0<T>): ITensor0<T>;
    (out: ITensor1<T> | null, a: ITensor1<T>): ITensor1<T>;
    (out: ITensor2<T> | null, a: ITensor2<T>): ITensor2<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>): ITensor4<T>;
}
export interface TensorOpTT<T = number> {
    (out: ITensor0<T> | null, a: ITensor0<T>, b: ITensor0<T>): ITensor0<T>;
    (out: ITensor1<T> | null, a: ITensor0<T>, b: ITensor1<T>): ITensor1<T>;
    (out: ITensor2<T> | null, a: ITensor0<T>, b: ITensor2<T>): ITensor2<T>;
    (out: ITensor3<T> | null, a: ITensor0<T>, b: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor0<T>, b: ITensor4<T>): ITensor4<T>;
    (out: ITensor1<T> | null, a: ITensor1<T>, b: ITensor0<T>): ITensor1<T>;
    (out: ITensor1<T> | null, a: ITensor1<T>, b: ITensor1<T>): ITensor1<T>;
    (out: ITensor2<T> | null, a: ITensor1<T>, b: ITensor2<T>): ITensor2<T>;
    (out: ITensor3<T> | null, a: ITensor1<T>, b: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor1<T>, b: ITensor4<T>): ITensor4<T>;
    (out: ITensor2<T> | null, a: ITensor2<T>, b: ITensor0<T>): ITensor2<T>;
    (out: ITensor2<T> | null, a: ITensor2<T>, b: ITensor1<T>): ITensor2<T>;
    (out: ITensor2<T> | null, a: ITensor2<T>, b: ITensor2<T>): ITensor2<T>;
    (out: ITensor3<T> | null, a: ITensor2<T>, b: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor2<T>, b: ITensor4<T>): ITensor4<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor0<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor1<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor2<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor3<T>, b: ITensor4<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor0<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor1<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor2<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor3<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor4<T>): ITensor4<T>;
}
export interface TensorOpTTT<T = number> {
    (out: ITensor0<T> | null, a: ITensor0<T>, b: ITensor0<T>, c: ITensor0<T>): ITensor0<T>;
    (out: ITensor1<T> | null, a: ITensor0<T>, b: ITensor0<T>, c: ITensor1<T>): ITensor1<T>;
    (out: ITensor2<T> | null, a: ITensor0<T>, b: ITensor0<T>, c: ITensor2<T>): ITensor2<T>;
    (out: ITensor3<T> | null, a: ITensor0<T>, b: ITensor0<T>, c: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor0<T>, b: ITensor0<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor1<T> | null, a: ITensor0<T>, b: ITensor1<T>, c: ITensor0<T>): ITensor1<T>;
    (out: ITensor1<T> | null, a: ITensor0<T>, b: ITensor1<T>, c: ITensor1<T>): ITensor1<T>;
    (out: ITensor2<T> | null, a: ITensor0<T>, b: ITensor1<T>, c: ITensor2<T>): ITensor2<T>;
    (out: ITensor3<T> | null, a: ITensor0<T>, b: ITensor1<T>, c: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor0<T>, b: ITensor1<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor2<T> | null, a: ITensor0<T>, b: ITensor2<T>, c: ITensor0<T>): ITensor2<T>;
    (out: ITensor2<T> | null, a: ITensor0<T>, b: ITensor2<T>, c: ITensor1<T>): ITensor2<T>;
    (out: ITensor2<T> | null, a: ITensor0<T>, b: ITensor2<T>, c: ITensor2<T>): ITensor2<T>;
    (out: ITensor3<T> | null, a: ITensor0<T>, b: ITensor2<T>, c: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor0<T>, b: ITensor2<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor3<T> | null, a: ITensor0<T>, b: ITensor3<T>, c: ITensor0<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor0<T>, b: ITensor3<T>, c: ITensor1<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor0<T>, b: ITensor3<T>, c: ITensor2<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor0<T>, b: ITensor3<T>, c: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor0<T>, b: ITensor3<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor0<T>, b: ITensor4<T>, c: ITensor0<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor0<T>, b: ITensor4<T>, c: ITensor1<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor0<T>, b: ITensor4<T>, c: ITensor2<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor0<T>, b: ITensor4<T>, c: ITensor3<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor0<T>, b: ITensor4<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor1<T> | null, a: ITensor1<T>, b: ITensor0<T>, c: ITensor0<T>): ITensor1<T>;
    (out: ITensor1<T> | null, a: ITensor1<T>, b: ITensor0<T>, c: ITensor1<T>): ITensor1<T>;
    (out: ITensor2<T> | null, a: ITensor1<T>, b: ITensor0<T>, c: ITensor2<T>): ITensor2<T>;
    (out: ITensor3<T> | null, a: ITensor1<T>, b: ITensor0<T>, c: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor1<T>, b: ITensor0<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor1<T> | null, a: ITensor1<T>, b: ITensor1<T>, c: ITensor0<T>): ITensor1<T>;
    (out: ITensor1<T> | null, a: ITensor1<T>, b: ITensor1<T>, c: ITensor1<T>): ITensor1<T>;
    (out: ITensor2<T> | null, a: ITensor1<T>, b: ITensor1<T>, c: ITensor2<T>): ITensor2<T>;
    (out: ITensor3<T> | null, a: ITensor1<T>, b: ITensor1<T>, c: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor1<T>, b: ITensor1<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor2<T> | null, a: ITensor1<T>, b: ITensor2<T>, c: ITensor0<T>): ITensor2<T>;
    (out: ITensor2<T> | null, a: ITensor1<T>, b: ITensor2<T>, c: ITensor1<T>): ITensor2<T>;
    (out: ITensor2<T> | null, a: ITensor1<T>, b: ITensor2<T>, c: ITensor2<T>): ITensor2<T>;
    (out: ITensor3<T> | null, a: ITensor1<T>, b: ITensor2<T>, c: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor1<T>, b: ITensor2<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor3<T> | null, a: ITensor1<T>, b: ITensor3<T>, c: ITensor0<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor1<T>, b: ITensor3<T>, c: ITensor1<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor1<T>, b: ITensor3<T>, c: ITensor2<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor1<T>, b: ITensor3<T>, c: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor1<T>, b: ITensor3<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor1<T>, b: ITensor4<T>, c: ITensor0<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor1<T>, b: ITensor4<T>, c: ITensor1<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor1<T>, b: ITensor4<T>, c: ITensor2<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor1<T>, b: ITensor4<T>, c: ITensor3<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor1<T>, b: ITensor4<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor2<T> | null, a: ITensor2<T>, b: ITensor0<T>, c: ITensor0<T>): ITensor2<T>;
    (out: ITensor2<T> | null, a: ITensor2<T>, b: ITensor0<T>, c: ITensor1<T>): ITensor2<T>;
    (out: ITensor2<T> | null, a: ITensor2<T>, b: ITensor0<T>, c: ITensor2<T>): ITensor2<T>;
    (out: ITensor3<T> | null, a: ITensor2<T>, b: ITensor0<T>, c: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor2<T>, b: ITensor0<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor2<T> | null, a: ITensor2<T>, b: ITensor1<T>, c: ITensor0<T>): ITensor2<T>;
    (out: ITensor2<T> | null, a: ITensor2<T>, b: ITensor1<T>, c: ITensor1<T>): ITensor2<T>;
    (out: ITensor2<T> | null, a: ITensor2<T>, b: ITensor1<T>, c: ITensor2<T>): ITensor2<T>;
    (out: ITensor3<T> | null, a: ITensor2<T>, b: ITensor1<T>, c: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor2<T>, b: ITensor1<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor2<T> | null, a: ITensor2<T>, b: ITensor2<T>, c: ITensor0<T>): ITensor2<T>;
    (out: ITensor2<T> | null, a: ITensor2<T>, b: ITensor2<T>, c: ITensor1<T>): ITensor2<T>;
    (out: ITensor2<T> | null, a: ITensor2<T>, b: ITensor2<T>, c: ITensor2<T>): ITensor2<T>;
    (out: ITensor3<T> | null, a: ITensor2<T>, b: ITensor2<T>, c: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor2<T>, b: ITensor2<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor3<T> | null, a: ITensor2<T>, b: ITensor3<T>, c: ITensor0<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor2<T>, b: ITensor3<T>, c: ITensor1<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor2<T>, b: ITensor3<T>, c: ITensor2<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor2<T>, b: ITensor3<T>, c: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor2<T>, b: ITensor3<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor2<T>, b: ITensor4<T>, c: ITensor0<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor2<T>, b: ITensor4<T>, c: ITensor1<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor2<T>, b: ITensor4<T>, c: ITensor2<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor2<T>, b: ITensor4<T>, c: ITensor3<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor2<T>, b: ITensor4<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor0<T>, c: ITensor0<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor0<T>, c: ITensor1<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor0<T>, c: ITensor2<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor0<T>, c: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor3<T>, b: ITensor0<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor1<T>, c: ITensor0<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor1<T>, c: ITensor1<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor1<T>, c: ITensor2<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor1<T>, c: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor3<T>, b: ITensor1<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor2<T>, c: ITensor0<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor2<T>, c: ITensor1<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor2<T>, c: ITensor2<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor2<T>, c: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor3<T>, b: ITensor2<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor3<T>, c: ITensor0<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor3<T>, c: ITensor1<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor3<T>, c: ITensor2<T>): ITensor3<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, b: ITensor3<T>, c: ITensor3<T>): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor3<T>, b: ITensor3<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor3<T>, b: ITensor4<T>, c: ITensor0<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor3<T>, b: ITensor4<T>, c: ITensor1<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor3<T>, b: ITensor4<T>, c: ITensor2<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor3<T>, b: ITensor4<T>, c: ITensor3<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor3<T>, b: ITensor4<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor0<T>, c: ITensor0<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor0<T>, c: ITensor1<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor0<T>, c: ITensor2<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor0<T>, c: ITensor3<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor0<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor1<T>, c: ITensor0<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor1<T>, c: ITensor1<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor1<T>, c: ITensor2<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor1<T>, c: ITensor3<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor1<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor2<T>, c: ITensor0<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor2<T>, c: ITensor1<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor2<T>, c: ITensor2<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor2<T>, c: ITensor3<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor2<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor3<T>, c: ITensor0<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor3<T>, c: ITensor1<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor3<T>, c: ITensor2<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor3<T>, c: ITensor3<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor3<T>, c: ITensor4<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor4<T>, c: ITensor0<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor4<T>, c: ITensor1<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor4<T>, c: ITensor2<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor4<T>, c: ITensor3<T>): ITensor4<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, b: ITensor4<T>, c: ITensor4<T>): ITensor4<T>;
}
export interface TensorOpN<A = number, B = A> {
    (out: ITensor0<B>, n: A): ITensor0<B>;
    (out: ITensor1<B>, n: A): ITensor1<B>;
    (out: ITensor2<B>, n: A): ITensor2<B>;
    (out: ITensor3<B>, n: A): ITensor3<B>;
    (out: ITensor4<B>, n: A): ITensor4<B>;
}
export interface TensorOpTN<T = number> {
    (out: ITensor0<T> | null, a: ITensor0<T>, n: T): ITensor0<T>;
    (out: ITensor1<T> | null, a: ITensor1<T>, n: T): ITensor1<T>;
    (out: ITensor2<T> | null, a: ITensor2<T>, n: T): ITensor2<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, n: T): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, n: T): ITensor4<T>;
}
export interface TensorOpTNO<T = number> {
    (out: ITensor0<T> | null, a: ITensor0<T>, n?: T): ITensor0<T>;
    (out: ITensor1<T> | null, a: ITensor1<T>, n?: T): ITensor1<T>;
    (out: ITensor2<T> | null, a: ITensor2<T>, n?: T): ITensor2<T>;
    (out: ITensor3<T> | null, a: ITensor3<T>, n?: T): ITensor3<T>;
    (out: ITensor4<T> | null, a: ITensor4<T>, n?: T): ITensor4<T>;
}
export interface TensorOpTNN<T = number> {
    (out: ITensor0<T>, a: ITensor0<T>, n: T, m: T): ITensor0<T>;
    (out: ITensor1<T>, a: ITensor1<T>, n: T, m: T): ITensor1<T>;
    (out: ITensor2<T>, a: ITensor2<T>, n: T, m: T): ITensor2<T>;
    (out: ITensor3<T>, a: ITensor3<T>, n: T, m: T): ITensor3<T>;
    (out: ITensor4<T>, a: ITensor4<T>, n: T, m: T): ITensor4<T>;
}
export type TensorOpRT<A, B, TA extends ITensor<A> = ITensor<A>> = (a: TA) => B;
export type TensorOpRTT<A, B, TA extends ITensor<A> = ITensor<A>> = (a: TA, b: TA) => B;
export interface MultiTensorOp<TOP> {
    /**
     * Adds / overwrites implementation for given tensor dimension.
     *
     * @param dim -
     * @param op -
     */
    add(dim: number, op: TOP): TOP;
    /**
     * Adds / overwrites default implementation (SHOULD support arbitrary tensor
     * dimensions).
     *
     * @param op -
     */
    default(op: TOP): TOP;
    /**
     * Returns implementation for given tensor dimension or default
     * implementation.
     *
     * @param dim -
     */
    impl(dim?: number): Maybe<TOP>;
}
export type MultiTensorOpImpl<T> = T & MultiTensorOp<T>;
/**
 * Convolution kernel spec for use with {@link applyKernel}.
 *
 * @remarks
 * Provided implementations:
 *
 * - {@link MAX2_MOORE}
 * - {@link MAX2_VON_NEUMANN}
 * - {@link MAXIMA2_MOORE}
 * - {@link MAXIMA2_VON_NEUMANN}
 */
export interface KernelSpec<T = any> {
    /**
     * Kernel shape/size
     */
    shape: Exclude<Shape, Shape0>;
    /**
     * Windowed intialization. Returns initial accumulator for each new kernel
     * window.
     */
    init: () => T;
    /**
     * Windowed reduction function. Receives current accumulator, domain value
     * and kernel-local coordinates. Returns updated accumulator.
     *
     * @param acc
     * @param value
     * @param coords
     */
    reduce: (acc: T, value: number, ...coords: number[]) => T;
    /**
     * Windowed reducer result function. Produces final result from current
     * accumulator.
     *
     * @param acc
     */
    complete: (acc: T) => number;
}
//# sourceMappingURL=api.d.ts.map