@cosyte/terminology 0.0.1

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/dist/index.mjs ADDED
@@ -0,0 +1,4669 @@
1
+ // src/common/coding.ts
2
+ function coding(init) {
3
+ const out = { code: init.code };
4
+ if (init.system !== void 0) out.system = init.system;
5
+ if (init.version !== void 0) out.version = init.version;
6
+ if (init.display !== void 0) out.display = init.display;
7
+ return Object.freeze(out);
8
+ }
9
+ function codeableConcept(init) {
10
+ const frozenCodings = Object.freeze(init.coding.map((c) => coding(c)));
11
+ const out = {
12
+ coding: frozenCodings
13
+ };
14
+ if (init.text !== void 0) out.text = init.text;
15
+ return Object.freeze(out);
16
+ }
17
+
18
+ // src/common/diagnostics.ts
19
+ var DIAGNOSTIC_CODES = {
20
+ /**
21
+ * A `$translate` found no target for the source code. A **first-class outcome, never an error** —
22
+ * the source is surfaced as `unmapped`, never replaced with a guessed target (the never-fabricate
23
+ * invariant).
24
+ */
25
+ TERM_TRANSLATE_UNMAPPED: "TERM_TRANSLATE_UNMAPPED",
26
+ /**
27
+ * A code-system identifier (URI, OID, or mnemonic) was not recognized by the identity resolver.
28
+ * Surfaced as a typed `unknown`, never coerced to a guessed canonical URI.
29
+ */
30
+ TERM_SYSTEM_UNRECOGNIZED: "TERM_SYSTEM_UNRECOGNIZED",
31
+ /**
32
+ * An RRF (pipe-delimited RxNorm/UMLS release) row was structurally unusable — too few columns to
33
+ * reach a configured field, or a missing code. The row is **skipped and surfaced** as a load
34
+ * warning (liberal on load), never kept as a partially-parsed concept.
35
+ */
36
+ TERM_RRF_MALFORMED_ROW: "TERM_RRF_MALFORMED_ROW",
37
+ /**
38
+ * A CSV (RFC-4180, e.g. LOINC `Loinc.csv`) row was structurally unusable — too few fields to reach
39
+ * a configured column. The row is **skipped and surfaced** as a load warning, never partial.
40
+ */
41
+ TERM_CSV_MALFORMED: "TERM_CSV_MALFORMED",
42
+ /**
43
+ * A fixed-width (e.g. ICD-10-CM order file) row was structurally unusable — too short to contain
44
+ * the configured code field, or a missing code. Skipped and surfaced, never partial.
45
+ */
46
+ TERM_FIXED_WIDTH_MALFORMED: "TERM_FIXED_WIDTH_MALFORMED",
47
+ /**
48
+ * A concept inside a FHIR `CodeSystem` resource was unusable — not an object, or missing its
49
+ * required `code`. Skipped and surfaced (the whole resource still loads); `line` is `0` since a
50
+ * JSON concept is not line-addressable.
51
+ */
52
+ TERM_FHIR_CONCEPT_MALFORMED: "TERM_FHIR_CONCEPT_MALFORMED",
53
+ /**
54
+ * A `$lookup`/`$validate-code` found no concept for the code in the loaded release. A **first-class
55
+ * typed outcome, never a guess** — the engine returns `unknown`/`valid: false`, never a fabricated
56
+ * display or a coerced `valid: true` (the never-fabricate invariant, applied to code identity).
57
+ */
58
+ TERM_CODE_UNKNOWN: "TERM_CODE_UNKNOWN",
59
+ /**
60
+ * A resolved concept is **deprecated / no longer current** (e.g. LOINC `STATUS = DEPRECATED`, or a
61
+ * FHIR concept flagged `inactive`). Surfaced on the concept's status so a caller never presents a
62
+ * non-current code as clean; the concept is still *found* (a lookup succeeds), it is just flagged.
63
+ */
64
+ TERM_CONCEPT_DEPRECATED: "TERM_CONCEPT_DEPRECATED",
65
+ /**
66
+ * A resolved concept is a **classification header, not a billable/valid leaf** (e.g. an ICD-10-CM
67
+ * order-file row with the position-15 flag `0`). Surfaced on the concept's status: a header code is
68
+ * found but is **not valid for claim submission**, and must never be presented as billable.
69
+ */
70
+ TERM_CONCEPT_HEADER_NOT_BILLABLE: "TERM_CONCEPT_HEADER_NOT_BILLABLE",
71
+ /**
72
+ * A ValueSet `compose` part could **not be expanded** — an intensional `include`/`exclude` whose
73
+ * code system was not supplied, an unresolvable referenced value set, or a `filter` operator the
74
+ * engine does not implement. Surfaced as a typed outcome that marks the expansion **incomplete**;
75
+ * the engine **never** fabricates a member and **never** returns a silently-empty "no members"
76
+ * answer for a part it could not compute (roadmap §4.4 — a false "not a member" is a clinical error).
77
+ */
78
+ TERM_VALUESET_CANNOT_EXPAND: "TERM_VALUESET_CANNOT_EXPAND",
79
+ /**
80
+ * A **pre-computed** `ValueSet.expansion` is **incomplete** — its `total` exceeds the number of
81
+ * `contains` entries, or it is flagged too-costly (the VSAC `$expand` >1200-code truncation hazard,
82
+ * roadmap §4.4). The engine **never treats a truncated expansion as complete membership**: a code
83
+ * absent from a truncated expansion is `undetermined`, never a confident "not a member".
84
+ */
85
+ TERM_VALUESET_EXPANSION_TRUNCATED: "TERM_VALUESET_EXPANSION_TRUNCATED",
86
+ /**
87
+ * A UCUM unit expression is **not valid** — it does not parse against the UCUM grammar, or it
88
+ * names an atom absent from the vendored UCUM table. A **first-class typed outcome, never an
89
+ * error and never a guess**: {@link validateUcum} returns `{ valid: false, reason }`, never a
90
+ * coerced or "nearest" unit (the never-fabricate invariant, applied to units — roadmap §4.3). The
91
+ * `reason` is value-free (a grammar fault or an unknown-atom shape), never PHI.
92
+ */
93
+ TERM_UCUM_INVALID: "TERM_UCUM_INVALID",
94
+ /**
95
+ * A crosswalk source code has an **authored No-Map** — the steward declares it has no valid target
96
+ * in the other classification (a GEM `NoDx`/`NoPCS` sentinel, or a SNOMED complex-map `447638001`
97
+ * "cannot be classified" category). A **first-class typed outcome, never an error and never a
98
+ * guess** (the never-fabricate invariant, applied to crosswalks — roadmap §4.1). Distinct from
99
+ * {@link TERM_CROSSWALK_UNMAPPED}: the source *is* in the map, and the map says "no target".
100
+ */
101
+ TERM_CROSSWALK_NO_MAP: "TERM_CROSSWALK_NO_MAP",
102
+ /**
103
+ * A crosswalk source code is **absent from the map entirely** — not an authored No-Map, simply not
104
+ * present. Surfaced as a typed outcome (never a fabricated target, never a silent success), and
105
+ * kept distinct from {@link TERM_CROSSWALK_NO_MAP} so a caller can tell "the steward said no target"
106
+ * from "this code was not in the file".
107
+ */
108
+ TERM_CROSSWALK_UNMAPPED: "TERM_CROSSWALK_UNMAPPED",
109
+ /**
110
+ * A SNOMED→ICD-10-CM complex-map group's decision needs **patient context** (an `IFA` age band or
111
+ * gender) the caller did not supply. The engine surfaces the candidate rules + advice and **refuses
112
+ * to pick a branch** it lacks the data for (roadmap §4.1) — never a silently-chosen target.
113
+ */
114
+ TERM_CROSSWALK_CONTEXT_REQUIRED: "TERM_CROSSWALK_CONTEXT_REQUIRED",
115
+ /**
116
+ * A GEM file line was structurally unusable — not three whitespace-delimited fields, or a flag
117
+ * field that is not a 5-digit code. The row is **skipped and surfaced** as a load warning (liberal
118
+ * on load), never kept as a partially-parsed entry.
119
+ */
120
+ TERM_GEM_MALFORMED_ROW: "TERM_GEM_MALFORMED_ROW",
121
+ /**
122
+ * A SNOMED complex-map RF2 refset row was structurally unusable — missing its
123
+ * `referencedComponentId`/`mapGroup`/`mapPriority`. Skipped and surfaced, never partial.
124
+ */
125
+ TERM_COMPLEX_MAP_MALFORMED_ROW: "TERM_COMPLEX_MAP_MALFORMED_ROW",
126
+ /**
127
+ * A RxNorm RRF row (`RXNCONSO` / `RXNREL` / `RXNSAT`) was structurally unusable — too few columns to
128
+ * reach a required field, or a missing `RXCUI`/NDC value. The row is **skipped and surfaced** as a
129
+ * load warning (liberal on load), never kept as a partial concept/edge. Rows that are simply *not of
130
+ * interest* (a non-`RXNORM` atom, an atom-level relationship, a non-`NDC` attribute) are skipped
131
+ * **silently** — they are expected, not faults.
132
+ */
133
+ TERM_RXNORM_MALFORMED_ROW: "TERM_RXNORM_MALFORMED_ROW",
134
+ /**
135
+ * A RxNorm graph navigation was asked about an `RXCUI` **absent from the loaded release** — a
136
+ * first-class typed outcome, never a fabricated concept and never an empty "success" (the
137
+ * never-fabricate invariant, applied to the drug graph — roadmap §4.2). Distinct from a *present*
138
+ * concept that simply has no edge of the requested relationship (that is a found result with empty
139
+ * targets).
140
+ */
141
+ TERM_RXNORM_UNKNOWN_RXCUI: "TERM_RXNORM_UNKNOWN_RXCUI",
142
+ /**
143
+ * An NDC could **not be resolved** to any `RXCUI` in the loaded RxNorm release — a typed, surfaced
144
+ * absence, never a guessed `RXCUI`. NDC↔RXCUI is many:1 and temporal (roadmap §4.2), so a resolution
145
+ * is always release-scoped; an NDC not present in the loaded release is this diagnostic.
146
+ */
147
+ TERM_RXNORM_NDC_UNMAPPED: "TERM_RXNORM_NDC_UNMAPPED"
148
+ };
149
+ var FATAL_CODES = {
150
+ /**
151
+ * A `ConceptMap` resource was structurally unusable — wrong `resourceType`, or a group/element
152
+ * missing a required field. Thrown rather than silently loading a partial, misleading map.
153
+ */
154
+ TERM_CONCEPTMAP_MALFORMED: "TERM_CONCEPTMAP_MALFORMED",
155
+ /**
156
+ * A CodeSystem *source* was structurally unusable — a FHIR resource with the wrong `resourceType`,
157
+ * or a delimited source whose configured code/display column is absent from the header. Thrown
158
+ * rather than silently loading an empty or mis-keyed release. (Malformed individual **rows** are
159
+ * skipped-and-surfaced load warnings, not fatals — only an unusable *source* is fatal.)
160
+ */
161
+ TERM_CODESYSTEM_MALFORMED: "TERM_CODESYSTEM_MALFORMED",
162
+ /**
163
+ * A `ValueSet` resource was structurally unusable — wrong `resourceType`, or a `compose`/`expansion`
164
+ * whose required shape (an `include` that is not an object, a `contains` entry missing its `code`)
165
+ * is corrupt. Thrown rather than silently loading a partial value set that would bind *some* codes
166
+ * and quietly drop others. (A `filter` operator the engine does not implement is **not** fatal — it
167
+ * is the surfaced `TERM_VALUESET_CANNOT_EXPAND` diagnostic at expansion time.)
168
+ */
169
+ TERM_VALUESET_MALFORMED: "TERM_VALUESET_MALFORMED",
170
+ /**
171
+ * A crosswalk map *source* was structurally unusable — e.g. a SNOMED complex-map RF2 refset with
172
+ * empty content or a header missing a required column. Thrown rather than silently loading an empty
173
+ * or mis-keyed map. (Malformed individual **rows** are skipped-and-surfaced warnings, not fatals.)
174
+ */
175
+ TERM_CROSSWALK_MALFORMED: "TERM_CROSSWALK_MALFORMED",
176
+ /**
177
+ * An **inversion** of a directional crosswalk was requested — a forbidden operation. The GEMs and
178
+ * the SNOMED→ICD-10-CM map are authoritative in **one direction only**; a forward map is not the
179
+ * inverse of the backward map (roadmap §4.1). Thrown by {@link ../crosswalk/gems.invertGem} so the
180
+ * never-invert refusal is a first-class, discoverable contract rather than a silent absence.
181
+ */
182
+ TERM_MAP_NOT_INVERTIBLE: "TERM_MAP_NOT_INVERTIBLE"
183
+ };
184
+ var TerminologyError = class _TerminologyError extends Error {
185
+ /** The stable fatal code. Branch on this, not on {@link message}. */
186
+ code;
187
+ /**
188
+ * @param code - The stable {@link FatalCode} describing the fault.
189
+ * @param message - A **value-free** structural description (path + fault; never an input value).
190
+ */
191
+ constructor(code, message) {
192
+ super(message);
193
+ this.name = "TerminologyError";
194
+ this.code = code;
195
+ Object.setPrototypeOf(this, _TerminologyError.prototype);
196
+ }
197
+ };
198
+
199
+ // src/common/fhir-json.ts
200
+ function isJsonObject(value) {
201
+ return typeof value === "object" && value !== null && !Array.isArray(value);
202
+ }
203
+ function getString(obj, key) {
204
+ if (!isJsonObject(obj)) return void 0;
205
+ const v = obj[key];
206
+ return typeof v === "string" ? v : void 0;
207
+ }
208
+ function getArray(obj, key) {
209
+ if (!isJsonObject(obj)) return void 0;
210
+ const v = obj[key];
211
+ return Array.isArray(v) ? v : void 0;
212
+ }
213
+ function getBoolean(obj, key) {
214
+ if (!isJsonObject(obj)) return void 0;
215
+ const v = obj[key];
216
+ return typeof v === "boolean" ? v : void 0;
217
+ }
218
+ function getNumber(obj, key) {
219
+ if (!isJsonObject(obj)) return void 0;
220
+ const v = obj[key];
221
+ return typeof v === "number" && Number.isFinite(v) ? v : void 0;
222
+ }
223
+
224
+ // src/systems/registry.ts
225
+ var SYSTEM_IDENTITIES = Object.freeze(
226
+ [
227
+ {
228
+ url: "http://loinc.org",
229
+ oid: "2.16.840.1.113883.6.1",
230
+ name: "LOINC",
231
+ mnemonics: ["LN", "LOINC"]
232
+ },
233
+ {
234
+ url: "http://snomed.info/sct",
235
+ oid: "2.16.840.1.113883.6.96",
236
+ name: "SNOMED CT",
237
+ mnemonics: ["SCT", "SNOMEDCT", "SNOMED"]
238
+ },
239
+ {
240
+ url: "http://hl7.org/fhir/sid/icd-10-cm",
241
+ oid: "2.16.840.1.113883.6.90",
242
+ name: "ICD-10-CM",
243
+ mnemonics: ["I10C", "ICD10CM"]
244
+ },
245
+ {
246
+ url: "http://www.nlm.nih.gov/research/umls/rxnorm",
247
+ oid: "2.16.840.1.113883.6.88",
248
+ name: "RxNorm",
249
+ mnemonics: ["RXNORM"]
250
+ },
251
+ {
252
+ url: "http://unitsofmeasure.org",
253
+ oid: "2.16.840.1.113883.6.8",
254
+ name: "UCUM",
255
+ mnemonics: ["UCUM"]
256
+ },
257
+ {
258
+ url: "http://www.ama-assn.org/go/cpt",
259
+ oid: "2.16.840.1.113883.6.12",
260
+ name: "CPT",
261
+ mnemonics: ["C4", "CPT"]
262
+ },
263
+ {
264
+ url: "http://hl7.org/fhir/sid/ndc",
265
+ oid: "2.16.840.1.113883.6.69",
266
+ name: "NDC",
267
+ mnemonics: ["NDC"]
268
+ },
269
+ {
270
+ url: "http://hl7.org/fhir/sid/cvx",
271
+ oid: "2.16.840.1.113883.12.292",
272
+ name: "CVX (CDC Vaccine Codes)",
273
+ mnemonics: ["CVX"]
274
+ }
275
+ ].map((e) => Object.freeze({ ...e, mnemonics: Object.freeze([...e.mnemonics]) }))
276
+ );
277
+ var HL7_V2_OID_ROOT = "2.16.840.1.113883.12";
278
+ var HL7_V2_URL_PREFIX = "http://terminology.hl7.org/CodeSystem/v2-";
279
+
280
+ // src/systems/resolve.ts
281
+ var byUrl = /* @__PURE__ */ new Map();
282
+ var byOid = /* @__PURE__ */ new Map();
283
+ var byMnemonic = /* @__PURE__ */ new Map();
284
+ for (const id of SYSTEM_IDENTITIES) {
285
+ byUrl.set(id.url.toLowerCase(), id);
286
+ if (id.oid !== void 0) byOid.set(id.oid, id);
287
+ for (const m of id.mnemonics) byMnemonic.set(m.toLowerCase(), id);
288
+ }
289
+ var OID_RE = /^[0-2](?:\.(?:0|[1-9]\d*))+$/;
290
+ function stripOidPrefix(input) {
291
+ const lower = input.toLowerCase();
292
+ return lower.startsWith("urn:oid:") ? input.slice("urn:oid:".length) : input;
293
+ }
294
+ function resolveV2Table(rawInput, bareOid) {
295
+ if (bareOid.startsWith(`${HL7_V2_OID_ROOT}.`)) {
296
+ const tail = bareOid.slice(HL7_V2_OID_ROOT.length + 1);
297
+ if (/^(?:0|[1-9]\d{0,3})$/.test(tail)) {
298
+ const padded = tail.padStart(4, "0");
299
+ return Object.freeze({
300
+ url: `${HL7_V2_URL_PREFIX}${padded}`,
301
+ oid: bareOid,
302
+ name: `HL7 v2 table ${padded}`,
303
+ mnemonics: Object.freeze([`v2-${padded}`])
304
+ });
305
+ }
306
+ }
307
+ const lower = rawInput.toLowerCase();
308
+ if (lower.startsWith(HL7_V2_URL_PREFIX.toLowerCase())) {
309
+ const tail = rawInput.slice(HL7_V2_URL_PREFIX.length);
310
+ if (/^\d{1,4}$/.test(tail)) {
311
+ const padded = tail.padStart(4, "0");
312
+ const table = String(Number(tail));
313
+ return Object.freeze({
314
+ url: `${HL7_V2_URL_PREFIX}${padded}`,
315
+ oid: `${HL7_V2_OID_ROOT}.${table}`,
316
+ name: `HL7 v2 table ${padded}`,
317
+ mnemonics: Object.freeze([`v2-${padded}`])
318
+ });
319
+ }
320
+ }
321
+ return void 0;
322
+ }
323
+ function resolveSystem(id) {
324
+ if (typeof id !== "string") return { unknown: true, input: "" };
325
+ const input = id.trim();
326
+ if (input === "") return { unknown: true, input: id };
327
+ const urlHit = byUrl.get(input.toLowerCase());
328
+ if (urlHit) return urlHit;
329
+ const mnemonicHit = byMnemonic.get(input.toLowerCase());
330
+ if (mnemonicHit) return mnemonicHit;
331
+ const bareOid = stripOidPrefix(input);
332
+ if (OID_RE.test(bareOid)) {
333
+ const oidHit = byOid.get(bareOid);
334
+ if (oidHit) return oidHit;
335
+ const v22 = resolveV2Table(input, bareOid);
336
+ if (v22) return v22;
337
+ return { unknown: true, input };
338
+ }
339
+ const v2 = resolveV2Table(input, bareOid);
340
+ if (v2) return v2;
341
+ return { unknown: true, input };
342
+ }
343
+ function isUnknownSystem(result) {
344
+ return "unknown" in result;
345
+ }
346
+
347
+ // src/conceptmap/load.ts
348
+ var R4_EQUIVALENCES = /* @__PURE__ */ new Set([
349
+ "relatedto",
350
+ "equivalent",
351
+ "equal",
352
+ "wider",
353
+ "subsumes",
354
+ "narrower",
355
+ "specializes",
356
+ "inexact",
357
+ "unmatched",
358
+ "disjoint"
359
+ ]);
360
+ var INPUT_UNMAPPED_MODES = /* @__PURE__ */ new Set([
361
+ "provided",
362
+ "fixed",
363
+ "other-map"
364
+ ]);
365
+ function malformed(path, fault) {
366
+ throw new TerminologyError(FATAL_CODES.TERM_CONCEPTMAP_MALFORMED, `ConceptMap ${path}: ${fault}`);
367
+ }
368
+ function assignString(out, src, key) {
369
+ const v = getString(src, key);
370
+ if (v !== void 0) out[key] = v;
371
+ }
372
+ function loadTarget(raw, path) {
373
+ if (!isJsonObject(raw)) malformed(path, "target is not an object");
374
+ const equivalence = getString(raw, "equivalence");
375
+ if (equivalence === void 0) {
376
+ malformed(path, "target is missing the required 'equivalence' field");
377
+ }
378
+ if (!R4_EQUIVALENCES.has(equivalence)) {
379
+ malformed(path, "target has an unrecognized 'equivalence' value");
380
+ }
381
+ const out = { equivalence };
382
+ assignString(out, raw, "code");
383
+ assignString(out, raw, "display");
384
+ assignString(out, raw, "comment");
385
+ return Object.freeze(out);
386
+ }
387
+ function loadElement(raw, path) {
388
+ if (!isJsonObject(raw)) malformed(path, "element is not an object");
389
+ const rawTargets = getArray(raw, "target") ?? [];
390
+ const target = Object.freeze(
391
+ rawTargets.map((t, i) => loadTarget(t, `${path}.target[${String(i)}]`))
392
+ );
393
+ const out = { target };
394
+ assignString(out, raw, "code");
395
+ assignString(out, raw, "display");
396
+ return Object.freeze(out);
397
+ }
398
+ function loadUnmapped(raw, path) {
399
+ if (!isJsonObject(raw)) malformed(path, "unmapped is not an object");
400
+ const mode = getString(raw, "mode");
401
+ if (mode === void 0 || !INPUT_UNMAPPED_MODES.has(mode)) {
402
+ malformed(path, "unmapped has a missing or unrecognized 'mode'");
403
+ }
404
+ const out = { mode };
405
+ assignString(out, raw, "code");
406
+ assignString(out, raw, "display");
407
+ assignString(out, raw, "url");
408
+ return Object.freeze(out);
409
+ }
410
+ function loadGroup(raw, path) {
411
+ if (!isJsonObject(raw)) malformed(path, "group is not an object");
412
+ const rawElements = getArray(raw, "element") ?? [];
413
+ const element = Object.freeze(
414
+ rawElements.map((e, i) => loadElement(e, `${path}.element[${String(i)}]`))
415
+ );
416
+ const out = { element };
417
+ assignString(out, raw, "source");
418
+ assignString(out, raw, "sourceVersion");
419
+ assignString(out, raw, "target");
420
+ assignString(out, raw, "targetVersion");
421
+ if (isJsonObject(raw) && raw["unmapped"] !== void 0) {
422
+ out.unmapped = loadUnmapped(raw["unmapped"], `${path}.unmapped`);
423
+ }
424
+ return Object.freeze(out);
425
+ }
426
+ function loadConceptMap(json) {
427
+ if (!isJsonObject(json)) malformed("", "resource is not a JSON object");
428
+ const resourceType = getString(json, "resourceType");
429
+ if (resourceType !== "ConceptMap") {
430
+ malformed("", "resource is not a ConceptMap (wrong or missing resourceType)");
431
+ }
432
+ const rawGroups = getArray(json, "group") ?? [];
433
+ const group = Object.freeze(rawGroups.map((g, i) => loadGroup(g, `group[${String(i)}]`)));
434
+ const out = { group };
435
+ assignString(out, json, "url");
436
+ assignString(out, json, "version");
437
+ const sourceScope = getString(json, "sourceUri") ?? getString(json, "sourceCanonical");
438
+ const targetScope = getString(json, "targetUri") ?? getString(json, "targetCanonical");
439
+ if (sourceScope !== void 0) out.sourceScope = sourceScope;
440
+ if (targetScope !== void 0) out.targetScope = targetScope;
441
+ return Object.freeze(out);
442
+ }
443
+
444
+ // src/conceptmap/translate.ts
445
+ function equivalenceToRelationship(equivalence) {
446
+ switch (equivalence) {
447
+ case "equivalent":
448
+ case "equal":
449
+ return "equivalent";
450
+ case "wider":
451
+ case "subsumes":
452
+ return "source-is-narrower-than-target";
453
+ case "narrower":
454
+ case "specializes":
455
+ return "source-is-broader-than-target";
456
+ case "relatedto":
457
+ case "inexact":
458
+ return "related-to";
459
+ case "disjoint":
460
+ case "unmatched":
461
+ return "not-related-to";
462
+ }
463
+ }
464
+ function groupApplies(group, system) {
465
+ if (system === void 0) return true;
466
+ return group.source === void 0 || group.source === system;
467
+ }
468
+ function provenanceOf(map, group, sourceSystem) {
469
+ const out = {};
470
+ if (map.url !== void 0) out.conceptMapUrl = map.url;
471
+ if (map.version !== void 0) out.conceptMapVersion = map.version;
472
+ const src = sourceSystem ?? group?.source;
473
+ if (src !== void 0) out.sourceSystem = src;
474
+ if (group?.target !== void 0) out.targetSystem = group.target;
475
+ return Object.freeze(out);
476
+ }
477
+ function unmappedResult(source, mode, provenance, fixedTarget, otherMapUrl) {
478
+ const out = {
479
+ unmapped: true,
480
+ code: "TERM_TRANSLATE_UNMAPPED",
481
+ mode,
482
+ source,
483
+ provenance
484
+ };
485
+ if (fixedTarget !== void 0) out.fixedTarget = fixedTarget;
486
+ if (otherMapUrl !== void 0) out.otherMapUrl = otherMapUrl;
487
+ return Object.freeze(out);
488
+ }
489
+ function translate(sourceCoding, map) {
490
+ const source = coding(sourceCoding);
491
+ const system = source.system;
492
+ const matches = [];
493
+ let firstMatchGroup;
494
+ let sourceCodePresent = false;
495
+ let fallbackGroup;
496
+ for (const group of map.group) {
497
+ if (!groupApplies(group, system)) continue;
498
+ if (fallbackGroup === void 0 && group.unmapped !== void 0) fallbackGroup = group;
499
+ for (const element of group.element) {
500
+ if (element.code !== source.code) continue;
501
+ sourceCodePresent = true;
502
+ for (const t of element.target) {
503
+ if (t.code === void 0 || t.equivalence === "unmatched") continue;
504
+ const targetCoding = coding({
505
+ ...group.target !== void 0 ? { system: group.target } : {},
506
+ code: t.code,
507
+ ...t.display !== void 0 ? { display: t.display } : {},
508
+ ...group.targetVersion !== void 0 ? { version: group.targetVersion } : {}
509
+ });
510
+ const match = {
511
+ target: targetCoding,
512
+ relationship: equivalenceToRelationship(t.equivalence),
513
+ equivalence: t.equivalence
514
+ };
515
+ if (t.comment !== void 0) match.comment = t.comment;
516
+ matches.push(Object.freeze(match));
517
+ if (firstMatchGroup === void 0) firstMatchGroup = group;
518
+ }
519
+ }
520
+ }
521
+ if (matches.length > 0) {
522
+ return Object.freeze({
523
+ unmapped: false,
524
+ matches: Object.freeze(matches),
525
+ provenance: provenanceOf(map, firstMatchGroup, system)
526
+ });
527
+ }
528
+ if (!sourceCodePresent && fallbackGroup?.unmapped !== void 0) {
529
+ const um = fallbackGroup.unmapped;
530
+ const provenance = provenanceOf(map, fallbackGroup, system);
531
+ if (um.mode === "fixed" && um.code !== void 0) {
532
+ const fixed = coding({
533
+ ...fallbackGroup.target !== void 0 ? { system: fallbackGroup.target } : {},
534
+ code: um.code,
535
+ ...um.display !== void 0 ? { display: um.display } : {}
536
+ });
537
+ return unmappedResult(source, "fixed", provenance, fixed, void 0);
538
+ }
539
+ if (um.mode === "other-map") {
540
+ return unmappedResult(source, "other-map", provenance, void 0, um.url);
541
+ }
542
+ if (um.mode === "provided") {
543
+ return unmappedResult(source, "provided", provenance, void 0, void 0);
544
+ }
545
+ }
546
+ return unmappedResult(
547
+ source,
548
+ "none",
549
+ provenanceOf(map, firstMatchGroup, system),
550
+ void 0,
551
+ void 0
552
+ );
553
+ }
554
+
555
+ // src/codesystem/status.ts
556
+ var defaultStatusMapper = (raw) => {
557
+ switch (raw.trim().toUpperCase()) {
558
+ case "":
559
+ case "N":
560
+ case "ACTIVE":
561
+ return "active";
562
+ case "DEPRECATED":
563
+ return "deprecated";
564
+ case "DISCOURAGED":
565
+ return "discouraged";
566
+ case "TRIAL":
567
+ return "trial";
568
+ case "O":
569
+ case "OBSOLETE":
570
+ return "obsolete";
571
+ case "Y":
572
+ case "E":
573
+ case "SUPPRESSED":
574
+ return "suppressed";
575
+ default:
576
+ return "unknown";
577
+ }
578
+ };
579
+ function makeStatus(activity, raw, billable) {
580
+ const out = { activity, active: activity === "active" };
581
+ if (raw !== void 0 && raw !== "") out.raw = raw;
582
+ if (billable !== void 0) out.billable = billable;
583
+ if (activity === "deprecated") out.code = DIAGNOSTIC_CODES.TERM_CONCEPT_DEPRECATED;
584
+ else if (activity === "header") out.code = DIAGNOSTIC_CODES.TERM_CONCEPT_HEADER_NOT_BILLABLE;
585
+ return Object.freeze(out);
586
+ }
587
+
588
+ // src/codesystem/csv.ts
589
+ function parseCsvRows(content) {
590
+ const rows = [];
591
+ let row = [];
592
+ let field = "";
593
+ let inQuotes = false;
594
+ let fieldStart = true;
595
+ let sawAny = false;
596
+ const n = content.length;
597
+ for (let i = 0; i < n; i++) {
598
+ const ch = content.charAt(i);
599
+ if (inQuotes) {
600
+ if (ch === '"') {
601
+ if (content.charAt(i + 1) === '"') {
602
+ field += '"';
603
+ i++;
604
+ } else {
605
+ inQuotes = false;
606
+ }
607
+ } else {
608
+ field += ch;
609
+ }
610
+ continue;
611
+ }
612
+ if (ch === '"' && fieldStart) {
613
+ inQuotes = true;
614
+ fieldStart = false;
615
+ sawAny = true;
616
+ } else if (ch === ",") {
617
+ row.push(field);
618
+ field = "";
619
+ fieldStart = true;
620
+ sawAny = true;
621
+ } else if (ch === "\n") {
622
+ row.push(field);
623
+ rows.push(row);
624
+ row = [];
625
+ field = "";
626
+ fieldStart = true;
627
+ sawAny = false;
628
+ } else if (ch === "\r") ; else {
629
+ field += ch;
630
+ fieldStart = false;
631
+ sawAny = true;
632
+ }
633
+ }
634
+ if (sawAny || field !== "" || row.length > 0) {
635
+ row.push(field);
636
+ rows.push(row);
637
+ }
638
+ return { rows, unterminatedQuote: inQuotes };
639
+ }
640
+ function parseCsv(content) {
641
+ return parseCsvRows(content).rows;
642
+ }
643
+ function requireHeader(header, name) {
644
+ const idx = header.indexOf(name);
645
+ if (idx < 0) {
646
+ throw new TerminologyError(
647
+ FATAL_CODES.TERM_CODESYSTEM_MALFORMED,
648
+ `CSV source: required column '${name}' is not present in the header row`
649
+ );
650
+ }
651
+ return idx;
652
+ }
653
+ function parseCsvSource(source) {
654
+ const statusMap = source.statusMap ?? defaultStatusMapper;
655
+ const { rows, unterminatedQuote } = parseCsvRows(source.content);
656
+ const header = rows[0];
657
+ if (header === void 0) {
658
+ throw new TerminologyError(
659
+ FATAL_CODES.TERM_CODESYSTEM_MALFORMED,
660
+ "CSV source: the file has no header row"
661
+ );
662
+ }
663
+ const warnings = [];
664
+ if (unterminatedQuote) {
665
+ warnings.push(
666
+ Object.freeze({
667
+ code: DIAGNOSTIC_CODES.TERM_CSV_MALFORMED,
668
+ line: rows.length,
669
+ detail: "an opened quoted field was not terminated before end-of-input"
670
+ })
671
+ );
672
+ }
673
+ const codeIdx = requireHeader(header, source.columns.code);
674
+ const displayIdx = requireHeader(header, source.columns.display);
675
+ const statusIdx = source.columns.status !== void 0 ? requireHeader(header, source.columns.status) : void 0;
676
+ const propIdx = (source.columns.properties ?? []).map((n) => ({
677
+ name: n,
678
+ index: requireHeader(header, n)
679
+ }));
680
+ const needCols = Math.max(codeIdx, displayIdx, statusIdx ?? 0, ...propIdx.map((p) => p.index)) + 1;
681
+ const concepts = /* @__PURE__ */ new Map();
682
+ for (let r = 1; r < rows.length; r++) {
683
+ const cells = rows[r] ?? [];
684
+ const lineNo = r + 1;
685
+ if (cells.length < needCols) {
686
+ warnings.push(
687
+ Object.freeze({
688
+ code: DIAGNOSTIC_CODES.TERM_CSV_MALFORMED,
689
+ line: lineNo,
690
+ detail: `row has ${String(cells.length)} fields, need ${String(needCols)}`
691
+ })
692
+ );
693
+ continue;
694
+ }
695
+ const code = (cells[codeIdx] ?? "").trim();
696
+ if (code === "") {
697
+ warnings.push(
698
+ Object.freeze({
699
+ code: DIAGNOSTIC_CODES.TERM_CSV_MALFORMED,
700
+ line: lineNo,
701
+ detail: "row is missing its code"
702
+ })
703
+ );
704
+ continue;
705
+ }
706
+ if (concepts.has(code)) continue;
707
+ const out = { code, properties: [] };
708
+ const display = (cells[displayIdx] ?? "").trim();
709
+ if (display !== "") out.display = display;
710
+ if (statusIdx !== void 0) {
711
+ const rawStatus = (cells[statusIdx] ?? "").trim();
712
+ out.status = makeStatus(statusMap(rawStatus), rawStatus);
713
+ }
714
+ const props = [];
715
+ for (const p of propIdx) {
716
+ const value = (cells[p.index] ?? "").trim();
717
+ if (value !== "") props.push(Object.freeze({ code: p.name, value }));
718
+ }
719
+ out.properties = Object.freeze(props);
720
+ concepts.set(code, Object.freeze(out));
721
+ }
722
+ return { concepts, warnings };
723
+ }
724
+
725
+ // src/codesystem/fhir.ts
726
+ function readPropertyValue(raw) {
727
+ const s = getString(raw, "valueString") ?? getString(raw, "valueCode") ?? getString(raw, "valueDateTime");
728
+ if (s !== void 0) return s;
729
+ const b = getBoolean(raw, "valueBoolean");
730
+ if (b !== void 0) return b;
731
+ const num = getNumber(raw, "valueInteger") ?? getNumber(raw, "valueDecimal");
732
+ if (num !== void 0) return num;
733
+ const coding2 = raw["valueCoding"];
734
+ const codingCode = getString(coding2, "code");
735
+ if (codingCode !== void 0) return codingCode;
736
+ return void 0;
737
+ }
738
+ function deriveStatus(props) {
739
+ const statusProp = props.find((p) => p.code === "status");
740
+ if (statusProp !== void 0 && typeof statusProp.value === "string") {
741
+ const raw = statusProp.value;
742
+ const activity = raw.trim().toLowerCase() === "active" ? "active" : "deprecated";
743
+ return makeStatus(activity, raw);
744
+ }
745
+ const inactive = props.find((p) => p.code === "inactive");
746
+ const deprecated = props.find((p) => p.code === "deprecated");
747
+ if (inactive?.value === true || deprecated !== void 0) {
748
+ return makeStatus("deprecated");
749
+ }
750
+ return void 0;
751
+ }
752
+ function collectConcepts(rawConcepts, into, warnings, parentCode) {
753
+ for (const raw of rawConcepts) {
754
+ if (!isJsonObject(raw)) {
755
+ warnings.push(
756
+ Object.freeze({
757
+ code: DIAGNOSTIC_CODES.TERM_FHIR_CONCEPT_MALFORMED,
758
+ line: 0,
759
+ detail: "concept is not an object"
760
+ })
761
+ );
762
+ continue;
763
+ }
764
+ const code = getString(raw, "code");
765
+ if (code !== void 0 && code !== "" && !into.has(code)) {
766
+ const props = [];
767
+ for (const p of getArray(raw, "property") ?? []) {
768
+ const pcode = getString(p, "code");
769
+ if (pcode === void 0) continue;
770
+ const value = isJsonObject(p) ? readPropertyValue(p) : void 0;
771
+ if (value !== void 0) props.push(Object.freeze({ code: pcode, value }));
772
+ }
773
+ if (parentCode !== void 0 && !props.some((p) => p.code === "parent" && p.value === parentCode)) {
774
+ props.push(Object.freeze({ code: "parent", value: parentCode }));
775
+ }
776
+ const out = { code, properties: Object.freeze(props) };
777
+ const display = getString(raw, "display");
778
+ if (display !== void 0) out.display = display;
779
+ const definition = getString(raw, "definition");
780
+ if (definition !== void 0) out.definition = definition;
781
+ const status = deriveStatus(props);
782
+ if (status !== void 0) out.status = status;
783
+ into.set(code, Object.freeze(out));
784
+ } else if (code === void 0 || code === "") {
785
+ warnings.push(
786
+ Object.freeze({
787
+ code: DIAGNOSTIC_CODES.TERM_FHIR_CONCEPT_MALFORMED,
788
+ line: 0,
789
+ detail: "concept is missing its required code"
790
+ })
791
+ );
792
+ }
793
+ const children = getArray(raw, "concept");
794
+ if (children !== void 0) {
795
+ collectConcepts(children, into, warnings, code !== "" ? code : void 0);
796
+ }
797
+ }
798
+ }
799
+ function parseFhirCodeSystem(source) {
800
+ const resource = source.resource;
801
+ if (!isJsonObject(resource) || getString(resource, "resourceType") !== "CodeSystem") {
802
+ throw new TerminologyError(
803
+ FATAL_CODES.TERM_CODESYSTEM_MALFORMED,
804
+ "FHIR source: resource is not a CodeSystem (wrong or missing resourceType)"
805
+ );
806
+ }
807
+ const concepts = /* @__PURE__ */ new Map();
808
+ const warnings = [];
809
+ collectConcepts(getArray(resource, "concept") ?? [], concepts, warnings);
810
+ const out = { concepts, warnings };
811
+ const url = getString(resource, "url");
812
+ if (url !== void 0) out.url = url;
813
+ const version = getString(resource, "version");
814
+ if (version !== void 0) out.version = version;
815
+ const name = getString(resource, "name");
816
+ if (name !== void 0) out.name = name;
817
+ return out;
818
+ }
819
+
820
+ // src/codesystem/fixed-width.ts
821
+ function sliceField(line, slice) {
822
+ const raw = slice.end === void 0 ? line.slice(slice.start) : line.slice(slice.start, slice.end);
823
+ return raw.trim();
824
+ }
825
+ var ICD10CM_ORDER_FILE_FIELDS = Object.freeze({
826
+ code: Object.freeze({ start: 6, end: 13 }),
827
+ display: Object.freeze({ start: 77 }),
828
+ billable: Object.freeze({ at: 14, billableValue: "1" }),
829
+ properties: Object.freeze([
830
+ Object.freeze({ name: "shortDescription", slice: Object.freeze({ start: 16, end: 76 }) })
831
+ ])
832
+ });
833
+ function parseFixedWidth(source) {
834
+ const statusMap = source.statusMap ?? defaultStatusMapper;
835
+ const fields = source.fields;
836
+ const concepts = /* @__PURE__ */ new Map();
837
+ const warnings = [];
838
+ const lines = source.content.split(/\r?\n/);
839
+ for (let i = 0; i < lines.length; i++) {
840
+ const line = lines[i] ?? "";
841
+ if (line.trim() === "") continue;
842
+ const lineNo = i + 1;
843
+ if (line.length <= fields.code.start) {
844
+ warnings.push(
845
+ Object.freeze({
846
+ code: DIAGNOSTIC_CODES.TERM_FIXED_WIDTH_MALFORMED,
847
+ line: lineNo,
848
+ detail: `line length ${String(line.length)} does not reach the code field`
849
+ })
850
+ );
851
+ continue;
852
+ }
853
+ const code = sliceField(line, fields.code);
854
+ if (code === "") {
855
+ warnings.push(
856
+ Object.freeze({
857
+ code: DIAGNOSTIC_CODES.TERM_FIXED_WIDTH_MALFORMED,
858
+ line: lineNo,
859
+ detail: "row is missing its code"
860
+ })
861
+ );
862
+ continue;
863
+ }
864
+ if (concepts.has(code)) continue;
865
+ const out = { code, properties: [] };
866
+ const display = sliceField(line, fields.display);
867
+ if (display !== "") out.display = display;
868
+ if (fields.billable !== void 0) {
869
+ const flag = line.charAt(fields.billable.at);
870
+ const billable = flag === fields.billable.billableValue;
871
+ const activity = billable ? "active" : "header";
872
+ out.status = makeStatus(activity, flag, billable);
873
+ } else if (fields.status !== void 0) {
874
+ const rawStatus = sliceField(line, fields.status);
875
+ out.status = makeStatus(statusMap(rawStatus), rawStatus);
876
+ }
877
+ const props = [];
878
+ for (const p of fields.properties ?? []) {
879
+ const value = sliceField(line, p.slice);
880
+ if (value !== "") props.push(Object.freeze({ code: p.name, value }));
881
+ }
882
+ out.properties = Object.freeze(props);
883
+ concepts.set(code, Object.freeze(out));
884
+ }
885
+ return { concepts, warnings };
886
+ }
887
+
888
+ // src/codesystem/rrf.ts
889
+ function parseRrfLine(line) {
890
+ const cells = line.split("|");
891
+ if (cells.length > 0 && cells[cells.length - 1] === "") cells.pop();
892
+ return cells;
893
+ }
894
+ function maxColumn(source) {
895
+ const { code, display, status, properties } = source.columns;
896
+ let max = Math.max(code, display, status ?? 0);
897
+ for (const p of properties ?? []) max = Math.max(max, p.column);
898
+ return max;
899
+ }
900
+ function cell(cells, index) {
901
+ const v = cells[index];
902
+ return v === void 0 ? void 0 : v.trim();
903
+ }
904
+ function parseRrf(source) {
905
+ const statusMap = source.statusMap ?? defaultStatusMapper;
906
+ const needCols = maxColumn(source) + 1;
907
+ const concepts = /* @__PURE__ */ new Map();
908
+ const warnings = [];
909
+ const lines = source.content.split(/\r?\n/);
910
+ for (let i = 0; i < lines.length; i++) {
911
+ const raw = lines[i] ?? "";
912
+ if (raw === "") continue;
913
+ const lineNo = i + 1;
914
+ const cells = parseRrfLine(raw);
915
+ if (cells.length < needCols) {
916
+ warnings.push(
917
+ Object.freeze({
918
+ code: DIAGNOSTIC_CODES.TERM_RRF_MALFORMED_ROW,
919
+ line: lineNo,
920
+ detail: `row has ${String(cells.length)} columns, need ${String(needCols)}`
921
+ })
922
+ );
923
+ continue;
924
+ }
925
+ const code = cell(cells, source.columns.code);
926
+ if (code === void 0 || code === "") {
927
+ warnings.push(
928
+ Object.freeze({
929
+ code: DIAGNOSTIC_CODES.TERM_RRF_MALFORMED_ROW,
930
+ line: lineNo,
931
+ detail: "row is missing its code"
932
+ })
933
+ );
934
+ continue;
935
+ }
936
+ if (concepts.has(code)) continue;
937
+ const out = { code, properties: [] };
938
+ const display = cell(cells, source.columns.display);
939
+ if (display !== void 0 && display !== "") out.display = display;
940
+ if (source.columns.status !== void 0) {
941
+ const rawStatus = cell(cells, source.columns.status) ?? "";
942
+ out.status = makeStatus(statusMap(rawStatus), rawStatus);
943
+ }
944
+ const props = [];
945
+ for (const p of source.columns.properties ?? []) {
946
+ const value = cell(cells, p.column);
947
+ if (value !== void 0 && value !== "") {
948
+ props.push(Object.freeze({ code: p.name, value }));
949
+ }
950
+ }
951
+ out.properties = Object.freeze(props);
952
+ concepts.set(code, Object.freeze(out));
953
+ }
954
+ return { concepts, warnings };
955
+ }
956
+
957
+ // src/codesystem/load.ts
958
+ function sealConceptMap(map) {
959
+ const guard = () => {
960
+ throw new TypeError("Cannot mutate a loaded CodeSystem's concepts map (it is immutable)");
961
+ };
962
+ for (const method of ["set", "delete", "clear"]) {
963
+ Object.defineProperty(map, method, { value: guard, writable: false, configurable: false });
964
+ }
965
+ return map;
966
+ }
967
+ function loadCodeSystem(source) {
968
+ let concepts;
969
+ let warnings;
970
+ const out = { count: 0, concepts: /* @__PURE__ */ new Map(), warnings: [] };
971
+ switch (source.format) {
972
+ case "rrf": {
973
+ ({ concepts, warnings } = parseRrf(source));
974
+ if (source.url !== void 0) out.url = source.url;
975
+ if (source.version !== void 0) out.version = source.version;
976
+ if (source.name !== void 0) out.name = source.name;
977
+ break;
978
+ }
979
+ case "csv": {
980
+ ({ concepts, warnings } = parseCsvSource(source));
981
+ if (source.url !== void 0) out.url = source.url;
982
+ if (source.version !== void 0) out.version = source.version;
983
+ if (source.name !== void 0) out.name = source.name;
984
+ break;
985
+ }
986
+ case "fixed-width": {
987
+ ({ concepts, warnings } = parseFixedWidth(source));
988
+ if (source.url !== void 0) out.url = source.url;
989
+ if (source.version !== void 0) out.version = source.version;
990
+ if (source.name !== void 0) out.name = source.name;
991
+ break;
992
+ }
993
+ case "fhir": {
994
+ const parsed = parseFhirCodeSystem(source);
995
+ concepts = parsed.concepts;
996
+ warnings = parsed.warnings;
997
+ if (parsed.url !== void 0) out.url = parsed.url;
998
+ if (parsed.version !== void 0) out.version = parsed.version;
999
+ if (parsed.name !== void 0) out.name = parsed.name;
1000
+ break;
1001
+ }
1002
+ }
1003
+ out.count = concepts.size;
1004
+ out.concepts = sealConceptMap(concepts);
1005
+ out.warnings = Object.freeze(warnings);
1006
+ return Object.freeze(out);
1007
+ }
1008
+
1009
+ // src/codesystem/lookup.ts
1010
+ function lookup(cs, code) {
1011
+ const concept = cs.concepts.get(code);
1012
+ if (concept === void 0) {
1013
+ const unknown = { found: false, code: "TERM_CODE_UNKNOWN", input: code };
1014
+ return Object.freeze(unknown);
1015
+ }
1016
+ const out = {
1017
+ found: true,
1018
+ code: concept.code,
1019
+ properties: concept.properties
1020
+ };
1021
+ if (concept.display !== void 0) out.display = concept.display;
1022
+ if (concept.definition !== void 0) out.definition = concept.definition;
1023
+ if (concept.status !== void 0) out.status = concept.status;
1024
+ if (cs.url !== void 0) out.system = cs.url;
1025
+ if (cs.version !== void 0) out.version = cs.version;
1026
+ return Object.freeze(out);
1027
+ }
1028
+ function validateCode(cs, code) {
1029
+ const concept = cs.concepts.get(code);
1030
+ if (concept === void 0) {
1031
+ return Object.freeze({ valid: false, code: "TERM_CODE_UNKNOWN" });
1032
+ }
1033
+ const out = { valid: true };
1034
+ if (concept.status !== void 0) out.status = concept.status;
1035
+ return Object.freeze(out);
1036
+ }
1037
+
1038
+ // src/valueset/load.ts
1039
+ var TOO_COSTLY_EXTENSION = "http://hl7.org/fhir/StructureDefinition/valueset-toocostly";
1040
+ function malformed2(path, fault) {
1041
+ throw new TerminologyError(FATAL_CODES.TERM_VALUESET_MALFORMED, `ValueSet ${path}: ${fault}`);
1042
+ }
1043
+ function assignString2(out, src, key) {
1044
+ const v = getString(src, key);
1045
+ if (v !== void 0) out[key] = v;
1046
+ }
1047
+ function loadFilter(raw, path) {
1048
+ if (!isJsonObject(raw)) malformed2(path, "filter is not an object");
1049
+ const property = getString(raw, "property");
1050
+ const op = getString(raw, "op");
1051
+ const value = getString(raw, "value");
1052
+ if (property === void 0 || op === void 0 || value === void 0) {
1053
+ malformed2(path, "filter is missing a required 'property', 'op', or 'value'");
1054
+ }
1055
+ return Object.freeze({ property, op, value });
1056
+ }
1057
+ function loadConcept(raw, path) {
1058
+ if (!isJsonObject(raw)) malformed2(path, "concept is not an object");
1059
+ const code = getString(raw, "code");
1060
+ if (code === void 0) malformed2(path, "concept is missing its required 'code'");
1061
+ const out = { code };
1062
+ assignString2(out, raw, "display");
1063
+ return Object.freeze(out);
1064
+ }
1065
+ function loadComponent(raw, path) {
1066
+ if (!isJsonObject(raw)) malformed2(path, "component is not an object");
1067
+ const out = {};
1068
+ assignString2(out, raw, "system");
1069
+ assignString2(out, raw, "version");
1070
+ const rawConcepts = getArray(raw, "concept");
1071
+ if (rawConcepts !== void 0) {
1072
+ out.concept = Object.freeze(
1073
+ rawConcepts.map((c, i) => loadConcept(c, `${path}.concept[${String(i)}]`))
1074
+ );
1075
+ }
1076
+ const rawFilters = getArray(raw, "filter");
1077
+ if (rawFilters !== void 0) {
1078
+ out.filter = Object.freeze(
1079
+ rawFilters.map((f, i) => loadFilter(f, `${path}.filter[${String(i)}]`))
1080
+ );
1081
+ }
1082
+ const rawValueSets = getArray(raw, "valueSet");
1083
+ if (rawValueSets !== void 0) {
1084
+ const urls = [];
1085
+ for (const [i, vsRef] of rawValueSets.entries()) {
1086
+ if (typeof vsRef !== "string") {
1087
+ malformed2(
1088
+ `${path}.valueSet[${String(i)}]`,
1089
+ "value set reference is not a canonical URL string"
1090
+ );
1091
+ }
1092
+ urls.push(vsRef);
1093
+ }
1094
+ out.valueSet = Object.freeze(urls);
1095
+ }
1096
+ const hasSystem = out.system !== void 0;
1097
+ const hasValueSet = out.valueSet !== void 0;
1098
+ if ((out.concept !== void 0 || out.filter !== void 0) && !hasSystem) {
1099
+ malformed2(path, "a component with 'concept' or 'filter' must name a 'system'");
1100
+ }
1101
+ if (!hasSystem && !hasValueSet) {
1102
+ malformed2(path, "a component must have a 'system' or a 'valueSet'");
1103
+ }
1104
+ return Object.freeze(out);
1105
+ }
1106
+ function loadCompose(raw, path) {
1107
+ if (!isJsonObject(raw)) malformed2(path, "compose is not an object");
1108
+ const include = Object.freeze(
1109
+ (getArray(raw, "include") ?? []).map(
1110
+ (c, i) => loadComponent(c, `${path}.include[${String(i)}]`)
1111
+ )
1112
+ );
1113
+ const exclude = Object.freeze(
1114
+ (getArray(raw, "exclude") ?? []).map(
1115
+ (c, i) => loadComponent(c, `${path}.exclude[${String(i)}]`)
1116
+ )
1117
+ );
1118
+ return Object.freeze({ include, exclude });
1119
+ }
1120
+ function loadContains(raw, path) {
1121
+ if (!isJsonObject(raw)) malformed2(path, "contains entry is not an object");
1122
+ const code = getString(raw, "code");
1123
+ if (code === void 0) malformed2(path, "contains entry is missing its required 'code'");
1124
+ const out = { code };
1125
+ assignString2(out, raw, "system");
1126
+ assignString2(out, raw, "display");
1127
+ assignString2(out, raw, "version");
1128
+ return Object.freeze(out);
1129
+ }
1130
+ function isTooCostly(raw) {
1131
+ for (const ext of getArray(raw, "extension") ?? []) {
1132
+ if (getString(ext, "url") === TOO_COSTLY_EXTENSION && getBoolean(ext, "valueBoolean") === true) {
1133
+ return true;
1134
+ }
1135
+ }
1136
+ return false;
1137
+ }
1138
+ function loadExpansion(raw, path) {
1139
+ if (!isJsonObject(raw)) malformed2(path, "expansion is not an object");
1140
+ const contains = Object.freeze(
1141
+ (getArray(raw, "contains") ?? []).map(
1142
+ (c, i) => loadContains(c, `${path}.contains[${String(i)}]`)
1143
+ )
1144
+ );
1145
+ const total = getNumber(raw, "total");
1146
+ const truncated2 = total !== void 0 && total > contains.length || isTooCostly(raw);
1147
+ const out = { contains, truncated: truncated2 };
1148
+ if (total !== void 0) out.total = total;
1149
+ return Object.freeze(out);
1150
+ }
1151
+ function loadValueSet(json) {
1152
+ if (!isJsonObject(json)) malformed2("", "resource is not a JSON object");
1153
+ if (getString(json, "resourceType") !== "ValueSet") {
1154
+ malformed2("", "resource is not a ValueSet (wrong or missing resourceType)");
1155
+ }
1156
+ const out = {};
1157
+ assignString2(out, json, "url");
1158
+ assignString2(out, json, "version");
1159
+ assignString2(out, json, "name");
1160
+ if (json["compose"] !== void 0) out.compose = loadCompose(json["compose"], "compose");
1161
+ if (json["expansion"] !== void 0)
1162
+ out.expansion = loadExpansion(json["expansion"], "expansion");
1163
+ return Object.freeze(out);
1164
+ }
1165
+
1166
+ // src/valueset/filters.ts
1167
+ var SUPPORTED_OPS = /* @__PURE__ */ new Set([
1168
+ "=",
1169
+ "is-a",
1170
+ "descendent-of",
1171
+ "is-not-a",
1172
+ "in",
1173
+ "not-in",
1174
+ "exists"
1175
+ ]);
1176
+ function unsupportedOps(filters) {
1177
+ return filters.filter((f) => !SUPPORTED_OPS.has(f.op));
1178
+ }
1179
+ function directParents(concept) {
1180
+ const parents = [];
1181
+ for (const p of concept.properties) {
1182
+ if (p.code === "parent" && typeof p.value === "string") parents.push(p.value);
1183
+ }
1184
+ return parents;
1185
+ }
1186
+ function buildSubsumption(cs) {
1187
+ const parentsOf = /* @__PURE__ */ new Map();
1188
+ for (const concept of cs.concepts.values()) {
1189
+ const parents = directParents(concept);
1190
+ if (parents.length > 0) parentsOf.set(concept.code, parents);
1191
+ }
1192
+ const cache = /* @__PURE__ */ new Map();
1193
+ const ancestorsOf = (code) => {
1194
+ const cached2 = cache.get(code);
1195
+ if (cached2 !== void 0) return cached2;
1196
+ const acc = /* @__PURE__ */ new Set();
1197
+ const stack = [...parentsOf.get(code) ?? []];
1198
+ while (stack.length > 0) {
1199
+ const next = stack.pop();
1200
+ if (next === void 0 || acc.has(next) || next === code) continue;
1201
+ acc.add(next);
1202
+ for (const p of parentsOf.get(next) ?? []) stack.push(p);
1203
+ }
1204
+ cache.set(code, acc);
1205
+ return acc;
1206
+ };
1207
+ return { ancestorsOf };
1208
+ }
1209
+ function isA(sub, code, anchor) {
1210
+ return code === anchor || sub.ancestorsOf(code).has(anchor);
1211
+ }
1212
+ function valueSet(value) {
1213
+ return new Set(
1214
+ value.split(",").map((v) => v.trim()).filter((v) => v.length > 0)
1215
+ );
1216
+ }
1217
+ function propertyValue(concept, property) {
1218
+ for (const p of concept.properties) {
1219
+ if (p.code === property) return typeof p.value === "string" ? p.value : String(p.value);
1220
+ }
1221
+ return void 0;
1222
+ }
1223
+ var UNSUPPORTED = Object.freeze({ matched: false, supported: false });
1224
+ function matchesFilter(concept, filter, sub) {
1225
+ const onCode = filter.property === "concept";
1226
+ switch (filter.op) {
1227
+ case "is-a":
1228
+ return { matched: isA(sub, concept.code, filter.value), supported: true };
1229
+ case "descendent-of":
1230
+ return {
1231
+ matched: concept.code !== filter.value && sub.ancestorsOf(concept.code).has(filter.value),
1232
+ supported: true
1233
+ };
1234
+ case "is-not-a":
1235
+ return { matched: !isA(sub, concept.code, filter.value), supported: true };
1236
+ case "=": {
1237
+ const actual = onCode ? concept.code : propertyValue(concept, filter.property);
1238
+ return { matched: actual === filter.value, supported: true };
1239
+ }
1240
+ case "in": {
1241
+ const set = valueSet(filter.value);
1242
+ const actual = onCode ? concept.code : propertyValue(concept, filter.property);
1243
+ return { matched: actual !== void 0 && set.has(actual), supported: true };
1244
+ }
1245
+ case "not-in": {
1246
+ const set = valueSet(filter.value);
1247
+ const actual = onCode ? concept.code : propertyValue(concept, filter.property);
1248
+ return { matched: actual === void 0 || !set.has(actual), supported: true };
1249
+ }
1250
+ case "exists": {
1251
+ const present = onCode ? true : propertyValue(concept, filter.property) !== void 0;
1252
+ const wantPresent = filter.value.trim().toLowerCase() === "true";
1253
+ return { matched: present === wantPresent, supported: true };
1254
+ }
1255
+ case "regex":
1256
+ case "generalizes":
1257
+ default:
1258
+ return UNSUPPORTED;
1259
+ }
1260
+ }
1261
+ function matchesAllFilters(concept, filters, sub) {
1262
+ let matched = true;
1263
+ for (const f of filters) {
1264
+ const r = matchesFilter(concept, f, sub);
1265
+ if (!r.supported) return UNSUPPORTED;
1266
+ if (!r.matched) matched = false;
1267
+ }
1268
+ return { matched, supported: true };
1269
+ }
1270
+
1271
+ // src/valueset/expand.ts
1272
+ function codingKey(system, code) {
1273
+ return `${system ?? ""}${code}`;
1274
+ }
1275
+ function makeCoding(system, code, display, version) {
1276
+ const init = { code };
1277
+ if (system !== void 0) init.system = system;
1278
+ if (version !== void 0) init.version = version;
1279
+ if (display !== void 0) init.display = display;
1280
+ return coding(init);
1281
+ }
1282
+ function cannotExpand(detail, system) {
1283
+ const d = { code: "TERM_VALUESET_CANNOT_EXPAND", detail };
1284
+ if (system !== void 0) d.system = system;
1285
+ return Object.freeze(d);
1286
+ }
1287
+ function truncated(detail, system) {
1288
+ const d = { code: "TERM_VALUESET_EXPANSION_TRUNCATED", detail };
1289
+ if (system !== void 0) d.system = system;
1290
+ return Object.freeze(d);
1291
+ }
1292
+ function intersectInto(into, other) {
1293
+ for (const k of into.keys()) if (!other.has(k)) into.delete(k);
1294
+ return into;
1295
+ }
1296
+ function expandReferencedValueSets(urls, ctx, visited) {
1297
+ const diagnostics = [];
1298
+ let complete = true;
1299
+ let acc = null;
1300
+ for (const url of urls) {
1301
+ if (visited.has(url)) {
1302
+ diagnostics.push(cannotExpand("cyclic value set reference", url));
1303
+ complete = false;
1304
+ acc = /* @__PURE__ */ new Map();
1305
+ continue;
1306
+ }
1307
+ const vs = ctx.valueSets?.get(url);
1308
+ if (vs === void 0) {
1309
+ diagnostics.push(cannotExpand("referenced value set not supplied", url));
1310
+ complete = false;
1311
+ acc = /* @__PURE__ */ new Map();
1312
+ continue;
1313
+ }
1314
+ const exp = expandInternal(vs, ctx, /* @__PURE__ */ new Set([...visited, url]));
1315
+ if (!exp.complete) complete = false;
1316
+ for (const d of exp.diagnostics) diagnostics.push(d);
1317
+ const members = /* @__PURE__ */ new Map();
1318
+ for (const c of exp.contains) members.set(codingKey(c.system, c.code), c);
1319
+ acc = acc === null ? members : intersectInto(acc, members);
1320
+ }
1321
+ return { members: acc ?? /* @__PURE__ */ new Map(), complete, diagnostics };
1322
+ }
1323
+ function expandComponent(component, ctx, visited) {
1324
+ const diagnostics = [];
1325
+ let complete = true;
1326
+ const { system, version, concept, filter, valueSet: valueSet2 } = component;
1327
+ const hasConcept = concept !== void 0;
1328
+ const hasFilter = filter !== void 0 && filter.length > 0;
1329
+ const hasVs = valueSet2 !== void 0 && valueSet2.length > 0;
1330
+ let base = null;
1331
+ if (hasConcept) {
1332
+ base = /* @__PURE__ */ new Map();
1333
+ for (const c of concept) {
1334
+ base.set(codingKey(system, c.code), makeCoding(system, c.code, c.display, version));
1335
+ }
1336
+ } else if (hasFilter || system !== void 0 && !hasVs) {
1337
+ if (system === void 0) {
1338
+ diagnostics.push(cannotExpand("intensional filter without a code system 'system'"));
1339
+ return { members: /* @__PURE__ */ new Map(), complete: false, diagnostics };
1340
+ }
1341
+ const cs = ctx.codeSystems?.get(system);
1342
+ if (cs === void 0) {
1343
+ diagnostics.push(cannotExpand("code system not supplied for intensional include", system));
1344
+ return { members: /* @__PURE__ */ new Map(), complete: false, diagnostics };
1345
+ }
1346
+ if (hasFilter) {
1347
+ const unsupported = unsupportedOps(filter);
1348
+ if (unsupported.length > 0) {
1349
+ diagnostics.push(cannotExpand("unsupported filter operator", system));
1350
+ return { members: /* @__PURE__ */ new Map(), complete: false, diagnostics };
1351
+ }
1352
+ const sub = buildSubsumption(cs);
1353
+ base = /* @__PURE__ */ new Map();
1354
+ for (const concpt of cs.concepts.values()) {
1355
+ if (matchesAllFilters(concpt, filter, sub).matched) {
1356
+ base.set(
1357
+ codingKey(system, concpt.code),
1358
+ makeCoding(system, concpt.code, concpt.display, version)
1359
+ );
1360
+ }
1361
+ }
1362
+ } else {
1363
+ base = /* @__PURE__ */ new Map();
1364
+ for (const concpt of cs.concepts.values()) {
1365
+ base.set(
1366
+ codingKey(system, concpt.code),
1367
+ makeCoding(system, concpt.code, concpt.display, version)
1368
+ );
1369
+ }
1370
+ }
1371
+ }
1372
+ if (hasVs) {
1373
+ const refs = expandReferencedValueSets(valueSet2, ctx, visited);
1374
+ for (const d of refs.diagnostics) diagnostics.push(d);
1375
+ if (!refs.complete) complete = false;
1376
+ base = base === null ? refs.members : intersectInto(base, refs.members);
1377
+ if (system !== void 0) {
1378
+ for (const [k, c] of [...base]) if (c.system !== system) base.delete(k);
1379
+ }
1380
+ }
1381
+ return { members: base ?? /* @__PURE__ */ new Map(), complete, diagnostics };
1382
+ }
1383
+ function expandInternal(vs, ctx, visited) {
1384
+ if (vs.expansion !== void 0) {
1385
+ const seen = /* @__PURE__ */ new Set();
1386
+ const contains = [];
1387
+ for (const c of vs.expansion.contains) {
1388
+ const key = codingKey(c.system, c.code);
1389
+ if (seen.has(key)) continue;
1390
+ seen.add(key);
1391
+ contains.push(makeCoding(c.system, c.code, c.display, c.version));
1392
+ }
1393
+ const diagnostics = [];
1394
+ let complete = true;
1395
+ if (vs.expansion.truncated) {
1396
+ complete = false;
1397
+ diagnostics.push(
1398
+ truncated("pre-computed expansion is incomplete (truncated or too-costly)", vs.url)
1399
+ );
1400
+ }
1401
+ const out = {
1402
+ complete,
1403
+ contains: Object.freeze(contains),
1404
+ diagnostics: Object.freeze(diagnostics)
1405
+ };
1406
+ if (vs.expansion.total !== void 0) out.total = vs.expansion.total;
1407
+ return Object.freeze(out);
1408
+ }
1409
+ if (vs.compose !== void 0) {
1410
+ const included = /* @__PURE__ */ new Map();
1411
+ const diagnostics = [];
1412
+ let complete = true;
1413
+ for (const inc of vs.compose.include) {
1414
+ const r = expandComponent(inc, ctx, visited);
1415
+ if (!r.complete) complete = false;
1416
+ for (const d of r.diagnostics) diagnostics.push(d);
1417
+ for (const [k, c] of r.members) if (!included.has(k)) included.set(k, c);
1418
+ }
1419
+ for (const exc of vs.compose.exclude) {
1420
+ const r = expandComponent(exc, ctx, visited);
1421
+ for (const d of r.diagnostics) diagnostics.push(d);
1422
+ for (const k of r.members.keys()) included.delete(k);
1423
+ if (!r.complete) {
1424
+ complete = false;
1425
+ for (const [k, c] of [...included]) {
1426
+ if (exc.system === void 0 || c.system === exc.system) included.delete(k);
1427
+ }
1428
+ }
1429
+ }
1430
+ return Object.freeze({
1431
+ complete,
1432
+ contains: Object.freeze([...included.values()]),
1433
+ diagnostics: Object.freeze(diagnostics)
1434
+ });
1435
+ }
1436
+ return Object.freeze({
1437
+ complete: true,
1438
+ contains: Object.freeze([]),
1439
+ diagnostics: Object.freeze([])
1440
+ });
1441
+ }
1442
+ function expand(vs, ctx = {}) {
1443
+ return expandInternal(vs, ctx, new Set(vs.url !== void 0 ? [vs.url] : []));
1444
+ }
1445
+
1446
+ // src/valueset/validate.ts
1447
+ function cannotExpand2(detail, system) {
1448
+ const d = { code: "TERM_VALUESET_CANNOT_EXPAND", detail };
1449
+ if (system !== void 0) d.system = system;
1450
+ return Object.freeze(d);
1451
+ }
1452
+ function matchComponent(target, component, ctx, visited) {
1453
+ const diagnostics = [];
1454
+ const { system, concept, filter, valueSet: valueSet2 } = component;
1455
+ const hasConcept = concept !== void 0;
1456
+ const hasFilter = filter !== void 0 && filter.length > 0;
1457
+ const hasVs = valueSet2 !== void 0 && valueSet2.length > 0;
1458
+ let baseMatched = null;
1459
+ let baseComplete = true;
1460
+ if (system !== void 0 && target.system !== void 0 && system !== target.system) {
1461
+ baseMatched = false;
1462
+ } else if (hasConcept) {
1463
+ baseMatched = concept.some((c) => c.code === target.code);
1464
+ } else if (hasFilter || system !== void 0 && !hasVs) {
1465
+ if (system === void 0) {
1466
+ diagnostics.push(cannotExpand2("intensional filter without a code system 'system'"));
1467
+ baseMatched = false;
1468
+ baseComplete = false;
1469
+ } else {
1470
+ const cs = ctx.codeSystems?.get(system);
1471
+ if (cs === void 0) {
1472
+ diagnostics.push(cannotExpand2("code system not supplied for intensional include", system));
1473
+ baseMatched = false;
1474
+ baseComplete = false;
1475
+ } else if (hasFilter) {
1476
+ if (unsupportedOps(filter).length > 0) {
1477
+ diagnostics.push(cannotExpand2("unsupported filter operator", system));
1478
+ baseMatched = false;
1479
+ baseComplete = false;
1480
+ } else {
1481
+ const concpt = cs.concepts.get(target.code);
1482
+ baseMatched = concpt !== void 0 && matchesAllFilters(concpt, filter, buildSubsumption(cs)).matched;
1483
+ }
1484
+ } else {
1485
+ baseMatched = cs.concepts.get(target.code) !== void 0;
1486
+ }
1487
+ }
1488
+ }
1489
+ let refDefiniteFalse = false;
1490
+ let refUndetermined = false;
1491
+ if (hasVs) {
1492
+ for (const url of valueSet2) {
1493
+ if (visited.has(url)) {
1494
+ diagnostics.push(cannotExpand2("cyclic value set reference", url));
1495
+ refUndetermined = true;
1496
+ continue;
1497
+ }
1498
+ const vs = ctx.valueSets?.get(url);
1499
+ if (vs === void 0) {
1500
+ diagnostics.push(cannotExpand2("referenced value set not supplied", url));
1501
+ refUndetermined = true;
1502
+ continue;
1503
+ }
1504
+ const m = validateInternal(target, vs, ctx, /* @__PURE__ */ new Set([...visited, url]));
1505
+ if (m.undetermined) {
1506
+ for (const d of m.diagnostics) diagnostics.push(d);
1507
+ refUndetermined = true;
1508
+ } else if (!m.result) {
1509
+ refDefiniteFalse = true;
1510
+ }
1511
+ }
1512
+ }
1513
+ const baseDefiniteFalse = baseMatched === false && baseComplete;
1514
+ const baseDefiniteTrue = baseMatched === null || baseMatched === true && baseComplete;
1515
+ const refDefiniteTrue = !hasVs || !refDefiniteFalse && !refUndetermined;
1516
+ if (baseDefiniteFalse || refDefiniteFalse) {
1517
+ return { matched: false, complete: true, diagnostics };
1518
+ }
1519
+ if (baseDefiniteTrue && refDefiniteTrue) {
1520
+ return { matched: true, complete: true, diagnostics };
1521
+ }
1522
+ return { matched: false, complete: false, diagnostics };
1523
+ }
1524
+ function decided(result, coding2) {
1525
+ return Object.freeze({ undetermined: false, result, coding: coding2 });
1526
+ }
1527
+ function undetermined(coding2, diagnostics) {
1528
+ return Object.freeze({
1529
+ undetermined: true,
1530
+ code: "TERM_VALUESET_CANNOT_EXPAND",
1531
+ coding: coding2,
1532
+ diagnostics: Object.freeze([...diagnostics])
1533
+ });
1534
+ }
1535
+ function validateInternal(target, vs, ctx, visited) {
1536
+ if (vs.expansion !== void 0) {
1537
+ const found = vs.expansion.contains.some(
1538
+ (c) => c.code === target.code && (c.system === void 0 || target.system === void 0 || c.system === target.system)
1539
+ );
1540
+ if (found) return decided(true, target);
1541
+ if (vs.expansion.truncated) {
1542
+ return undetermined(target, [
1543
+ cannotExpand2("pre-computed expansion is incomplete (truncated or too-costly)", vs.url)
1544
+ ]);
1545
+ }
1546
+ return decided(false, target);
1547
+ }
1548
+ if (vs.compose !== void 0) {
1549
+ const diagnostics = [];
1550
+ let includedDefinite = false;
1551
+ let anyIncludeUndetermined = false;
1552
+ for (const inc of vs.compose.include) {
1553
+ const m = matchComponent(target, inc, ctx, visited);
1554
+ for (const d of m.diagnostics) diagnostics.push(d);
1555
+ if (m.complete && m.matched) includedDefinite = true;
1556
+ if (!m.complete) anyIncludeUndetermined = true;
1557
+ }
1558
+ let excludedDefinite = false;
1559
+ let anyExcludeUndetermined = false;
1560
+ for (const exc of vs.compose.exclude) {
1561
+ const m = matchComponent(target, exc, ctx, visited);
1562
+ for (const d of m.diagnostics) diagnostics.push(d);
1563
+ if (m.complete && m.matched) excludedDefinite = true;
1564
+ if (!m.complete) anyExcludeUndetermined = true;
1565
+ }
1566
+ if (excludedDefinite) return decided(false, target);
1567
+ if (includedDefinite && !anyExcludeUndetermined) return decided(true, target);
1568
+ if (!includedDefinite && !anyIncludeUndetermined && !anyExcludeUndetermined) {
1569
+ return decided(false, target);
1570
+ }
1571
+ return undetermined(target, diagnostics);
1572
+ }
1573
+ return decided(false, target);
1574
+ }
1575
+ function validateCodeInValueSet(coding2, valueSet2, ctx = {}) {
1576
+ return validateInternal(
1577
+ coding2,
1578
+ valueSet2,
1579
+ ctx,
1580
+ new Set(valueSet2.url !== void 0 ? [valueSet2.url] : [])
1581
+ );
1582
+ }
1583
+
1584
+ // src/ucum/essence-data.generated.ts
1585
+ var UCUM_ESSENCE_XML = `<?xml version="1.0" encoding="ascii"?>
1586
+ <root xmlns="http://unitsofmeasure.org/ucum-essence" version="2.2" revision="N/A"
1587
+ revision-date="2024-06-17">
1588
+ <prefix Code="Y" CODE="YA">
1589
+ <name>yotta</name>
1590
+ <printSymbol>Y</printSymbol>
1591
+ <value value="1e24">1 &#215; 10<sup>24</sup>
1592
+ </value>
1593
+ </prefix>
1594
+ <prefix Code="Z" CODE="ZA">
1595
+ <name>zetta</name>
1596
+ <printSymbol>Z</printSymbol>
1597
+ <value value="1e21">1 &#215; 10<sup>21</sup>
1598
+ </value>
1599
+ </prefix>
1600
+ <prefix Code="E" CODE="EX">
1601
+ <name>exa</name>
1602
+ <printSymbol>E</printSymbol>
1603
+ <value value="1e18">1 &#215; 10<sup>18</sup>
1604
+ </value>
1605
+ </prefix>
1606
+ <prefix Code="P" CODE="PT">
1607
+ <name>peta</name>
1608
+ <printSymbol>P</printSymbol>
1609
+ <value value="1e15">1 &#215; 10<sup>15</sup>
1610
+ </value>
1611
+ </prefix>
1612
+ <prefix Code="T" CODE="TR">
1613
+ <name>tera</name>
1614
+ <printSymbol>T</printSymbol>
1615
+ <value value="1e12">1 &#215; 10<sup>12</sup>
1616
+ </value>
1617
+ </prefix>
1618
+ <prefix Code="G" CODE="GA">
1619
+ <name>giga</name>
1620
+ <printSymbol>G</printSymbol>
1621
+ <value value="1e9">1 &#215; 10<sup>9</sup>
1622
+ </value>
1623
+ </prefix>
1624
+ <prefix Code="M" CODE="MA">
1625
+ <name>mega</name>
1626
+ <printSymbol>M</printSymbol>
1627
+ <value value="1e6">1 &#215; 10<sup>6</sup>
1628
+ </value>
1629
+ </prefix>
1630
+ <prefix Code="k" CODE="K">
1631
+ <name>kilo</name>
1632
+ <printSymbol>k</printSymbol>
1633
+ <value value="1e3">1 &#215; 10<sup>3</sup>
1634
+ </value>
1635
+ </prefix>
1636
+ <prefix Code="h" CODE="H">
1637
+ <name>hecto</name>
1638
+ <printSymbol>h</printSymbol>
1639
+ <value value="1e2">1 &#215; 10<sup>2</sup>
1640
+ </value>
1641
+ </prefix>
1642
+ <prefix Code="da" CODE="DA">
1643
+ <name>deka</name>
1644
+ <printSymbol>da</printSymbol>
1645
+ <value value="1e1">1 &#215; 10<sup>1</sup>
1646
+ </value>
1647
+ </prefix>
1648
+ <prefix Code="d" CODE="D">
1649
+ <name>deci</name>
1650
+ <printSymbol>d</printSymbol>
1651
+ <value value="1e-1">1 &#215; 10<sup>-1</sup>
1652
+ </value>
1653
+ </prefix>
1654
+ <prefix Code="c" CODE="C">
1655
+ <name>centi</name>
1656
+ <printSymbol>c</printSymbol>
1657
+ <value value="1e-2">1 &#215; 10<sup>-2</sup>
1658
+ </value>
1659
+ </prefix>
1660
+ <prefix Code="m" CODE="M">
1661
+ <name>milli</name>
1662
+ <printSymbol>m</printSymbol>
1663
+ <value value="1e-3">1 &#215; 10<sup>-3</sup>
1664
+ </value>
1665
+ </prefix>
1666
+ <prefix Code="u" CODE="U">
1667
+ <name>micro</name>
1668
+ <printSymbol>&#956;</printSymbol>
1669
+ <value value="1e-6">1 &#215; 10<sup>-6</sup>
1670
+ </value>
1671
+ </prefix>
1672
+ <prefix Code="n" CODE="N">
1673
+ <name>nano</name>
1674
+ <printSymbol>n</printSymbol>
1675
+ <value value="1e-9">1 &#215; 10<sup>-9</sup>
1676
+ </value>
1677
+ </prefix>
1678
+ <prefix Code="p" CODE="P">
1679
+ <name>pico</name>
1680
+ <printSymbol>p</printSymbol>
1681
+ <value value="1e-12">1 &#215; 10<sup>-12</sup>
1682
+ </value>
1683
+ </prefix>
1684
+ <prefix Code="f" CODE="F">
1685
+ <name>femto</name>
1686
+ <printSymbol>f</printSymbol>
1687
+ <value value="1e-15">1 &#215; 10<sup>-15</sup>
1688
+ </value>
1689
+ </prefix>
1690
+ <prefix Code="a" CODE="A">
1691
+ <name>atto</name>
1692
+ <printSymbol>a</printSymbol>
1693
+ <value value="1e-18">1 &#215; 10<sup>-18</sup>
1694
+ </value>
1695
+ </prefix>
1696
+ <prefix Code="z" CODE="ZO">
1697
+ <name>zepto</name>
1698
+ <printSymbol>z</printSymbol>
1699
+ <value value="1e-21">1 &#215; 10<sup>-21</sup>
1700
+ </value>
1701
+ </prefix>
1702
+ <prefix Code="y" CODE="YO">
1703
+ <name>yocto</name>
1704
+ <printSymbol>y</printSymbol>
1705
+ <value value="1e-24">1 &#215; 10<sup>-24</sup>
1706
+ </value>
1707
+ </prefix>
1708
+ <base-unit Code="m" CODE="M" dim="L">
1709
+ <name>meter</name>
1710
+ <printSymbol>m</printSymbol>
1711
+ <property>length</property>
1712
+ </base-unit>
1713
+ <base-unit Code="s" CODE="S" dim="T">
1714
+ <name>second</name>
1715
+ <printSymbol>s</printSymbol>
1716
+ <property>time</property>
1717
+ </base-unit>
1718
+ <base-unit Code="g" CODE="G" dim="M">
1719
+ <name>gram</name>
1720
+ <printSymbol>g</printSymbol>
1721
+ <property>mass</property>
1722
+ </base-unit>
1723
+ <base-unit Code="rad" CODE="RAD" dim="A">
1724
+ <name>radian</name>
1725
+ <printSymbol>rad</printSymbol>
1726
+ <property>plane angle</property>
1727
+ </base-unit>
1728
+ <base-unit Code="K" CODE="K" dim="C">
1729
+ <name>kelvin</name>
1730
+ <printSymbol>K</printSymbol>
1731
+ <property>temperature</property>
1732
+ </base-unit>
1733
+ <base-unit Code="C" CODE="C" dim="Q">
1734
+ <name>coulomb</name>
1735
+ <printSymbol>C</printSymbol>
1736
+ <property>electric charge</property>
1737
+ </base-unit>
1738
+ <base-unit Code="cd" CODE="CD" dim="F">
1739
+ <name>candela</name>
1740
+ <printSymbol>cd</printSymbol>
1741
+ <property>luminous intensity</property>
1742
+ </base-unit>
1743
+ <unit Code="10*" CODE="10*" isMetric="no" class="dimless">
1744
+ <name>the number ten for arbitrary powers</name>
1745
+ <printSymbol>10</printSymbol>
1746
+ <property>number</property>
1747
+ <value Unit="1" UNIT="1" value="10">10</value>
1748
+ </unit>
1749
+ <unit Code="10^" CODE="10^" isMetric="no" class="dimless">
1750
+ <name>the number ten for arbitrary powers</name>
1751
+ <printSymbol>10</printSymbol>
1752
+ <property>number</property>
1753
+ <value Unit="1" UNIT="1" value="10">10</value>
1754
+ </unit>
1755
+ <unit Code="[pi]" CODE="[PI]" isMetric="no" class="dimless">
1756
+ <name>the number pi</name>
1757
+ <printSymbol>&#960;</printSymbol>
1758
+ <property>number</property>
1759
+ <value Unit="1" UNIT="1"
1760
+ value="3.1415926535897932384626433832795028841971693993751058209749445923">&#960;</value>
1761
+ </unit>
1762
+ <unit Code="%" CODE="%" isMetric="no" class="dimless">
1763
+ <name>percent</name>
1764
+ <printSymbol>%</printSymbol>
1765
+ <property>fraction</property>
1766
+ <value Unit="10*-2" UNIT="10*-2" value="1">1</value>
1767
+ </unit>
1768
+ <unit Code="[ppth]" CODE="[PPTH]" isMetric="no" class="dimless">
1769
+ <name>parts per thousand</name>
1770
+ <printSymbol>ppth</printSymbol>
1771
+ <property>fraction</property>
1772
+ <value Unit="10*-3" UNIT="10*-3" value="1">1</value>
1773
+ </unit>
1774
+ <unit Code="[ppm]" CODE="[PPM]" isMetric="no" class="dimless">
1775
+ <name>parts per million</name>
1776
+ <printSymbol>ppm</printSymbol>
1777
+ <property>fraction</property>
1778
+ <value Unit="10*-6" UNIT="10*-6" value="1">1</value>
1779
+ </unit>
1780
+ <unit Code="[ppb]" CODE="[PPB]" isMetric="no" class="dimless">
1781
+ <name>parts per billion</name>
1782
+ <printSymbol>ppb</printSymbol>
1783
+ <property>fraction</property>
1784
+ <value Unit="10*-9" UNIT="10*-9" value="1">1</value>
1785
+ </unit>
1786
+ <unit Code="[pptr]" CODE="[PPTR]" isMetric="no" class="dimless">
1787
+ <name>parts per trillion</name>
1788
+ <printSymbol>pptr</printSymbol>
1789
+ <property>fraction</property>
1790
+ <value Unit="10*-12" UNIT="10*-12" value="1">1</value>
1791
+ </unit>
1792
+ <unit Code="mol" CODE="MOL" isMetric="yes" class="si">
1793
+ <name>mole</name>
1794
+ <printSymbol>mol</printSymbol>
1795
+ <property>amount of substance</property>
1796
+ <value Unit="10*23" UNIT="10*23" value="6.02214076">6.02214076</value>
1797
+ </unit>
1798
+ <unit Code="sr" CODE="SR" isMetric="yes" class="si">
1799
+ <name>steradian</name>
1800
+ <printSymbol>sr</printSymbol>
1801
+ <property>solid angle</property>
1802
+ <value Unit="rad2" UNIT="RAD2" value="1">1</value>
1803
+ </unit>
1804
+ <unit Code="Hz" CODE="HZ" isMetric="yes" class="si">
1805
+ <name>hertz</name>
1806
+ <printSymbol>Hz</printSymbol>
1807
+ <property>frequency</property>
1808
+ <value Unit="s-1" UNIT="S-1" value="1">1</value>
1809
+ </unit>
1810
+ <unit Code="N" CODE="N" isMetric="yes" class="si">
1811
+ <name>newton</name>
1812
+ <printSymbol>N</printSymbol>
1813
+ <property>force</property>
1814
+ <value Unit="kg.m/s2" UNIT="KG.M/S2" value="1">1</value>
1815
+ </unit>
1816
+ <unit Code="Pa" CODE="PAL" isMetric="yes" class="si">
1817
+ <name>pascal</name>
1818
+ <printSymbol>Pa</printSymbol>
1819
+ <property>pressure</property>
1820
+ <value Unit="N/m2" UNIT="N/M2" value="1">1</value>
1821
+ </unit>
1822
+ <unit Code="J" CODE="J" isMetric="yes" class="si">
1823
+ <name>joule</name>
1824
+ <printSymbol>J</printSymbol>
1825
+ <property>energy</property>
1826
+ <value Unit="N.m" UNIT="N.M" value="1">1</value>
1827
+ </unit>
1828
+ <unit Code="W" CODE="W" isMetric="yes" class="si">
1829
+ <name>watt</name>
1830
+ <printSymbol>W</printSymbol>
1831
+ <property>power</property>
1832
+ <value Unit="J/s" UNIT="J/S" value="1">1</value>
1833
+ </unit>
1834
+ <unit Code="A" CODE="A" isMetric="yes" class="si">
1835
+ <name>amp&#232;re</name>
1836
+ <printSymbol>A</printSymbol>
1837
+ <property>electric current</property>
1838
+ <value Unit="C/s" UNIT="C/S" value="1">1</value>
1839
+ </unit>
1840
+ <unit Code="V" CODE="V" isMetric="yes" class="si">
1841
+ <name>volt</name>
1842
+ <printSymbol>V</printSymbol>
1843
+ <property>electric potential</property>
1844
+ <value Unit="J/C" UNIT="J/C" value="1">1</value>
1845
+ </unit>
1846
+ <unit Code="F" CODE="F" isMetric="yes" class="si">
1847
+ <name>farad</name>
1848
+ <printSymbol>F</printSymbol>
1849
+ <property>electric capacitance</property>
1850
+ <value Unit="C/V" UNIT="C/V" value="1">1</value>
1851
+ </unit>
1852
+ <unit Code="Ohm" CODE="OHM" isMetric="yes" class="si">
1853
+ <name>ohm</name>
1854
+ <printSymbol>&#937;</printSymbol>
1855
+ <property>electric resistance</property>
1856
+ <value Unit="V/A" UNIT="V/A" value="1">1</value>
1857
+ </unit>
1858
+ <unit Code="S" CODE="SIE" isMetric="yes" class="si">
1859
+ <name>siemens</name>
1860
+ <printSymbol>S</printSymbol>
1861
+ <property>electric conductance</property>
1862
+ <value Unit="Ohm-1" UNIT="OHM-1" value="1">1</value>
1863
+ </unit>
1864
+ <unit Code="Wb" CODE="WB" isMetric="yes" class="si">
1865
+ <name>weber</name>
1866
+ <printSymbol>Wb</printSymbol>
1867
+ <property>magnetic flux</property>
1868
+ <value Unit="V.s" UNIT="V.S" value="1">1</value>
1869
+ </unit>
1870
+ <unit Code="Cel" CODE="CEL" isMetric="yes" isSpecial="yes" class="si">
1871
+ <name>degree Celsius</name>
1872
+ <printSymbol>&#176;C</printSymbol>
1873
+ <property>temperature</property>
1874
+ <value Unit="cel(1 K)" UNIT="CEL(1 K)">
1875
+ <function name="Cel" value="1" Unit="K"/>
1876
+ </value>
1877
+ </unit>
1878
+ <unit Code="T" CODE="T" isMetric="yes" class="si">
1879
+ <name>tesla</name>
1880
+ <printSymbol>T</printSymbol>
1881
+ <property>magnetic flux density</property>
1882
+ <value Unit="Wb/m2" UNIT="WB/M2" value="1">1</value>
1883
+ </unit>
1884
+ <unit Code="H" CODE="H" isMetric="yes" class="si">
1885
+ <name>henry</name>
1886
+ <printSymbol>H</printSymbol>
1887
+ <property>inductance</property>
1888
+ <value Unit="Wb/A" UNIT="WB/A" value="1">1</value>
1889
+ </unit>
1890
+ <unit Code="lm" CODE="LM" isMetric="yes" class="si">
1891
+ <name>lumen</name>
1892
+ <printSymbol>lm</printSymbol>
1893
+ <property>luminous flux</property>
1894
+ <value Unit="cd.sr" UNIT="CD.SR" value="1">1</value>
1895
+ </unit>
1896
+ <unit Code="lx" CODE="LX" isMetric="yes" class="si">
1897
+ <name>lux</name>
1898
+ <printSymbol>lx</printSymbol>
1899
+ <property>illuminance</property>
1900
+ <value Unit="lm/m2" UNIT="LM/M2" value="1">1</value>
1901
+ </unit>
1902
+ <unit Code="Bq" CODE="BQ" isMetric="yes" class="si">
1903
+ <name>becquerel</name>
1904
+ <printSymbol>Bq</printSymbol>
1905
+ <property>radioactivity</property>
1906
+ <value Unit="s-1" UNIT="S-1" value="1">1</value>
1907
+ </unit>
1908
+ <unit Code="Gy" CODE="GY" isMetric="yes" class="si">
1909
+ <name>gray</name>
1910
+ <printSymbol>Gy</printSymbol>
1911
+ <property>energy dose</property>
1912
+ <value Unit="J/kg" UNIT="J/KG" value="1">1</value>
1913
+ </unit>
1914
+ <unit Code="Sv" CODE="SV" isMetric="yes" class="si">
1915
+ <name>sievert</name>
1916
+ <printSymbol>Sv</printSymbol>
1917
+ <property>dose equivalent</property>
1918
+ <value Unit="J/kg" UNIT="J/KG" value="1">1</value>
1919
+ </unit>
1920
+ <unit Code="gon" CODE="GON" isMetric="no" class="iso1000">
1921
+ <name>gon</name>
1922
+ <name>grade</name>
1923
+ <printSymbol>
1924
+ <sup>g</sup>
1925
+ </printSymbol>
1926
+ <property>plane angle</property>
1927
+ <value Unit="deg" UNIT="DEG" value="0.9">0.9</value>
1928
+ </unit>
1929
+ <unit Code="deg" CODE="DEG" isMetric="no" class="iso1000">
1930
+ <name>degree</name>
1931
+ <printSymbol>&#176;</printSymbol>
1932
+ <property>plane angle</property>
1933
+ <value Unit="[pi].rad/360" UNIT="[PI].RAD/360" value="2">2</value>
1934
+ </unit>
1935
+ <unit Code="'" CODE="'" isMetric="no" class="iso1000">
1936
+ <name>minute</name>
1937
+ <printSymbol>'</printSymbol>
1938
+ <property>plane angle</property>
1939
+ <value Unit="deg/60" UNIT="DEG/60" value="1">1</value>
1940
+ </unit>
1941
+ <unit Code="''" CODE="''" isMetric="no" class="iso1000">
1942
+ <name>second</name>
1943
+ <printSymbol>''</printSymbol>
1944
+ <property>plane angle</property>
1945
+ <value Unit="'/60" UNIT="'/60" value="1">1</value>
1946
+ </unit>
1947
+ <unit Code="l" CODE="L" isMetric="yes" class="iso1000">
1948
+ <name>liter</name>
1949
+ <printSymbol>l</printSymbol>
1950
+ <property>volume</property>
1951
+ <value Unit="dm3" UNIT="DM3" value="1">1</value>
1952
+ </unit>
1953
+ <unit Code="L" CODE="L" isMetric="yes" class="iso1000">
1954
+ <name>liter</name>
1955
+ <printSymbol>L</printSymbol>
1956
+ <property>volume</property>
1957
+ <value Unit="l" UNIT="L" value="1">1</value>
1958
+ </unit>
1959
+ <unit Code="ar" CODE="AR" isMetric="yes" class="iso1000">
1960
+ <name>are</name>
1961
+ <printSymbol>a</printSymbol>
1962
+ <property>area</property>
1963
+ <value Unit="m2" UNIT="M2" value="100">100</value>
1964
+ </unit>
1965
+ <unit Code="min" CODE="MIN" isMetric="no" class="iso1000">
1966
+ <name>minute</name>
1967
+ <printSymbol>min</printSymbol>
1968
+ <property>time</property>
1969
+ <value Unit="s" UNIT="S" value="60">60</value>
1970
+ </unit>
1971
+ <unit Code="h" CODE="HR" isMetric="no" class="iso1000">
1972
+ <name>hour</name>
1973
+ <printSymbol>h</printSymbol>
1974
+ <property>time</property>
1975
+ <value Unit="min" UNIT="MIN" value="60">60</value>
1976
+ </unit>
1977
+ <unit Code="d" CODE="D" isMetric="no" class="iso1000">
1978
+ <name>day</name>
1979
+ <printSymbol>d</printSymbol>
1980
+ <property>time</property>
1981
+ <value Unit="h" UNIT="HR" value="24">24</value>
1982
+ </unit>
1983
+ <unit Code="a_t" CODE="ANN_T" isMetric="no" class="iso1000">
1984
+ <name>tropical year</name>
1985
+ <printSymbol>a<sub>t</sub>
1986
+ </printSymbol>
1987
+ <property>time</property>
1988
+ <value Unit="d" UNIT="D" value="365.24219">365.24219</value>
1989
+ </unit>
1990
+ <unit Code="a_j" CODE="ANN_J" isMetric="no" class="iso1000">
1991
+ <name>mean Julian year</name>
1992
+ <printSymbol>a<sub>j</sub>
1993
+ </printSymbol>
1994
+ <property>time</property>
1995
+ <value Unit="d" UNIT="D" value="365.25">365.25</value>
1996
+ </unit>
1997
+ <unit Code="a_g" CODE="ANN_G" isMetric="no" class="iso1000">
1998
+ <name>mean Gregorian year</name>
1999
+ <printSymbol>a<sub>g</sub>
2000
+ </printSymbol>
2001
+ <property>time</property>
2002
+ <value Unit="d" UNIT="D" value="365.2425">365.2425</value>
2003
+ </unit>
2004
+ <unit Code="a" CODE="ANN" isMetric="no" class="iso1000">
2005
+ <name>year</name>
2006
+ <printSymbol>a</printSymbol>
2007
+ <property>time</property>
2008
+ <value Unit="a_j" UNIT="ANN_J" value="1">1</value>
2009
+ </unit>
2010
+ <unit Code="wk" CODE="WK" isMetric="no" class="iso1000">
2011
+ <name>week</name>
2012
+ <printSymbol>wk</printSymbol>
2013
+ <property>time</property>
2014
+ <value Unit="d" UNIT="D" value="7">7</value>
2015
+ </unit>
2016
+ <unit Code="mo_s" CODE="MO_S" isMetric="no" class="iso1000">
2017
+ <name>synodal month</name>
2018
+ <printSymbol>mo<sub>s</sub>
2019
+ </printSymbol>
2020
+ <property>time</property>
2021
+ <value Unit="d" UNIT="D" value="29.53059">29.53059</value>
2022
+ </unit>
2023
+ <unit Code="mo_j" CODE="MO_J" isMetric="no" class="iso1000">
2024
+ <name>mean Julian month</name>
2025
+ <printSymbol>mo<sub>j</sub>
2026
+ </printSymbol>
2027
+ <property>time</property>
2028
+ <value Unit="a_j/12" UNIT="ANN_J/12" value="1">1</value>
2029
+ </unit>
2030
+ <unit Code="mo_g" CODE="MO_G" isMetric="no" class="iso1000">
2031
+ <name>mean Gregorian month</name>
2032
+ <printSymbol>mo<sub>g</sub>
2033
+ </printSymbol>
2034
+ <property>time</property>
2035
+ <value Unit="a_g/12" UNIT="ANN_G/12" value="1">1</value>
2036
+ </unit>
2037
+ <unit Code="mo" CODE="MO" isMetric="no" class="iso1000">
2038
+ <name>month</name>
2039
+ <printSymbol>mo</printSymbol>
2040
+ <property>time</property>
2041
+ <value Unit="mo_j" UNIT="MO_J" value="1">1</value>
2042
+ </unit>
2043
+ <unit Code="t" CODE="TNE" isMetric="yes" class="iso1000">
2044
+ <name>tonne</name>
2045
+ <printSymbol>t</printSymbol>
2046
+ <property>mass</property>
2047
+ <value Unit="kg" UNIT="KG" value="1e3">1 &#215; 10<sup>3</sup>
2048
+ </value>
2049
+ </unit>
2050
+ <unit Code="bar" CODE="BAR" isMetric="yes" class="iso1000">
2051
+ <name>bar</name>
2052
+ <printSymbol>bar</printSymbol>
2053
+ <property>pressure</property>
2054
+ <value Unit="Pa" UNIT="PAL" value="1e5">1 &#215; 10<sup>5</sup>
2055
+ </value>
2056
+ </unit>
2057
+ <unit Code="u" CODE="AMU" isMetric="yes" class="iso1000">
2058
+ <name>unified atomic mass unit</name>
2059
+ <printSymbol>u</printSymbol>
2060
+ <property>mass</property>
2061
+ <value Unit="g" UNIT="G" value="1.66053906660e-24">1.66053906660 &#215; 10<sup>-24</sup>
2062
+ </value>
2063
+ </unit>
2064
+ <unit Code="eV" CODE="EV" isMetric="yes" class="iso1000">
2065
+ <name>electronvolt</name>
2066
+ <printSymbol>eV</printSymbol>
2067
+ <property>energy</property>
2068
+ <value Unit="[e].V" UNIT="[E].V" value="1">1</value>
2069
+ </unit>
2070
+ <unit Code="AU" CODE="ASU" isMetric="no" class="iso1000">
2071
+ <name>astronomic unit</name>
2072
+ <printSymbol>AU</printSymbol>
2073
+ <property>length</property>
2074
+ <value Unit="Mm" UNIT="MAM" value="149597.870691">149597.870691</value>
2075
+ </unit>
2076
+ <unit Code="pc" CODE="PRS" isMetric="yes" class="iso1000">
2077
+ <name>parsec</name>
2078
+ <printSymbol>pc</printSymbol>
2079
+ <property>length</property>
2080
+ <value Unit="m" UNIT="M" value="3.085678e16">3.085678 &#215; 10<sup>16</sup>
2081
+ </value>
2082
+ </unit>
2083
+ <unit Code="[c]" CODE="[C]" isMetric="yes" class="const">
2084
+ <name>velocity of light</name>
2085
+ <printSymbol>
2086
+ <i>c</i>
2087
+ </printSymbol>
2088
+ <property>velocity</property>
2089
+ <value Unit="m/s" UNIT="M/S" value="299792458">299792458</value>
2090
+ </unit>
2091
+ <unit Code="[h]" CODE="[H]" isMetric="yes" class="const">
2092
+ <name>Planck constant</name>
2093
+ <printSymbol>
2094
+ <i>h</i>
2095
+ </printSymbol>
2096
+ <property>action</property>
2097
+ <value Unit="J.s" UNIT="J.S" value="6.62607015e-34">6.62607015 &#215; 10<sup>-34</sup>
2098
+ </value>
2099
+ </unit>
2100
+ <unit Code="[k]" CODE="[K]" isMetric="yes" class="const">
2101
+ <name>Boltzmann constant</name>
2102
+ <printSymbol>
2103
+ <i>k</i>
2104
+ </printSymbol>
2105
+ <property>(unclassified)</property>
2106
+ <value Unit="J/K" UNIT="J/K" value="1.380649e-23">1.380649 &#215; 10<sup>-23</sup>
2107
+ </value>
2108
+ </unit>
2109
+ <unit Code="[eps_0]" CODE="[EPS_0]" isMetric="yes" class="const">
2110
+ <name>permittivity of vacuum</name>
2111
+ <printSymbol>
2112
+ <i>&#949;<sub>
2113
+ <r>0</r>
2114
+ </sub>
2115
+ </i>
2116
+ </printSymbol>
2117
+ <property>electric permittivity</property>
2118
+ <value Unit="F/m" UNIT="F/M" value="8.854187817e-12">8.854187817 &#215; 10<sup>-12</sup>
2119
+ </value>
2120
+ </unit>
2121
+ <unit Code="[mu_0]" CODE="[MU_0]" isMetric="yes" class="const">
2122
+ <name>permeability of vacuum</name>
2123
+ <printSymbol>
2124
+ <i>&#956;<sub>
2125
+ <r>0</r>
2126
+ </sub>
2127
+ </i>
2128
+ </printSymbol>
2129
+ <property>magnetic permeability</property>
2130
+ <value Unit="4.[pi].10*-7.N/A2" UNIT="4.[PI].10*-7.N/A2" value="1">1</value>
2131
+ </unit>
2132
+ <unit Code="[e]" CODE="[E]" isMetric="yes" class="const">
2133
+ <name>elementary charge</name>
2134
+ <printSymbol>
2135
+ <i>e</i>
2136
+ </printSymbol>
2137
+ <property>electric charge</property>
2138
+ <value Unit="C" UNIT="C" value="1.602176634e-19">1.602176634 &#215; 10<sup>-19</sup>
2139
+ </value>
2140
+ </unit>
2141
+ <unit Code="[m_e]" CODE="[M_E]" isMetric="yes" class="const">
2142
+ <name>electron mass</name>
2143
+ <printSymbol>
2144
+ <i>m<sub>
2145
+ <r>e</r>
2146
+ </sub>
2147
+ </i>
2148
+ </printSymbol>
2149
+ <property>mass</property>
2150
+ <value Unit="kg" UNIT="kg" value="9.1093837139e-31">9.1093837139 &#215; 10<sup>-31</sup>
2151
+ </value>
2152
+ </unit>
2153
+ <unit Code="[m_p]" CODE="[M_P]" isMetric="yes" class="const">
2154
+ <name>proton mass</name>
2155
+ <printSymbol>
2156
+ <i>m<sub>
2157
+ <r>p</r>
2158
+ </sub>
2159
+ </i>
2160
+ </printSymbol>
2161
+ <property>mass</property>
2162
+ <value Unit="kg" UNIT="kg" value="1.67262192595e-27">1.67262192595 &#215; 10<sup>-27</sup>
2163
+ </value>
2164
+ </unit>
2165
+ <unit Code="[G]" CODE="[GC]" isMetric="yes" class="const">
2166
+ <name>Newtonian constant of gravitation</name>
2167
+ <printSymbol>
2168
+ <i>G</i>
2169
+ </printSymbol>
2170
+ <property>(unclassified)</property>
2171
+ <value Unit="m3.kg-1.s-2" UNIT="M3.KG-1.S-2" value="6.67430e-11">6.67430 &#215; 10<sup>-11</sup>
2172
+ </value>
2173
+ </unit>
2174
+ <unit Code="[g]" CODE="[G]" isMetric="yes" class="const">
2175
+ <name>standard acceleration of free fall</name>
2176
+ <printSymbol>
2177
+ <i>g<sub>n</sub>
2178
+ </i>
2179
+ </printSymbol>
2180
+ <property>acceleration</property>
2181
+ <value Unit="m/s2" UNIT="M/S2" value="980665e-5">9.80665</value>
2182
+ </unit>
2183
+ <unit Code="atm" CODE="ATM" isMetric="no" class="const">
2184
+ <name>standard atmosphere</name>
2185
+ <printSymbol>atm</printSymbol>
2186
+ <property>pressure</property>
2187
+ <value Unit="Pa" UNIT="PAL" value="101325">101325</value>
2188
+ </unit>
2189
+ <unit Code="[ly]" CODE="[LY]" isMetric="yes" class="const">
2190
+ <name>light-year</name>
2191
+ <printSymbol>l.y.</printSymbol>
2192
+ <property>length</property>
2193
+ <value Unit="[c].a_j" UNIT="[C].ANN_J" value="1">1</value>
2194
+ </unit>
2195
+ <unit Code="gf" CODE="GF" isMetric="yes" class="const">
2196
+ <name>gram-force</name>
2197
+ <printSymbol>gf</printSymbol>
2198
+ <property>force</property>
2199
+ <value Unit="g.[g]" UNIT="G.[G]" value="1">1</value>
2200
+ </unit>
2201
+ <unit Code="[lbf_av]" CODE="[LBF_AV]" isMetric="no" class="const">
2202
+ <name>pound force</name>
2203
+ <printSymbol>lbf</printSymbol>
2204
+ <property>force</property>
2205
+ <value Unit="[lb_av].[g]" UNIT="[LB_AV].[G]" value="1">1</value>
2206
+ </unit>
2207
+ <unit Code="Ky" CODE="KY" isMetric="yes" class="cgs">
2208
+ <name>Kayser</name>
2209
+ <printSymbol>K</printSymbol>
2210
+ <property>lineic number</property>
2211
+ <value Unit="cm-1" UNIT="CM-1" value="1">1</value>
2212
+ </unit>
2213
+ <unit Code="Gal" CODE="GL" isMetric="yes" class="cgs">
2214
+ <name>Gal</name>
2215
+ <printSymbol>Gal</printSymbol>
2216
+ <property>acceleration</property>
2217
+ <value Unit="cm/s2" UNIT="CM/S2" value="1">1</value>
2218
+ </unit>
2219
+ <unit Code="dyn" CODE="DYN" isMetric="yes" class="cgs">
2220
+ <name>dyne</name>
2221
+ <printSymbol>dyn</printSymbol>
2222
+ <property>force</property>
2223
+ <value Unit="g.cm/s2" UNIT="G.CM/S2" value="1">1</value>
2224
+ </unit>
2225
+ <unit Code="erg" CODE="ERG" isMetric="yes" class="cgs">
2226
+ <name>erg</name>
2227
+ <printSymbol>erg</printSymbol>
2228
+ <property>energy</property>
2229
+ <value Unit="dyn.cm" UNIT="DYN.CM" value="1">1</value>
2230
+ </unit>
2231
+ <unit Code="P" CODE="P" isMetric="yes" class="cgs">
2232
+ <name>Poise</name>
2233
+ <printSymbol>P</printSymbol>
2234
+ <property>dynamic viscosity</property>
2235
+ <value Unit="dyn.s/cm2" UNIT="DYN.S/CM2" value="1">1</value>
2236
+ </unit>
2237
+ <unit Code="Bi" CODE="BI" isMetric="yes" class="cgs">
2238
+ <name>Biot</name>
2239
+ <printSymbol>Bi</printSymbol>
2240
+ <property>electric current</property>
2241
+ <value Unit="A" UNIT="A" value="10">10</value>
2242
+ </unit>
2243
+ <unit Code="St" CODE="ST" isMetric="yes" class="cgs">
2244
+ <name>Stokes</name>
2245
+ <printSymbol>St</printSymbol>
2246
+ <property>kinematic viscosity</property>
2247
+ <value Unit="cm2/s" UNIT="CM2/S" value="1">1</value>
2248
+ </unit>
2249
+ <unit Code="Mx" CODE="MX" isMetric="yes" class="cgs">
2250
+ <name>Maxwell</name>
2251
+ <printSymbol>Mx</printSymbol>
2252
+ <property>flux of magnetic induction</property>
2253
+ <value Unit="Wb" UNIT="WB" value="1e-8">1 &#215; 10<sup>-8</sup>
2254
+ </value>
2255
+ </unit>
2256
+ <unit Code="G" CODE="GS" isMetric="yes" class="cgs">
2257
+ <name>Gauss</name>
2258
+ <printSymbol>Gs</printSymbol>
2259
+ <property>magnetic flux density</property>
2260
+ <value Unit="T" UNIT="T" value="1e-4">1 &#215; 10<sup>-4</sup>
2261
+ </value>
2262
+ </unit>
2263
+ <unit Code="Oe" CODE="OE" isMetric="yes" class="cgs">
2264
+ <name>Oersted</name>
2265
+ <printSymbol>Oe</printSymbol>
2266
+ <property>magnetic field intensity</property>
2267
+ <value Unit="/[pi].A/m" UNIT="/[PI].A/M" value="250">250</value>
2268
+ </unit>
2269
+ <unit Code="Gb" CODE="GB" isMetric="yes" class="cgs">
2270
+ <name>Gilbert</name>
2271
+ <printSymbol>Gb</printSymbol>
2272
+ <property>magnetic tension</property>
2273
+ <value Unit="Oe.cm" UNIT="OE.CM" value="1">1</value>
2274
+ </unit>
2275
+ <unit Code="sb" CODE="SB" isMetric="yes" class="cgs">
2276
+ <name>stilb</name>
2277
+ <printSymbol>sb</printSymbol>
2278
+ <property>lum. intensity density</property>
2279
+ <value Unit="cd/cm2" UNIT="CD/CM2" value="1">1</value>
2280
+ </unit>
2281
+ <unit Code="Lmb" CODE="LMB" isMetric="yes" class="cgs">
2282
+ <name>Lambert</name>
2283
+ <printSymbol>L</printSymbol>
2284
+ <property>brightness</property>
2285
+ <value Unit="cd/cm2/[pi]" UNIT="CD/CM2/[PI]" value="1">1</value>
2286
+ </unit>
2287
+ <unit Code="ph" CODE="PHT" isMetric="yes" class="cgs">
2288
+ <name>phot</name>
2289
+ <printSymbol>ph</printSymbol>
2290
+ <property>illuminance</property>
2291
+ <value Unit="lx" UNIT="LX" value="1e-4">1 &#215; 10<sup>-4</sup>
2292
+ </value>
2293
+ </unit>
2294
+ <unit Code="Ci" CODE="CI" isMetric="yes" class="cgs">
2295
+ <name>Curie</name>
2296
+ <printSymbol>Ci</printSymbol>
2297
+ <property>radioactivity</property>
2298
+ <value Unit="Bq" UNIT="BQ" value="37e9">3.7 &#215; 10<sup>10</sup>
2299
+ </value>
2300
+ </unit>
2301
+ <unit Code="R" CODE="ROE" isMetric="yes" class="cgs">
2302
+ <name>Roentgen</name>
2303
+ <printSymbol>R</printSymbol>
2304
+ <property>ion dose</property>
2305
+ <value Unit="C/kg" UNIT="C/KG" value="2.58e-4">2.58 &#215; 10<sup>-4</sup>
2306
+ </value>
2307
+ </unit>
2308
+ <unit Code="RAD" CODE="[RAD]" isMetric="yes" class="cgs">
2309
+ <name>radiation absorbed dose</name>
2310
+ <printSymbol>RAD</printSymbol>
2311
+ <property>energy dose</property>
2312
+ <value Unit="erg/g" UNIT="ERG/G" value="100">100</value>
2313
+ </unit>
2314
+ <unit Code="REM" CODE="[REM]" isMetric="yes" class="cgs">
2315
+ <name>radiation equivalent man</name>
2316
+ <printSymbol>REM</printSymbol>
2317
+ <property>dose equivalent</property>
2318
+ <value Unit="RAD" UNIT="[RAD]" value="1">1</value>
2319
+ </unit>
2320
+ <unit Code="[in_i]" CODE="[IN_I]" isMetric="no" class="intcust">
2321
+ <name>inch</name>
2322
+ <printSymbol>in</printSymbol>
2323
+ <property>length</property>
2324
+ <value Unit="cm" UNIT="CM" value="254e-2">2.54</value>
2325
+ </unit>
2326
+ <unit Code="[ft_i]" CODE="[FT_I]" isMetric="no" class="intcust">
2327
+ <name>foot</name>
2328
+ <printSymbol>ft</printSymbol>
2329
+ <property>length</property>
2330
+ <value Unit="[in_i]" UNIT="[IN_I]" value="12">12</value>
2331
+ </unit>
2332
+ <unit Code="[yd_i]" CODE="[YD_I]" isMetric="no" class="intcust">
2333
+ <name>yard</name>
2334
+ <printSymbol>yd</printSymbol>
2335
+ <property>length</property>
2336
+ <value Unit="[ft_i]" UNIT="[FT_I]" value="3">3</value>
2337
+ </unit>
2338
+ <unit Code="[mi_i]" CODE="[MI_I]" isMetric="no" class="intcust">
2339
+ <name>mile</name>
2340
+ <printSymbol>mi</printSymbol>
2341
+ <property>length</property>
2342
+ <value Unit="[ft_i]" UNIT="[FT_I]" value="5280">5280</value>
2343
+ </unit>
2344
+ <unit Code="[fth_i]" CODE="[FTH_I]" isMetric="no" class="intcust">
2345
+ <name>fathom</name>
2346
+ <printSymbol>fth</printSymbol>
2347
+ <property>depth of water</property>
2348
+ <value Unit="[ft_i]" UNIT="[FT_I]" value="6">6</value>
2349
+ </unit>
2350
+ <unit Code="[nmi_i]" CODE="[NMI_I]" isMetric="no" class="intcust">
2351
+ <name>nautical mile</name>
2352
+ <printSymbol>n.mi</printSymbol>
2353
+ <property>length</property>
2354
+ <value Unit="m" UNIT="M" value="1852">1852</value>
2355
+ </unit>
2356
+ <unit Code="[kn_i]" CODE="[KN_I]" isMetric="no" class="intcust">
2357
+ <name>knot</name>
2358
+ <printSymbol>knot</printSymbol>
2359
+ <property>velocity</property>
2360
+ <value Unit="[nmi_i]/h" UNIT="[NMI_I]/H" value="1">1</value>
2361
+ </unit>
2362
+ <unit Code="[sin_i]" CODE="[SIN_I]" isMetric="no" class="intcust">
2363
+ <name>square inch</name>
2364
+ <property>area</property>
2365
+ <value Unit="[in_i]2" UNIT="[IN_I]2" value="1">1</value>
2366
+ </unit>
2367
+ <unit Code="[sft_i]" CODE="[SFT_I]" isMetric="no" class="intcust">
2368
+ <name>square foot</name>
2369
+ <property>area</property>
2370
+ <value Unit="[ft_i]2" UNIT="[FT_I]2" value="1">1</value>
2371
+ </unit>
2372
+ <unit Code="[syd_i]" CODE="[SYD_I]" isMetric="no" class="intcust">
2373
+ <name>square yard</name>
2374
+ <property>area</property>
2375
+ <value Unit="[yd_i]2" UNIT="[YD_I]2" value="1">1</value>
2376
+ </unit>
2377
+ <unit Code="[cin_i]" CODE="[CIN_I]" isMetric="no" class="intcust">
2378
+ <name>cubic inch</name>
2379
+ <property>volume</property>
2380
+ <value Unit="[in_i]3" UNIT="[IN_I]3" value="1">1</value>
2381
+ </unit>
2382
+ <unit Code="[cft_i]" CODE="[CFT_I]" isMetric="no" class="intcust">
2383
+ <name>cubic foot</name>
2384
+ <property>volume</property>
2385
+ <value Unit="[ft_i]3" UNIT="[FT_I]3" value="1">1</value>
2386
+ </unit>
2387
+ <unit Code="[cyd_i]" CODE="[CYD_I]" isMetric="no" class="intcust">
2388
+ <name>cubic yard</name>
2389
+ <printSymbol>cu.yd</printSymbol>
2390
+ <property>volume</property>
2391
+ <value Unit="[yd_i]3" UNIT="[YD_I]3" value="1">1</value>
2392
+ </unit>
2393
+ <unit Code="[bf_i]" CODE="[BF_I]" isMetric="no" class="intcust">
2394
+ <name>board foot</name>
2395
+ <property>volume</property>
2396
+ <value Unit="[in_i]3" UNIT="[IN_I]3" value="144">144</value>
2397
+ </unit>
2398
+ <unit Code="[cr_i]" CODE="[CR_I]" isMetric="no" class="intcust">
2399
+ <name>cord</name>
2400
+ <property>volume</property>
2401
+ <value Unit="[ft_i]3" UNIT="[FT_I]3" value="128">128</value>
2402
+ </unit>
2403
+ <unit Code="[mil_i]" CODE="[MIL_I]" isMetric="no" class="intcust">
2404
+ <name>mil</name>
2405
+ <printSymbol>mil</printSymbol>
2406
+ <property>length</property>
2407
+ <value Unit="[in_i]" UNIT="[IN_I]" value="1e-3">1 &#215; 10<sup>-3</sup>
2408
+ </value>
2409
+ </unit>
2410
+ <unit Code="[cml_i]" CODE="[CML_I]" isMetric="no" class="intcust">
2411
+ <name>circular mil</name>
2412
+ <printSymbol>circ.mil</printSymbol>
2413
+ <property>area</property>
2414
+ <value Unit="[pi]/4.[mil_i]2" UNIT="[PI]/4.[MIL_I]2" value="1">1</value>
2415
+ </unit>
2416
+ <unit Code="[hd_i]" CODE="[HD_I]" isMetric="no" class="intcust">
2417
+ <name>hand</name>
2418
+ <printSymbol>hd</printSymbol>
2419
+ <property>height of horses</property>
2420
+ <value Unit="[in_i]" UNIT="[IN_I]" value="4">4</value>
2421
+ </unit>
2422
+ <unit Code="[ft_us]" CODE="[FT_US]" isMetric="no" class="us-lengths">
2423
+ <name>foot</name>
2424
+ <printSymbol>ft<sub>us</sub>
2425
+ </printSymbol>
2426
+ <property>length</property>
2427
+ <value Unit="m/3937" UNIT="M/3937" value="1200">1200</value>
2428
+ </unit>
2429
+ <unit Code="[yd_us]" CODE="[YD_US]" isMetric="no" class="us-lengths">
2430
+ <name>yard</name>
2431
+ <property>length</property>
2432
+ <value Unit="[ft_us]" UNIT="[FT_US]" value="3">3</value>
2433
+ </unit>
2434
+ <unit Code="[in_us]" CODE="[IN_US]" isMetric="no" class="us-lengths">
2435
+ <name>inch</name>
2436
+ <property>length</property>
2437
+ <value Unit="[ft_us]/12" UNIT="[FT_US]/12" value="1">1</value>
2438
+ </unit>
2439
+ <unit Code="[rd_us]" CODE="[RD_US]" isMetric="no" class="us-lengths">
2440
+ <name>rod</name>
2441
+ <property>length</property>
2442
+ <value Unit="[ft_us]" UNIT="[FT_US]" value="16.5">16.5</value>
2443
+ </unit>
2444
+ <unit Code="[ch_us]" CODE="[CH_US]" isMetric="no" class="us-lengths">
2445
+ <name>Gunter's chain</name>
2446
+ <name>Surveyor's chain</name>
2447
+ <property>length</property>
2448
+ <value Unit="[rd_us]" UNIT="[RD_US]" value="4">4</value>
2449
+ </unit>
2450
+ <unit Code="[lk_us]" CODE="[LK_US]" isMetric="no" class="us-lengths">
2451
+ <name>link for Gunter's chain</name>
2452
+ <property>length</property>
2453
+ <value Unit="[ch_us]/100" UNIT="[CH_US]/100" value="1">1</value>
2454
+ </unit>
2455
+ <unit Code="[rch_us]" CODE="[RCH_US]" isMetric="no" class="us-lengths">
2456
+ <name>Ramden's chain</name>
2457
+ <name>Engineer's chain</name>
2458
+ <property>length</property>
2459
+ <value Unit="[ft_us]" UNIT="[FT_US]" value="100">100</value>
2460
+ </unit>
2461
+ <unit Code="[rlk_us]" CODE="[RLK_US]" isMetric="no" class="us-lengths">
2462
+ <name>link for Ramden's chain</name>
2463
+ <property>length</property>
2464
+ <value Unit="[rch_us]/100" UNIT="[RCH_US]/100" value="1">1</value>
2465
+ </unit>
2466
+ <unit Code="[fth_us]" CODE="[FTH_US]" isMetric="no" class="us-lengths">
2467
+ <name>fathom</name>
2468
+ <property>length</property>
2469
+ <value Unit="[ft_us]" UNIT="[FT_US]" value="6">6</value>
2470
+ </unit>
2471
+ <unit Code="[fur_us]" CODE="[FUR_US]" isMetric="no" class="us-lengths">
2472
+ <name>furlong</name>
2473
+ <property>length</property>
2474
+ <value Unit="[rd_us]" UNIT="[RD_US]" value="40">40</value>
2475
+ </unit>
2476
+ <unit Code="[mi_us]" CODE="[MI_US]" isMetric="no" class="us-lengths">
2477
+ <name>mile</name>
2478
+ <property>length</property>
2479
+ <value Unit="[fur_us]" UNIT="[FUR_US]" value="8">8</value>
2480
+ </unit>
2481
+ <unit Code="[acr_us]" CODE="[ACR_US]" isMetric="no" class="us-lengths">
2482
+ <name>acre</name>
2483
+ <property>area</property>
2484
+ <value Unit="[rd_us]2" UNIT="[RD_US]2" value="160">160</value>
2485
+ </unit>
2486
+ <unit Code="[srd_us]" CODE="[SRD_US]" isMetric="no" class="us-lengths">
2487
+ <name>square rod</name>
2488
+ <property>area</property>
2489
+ <value Unit="[rd_us]2" UNIT="[RD_US]2" value="1">1</value>
2490
+ </unit>
2491
+ <unit Code="[smi_us]" CODE="[SMI_US]" isMetric="no" class="us-lengths">
2492
+ <name>square mile</name>
2493
+ <property>area</property>
2494
+ <value Unit="[mi_us]2" UNIT="[MI_US]2" value="1">1</value>
2495
+ </unit>
2496
+ <unit Code="[sct]" CODE="[SCT]" isMetric="no" class="us-lengths">
2497
+ <name>section</name>
2498
+ <property>area</property>
2499
+ <value Unit="[mi_us]2" UNIT="[MI_US]2" value="1">1</value>
2500
+ </unit>
2501
+ <unit Code="[twp]" CODE="[TWP]" isMetric="no" class="us-lengths">
2502
+ <name>township</name>
2503
+ <property>area</property>
2504
+ <value Unit="[sct]" UNIT="[SCT]" value="36">36</value>
2505
+ </unit>
2506
+ <unit Code="[mil_us]" CODE="[MIL_US]" isMetric="no" class="us-lengths">
2507
+ <name>mil</name>
2508
+ <property>length</property>
2509
+ <value Unit="[in_us]" UNIT="[IN_US]" value="1e-3">1 &#215; 10<sup>-3</sup>
2510
+ </value>
2511
+ </unit>
2512
+ <unit Code="[in_br]" CODE="[IN_BR]" isMetric="no" class="brit-length">
2513
+ <name>inch</name>
2514
+ <property>length</property>
2515
+ <value Unit="cm" UNIT="CM" value="2.539998">2.539998</value>
2516
+ </unit>
2517
+ <unit Code="[ft_br]" CODE="[FT_BR]" isMetric="no" class="brit-length">
2518
+ <name>foot</name>
2519
+ <property>length</property>
2520
+ <value Unit="[in_br]" UNIT="[IN_BR]" value="12">12</value>
2521
+ </unit>
2522
+ <unit Code="[rd_br]" CODE="[RD_BR]" isMetric="no" class="brit-length">
2523
+ <name>rod</name>
2524
+ <property>length</property>
2525
+ <value Unit="[ft_br]" UNIT="[FT_BR]" value="16.5">16.5</value>
2526
+ </unit>
2527
+ <unit Code="[ch_br]" CODE="[CH_BR]" isMetric="no" class="brit-length">
2528
+ <name>Gunter's chain</name>
2529
+ <property>length</property>
2530
+ <value Unit="[rd_br]" UNIT="[RD_BR]" value="4">4</value>
2531
+ </unit>
2532
+ <unit Code="[lk_br]" CODE="[LK_BR]" isMetric="no" class="brit-length">
2533
+ <name>link for Gunter's chain</name>
2534
+ <property>length</property>
2535
+ <value Unit="[ch_br]/100" UNIT="[CH_BR]/100" value="1">1</value>
2536
+ </unit>
2537
+ <unit Code="[fth_br]" CODE="[FTH_BR]" isMetric="no" class="brit-length">
2538
+ <name>fathom</name>
2539
+ <property>length</property>
2540
+ <value Unit="[ft_br]" UNIT="[FT_BR]" value="6">6</value>
2541
+ </unit>
2542
+ <unit Code="[pc_br]" CODE="[PC_BR]" isMetric="no" class="brit-length">
2543
+ <name>pace</name>
2544
+ <property>length</property>
2545
+ <value Unit="[ft_br]" UNIT="[FT_BR]" value="2.5">2.5</value>
2546
+ </unit>
2547
+ <unit Code="[yd_br]" CODE="[YD_BR]" isMetric="no" class="brit-length">
2548
+ <name>yard</name>
2549
+ <property>length</property>
2550
+ <value Unit="[ft_br]" UNIT="[FT_BR]" value="3">3</value>
2551
+ </unit>
2552
+ <unit Code="[mi_br]" CODE="[MI_BR]" isMetric="no" class="brit-length">
2553
+ <name>mile</name>
2554
+ <property>length</property>
2555
+ <value Unit="[ft_br]" UNIT="[FT_BR]" value="5280">5280</value>
2556
+ </unit>
2557
+ <unit Code="[nmi_br]" CODE="[NMI_BR]" isMetric="no" class="brit-length">
2558
+ <name>nautical mile</name>
2559
+ <property>length</property>
2560
+ <value Unit="[ft_br]" UNIT="[FT_BR]" value="6080">6080</value>
2561
+ </unit>
2562
+ <unit Code="[kn_br]" CODE="[KN_BR]" isMetric="no" class="brit-length">
2563
+ <name>knot</name>
2564
+ <property>velocity</property>
2565
+ <value Unit="[nmi_br]/h" UNIT="[NMI_BR]/H" value="1">1</value>
2566
+ </unit>
2567
+ <unit Code="[acr_br]" CODE="[ACR_BR]" isMetric="no" class="brit-length">
2568
+ <name>acre</name>
2569
+ <property>area</property>
2570
+ <value Unit="[yd_br]2" UNIT="[YD_BR]2" value="4840">4840</value>
2571
+ </unit>
2572
+ <unit Code="[gal_us]" CODE="[GAL_US]" isMetric="no" class="us-volumes">
2573
+ <name>Queen&#160;Anne's wine gallon</name>
2574
+ <property>fluid volume</property>
2575
+ <value Unit="[in_i]3" UNIT="[IN_I]3" value="231">231</value>
2576
+ </unit>
2577
+ <unit Code="[bbl_us]" CODE="[BBL_US]" isMetric="no" class="us-volumes">
2578
+ <name>barrel</name>
2579
+ <property>fluid volume</property>
2580
+ <value Unit="[gal_us]" UNIT="[GAL_US]" value="42">42</value>
2581
+ </unit>
2582
+ <unit Code="[qt_us]" CODE="[QT_US]" isMetric="no" class="us-volumes">
2583
+ <name>quart</name>
2584
+ <property>fluid volume</property>
2585
+ <value Unit="[gal_us]/4" UNIT="[GAL_US]/4" value="1">1</value>
2586
+ </unit>
2587
+ <unit Code="[pt_us]" CODE="[PT_US]" isMetric="no" class="us-volumes">
2588
+ <name>pint</name>
2589
+ <property>fluid volume</property>
2590
+ <value Unit="[qt_us]/2" UNIT="[QT_US]/2" value="1">1</value>
2591
+ </unit>
2592
+ <unit Code="[gil_us]" CODE="[GIL_US]" isMetric="no" class="us-volumes">
2593
+ <name>gill</name>
2594
+ <property>fluid volume</property>
2595
+ <value Unit="[pt_us]/4" UNIT="[PT_US]/4" value="1">1</value>
2596
+ </unit>
2597
+ <unit Code="[foz_us]" CODE="[FOZ_US]" isMetric="no" class="us-volumes">
2598
+ <name>fluid ounce</name>
2599
+ <printSymbol>oz fl</printSymbol>
2600
+ <property>fluid volume</property>
2601
+ <value Unit="[gil_us]/4" UNIT="[GIL_US]/4" value="1">1</value>
2602
+ </unit>
2603
+ <unit Code="[fdr_us]" CODE="[FDR_US]" isMetric="no" class="us-volumes">
2604
+ <name>fluid dram</name>
2605
+ <property>fluid volume</property>
2606
+ <value Unit="[foz_us]/8" UNIT="[FOZ_US]/8" value="1">1</value>
2607
+ </unit>
2608
+ <unit Code="[min_us]" CODE="[MIN_US]" isMetric="no" class="us-volumes">
2609
+ <name>minim</name>
2610
+ <property>fluid volume</property>
2611
+ <value Unit="[fdr_us]/60" UNIT="[FDR_US]/60" value="1">1</value>
2612
+ </unit>
2613
+ <unit Code="[crd_us]" CODE="[CRD_US]" isMetric="no" class="us-volumes">
2614
+ <name>cord</name>
2615
+ <property>fluid volume</property>
2616
+ <value Unit="[ft_i]3" UNIT="[FT_I]3" value="128">128</value>
2617
+ </unit>
2618
+ <unit Code="[bu_us]" CODE="[BU_US]" isMetric="no" class="us-volumes">
2619
+ <name>bushel</name>
2620
+ <property>dry volume</property>
2621
+ <value Unit="[in_i]3" UNIT="[IN_I]3" value="2150.42">2150.42</value>
2622
+ </unit>
2623
+ <unit Code="[gal_wi]" CODE="[GAL_WI]" isMetric="no" class="us-volumes">
2624
+ <name>historical winchester gallon</name>
2625
+ <property>dry volume</property>
2626
+ <value Unit="[bu_us]/8" UNIT="[BU_US]/8" value="1">1</value>
2627
+ </unit>
2628
+ <unit Code="[pk_us]" CODE="[PK_US]" isMetric="no" class="us-volumes">
2629
+ <name>peck</name>
2630
+ <property>dry volume</property>
2631
+ <value Unit="[bu_us]/4" UNIT="[BU_US]/4" value="1">1</value>
2632
+ </unit>
2633
+ <unit Code="[dqt_us]" CODE="[DQT_US]" isMetric="no" class="us-volumes">
2634
+ <name>dry quart</name>
2635
+ <property>dry volume</property>
2636
+ <value Unit="[pk_us]/8" UNIT="[PK_US]/8" value="1">1</value>
2637
+ </unit>
2638
+ <unit Code="[dpt_us]" CODE="[DPT_US]" isMetric="no" class="us-volumes">
2639
+ <name>dry pint</name>
2640
+ <property>dry volume</property>
2641
+ <value Unit="[dqt_us]/2" UNIT="[DQT_US]/2" value="1">1</value>
2642
+ </unit>
2643
+ <unit Code="[tbs_us]" CODE="[TBS_US]" isMetric="no" class="us-volumes">
2644
+ <name>tablespoon</name>
2645
+ <property>volume</property>
2646
+ <value Unit="[foz_us]/2" UNIT="[FOZ_US]/2" value="1">1</value>
2647
+ </unit>
2648
+ <unit Code="[tsp_us]" CODE="[TSP_US]" isMetric="no" class="us-volumes">
2649
+ <name>teaspoon</name>
2650
+ <property>volume</property>
2651
+ <value Unit="[tbs_us]/3" UNIT="[TBS_US]/3" value="1">1</value>
2652
+ </unit>
2653
+ <unit Code="[cup_us]" CODE="[CUP_US]" isMetric="no" class="us-volumes">
2654
+ <name>cup</name>
2655
+ <property>volume</property>
2656
+ <value Unit="[tbs_us]" UNIT="[TBS_US]" value="16">16</value>
2657
+ </unit>
2658
+ <unit Code="[foz_m]" CODE="[FOZ_M]" isMetric="no" class="us-volumes">
2659
+ <name>metric fluid ounce</name>
2660
+ <printSymbol>oz fl</printSymbol>
2661
+ <property>fluid volume</property>
2662
+ <value Unit="mL" UNIT="ML" value="30">30</value>
2663
+ </unit>
2664
+ <unit Code="[cup_m]" CODE="[CUP_M]" isMetric="no" class="us-volumes">
2665
+ <name>metric cup</name>
2666
+ <property>volume</property>
2667
+ <value Unit="mL" UNIT="ML" value="240">240</value>
2668
+ </unit>
2669
+ <unit Code="[tsp_m]" CODE="[TSP_M]" isMetric="no" class="us-volumes">
2670
+ <name>metric teaspoon</name>
2671
+ <property>volume</property>
2672
+ <value Unit="mL" UNIT="mL" value="5">5</value>
2673
+ </unit>
2674
+ <unit Code="[tbs_m]" CODE="[TBS_M]" isMetric="no" class="us-volumes">
2675
+ <name>metric tablespoon</name>
2676
+ <property>volume</property>
2677
+ <value Unit="mL" UNIT="mL" value="15">15</value>
2678
+ </unit>
2679
+ <unit Code="[gal_br]" CODE="[GAL_BR]" isMetric="no" class="brit-volumes">
2680
+ <name>gallon</name>
2681
+ <property>volume</property>
2682
+ <value Unit="l" UNIT="L" value="4.54609">4.54609</value>
2683
+ </unit>
2684
+ <unit Code="[pk_br]" CODE="[PK_BR]" isMetric="no" class="brit-volumes">
2685
+ <name>peck</name>
2686
+ <property>volume</property>
2687
+ <value Unit="[gal_br]" UNIT="[GAL_BR]" value="2">2</value>
2688
+ </unit>
2689
+ <unit Code="[bu_br]" CODE="[BU_BR]" isMetric="no" class="brit-volumes">
2690
+ <name>bushel</name>
2691
+ <property>volume</property>
2692
+ <value Unit="[pk_br]" UNIT="[PK_BR]" value="4">4</value>
2693
+ </unit>
2694
+ <unit Code="[qt_br]" CODE="[QT_BR]" isMetric="no" class="brit-volumes">
2695
+ <name>quart</name>
2696
+ <property>volume</property>
2697
+ <value Unit="[gal_br]/4" UNIT="[GAL_BR]/4" value="1">1</value>
2698
+ </unit>
2699
+ <unit Code="[pt_br]" CODE="[PT_BR]" isMetric="no" class="brit-volumes">
2700
+ <name>pint</name>
2701
+ <property>volume</property>
2702
+ <value Unit="[qt_br]/2" UNIT="[QT_BR]/2" value="1">1</value>
2703
+ </unit>
2704
+ <unit Code="[gil_br]" CODE="[GIL_BR]" isMetric="no" class="brit-volumes">
2705
+ <name>gill</name>
2706
+ <property>volume</property>
2707
+ <value Unit="[pt_br]/4" UNIT="[PT_BR]/4" value="1">1</value>
2708
+ </unit>
2709
+ <unit Code="[foz_br]" CODE="[FOZ_BR]" isMetric="no" class="brit-volumes">
2710
+ <name>fluid ounce</name>
2711
+ <property>volume</property>
2712
+ <value Unit="[gil_br]/5" UNIT="[GIL_BR]/5" value="1">1</value>
2713
+ </unit>
2714
+ <unit Code="[fdr_br]" CODE="[FDR_BR]" isMetric="no" class="brit-volumes">
2715
+ <name>fluid dram</name>
2716
+ <property>volume</property>
2717
+ <value Unit="[foz_br]/8" UNIT="[FOZ_BR]/8" value="1">1</value>
2718
+ </unit>
2719
+ <unit Code="[min_br]" CODE="[MIN_BR]" isMetric="no" class="brit-volumes">
2720
+ <name>minim</name>
2721
+ <property>volume</property>
2722
+ <value Unit="[fdr_br]/60" UNIT="[FDR_BR]/60" value="1">1</value>
2723
+ </unit>
2724
+ <unit Code="[gr]" CODE="[GR]" isMetric="no" class="avoirdupois">
2725
+ <name>grain</name>
2726
+ <property>mass</property>
2727
+ <value Unit="mg" UNIT="MG" value="64.79891">64.79891</value>
2728
+ </unit>
2729
+ <unit Code="[lb_av]" CODE="[LB_AV]" isMetric="no" class="avoirdupois">
2730
+ <name>pound</name>
2731
+ <printSymbol>lb</printSymbol>
2732
+ <property>mass</property>
2733
+ <value Unit="[gr]" UNIT="[GR]" value="7000">7000</value>
2734
+ </unit>
2735
+ <unit Code="[oz_av]" CODE="[OZ_AV]" isMetric="no" class="avoirdupois">
2736
+ <name>ounce</name>
2737
+ <printSymbol>oz</printSymbol>
2738
+ <property>mass</property>
2739
+ <value Unit="[lb_av]/16" UNIT="[LB_AV]/16" value="1">1</value>
2740
+ </unit>
2741
+ <unit Code="[dr_av]" CODE="[DR_AV]" isMetric="no" class="avoirdupois">
2742
+ <name>dram</name>
2743
+ <property>mass</property>
2744
+ <value Unit="[oz_av]/16" UNIT="[OZ_AV]/16" value="1">1</value>
2745
+ </unit>
2746
+ <unit Code="[scwt_av]" CODE="[SCWT_AV]" isMetric="no" class="avoirdupois">
2747
+ <name>short hundredweight</name>
2748
+ <name>U.S. hundredweight</name>
2749
+ <property>mass</property>
2750
+ <value Unit="[lb_av]" UNIT="[LB_AV]" value="100">100</value>
2751
+ </unit>
2752
+ <unit Code="[lcwt_av]" CODE="[LCWT_AV]" isMetric="no" class="avoirdupois">
2753
+ <name>long hundredweight</name>
2754
+ <name>British hundredweight</name>
2755
+ <property>mass</property>
2756
+ <value Unit="[lb_av]" UNIT="[LB_AV]" value="112">112</value>
2757
+ </unit>
2758
+ <unit Code="[ston_av]" CODE="[STON_AV]" isMetric="no" class="avoirdupois">
2759
+ <name>short ton</name>
2760
+ <name>U.S. ton</name>
2761
+ <property>mass</property>
2762
+ <value Unit="[scwt_av]" UNIT="[SCWT_AV]" value="20">20</value>
2763
+ </unit>
2764
+ <unit Code="[lton_av]" CODE="[LTON_AV]" isMetric="no" class="avoirdupois">
2765
+ <name>long ton</name>
2766
+ <name>British ton</name>
2767
+ <property>mass</property>
2768
+ <value Unit="[lcwt_av]" UNIT="[LCWT_AV]" value="20">20</value>
2769
+ </unit>
2770
+ <unit Code="[stone_av]" CODE="[STONE_AV]" isMetric="no" class="avoirdupois">
2771
+ <name>stone</name>
2772
+ <name>British stone</name>
2773
+ <property>mass</property>
2774
+ <value Unit="[lb_av]" UNIT="[LB_AV]" value="14">14</value>
2775
+ </unit>
2776
+ <unit Code="[pwt_tr]" CODE="[PWT_TR]" isMetric="no" class="troy">
2777
+ <name>pennyweight</name>
2778
+ <property>mass</property>
2779
+ <value Unit="[gr]" UNIT="[GR]" value="24">24</value>
2780
+ </unit>
2781
+ <unit Code="[oz_tr]" CODE="[OZ_TR]" isMetric="no" class="troy">
2782
+ <name>ounce</name>
2783
+ <property>mass</property>
2784
+ <value Unit="[pwt_tr]" UNIT="[PWT_TR]" value="20">20</value>
2785
+ </unit>
2786
+ <unit Code="[lb_tr]" CODE="[LB_TR]" isMetric="no" class="troy">
2787
+ <name>pound</name>
2788
+ <property>mass</property>
2789
+ <value Unit="[oz_tr]" UNIT="[OZ_TR]" value="12">12</value>
2790
+ </unit>
2791
+ <unit Code="[sc_ap]" CODE="[SC_AP]" isMetric="no" class="apoth">
2792
+ <name>scruple</name>
2793
+ <property>mass</property>
2794
+ <value Unit="[gr]" UNIT="[GR]" value="20">20</value>
2795
+ </unit>
2796
+ <unit Code="[dr_ap]" CODE="[DR_AP]" isMetric="no" class="apoth">
2797
+ <name>dram</name>
2798
+ <name>drachm</name>
2799
+ <property>mass</property>
2800
+ <value Unit="[sc_ap]" UNIT="[SC_AP]" value="3">3</value>
2801
+ </unit>
2802
+ <unit Code="[oz_ap]" CODE="[OZ_AP]" isMetric="no" class="apoth">
2803
+ <name>ounce</name>
2804
+ <property>mass</property>
2805
+ <value Unit="[dr_ap]" UNIT="[DR_AP]" value="8">8</value>
2806
+ </unit>
2807
+ <unit Code="[lb_ap]" CODE="[LB_AP]" isMetric="no" class="apoth">
2808
+ <name>pound</name>
2809
+ <property>mass</property>
2810
+ <value Unit="[oz_ap]" UNIT="[OZ_AP]" value="12">12</value>
2811
+ </unit>
2812
+ <unit Code="[oz_m]" CODE="[OZ_M]" isMetric="no" class="apoth">
2813
+ <name>metric ounce</name>
2814
+ <property>mass</property>
2815
+ <value Unit="g" UNIT="g" value="28">28</value>
2816
+ </unit>
2817
+ <unit Code="[lne]" CODE="[LNE]" isMetric="no" class="typeset">
2818
+ <name>line</name>
2819
+ <property>length</property>
2820
+ <value Unit="[in_i]/12" UNIT="[IN_I]/12" value="1">1</value>
2821
+ </unit>
2822
+ <unit Code="[pnt]" CODE="[PNT]" isMetric="no" class="typeset">
2823
+ <name>point</name>
2824
+ <property>length</property>
2825
+ <value Unit="[lne]/6" UNIT="[LNE]/6" value="1">1</value>
2826
+ </unit>
2827
+ <unit Code="[pca]" CODE="[PCA]" isMetric="no" class="typeset">
2828
+ <name>pica</name>
2829
+ <property>length</property>
2830
+ <value Unit="[pnt]" UNIT="[PNT]" value="12">12</value>
2831
+ </unit>
2832
+ <unit Code="[pnt_pr]" CODE="[PNT_PR]" isMetric="no" class="typeset">
2833
+ <name>Printer's point</name>
2834
+ <property>length</property>
2835
+ <value Unit="[in_i]" UNIT="[IN_I]" value="0.013837">0.013837</value>
2836
+ </unit>
2837
+ <unit Code="[pca_pr]" CODE="[PCA_PR]" isMetric="no" class="typeset">
2838
+ <name>Printer's pica</name>
2839
+ <property>length</property>
2840
+ <value Unit="[pnt_pr]" UNIT="[PNT_PR]" value="12">12</value>
2841
+ </unit>
2842
+ <unit Code="[pied]" CODE="[PIED]" isMetric="no" class="typeset">
2843
+ <name>pied</name>
2844
+ <name>French foot</name>
2845
+ <property>length</property>
2846
+ <value Unit="cm" UNIT="CM" value="32.48">32.48</value>
2847
+ </unit>
2848
+ <unit Code="[pouce]" CODE="[POUCE]" isMetric="no" class="typeset">
2849
+ <name>pouce</name>
2850
+ <name>French inch</name>
2851
+ <property>length</property>
2852
+ <value Unit="[pied]/12" UNIT="[PIED]/12" value="1">1</value>
2853
+ </unit>
2854
+ <unit Code="[ligne]" CODE="[LIGNE]" isMetric="no" class="typeset">
2855
+ <name>ligne</name>
2856
+ <name>French line</name>
2857
+ <property>length</property>
2858
+ <value Unit="[pouce]/12" UNIT="[POUCE]/12" value="1">1</value>
2859
+ </unit>
2860
+ <unit Code="[didot]" CODE="[DIDOT]" isMetric="no" class="typeset">
2861
+ <name>didot</name>
2862
+ <name>Didot's point</name>
2863
+ <property>length</property>
2864
+ <value Unit="[ligne]/6" UNIT="[LIGNE]/6" value="1">1</value>
2865
+ </unit>
2866
+ <unit Code="[cicero]" CODE="[CICERO]" isMetric="no" class="typeset">
2867
+ <name>cicero</name>
2868
+ <name>Didot's pica</name>
2869
+ <property>length</property>
2870
+ <value Unit="[didot]" UNIT="[DIDOT]" value="12">12</value>
2871
+ </unit>
2872
+ <unit Code="[degF]" CODE="[DEGF]" isMetric="no" isSpecial="yes" class="heat">
2873
+ <name>degree Fahrenheit</name>
2874
+ <printSymbol>&#176;F</printSymbol>
2875
+ <property>temperature</property>
2876
+ <value Unit="degf(5 K/9)" UNIT="DEGF(5 K/9)">
2877
+ <function name="degF" value="5" Unit="K/9"/>
2878
+ </value>
2879
+ </unit>
2880
+ <unit Code="[degR]" CODE="[degR]" isMetric="no" class="heat">
2881
+ <name>degree Rankine</name>
2882
+ <printSymbol>&#176;R</printSymbol>
2883
+ <property>temperature</property>
2884
+ <value value="5" Unit="K/9" UNIT="K/9">5</value>
2885
+ </unit>
2886
+ <unit Code="[degRe]" CODE="[degRe]" isMetric="no" isSpecial="yes" class="heat">
2887
+ <name>degree R&#233;aumur</name>
2888
+ <printSymbol>&#176;R&#233;</printSymbol>
2889
+ <property>temperature</property>
2890
+ <value Unit="degre(5 K/4)" UNIT="DEGRE(5 K/4)">
2891
+ <function name="degRe" value="5" Unit="K/4"/>
2892
+ </value>
2893
+ </unit>
2894
+ <unit Code="cal_[15]" CODE="CAL_[15]" isMetric="yes" class="heat">
2895
+ <name>calorie at 15&#160;&#176;C</name>
2896
+ <printSymbol>cal<sub>15&#176;C</sub>
2897
+ </printSymbol>
2898
+ <property>energy</property>
2899
+ <value Unit="J" UNIT="J" value="4.18580">4.18580</value>
2900
+ </unit>
2901
+ <unit Code="cal_[20]" CODE="CAL_[20]" isMetric="yes" class="heat">
2902
+ <name>calorie at 20&#160;&#176;C</name>
2903
+ <printSymbol>cal<sub>20&#176;C</sub>
2904
+ </printSymbol>
2905
+ <property>energy</property>
2906
+ <value Unit="J" UNIT="J" value="4.18190">4.18190</value>
2907
+ </unit>
2908
+ <unit Code="cal_m" CODE="CAL_M" isMetric="yes" class="heat">
2909
+ <name>mean calorie</name>
2910
+ <printSymbol>cal<sub>m</sub>
2911
+ </printSymbol>
2912
+ <property>energy</property>
2913
+ <value Unit="J" UNIT="J" value="4.19002">4.19002</value>
2914
+ </unit>
2915
+ <unit Code="cal_IT" CODE="CAL_IT" isMetric="yes" class="heat">
2916
+ <name>international table calorie</name>
2917
+ <printSymbol>cal<sub>IT</sub>
2918
+ </printSymbol>
2919
+ <property>energy</property>
2920
+ <value Unit="J" UNIT="J" value="4.1868">4.1868</value>
2921
+ </unit>
2922
+ <unit Code="cal_th" CODE="CAL_TH" isMetric="yes" class="heat">
2923
+ <name>thermochemical calorie</name>
2924
+ <printSymbol>cal<sub>th</sub>
2925
+ </printSymbol>
2926
+ <property>energy</property>
2927
+ <value Unit="J" UNIT="J" value="4.184">4.184</value>
2928
+ </unit>
2929
+ <unit Code="cal" CODE="CAL" isMetric="yes" class="heat">
2930
+ <name>calorie</name>
2931
+ <printSymbol>cal</printSymbol>
2932
+ <property>energy</property>
2933
+ <value Unit="cal_th" UNIT="CAL_TH" value="1">1</value>
2934
+ </unit>
2935
+ <unit Code="[Cal]" CODE="[CAL]" isMetric="no" class="heat">
2936
+ <name>nutrition label Calories</name>
2937
+ <printSymbol>Cal</printSymbol>
2938
+ <property>energy</property>
2939
+ <value Unit="kcal_th" UNIT="KCAL_TH" value="1">1</value>
2940
+ </unit>
2941
+ <unit Code="[Btu_39]" CODE="[BTU_39]" isMetric="no" class="heat">
2942
+ <name>British thermal unit at 39&#160;&#176;F</name>
2943
+ <printSymbol>Btu<sub>39&#176;F</sub>
2944
+ </printSymbol>
2945
+ <property>energy</property>
2946
+ <value Unit="kJ" UNIT="kJ" value="1.05967">1.05967</value>
2947
+ </unit>
2948
+ <unit Code="[Btu_59]" CODE="[BTU_59]" isMetric="no" class="heat">
2949
+ <name>British thermal unit at 59&#160;&#176;F</name>
2950
+ <printSymbol>Btu<sub>59&#176;F</sub>
2951
+ </printSymbol>
2952
+ <property>energy</property>
2953
+ <value Unit="kJ" UNIT="kJ" value="1.05480">1.05480</value>
2954
+ </unit>
2955
+ <unit Code="[Btu_60]" CODE="[BTU_60]" isMetric="no" class="heat">
2956
+ <name>British thermal unit at 60&#160;&#176;F</name>
2957
+ <printSymbol>Btu<sub>60&#176;F</sub>
2958
+ </printSymbol>
2959
+ <property>energy</property>
2960
+ <value Unit="kJ" UNIT="kJ" value="1.05468">1.05468</value>
2961
+ </unit>
2962
+ <unit Code="[Btu_m]" CODE="[BTU_M]" isMetric="no" class="heat">
2963
+ <name>mean British thermal unit</name>
2964
+ <printSymbol>Btu<sub>m</sub>
2965
+ </printSymbol>
2966
+ <property>energy</property>
2967
+ <value Unit="kJ" UNIT="kJ" value="1.05587">1.05587</value>
2968
+ </unit>
2969
+ <unit Code="[Btu_IT]" CODE="[BTU_IT]" isMetric="no" class="heat">
2970
+ <name>international table British thermal unit</name>
2971
+ <printSymbol>Btu<sub>IT</sub>
2972
+ </printSymbol>
2973
+ <property>energy</property>
2974
+ <value Unit="kJ" UNIT="kJ" value="1.05505585262">1.05505585262</value>
2975
+ </unit>
2976
+ <unit Code="[Btu_th]" CODE="[BTU_TH]" isMetric="no" class="heat">
2977
+ <name>thermochemical British thermal unit</name>
2978
+ <printSymbol>Btu<sub>th</sub>
2979
+ </printSymbol>
2980
+ <property>energy</property>
2981
+ <value Unit="kJ" UNIT="kJ" value="1.054350">1.054350</value>
2982
+ </unit>
2983
+ <unit Code="[Btu]" CODE="[BTU]" isMetric="no" class="heat">
2984
+ <name>British thermal unit</name>
2985
+ <printSymbol>btu</printSymbol>
2986
+ <property>energy</property>
2987
+ <value Unit="[Btu_th]" UNIT="[BTU_TH]" value="1">1</value>
2988
+ </unit>
2989
+ <unit Code="[HP]" CODE="[HP]" isMetric="no" class="heat">
2990
+ <name>horsepower</name>
2991
+ <property>power</property>
2992
+ <value Unit="[ft_i].[lbf_av]/s" UNIT="[FT_I].[LBF_AV]/S" value="550">550</value>
2993
+ </unit>
2994
+ <unit Code="tex" CODE="TEX" isMetric="yes" class="heat">
2995
+ <name>tex</name>
2996
+ <printSymbol>tex</printSymbol>
2997
+ <property>linear mass density (of textile thread)</property>
2998
+ <value value="1" Unit="g/km" UNIT="G/KM">1</value>
2999
+ </unit>
3000
+ <unit Code="[den]" CODE="[DEN]" isMetric="no" class="heat">
3001
+ <name>Denier</name>
3002
+ <printSymbol>den</printSymbol>
3003
+ <property>linear mass density (of textile thread)</property>
3004
+ <value value="1" Unit="g/9/km" UNIT="G/9/KM">1</value>
3005
+ </unit>
3006
+ <unit Code="m[H2O]" CODE="M[H2O]" isMetric="yes" class="clinical">
3007
+ <name>meter of water column</name>
3008
+ <printSymbol>m&#160;H<sub>
3009
+ <r>2</r>
3010
+ </sub>O</printSymbol>
3011
+ <property>pressure</property>
3012
+ <value Unit="kPa" UNIT="KPAL" value="980665e-5">9.80665</value>
3013
+ </unit>
3014
+ <unit Code="m[Hg]" CODE="M[HG]" isMetric="yes" class="clinical">
3015
+ <name>meter of mercury column</name>
3016
+ <printSymbol>m&#160;Hg</printSymbol>
3017
+ <property>pressure</property>
3018
+ <value Unit="kPa" UNIT="KPAL" value="133.3220">133.3220</value>
3019
+ </unit>
3020
+ <unit Code="[in_i'H2O]" CODE="[IN_I'H2O]" isMetric="no" class="clinical">
3021
+ <name>inch of water column</name>
3022
+ <printSymbol>in&#160;H<sub>
3023
+ <r>2</r>
3024
+ </sub>O</printSymbol>
3025
+ <property>pressure</property>
3026
+ <value Unit="m[H2O].[in_i]/m" UNIT="M[H2O].[IN_I]/M" value="1">1</value>
3027
+ </unit>
3028
+ <unit Code="[in_i'Hg]" CODE="[IN_I'HG]" isMetric="no" class="clinical">
3029
+ <name>inch of mercury column</name>
3030
+ <printSymbol>in&#160;Hg</printSymbol>
3031
+ <property>pressure</property>
3032
+ <value Unit="m[Hg].[in_i]/m" UNIT="M[HG].[IN_I]/M" value="1">1</value>
3033
+ </unit>
3034
+ <unit Code="[PRU]" CODE="[PRU]" isMetric="no" class="clinical">
3035
+ <name>peripheral vascular resistance unit</name>
3036
+ <printSymbol>P.R.U.</printSymbol>
3037
+ <property>fluid resistance</property>
3038
+ <value Unit="mm[Hg].s/ml" UNIT="MM[HG].S/ML" value="1">1</value>
3039
+ </unit>
3040
+ <unit Code="[wood'U]" CODE="[WOOD'U]" isMetric="no" class="clinical">
3041
+ <name>Wood unit</name>
3042
+ <printSymbol>Wood U.</printSymbol>
3043
+ <property>fluid resistance</property>
3044
+ <value Unit="mm[Hg].min/L" UNIT="MM[HG].MIN/L" value="1">1</value>
3045
+ </unit>
3046
+ <unit Code="[diop]" CODE="[DIOP]" isMetric="no" class="clinical">
3047
+ <name>diopter</name>
3048
+ <printSymbol>dpt</printSymbol>
3049
+ <property>refraction of a lens</property>
3050
+ <value Unit="/m" UNIT="/M" value="1">1</value>
3051
+ </unit>
3052
+ <unit Code="[p'diop]" CODE="[P'DIOP]" isMetric="no" isSpecial="yes" class="clinical">
3053
+ <name>prism diopter</name>
3054
+ <printSymbol>PD</printSymbol>
3055
+ <property>refraction of a prism</property>
3056
+ <value Unit="100tan(1 rad)" UNIT="100TAN(1 RAD)">
3057
+ <function name="tanTimes100" value="1" Unit="rad"/>
3058
+ </value>
3059
+ </unit>
3060
+ <unit Code="%[slope]" CODE="%[SLOPE]" isMetric="no" isSpecial="yes" class="clinical">
3061
+ <name>percent of slope</name>
3062
+ <printSymbol>%</printSymbol>
3063
+ <property>slope</property>
3064
+ <value Unit="100tan(1 rad)" UNIT="100TAN(1 RAD)">
3065
+ <function name="100tan" value="1" Unit="deg"/>
3066
+ </value>
3067
+ </unit>
3068
+ <unit Code="[mesh_i]" CODE="[MESH_I]" isMetric="no" class="clinical">
3069
+ <name>mesh</name>
3070
+ <property>lineic number</property>
3071
+ <value Unit="/[in_i]" UNIT="/[IN_I]" value="1">1</value>
3072
+ </unit>
3073
+ <unit Code="[Ch]" CODE="[CH]" isMetric="no" class="clinical">
3074
+ <name>Charri&#232;re</name>
3075
+ <name>french</name>
3076
+ <printSymbol>Ch</printSymbol>
3077
+ <property>gauge of catheters</property>
3078
+ <value Unit="mm/3" UNIT="MM/3" value="1">1</value>
3079
+ </unit>
3080
+ <unit Code="[drp]" CODE="[DRP]" isMetric="no" class="clinical">
3081
+ <name>drop</name>
3082
+ <printSymbol>drp</printSymbol>
3083
+ <property>volume</property>
3084
+ <value Unit="ml/20" UNIT="ML/20" value="1">1</value>
3085
+ </unit>
3086
+ <unit Code="[hnsf'U]" CODE="[HNSF'U]" isMetric="no" class="clinical">
3087
+ <name>Hounsfield unit</name>
3088
+ <printSymbol>HF</printSymbol>
3089
+ <property>x-ray attenuation</property>
3090
+ <value Unit="1" UNIT="1" value="1">1</value>
3091
+ </unit>
3092
+ <unit Code="[MET]" CODE="[MET]" isMetric="no" class="clinical">
3093
+ <name>metabolic equivalent</name>
3094
+ <printSymbol>MET</printSymbol>
3095
+ <property>metabolic cost of physical activity</property>
3096
+ <value Unit="mL/min/kg" UNIT="ML/MIN/KG" value="3.5">3.5</value>
3097
+ </unit>
3098
+ <unit Code="[hp'_X]" CODE="[HP'_X]" isMetric="no" isSpecial="yes" class="clinical">
3099
+ <name>homeopathic potency of decimal series (retired)</name>
3100
+ <printSymbol>X</printSymbol>
3101
+ <property>homeopathic potency (retired)</property>
3102
+ <value Unit="hpX(1 1)" UNIT="HPX(1 1)">
3103
+ <function name="hpX" value="1" Unit="1"/>
3104
+ </value>
3105
+ </unit>
3106
+ <unit Code="[hp'_C]" CODE="[HP'_C]" isMetric="no" isSpecial="yes" class="clinical">
3107
+ <name>homeopathic potency of centesimal series (retired)</name>
3108
+ <printSymbol>C</printSymbol>
3109
+ <property>homeopathic potency (retired)</property>
3110
+ <value Unit="hpC(1 1)" UNIT="HPC(1 1)">
3111
+ <function name="hpC" value="1" Unit="1"/>
3112
+ </value>
3113
+ </unit>
3114
+ <unit Code="[hp'_M]" CODE="[HP'_M]" isMetric="no" isSpecial="yes" class="clinical">
3115
+ <name>homeopathic potency of millesimal series (retired)</name>
3116
+ <printSymbol>M</printSymbol>
3117
+ <property>homeopathic potency (retired)</property>
3118
+ <value Unit="hpM(1 1)" UNIT="HPM(1 1)">
3119
+ <function name="hpM" value="1" Unit="1"/>
3120
+ </value>
3121
+ </unit>
3122
+ <unit Code="[hp'_Q]" CODE="[HP'_Q]" isMetric="no" isSpecial="yes" class="clinical">
3123
+ <name>homeopathic potency of quintamillesimal series (retired)</name>
3124
+ <printSymbol>Q</printSymbol>
3125
+ <property>homeopathic potency (retired)</property>
3126
+ <value Unit="hpQ(1 1)" UNIT="HPQ(1 1)">
3127
+ <function name="hpQ" value="1" Unit="1"/>
3128
+ </value>
3129
+ </unit>
3130
+ <unit Code="[hp_X]" CODE="[HP_X]" isMetric="no" isArbitrary="yes" class="clinical">
3131
+ <name>homeopathic potency of decimal hahnemannian series</name>
3132
+ <printSymbol>X</printSymbol>
3133
+ <property>homeopathic potency (Hahnemann)</property>
3134
+ <value Unit="1" UNIT="1" value="1">1</value>
3135
+ </unit>
3136
+ <unit Code="[hp_C]" CODE="[HP_C]" isMetric="no" isArbitrary="yes" class="clinical">
3137
+ <name>homeopathic potency of centesimal hahnemannian series</name>
3138
+ <printSymbol>C</printSymbol>
3139
+ <property>homeopathic potency (Hahnemann)</property>
3140
+ <value Unit="1" UNIT="1" value="1">1</value>
3141
+ </unit>
3142
+ <unit Code="[hp_M]" CODE="[HP_M]" isMetric="no" isArbitrary="yes" class="clinical">
3143
+ <name>homeopathic potency of millesimal hahnemannian series</name>
3144
+ <printSymbol>M</printSymbol>
3145
+ <property>homeopathic potency (Hahnemann)</property>
3146
+ <value Unit="1" UNIT="1" value="1">1</value>
3147
+ </unit>
3148
+ <unit Code="[hp_Q]" CODE="[HP_Q]" isMetric="no" isArbitrary="yes" class="clinical">
3149
+ <name>homeopathic potency of quintamillesimal hahnemannian series</name>
3150
+ <printSymbol>Q</printSymbol>
3151
+ <property>homeopathic potency (Hahnemann)</property>
3152
+ <value Unit="1" UNIT="1" value="1">1</value>
3153
+ </unit>
3154
+ <unit Code="[kp_X]" CODE="[KP_X]" isMetric="no" isArbitrary="yes" class="clinical">
3155
+ <name>homeopathic potency of decimal korsakovian series</name>
3156
+ <printSymbol>X</printSymbol>
3157
+ <property>homeopathic potency (Korsakov)</property>
3158
+ <value Unit="1" UNIT="1" value="1">1</value>
3159
+ </unit>
3160
+ <unit Code="[kp_C]" CODE="[KP_C]" isMetric="no" isArbitrary="yes" class="clinical">
3161
+ <name>homeopathic potency of centesimal korsakovian series</name>
3162
+ <printSymbol>C</printSymbol>
3163
+ <property>homeopathic potency (Korsakov)</property>
3164
+ <value Unit="1" UNIT="1" value="1">1</value>
3165
+ </unit>
3166
+ <unit Code="[kp_M]" CODE="[KP_M]" isMetric="no" isArbitrary="yes" class="clinical">
3167
+ <name>homeopathic potency of millesimal korsakovian series</name>
3168
+ <printSymbol>M</printSymbol>
3169
+ <property>homeopathic potency (Korsakov)</property>
3170
+ <value Unit="1" UNIT="1" value="1">1</value>
3171
+ </unit>
3172
+ <unit Code="[kp_Q]" CODE="[KP_Q]" isMetric="no" isArbitrary="yes" class="clinical">
3173
+ <name>homeopathic potency of quintamillesimal korsakovian series</name>
3174
+ <printSymbol>Q</printSymbol>
3175
+ <property>homeopathic potency (Korsakov)</property>
3176
+ <value Unit="1" UNIT="1" value="1">1</value>
3177
+ </unit>
3178
+ <unit Code="eq" CODE="EQ" isMetric="yes" class="chemical">
3179
+ <name>equivalents</name>
3180
+ <printSymbol>eq</printSymbol>
3181
+ <property>amount of substance</property>
3182
+ <value Unit="mol" UNIT="MOL" value="1">1</value>
3183
+ </unit>
3184
+ <unit Code="osm" CODE="OSM" isMetric="yes" class="chemical">
3185
+ <name>osmole</name>
3186
+ <printSymbol>osm</printSymbol>
3187
+ <property>amount of substance (dissolved particles)</property>
3188
+ <value Unit="mol" UNIT="MOL" value="1">1</value>
3189
+ </unit>
3190
+ <unit Code="[pH]" CODE="[PH]" isMetric="no" isSpecial="yes" class="chemical">
3191
+ <name>pH</name>
3192
+ <printSymbol>pH</printSymbol>
3193
+ <property>acidity</property>
3194
+ <value Unit="pH(1 mol/l)" UNIT="PH(1 MOL/L)">
3195
+ <function name="pH" value="1" Unit="mol/l"/>
3196
+ </value>
3197
+ </unit>
3198
+ <unit Code="g%" CODE="G%" isMetric="yes" class="chemical">
3199
+ <name>gram percent</name>
3200
+ <printSymbol>g%</printSymbol>
3201
+ <property>mass concentration</property>
3202
+ <value Unit="g/dl" UNIT="G/DL" value="1">1</value>
3203
+ </unit>
3204
+ <unit Code="[S]" CODE="[S]" isMetric="no" class="chemical">
3205
+ <name>Svedberg unit</name>
3206
+ <printSymbol>S</printSymbol>
3207
+ <property>sedimentation coefficient</property>
3208
+ <value Unit="10*-13.s" UNIT="10*-13.S" value="1">1</value>
3209
+ </unit>
3210
+ <unit Code="[HPF]" CODE="[HPF]" isMetric="no" class="chemical">
3211
+ <name>high power field</name>
3212
+ <printSymbol>HPF</printSymbol>
3213
+ <property>view area in microscope</property>
3214
+ <value Unit="1" UNIT="1" value="1">1</value>
3215
+ </unit>
3216
+ <unit Code="[LPF]" CODE="[LPF]" isMetric="no" class="chemical">
3217
+ <name>low power field</name>
3218
+ <printSymbol>LPF</printSymbol>
3219
+ <property>view area in microscope</property>
3220
+ <value Unit="1" UNIT="1" value="100">100</value>
3221
+ </unit>
3222
+ <unit Code="kat" CODE="KAT" isMetric="yes" class="chemical">
3223
+ <name>katal</name>
3224
+ <printSymbol>kat</printSymbol>
3225
+ <property>catalytic activity</property>
3226
+ <value Unit="mol/s" UNIT="MOL/S" value="1">1</value>
3227
+ </unit>
3228
+ <unit Code="U" CODE="U" isMetric="yes" class="chemical">
3229
+ <name>Unit</name>
3230
+ <printSymbol>U</printSymbol>
3231
+ <property>catalytic activity</property>
3232
+ <value Unit="umol/min" UNIT="UMOL/MIN" value="1">1</value>
3233
+ </unit>
3234
+ <unit Code="[iU]" CODE="[IU]" isMetric="yes" isArbitrary="yes" class="chemical">
3235
+ <name>international unit</name>
3236
+ <printSymbol>IU</printSymbol>
3237
+ <property>arbitrary</property>
3238
+ <value Unit="1" UNIT="1" value="1">1</value>
3239
+ </unit>
3240
+ <unit Code="[IU]" CODE="[IU]" isMetric="yes" isArbitrary="yes" class="chemical">
3241
+ <name>international unit</name>
3242
+ <printSymbol>i.U.</printSymbol>
3243
+ <property>arbitrary</property>
3244
+ <value Unit="[iU]" UNIT="[IU]" value="1">1</value>
3245
+ </unit>
3246
+ <unit Code="[arb'U]" CODE="[ARB'U]" isMetric="no" isArbitrary="yes" class="chemical">
3247
+ <name>arbitrary unit</name>
3248
+ <printSymbol>arb. U</printSymbol>
3249
+ <property>arbitrary</property>
3250
+ <value Unit="1" UNIT="1" value="1">1</value>
3251
+ </unit>
3252
+ <unit Code="[USP'U]" CODE="[USP'U]" isMetric="no" isArbitrary="yes" class="chemical">
3253
+ <name>United States Pharmacopeia unit</name>
3254
+ <printSymbol>U.S.P.</printSymbol>
3255
+ <property>arbitrary</property>
3256
+ <value Unit="1" UNIT="1" value="1">1</value>
3257
+ </unit>
3258
+ <unit Code="[GPL'U]" CODE="[GPL'U]" isMetric="no" isArbitrary="yes" class="chemical">
3259
+ <name>GPL unit</name>
3260
+ <property>biologic activity of anticardiolipin IgG</property>
3261
+ <value Unit="1" UNIT="1" value="1">1</value>
3262
+ </unit>
3263
+ <unit Code="[MPL'U]" CODE="[MPL'U]" isMetric="no" isArbitrary="yes" class="chemical">
3264
+ <name>MPL unit</name>
3265
+ <property>biologic activity of anticardiolipin IgM</property>
3266
+ <value Unit="1" UNIT="1" value="1">1</value>
3267
+ </unit>
3268
+ <unit Code="[APL'U]" CODE="[APL'U]" isMetric="no" isArbitrary="yes" class="chemical">
3269
+ <name>APL unit</name>
3270
+ <property>biologic activity of anticardiolipin IgA</property>
3271
+ <value Unit="1" UNIT="1" value="1">1</value>
3272
+ </unit>
3273
+ <unit Code="[beth'U]" CODE="[BETH'U]" isMetric="no" isArbitrary="yes"
3274
+ class="chemical">
3275
+ <name>Bethesda unit</name>
3276
+ <property>biologic activity of factor VIII inhibitor</property>
3277
+ <value Unit="1" UNIT="1" value="1">1</value>
3278
+ </unit>
3279
+ <unit Code="[anti'Xa'U]" CODE="[ANTI'XA'U]" isMetric="no" isArbitrary="yes"
3280
+ class="chemical">
3281
+ <name>anti factor Xa unit</name>
3282
+ <property>biologic activity of factor Xa inhibitor (heparin)</property>
3283
+ <value Unit="1" UNIT="1" value="1">1</value>
3284
+ </unit>
3285
+ <unit Code="[todd'U]" CODE="[TODD'U]" isMetric="no" isArbitrary="yes"
3286
+ class="chemical">
3287
+ <name>Todd unit</name>
3288
+ <property>biologic activity antistreptolysin O</property>
3289
+ <value Unit="1" UNIT="1" value="1">1</value>
3290
+ </unit>
3291
+ <unit Code="[dye'U]" CODE="[DYE'U]" isMetric="no" isArbitrary="yes" class="chemical">
3292
+ <name>Dye unit</name>
3293
+ <property>biologic activity of amylase</property>
3294
+ <value Unit="1" UNIT="1" value="1">1</value>
3295
+ </unit>
3296
+ <unit Code="[smgy'U]" CODE="[SMGY'U]" isMetric="no" isArbitrary="yes"
3297
+ class="chemical">
3298
+ <name>Somogyi unit</name>
3299
+ <property>biologic activity of amylase</property>
3300
+ <value Unit="1" UNIT="1" value="1">1</value>
3301
+ </unit>
3302
+ <unit Code="[bdsk'U]" CODE="[BDSK'U]" isMetric="no" isArbitrary="yes"
3303
+ class="chemical">
3304
+ <name>Bodansky unit</name>
3305
+ <property>biologic activity of phosphatase</property>
3306
+ <value Unit="1" UNIT="1" value="1">1</value>
3307
+ </unit>
3308
+ <unit Code="[ka'U]" CODE="[KA'U]" isMetric="no" isArbitrary="yes" class="chemical">
3309
+ <name>King-Armstrong unit</name>
3310
+ <property>biologic activity of phosphatase</property>
3311
+ <value Unit="1" UNIT="1" value="1">1</value>
3312
+ </unit>
3313
+ <unit Code="[knk'U]" CODE="[KNK'U]" isMetric="no" isArbitrary="yes" class="chemical">
3314
+ <name>Kunkel unit</name>
3315
+ <property>arbitrary biologic activity</property>
3316
+ <value Unit="1" UNIT="1" value="1">1</value>
3317
+ </unit>
3318
+ <unit Code="[mclg'U]" CODE="[MCLG'U]" isMetric="no" isArbitrary="yes"
3319
+ class="chemical">
3320
+ <name>Mac Lagan unit</name>
3321
+ <property>arbitrary biologic activity</property>
3322
+ <value Unit="1" UNIT="1" value="1">1</value>
3323
+ </unit>
3324
+ <unit Code="[tb'U]" CODE="[TB'U]" isMetric="no" isArbitrary="yes" class="chemical">
3325
+ <name>tuberculin unit</name>
3326
+ <property>biologic activity of tuberculin</property>
3327
+ <value Unit="1" UNIT="1" value="1">1</value>
3328
+ </unit>
3329
+ <unit Code="[CCID_50]" CODE="[CCID_50]" isMetric="no" isArbitrary="yes"
3330
+ class="chemical">
3331
+ <name>50% cell culture infectious dose</name>
3332
+ <printSymbol>CCID<sub>50</sub>
3333
+ </printSymbol>
3334
+ <property>biologic activity (infectivity) of an infectious agent preparation</property>
3335
+ <value Unit="1" UNIT="1" value="1">1</value>
3336
+ </unit>
3337
+ <unit Code="[TCID_50]" CODE="[TCID_50]" isMetric="no" isArbitrary="yes"
3338
+ class="chemical">
3339
+ <name>50% tissue culture infectious dose</name>
3340
+ <printSymbol>TCID<sub>50</sub>
3341
+ </printSymbol>
3342
+ <property>biologic activity (infectivity) of an infectious agent preparation</property>
3343
+ <value Unit="1" UNIT="1" value="1">1</value>
3344
+ </unit>
3345
+ <unit Code="[EID_50]" CODE="[EID_50]" isMetric="no" isArbitrary="yes"
3346
+ class="chemical">
3347
+ <name>50% embryo infectious dose</name>
3348
+ <printSymbol>EID<sub>50</sub>
3349
+ </printSymbol>
3350
+ <property>biologic activity (infectivity) of an infectious agent preparation</property>
3351
+ <value Unit="1" UNIT="1" value="1">1</value>
3352
+ </unit>
3353
+ <unit Code="[PFU]" CODE="[PFU]" isMetric="no" isArbitrary="yes" class="chemical">
3354
+ <name>plaque forming units</name>
3355
+ <printSymbol>PFU</printSymbol>
3356
+ <property>amount of an infectious agent</property>
3357
+ <value Unit="1" UNIT="1" value="1">1</value>
3358
+ </unit>
3359
+ <unit Code="[FFU]" CODE="[FFU]" isMetric="no" isArbitrary="yes" class="chemical">
3360
+ <name>focus forming units</name>
3361
+ <printSymbol>FFU</printSymbol>
3362
+ <property>amount of an infectious agent</property>
3363
+ <value Unit="1" UNIT="1" value="1">1</value>
3364
+ </unit>
3365
+ <unit Code="[CFU]" CODE="[CFU]" isMetric="no" isArbitrary="yes" class="chemical">
3366
+ <name>colony forming units</name>
3367
+ <printSymbol>CFU</printSymbol>
3368
+ <property>amount of a proliferating organism</property>
3369
+ <value Unit="1" UNIT="1" value="1">1</value>
3370
+ </unit>
3371
+ <unit Code="[IR]" CODE="[IR]" isMetric="no" isArbitrary="yes" class="chemical">
3372
+ <name>index of reactivity</name>
3373
+ <printSymbol>IR</printSymbol>
3374
+ <property>amount of an allergen calibrated through in-vivo testing using the Stallergenes&#174; method</property>
3375
+ <value Unit="1" UNIT="1" value="1">1</value>
3376
+ </unit>
3377
+ <unit Code="[BAU]" CODE="[BAU]" isMetric="no" isArbitrary="yes" class="chemical">
3378
+ <name>bioequivalent allergen unit</name>
3379
+ <printSymbol>BAU</printSymbol>
3380
+ <property>amount of an allergen calibrated through in-vivo testing based on the ID50EAL method of (intradermal dilution for 50mm sum of erythema diameters</property>
3381
+ <value Unit="1" UNIT="1" value="1">1</value>
3382
+ </unit>
3383
+ <unit Code="[AU]" CODE="[AU]" isMetric="no" isArbitrary="yes" class="chemical">
3384
+ <name>allergen unit</name>
3385
+ <printSymbol>AU</printSymbol>
3386
+ <property>procedure defined amount of an allergen using some reference standard</property>
3387
+ <value Unit="1" UNIT="1" value="1">1</value>
3388
+ </unit>
3389
+ <unit Code="[Amb'a'1'U]" CODE="[AMB'A'1'U]" isMetric="no" isArbitrary="yes"
3390
+ class="chemical">
3391
+ <name>allergen unit for Ambrosia artemisiifolia</name>
3392
+ <printSymbol>Amb a 1 U</printSymbol>
3393
+ <property>procedure defined amount of the major allergen of ragweed</property>
3394
+ <value Unit="1" UNIT="1" value="1">1</value>
3395
+ </unit>
3396
+ <unit Code="[PNU]" CODE="[PNU]" isMetric="no" isArbitrary="yes" class="chemical">
3397
+ <name>protein nitrogen unit</name>
3398
+ <printSymbol>PNU</printSymbol>
3399
+ <property>procedure defined amount of a protein substance</property>
3400
+ <value Unit="1" UNIT="1" value="1">1</value>
3401
+ </unit>
3402
+ <unit Code="[Lf]" CODE="[LF]" isMetric="no" isArbitrary="yes" class="chemical">
3403
+ <name>Limit of flocculation</name>
3404
+ <printSymbol>Lf</printSymbol>
3405
+ <property>procedure defined amount of an antigen substance</property>
3406
+ <value Unit="1" UNIT="1" value="1">1</value>
3407
+ </unit>
3408
+ <unit Code="[D'ag'U]" CODE="[D'AG'U]" isMetric="no" isArbitrary="yes"
3409
+ class="chemical">
3410
+ <name>D-antigen unit</name>
3411
+ <printSymbol/>
3412
+ <property>procedure defined amount of a poliomyelitis d-antigen substance</property>
3413
+ <value Unit="1" UNIT="1" value="1">1</value>
3414
+ </unit>
3415
+ <unit Code="[FEU]" CODE="[FEU]" isMetric="no" isArbitrary="yes" class="chemical">
3416
+ <name>fibrinogen equivalent unit</name>
3417
+ <printSymbol/>
3418
+ <property>amount of fibrinogen broken down into the measured d-dimers</property>
3419
+ <value Unit="1" UNIT="1" value="1">1</value>
3420
+ </unit>
3421
+ <unit Code="[ELU]" CODE="[ELU]" isMetric="no" isArbitrary="yes" class="chemical">
3422
+ <name>ELISA unit</name>
3423
+ <printSymbol/>
3424
+ <property>arbitrary ELISA unit</property>
3425
+ <value Unit="1" UNIT="1" value="1">1</value>
3426
+ </unit>
3427
+ <unit Code="[EU]" CODE="[EU]" isMetric="no" isArbitrary="yes" class="chemical">
3428
+ <name>Ehrlich unit</name>
3429
+ <printSymbol/>
3430
+ <property>Ehrlich unit</property>
3431
+ <value Unit="1" UNIT="1" value="1">1</value>
3432
+ </unit>
3433
+ <unit Code="Np" CODE="NEP" isMetric="yes" isSpecial="yes" class="levels">
3434
+ <name>neper</name>
3435
+ <printSymbol>Np</printSymbol>
3436
+ <property>level</property>
3437
+ <value Unit="ln(1 1)" UNIT="LN(1 1)">
3438
+ <function name="ln" value="1" Unit="1"/>
3439
+ </value>
3440
+ </unit>
3441
+ <unit Code="B" CODE="B" isMetric="yes" isSpecial="yes" class="levels">
3442
+ <name>bel</name>
3443
+ <printSymbol>B</printSymbol>
3444
+ <property>level</property>
3445
+ <value Unit="lg(1 1)" UNIT="LG(1 1)">
3446
+ <function name="lg" value="1" Unit="1"/>
3447
+ </value>
3448
+ </unit>
3449
+ <unit Code="B[SPL]" CODE="B[SPL]" isMetric="yes" isSpecial="yes" class="levels">
3450
+ <name>bel sound pressure</name>
3451
+ <printSymbol>B(SPL)</printSymbol>
3452
+ <property>pressure level</property>
3453
+ <value Unit="2lg(2 10*-5.Pa)" UNIT="2LG(2 10*-5.PAL)">
3454
+ <function name="lgTimes2" value="2" Unit="10*-5.Pa"/>
3455
+ </value>
3456
+ </unit>
3457
+ <unit Code="B[V]" CODE="B[V]" isMetric="yes" isSpecial="yes" class="levels">
3458
+ <name>bel volt</name>
3459
+ <printSymbol>B(V)</printSymbol>
3460
+ <property>electric potential level</property>
3461
+ <value Unit="2lg(1 V)" UNIT="2LG(1 V)">
3462
+ <function name="lgTimes2" value="1" Unit="V"/>
3463
+ </value>
3464
+ </unit>
3465
+ <unit Code="B[mV]" CODE="B[MV]" isMetric="yes" isSpecial="yes" class="levels">
3466
+ <name>bel millivolt</name>
3467
+ <printSymbol>B(mV)</printSymbol>
3468
+ <property>electric potential level</property>
3469
+ <value Unit="2lg(1 mV)" UNIT="2LG(1 MV)">
3470
+ <function name="lgTimes2" value="1" Unit="mV"/>
3471
+ </value>
3472
+ </unit>
3473
+ <unit Code="B[uV]" CODE="B[UV]" isMetric="yes" isSpecial="yes" class="levels">
3474
+ <name>bel microvolt</name>
3475
+ <printSymbol>B(&#956;V)</printSymbol>
3476
+ <property>electric potential level</property>
3477
+ <value Unit="2lg(1 uV)" UNIT="2LG(1 UV)">
3478
+ <function name="lgTimes2" value="1" Unit="uV"/>
3479
+ </value>
3480
+ </unit>
3481
+ <unit Code="B[10.nV]" CODE="B[10.NV]" isMetric="yes" isSpecial="yes" class="levels">
3482
+ <name>bel 10 nanovolt</name>
3483
+ <printSymbol>B(10 nV)</printSymbol>
3484
+ <property>electric potential level</property>
3485
+ <value Unit="2lg(10 nV)" UNIT="2LG(10 NV)">
3486
+ <function name="lgTimes2" value="10" Unit="nV"/>
3487
+ </value>
3488
+ </unit>
3489
+ <unit Code="B[W]" CODE="B[W]" isMetric="yes" isSpecial="yes" class="levels">
3490
+ <name>bel watt</name>
3491
+ <printSymbol>B(W)</printSymbol>
3492
+ <property>power level</property>
3493
+ <value Unit="lg(1 W)" UNIT="LG(1 W)">
3494
+ <function name="lg" value="1" Unit="W"/>
3495
+ </value>
3496
+ </unit>
3497
+ <unit Code="B[kW]" CODE="B[KW]" isMetric="yes" isSpecial="yes" class="levels">
3498
+ <name>bel kilowatt</name>
3499
+ <printSymbol>B(kW)</printSymbol>
3500
+ <property>power level</property>
3501
+ <value Unit="lg(1 kW)" UNIT="LG(1 KW)">
3502
+ <function name="lg" value="1" Unit="kW"/>
3503
+ </value>
3504
+ </unit>
3505
+ <unit Code="st" CODE="STR" isMetric="yes" class="misc">
3506
+ <name>stere</name>
3507
+ <printSymbol>st</printSymbol>
3508
+ <property>volume</property>
3509
+ <value Unit="m3" UNIT="M3" value="1">1</value>
3510
+ </unit>
3511
+ <unit Code="Ao" CODE="AO" isMetric="no" class="misc">
3512
+ <name>&#197;ngstr&#246;m</name>
3513
+ <printSymbol>&#197;</printSymbol>
3514
+ <property>length</property>
3515
+ <value Unit="nm" UNIT="NM" value="0.1">0.1</value>
3516
+ </unit>
3517
+ <unit Code="b" CODE="BRN" isMetric="no" class="misc">
3518
+ <name>barn</name>
3519
+ <printSymbol>b</printSymbol>
3520
+ <property>action area</property>
3521
+ <value Unit="fm2" UNIT="FM2" value="100">100</value>
3522
+ </unit>
3523
+ <unit Code="att" CODE="ATT" isMetric="no" class="misc">
3524
+ <name>technical atmosphere</name>
3525
+ <printSymbol>at</printSymbol>
3526
+ <property>pressure</property>
3527
+ <value Unit="kgf/cm2" UNIT="KGF/CM2" value="1">1</value>
3528
+ </unit>
3529
+ <unit Code="mho" CODE="MHO" isMetric="yes" class="misc">
3530
+ <name>mho</name>
3531
+ <printSymbol>mho</printSymbol>
3532
+ <property>electric conductance</property>
3533
+ <value Unit="S" UNIT="S" value="1">1</value>
3534
+ </unit>
3535
+ <unit Code="[psi]" CODE="[PSI]" isMetric="no" class="misc">
3536
+ <name>pound per square inch</name>
3537
+ <printSymbol>psi</printSymbol>
3538
+ <property>pressure</property>
3539
+ <value Unit="[lbf_av]/[in_i]2" UNIT="[LBF_AV]/[IN_I]2" value="1">1</value>
3540
+ </unit>
3541
+ <unit Code="circ" CODE="CIRC" isMetric="no" class="misc">
3542
+ <name>circle</name>
3543
+ <printSymbol>circ</printSymbol>
3544
+ <property>plane angle</property>
3545
+ <value Unit="[pi].rad" UNIT="[PI].RAD" value="2">2</value>
3546
+ </unit>
3547
+ <unit Code="sph" CODE="SPH" isMetric="no" class="misc">
3548
+ <name>sphere</name>
3549
+ <printSymbol>sph</printSymbol>
3550
+ <property>solid angle</property>
3551
+ <value Unit="[pi].sr" UNIT="[PI].SR" value="4">4</value>
3552
+ </unit>
3553
+ <unit Code="[car_m]" CODE="[CAR_M]" isMetric="no" class="misc">
3554
+ <name>metric carat</name>
3555
+ <printSymbol>ct<sub>m</sub>
3556
+ </printSymbol>
3557
+ <property>mass</property>
3558
+ <value Unit="g" UNIT="G" value="2e-1">0.2</value>
3559
+ </unit>
3560
+ <unit Code="[car_Au]" CODE="[CAR_AU]" isMetric="no" class="misc">
3561
+ <name>carat of gold alloys</name>
3562
+ <printSymbol>ct<sub>
3563
+ <r>Au</r>
3564
+ </sub>
3565
+ </printSymbol>
3566
+ <property>mass fraction</property>
3567
+ <value Unit="/24" UNIT="/24" value="1">1</value>
3568
+ </unit>
3569
+ <unit Code="[smoot]" CODE="[SMOOT]" isMetric="no" class="misc">
3570
+ <name>Smoot</name>
3571
+ <printSymbol/>
3572
+ <property>length</property>
3573
+ <value Unit="[in_i]" UNIT="[IN_I]" value="67">67</value>
3574
+ </unit>
3575
+ <unit Code="[m/s2/Hz^(1/2)]" CODE="[M/S2/HZ^(1/2)]" isMetric="no" isSpecial="yes"
3576
+ class="misc">
3577
+ <name>meter per square seconds per square root of hertz</name>
3578
+ <printSymbol/>
3579
+ <property>amplitude spectral density</property>
3580
+ <value Unit="sqrt(1 m2/s4/Hz)" UNIT="SQRT(1 M2/S4/HZ)">
3581
+ <function name="sqrt" value="1" Unit="m2/s4/Hz"/>
3582
+ </value>
3583
+ </unit>
3584
+ <unit Code="[NTU]" CODE="[NTU]" isMetric="no" class="misc">
3585
+ <name>Nephelometric Turbidity Unit</name>
3586
+ <printSymbol/>
3587
+ <property>turbidity</property>
3588
+ <value Unit="1" UNIT="1" value="1">1</value>
3589
+ </unit>
3590
+ <unit Code="[FNU]" CODE="[FNU]" isMetric="no" class="misc">
3591
+ <name>Formazin Nephelometric Unit</name>
3592
+ <printSymbol/>
3593
+ <property>turbidity</property>
3594
+ <value Unit="1" UNIT="1" value="1">1</value>
3595
+ </unit>
3596
+ <unit Code="bit_s" CODE="BIT_S" isMetric="no" isSpecial="yes" class="infotech">
3597
+ <name>bit</name>
3598
+ <printSymbol>bit<sub>s</sub>
3599
+ </printSymbol>
3600
+ <property>amount of information</property>
3601
+ <value Unit="ld(1 1)" UNIT="ld(1 1)">
3602
+ <function name="ld" value="1" Unit="1"/>
3603
+ </value>
3604
+ </unit>
3605
+ <unit Code="bit" CODE="BIT" isMetric="yes" class="infotech">
3606
+ <name>bit</name>
3607
+ <printSymbol>bit</printSymbol>
3608
+ <property>amount of information</property>
3609
+ <value Unit="1" UNIT="1" value="1">1</value>
3610
+ </unit>
3611
+ <unit Code="By" CODE="BY" isMetric="yes" class="infotech">
3612
+ <name>byte</name>
3613
+ <printSymbol>B</printSymbol>
3614
+ <property>amount of information</property>
3615
+ <value Unit="bit" UNIT="bit" value="8">8</value>
3616
+ </unit>
3617
+ <unit Code="Bd" CODE="BD" isMetric="yes" class="infotech">
3618
+ <name>baud</name>
3619
+ <printSymbol>Bd</printSymbol>
3620
+ <property>signal transmission rate</property>
3621
+ <value Unit="/s" UNIT="/s" value="1">1</value>
3622
+ </unit>
3623
+ <prefix Code="Ki" CODE="KIB">
3624
+ <name>kibi</name>
3625
+ <printSymbol>Ki</printSymbol>
3626
+ <value value="1024">1024</value>
3627
+ </prefix>
3628
+ <prefix Code="Mi" CODE="MIB">
3629
+ <name>mebi</name>
3630
+ <printSymbol>Mi</printSymbol>
3631
+ <value value="1048576">1048576</value>
3632
+ </prefix>
3633
+ <prefix Code="Gi" CODE="GIB">
3634
+ <name>gibi</name>
3635
+ <printSymbol>Gi</printSymbol>
3636
+ <value value="1073741824">1073741824</value>
3637
+ </prefix>
3638
+ <prefix Code="Ti" CODE="TIB">
3639
+ <name>tebi</name>
3640
+ <printSymbol>Ti</printSymbol>
3641
+ <value value="1099511627776">1099511627776</value>
3642
+ </prefix>
3643
+ </root>`;
3644
+
3645
+ // src/ucum/essence.ts
3646
+ function attr(tag, name) {
3647
+ const m = new RegExp(`\\b${name}="([^"]*)"`).exec(tag);
3648
+ return m?.[1];
3649
+ }
3650
+ function readValue(block) {
3651
+ const m = /<value\b([^>]*)>/.exec(block);
3652
+ if (!m?.[1]) return void 0;
3653
+ const valueAttr = attr(m[1], "value");
3654
+ const unitAttr = attr(m[1], "Unit");
3655
+ if (valueAttr === void 0 || unitAttr === void 0) return void 0;
3656
+ const factor = Number(valueAttr);
3657
+ if (!Number.isFinite(factor)) return void 0;
3658
+ return { factor, unit: unitAttr };
3659
+ }
3660
+ function parseEssence(xml) {
3661
+ const prefixes = [];
3662
+ const atoms = [];
3663
+ for (const m of xml.matchAll(/<prefix\b([^>]*)>([\s\S]*?)<\/prefix>/g)) {
3664
+ const openTag = m[1] ?? "";
3665
+ const body = m[2] ?? "";
3666
+ const code = attr(openTag, "Code");
3667
+ const valueTag = /<value\b([^>]*)>/.exec(body);
3668
+ const valueAttr = valueTag?.[1] === void 0 ? void 0 : attr(valueTag[1], "value");
3669
+ const factor = valueAttr === void 0 ? NaN : Number(valueAttr);
3670
+ if (code !== void 0 && Number.isFinite(factor)) prefixes.push({ code, factor });
3671
+ }
3672
+ for (const m of xml.matchAll(/<base-unit\b([^>]*)>/g)) {
3673
+ const openTag = m[1] ?? "";
3674
+ const code = attr(openTag, "Code");
3675
+ if (code === void 0) continue;
3676
+ atoms.push({
3677
+ code,
3678
+ metric: true,
3679
+ base: true,
3680
+ dim: code,
3681
+ special: false,
3682
+ arbitrary: false
3683
+ });
3684
+ }
3685
+ for (const m of xml.matchAll(/<unit\b([^>]*)>([\s\S]*?)<\/unit>/g)) {
3686
+ const openTag = m[1] ?? "";
3687
+ const body = m[2] ?? "";
3688
+ const code = attr(openTag, "Code");
3689
+ if (code === void 0) continue;
3690
+ const special = attr(openTag, "isSpecial") === "yes";
3691
+ const arbitrary = attr(openTag, "isArbitrary") === "yes";
3692
+ const value = special ? void 0 : readValue(body);
3693
+ atoms.push({
3694
+ code,
3695
+ metric: attr(openTag, "isMetric") === "yes",
3696
+ base: false,
3697
+ special,
3698
+ arbitrary,
3699
+ ...value ? { value } : {}
3700
+ });
3701
+ }
3702
+ prefixes.sort((a, b) => b.code.length - a.code.length);
3703
+ atoms.sort((a, b) => b.code.length - a.code.length);
3704
+ const atomByCode = new Map(atoms.map((a) => [a.code, a]));
3705
+ const prefixByCode = new Map(prefixes.map((p) => [p.code, p]));
3706
+ return { prefixes, atoms, atomByCode, prefixByCode };
3707
+ }
3708
+ var cached;
3709
+ function loadUcumEssence() {
3710
+ cached ??= parseEssence(UCUM_ESSENCE_XML);
3711
+ return cached;
3712
+ }
3713
+
3714
+ // src/ucum/parse.ts
3715
+ var isDigitCode = (cc) => cc >= 48 && cc <= 57;
3716
+ var isDigitAt = (s, i) => isDigitCode(s.charCodeAt(i));
3717
+ function atBoundary(s, pos) {
3718
+ if (pos >= s.length) return true;
3719
+ const c = s[pos];
3720
+ return c === "." || c === "/" || c === ")";
3721
+ }
3722
+ function simpleMatches(essence, s, pos) {
3723
+ const out = [];
3724
+ for (const atom of essence.atoms) {
3725
+ if (s.startsWith(atom.code, pos)) out.push({ atom, len: atom.code.length });
3726
+ }
3727
+ for (const prefix of essence.prefixes) {
3728
+ if (!s.startsWith(prefix.code, pos)) continue;
3729
+ const rem = pos + prefix.code.length;
3730
+ for (const atom of essence.atoms) {
3731
+ if (atom.metric && s.startsWith(atom.code, rem)) {
3732
+ out.push({ prefix, atom, len: prefix.code.length + atom.code.length });
3733
+ }
3734
+ }
3735
+ }
3736
+ out.sort((a, b) => b.len - a.len || (a.prefix ? 1 : 0) - (b.prefix ? 1 : 0));
3737
+ return out;
3738
+ }
3739
+ var MAX_PAREN_DEPTH = 100;
3740
+ function parseExponent(cur) {
3741
+ const { s } = cur;
3742
+ let i = cur.pos;
3743
+ let sign = 1;
3744
+ if (s[i] === "+") i++;
3745
+ else if (s[i] === "-") {
3746
+ sign = -1;
3747
+ i++;
3748
+ }
3749
+ const start = i;
3750
+ while (i < s.length && isDigitAt(s, i)) i++;
3751
+ if (i === start) return { value: 1, consumed: false };
3752
+ cur.pos = i;
3753
+ return { value: sign * Number(s.slice(start, i)), consumed: true };
3754
+ }
3755
+ function parseAnnotation(cur) {
3756
+ const { s } = cur;
3757
+ let i = cur.pos + 1;
3758
+ for (; i < s.length; i++) {
3759
+ const code = s.charCodeAt(i);
3760
+ if (code === 125) {
3761
+ cur.pos = i + 1;
3762
+ return void 0;
3763
+ }
3764
+ if (code < 32 || code > 126 || code === 123) {
3765
+ return { ok: false, reason: "annotation contains a non-ASCII or illegal character" };
3766
+ }
3767
+ }
3768
+ return { ok: false, reason: "annotation is not closed with '}'" };
3769
+ }
3770
+ function parseSimpleUnit(cur) {
3771
+ const candidates = simpleMatches(cur.essence, cur.s, cur.pos);
3772
+ for (const cand of candidates) {
3773
+ const save = cur.pos;
3774
+ cur.pos = save + cand.len;
3775
+ const exp = parseExponent(cur);
3776
+ if ((cand.atom.code === "10*" || cand.atom.code === "10^") && !exp.consumed) {
3777
+ cur.pos = save;
3778
+ continue;
3779
+ }
3780
+ let annotationEnd = cur.pos;
3781
+ if (cur.s.charCodeAt(cur.pos) === 123) {
3782
+ const err = parseAnnotation(cur);
3783
+ if (err) {
3784
+ cur.pos = save;
3785
+ return err;
3786
+ }
3787
+ annotationEnd = cur.pos;
3788
+ }
3789
+ if (atBoundary(cur.s, annotationEnd)) {
3790
+ const node = cand.prefix ? { kind: "simple", prefix: cand.prefix, atom: cand.atom, exponent: exp.value } : { kind: "simple", atom: cand.atom, exponent: exp.value };
3791
+ return { ok: true, node };
3792
+ }
3793
+ cur.pos = save;
3794
+ }
3795
+ return { ok: false, reason: "unrecognized unit atom" };
3796
+ }
3797
+ function parseComponent(cur) {
3798
+ const { s } = cur;
3799
+ const cc = s.charCodeAt(cur.pos);
3800
+ if (cc === 40) {
3801
+ if (cur.depth >= MAX_PAREN_DEPTH) {
3802
+ return { ok: false, reason: "parentheses nested too deeply" };
3803
+ }
3804
+ cur.pos++;
3805
+ cur.depth++;
3806
+ const inner = parseTerm(cur, true);
3807
+ cur.depth--;
3808
+ if (!inner.ok) return inner;
3809
+ return { ok: true, node: { kind: "group", term: inner.node } };
3810
+ }
3811
+ if (cc === 123) {
3812
+ const err = parseAnnotation(cur);
3813
+ if (err) return err;
3814
+ return { ok: true, node: { kind: "annotation" } };
3815
+ }
3816
+ if (isDigitCode(cc) && !s.startsWith("10*", cur.pos) && !s.startsWith("10^", cur.pos)) {
3817
+ const start = cur.pos;
3818
+ while (cur.pos < s.length && isDigitAt(s, cur.pos)) cur.pos++;
3819
+ if (s.charCodeAt(cur.pos) === 123) {
3820
+ const err = parseAnnotation(cur);
3821
+ if (err) return err;
3822
+ }
3823
+ if (!atBoundary(s, cur.pos)) {
3824
+ return { ok: false, reason: "a numeric factor must be followed by an operator" };
3825
+ }
3826
+ return { ok: true, node: { kind: "factor", value: Number(s.slice(start, cur.pos)) } };
3827
+ }
3828
+ return parseSimpleUnit(cur);
3829
+ }
3830
+ function parseTerm(cur, inParen) {
3831
+ const factors = [];
3832
+ let sign = 1;
3833
+ if (cur.s[cur.pos] === "/") {
3834
+ sign = -1;
3835
+ cur.pos++;
3836
+ }
3837
+ const first = parseComponent(cur);
3838
+ if (!first.ok) return first;
3839
+ factors.push({ sign, node: first.node });
3840
+ while (cur.pos < cur.s.length) {
3841
+ const op = cur.s[cur.pos];
3842
+ if (op !== "." && op !== "/") break;
3843
+ cur.pos++;
3844
+ const comp = parseComponent(cur);
3845
+ if (!comp.ok) return comp;
3846
+ factors.push({ sign: op === "/" ? -1 : 1, node: comp.node });
3847
+ }
3848
+ if (inParen) {
3849
+ if (cur.s[cur.pos] !== ")") return { ok: false, reason: "unbalanced '(' \u2014 missing ')'" };
3850
+ cur.pos++;
3851
+ }
3852
+ return { ok: true, node: { kind: "term", factors } };
3853
+ }
3854
+ function parseUcum(unit) {
3855
+ if (unit.length === 0) return { ok: false, reason: "empty unit expression" };
3856
+ const cur = { s: unit, pos: 0, depth: 0, essence: loadUcumEssence() };
3857
+ const result = parseTerm(cur, false);
3858
+ if (!result.ok) return result;
3859
+ if (cur.pos !== unit.length) {
3860
+ return { ok: false, reason: "unexpected trailing input (missing operator?)" };
3861
+ }
3862
+ return { ok: true, node: result.node };
3863
+ }
3864
+
3865
+ // src/ucum/reduce.ts
3866
+ function multiply(a, b) {
3867
+ const dims = { ...a.dims };
3868
+ for (const [k, v] of Object.entries(b.dims)) {
3869
+ const next = (dims[k] ?? 0) + v;
3870
+ if (next === 0) delete dims[k];
3871
+ else dims[k] = next;
3872
+ }
3873
+ return { kind: "linear", factor: a.factor * b.factor, dims };
3874
+ }
3875
+ function power(r, p) {
3876
+ if (p === 1) return r;
3877
+ const dims = {};
3878
+ for (const [k, v] of Object.entries(r.dims)) {
3879
+ const e = v * p;
3880
+ if (e !== 0) dims[k] = e;
3881
+ }
3882
+ return { kind: "linear", factor: Math.pow(r.factor, p), dims };
3883
+ }
3884
+ var DIMENSIONLESS = { kind: "linear", factor: 1, dims: {} };
3885
+ var atomMemo = /* @__PURE__ */ new Map();
3886
+ var inProgress = /* @__PURE__ */ new Set();
3887
+ function reduceAtomLinear(atom) {
3888
+ if (atom.base) return { kind: "linear", factor: 1, dims: { [atom.dim ?? atom.code]: 1 } };
3889
+ if (atom.arbitrary) return { kind: "linear", factor: 1, dims: { [`arb:${atom.code}`]: 1 } };
3890
+ const cached2 = atomMemo.get(atom.code);
3891
+ if (cached2) return cached2;
3892
+ if (inProgress.has(atom.code)) {
3893
+ throw new Error(`cyclic UCUM atom definition for '${atom.code}'`);
3894
+ }
3895
+ if (!atom.value) {
3896
+ atomMemo.set(atom.code, DIMENSIONLESS);
3897
+ return DIMENSIONLESS;
3898
+ }
3899
+ inProgress.add(atom.code);
3900
+ const parsed = parseUcum(atom.value.unit);
3901
+ if (!parsed.ok) {
3902
+ inProgress.delete(atom.code);
3903
+ throw new Error(`unparseable UCUM essence definition for '${atom.code}'`);
3904
+ }
3905
+ const reduced = linearReduceTerm(parsed.node);
3906
+ const result = multiply({ factor: atom.value.factor, dims: {} }, reduced);
3907
+ inProgress.delete(atom.code);
3908
+ atomMemo.set(atom.code, result);
3909
+ return result;
3910
+ }
3911
+ function reduceSimpleLinear(node) {
3912
+ const base = reduceAtomLinear(node.atom);
3913
+ const prefixed = node.prefix ? { kind: "linear", factor: base.factor * node.prefix.factor, dims: base.dims } : base;
3914
+ return power(prefixed, node.exponent);
3915
+ }
3916
+ function linearReduceComponent(comp) {
3917
+ switch (comp.kind) {
3918
+ case "factor":
3919
+ return { kind: "linear", factor: comp.value, dims: {} };
3920
+ case "annotation":
3921
+ return DIMENSIONLESS;
3922
+ case "group":
3923
+ return linearReduceTerm(comp.term);
3924
+ case "simple":
3925
+ return reduceSimpleLinear(comp);
3926
+ }
3927
+ }
3928
+ function linearReduceTerm(node) {
3929
+ let acc = DIMENSIONLESS;
3930
+ for (const { sign, node: comp } of node.factors) {
3931
+ acc = multiply(acc, power(linearReduceComponent(comp), sign));
3932
+ }
3933
+ return acc;
3934
+ }
3935
+ function containsSpecial(node) {
3936
+ return node.factors.some(({ node: comp }) => {
3937
+ if (comp.kind === "simple") return comp.atom.special;
3938
+ if (comp.kind === "group") return containsSpecial(comp.term);
3939
+ return false;
3940
+ });
3941
+ }
3942
+ function serializeSpecial(node) {
3943
+ const tokens = [];
3944
+ const walk = (t, outerSign) => {
3945
+ for (const { sign, node: comp } of t.factors) {
3946
+ const s = sign * outerSign;
3947
+ if (comp.kind === "simple") {
3948
+ const net = comp.exponent * s;
3949
+ tokens.push(`${comp.prefix?.code ?? ""}${comp.atom.code}${net === 1 ? "" : String(net)}`);
3950
+ } else if (comp.kind === "factor") {
3951
+ tokens.push(`#${String(comp.value)}${s === 1 ? "" : `^${String(s)}`}`);
3952
+ } else if (comp.kind === "group") {
3953
+ walk(comp.term, s);
3954
+ }
3955
+ }
3956
+ };
3957
+ walk(node, 1);
3958
+ return tokens.sort().join(".");
3959
+ }
3960
+ function reduce(node) {
3961
+ if (containsSpecial(node)) return { kind: "special", form: serializeSpecial(node) };
3962
+ return linearReduceTerm(node);
3963
+ }
3964
+
3965
+ // src/ucum/validate.ts
3966
+ function roundFactor(x) {
3967
+ return String(Number(x.toPrecision(12)));
3968
+ }
3969
+ function canonicalOf(r) {
3970
+ if (r.kind === "special") return `special:${r.form}`;
3971
+ const keys = Object.keys(r.dims).sort();
3972
+ const dims = keys.length === 0 ? "1" : keys.map((k) => `${k}${String(r.dims[k])}`).join(".");
3973
+ return `${roundFactor(r.factor)} ${dims}`;
3974
+ }
3975
+ function validateUcum(unit) {
3976
+ const parsed = parseUcum(unit);
3977
+ if (!parsed.ok) return { valid: false, code: "TERM_UCUM_INVALID", reason: parsed.reason };
3978
+ return { valid: true, canonical: canonicalOf(reduce(parsed.node)) };
3979
+ }
3980
+ function ucumEqual(a, b) {
3981
+ const va = validateUcum(a);
3982
+ const vb = validateUcum(b);
3983
+ return va.valid && vb.valid && va.canonical === vb.canonical;
3984
+ }
3985
+
3986
+ // src/crosswalk/gems.ts
3987
+ var NO_DX = "NoDx";
3988
+ var NO_PCS = "NoPCS";
3989
+ function isNoMapSentinel(target) {
3990
+ return target === NO_DX || target === NO_PCS;
3991
+ }
3992
+ function decodeFlags(raw) {
3993
+ if (!/^[0-9]{5}$/.test(raw)) return void 0;
3994
+ return Object.freeze({
3995
+ approximate: raw[0] === "1",
3996
+ noMap: raw[1] === "1",
3997
+ combination: raw[2] === "1",
3998
+ scenario: Number(raw[3]),
3999
+ choiceList: Number(raw[4]),
4000
+ raw
4001
+ });
4002
+ }
4003
+ function loadGems(source) {
4004
+ const entries = /* @__PURE__ */ new Map();
4005
+ const warnings = [];
4006
+ let count = 0;
4007
+ const lines = source.content.split(/\r?\n/);
4008
+ for (let i = 0; i < lines.length; i++) {
4009
+ const raw = lines[i];
4010
+ if (raw === void 0) continue;
4011
+ const trimmed = raw.trim();
4012
+ if (trimmed === "") continue;
4013
+ const fields = trimmed.split(/\s+/);
4014
+ if (fields.length !== 3) {
4015
+ warnings.push({
4016
+ code: "TERM_GEM_MALFORMED_ROW",
4017
+ line: i + 1,
4018
+ detail: `expected 3 whitespace-delimited fields, found ${String(fields.length)}`
4019
+ });
4020
+ continue;
4021
+ }
4022
+ const [src, tgt, flagStr] = fields;
4023
+ const flags = decodeFlags(flagStr);
4024
+ if (flags === void 0) {
4025
+ warnings.push({
4026
+ code: "TERM_GEM_MALFORMED_ROW",
4027
+ line: i + 1,
4028
+ detail: "flag field is not a 5-digit code"
4029
+ });
4030
+ continue;
4031
+ }
4032
+ const entry = { source: src, flags };
4033
+ if (!isNoMapSentinel(tgt)) entry.target = tgt;
4034
+ const frozen = Object.freeze(entry);
4035
+ const list = entries.get(src);
4036
+ if (list) list.push(frozen);
4037
+ else entries.set(src, [frozen]);
4038
+ count++;
4039
+ }
4040
+ return Object.freeze({
4041
+ direction: source.direction,
4042
+ ...source.version !== void 0 ? { version: source.version } : {},
4043
+ count,
4044
+ entries,
4045
+ warnings: Object.freeze(warnings)
4046
+ });
4047
+ }
4048
+ function buildCombinations(entries) {
4049
+ const combo = entries.filter((e) => e.flags.combination && e.target !== void 0);
4050
+ if (combo.length === 0) return void 0;
4051
+ const scenarioNums = [];
4052
+ const byScenario = /* @__PURE__ */ new Map();
4053
+ for (const e of combo) {
4054
+ const s = e.flags.scenario;
4055
+ let lists = byScenario.get(s);
4056
+ if (!lists) {
4057
+ lists = /* @__PURE__ */ new Map();
4058
+ byScenario.set(s, lists);
4059
+ scenarioNums.push(s);
4060
+ }
4061
+ const cl = e.flags.choiceList;
4062
+ const targets = lists.get(cl);
4063
+ if (targets) targets.push(e.target);
4064
+ else lists.set(cl, [e.target]);
4065
+ }
4066
+ const scenarios = [];
4067
+ for (const s of scenarioNums.sort((a, b) => a - b)) {
4068
+ const lists = byScenario.get(s);
4069
+ const choiceLists = [];
4070
+ for (const cl of [...lists.keys()].sort((a, b) => a - b)) {
4071
+ choiceLists.push(
4072
+ Object.freeze({ choiceList: cl, targets: Object.freeze(lists.get(cl)) })
4073
+ );
4074
+ }
4075
+ scenarios.push(Object.freeze({ scenario: s, choiceLists: Object.freeze(choiceLists) }));
4076
+ }
4077
+ return Object.freeze(scenarios);
4078
+ }
4079
+ function applyGem(map, source) {
4080
+ const all = map.entries.get(source);
4081
+ if (all === void 0 || all.length === 0) {
4082
+ const unmapped = Object.freeze({
4083
+ mapped: false,
4084
+ noMap: false,
4085
+ code: "TERM_CROSSWALK_UNMAPPED",
4086
+ source
4087
+ });
4088
+ return unmapped;
4089
+ }
4090
+ const realTargets = all.filter((e) => e.target !== void 0);
4091
+ if (realTargets.length === 0) {
4092
+ const noMap = Object.freeze({
4093
+ mapped: false,
4094
+ noMap: true,
4095
+ code: "TERM_CROSSWALK_NO_MAP",
4096
+ source,
4097
+ entries: Object.freeze([...all])
4098
+ });
4099
+ return noMap;
4100
+ }
4101
+ const combinations = buildCombinations(realTargets);
4102
+ const matched = {
4103
+ mapped: true,
4104
+ source,
4105
+ direction: map.direction,
4106
+ entries: Object.freeze([...realTargets])
4107
+ };
4108
+ if (combinations !== void 0) matched.combinations = combinations;
4109
+ return Object.freeze(matched);
4110
+ }
4111
+ function invertGem(map) {
4112
+ throw new TerminologyError(
4113
+ FATAL_CODES.TERM_MAP_NOT_INVERTIBLE,
4114
+ `GEM map (direction ${map.direction}) cannot be inverted \u2014 load the reverse GEM file instead`
4115
+ );
4116
+ }
4117
+
4118
+ // src/crosswalk/categories.ts
4119
+ var MAP_CATEGORIES = {
4120
+ /** `447637006` — "Map source concept is properly classified" (a normal, usable target). */
4121
+ PROPERLY_CLASSIFIED: "447637006",
4122
+ /** `447638001` — "Map source concept cannot be classified with available data" — a **No-Map**. */
4123
+ NO_MAP: "447638001",
4124
+ /** `447639009` — "Map of source concept is context dependent" (needs runtime patient context). */
4125
+ CONTEXT_DEPENDENT: "447639009",
4126
+ /** `447640006` — "Source concept is ambiguous" — surface candidates, never pick one. */
4127
+ AMBIGUOUS: "447640006"
4128
+ };
4129
+ var NO_MAP_CATEGORIES = /* @__PURE__ */ new Set([MAP_CATEGORIES.NO_MAP]);
4130
+ var ICD10CM_SYSTEM = "http://hl7.org/fhir/sid/icd-10-cm";
4131
+ var ICD9CM_SYSTEM = "http://hl7.org/fhir/sid/icd-9-cm";
4132
+ var SNOMEDCT_SYSTEM = "http://snomed.info/sct";
4133
+
4134
+ // src/crosswalk/complex-map.ts
4135
+ var SNOMED_FEMALE = "248152002";
4136
+ var SNOMED_MALE = "248153007";
4137
+ function freezeEntry(e) {
4138
+ const out = {
4139
+ source: e.source,
4140
+ group: e.group,
4141
+ priority: e.priority,
4142
+ rule: e.rule,
4143
+ advice: e.advice
4144
+ };
4145
+ if (e.target !== void 0 && e.target !== "") out.target = e.target;
4146
+ if (e.category !== void 0 && e.category !== "") out.category = e.category;
4147
+ if (e.correlation !== void 0 && e.correlation !== "") out.correlation = e.correlation;
4148
+ return Object.freeze(out);
4149
+ }
4150
+ function parseRf2(content) {
4151
+ const rows = [];
4152
+ const warnings = [];
4153
+ const lines = content.split(/\r?\n/);
4154
+ if (lines.length === 0 || lines[0] === void 0 || lines[0].trim() === "") {
4155
+ throw new TerminologyError(
4156
+ FATAL_CODES.TERM_CROSSWALK_MALFORMED,
4157
+ "complex-map RF2: empty content (no header row)"
4158
+ );
4159
+ }
4160
+ const header = lines[0].split(" ").map((h) => h.trim());
4161
+ const col = (name) => header.indexOf(name);
4162
+ const iActive = col("active");
4163
+ const iSource = col("referencedComponentId");
4164
+ const iGroup = col("mapGroup");
4165
+ const iPriority = col("mapPriority");
4166
+ const iRule = col("mapRule");
4167
+ const iAdvice = col("mapAdvice");
4168
+ const iTarget = col("mapTarget");
4169
+ const iCorr = col("correlationId");
4170
+ const iCat = col("mapCategoryId");
4171
+ if (iSource < 0 || iGroup < 0 || iPriority < 0) {
4172
+ throw new TerminologyError(
4173
+ FATAL_CODES.TERM_CROSSWALK_MALFORMED,
4174
+ "complex-map RF2: header is missing a required column (referencedComponentId/mapGroup/mapPriority)"
4175
+ );
4176
+ }
4177
+ const at = (fields, i) => i >= 0 && i < fields.length ? fields[i] ?? "" : "";
4178
+ for (let i = 1; i < lines.length; i++) {
4179
+ const raw = lines[i];
4180
+ if (raw === void 0 || raw === "") continue;
4181
+ const f = raw.split(" ");
4182
+ if (iActive >= 0 && at(f, iActive) === "0") continue;
4183
+ const source = at(f, iSource);
4184
+ const groupN = Number(at(f, iGroup));
4185
+ const priorityN = Number(at(f, iPriority));
4186
+ if (source === "" || !Number.isFinite(groupN) || !Number.isFinite(priorityN)) {
4187
+ warnings.push({
4188
+ code: "TERM_COMPLEX_MAP_MALFORMED_ROW",
4189
+ line: i + 1,
4190
+ detail: "row is missing referencedComponentId / mapGroup / mapPriority"
4191
+ });
4192
+ continue;
4193
+ }
4194
+ rows.push({
4195
+ source,
4196
+ group: groupN,
4197
+ priority: priorityN,
4198
+ rule: at(f, iRule),
4199
+ advice: at(f, iAdvice),
4200
+ target: at(f, iTarget),
4201
+ category: at(f, iCat),
4202
+ correlation: at(f, iCorr)
4203
+ });
4204
+ }
4205
+ return { rows, warnings };
4206
+ }
4207
+ function loadComplexMap(input) {
4208
+ let rawRows;
4209
+ let warnings;
4210
+ if (input.format === "rf2") {
4211
+ const parsed = parseRf2(input.content);
4212
+ rawRows = parsed.rows;
4213
+ warnings = Object.freeze(parsed.warnings);
4214
+ } else {
4215
+ rawRows = input.rows;
4216
+ warnings = Object.freeze([]);
4217
+ }
4218
+ const bySource = /* @__PURE__ */ new Map();
4219
+ for (const r of rawRows) {
4220
+ const e = freezeEntry(r);
4221
+ const list = bySource.get(e.source);
4222
+ if (list) list.push(e);
4223
+ else bySource.set(e.source, [e]);
4224
+ }
4225
+ const entries = /* @__PURE__ */ new Map();
4226
+ let count = 0;
4227
+ for (const [src, list] of bySource) {
4228
+ const sorted = [...list].sort((a, b) => a.group - b.group || a.priority - b.priority);
4229
+ entries.set(src, Object.freeze(sorted));
4230
+ count += sorted.length;
4231
+ }
4232
+ const out = {
4233
+ count,
4234
+ entries,
4235
+ warnings
4236
+ };
4237
+ if (input.version !== void 0) out.version = input.version;
4238
+ return Object.freeze(out);
4239
+ }
4240
+ function evaluateConjunct(clause, context) {
4241
+ const trimmed = clause.trim();
4242
+ if (!/^IFA\b/i.test(trimmed)) return "unknown";
4243
+ if (trimmed.includes(SNOMED_FEMALE)) {
4244
+ if (context.gender === void 0) return "unknown";
4245
+ return context.gender === "female" ? "match" : "no-match";
4246
+ }
4247
+ if (trimmed.includes(SNOMED_MALE)) {
4248
+ if (context.gender === void 0) return "unknown";
4249
+ return context.gender === "male" ? "match" : "no-match";
4250
+ }
4251
+ const ageMatch = /(<=|>=|<|>|=)\s*([0-9]+(?:\.[0-9]+)?)\s*year/i.exec(trimmed);
4252
+ if (ageMatch) {
4253
+ const op = ageMatch[1];
4254
+ const bound = Number(ageMatch[2]);
4255
+ if (context.ageYears === void 0 || !Number.isFinite(bound)) return "unknown";
4256
+ const age = context.ageYears;
4257
+ const ok = op === "<=" ? age <= bound : op === ">=" ? age >= bound : op === "<" ? age < bound : op === ">" ? age > bound : op === "=" ? age === bound : void 0;
4258
+ if (ok === void 0) return "unknown";
4259
+ return ok ? "match" : "no-match";
4260
+ }
4261
+ return "unknown";
4262
+ }
4263
+ function evaluateRule(rule, context) {
4264
+ const trimmed = rule.trim();
4265
+ if (/^(OTHERWISE\s+)?TRUE$/.test(trimmed)) return "match";
4266
+ const conjuncts = trimmed.split(/\s+AND\s+(?=IFA\b)/);
4267
+ let sawUnknown = false;
4268
+ for (const c of conjuncts) {
4269
+ const m = evaluateConjunct(c, context);
4270
+ if (m === "no-match") return "no-match";
4271
+ if (m === "unknown") sawUnknown = true;
4272
+ }
4273
+ return sawUnknown ? "unknown" : "match";
4274
+ }
4275
+ function isNoMap(e) {
4276
+ return e.category === MAP_CATEGORIES.NO_MAP || e.target === void 0;
4277
+ }
4278
+ function resolveGroup(group, rules, context) {
4279
+ for (const entry of rules) {
4280
+ const m = evaluateRule(entry.rule, context);
4281
+ if (m === "no-match") continue;
4282
+ if (m === "unknown") {
4283
+ return Object.freeze({
4284
+ outcome: "context-required",
4285
+ code: "TERM_CROSSWALK_CONTEXT_REQUIRED",
4286
+ group,
4287
+ rules
4288
+ });
4289
+ }
4290
+ if (isNoMap(entry)) {
4291
+ const noMap = {
4292
+ outcome: "no-map",
4293
+ code: "TERM_CROSSWALK_NO_MAP",
4294
+ group,
4295
+ advice: entry.advice
4296
+ };
4297
+ if (entry.category !== void 0) noMap.category = entry.category;
4298
+ return Object.freeze(noMap);
4299
+ }
4300
+ const target = coding({ system: ICD10CM_SYSTEM, code: entry.target });
4301
+ const resolved = {
4302
+ outcome: "resolved",
4303
+ group,
4304
+ target,
4305
+ advice: entry.advice,
4306
+ rule: entry.rule
4307
+ };
4308
+ if (entry.category !== void 0) resolved.category = entry.category;
4309
+ return Object.freeze(resolved);
4310
+ }
4311
+ return Object.freeze({
4312
+ outcome: "context-required",
4313
+ code: "TERM_CROSSWALK_CONTEXT_REQUIRED",
4314
+ group,
4315
+ rules
4316
+ });
4317
+ }
4318
+ function applyComplexMap(map, source, context = {}) {
4319
+ const rows = map.entries.get(source);
4320
+ if (rows === void 0 || rows.length === 0) {
4321
+ const unmapped = Object.freeze({
4322
+ mapped: false,
4323
+ noMap: false,
4324
+ code: "TERM_CROSSWALK_UNMAPPED",
4325
+ source
4326
+ });
4327
+ return unmapped;
4328
+ }
4329
+ const groupNumbers = [];
4330
+ const byGroup = /* @__PURE__ */ new Map();
4331
+ for (const r of rows) {
4332
+ const list = byGroup.get(r.group);
4333
+ if (list) list.push(r);
4334
+ else {
4335
+ byGroup.set(r.group, [r]);
4336
+ groupNumbers.push(r.group);
4337
+ }
4338
+ }
4339
+ const groups = [];
4340
+ for (const g of groupNumbers) {
4341
+ const rules = Object.freeze(byGroup.get(g));
4342
+ groups.push(resolveGroup(g, rules, context));
4343
+ }
4344
+ const matched = Object.freeze({
4345
+ mapped: true,
4346
+ source,
4347
+ groups: Object.freeze(groups)
4348
+ });
4349
+ return matched;
4350
+ }
4351
+ var COMPLEX_MAP_SOURCE_SYSTEM = SNOMEDCT_SYSTEM;
4352
+
4353
+ // src/rxnorm/tty.ts
4354
+ var TERM_TYPES = Object.freeze({
4355
+ IN: "Ingredient",
4356
+ PIN: "Precise Ingredient",
4357
+ MIN: "Multiple Ingredients",
4358
+ BN: "Brand Name",
4359
+ SCDC: "Semantic Clinical Drug Component",
4360
+ SBDC: "Semantic Branded Drug Component",
4361
+ SCD: "Semantic Clinical Drug",
4362
+ SBD: "Semantic Branded Drug",
4363
+ SCDG: "Semantic Clinical Drug Group",
4364
+ SBDG: "Semantic Branded Drug Group",
4365
+ GPCK: "Generic Pack",
4366
+ BPCK: "Branded Pack",
4367
+ DF: "Dose Form",
4368
+ DFG: "Dose Form Group",
4369
+ PSN: "Prescribable Name",
4370
+ SY: "Synonym",
4371
+ TMSY: "Tall Man Lettering Synonym",
4372
+ ET: "Entry Term"
4373
+ });
4374
+ var KNOWN = new Set(Object.keys(TERM_TYPES));
4375
+ function asTermType(tty) {
4376
+ return KNOWN.has(tty) ? tty : void 0;
4377
+ }
4378
+
4379
+ // src/rxnorm/load.ts
4380
+ var SAB_RXNORM = "RXNORM";
4381
+ var ATN_NDC = "NDC";
4382
+ var CONSO = { RXCUI: 0, SAB: 11, TTY: 12, STR: 14, SUPPRESS: 16 };
4383
+ var REL = { RXCUI1: 0, RXCUI2: 4, RELA: 7 };
4384
+ var SAT = { RXCUI: 0, ATN: 8, ATV: 10 };
4385
+ function cell2(cells, index) {
4386
+ const v = cells[index];
4387
+ return v === void 0 ? void 0 : v.trim();
4388
+ }
4389
+ function parseConso(content, warnings) {
4390
+ const concepts = /* @__PURE__ */ new Map();
4391
+ const lines = content.split(/\r?\n/);
4392
+ for (let i = 0; i < lines.length; i++) {
4393
+ const raw = lines[i] ?? "";
4394
+ if (raw === "") continue;
4395
+ const cells = parseRrfLine(raw);
4396
+ if (cells.length <= CONSO.STR) {
4397
+ warnings.push(
4398
+ Object.freeze({
4399
+ code: "TERM_RXNORM_MALFORMED_ROW",
4400
+ file: "RXNCONSO",
4401
+ line: i + 1,
4402
+ detail: `row has ${String(cells.length)} columns, need at least ${String(CONSO.STR + 1)}`
4403
+ })
4404
+ );
4405
+ continue;
4406
+ }
4407
+ if (cell2(cells, CONSO.SAB) !== SAB_RXNORM) continue;
4408
+ const tty = asTermType(cell2(cells, CONSO.TTY) ?? "");
4409
+ if (tty === void 0) continue;
4410
+ const rxcui = cell2(cells, CONSO.RXCUI);
4411
+ if (rxcui === void 0 || rxcui === "") {
4412
+ warnings.push(
4413
+ Object.freeze({
4414
+ code: "TERM_RXNORM_MALFORMED_ROW",
4415
+ file: "RXNCONSO",
4416
+ line: i + 1,
4417
+ detail: "row is missing its RXCUI"
4418
+ })
4419
+ );
4420
+ continue;
4421
+ }
4422
+ if (concepts.has(rxcui)) continue;
4423
+ const name = cell2(cells, CONSO.STR) ?? "";
4424
+ const suppress = cell2(cells, CONSO.SUPPRESS) ?? "N";
4425
+ concepts.set(
4426
+ rxcui,
4427
+ Object.freeze({ rxcui, tty, name, suppressed: suppress !== "" && suppress !== "N" })
4428
+ );
4429
+ }
4430
+ return concepts;
4431
+ }
4432
+ function parseRel(content, warnings) {
4433
+ const edges = /* @__PURE__ */ new Map();
4434
+ let edgeCount = 0;
4435
+ const lines = content.split(/\r?\n/);
4436
+ for (let i = 0; i < lines.length; i++) {
4437
+ const raw = lines[i] ?? "";
4438
+ if (raw === "") continue;
4439
+ const cells = parseRrfLine(raw);
4440
+ if (cells.length <= REL.RELA) {
4441
+ warnings.push(
4442
+ Object.freeze({
4443
+ code: "TERM_RXNORM_MALFORMED_ROW",
4444
+ file: "RXNREL",
4445
+ line: i + 1,
4446
+ detail: `row has ${String(cells.length)} columns, need at least ${String(REL.RELA + 1)}`
4447
+ })
4448
+ );
4449
+ continue;
4450
+ }
4451
+ const rela = cell2(cells, REL.RELA);
4452
+ const rxcui1 = cell2(cells, REL.RXCUI1);
4453
+ const rxcui2 = cell2(cells, REL.RXCUI2);
4454
+ if (rela === void 0 || rela === "") continue;
4455
+ if (rxcui1 === void 0 || rxcui1 === "" || rxcui2 === void 0 || rxcui2 === "") continue;
4456
+ const edge = Object.freeze({ subject: rxcui2, predicate: rela, object: rxcui1 });
4457
+ const list = edges.get(rxcui2);
4458
+ if (list) list.push(edge);
4459
+ else edges.set(rxcui2, [edge]);
4460
+ edgeCount++;
4461
+ }
4462
+ return { edges, edgeCount };
4463
+ }
4464
+ function parseNdcs(content, warnings) {
4465
+ const ndcs = /* @__PURE__ */ new Map();
4466
+ const lines = content.split(/\r?\n/);
4467
+ for (let i = 0; i < lines.length; i++) {
4468
+ const raw = lines[i] ?? "";
4469
+ if (raw === "") continue;
4470
+ const cells = parseRrfLine(raw);
4471
+ if (cells.length <= SAT.ATV) {
4472
+ warnings.push(
4473
+ Object.freeze({
4474
+ code: "TERM_RXNORM_MALFORMED_ROW",
4475
+ file: "RXNSAT",
4476
+ line: i + 1,
4477
+ detail: `row has ${String(cells.length)} columns, need at least ${String(SAT.ATV + 1)}`
4478
+ })
4479
+ );
4480
+ continue;
4481
+ }
4482
+ if (cell2(cells, SAT.ATN) !== ATN_NDC) continue;
4483
+ const ndc = cell2(cells, SAT.ATV);
4484
+ const rxcui = cell2(cells, SAT.RXCUI);
4485
+ if (ndc === void 0 || ndc === "" || rxcui === void 0 || rxcui === "") {
4486
+ warnings.push(
4487
+ Object.freeze({
4488
+ code: "TERM_RXNORM_MALFORMED_ROW",
4489
+ file: "RXNSAT",
4490
+ line: i + 1,
4491
+ detail: "NDC attribute row is missing its RXCUI or NDC value"
4492
+ })
4493
+ );
4494
+ continue;
4495
+ }
4496
+ if (!ndcs.has(ndc)) ndcs.set(ndc, Object.freeze({ rxcui, status: "active" }));
4497
+ }
4498
+ return ndcs;
4499
+ }
4500
+ function loadRxNormGraph(source) {
4501
+ const warnings = [];
4502
+ const concepts = parseConso(source.conso, warnings);
4503
+ const { edges, edgeCount } = parseRel(source.rel, warnings);
4504
+ const ndcs = source.sat !== void 0 ? parseNdcs(source.sat, warnings) : /* @__PURE__ */ new Map();
4505
+ for (const list of edges.values()) Object.freeze(list);
4506
+ const out = {
4507
+ concepts,
4508
+ edges,
4509
+ ndcs,
4510
+ conceptCount: concepts.size,
4511
+ edgeCount,
4512
+ warnings: Object.freeze(warnings)
4513
+ };
4514
+ if (source.version !== void 0) out.version = source.version;
4515
+ return Object.freeze(out);
4516
+ }
4517
+
4518
+ // src/rxnorm/rela.ts
4519
+ var RELA = {
4520
+ /** `has_ingredient` — subject (a drug/component) *has ingredient* object (an `IN`/`PIN`). */
4521
+ HAS_INGREDIENT: "has_ingredient",
4522
+ /** `ingredient_of` — subject (an `IN`/`PIN`) *is an ingredient of* object (a drug/component). */
4523
+ INGREDIENT_OF: "ingredient_of",
4524
+ /** `has_precise_ingredient` — subject *has precise ingredient* object (a `PIN`). */
4525
+ HAS_PRECISE_INGREDIENT: "has_precise_ingredient",
4526
+ /** `precise_ingredient_of` — inverse of `has_precise_ingredient`. */
4527
+ PRECISE_INGREDIENT_OF: "precise_ingredient_of",
4528
+ /** `tradename_of` — subject (a branded concept) *is a tradename of* object (its generic). */
4529
+ TRADENAME_OF: "tradename_of",
4530
+ /** `has_tradename` — subject (a generic concept) *has tradename* object (a branded concept). */
4531
+ HAS_TRADENAME: "has_tradename",
4532
+ /** `has_dose_form` — subject (a drug) *has dose form* object (a `DF`). */
4533
+ HAS_DOSE_FORM: "has_dose_form",
4534
+ /** `dose_form_of` — subject (a `DF`) *is the dose form of* object (a drug). */
4535
+ DOSE_FORM_OF: "dose_form_of",
4536
+ /** `has_doseformgroup` — subject *has dose-form group* object (a `DFG`). */
4537
+ HAS_DOSE_FORM_GROUP: "has_doseformgroup",
4538
+ /** `doseformgroup_of` — inverse of `has_doseformgroup`. */
4539
+ DOSE_FORM_GROUP_OF: "doseformgroup_of",
4540
+ /** `consists_of` — subject (an `SCD`/`SBD`) *consists of* object (its `SCDC`/`SBDC` component(s)). */
4541
+ CONSISTS_OF: "consists_of",
4542
+ /** `constitutes` — subject (a component) *constitutes* object (the drug). Inverse of `consists_of`. */
4543
+ CONSTITUTES: "constitutes",
4544
+ /** `contains` — subject (a pack) *contains* object (a member drug). */
4545
+ CONTAINS: "contains",
4546
+ /** `contained_in` — subject (a drug) *is contained in* object (a pack). Inverse of `contains`. */
4547
+ CONTAINED_IN: "contained_in",
4548
+ /** `has_quantified_form` — subject *has quantified form* object. */
4549
+ HAS_QUANTIFIED_FORM: "has_quantified_form",
4550
+ /** `quantified_form_of` — inverse of `has_quantified_form`. */
4551
+ QUANTIFIED_FORM_OF: "quantified_form_of",
4552
+ /** `isa` — subject *is a* object (hierarchical, e.g. `SCD isa SCDG`). */
4553
+ ISA: "isa",
4554
+ /** `inverse_isa` — subject *is a parent of* object. Inverse of `isa`. */
4555
+ INVERSE_ISA: "inverse_isa"
4556
+ };
4557
+ var RELA_INVERSE = Object.freeze({
4558
+ [RELA.HAS_INGREDIENT]: RELA.INGREDIENT_OF,
4559
+ [RELA.INGREDIENT_OF]: RELA.HAS_INGREDIENT,
4560
+ [RELA.HAS_PRECISE_INGREDIENT]: RELA.PRECISE_INGREDIENT_OF,
4561
+ [RELA.PRECISE_INGREDIENT_OF]: RELA.HAS_PRECISE_INGREDIENT,
4562
+ [RELA.TRADENAME_OF]: RELA.HAS_TRADENAME,
4563
+ [RELA.HAS_TRADENAME]: RELA.TRADENAME_OF,
4564
+ [RELA.HAS_DOSE_FORM]: RELA.DOSE_FORM_OF,
4565
+ [RELA.DOSE_FORM_OF]: RELA.HAS_DOSE_FORM,
4566
+ [RELA.HAS_DOSE_FORM_GROUP]: RELA.DOSE_FORM_GROUP_OF,
4567
+ [RELA.DOSE_FORM_GROUP_OF]: RELA.HAS_DOSE_FORM_GROUP,
4568
+ [RELA.CONSISTS_OF]: RELA.CONSTITUTES,
4569
+ [RELA.CONSTITUTES]: RELA.CONSISTS_OF,
4570
+ [RELA.CONTAINS]: RELA.CONTAINED_IN,
4571
+ [RELA.CONTAINED_IN]: RELA.CONTAINS,
4572
+ [RELA.HAS_QUANTIFIED_FORM]: RELA.QUANTIFIED_FORM_OF,
4573
+ [RELA.QUANTIFIED_FORM_OF]: RELA.HAS_QUANTIFIED_FORM,
4574
+ [RELA.ISA]: RELA.INVERSE_ISA,
4575
+ [RELA.INVERSE_ISA]: RELA.ISA
4576
+ });
4577
+ var RXNORM_SYSTEM = "http://www.nlm.nih.gov/research/umls/rxnorm";
4578
+
4579
+ // src/rxnorm/navigate.ts
4580
+ function getConcept(graph, rxcui) {
4581
+ return graph.concepts.get(rxcui);
4582
+ }
4583
+ function follow(graph, rxcui, predicates) {
4584
+ if (!graph.concepts.has(rxcui)) {
4585
+ return Object.freeze({ found: false, code: "TERM_RXNORM_UNKNOWN_RXCUI", rxcui });
4586
+ }
4587
+ const out = [];
4588
+ const seen = /* @__PURE__ */ new Set();
4589
+ for (const edge of graph.edges.get(rxcui) ?? []) {
4590
+ if (!predicates.has(edge.predicate)) continue;
4591
+ if (seen.has(edge.object)) continue;
4592
+ const target = graph.concepts.get(edge.object);
4593
+ if (target !== void 0) {
4594
+ out.push(target);
4595
+ seen.add(edge.object);
4596
+ }
4597
+ }
4598
+ return Object.freeze({
4599
+ found: true,
4600
+ rxcui,
4601
+ predicates: Object.freeze([...predicates]),
4602
+ targets: Object.freeze(out)
4603
+ });
4604
+ }
4605
+ function relatedByRela(graph, rxcui, predicate) {
4606
+ const set = new Set(typeof predicate === "string" ? [predicate] : predicate);
4607
+ return follow(graph, rxcui, set);
4608
+ }
4609
+ function ingredientsOf(graph, rxcui) {
4610
+ return follow(graph, rxcui, /* @__PURE__ */ new Set([RELA.HAS_INGREDIENT, RELA.HAS_PRECISE_INGREDIENT]));
4611
+ }
4612
+ function genericFor(graph, rxcui) {
4613
+ return follow(graph, rxcui, /* @__PURE__ */ new Set([RELA.TRADENAME_OF]));
4614
+ }
4615
+ function brandsFor(graph, rxcui) {
4616
+ return follow(graph, rxcui, /* @__PURE__ */ new Set([RELA.HAS_TRADENAME]));
4617
+ }
4618
+ function doseFormsOf(graph, rxcui) {
4619
+ return follow(graph, rxcui, /* @__PURE__ */ new Set([RELA.HAS_DOSE_FORM, RELA.HAS_DOSE_FORM_GROUP]));
4620
+ }
4621
+ function consistsOf(graph, rxcui) {
4622
+ return follow(graph, rxcui, /* @__PURE__ */ new Set([RELA.CONSISTS_OF]));
4623
+ }
4624
+ function resolveNdc(graph, ndc) {
4625
+ const hit = graph.ndcs.get(ndc);
4626
+ if (hit === void 0) {
4627
+ return Object.freeze({ resolved: false, code: "TERM_RXNORM_NDC_UNMAPPED", ndc });
4628
+ }
4629
+ const out = {
4630
+ resolved: true,
4631
+ ndc,
4632
+ rxcui: hit.rxcui,
4633
+ status: hit.status,
4634
+ ...graph.version !== void 0 ? { asOf: graph.version } : {}
4635
+ };
4636
+ return Object.freeze(out);
4637
+ }
4638
+ function tokenize(name) {
4639
+ return new Set(
4640
+ name.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t !== "")
4641
+ );
4642
+ }
4643
+ function jaccard(a, b) {
4644
+ if (a.size === 0 || b.size === 0) return 0;
4645
+ let inter = 0;
4646
+ for (const t of a) if (b.has(t)) inter++;
4647
+ const union = a.size + b.size - inter;
4648
+ return union === 0 ? 0 : inter / union;
4649
+ }
4650
+ function approximateMatch(graph, query, options = {}) {
4651
+ const minScore = options.minScore ?? 0.34;
4652
+ const limit = options.limit ?? 20;
4653
+ const q = tokenize(query);
4654
+ if (q.size === 0) return Object.freeze([]);
4655
+ const scored = [];
4656
+ for (const concept of graph.concepts.values()) {
4657
+ const score = jaccard(q, tokenize(concept.name));
4658
+ if (score >= minScore) scored.push(Object.freeze({ approximate: true, concept, score }));
4659
+ }
4660
+ scored.sort((a, b) => b.score - a.score || a.concept.rxcui.localeCompare(b.concept.rxcui));
4661
+ return Object.freeze(scored.slice(0, limit));
4662
+ }
4663
+
4664
+ // src/index.ts
4665
+ var VERSION = "0.0.0";
4666
+
4667
+ export { COMPLEX_MAP_SOURCE_SYSTEM, DIAGNOSTIC_CODES, FATAL_CODES, HL7_V2_OID_ROOT, HL7_V2_URL_PREFIX, ICD10CM_ORDER_FILE_FIELDS, ICD10CM_SYSTEM, ICD9CM_SYSTEM, MAP_CATEGORIES, NO_MAP_CATEGORIES, RELA, RELA_INVERSE, RXNORM_SYSTEM, SNOMEDCT_SYSTEM, SYSTEM_IDENTITIES, TERM_TYPES, TerminologyError, VERSION, applyComplexMap, applyGem, approximateMatch, asTermType, brandsFor, buildSubsumption, codeableConcept, coding, consistsOf, defaultStatusMapper, doseFormsOf, expand, genericFor, getArray, getBoolean, getConcept, getNumber, getString, ingredientsOf, invertGem, isA, isJsonObject, isUnknownSystem, loadCodeSystem, loadComplexMap, loadConceptMap, loadGems, loadRxNormGraph, loadUcumEssence, loadValueSet, lookup, makeStatus, matchesFilter, parseCsv, parseCsvSource, parseFhirCodeSystem, parseFixedWidth, parseRrf, parseRrfLine, parseUcum, reduce, relatedByRela, resolveNdc, resolveSystem, sliceField, translate, ucumEqual, unsupportedOps, validateCode, validateCodeInValueSet, validateUcum };
4668
+ //# sourceMappingURL=index.mjs.map
4669
+ //# sourceMappingURL=index.mjs.map