{"version":3,"sources":["factorUnit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAQhD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD;;;;;GAKG;AACH,qBAAa,UAAW,YAAW,cAAc,CAAC,UAAU,CAAC;IAC3D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;gBAER,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM;IAMxC;;;;;;;;;;OAUG;IACH,MAAM,CAAC,iBAAiB,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE;IAqBjE,MAAM,CAAC,eAAe,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE;IAuB/D,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU;IAK3B,oBAAoB,CAAC,iBAAiB,EAAE,MAAM,GAAG,MAAM;IAKvD,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO;IAM5C,uBAAuB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO;IAOnD,MAAM,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO;IAQnC,QAAQ,IAAI,MAAM;IAMlB,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,GAAG,UAAU;IAa/D;;OAEG;IACH,OAAO,IAAI,MAAM;IAOjB,yCAAyC,IAAI,UAAU,EAAE;IASzD,SAAS,IAAI,WAAW;IAIxB,oCAAoC,IAAI,UAAU,EAAE,EAAE;IAUtD,MAAM,CAAC,oCAAoC,CACzC,WAAW,EAAE,UAAU,EAAE,GACxB,UAAU,EAAE,EAAE;IAiCV,kBAAkB,IAAI,eAAe,GAAG,SAAS;IAQxD,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI;CAGzB","file":"factorUnit.d.ts","sourcesContent":["import { SupportsEquals } from \"./baseTypes.js\";\nimport {\n  arrayDeduplicate,\n  arrayEqualsIgnoreOrdering,\n  checkInteger,\n  compareUsingEquals,\n  isNullish,\n} from \"./utils.js\";\nimport { FactorUnits } from \"./factorUnits.js\";\nimport { Unit } from \"./unit.js\";\nimport { Decimal } from \"decimal.js\";\nimport { DimensionVector } from \"./dimensionVector.js\";\n\n/**\n * Combines a {@link Unit} and an exponent; some Units are a combination of {@link FactorUnit}s. If\n * a unit is such a 'derived unit', its {@link Unit#getFactorUnits()} method returns a non-empty Set\n * of FactorUnits.\n *\n */\nexport class FactorUnit implements SupportsEquals<FactorUnit> {\n  readonly exponent: number;\n  readonly unit: Unit;\n\n  constructor(unit: Unit, exponent: number) {\n    checkInteger(exponent, \"exponent\");\n    this.exponent = exponent;\n    this.unit = unit;\n  }\n\n  /**\n   * Perform mathematical simplification on factor units. Only simplifies units with exponents of the same sign.\n   *\n   * For example,\n   * ```\n   * N / M * M -> N per M^2\n   * ```\n   *\n   * @param factorUnits the factor units to simplify\n   * @return the simplified factor units.\n   */\n  static contractExponents(factorUnits: FactorUnit[]): FactorUnit[] {\n    const ret: FactorUnit[] = [];\n    const factorUnitsByKind: Map<string, FactorUnit> = factorUnits.reduce(\n      (mapping, cur) => {\n        const kind = cur.getKind();\n        const prevUnit = mapping.get(kind);\n        if (prevUnit) {\n          mapping.set(kind, FactorUnit.combine(prevUnit, cur));\n        } else {\n          mapping.set(kind, cur);\n        }\n        return mapping;\n      },\n      new Map<string, FactorUnit>()\n    );\n    for (const fu of factorUnitsByKind.values()) {\n      ret.push(fu);\n    }\n    return ret;\n  }\n\n  static reduceExponents(factorUnits: FactorUnit[]): FactorUnit[] {\n    const ret: FactorUnit[] = [];\n    const exponentsByUnit: Map<Unit, number> = factorUnits.reduce(\n      (mapping, cur) => {\n        const unit = cur.unit;\n        const prevExponent = mapping.get(unit);\n        if (prevExponent) {\n          mapping.set(unit, prevExponent + cur.exponent);\n        } else {\n          mapping.set(unit, cur.exponent);\n        }\n        return mapping;\n      },\n      new Map<Unit, number>()\n    );\n    for (const [unit, exponent] of exponentsByUnit.entries()) {\n      if (Math.abs(exponent) > 0) {\n        ret.push(new FactorUnit(unit, exponent));\n      }\n    }\n    return ret;\n  }\n\n  pow(by: number): FactorUnit {\n    checkInteger(by, \"by\");\n    return new FactorUnit(this.unit, this.exponent * by);\n  }\n\n  getExponentCumulated(cumulatedExponent: number): number {\n    checkInteger(cumulatedExponent, \"cumulatedExponent\");\n    return this.exponent * cumulatedExponent;\n  }\n\n  isCompatibleWith(other: FactorUnit): boolean {\n    return (\n      this.exponent === other.exponent && this.unit.isConvertible(other.unit)\n    );\n  }\n\n  getConversionMultiplier(other: FactorUnit): Decimal {\n    if (!this.isCompatibleWith(other)) {\n      throw `${this.toString()} is not compatible with ${other.toString()}`;\n    }\n    return this.unit.getConversionMultiplier(other.unit).pow(this.exponent);\n  }\n\n  equals(other?: FactorUnit): boolean {\n    return (\n      !!other &&\n      this.exponent === other.exponent &&\n      this.unit.equals(other.unit)\n    );\n  }\n\n  toString(): string {\n    return (\n      this.unit.toString() + (this.exponent === 1 ? \"\" : \"^\" + this.exponent)\n    );\n  }\n\n  static combine(left: FactorUnit, right: FactorUnit): FactorUnit {\n    if (!left) {\n      return right;\n    }\n    if (!right) {\n      return left;\n    }\n    if (!left.unit.equals(right.unit)) {\n      throw `Cannot combine UnitFactors of different units (left: ${left.unit.toString()}, right:${right.unit.toString()}`;\n    }\n    return new FactorUnit(left.unit, left.exponent + right.exponent);\n  }\n\n  /**\n   * Combines unit IRI and sign of exponent in one string.\n   */\n  getKind(): string {\n    return (\n      this.unit.iri +\n      (this.exponent === 0 ? \"0\" : this.exponent > 0 ? \"1\" : \"-1\")\n    );\n  }\n\n  getLeafFactorUnitsWithCumulativeExponents(): FactorUnit[] {\n    const leafFactorUnits =\n      this.unit.getLeafFactorUnitsWithCumulativeExponents();\n    if (!!leafFactorUnits?.length) {\n      return leafFactorUnits.map((fu) => fu.pow(this.exponent));\n    }\n    return [this];\n  }\n\n  normalize(): FactorUnits {\n    return this.unit.normalize().pow(this.exponent);\n  }\n\n  getAllPossibleFactorUnitCombinations(): FactorUnit[][] {\n    const subResult = this.unit.getAllPossibleFactorUnitCombinations();\n    const result = subResult.map((fus) =>\n      fus.map((fu) => fu.pow(this.exponent))\n    );\n    return arrayDeduplicate(result, (left, right) =>\n      arrayEqualsIgnoreOrdering(left, right, compareUsingEquals)\n    );\n  }\n\n  static getAllPossibleFactorUnitCombinations(\n    factorUnits: FactorUnit[]\n  ): FactorUnit[][] {\n    const numFactors = factorUnits.length;\n    const subResults: FactorUnit[][][] = factorUnits.map((fu) =>\n      fu.getAllPossibleFactorUnitCombinations()\n    );\n    const subResultLengths = subResults.map((s) => s.length);\n    const currentIndices: number[] = [];\n    currentIndices.length = numFactors;\n    currentIndices.fill(0);\n    const results: FactorUnit[][] = [];\n    // cycle through all possible combinations of results per factor unit and combine them\n    do {\n      const curResult: FactorUnit[] = [];\n      let countUp = true;\n      for (let i = 0; i < numFactors; i++) {\n        curResult.push(...subResults[i][currentIndices[i]]);\n        if (countUp) {\n          currentIndices[i]++;\n          if (currentIndices[i] >= subResultLengths[i]) {\n            currentIndices[i] = 0;\n          } else {\n            countUp = false;\n          }\n        }\n      }\n      results.push(FactorUnit.contractExponents(curResult));\n      results.push(FactorUnit.reduceExponents(curResult));\n    } while (!currentIndices.every((val) => val === 0));\n    return arrayDeduplicate(results, (left, right) =>\n      arrayEqualsIgnoreOrdering(left, right, compareUsingEquals)\n    );\n  }\n\n  public getDimensionVector(): DimensionVector | undefined {\n    if (isNullish(this.unit.dimensionVectorIri)) {\n      return undefined;\n    }\n    const dv = new DimensionVector(this.unit.dimensionVectorIri as string);\n    return dv.multiply(this.exponent);\n  }\n\n  static ofUnit(unit: Unit) {\n    return new FactorUnit(unit, 1);\n  }\n}\n"]}