@qudtlib/core
Version:
Data model for QUDTLib
1 lines • 7.82 kB
Source Map (JSON)
{"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"]}