@callis/ucum 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/LICENSE.md +39 -0
- package/README.md +55 -2
- package/SOURCE.md +32 -0
- package/UCUM-LICENSE.md +283 -0
- package/data/source.json +20 -0
- package/data/ucum-essence.xml +2059 -0
- package/dist/essence/ucum-essence-xml.d.ts +3 -0
- package/dist/essence/ucum-essence-xml.js +21 -0
- package/dist/essence/ucum-essence-xml.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +1000 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["compareRational"],"sources":["../src/essence/xml-elements.ts","../src/essence/essence-reader.ts","../src/rational.ts","../src/decimal-rational.ts","../src/dimension.ts","../src/expression/unit-expression.ts","../src/resolve-unit.ts","../src/ucum-unit-system.ts","../src/unit-table.ts","../src/index.ts"],"sourcesContent":["/** An XML element with its attributes and child elements. Text content is not kept. */\nexport interface XmlElement {\n readonly name: string;\n readonly attributes: ReadonlyMap<string, string>;\n readonly children: readonly XmlElement[];\n}\n\ninterface OpenElement {\n readonly name: string;\n readonly attributes: ReadonlyMap<string, string>;\n readonly children: XmlElement[];\n}\n\nconst NAME = /[A-Za-z_:][-A-Za-z0-9_:.]*/y;\nconst ATTRIBUTE = /\\s+([A-Za-z_:][-A-Za-z0-9_:.]*)\\s*=\\s*(?:\"([^\"<]*)\"|'([^'<]*)')/y;\nconst TAG_END = /\\s*(\\/?)>/y;\nconst PREDEFINED_ENTITIES: Readonly<Record<string, string>> = Object.freeze({\n amp: '&',\n apos: \"'\",\n gt: '>',\n lt: '<',\n quot: '\"',\n});\n\n/**\n * Reads the element tree of a well-formed XML document, as far as the UCUM essence file needs:\n * elements, attributes, comments, processing instructions and CDATA sections. Text is skipped.\n * Document type declarations are rejected, so no external or custom entities are ever expanded.\n *\n * @returns the root element, or `undefined` if the text is not well-formed.\n * @see https://www.w3.org/TR/xml/\n */\nexport function readXmlElements(text: string): XmlElement | undefined {\n const stack: OpenElement[] = [];\n let root: XmlElement | undefined;\n let index = 0;\n while (index < text.length) {\n const open = text.indexOf('<', index);\n if (open === -1) {\n if (!isAllowedText(text.slice(index), stack.length)) return undefined;\n break;\n }\n if (!isAllowedText(text.slice(index, open), stack.length)) return undefined;\n if (text.startsWith('<?', open)) {\n const end = text.indexOf('?>', open + 2);\n if (end === -1) return undefined;\n index = end + 2;\n } else if (text.startsWith('<!--', open)) {\n const end = text.indexOf('-->', open + 4);\n if (end === -1) return undefined;\n index = end + 3;\n } else if (text.startsWith('<![CDATA[', open)) {\n const end = text.indexOf(']]>', open + 9);\n if (end === -1 || stack.length === 0) return undefined;\n index = end + 3;\n } else if (text.startsWith('<!', open)) {\n // DOCTYPE and other declarations could define entities; the essence file has none.\n return undefined;\n } else if (text.startsWith('</', open)) {\n NAME.lastIndex = open + 2;\n const name = NAME.exec(text)?.[0];\n const element = stack.pop();\n if (name === undefined || element === undefined || element.name !== name) return undefined;\n TAG_END.lastIndex = open + 2 + name.length;\n const end = TAG_END.exec(text);\n if (end === null || end[1] === '/') return undefined;\n index = TAG_END.lastIndex;\n const closed: XmlElement = {\n name: element.name,\n attributes: element.attributes,\n children: element.children,\n };\n const parent = stack.at(-1);\n if (parent === undefined) root = closed;\n else parent.children.push(closed);\n } else {\n if (root !== undefined) return undefined;\n NAME.lastIndex = open + 1;\n const name = NAME.exec(text)?.[0];\n if (name === undefined) return undefined;\n index = open + 1 + name.length;\n const attributes = new Map<string, string>();\n for (;;) {\n ATTRIBUTE.lastIndex = index;\n const attribute = ATTRIBUTE.exec(text);\n if (attribute === null) break;\n const [, key = '', double, single] = attribute;\n const value = decodeEntities(double ?? single ?? '');\n if (value === undefined || attributes.has(key)) return undefined;\n attributes.set(key, value);\n index = ATTRIBUTE.lastIndex;\n }\n TAG_END.lastIndex = index;\n const end = TAG_END.exec(text);\n if (end === null) return undefined;\n index = TAG_END.lastIndex;\n if (end[1] === '/') {\n const element: XmlElement = { name, attributes, children: [] };\n const parent = stack.at(-1);\n if (parent === undefined) root = element;\n else parent.children.push(element);\n } else {\n stack.push({ name, attributes, children: [] });\n }\n }\n }\n return stack.length === 0 ? root : undefined;\n}\n\n/** Text inside elements is skipped; outside the root element only whitespace may appear. */\nfunction isAllowedText(text: string, depth: number): boolean {\n return depth > 0 || /^[ \\t\\r\\n]*$/.test(text);\n}\n\n/** Replaces the predefined entities and character references; undefined for anything else. */\nfunction decodeEntities(value: string): string | undefined {\n let invalid = false;\n const decoded = value.replace(/&([^;]*);?/g, (match, reference: string) => {\n if (!match.endsWith(';')) {\n invalid = true;\n return '';\n }\n if (Object.hasOwn(PREDEFINED_ENTITIES, reference)) return PREDEFINED_ENTITIES[reference] ?? '';\n const code = /^#[0-9]+$/.test(reference)\n ? Number.parseInt(reference.slice(1), 10)\n : /^#x[0-9A-Fa-f]+$/.test(reference)\n ? Number.parseInt(reference.slice(2), 16)\n : Number.NaN;\n if (\n !Number.isInteger(code) ||\n code < 1 ||\n code > 0x10ffff ||\n (code >= 0xd800 && code <= 0xdfff)\n ) {\n invalid = true;\n return '';\n }\n return String.fromCodePoint(code);\n });\n return invalid ? undefined : decoded;\n}\n","import { readXmlElements, type XmlElement } from './xml-elements.ts';\n\n/** A prefix such as `k`, with its value as decimal text (`1e3`). */\nexport interface EssencePrefix {\n readonly code: string;\n readonly value: string;\n}\n\n/** One of the seven base units, such as `m` with dimension `L`. */\nexport interface EssenceBaseUnit {\n readonly code: string;\n readonly dimension: string;\n}\n\n/** The conversion function of a special unit, such as `Cel` with `value` 1 and `unit` `K`. */\nexport interface EssenceFunction {\n readonly name: string;\n readonly value: string;\n readonly unit: string;\n}\n\n/** A defined unit: `value` times the unit expression `unit`, or a special unit's function. */\nexport interface EssenceUnit {\n readonly code: string;\n readonly isMetric: boolean;\n readonly isSpecial: boolean;\n readonly isArbitrary: boolean;\n readonly unit: string;\n readonly value: string | undefined;\n readonly function: EssenceFunction | undefined;\n}\n\n/** The parts of the UCUM essence file that unit conversion needs, in document order. */\nexport interface EssenceData {\n readonly version: string;\n readonly revisionDate: string;\n readonly prefixes: readonly EssencePrefix[];\n readonly baseUnits: readonly EssenceBaseUnit[];\n readonly units: readonly EssenceUnit[];\n}\n\n/**\n * Reads prefixes, base units and units from the text of `ucum-essence.xml`. Only the case-sensitive\n * `Code` attributes are used. Names, print symbols and the other descriptive content are skipped.\n *\n * @returns the definitions, or `undefined` if the text is not a well-formed essence document.\n * @see https://ucum.org/ucum#section-Character-Set-and-Lexical-Rules\n */\nexport function readEssence(xml: string): EssenceData | undefined {\n const root = readXmlElements(xml);\n if (root === undefined || root.name !== 'root') return undefined;\n const prefixes: EssencePrefix[] = [];\n const baseUnits: EssenceBaseUnit[] = [];\n const units: EssenceUnit[] = [];\n for (const element of root.children) {\n const code = element.attributes.get('Code');\n if (element.name === 'prefix') {\n const value = child(element, 'value')?.attributes.get('value');\n if (code === undefined || value === undefined) return undefined;\n prefixes.push({ code, value });\n } else if (element.name === 'base-unit') {\n const dimension = element.attributes.get('dim');\n if (code === undefined || dimension === undefined) return undefined;\n baseUnits.push({ code, dimension });\n } else if (element.name === 'unit') {\n const unit = readUnit(element, code);\n if (unit === undefined) return undefined;\n units.push(unit);\n }\n }\n return {\n version: root.attributes.get('version') ?? '',\n revisionDate: root.attributes.get('revision-date') ?? '',\n prefixes,\n baseUnits,\n units,\n };\n}\n\nfunction readUnit(element: XmlElement, code: string | undefined): EssenceUnit | undefined {\n const value = child(element, 'value');\n const unit = value?.attributes.get('Unit');\n if (code === undefined || value === undefined || unit === undefined) return undefined;\n const fn = child(value, 'function');\n let definition: EssenceFunction | undefined;\n if (fn !== undefined) {\n const name = fn.attributes.get('name');\n const fnValue = fn.attributes.get('value');\n const fnUnit = fn.attributes.get('Unit');\n if (name === undefined || fnValue === undefined || fnUnit === undefined) return undefined;\n definition = { name, value: fnValue, unit: fnUnit };\n }\n const isSpecial = element.attributes.get('isSpecial') === 'yes';\n // A special unit is defined by its function; every other unit by a value and a unit term.\n if (isSpecial !== (definition !== undefined)) return undefined;\n const factor = value.attributes.get('value');\n if (!isSpecial && factor === undefined) return undefined;\n return {\n code,\n isMetric: element.attributes.get('isMetric') === 'yes',\n isSpecial,\n isArbitrary: element.attributes.get('isArbitrary') === 'yes',\n unit,\n value: factor,\n function: definition,\n };\n}\n\nfunction child(element: XmlElement, name: string): XmlElement | undefined {\n return element.children.find((candidate) => candidate.name === name);\n}\n","/**\n * An exact fraction `numerator / denominator` in lowest terms, with a positive denominator.\n * Unit magnitudes are kept as rationals, so conversions only round once, at the very end.\n */\nexport interface Rational {\n readonly numerator: bigint;\n readonly denominator: bigint;\n}\n\n/**\n * The largest numerator or denominator, in bits (about 21,000 decimal digits). A Decimal has at\n * most 10,000 digits on either side of the point, so a ratio of 10^20000 or more already maps\n * every non-zero Decimal outside that bound. Larger magnitudes are rejected before `BigInt` work\n * grows with them.\n */\nexport const MAX_RATIONAL_BITS = 70_000;\n\n/**\n * The largest numerator or denominator of a unit magnitude, in bits (about 1,200 decimal digits).\n * The largest magnitude in the essence file needs a few hundred bits, and a realistic unit term\n * a few times more. Unit strings can come from untrusted data, and every `.` or `/` multiplies\n * magnitudes, so this much smaller bound keeps each step cheap: without it, a 10 kB string of\n * `[pi].[pi]…` would take about a minute of `BigInt` work before reaching the value bound.\n */\nexport const MAX_MAGNITUDE_BITS = 4_096;\n\n/** The rational 1. */\nexport const ONE: Rational = Object.freeze({ numerator: 1n, denominator: 1n });\n\n/**\n * `numerator / denominator` in lowest terms, or `undefined` for a zero denominator or when either\n * part needs more than `limit` bits.\n */\nexport function rational(\n numerator: bigint,\n denominator = 1n,\n limit: number = MAX_RATIONAL_BITS,\n): Rational | undefined {\n if (denominator === 0n) return undefined;\n if (denominator < 0n) {\n numerator = -numerator;\n denominator = -denominator;\n }\n const divisor = gcd(abs(numerator), denominator);\n if (divisor > 1n) {\n numerator /= divisor;\n denominator /= divisor;\n }\n if (bitLength(numerator) > limit || bitLength(denominator) > limit) {\n return undefined;\n }\n return { numerator, denominator };\n}\n\n/** `a × b`, or `undefined` when a part needs more than `limit` bits. */\nexport function multiply(\n a: Rational,\n b: Rational,\n limit: number = MAX_RATIONAL_BITS,\n): Rational | undefined {\n return rational(a.numerator * b.numerator, a.denominator * b.denominator, limit);\n}\n\n/** `a / b`, or `undefined` when `b` is zero or a part needs more than `limit` bits. */\nexport function divide(\n a: Rational,\n b: Rational,\n limit: number = MAX_RATIONAL_BITS,\n): Rational | undefined {\n return rational(a.numerator * b.denominator, a.denominator * b.numerator, limit);\n}\n\n/** `a + b`, or `undefined` on overflow. */\nexport function add(a: Rational, b: Rational): Rational | undefined {\n return rational(\n a.numerator * b.denominator + b.numerator * a.denominator,\n a.denominator * b.denominator,\n );\n}\n\n/** `a - b`, or `undefined` on overflow. */\nexport function subtract(a: Rational, b: Rational): Rational | undefined {\n return rational(\n a.numerator * b.denominator - b.numerator * a.denominator,\n a.denominator * b.denominator,\n );\n}\n\n/**\n * `base ^ exponent` for an integer exponent, or `undefined` for `0 ^ -n` and for results with a\n * part beyond `limit` bits. The size is checked before the power is computed.\n */\nexport function power(\n base: Rational,\n exponent: number,\n limit: number = MAX_RATIONAL_BITS,\n): Rational | undefined {\n if (!Number.isSafeInteger(exponent)) return undefined;\n if (exponent === 0) return ONE;\n const magnitude = Math.abs(exponent);\n const size = Math.max(bitLength(base.numerator), bitLength(base.denominator));\n // |x|^n needs at most n × bits(x) bits; 1 stays 1 for any n.\n if (size > 1 && (size - 1) * magnitude > limit) return undefined;\n const n = BigInt(magnitude);\n return exponent > 0\n ? rational(base.numerator ** n, base.denominator ** n, limit)\n : rational(base.denominator ** n, base.numerator ** n, limit);\n}\n\n/** Orders two rationals exactly. */\nexport function compare(a: Rational, b: Rational): -1 | 0 | 1 {\n const left = a.numerator * b.denominator;\n const right = b.numerator * a.denominator;\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\nconst DECIMAL_TEXT = /^([+-]?)([0-9]+)(?:\\.([0-9]+))?(?:[eE]([+-]?[0-9]+))?$/;\n\n/**\n * Parses decimal text with an optional exponent, such as `1e-3`, `980665e-5` or `3.14159`, as the\n * exact rational it denotes. This is the number format of the essence file's `value` attributes.\n */\nexport function parseDecimalText(text: string): Rational | undefined {\n const match = DECIMAL_TEXT.exec(text);\n if (match === null) return undefined;\n const [, sign = '', integer = '', fraction = '', exponentText = '0'] = match;\n const exponent = Number(exponentText) - fraction.length;\n // 10^n has more than 3n bits, so a longer exponent cannot give a magnitude within the bound.\n if (!Number.isSafeInteger(exponent) || Math.abs(exponent) * 3 > MAX_RATIONAL_BITS) {\n return undefined;\n }\n const digits = BigInt(integer + fraction) * (sign === '-' ? -1n : 1n);\n const scale = 10n ** BigInt(Math.abs(exponent));\n return exponent >= 0 ? rational(digits * scale) : rational(digits, scale);\n}\n\n/** The number of bits in `|value|`. */\nfunction bitLength(value: bigint): number {\n return value === 0n ? 0 : abs(value).toString(2).length;\n}\n\n/** The greatest common divisor of two non-negative integers. */\nfunction gcd(a: bigint, b: bigint): bigint {\n while (b !== 0n) [a, b] = [b, a % b];\n return a;\n}\n\nfunction abs(value: bigint): bigint {\n return value < 0n ? -value : value;\n}\n","import { Decimal, MAX_DECIMAL_DIGITS } from '@callis/core';\nimport { type Rational, rational } from './rational.ts';\n\nconst COEFFICIENT_LIMIT = 10n ** BigInt(MAX_DECIMAL_DIGITS);\n\n/** Whether `coefficient × 10^-scale` is within the Decimal size bound. */\nfunction fits(coefficient: bigint, scale: number): boolean {\n return (\n scale <= MAX_DECIMAL_DIGITS &&\n coefficient < COEFFICIENT_LIMIT &&\n -coefficient < COEFFICIENT_LIMIT\n );\n}\n\n/** The exact value of a Decimal as a rational. */\nexport function decimalToRational(value: Decimal): Rational | undefined {\n return rational(value.coefficient, 10n ** BigInt(value.scale));\n}\n\n/**\n * Converts an exact result to a Decimal, as the minimal unit system does. A terminating result\n * keeps every digit and at least `minScale` digits after the point, so `1.0 'm'` becomes\n * `100.0 'cm'`; redundant zeros are only dropped when the value would not fit otherwise. A\n * recurring result is rounded once, by Decimal division (28 significant digits).\n *\n * @returns the Decimal, or `undefined` if it is outside the Decimal size bound.\n * @see https://hl7.org/fhirpath/STU3/en/index.html#unit-conversions\n */\nexport function rationalToDecimal(value: Rational, minScale: number): Decimal | undefined {\n let rest = value.denominator;\n let twos = 0;\n let fives = 0;\n while (rest % 2n === 0n) {\n rest /= 2n;\n twos++;\n }\n while (rest % 5n === 0n) {\n rest /= 5n;\n fives++;\n }\n const places = Math.max(twos, fives);\n if (places > MAX_DECIMAL_DIGITS) return undefined;\n let coefficient = value.numerator * 2n ** BigInt(places - twos) * 5n ** BigInt(places - fives);\n if (rest !== 1n) {\n return fits(coefficient, places) && fits(rest, 0)\n ? Decimal.of(coefficient, places).divide(Decimal.of(rest))\n : undefined;\n }\n let scale = places;\n if (scale < minScale) {\n coefficient *= 10n ** BigInt(minScale - scale);\n scale = minScale;\n }\n while (!fits(coefficient, scale) && scale > 0 && coefficient % 10n === 0n) {\n coefficient /= 10n;\n scale--;\n }\n return fits(coefficient, scale) ? Decimal.of(coefficient, scale) : undefined;\n}\n\n/**\n * A strictly positive scale as `factor` and optional `divisor` Decimals: a terminating scale is a\n * single exact factor, and a recurring one such as 1/60 keeps both integers so that callers can\n * divide once at the end.\n */\nexport function rationalToScale(\n value: Rational,\n): { readonly factor: Decimal; readonly divisor?: Decimal } | undefined {\n if (value.numerator <= 0n) return undefined;\n const exact = isTerminating(value.denominator) ? rationalToDecimal(value, 0) : undefined;\n if (exact !== undefined) return { factor: exact };\n return fits(value.numerator, 0) && fits(value.denominator, 0)\n ? { factor: Decimal.of(value.numerator), divisor: Decimal.of(value.denominator) }\n : undefined;\n}\n\nfunction isTerminating(denominator: bigint): boolean {\n let rest = denominator;\n while (rest % 2n === 0n) rest /= 2n;\n while (rest % 5n === 0n) rest /= 5n;\n return rest === 1n;\n}\n","/**\n * A dimension: the exponent of each axis, keyed by base unit code (`m`, `s`, `g`, `rad`, `K`, `C`,\n * `cd`) or by the code of an arbitrary unit, which is its own axis. Zero exponents are omitted, so\n * the dimensionless unit is the empty map.\n * @see https://ucum.org/ucum#section-Semantics\n */\nexport type Dimension = ReadonlyMap<string, number>;\n\n/** The dimension of the unity `1`. */\nexport const DIMENSIONLESS: Dimension = new Map();\n\n/** The dimension with one axis at exponent 1. */\nexport function axis(code: string): Dimension {\n return new Map([[code, 1]]);\n}\n\n/**\n * `a × b^exponent`, or `undefined` if an exponent leaves the safe integer range.\n */\nexport function combineDimensions(a: Dimension, b: Dimension, exponent = 1): Dimension | undefined {\n const result = new Map(a);\n for (const [code, value] of b) {\n const product = value * exponent;\n const sum = (result.get(code) ?? 0) + product;\n if (!Number.isSafeInteger(product) || !Number.isSafeInteger(sum)) return undefined;\n if (sum === 0) result.delete(code);\n else result.set(code, sum);\n }\n return result;\n}\n\n/** Whether two dimensions are the same, so that their units are commensurable. */\nexport function sameDimension(a: Dimension, b: Dimension): boolean {\n if (a.size !== b.size) return false;\n for (const [code, value] of a) {\n if (b.get(code) !== value) return false;\n }\n return true;\n}\n","/** A simple unit (an optional prefix and an atom, not yet split) with its exponent. */\nexport interface SymbolComponent {\n readonly kind: 'symbol';\n readonly symbol: string;\n readonly exponent: number;\n readonly annotation: string | undefined;\n}\n\n/** A positive integer used as a unit, as in `10.L`; `2+10` raises it to a power (§9). */\nexport interface NumberComponent {\n readonly kind: 'number';\n readonly value: bigint;\n readonly exponent: number;\n}\n\n/** An annotation on its own, such as `{RBC}`, which means the unity `1`. */\nexport interface AnnotationComponent {\n readonly kind: 'annotation';\n readonly text: string;\n}\n\n/** A parenthesized term. */\nexport interface GroupComponent {\n readonly kind: 'group';\n readonly term: UnitTermSyntax;\n}\n\n/** One component of a term. */\nexport type UnitComponent =\n | SymbolComponent\n | NumberComponent\n | AnnotationComponent\n | GroupComponent;\n\n/** A component with the operator before it: 1 for `.` (and the first), -1 for `/`. */\nexport interface UnitFactorSyntax {\n readonly operator: 1 | -1;\n readonly component: UnitComponent;\n}\n\n/** A term: components joined by `.` and `/`, evaluated from left to right. */\nexport interface UnitTermSyntax {\n readonly factors: readonly UnitFactorSyntax[];\n}\n\n/** Parentheses nested deeper than this are rejected, so parsing cannot exhaust the stack. */\nexport const MAX_GROUP_DEPTH = 32;\n\n/** Characters that end a symbol outside square brackets. */\nconst DELIMITERS = new Set(['.', '/', '(', ')', '{', '}']);\nconst DIGITS = /^[0-9]+$/;\n\ninterface Cursor {\n index: number;\n}\n\n/**\n * Parses the syntax of a case-sensitive UCUM unit expression without looking up any symbol, so\n * `xyz` parses here and is rejected later. Whitespace and characters outside ASCII 33–126 are\n * invalid.\n *\n * @returns the term, or `undefined` if the text is not a syntactically valid unit expression.\n * @see https://ucum.org/ucum#section-Syntax-Rules\n */\nexport function parseUnitExpression(text: string): UnitTermSyntax | undefined {\n if (text.length === 0) return undefined;\n for (let index = 0; index < text.length; index++) {\n const code = text.charCodeAt(index);\n if (code < 0x21 || code > 0x7e) return undefined;\n }\n // §7■3: a leading solidus inverts the unit that directly follows it.\n const leading = text.startsWith('/');\n const cursor: Cursor = { index: leading ? 1 : 0 };\n const term = parseTerm(text, cursor, leading ? -1 : 1, 0);\n return term !== undefined && cursor.index === text.length ? term : undefined;\n}\n\nfunction parseTerm(\n text: string,\n cursor: Cursor,\n first: 1 | -1,\n depth: number,\n): UnitTermSyntax | undefined {\n const factors: UnitFactorSyntax[] = [];\n let operator = first;\n for (;;) {\n const component = parseComponent(text, cursor, depth);\n if (component === undefined) return undefined;\n factors.push({ operator, component });\n const next = text[cursor.index];\n if (next === '.') operator = 1;\n else if (next === '/') operator = -1;\n else return { factors };\n cursor.index++;\n }\n}\n\nfunction parseComponent(text: string, cursor: Cursor, depth: number): UnitComponent | undefined {\n const start = cursor.index;\n const first = text[start];\n if (first === '(') {\n if (depth >= MAX_GROUP_DEPTH) return undefined;\n cursor.index++;\n const term = parseTerm(text, cursor, 1, depth + 1);\n if (term === undefined || text[cursor.index] !== ')') return undefined;\n cursor.index++;\n return { kind: 'group', term };\n }\n if (first === '{') {\n const annotation = parseAnnotation(text, cursor);\n return annotation === undefined ? undefined : { kind: 'annotation', text: annotation };\n }\n // A symbol runs to the next delimiter; inside square brackets every character is part of it.\n let index = start;\n let brackets = 0;\n for (; index < text.length; index++) {\n const char = text.charAt(index);\n if (char === '[') brackets++;\n else if (char === ']') {\n if (brackets === 0) return undefined;\n brackets--;\n } else if (brackets === 0 && DELIMITERS.has(char)) break;\n }\n if (brackets !== 0 || index === start) return undefined;\n const run = text.slice(start, index);\n cursor.index = index;\n // §8: only a pure string of digits is a number.\n if (DIGITS.test(run)) return { kind: 'number', value: BigInt(run), exponent: 1 };\n const split = exponentStart(run);\n const symbol = run.slice(0, split);\n const exponent = split === run.length ? 1 : Number(run.slice(split));\n if (!Number.isSafeInteger(exponent)) return undefined;\n if (DIGITS.test(symbol)) {\n // §9: an explicit sign separates an exponent from a number, so `2+10` is 2^10.\n return { kind: 'number', value: BigInt(symbol), exponent };\n }\n let annotation: string | undefined;\n if (text[cursor.index] === '{') {\n annotation = parseAnnotation(text, cursor);\n if (annotation === undefined) return undefined;\n }\n return { kind: 'symbol', symbol, exponent, annotation };\n}\n\n/**\n * Where the exponent of a symbol starts: its trailing digits with an optional sign (§9), or the\n * end of the symbol if it has none. A linear scan, so long input cannot cause backtracking.\n */\nfunction exponentStart(run: string): number {\n let start = run.length;\n while (start > 0 && isDigit(run.charCodeAt(start - 1))) start--;\n if (start === run.length) return run.length;\n const sign = run[start - 1];\n if (sign === '+' || sign === '-') start--;\n return start === 0 ? run.length : start;\n}\n\nfunction isDigit(code: number): boolean {\n return code >= 0x30 && code <= 0x39;\n}\n\n/** Reads `{…}` at the cursor; the text inside may not contain another curly brace. */\nfunction parseAnnotation(text: string, cursor: Cursor): string | undefined {\n const end = text.indexOf('}', cursor.index + 1);\n if (end === -1) return undefined;\n const annotation = text.slice(cursor.index + 1, end);\n if (annotation.includes('{')) return undefined;\n cursor.index = end + 1;\n return annotation;\n}\n","import type { Atom, SpecialScale, UnitLookup } from './atom.ts';\nimport { combineDimensions, DIMENSIONLESS, type Dimension } from './dimension.ts';\nimport { parseUnitExpression, type UnitTermSyntax } from './expression/unit-expression.ts';\nimport { MAX_MAGNITUDE_BITS, multiply, ONE, power, type Rational } from './rational.ts';\n\n/** A simple unit of an expression with its exponent, kept for unit algebra. */\nexport interface UnitTerm {\n /** The prefix and atom as written, without exponent or annotation, such as `cm`. */\n readonly symbol: string;\n readonly exponent: number;\n /** The magnitude of the simple unit itself (prefix × atom), before the exponent. */\n readonly magnitude: Rational;\n /** The dimension of the simple unit itself, before the exponent. */\n readonly dimension: Dimension;\n readonly arbitrary: boolean;\n}\n\n/** A unit expression resolved to its magnitude and dimension in base units. */\nexport interface ResolvedUnit {\n readonly magnitude: Rational;\n readonly dimension: Dimension;\n /** Every simple unit with its signed exponent, in written order. */\n readonly terms: readonly UnitTerm[];\n /** The product of the integer numbers in the expression, such as 10 in `10.L`. */\n readonly scalar: Rational;\n /** Whether an arbitrary unit occurs, which makes the whole term arbitrary (§25). */\n readonly arbitrary: boolean;\n /**\n * Set when a special unit occurs. Only a special unit on its own, without prefix or exponent,\n * keeps its scale; any other use is `unsupported` (§22).\n */\n readonly special: SpecialScale | undefined;\n}\n\nconst UNSUPPORTED: SpecialScale = Object.freeze({ kind: 'unsupported' });\n\ninterface Accumulator {\n magnitude: Rational;\n dimension: Dimension;\n scalar: Rational;\n arbitrary: boolean;\n special: boolean;\n readonly terms: UnitTerm[];\n}\n\n/**\n * Resolves a case-sensitive UCUM expression such as `mg/dL` or `kg.m/s2` against the symbol\n * tables. Annotations are ignored (§12).\n *\n * @returns the unit, or `undefined` if it is invalid, uses an unknown symbol, has a zero\n * number, or a magnitude on the way needs more than {@link MAX_MAGNITUDE_BITS} bits.\n * @see https://ucum.org/ucum#section-Semantics\n */\nexport function resolveUnit(text: string, lookup: UnitLookup): ResolvedUnit | undefined {\n const syntax = parseUnitExpression(text);\n if (syntax === undefined) return undefined;\n const state: Accumulator = {\n magnitude: ONE,\n dimension: DIMENSIONLESS,\n scalar: ONE,\n arbitrary: false,\n special: false,\n terms: [],\n };\n if (!accumulate(syntax, 1, state, lookup)) return undefined;\n if (state.special) return resolveSpecial(syntax, lookup);\n return {\n magnitude: state.magnitude,\n dimension: state.dimension,\n terms: state.terms,\n scalar: state.scalar,\n arbitrary: state.arbitrary,\n special: undefined,\n };\n}\n\nfunction accumulate(\n term: UnitTermSyntax,\n sign: 1 | -1,\n state: Accumulator,\n lookup: UnitLookup,\n): boolean {\n for (const { operator, component } of term.factors) {\n const direction = sign === operator ? 1 : -1;\n switch (component.kind) {\n case 'annotation':\n break;\n case 'group':\n if (!accumulate(component.term, direction, state, lookup)) return false;\n break;\n case 'number': {\n const value = power(\n { numerator: component.value, denominator: 1n },\n component.exponent,\n MAX_MAGNITUDE_BITS,\n );\n const scaled = value === undefined ? undefined : power(value, direction);\n if (scaled === undefined || scaled.numerator === 0n) return false;\n const magnitude = multiply(state.magnitude, scaled, MAX_MAGNITUDE_BITS);\n const scalar = multiply(state.scalar, scaled, MAX_MAGNITUDE_BITS);\n if (magnitude === undefined || scalar === undefined) return false;\n state.magnitude = magnitude;\n state.scalar = scalar;\n break;\n }\n case 'symbol': {\n const unit = simpleUnit(component.symbol, lookup);\n if (unit === undefined) return false;\n if (unit.atom.special !== undefined) {\n state.special = true;\n break;\n }\n const exponent = component.exponent * direction;\n const perUnit = multiply(unit.prefix, unit.atom.magnitude, MAX_MAGNITUDE_BITS);\n const scaled =\n perUnit === undefined ? undefined : power(perUnit, exponent, MAX_MAGNITUDE_BITS);\n const magnitude =\n scaled === undefined ? undefined : multiply(state.magnitude, scaled, MAX_MAGNITUDE_BITS);\n const dimension = combineDimensions(state.dimension, unit.atom.dimension, exponent);\n if (perUnit === undefined || magnitude === undefined || dimension === undefined) {\n return false;\n }\n state.magnitude = magnitude;\n state.dimension = dimension;\n state.arbitrary ||= unit.atom.arbitrary;\n state.terms.push({\n symbol: component.symbol,\n exponent,\n magnitude: perUnit,\n dimension: unit.atom.dimension,\n arbitrary: unit.atom.arbitrary,\n });\n break;\n }\n default:\n return assertNever(component);\n }\n }\n return true;\n}\n\n/**\n * Special units take no part in algebra (§22■1). Only a lone, unprefixed special unit with\n * exponent 1, such as `Cel` or `Cel{body}`, keeps its scale.\n */\nfunction resolveSpecial(syntax: UnitTermSyntax, lookup: UnitLookup): ResolvedUnit {\n const [only, ...rest] = syntax.factors;\n const component = only?.component;\n const atom =\n rest.length === 0 &&\n only?.operator === 1 &&\n component?.kind === 'symbol' &&\n component.exponent === 1\n ? lookup.atom(component.symbol)\n : undefined;\n if (atom?.special?.kind === 'affine') {\n return {\n magnitude: atom.magnitude,\n dimension: atom.dimension,\n terms: [],\n scalar: ONE,\n arbitrary: false,\n special: atom.special,\n };\n }\n return {\n magnitude: ONE,\n dimension: DIMENSIONLESS,\n terms: [],\n scalar: ONE,\n arbitrary: false,\n special: UNSUPPORTED,\n };\n}\n\n/**\n * Splits a simple unit into prefix and atom. The prefix is the longest one whose remainder is a\n * metric atom; without such a prefix the whole symbol must be an atom (§4■4).\n */\nfunction simpleUnit(\n symbol: string,\n lookup: UnitLookup,\n): { readonly prefix: Rational; readonly atom: Atom } | undefined {\n for (const code of lookup.prefixCodes) {\n if (symbol.length <= code.length || !symbol.startsWith(code)) continue;\n const rest = symbol.slice(code.length);\n if (!lookup.hasAtom(rest) || !lookup.isMetric(rest)) continue;\n const atom = lookup.atom(rest);\n const prefix = lookup.prefix(code);\n return atom === undefined || prefix === undefined ? undefined : { prefix, atom };\n }\n const atom = lookup.atom(symbol);\n return atom === undefined ? undefined : { prefix: ONE, atom };\n}\n\nfunction assertNever(value: never): never {\n return value;\n}\n","import {\n Decimal,\n minimalUnitSystem,\n type ParsedUnit,\n type UnitConversionOptions,\n type UnitProduct,\n type UnitSystem,\n} from '@callis/core';\nimport type { UnitLookup } from './atom.ts';\nimport { decimalToRational, rationalToDecimal, rationalToScale } from './decimal-rational.ts';\nimport { type Dimension, sameDimension } from './dimension.ts';\nimport {\n add,\n compare as compareRational,\n divide,\n MAX_MAGNITUDE_BITS,\n multiply,\n power,\n type Rational,\n subtract,\n} from './rational.ts';\nimport { type ResolvedUnit, resolveUnit, type UnitTerm } from './resolve-unit.ts';\n\n/**\n * The UCUM counterpart of each calendar keyword. Week to millisecond are equal to theirs; year and\n * month are only equivalent to `a` and `mo`.\n * @see https://hl7.org/fhirpath/STU3/#time-valued-quantities\n */\nconst CALENDAR_UCUM: Readonly<Record<string, string>> = Object.freeze({\n year: 'a',\n month: 'mo',\n week: 'wk',\n day: 'd',\n hour: 'h',\n minute: 'min',\n second: 's',\n millisecond: 'ms',\n});\n\n/**\n * Creates a UCUM unit system from resolved symbol tables.\n *\n * Calendar keywords and the units the minimal unit system knows (`1` and the UCUM time units)\n * are handed to `minimalUnitSystem` whenever both units of an operation are among them, so the\n * calendar rules stay exactly as in core. Other units are resolved as UCUM expressions:\n * commensurable units convert exactly, `Cel` and `[degF]` convert on their offset scales, and\n * arbitrary or other special units only match the identical unit.\n */\nexport function createUcumUnitSystem(lookup: UnitLookup): UnitSystem {\n const resolve = (unit: string): ResolvedUnit | undefined => resolveUnit(unit, lookup);\n\n function convertUcum(value: Decimal, from: string, to: string): Decimal | undefined {\n const source = commensurable(resolve(from), resolve(to));\n if (source === undefined) return undefined;\n const exact = decimalToRational(value);\n const base = exact === undefined ? undefined : toBase(exact, source[0]);\n const result = base === undefined ? undefined : fromBase(base, source[1]);\n return result === undefined ? undefined : rationalToDecimal(result, value.scale);\n }\n\n function compareUcum(a: Decimal, from: string, b: Decimal, to: string): -1 | 0 | 1 | undefined {\n const units = commensurable(resolve(from), resolve(to));\n if (units === undefined) return undefined;\n const left = decimalToRational(a);\n const right = decimalToRational(b);\n const leftBase = left === undefined ? undefined : toBase(left, units[0]);\n const rightBase = right === undefined ? undefined : toBase(right, units[1]);\n return leftBase === undefined || rightBase === undefined\n ? undefined\n : compareRational(leftBase, rightBase);\n }\n\n function algebra(a: string, b: string, sign: 1 | -1): UnitProduct | undefined {\n const left = resolve(a);\n const right = resolve(b);\n // §22: special units take no part in algebra, not even with a scalar.\n if (left?.special !== undefined || right?.special !== undefined) return undefined;\n // Like the minimal unit system, '1' and identical units keep units that UCUM does not know.\n if (b === '1') return { unit: a, factor: Decimal.ONE };\n if (sign === 1 && a === '1') return { unit: b, factor: Decimal.ONE };\n if (sign === -1 && a === b) return { unit: '1', factor: Decimal.ONE };\n if (left === undefined || right === undefined) return undefined;\n const product = canonicalProduct(left, right, sign);\n // The unit must resolve again within the same bounds, so that later operations can use it.\n return product === undefined || resolve(product.unit) === undefined ? undefined : product;\n }\n\n return Object.freeze({\n parse(unit: string): ParsedUnit | undefined {\n return minimalUnitSystem.parse(unit) ?? (resolve(unit) === undefined ? undefined : { unit });\n },\n convert(\n value: Decimal,\n from: string,\n to: string,\n options?: UnitConversionOptions,\n ): Decimal | undefined {\n const source = calendarKeyword(from);\n const target = calendarKeyword(to);\n if ((source ?? from) === (target ?? to)) return value;\n if (isMinimalUnit(from) && isMinimalUnit(to)) {\n return minimalUnitSystem.convert(value, from, to, options);\n }\n // Explicit conversion stays in the source system and relabels to the target's\n // counterpart, so only a calendar target may use its year/month counterpart.\n const explicit = options?.explicit === true;\n const equivalence = !explicit && options?.equivalence === true;\n const a = source === undefined ? from : ucumCounterpart(source, equivalence);\n const b = target === undefined ? to : ucumCounterpart(target, equivalence || explicit);\n return a === undefined || b === undefined ? undefined : convertUcum(value, a, b);\n },\n compare(a: Decimal, from: string, b: Decimal, to: string): -1 | 0 | 1 | undefined {\n const source = calendarKeyword(from);\n const target = calendarKeyword(to);\n if ((source ?? from) === (target ?? to)) return a.compare(b);\n if (isMinimalUnit(from) && isMinimalUnit(to)) {\n return minimalUnitSystem.compare?.(a, from, b, to);\n }\n const x = source === undefined ? from : ucumCounterpart(source, false);\n const y = target === undefined ? to : ucumCounterpart(target, false);\n return x === undefined || y === undefined ? undefined : compareUcum(a, x, b, y);\n },\n multiply(a: string, b: string): UnitProduct | undefined {\n // Calendar units only combine with '1' (3.0.0 multiplication).\n if (calendarKeyword(a) !== undefined || calendarKeyword(b) !== undefined) {\n return minimalUnitSystem.multiply(a, b);\n }\n return algebra(a, b, 1);\n },\n divide(a: string, b: string): UnitProduct | undefined {\n if (calendarKeyword(a) !== undefined || calendarKeyword(b) !== undefined) {\n return minimalUnitSystem.divide(a, b);\n }\n return algebra(a, b, -1);\n },\n });\n}\n\n/** Both units if they can be converted into each other, else `undefined`. */\nfunction commensurable(\n a: ResolvedUnit | undefined,\n b: ResolvedUnit | undefined,\n): readonly [ResolvedUnit, ResolvedUnit] | undefined {\n if (a === undefined || b === undefined) return undefined;\n if (a.special?.kind === 'unsupported' || b.special?.kind === 'unsupported') return undefined;\n // §25: a term with an arbitrary unit is not comparable with any other term.\n if (a.arbitrary || b.arbitrary) return undefined;\n return sameDimension(a.dimension, b.dimension) ? [a, b] : undefined;\n}\n\n/** The value in base units: `(value + offset) × magnitude` for `Cel` and `[degF]`. */\nfunction toBase(value: Rational, unit: ResolvedUnit): Rational | undefined {\n const shifted = unit.special?.kind === 'affine' ? add(value, unit.special.offset) : value;\n return shifted === undefined ? undefined : multiply(shifted, unit.magnitude);\n}\n\nfunction fromBase(base: Rational, unit: ResolvedUnit): Rational | undefined {\n const scaled = divide(base, unit.magnitude);\n if (scaled === undefined || unit.special?.kind !== 'affine') return scaled;\n return subtract(scaled, unit.special.offset);\n}\n\n/**\n * The product or quotient of two units in canonical form. Identical simple units add their\n * exponents (`cm2 / cm` is `cm`); a simple unit commensurable with an earlier one that has not\n * cancelled out is converted into it (`m/s × min` is `m` with factor 60, and `cm / m` is `1` with\n * factor 1/100). Arbitrary and dimensionless units only combine with identical ones. Integer\n * factors and annotations are folded into the scale.\n * @see https://hl7.org/fhirpath/STU3/en/index.html#multiplication\n */\nfunction canonicalProduct(\n left: ResolvedUnit,\n right: ResolvedUnit,\n sign: 1 | -1,\n): UnitProduct | undefined {\n let scale =\n sign === 1\n ? multiply(left.scalar, right.scalar, MAX_MAGNITUDE_BITS)\n : divide(left.scalar, right.scalar, MAX_MAGNITUDE_BITS);\n const terms: { term: UnitTerm; exponent: number }[] = [];\n // Maps keep this linear in the number of terms, whatever the input.\n const bySymbol = new Map<string, { term: UnitTerm; exponent: number }>();\n const byDimension = new Map<string, { term: UnitTerm; exponent: number }>();\n const inputs = [\n ...left.terms.map((term) => ({ term, exponent: term.exponent })),\n ...right.terms.map((term) => ({ term, exponent: term.exponent * sign })),\n ];\n for (const input of inputs) {\n if (scale === undefined) return undefined;\n const merges = !input.term.arbitrary && input.term.dimension.size > 0;\n const key = merges ? dimensionKey(input.term.dimension) : '';\n const same = bySymbol.get(input.term.symbol);\n const target = same ?? (merges ? byDimension.get(key) : undefined);\n if (target === undefined) {\n const entry = { term: input.term, exponent: input.exponent };\n terms.push(entry);\n bySymbol.set(input.term.symbol, entry);\n if (merges) byDimension.set(key, entry);\n continue;\n }\n if (target !== same) {\n const ratio = divide(input.term.magnitude, target.term.magnitude, MAX_MAGNITUDE_BITS);\n const factor =\n ratio === undefined ? undefined : power(ratio, input.exponent, MAX_MAGNITUDE_BITS);\n scale = factor === undefined ? undefined : multiply(scale, factor, MAX_MAGNITUDE_BITS);\n }\n target.exponent += input.exponent;\n if (!Number.isSafeInteger(target.exponent)) return undefined;\n // A unit that cancelled out no longer appears, so later units do not convert into it.\n if (target.exponent === 0) {\n bySymbol.delete(target.term.symbol);\n if (byDimension.get(key) === target) byDimension.delete(key);\n }\n }\n if (scale === undefined) return undefined;\n const parts = rationalToScale(scale);\n if (parts === undefined) return undefined;\n const unit = formatTerms(terms);\n return parts.divisor === undefined\n ? { unit, factor: parts.factor }\n : { unit, factor: parts.factor, divisor: parts.divisor };\n}\n\n/** A string that two dimensions share exactly when they are the same. */\nfunction dimensionKey(dimension: Dimension): string {\n return JSON.stringify([...dimension].sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)));\n}\n\n/** Writes terms as `a.b2/c/d3`, or `/s` without a numerator, or `1` when nothing is left. */\nfunction formatTerms(terms: readonly { term: UnitTerm; exponent: number }[]): string {\n let numerator = '';\n let denominator = '';\n for (const { term, exponent } of terms) {\n if (exponent > 0) {\n numerator += `${numerator === '' ? '' : '.'}${term.symbol}${exponent === 1 ? '' : exponent}`;\n } else if (exponent < 0) {\n denominator += `/${term.symbol}${exponent === -1 ? '' : -exponent}`;\n }\n }\n return numerator === '' && denominator === '' ? '1' : numerator + denominator;\n}\n\n/** The singular calendar keyword a unit spells, if any (`weeks` is `week`). */\nfunction calendarKeyword(unit: string): string | undefined {\n const singular = unit.endsWith('s') ? unit.slice(0, -1) : unit;\n if (Object.hasOwn(CALENDAR_UCUM, unit)) return unit;\n return Object.hasOwn(CALENDAR_UCUM, singular) ? singular : undefined;\n}\n\n/** The UCUM unit a calendar keyword may be related to; year/month only with equivalence. */\nfunction ucumCounterpart(keyword: string, yearAndMonth: boolean): string | undefined {\n if ((keyword === 'year' || keyword === 'month') && !yearAndMonth) return undefined;\n return Object.hasOwn(CALENDAR_UCUM, keyword) ? CALENDAR_UCUM[keyword] : undefined;\n}\n\n/** Units the minimal unit system knows: `1`, calendar keywords and the UCUM time units. */\nfunction isMinimalUnit(unit: string): boolean {\n return minimalUnitSystem.parse(unit) !== undefined;\n}\n","import type { Atom, SpecialScale, UnitLookup } from './atom.ts';\nimport { axis, combineDimensions } from './dimension.ts';\nimport type { EssenceData, EssenceUnit } from './essence/essence-reader.ts';\nimport { MAX_MAGNITUDE_BITS, multiply, ONE, parseDecimalText, type Rational } from './rational.ts';\nimport { resolveUnit } from './resolve-unit.ts';\n\n/**\n * The special-unit functions Callis converts, by function name in the essence file. Each is the\n * affine relation `proper = (value + offset) × magnitude`: `Cel` gives kelvin = °C + 273.15, and\n * `degF` gives (5/9 K) multiples = °F + 459.67. The essence file names these functions; their\n * definitions come from the UCUM specification text. Other special units are not convertible.\n * @see https://ucum.org/ucum#section-Special-Units-on-non-ratio-Scales\n */\nconst AFFINE_OFFSETS: Readonly<Record<string, Rational>> = Object.freeze({\n Cel: Object.freeze({ numerator: 5463n, denominator: 20n }), // 273.15\n degF: Object.freeze({ numerator: 45967n, denominator: 100n }), // 459.67\n});\n\n/** A lookup that knows no units, for when the essence data cannot be read. */\nexport const EMPTY_UNIT_LOOKUP: UnitLookup = Object.freeze({\n hasAtom: () => false,\n isMetric: () => false,\n atom: () => undefined,\n prefix: () => undefined,\n prefixCodes: Object.freeze([]),\n});\n\n/**\n * Resolves every prefix, base unit and unit of the essence data to a magnitude and dimension in\n * base units. Definitions refer to other units, so each atom is resolved once, on first need.\n * An atom whose definition is invalid, circular or out of bounds is left out.\n */\nexport function buildUnitTable(data: EssenceData): UnitLookup {\n const prefixes = new Map<string, Rational>();\n for (const prefix of data.prefixes) {\n const value = parseDecimalText(prefix.value);\n if (value !== undefined && value.numerator > 0n) prefixes.set(prefix.code, value);\n }\n const atoms = new Map<string, Atom>();\n for (const base of data.baseUnits) {\n atoms.set(base.code, {\n code: base.code,\n isMetric: true,\n magnitude: ONE,\n dimension: axis(base.code),\n arbitrary: false,\n special: undefined,\n });\n }\n const definitions = new Map<string, EssenceUnit>();\n for (const unit of data.units) {\n if (!atoms.has(unit.code) && !definitions.has(unit.code)) definitions.set(unit.code, unit);\n }\n const prefixCodes = Object.freeze(\n [...prefixes.keys()].sort((a, b) => b.length - a.length || (a < b ? -1 : a > b ? 1 : 0)),\n );\n const pending = new Set<string>();\n const failed = new Set<string>();\n\n const lookup: UnitLookup = {\n hasAtom: (code) => atoms.has(code) || definitions.has(code),\n isMetric: (code) => atoms.get(code)?.isMetric ?? definitions.get(code)?.isMetric ?? false,\n atom: (code) => {\n const known = atoms.get(code);\n if (known !== undefined) return known;\n const definition = definitions.get(code);\n if (definition === undefined || pending.has(code) || failed.has(code)) return undefined;\n pending.add(code);\n const atom = defineAtom(definition, lookup);\n pending.delete(code);\n if (atom === undefined) failed.add(code);\n else atoms.set(code, atom);\n return atom;\n },\n prefix: (code) => prefixes.get(code),\n prefixCodes,\n };\n for (const code of definitions.keys()) lookup.atom(code);\n\n return Object.freeze({\n hasAtom: (code: string) => atoms.has(code),\n isMetric: (code: string) => atoms.get(code)?.isMetric ?? false,\n atom: (code: string) => atoms.get(code),\n prefix: (code: string) => prefixes.get(code),\n prefixCodes,\n });\n}\n\nfunction defineAtom(definition: EssenceUnit, lookup: UnitLookup): Atom | undefined {\n const source = definition.function ?? { value: definition.value ?? '', unit: definition.unit };\n const value = parseDecimalText(source.value);\n const unit = resolveUnit(source.unit, lookup);\n if (\n value === undefined ||\n value.numerator <= 0n ||\n unit === undefined ||\n unit.special !== undefined\n ) {\n return undefined;\n }\n const magnitude = multiply(value, unit.magnitude, MAX_MAGNITUDE_BITS);\n if (magnitude === undefined) return undefined;\n let special: SpecialScale | undefined;\n if (definition.function !== undefined) {\n const name = definition.function.name;\n const offset = Object.hasOwn(AFFINE_OFFSETS, name) ? AFFINE_OFFSETS[name] : undefined;\n special = offset === undefined ? { kind: 'unsupported' } : { kind: 'affine', offset };\n }\n // §24: an arbitrary unit is its own dimension, commensurable with nothing else.\n const dimension = definition.isArbitrary\n ? combineDimensions(unit.dimension, axis(definition.code))\n : unit.dimension;\n if (dimension === undefined) return undefined;\n return {\n code: definition.code,\n isMetric: definition.isMetric,\n magnitude,\n dimension,\n arbitrary: definition.isArbitrary || unit.arbitrary,\n special,\n };\n}\n","/**\n * Public API of `@callis/ucum`: full UCUM unit conversion for Callis.\n *\n * The package embeds the unchanged UCUM essence file (`ucum-essence.xml`, under the UCUM license;\n * see `SOURCE.md`) and reads it once, when this module is first imported. The code is MIT\n * licensed and has no runtime dependencies besides its `@callis/core` peer.\n *\n * @packageDocumentation\n */\nimport type { UnitSystem } from '@callis/core';\nimport type { UnitLookup } from './atom.ts';\nimport { readEssence } from './essence/essence-reader.ts';\nimport { UCUM_ESSENCE_XML } from './essence/ucum-essence-xml.ts';\nimport { createUcumUnitSystem } from './ucum-unit-system.ts';\nimport { buildUnitTable, EMPTY_UNIT_LOOKUP } from './unit-table.ts';\n\n/**\n * A `UnitSystem` with the full UCUM: prefixes, every unit of the essence file, unit expressions\n * such as `mg/dL` or `kg.m/s2`, annotations, `10*n` and `10^n`. Commensurable units convert\n * exactly; `Cel` and `[degF]` convert on their offset scales; arbitrary units and other special\n * units only match the identical unit. Calendar keywords keep the rules of the minimal unit\n * system in `@callis/core`. Unknown or invalid units give `undefined`; nothing throws.\n *\n * @example\n * ```ts\n * import { Decimal } from '@callis/core';\n * import { ucum } from '@callis/ucum';\n *\n * ucum.convert(Decimal.ONE, 'mg/dL', 'g/L')?.toString(); // '0.01'\n * ucum.compare?.(Decimal.ONE, 'kg', Decimal.of(1000n), 'g'); // 0\n * ```\n * @see https://ucum.org/ucum\n * @see https://hl7.org/fhirpath/STU3/#quantity\n */\nexport const ucum: UnitSystem = /* @__PURE__ */ createUcumUnitSystem(\n /* @__PURE__ */ loadUnitTable(),\n);\n\nfunction loadUnitTable(): UnitLookup {\n const essence = readEssence(UCUM_ESSENCE_XML);\n // The embedded file is fixed and checked by the tests, so this fallback is defensive only.\n return essence === undefined ? EMPTY_UNIT_LOOKUP : buildUnitTable(essence);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,59 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@callis/ucum",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "UCUM unit conversion for Callis, from the unchanged UCUM essence file",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"fhirpath",
|
|
7
|
+
"fhir",
|
|
8
|
+
"ucum",
|
|
9
|
+
"units",
|
|
10
|
+
"hl7",
|
|
11
|
+
"healthcare",
|
|
12
|
+
"typescript"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT AND LicenseRef-UCUM",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/losol/callis.git",
|
|
18
|
+
"directory": "packages/ucum"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/losol/callis/tree/main/packages/ucum#readme",
|
|
21
|
+
"bugs": "https://github.com/losol/callis/issues",
|
|
22
|
+
"type": "module",
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"default": "./dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./package.json": "./package.json"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"data",
|
|
34
|
+
"LICENSE.md",
|
|
35
|
+
"SOURCE.md",
|
|
36
|
+
"UCUM-LICENSE.md",
|
|
37
|
+
"CHANGELOG.md"
|
|
38
|
+
],
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=22"
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"@callis/core": "^0.1.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@callis/core": "^0.1.0",
|
|
50
|
+
"fast-check": "4.10.2"
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "tsdown",
|
|
54
|
+
"typecheck": "tsc -p . && tsc -p tsconfig.node.json",
|
|
55
|
+
"embed": "node scripts/embed-essence.ts",
|
|
56
|
+
"measure": "node scripts/measure-startup.ts",
|
|
57
|
+
"check:package": "publint --strict && attw --pack . --profile esm-only && node scripts/check-pack.ts"
|
|
58
|
+
}
|
|
6
59
|
}
|