import { AddendOf, AddExponents, DivideExponents, Exponent, MultiplicandOf, MultiplyExponents, PositiveExponent, ProductOf, SubtractExponents, SubtrahendOf } from "../exponent";
export type Unit = {
    [dimension: string]: Exponent | undefined;
};
export type UnitWithSymbols<U extends Unit = Unit> = {
    [D in keyof U]+?: [string, NonNullable<U[D]>];
};
export type SymbolAndExponent = [string, Exponent];
/** Returns the product of two units. This is the sum of two dimension vectors. */
export type MultiplyUnits<L extends Unit, R extends Unit> = {
    [Dim in keyof L | keyof R]: AddExponents<GetExponent<L, Dim>, GetExponent<R, Dim>>;
};
/** A type that is assignable from all units that can be multiplied by U without producing an error. */
export type MultiplicandUnit<U extends Unit> = Partial<{
    [D in keyof U]: AddendOf<CleanExponent<U[D]>>;
}> & Unit;
/** Returns the quotient of two units. This is the difference of two dimension vectors. */
export type DivideUnits<L extends Unit, R extends DivisorUnit<L>> = {
    [Dim in keyof L | keyof R]: SubtractExponents<GetExponent<L, Dim>, GetExponent<R, Dim>>;
};
/** A type that is assignable from all units that U can be divided by without producing an error. */
export type DivisorUnit<U extends Unit> = U | (Partial<{
    [D in keyof U]: SubtrahendOf<CleanExponent<U[D]>>;
}> & Unit);
/** Returns the unit raised to a power. This is the scalar multiple of the dimension vector. */
export type ExponentiateUnit<U extends Unit, N extends Exponent> = "0" extends N ? Record<never, Exponent | undefined> : {
    [Dim in keyof U]: MultiplyExponents<GetExponent<U, Dim>, N>;
};
/** Returns the union of exponents to which a given unit is allowed to be raised.  */
export type AllowedExponents<U extends Unit> = Exclude<Exponent, NonAllowedExponents<U>> | "-1" | "0" | "1";
/** Returns the union of exponents that raising and exponent to would produce an error. */
type NonAllowedExponents<U extends Unit> = {
    [Dim in keyof U]: undefined extends U[Dim] ? never : Exclude<Exponent, MultiplicandOf<NonNullable<U[Dim]>>>;
}[keyof U];
/** Returns the nth root of a unit. This is the inverse scalar multiple of the dimension vector. */
export type NthRootUnit<U extends RadicandUnit<N>, N extends PositiveExponent> = 1 extends N ? U : {
    [Dim in keyof U]: DivideExponents<GetExponent<U, Dim>, N>;
};
/** A type that is assignable from all units whose Nth root does not produce an error. */
export type RadicandUnit<N extends PositiveExponent> = {
    [dimension: string]: ProductOf<N> | undefined;
};
/** Get the exponent at a given dimension of a unit, or 0 if that dimension is undefined */
type GetExponent<U extends Unit, D> = D extends keyof U ? NonNullable<U[D]> : "0";
type CleanExponent<E extends undefined | Exponent> = undefined extends E ? "0" : NonNullable<E>;
export {};
