import { Exponent, NonZeroExponent } from "../exponent"; import { addExponents, divideExponents, multiplyExponents } from "../exponent/exponentValueArithmetic"; import { AllowedExponents, DivideUnits, DivisorUnit, ExponentiateUnit, MultiplicandUnit, MultiplyUnits, NthRootUnit, RadicandUnit, SymbolAndExponent, Unit, UnitWithSymbols, } from "./unitTypeArithmetic"; export function dimension(dim: Dim, symbol?: string): UnitWithSymbols<{ [D in Dim]: "1" }> { return { [dim]: [symbol || dim, "1"] } as any; } export function multiplyUnits>( left: UnitWithSymbols, right: UnitWithSymbols, ): UnitWithSymbols> { const result: UnitWithSymbols = {}; for (const dimension in left) { const symbolAndExponent = copySymbolAndExponent(left, dimension); if (symbolAndExponent !== undefined && symbolAndExponent[1] !== "0") { result[dimension] = symbolAndExponent; } } for (const dimension in right) { const symbolAndExponent = copySymbolAndExponent(right, dimension); if (symbolAndExponent === undefined) { continue; } const [, exponent] = symbolAndExponent; const resultValue: SymbolAndExponent | undefined = result[dimension]; if (resultValue !== undefined) { const newExponent = addExponents(resultValue[1], exponent); if (newExponent === "0") { delete result[dimension]; } else { resultValue[1] = newExponent; } } else if (exponent !== "0") { result[dimension] = symbolAndExponent; } } return result as any; } function copySymbolAndExponent(unit: UnitWithSymbols, dimension: string): SymbolAndExponent | undefined { const result = unit[dimension]; if (result === undefined) { return undefined; } const [symbol, exponent] = result; return [symbol, exponent]; } export function divideUnits>( left: UnitWithSymbols, right: UnitWithSymbols, ): UnitWithSymbols> { const rightInverse = exponentiateUnit(right, "-1") as any; return multiplyUnits(left, rightInverse) as any; } export function exponentiateUnit>( unit: UnitWithSymbols, power: N, ): UnitWithSymbols> { return expAndRootImpl(unit, exponent => multiplyExponents(exponent, power)); } export function nthRootUnit, N extends NonZeroExponent>( unit: UnitWithSymbols, root: N, ): UnitWithSymbols> { return expAndRootImpl(unit, exponent => divideExponents(exponent, root)); } function expAndRootImpl(unit: UnitWithSymbols, updateExponent: (exp: Exponent) => Exponent): any { const result: UnitWithSymbols = {}; for (const dimension in unit) { const symbolAndExponent = unit[dimension]; if (symbolAndExponent === undefined) { continue; } const [symbol, exponent] = symbolAndExponent; const newExponent = updateExponent(exponent); if (newExponent !== "0") { result[dimension] = [symbol, newExponent]; } } return result; }