<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://invarians.org/index.php?action=history&amp;feed=atom&amp;title=The_Principia_Machina%2FTPC-PY%2Ftpc_units.py</id>
	<title>The Principia Machina/TPC-PY/tpc units.py - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://invarians.org/index.php?action=history&amp;feed=atom&amp;title=The_Principia_Machina%2FTPC-PY%2Ftpc_units.py"/>
	<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY/tpc_units.py&amp;action=history"/>
	<updated>2026-10-21T11:16:25Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.46.2</generator>
	<entry>
		<id>https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY/tpc_units.py&amp;diff=4893&amp;oldid=prev</id>
		<title>BFP Rauch: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY/tpc_units.py&amp;diff=4893&amp;oldid=prev"/>
		<updated>2026-09-30T02:11:04Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw-interface=&quot;&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 02:11, 30 September 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;4&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key pma_cutover_20261020t051351z-soft_:diff:1.41:old-4892:rev-4893 --&gt;
&lt;/table&gt;</summary>
		<author><name>BFP Rauch</name></author>
	</entry>
	<entry>
		<id>https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY/tpc_units.py&amp;diff=4892&amp;oldid=prev</id>
		<title>BFP Rauch: TPC-PY source tpc_units.py (0.1.2), SHA-256 be8b289b1eca5ae4; conformed TPS 0.4.0; PROPOSED, not declared (TPC-PY 0.2.0)</title>
		<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY/tpc_units.py&amp;diff=4892&amp;oldid=prev"/>
		<updated>2026-09-30T02:10:58Z</updated>

		<summary type="html">&lt;p&gt;TPC-PY source tpc_units.py (0.1.2), SHA-256 be8b289b1eca5ae4; conformed TPS 0.4.0; PROPOSED, not declared (TPC-PY 0.2.0)&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw-interface=&quot;&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 02:10, 30 September 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l83&quot;&gt;Line 83:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 83:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;import tpc_zone as Z&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;import tpc_zone as Z&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;TPC_UNITS_VERSION = &quot;0.1.&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;1&lt;/del&gt;&quot;    # proposed PATCH &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;label &lt;/del&gt;(S15&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;)&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;TPC_UNITS_VERSION = &quot;0.1.&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;2&lt;/ins&gt;&quot;    # proposed PATCH &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;with TPC-PY 0.2.0 &lt;/ins&gt;(&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;C-MS-5: TPC-PHP reads the JSON as written, a {} apart from a []); 0.1.1: &lt;/ins&gt;S15&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#          symbol    L  M  T  I TH  N  J   factor           prefixable&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;#          symbol    L  M  T  I TH  N  J   factor           prefixable&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>BFP Rauch</name></author>
	</entry>
	<entry>
		<id>https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY/tpc_units.py&amp;diff=4239&amp;oldid=prev</id>
		<title>BFP Rauch: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY/tpc_units.py&amp;diff=4239&amp;oldid=prev"/>
		<updated>2026-09-28T04:37:36Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw-interface=&quot;&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 04:37, 28 September 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;4&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key pma_cutover_20261020t051351z-soft_:diff:1.41:old-4238:rev-4239 --&gt;
&lt;/table&gt;</summary>
		<author><name>BFP Rauch</name></author>
	</entry>
	<entry>
		<id>https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY/tpc_units.py&amp;diff=4238&amp;oldid=prev</id>
		<title>BFP Rauch: TPC-PY source tpc_units.py (0.1.1), SHA-256 137880e759657453; conformed TPS 0.3.0; PROPOSED, not declared (CO-8)</title>
		<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY/tpc_units.py&amp;diff=4238&amp;oldid=prev"/>
		<updated>2026-09-27T15:43:18Z</updated>

		<summary type="html">&lt;p&gt;TPC-PY source tpc_units.py (0.1.1), SHA-256 137880e759657453; conformed TPS 0.3.0; PROPOSED, not declared (CO-8)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;# -*- coding: utf-8 -*-&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
TPC-PY --- units (TPC step 2, increment 6) --- SELECTED D103.1-D105.1&lt;br /&gt;
=====================================================================&lt;br /&gt;
SELECTED 2026-09-22: D103.1 (this grammar and catalogue), D104.1 (UNIT&lt;br /&gt;
checked and canonicalized at zone entry; tpc_zone 0.3.0), D105.1 (KIND at&lt;br /&gt;
the test; CONVENTION on a difference). Spec: tpm_units 0.2.0.&lt;br /&gt;
The unit grammar, the commensurability check C-32 asks for (TPS 3.2.9), and&lt;br /&gt;
the normalization D40 requires before any contradiction test (&amp;quot;TPX&lt;br /&gt;
normalizes before any contradiction test and refuses a cross-entry M-M&lt;br /&gt;
test&amp;quot;). D103.1: a DIMENSION-style ASCII token grammar over a closed SI&lt;br /&gt;
catalogue. Standard library only; Python 3.8+; Windows/Linux.&lt;br /&gt;
&lt;br /&gt;
GRAMMAR&lt;br /&gt;
  UNIT   := &amp;quot;1&amp;quot; | token ( &amp;quot; &amp;quot; token )*          single spaces, ASCII only&lt;br /&gt;
  token  := [prefix] symbol [exponent]          exponent := -?[0-9]{1,4}&lt;br /&gt;
  A token&amp;#039;s exponent applies to the prefixed symbol: cm2 = (0.01 m)^2.&lt;br /&gt;
  An absent exponent is 1; a zero exponent drops the token.&lt;br /&gt;
&lt;br /&gt;
CATALOGUE (order is the canonical order)&lt;br /&gt;
  SI base, with the gram in place of the kilogram so that kg = k + g:&lt;br /&gt;
      m g s A K mol cd&lt;br /&gt;
  SI dimensionless: rad sr&lt;br /&gt;
  SI derived with special names, degree Celsius excluded (affine):&lt;br /&gt;
      Hz N Pa J W C V F Ohm S Wb T H lm lx Bq Gy Sv kat&lt;br /&gt;
  SI Table 8, ratio units with an exactly defined value:&lt;br /&gt;
      min h d au deg arcmin arcsec ha L t eV&lt;br /&gt;
  Refused, with the reason recorded: degC (an offset, not a ratio); Da&lt;br /&gt;
  (its value is measured, with an uncertainty the conversion would have&lt;br /&gt;
  to carry); Np, B, dB (logarithmic).&lt;br /&gt;
  Prefixes: the 24 SI prefixes q r y z a f p n u m c d da h k M G T P E Z Y R Q&lt;br /&gt;
  (u for micro, ASCII). Prefixable: every SI unit (including g, rad, sr),&lt;br /&gt;
  L, eV, arcsec and t. Not prefixable: min h d (the SI Brochure forbids&lt;br /&gt;
  prefixes on the non-SI units of time), ha (already a prefixed unit), au,&lt;br /&gt;
  deg, arcmin. The Brochure names mas, uas, pas and prefixed eV; it is&lt;br /&gt;
  silent on t, whose kt, Mt, Gt are in wide use. kg takes no second&lt;br /&gt;
  prefix (write Mg, not kkg).&lt;br /&gt;
  Every string parses in at most one way: the module asserts it at import.&lt;br /&gt;
  Every merged exponent, and every exponent of the resulting DIMENSION,&lt;br /&gt;
  lies within -9999..9999, so a canonical spelling and its DIMENSION always&lt;br /&gt;
  parse again. S15 (tpc_units 0.1.1, proposed): C-32 refuses a DIMENSION&lt;br /&gt;
  whose repeated bases sum outside that range with the same words,&lt;br /&gt;
  &amp;quot;DIMENSION &amp;lt;D&amp;gt;: an exponent is out of range&amp;quot; (tpc_zone 0.4.1). A KIND is&lt;br /&gt;
  derived, written by no author and entering no preimage; it is not bounded&lt;br /&gt;
  here, and tpc_form refuses one past 9999 where it reads it (S14).&lt;br /&gt;
&lt;br /&gt;
KIND (D105.1)&lt;br /&gt;
  The SI treats the radian and the steradian as the number one, so Hz and&lt;br /&gt;
  rad s-1 share a dimension while a value in one is 2 pi times the value in&lt;br /&gt;
  the other; the SI also names Bq, Gy and Sv for kinds that share a&lt;br /&gt;
  dimension with Hz and J kg-1. Each canonical unit therefore carries a&lt;br /&gt;
  KIND: the exponents of angle (rad, deg, arcmin, arcsec; sr counts as&lt;br /&gt;
  rad2 and so do lm and lx), of Hz, Bq, Gy and Sv, written &amp;quot;rad2 Hz-1&amp;quot;,&lt;br /&gt;
  or &amp;quot;none&amp;quot;. Two values are compared only when DIMENSION and KIND both&lt;br /&gt;
  agree. A KIND difference is a convention difference: the result is&lt;br /&gt;
  [&amp;quot;CONVENTION&amp;quot;, reason], on which TPX opens an audit block (TPS 4.4.4,&lt;br /&gt;
  row 43); it is never compared, and never refused as an error.&lt;br /&gt;
&lt;br /&gt;
CANONICAL SPELLING&lt;br /&gt;
  Tokens with the same prefixed symbol merge (exponents add); zero&lt;br /&gt;
  exponents drop; tokens sort by the symbol&amp;#039;s catalogue position, then by&lt;br /&gt;
  the prefix&amp;#039;s power of ten; exponent 1 is not written; &amp;quot;1&amp;quot; if none&lt;br /&gt;
  remain. &amp;quot;s-2 m kg&amp;quot; -&amp;gt; &amp;quot;m kg s-2&amp;quot;. Only spelling is canonical: &amp;quot;km m&amp;quot; is&lt;br /&gt;
  &amp;quot;m km&amp;quot;, not &amp;quot;1e3 m2&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
NUMBERS&lt;br /&gt;
  The scale of a unit to coherent SI is computed in IEEE doubles in a fixed&lt;br /&gt;
  order - per canonical token, prefix factor times symbol factor, raised to&lt;br /&gt;
  its exponent by repeated multiplication (one division for a negative&lt;br /&gt;
  exponent), then multiplied into the product in canonical order - so both&lt;br /&gt;
  residences produce the same bits. Decimal factors are parsed from their&lt;br /&gt;
  exact strings; deg, arcmin and arcsec use pi / 180, pi / 10800 and&lt;br /&gt;
  pi / 648000. A scale that overflows or underflows to zero is refused.&lt;br /&gt;
&lt;br /&gt;
REFUSED, as [&amp;quot;REFUSED&amp;quot;, reason], never raised; reasons escape what they&lt;br /&gt;
quote (zone schemas 6.3).&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
import math&lt;br /&gt;
import re&lt;br /&gt;
&lt;br /&gt;
import tpc_strike as S&lt;br /&gt;
import tpc_zone as Z&lt;br /&gt;
&lt;br /&gt;
TPC_UNITS_VERSION = &amp;quot;0.1.1&amp;quot;    # proposed PATCH label (S15)&lt;br /&gt;
&lt;br /&gt;
#          symbol    L  M  T  I TH  N  J   factor           prefixable&lt;br /&gt;
CATALOGUE = [&lt;br /&gt;
    (&amp;quot;m&amp;quot;,      (1, 0, 0, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;g&amp;quot;,      (0, 1, 0, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1e-3&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;s&amp;quot;,      (0, 0, 1, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;A&amp;quot;,      (0, 0, 0, 1, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;K&amp;quot;,      (0, 0, 0, 0, 1, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;mol&amp;quot;,    (0, 0, 0, 0, 0, 1, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;cd&amp;quot;,     (0, 0, 0, 0, 0, 0, 1), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;rad&amp;quot;,    (0, 0, 0, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;sr&amp;quot;,     (0, 0, 0, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;Hz&amp;quot;,     (0, 0, -1, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;N&amp;quot;,      (1, 1, -2, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;Pa&amp;quot;,     (-1, 1, -2, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;J&amp;quot;,      (2, 1, -2, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;W&amp;quot;,      (2, 1, -3, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;C&amp;quot;,      (0, 0, 1, 1, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;V&amp;quot;,      (2, 1, -3, -1, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;F&amp;quot;,      (-2, -1, 4, 2, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;Ohm&amp;quot;,    (2, 1, -3, -2, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;S&amp;quot;,      (-2, -1, 3, 2, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;Wb&amp;quot;,     (2, 1, -2, -1, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;T&amp;quot;,      (0, 1, -2, -1, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;H&amp;quot;,      (2, 1, -2, -2, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;lm&amp;quot;,     (0, 0, 0, 0, 0, 0, 1), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;lx&amp;quot;,     (-2, 0, 0, 0, 0, 0, 1), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;Bq&amp;quot;,     (0, 0, -1, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;Gy&amp;quot;,     (2, 0, -2, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;Sv&amp;quot;,     (2, 0, -2, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;kat&amp;quot;,    (0, 0, -1, 0, 0, 1, 0), (&amp;quot;d&amp;quot;, &amp;quot;1&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;min&amp;quot;,    (0, 0, 1, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;60&amp;quot;), False),&lt;br /&gt;
    (&amp;quot;h&amp;quot;,      (0, 0, 1, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;3600&amp;quot;), False),&lt;br /&gt;
    (&amp;quot;d&amp;quot;,      (0, 0, 1, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;86400&amp;quot;), False),&lt;br /&gt;
    (&amp;quot;au&amp;quot;,     (1, 0, 0, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;149597870700&amp;quot;), False),&lt;br /&gt;
    (&amp;quot;deg&amp;quot;,    (0, 0, 0, 0, 0, 0, 0), (&amp;quot;pi&amp;quot;, 180), False),&lt;br /&gt;
    (&amp;quot;arcmin&amp;quot;, (0, 0, 0, 0, 0, 0, 0), (&amp;quot;pi&amp;quot;, 10800), False),&lt;br /&gt;
    (&amp;quot;arcsec&amp;quot;, (0, 0, 0, 0, 0, 0, 0), (&amp;quot;pi&amp;quot;, 648000), True),&lt;br /&gt;
    (&amp;quot;ha&amp;quot;,     (2, 0, 0, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1e4&amp;quot;), False),&lt;br /&gt;
    (&amp;quot;L&amp;quot;,      (3, 0, 0, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1e-3&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;t&amp;quot;,      (0, 1, 0, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1e3&amp;quot;), True),&lt;br /&gt;
    (&amp;quot;eV&amp;quot;,     (2, 1, -2, 0, 0, 0, 0), (&amp;quot;d&amp;quot;, &amp;quot;1.602176634e-19&amp;quot;), True),&lt;br /&gt;
]&lt;br /&gt;
# KIND contributions per unit symbol: (angle, Hz, Bq, Gy, Sv)&lt;br /&gt;
KIND_BASES = [&amp;quot;rad&amp;quot;, &amp;quot;Hz&amp;quot;, &amp;quot;Bq&amp;quot;, &amp;quot;Gy&amp;quot;, &amp;quot;Sv&amp;quot;]&lt;br /&gt;
KIND_OF = {&amp;quot;rad&amp;quot;: (1, 0, 0, 0, 0), &amp;quot;deg&amp;quot;: (1, 0, 0, 0, 0), &amp;quot;arcmin&amp;quot;: (1, 0, 0, 0, 0),&lt;br /&gt;
           &amp;quot;arcsec&amp;quot;: (1, 0, 0, 0, 0), &amp;quot;sr&amp;quot;: (2, 0, 0, 0, 0), &amp;quot;lm&amp;quot;: (2, 0, 0, 0, 0),&lt;br /&gt;
           &amp;quot;lx&amp;quot;: (2, 0, 0, 0, 0), &amp;quot;Hz&amp;quot;: (0, 1, 0, 0, 0), &amp;quot;Bq&amp;quot;: (0, 0, 1, 0, 0),&lt;br /&gt;
           &amp;quot;Gy&amp;quot;: (0, 0, 0, 1, 0), &amp;quot;Sv&amp;quot;: (0, 0, 0, 0, 1)}&lt;br /&gt;
EXP_MAX = 9999&lt;br /&gt;
&lt;br /&gt;
REFUSED_UNITS = {&lt;br /&gt;
    &amp;quot;degC&amp;quot;: &amp;quot;an offset scale, not a ratio&amp;quot;,&lt;br /&gt;
    &amp;quot;Da&amp;quot;: &amp;quot;a measured value; the conversion would carry an uncertainty&amp;quot;,&lt;br /&gt;
    &amp;quot;Np&amp;quot;: &amp;quot;a logarithmic scale&amp;quot;, &amp;quot;B&amp;quot;: &amp;quot;a logarithmic scale&amp;quot;, &amp;quot;dB&amp;quot;: &amp;quot;a logarithmic scale&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
PREFIXES = [(&amp;quot;q&amp;quot;, -30), (&amp;quot;r&amp;quot;, -27), (&amp;quot;y&amp;quot;, -24), (&amp;quot;z&amp;quot;, -21), (&amp;quot;a&amp;quot;, -18), (&amp;quot;f&amp;quot;, -15),&lt;br /&gt;
            (&amp;quot;p&amp;quot;, -12), (&amp;quot;n&amp;quot;, -9), (&amp;quot;u&amp;quot;, -6), (&amp;quot;m&amp;quot;, -3), (&amp;quot;c&amp;quot;, -2), (&amp;quot;d&amp;quot;, -1),&lt;br /&gt;
            (&amp;quot;da&amp;quot;, 1), (&amp;quot;h&amp;quot;, 2), (&amp;quot;k&amp;quot;, 3), (&amp;quot;M&amp;quot;, 6), (&amp;quot;G&amp;quot;, 9), (&amp;quot;T&amp;quot;, 12),&lt;br /&gt;
            (&amp;quot;P&amp;quot;, 15), (&amp;quot;E&amp;quot;, 18), (&amp;quot;Z&amp;quot;, 21), (&amp;quot;Y&amp;quot;, 24), (&amp;quot;R&amp;quot;, 27), (&amp;quot;Q&amp;quot;, 30)]&lt;br /&gt;
&lt;br /&gt;
_SYM = dict((c[0], (i, c[1], c[2], c[3])) for i, c in enumerate(CATALOGUE))&lt;br /&gt;
_PRE = dict(PREFIXES)&lt;br /&gt;
_TOKEN = re.compile(r&amp;quot;([A-Za-z]+)(-?[0-9]{1,4})?\Z&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def _readings(letters):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Every (prefix, symbol) reading of a token&amp;#039;s letters, prefix None for&lt;br /&gt;
    a bare symbol; only prefixable symbols take a prefix.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    out = []&lt;br /&gt;
    if letters in _SYM:&lt;br /&gt;
        out.append((None, letters))&lt;br /&gt;
    for p in _PRE:&lt;br /&gt;
        rest = letters[len(p):]&lt;br /&gt;
        if letters.startswith(p) and rest in _SYM and _SYM[rest][3]:&lt;br /&gt;
            out.append((p, rest))&lt;br /&gt;
    return out&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def _assert_unambiguous():&lt;br /&gt;
    seen = {}&lt;br /&gt;
    for sym in _SYM:&lt;br /&gt;
        seen.setdefault(sym, []).append((None, sym))&lt;br /&gt;
        if _SYM[sym][3]:&lt;br /&gt;
            for p in _PRE:&lt;br /&gt;
                seen.setdefault(p + sym, []).append((p, sym))&lt;br /&gt;
    for s, rs in seen.items():&lt;br /&gt;
        assert len(rs) == 1, &amp;quot;ambiguous unit token %s: %r&amp;quot; % (s, rs)&lt;br /&gt;
        assert s not in REFUSED_UNITS, s&lt;br /&gt;
    return len(seen)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TOKEN_COUNT = _assert_unambiguous()          # every string parses at most one way&lt;br /&gt;
assert TOKEN_COUNT == 807, &amp;quot;unit catalogue changed&amp;quot;   # TPC-PHP checks the same count&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def _refuse(msg):&lt;br /&gt;
    return [&amp;quot;REFUSED&amp;quot;, Z._show(msg)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def _q(x):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;What a reason quotes: the string itself, or ? for anything else.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    return x if isinstance(x, str) else &amp;quot;?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def _tokens(u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;[(prefix, symbol, exponent), ...] merged, or a reason string.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if not isinstance(u, str) or u == &amp;quot;&amp;quot;:&lt;br /&gt;
        return &amp;quot;UNIT %s is not a unit&amp;quot; % _q(u)&lt;br /&gt;
    if u == &amp;quot;1&amp;quot;:&lt;br /&gt;
        return []&lt;br /&gt;
    merged = {}&lt;br /&gt;
    for tok in u.split(&amp;quot; &amp;quot;):&lt;br /&gt;
        m = _TOKEN.match(tok)&lt;br /&gt;
        if not m:&lt;br /&gt;
            return &amp;quot;UNIT %s is not a unit&amp;quot; % u&lt;br /&gt;
        letters, ex = m.group(1), int(m.group(2)) if m.group(2) else 1&lt;br /&gt;
        if letters in REFUSED_UNITS:&lt;br /&gt;
            return &amp;quot;UNIT %s: %s is refused, %s&amp;quot; % (u, letters, REFUSED_UNITS[letters])&lt;br /&gt;
        rs = _readings(letters)&lt;br /&gt;
        if not rs:&lt;br /&gt;
            for p in _PRE:&lt;br /&gt;
                rest = letters[len(p):]&lt;br /&gt;
                if letters.startswith(p) and rest in REFUSED_UNITS:&lt;br /&gt;
                    return &amp;quot;UNIT %s: %s is refused, %s&amp;quot; % (u, rest, REFUSED_UNITS[rest])&lt;br /&gt;
            for p in _PRE:&lt;br /&gt;
                rest = letters[len(p):]&lt;br /&gt;
                if letters.startswith(p) and rest in _SYM:&lt;br /&gt;
                    return &amp;quot;UNIT %s: %s takes no prefix&amp;quot; % (u, rest)&lt;br /&gt;
            return &amp;quot;UNIT %s: %s is not a unit symbol&amp;quot; % (u, letters)&lt;br /&gt;
        key = rs[0]&lt;br /&gt;
        merged[key] = merged.get(key, 0) + ex&lt;br /&gt;
    items = [(p, s, e) for (p, s), e in merged.items() if e != 0]&lt;br /&gt;
    items.sort(key=lambda t: (_SYM[t[1]][0], _PRE[t[0]] if t[0] else 0))&lt;br /&gt;
    if any(abs(e) &amp;gt; EXP_MAX for p, s, e in items) or \&lt;br /&gt;
            any(abs(x) &amp;gt; EXP_MAX for x in _dim_exps(items)):&lt;br /&gt;
        return &amp;quot;UNIT %s: an exponent is out of range&amp;quot; % u&lt;br /&gt;
    return items&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def _spell(items):&lt;br /&gt;
    if not items:&lt;br /&gt;
        return &amp;quot;1&amp;quot;&lt;br /&gt;
    return &amp;quot; &amp;quot;.join((p or &amp;quot;&amp;quot;) + s + (&amp;quot;&amp;quot; if e == 1 else str(e)) for p, s, e in items)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def _dim_exps(items):&lt;br /&gt;
    exps = [0] * len(Z.DIM_BASES)&lt;br /&gt;
    for p, s, e in items:&lt;br /&gt;
        for j, d in enumerate(_SYM[s][1]):&lt;br /&gt;
            exps[j] += d * e&lt;br /&gt;
    return exps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def _dimension(items):&lt;br /&gt;
    return Z.canon_dimension(dict(zip(Z.DIM_BASES, _dim_exps(items))))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def _kind(items):&lt;br /&gt;
    k = [0] * len(KIND_BASES)&lt;br /&gt;
    for p, s, e in items:&lt;br /&gt;
        if s in KIND_OF:&lt;br /&gt;
            for j, c in enumerate(KIND_OF[s]):&lt;br /&gt;
                k[j] += c * e&lt;br /&gt;
    toks = [KIND_BASES[j] + str(k[j]) for j in range(len(KIND_BASES)) if k[j] != 0]&lt;br /&gt;
    return &amp;quot; &amp;quot;.join(toks) if toks else &amp;quot;none&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def _symbol_factor(s):&lt;br /&gt;
    kind, v = _SYM[s][2]&lt;br /&gt;
    return float(v) if kind == &amp;quot;d&amp;quot; else math.pi / v&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def _scale(items):&lt;br /&gt;
    total = 1.0&lt;br /&gt;
    for p, s, e in items:&lt;br /&gt;
        base = _symbol_factor(s)&lt;br /&gt;
        if p is not None:&lt;br /&gt;
            base = float(&amp;quot;1e%d&amp;quot; % _PRE[p]) * base&lt;br /&gt;
        r = 1.0&lt;br /&gt;
        for _ in range(abs(e)):&lt;br /&gt;
            r = r * base&lt;br /&gt;
        if e &amp;lt; 0:&lt;br /&gt;
            r = math.inf if r == 0.0 else 1.0 / r     # no division by zero in either residence&lt;br /&gt;
        total = total * r&lt;br /&gt;
    return total&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def unit_parse(u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;[&amp;quot;OK&amp;quot;, canonical spelling, canonical DIMENSION, KIND] or [&amp;quot;REFUSED&amp;quot;, reason].&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    items = _tokens(u)&lt;br /&gt;
    if isinstance(items, str):&lt;br /&gt;
        return _refuse(items)&lt;br /&gt;
    return [&amp;quot;OK&amp;quot;, _spell(items), _dimension(items), _kind(items)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def unit_scale(u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;[&amp;quot;OK&amp;quot;, the factor to coherent SI as a double] or [&amp;quot;REFUSED&amp;quot;, reason].&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    items = _tokens(u)&lt;br /&gt;
    if isinstance(items, str):&lt;br /&gt;
        return _refuse(items)&lt;br /&gt;
    f = _scale(items)&lt;br /&gt;
    if f == 0.0 or not math.isfinite(f):&lt;br /&gt;
        return _refuse(&amp;quot;UNIT %s has no finite scale&amp;quot; % u)&lt;br /&gt;
    return [&amp;quot;OK&amp;quot;, f]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def unit_matches(u, dimension):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;C-32: [&amp;quot;OK&amp;quot;, true or false] - the UNIT is commensurable with the&lt;br /&gt;
    DIMENSION - or [&amp;quot;REFUSED&amp;quot;, reason] when either does not parse.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    r = unit_parse(u)&lt;br /&gt;
    if r[0] != &amp;quot;OK&amp;quot;:&lt;br /&gt;
        return r&lt;br /&gt;
    d = Z.normalize_dimension(dimension)&lt;br /&gt;
    if d is None:&lt;br /&gt;
        if Z.dimension_out_of_range(dimension):                           # S15&lt;br /&gt;
            return _refuse(&amp;quot;DIMENSION %s: an exponent is out of range&amp;quot; % dimension)&lt;br /&gt;
        return _refuse(&amp;quot;DIMENSION %s is not a dimension&amp;quot; % _q(dimension))&lt;br /&gt;
    return [&amp;quot;OK&amp;quot;, r[2] == d]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def normalize_measurement(value, uncertainty, u):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;D40: a VALUE and its UNCERTAINTY (decimal strings) in UNIT, scaled to&lt;br /&gt;
    coherent SI: [&amp;quot;OK&amp;quot;, x_SI, u_SI, DIMENSION, KIND] or [&amp;quot;REFUSED&amp;quot;, reason].&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if Z.canon_decimal(value) is None:&lt;br /&gt;
        return _refuse(&amp;quot;VALUE %s is not a decimal&amp;quot; % _q(value))&lt;br /&gt;
    if Z.canon_decimal(uncertainty) is None:&lt;br /&gt;
        return _refuse(&amp;quot;UNCERTAINTY %s is not a decimal&amp;quot; % _q(uncertainty))&lt;br /&gt;
    if Z._dec_sign(uncertainty) &amp;lt; 0:&lt;br /&gt;
        return _refuse(&amp;quot;UNCERTAINTY %s is negative&amp;quot; % uncertainty)&lt;br /&gt;
    items = _tokens(u)&lt;br /&gt;
    if isinstance(items, str):&lt;br /&gt;
        return _refuse(items)&lt;br /&gt;
    f = _scale(items)&lt;br /&gt;
    if f == 0.0 or not math.isfinite(f):&lt;br /&gt;
        return _refuse(&amp;quot;UNIT %s has no finite scale&amp;quot; % u)&lt;br /&gt;
    x = float(value) * f&lt;br /&gt;
    su = float(uncertainty) * f&lt;br /&gt;
    if not (math.isfinite(x) and math.isfinite(su)):&lt;br /&gt;
        return _refuse(&amp;quot;VALUE %s in UNIT %s is not a finite double&amp;quot; % (value, u))&lt;br /&gt;
    return [&amp;quot;OK&amp;quot;, x + 0.0, su + 0.0, _dimension(items), _kind(items)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def _convention(k1, k2):&lt;br /&gt;
    return [&amp;quot;CONVENTION&amp;quot;, &amp;quot;units of different kind: %s and %s&amp;quot; % (k1, k2)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def _pair(a, b):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Normalize two measurements; refuse unless they share a dimension;&lt;br /&gt;
    CONVENTION unless they share a kind.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ra = normalize_measurement(*a)&lt;br /&gt;
    if ra[0] != &amp;quot;OK&amp;quot;:&lt;br /&gt;
        return ra, None&lt;br /&gt;
    rb = normalize_measurement(*b)&lt;br /&gt;
    if rb[0] != &amp;quot;OK&amp;quot;:&lt;br /&gt;
        return rb, None&lt;br /&gt;
    if ra[3] != rb[3]:&lt;br /&gt;
        return _refuse(&amp;quot;units of different dimension: %s and %s&amp;quot; % (ra[3], rb[3])), None&lt;br /&gt;
    if ra[4] != rb[4]:&lt;br /&gt;
        return _convention(ra[4], rb[4]), None&lt;br /&gt;
    return ra, rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def mm_contradicts_units(x1, u1, unit1, x2, u2, unit2, k, s=1.0):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;SR3 M-M after normalization: [&amp;quot;OK&amp;quot;, bool], [&amp;quot;CONVENTION&amp;quot;, reason] or&lt;br /&gt;
    [&amp;quot;REFUSED&amp;quot;, reason].&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ra, rb = _pair((x1, u1, unit1), (x2, u2, unit2))&lt;br /&gt;
    if rb is None:&lt;br /&gt;
        return ra&lt;br /&gt;
    return [&amp;quot;OK&amp;quot;, S.mm_contradicts(ra[1], ra[2], rb[1], rb[2], k, s)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def lm_contradicts_units(x_l, unit_l, x_m, u_m, unit_m, k, s=1.0):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;SR3 L-M after normalization: the L value carries no uncertainty.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ra, rb = _pair((x_l, &amp;quot;0&amp;quot;, unit_l), (x_m, u_m, unit_m))&lt;br /&gt;
    if rb is None:&lt;br /&gt;
        return ra&lt;br /&gt;
    return [&amp;quot;OK&amp;quot;, S.lm_contradicts(ra[1], rb[1], rb[2], k, s)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def sr8_scale_factor_units(measurements):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;SR8 over [{&amp;quot;x&amp;quot;, &amp;quot;u&amp;quot;, &amp;quot;unit&amp;quot;}, ...] of one dimension and kind, after&lt;br /&gt;
    normalization: [&amp;quot;OK&amp;quot;, S], [&amp;quot;CONVENTION&amp;quot;, reason] or [&amp;quot;REFUSED&amp;quot;, reason].&lt;br /&gt;
    Every record is normalized first; a refusal outranks a convention&lt;br /&gt;
    difference, which outranks a missing uncertainty.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    norm, dim, kind, conv = [], None, None, None&lt;br /&gt;
    for m in measurements:&lt;br /&gt;
        r = normalize_measurement(m[&amp;quot;x&amp;quot;], m[&amp;quot;u&amp;quot;], m[&amp;quot;unit&amp;quot;])&lt;br /&gt;
        if r[0] != &amp;quot;OK&amp;quot;:&lt;br /&gt;
            return r&lt;br /&gt;
        if dim is None:&lt;br /&gt;
            dim, kind = r[3], r[4]&lt;br /&gt;
        elif r[3] != dim:&lt;br /&gt;
            return _refuse(&amp;quot;units of different dimension: %s and %s&amp;quot; % (dim, r[3]))&lt;br /&gt;
        elif r[4] != kind and conv is None:&lt;br /&gt;
            conv = _convention(kind, r[4])&lt;br /&gt;
        norm.append(r)&lt;br /&gt;
    if conv is not None:&lt;br /&gt;
        return conv&lt;br /&gt;
    out = []&lt;br /&gt;
    for r in norm:&lt;br /&gt;
        if r[2] &amp;lt;= 0.0:&lt;br /&gt;
            return _refuse(&amp;quot;every M record needs an uncertainty above zero&amp;quot;)&lt;br /&gt;
        out.append({&amp;quot;x&amp;quot;: r[1], &amp;quot;u&amp;quot;: r[2]})&lt;br /&gt;
    return [&amp;quot;OK&amp;quot;, S.sr8_scale_factor(out)]&lt;br /&gt;
&lt;/div&gt;</summary>
		<author><name>BFP Rauch</name></author>
	</entry>
</feed>