mirror of
https://github.com/ganelson/inform.git
synced 2024-07-08 18:14:21 +03:00
2049 lines
224 KiB
HTML
2049 lines
224 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>2/dk</title>
|
|
<meta name="viewport" content="width=device-width initial-scale=1">
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<meta http-equiv="Content-Language" content="en-gb">
|
|
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
</head>
|
|
<body>
|
|
<nav role="navigation">
|
|
<h1><a href="../webs.html">Sources</a></h1>
|
|
<ul>
|
|
<li><a href="../compiler.html"><b>compiler</b></a></li>
|
|
<li><a href="../other.html">other tools</a></li>
|
|
<li><a href="../extensions.html">extensions and kits</a></li>
|
|
<li><a href="../units.html">unit test tools</a></li>
|
|
</ul>
|
|
<h2>Compiler Webs</h2>
|
|
<ul>
|
|
<li><a href="../inbuild/index.html">inbuild</a></li>
|
|
<li><a href="../inform7/index.html">inform7</a></li>
|
|
<li><a href="../inter/index.html">inter</a></li>
|
|
</ul>
|
|
<h2>Inbuild Modules</h2>
|
|
<ul>
|
|
<li><a href="../inbuild-module/index.html">inbuild</a></li>
|
|
<li><a href="../arch-module/index.html">arch</a></li>
|
|
<li><a href="../words-module/index.html">words</a></li>
|
|
<li><a href="../syntax-module/index.html">syntax</a></li>
|
|
<li><a href="../html-module/index.html">html</a></li>
|
|
</ul>
|
|
<h2>Inform7 Modules</h2>
|
|
<ul>
|
|
<li><a href="../core-module/index.html">core</a></li>
|
|
<li><a href="../problems-module/index.html">problems</a></li>
|
|
<li><a href="../inflections-module/index.html">inflections</a></li>
|
|
<li><a href="../linguistics-module/index.html">linguistics</a></li>
|
|
<li><a href="../kinds-module/index.html">kinds</a></li>
|
|
<li><a href="../if-module/index.html">if</a></li>
|
|
<li><a href="../multimedia-module/index.html">multimedia</a></li>
|
|
<li><a href="../index-module/index.html">index</a></li>
|
|
</ul>
|
|
<h2>Inter Modules</h2>
|
|
<ul>
|
|
<li><a href="../inter-module/index.html">inter</a></li>
|
|
<li><a href="../building-module/index.html">building</a></li>
|
|
<li><a href="../codegen-module/index.html">codegen</a></li>
|
|
</ul>
|
|
<h2>Foundation</h2>
|
|
<ul>
|
|
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
|
|
</ul>
|
|
|
|
|
|
</nav>
|
|
<main role="main">
|
|
|
|
<!--Weave of '2/dmn' generated by 7-->
|
|
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="../compiler.html">Compiler Modules</a></li><li><a href="index.html">kinds</a></li><li><a href="index.html#2">Chapter 2: Kinds</a></li><li><b>Dimensions</b></li></ul><p class="purpose">To keep a small database indicating the physical dimensions of numerical values, and how they combine: for instance, allowing us to specify that a length times a length is an area.</p>
|
|
|
|
<ul class="toc"><li><a href="#SP1">§1. Definitions</a></li><li><a href="#SP14">§14. Prior kinds</a></li><li><a href="#SP15">§15. Multiplication lists</a></li><li><a href="#SP19">§19. Unary operations</a></li><li><a href="#SP20">§20. Euclid's algorithm</a></li><li><a href="#SP22">§22. Unit sequences</a></li><li><a href="#SP30">§30. Performing derivations</a></li><li><a href="#SP31">§31. Classifying the units</a></li><li><a href="#SP34">§34. Scaling</a></li><li><a href="#SP40">§40. Arithmetic on kinds</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§1. Definitions. </b></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2"></a><b>§2. </b>Dimension in this sense is a term drawn from physics. The idea is that when
|
|
quantities are multiplied together, their natures are combined as well as
|
|
the actual numbers involved. For instance, in
|
|
v = fλ
|
|
if the frequency f of a wave is measured in Hz (counts per second), and
|
|
the wavelength λ in m, then the velocity v must be measured
|
|
in m/s: and that is indeed a measure of velocity, so this looks right.
|
|
We can tell that the formula
|
|
v = f^2λ
|
|
must be wrong because it would result in an acceleration. Physicists use the
|
|
term "dimensions" much as Inform uses the term "kinds of value".
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Inform applies dimension-checking to all "quasinumerical" kinds — those
|
|
which can be expressed numerically. The choice of which kinds are quasinumerical
|
|
is all done in the I6 template, not built into Inform at the compiler level,
|
|
but the standard setup makes number, time, intermediate results of calculations
|
|
(see below), and what the Inform documentation calls "units" — kinds of
|
|
value specified by literal patterns.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§3. </b>Inform divides quasinumerical kinds into three: fundamental units, derived units
|
|
with dimensions, and dimensionless units. In the default setup provided by
|
|
the template, a typical run has one fundamental unit ("time"), one
|
|
dimensionless unit ("number") and — unless the source text does
|
|
something very strange — no derived units.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">It would no doubt be cool to distinguish these by applying Buckingham's
|
|
π-theorem to all the equations we need to use, but this is a tricky
|
|
technique and does not always produce the "natural" results which people
|
|
expect. Instead, Inform requires the writer to specify explicitly how units
|
|
combine.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Number and time are built-in special cases. Further fundamental units are created
|
|
every time source text like this is read:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>Mass is a kind of value. 1kg specifies a mass.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">Derived units only come about when the source text specifies a multiplication
|
|
rule. For instance, when Inform reads
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>A mass times an acceleration specifies a force.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">it chooses one of the three units — say, force — and derives that from the
|
|
others.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Multiplication rules are stored in a linked list associated with left operand;
|
|
so that the rule A times B specifies C causes (B, C) to be stored
|
|
in the list of <code class="display"><span class="extract">multiplications</span></code> belonging to A.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">dimensional_rules</span><span class="plain"> {</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">dimensional_rule</span><span class="plain"> *</span><span class="identifier">multiplications</span><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">dimensional_rules</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">dimensional_rule</span><span class="plain"> {</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">name</span><span class="plain">;</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">right</span><span class="plain">;</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">outcome</span><span class="plain">;</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">dimensional_rule</span><span class="plain"> *</span><span class="identifier">next</span><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">dimensional_rule</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The structure dimensional_rules is private to this section.</p>
|
|
|
|
<p class="endnote">The structure dimensional_rule is accessed in 2/kc and here.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4"></a><b>§4. </b>The derivation process can be seen in action by feeding Inform
|
|
definitions of the SI units (see the test case <code class="display"><span class="extract">SIUnits-G</span></code>) and looking at
|
|
the output of:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>Test dimensions (internal) with --.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">(The dash is meaningless — this is a test with no input.) In the output, we
|
|
see that
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">Base units: time, length, mass, elapsed time, electric current, temperature, luminosity</span>
|
|
<span class="plain">Derived units:</span>
|
|
<span class="plain">frequency = (elapsed time)-1</span>
|
|
<span class="plain">force = (length).(mass).(elapsed time)-2</span>
|
|
<span class="plain">energy = (length)2.(mass).(elapsed time)-2</span>
|
|
<span class="plain">pressure = (length)-1.(mass).(elapsed time)-2</span>
|
|
<span class="plain">power = (length)2.(mass).(elapsed time)-3</span>
|
|
<span class="plain">electric charge = (elapsed time).(electric current)</span>
|
|
<span class="plain">voltage = (length)2.(mass).(elapsed time)-3.(electric current)-1</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">...and so on. Those expressions on the right hand sides are "derived units",
|
|
where the numbers are powers, so that negative numbers mean division.
|
|
It's easy to see why we want to give names and notations for some of
|
|
these derived units — imagine going into a cycle shop and asking for a
|
|
5 m^2.kg.s^{-3}.A^{-1} battery.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5"></a><b>§5. </b>A "dimensionless" quantity is one which is just a number, and is not a
|
|
physical measurement as such. In an equation like
|
|
K = ((mv^2) / (2))
|
|
the 2 is clearly dimensionless, but other possibilities also exist. The
|
|
arc length of part of a circle at radius r drawn out to angle θ
|
|
(if measured in radians) is given by:
|
|
A = θ r
|
|
Here A and r are both lengths, so the angle θ must be dimensionless.
|
|
But clearly it's not quite conceptually the same thing as an ordinary number.
|
|
Inform creates new dimensionless quantities this way, too:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>Angle is a kind of value. 1 rad specifies an angle. Length times angle specifies a length.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">Inform is not quite so careful about distinguishing dimensionless quantities
|
|
as some physicists might be. The official SI units distinguish angle, measured
|
|
in radians, and solid angle, in steradians, writing them as having units
|
|
m.m^{-1} and m^2.m^{-2} respectively —
|
|
one is a ratio of lengths, the other of areas. Inform cancels the units
|
|
and sees them as dimensionally equal. So if we write:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>Solid angle is a kind of value. 1 srad specifies an solid angle. Area times solid angle specifies an area.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">then Inform treats angle and solid angle as having the same multiplicative
|
|
properties — but it still allows variables to have either one as a kind of
|
|
value, and prints them differently.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Note that a dimensionless unit (other than number) can only get that way
|
|
by derivation, so it is always a derived unit, never a fundamental unit.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6"></a><b>§6. </b>In the process of calculations, we often need to create other and nameless
|
|
units as partial answers of calculations. Consider the kinetic energy equation
|
|
K = ((mv^2) / (2))
|
|
being evaluated the way a computer does it, one step at a time. One way takes
|
|
the mass, multiplies by the velocity to get a momentum, multiplies by the
|
|
velocity again to get energy, then divides by a dimensionless constant. But
|
|
another way would be to square the velocity first, then multiply by mass
|
|
to get energy, then halve. If we do it that way, what units are the squared
|
|
velocity in? The answer has to be
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">(length)2.(elapsed time)-2</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">but that's a unit which isn't useful for much, and doesn't have any everyday
|
|
name. Inform creates what are called "intermediate kinds" like this in
|
|
order to be able to represent the kinds of intermediate values which turn
|
|
up in calculation. They use the special <code class="display"><span class="extract">CON_INTERMEDIATE</span></code> construction, they
|
|
are nameless, and the user isn't allowed to store the results permanently.
|
|
(They can't be the kind of a global variable, a table column, and so on.)
|
|
If the user wants to deal with such values on a long-term basis, he must give
|
|
them a name, like this:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>Funkiness is a kind of value. 1 Claude is a funkiness. A velocity times a velocity specifies a funkiness.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph"><a id="SP7"></a><b>§7. </b>Expressions like m^2.kg are stored inside Inform as
|
|
sequences of ordered pairs in the form
|
|
((B_1, p_1), (B_2, p_2), ..., (B_k, p_k))
|
|
where each B_i is the type ID of a fundamental unit, each p_i is a non-zero
|
|
integer, and B_1 < B_2 < ... < B_k. For instance, energy would be
|
|
((length, 2), (mass, 1), (elapsed~time, -2)).
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Every physically different derived unit has a unique and distinct sequence.
|
|
This is only true because a unit sequence is forbidden to contain derived
|
|
units. For instance, specific heat capacity looks as if it is written with
|
|
two different units in physics:
|
|
J. K^{-1}. kg^{-1} =
|
|
m^2.s^{-2}.K^{-1}
|
|
But this is because the Joule is a derived unit. Substituting
|
|
J = m^2.kg.s^{-2}
|
|
to get back to fundamental units shows that both sides would be computed as the
|
|
same unit sequence.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The case k=0, the empty sequence, is not only legal but important: it is
|
|
the derivation for a dimensionless unit. (As discussed above, Inform doesn't
|
|
see different dimensionless units as being physically different.)
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">unit_pair</span><span class="plain"> {</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">fund_unit</span><span class="plain">; </span> <span class="comment">and this really must be a fundamental kind</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">power</span><span class="plain">; </span> <span class="comment">a non-zero integer</span>
|
|
<span class="plain">} </span><span class="reserved">unit_pair</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The structure unit_pair is private to this section.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8"></a><b>§8. </b>The following is a hard limit, but really not a problematic one. The
|
|
entire SI system has only 7 fundamental units, and the only named scientific
|
|
unit I've seen which has even 5 terms in its derivation is molar entropy, a
|
|
less than everyday chemical measure
|
|
(kg.m^2.s^{-2}.K^{-1}.mol^{-1},
|
|
if you're taking notes).
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">MAX_BASE_UNITS_IN_SEQUENCE</span><span class="plain"> 16</span>
|
|
</pre>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">unit_sequence</span><span class="plain"> {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_unit_pairs</span><span class="plain">; </span> <span class="comment">in range 0 to <code class="display"><span class="extract">MAX_BASE_UNITS_IN_SEQUENCE</span></code></span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">unit_pair</span><span class="plain"> </span><span class="identifier">unit_pairs</span><span class="plain">[</span><span class="constant">MAX_BASE_UNITS_IN_SEQUENCE</span><span class="plain">];</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">scaling_factor</span><span class="plain">; </span> <span class="comment">see discussion of scaling below</span>
|
|
<span class="plain">} </span><span class="reserved">unit_sequence</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The structure unit_sequence is private to this section.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9"></a><b>§9. </b>Manipulating units like m^2.kg.s^{-2} looks
|
|
a little like manipulating formal polynomials in several variables, and of
|
|
course that isn't an accident. Another way of thinking of the above is that
|
|
we have a ring R of underlying numbers but that all arithmetic is done
|
|
in a larger ring. For each unit extend by R by a pair of formal
|
|
variables U_i and U_i^{-1}, and then quotient by the ideal generated
|
|
by U_jU_j^{-1} (so that they are indeed reciprocals of each other, as
|
|
the notation suggests) and also by all of the derivations we know of. Thus
|
|
Inform calculates in the ring:
|
|
I = R[U_1, U_2, ..., U_n, U_1^{-1}, ..., U_n^{-1}] /
|
|
(U_1U_1^{-1}, U_2U_2^{-1}, ..., U_nU_n^{-1}, D_1, D_2, ..., D_i).
|
|
It does that in practice by eliminating all of the U_i and U_i^{-1}
|
|
which are derived, so that it's left with just
|
|
I = R[U_1, U_2, ..., U_k, U_1^{-1}, ..., U_k^{-1}] /
|
|
(U_1U_1^{-1}, U_2U_2^{-1}, ..., U_kU_k^{-1}).
|
|
</p>
|
|
|
|
<p class="inwebparagraph">For instance, given seconds, Watts and Joules,
|
|
I = R[s, s^{-1}, W, W^{-1}, J, J^{-1}]/
|
|
(ss^{-1} = 1, WW^{-1}=1, JJ^{-1} = 1,
|
|
sW = J)
|
|
which by substituting all occurrences of J can be reduced to:
|
|
I = R[s, s^{-1}, W, W^{-1}]/
|
|
(ss^{-1} = 1, WW^{-1}=1).
|
|
Of course there are other ways to calculate I — we could have
|
|
eliminated any of the three units and kept the other two.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">If the derivations were ever more complex than AB=C, we might have to
|
|
use some elegant algorithms for calculating Gröbner bases in order to
|
|
determine I. But Inform's syntax is such that the writer of the source
|
|
text gives us the simplest possible description of the ideal, so no such
|
|
fun occurs.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">What does this ring look like? Because we are not allowed to add terms with
|
|
different powers of the variables, we only ever deal with monomials. Thus
|
|
we can form 2Ws^{-1} + 7Ws^{-1}, but Inform forbids
|
|
us to form (say) 6J + 7W. We can therefore picture the ring I
|
|
as a great mass of parallel copies of R. Dimensionless values all live
|
|
in R itself, while energies all live in R.s.W, powers in R.W
|
|
and so on. Addition and subtraction slide values around within their own
|
|
parallel copies, but multiplication and division move them from one to
|
|
another. The computation v_1v_2 is done in general by calculating the
|
|
numerical part (in R) at run-time, and the units (the choice of which
|
|
copy of R) at compile-time.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10"></a><b>§10. </b>But enough abstraction: time for some arithmetic. Inform performs
|
|
checking whenever values from two different kinds are combined by any of
|
|
eight arithmetic operations, numbered as follows. The numbers must not
|
|
be changed without amending the definitions of "plus" and so on
|
|
in the Standard Rules.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">NO_OPERATIONS</span><span class="plain"> 9</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">PLUS_OPERATION</span><span class="plain"> 0 </span> <span class="comment">addition</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">MINUS_OPERATION</span><span class="plain"> 1 </span> <span class="comment">subtraction</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">TIMES_OPERATION</span><span class="plain"> 2 </span> <span class="comment">multiplication</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">DIVIDE_OPERATION</span><span class="plain"> 3 </span> <span class="comment">division</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">REMAINDER_OPERATION</span><span class="plain"> 4 </span> <span class="comment">remainder after division</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">APPROXIMATION_OPERATION</span><span class="plain"> 5 </span> <span class="comment">"X to the nearest Y"</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">ROOT_OPERATION</span><span class="plain"> 6 </span> <span class="comment">square root — a unary operation</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">REALROOT_OPERATION</span><span class="plain"> 7 </span> <span class="comment">real-valued square root — a unary operation</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">CUBEROOT_OPERATION</span><span class="plain"> 8 </span> <span class="comment">cube root — similarly unary</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">EQUALS_OPERATION</span><span class="plain"> 9 </span> <span class="comment">set equal — used only in equations</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">POWER_OPERATION</span><span class="plain"> 10 </span> <span class="comment">raise to integer power — used only in equations</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">UNARY_MINUS_OPERATION</span><span class="plain"> 11 </span> <span class="comment">unary minus — used only in equations</span>
|
|
</pre>
|
|
<p class="inwebparagraph"><a id="SP11"></a><b>§11. </b>The following is associated with "total...", as in "the total weight
|
|
of things on the table", but that's a dodge used in the Standard Rules,
|
|
and for dimensional purposes we ignore it.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">TOTAL_OPERATION</span><span class="plain"> 12 </span> <span class="comment">not really one of the above</span>
|
|
</pre>
|
|
<p class="inwebparagraph"><a id="SP12"></a><b>§12. </b>There are two reasons why Inform monitors arithmetic: to keep track of
|
|
how it changes kinds, and to preserve scaling factors.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We start from the principle that not every arithmetic operation can be done,
|
|
and that even when it can, the result may have a different kind than the
|
|
operand(s) had. For one thing, every arithmetic operation requires that its
|
|
operands are quasinumerical — Inform won't allow a text to be multiplied by
|
|
a sound effect. (Occasionally we have thought about allowing text to be
|
|
duplicated by multiplication — 2 times "zig" would be "zigzig", and
|
|
maybe similarly for lists — but it always seemed more likely to be used by
|
|
mistake than intentionally.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Other restrictions are also applied. For instance, a time cannot be added
|
|
to a number, or vice versa; addition, subtraction and approximation require
|
|
both operands to have the same units.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP13"></a><b>§13. </b>Finally, scaling. Number is straightforwardly an integer kind:
|
|
it holds whole numbers. But other quasinumerical kinds can be stored
|
|
using scaled, fixed-point arithmetic. In general for each named unit
|
|
U (fundamental or derived) there is a positive integer k_U such that the
|
|
true value v is stored at run-time as the I6 integer k_U v. We call
|
|
this the scaled value.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">For example, if the text reads:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>Force is a kind of value. 1N specifies a force scaled up by 1000.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">then k = 1000 and the value 1N will be stored at run-time as <code class="display"><span class="extract">1000</span></code>;
|
|
forces can thus be calculated to a true value accuracy of at best 0.001N,
|
|
stored at run-time as <code class="display"><span class="extract">1</span></code>.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">It must be emphasised that this is scaled, fixed-point arithmetic: there
|
|
are no mantissas or exponents. In such schemes the scale factor is usually
|
|
2^{16} or some similar power of 2, but here we want to use exactly the
|
|
scale factors laid out by the source text — partly because the user
|
|
knows best, partly so that it is unambiguous how to print values, partly
|
|
so that source text like "0.001N" determines an exact value rather than
|
|
being approximated by a binary equivalent.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14"></a><b>§14. Prior kinds. </b>It turns out to be convenient to have a definition ordering of fundamental kinds,
|
|
which is completely unlike the <= relation; it just places them in
|
|
order of creation.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::kind_prior</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">A</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">B</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">A</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">B</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">B</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">A</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">A</span><span class="plain">)-></span><span class="identifier">allocation_id</span><span class="plain"> < </span><span class="functiontext">Kinds::get_construct</span><span class="plain">(</span><span class="identifier">B</span><span class="plain">)-></span><span class="identifier">allocation_id</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::kind_prior is used in <a href="#SP24_4">§24.4</a>, <a href="#SP30_1">§30.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15"></a><b>§15. Multiplication lists. </b>The linked lists of multiplication rules begin empty for every kind:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::dim_initialise</span><span class="plain">(</span><span class="reserved">dimensional_rules</span><span class="plain"> *</span><span class="identifier">dimrs</span><span class="plain">) {</span>
|
|
<span class="identifier">dimrs</span><span class="plain">-</span><span class="element">>multiplications</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::dim_initialise is used in 2/kc2 (<a href="2-kc2.html#SP7_1">§7.1</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16"></a><b>§16. </b>And this adds a new one to the relevant list:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::record_multiplication_rule</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">left</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">right</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">outcome</span><span class="plain">) {</span>
|
|
<span class="reserved">dimensional_rules</span><span class="plain"> *</span><span class="identifier">dimrs</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_dim_rules</span><span class="plain">(</span><span class="identifier">left</span><span class="plain">);</span>
|
|
<span class="reserved">dimensional_rule</span><span class="plain"> *</span><span class="identifier">dimr</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">dimr</span><span class="plain"> = </span><span class="identifier">dimrs</span><span class="plain">-</span><span class="element">>multiplications</span><span class="plain">; </span><span class="identifier">dimr</span><span class="plain">; </span><span class="identifier">dimr</span><span class="plain"> = </span><span class="identifier">dimr</span><span class="plain">-</span><span class="element">>next</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">dimr</span><span class="plain">-</span><span class="element">>right</span><span class="plain"> == </span><span class="identifier">right</span><span class="plain">) {</span>
|
|
<span class="identifier">KINDS_PROBLEM_HANDLER</span><span class="plain">(</span><span class="constant">DimensionRedundant_KINDERROR</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">dimensional_rule</span><span class="plain"> *</span><span class="identifier">dimr_new</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">dimensional_rule</span><span class="plain">);</span>
|
|
<span class="identifier">dimr_new</span><span class="plain">-</span><span class="element">>right</span><span class="plain"> = </span><span class="identifier">right</span><span class="plain">;</span>
|
|
<span class="identifier">dimr_new</span><span class="plain">-</span><span class="element">>outcome</span><span class="plain"> = </span><span class="identifier">outcome</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_sentence</span><span class="plain">)</span>
|
|
<span class="identifier">dimr_new</span><span class="plain">-</span><span class="element">>name</span><span class="plain"> = </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">);</span>
|
|
<span class="reserved">else</span>
|
|
<span class="identifier">dimr_new</span><span class="plain">-</span><span class="element">>name</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
|
|
<span class="identifier">dimr_new</span><span class="plain">-</span><span class="element">>next</span><span class="plain"> = </span><span class="identifier">dimrs</span><span class="plain">-</span><span class="element">>multiplications</span><span class="plain">;</span>
|
|
<span class="identifier">dimrs</span><span class="plain">-</span><span class="element">>multiplications</span><span class="plain"> = </span><span class="identifier">dimr_new</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::record_multiplication_rule is used in <a href="#SP18">§18</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP17"></a><b>§17. </b>The following loop-header macro iterates through the possible triples
|
|
(L, R, O) of multiplication rules L* R = O.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_OVER_MULTIPLICATIONS</span><span class="plain">(</span><span class="identifier">left_operand</span><span class="plain">, </span><span class="identifier">right_operand</span><span class="plain">, </span><span class="identifier">outcome_type</span><span class="plain">, </span><span class="identifier">wn</span><span class="plain">)</span>
|
|
<span class="reserved">dimensional_rules</span><span class="plain"> *</span><span class="identifier">dimrs</span><span class="plain">;</span>
|
|
<span class="reserved">dimensional_rule</span><span class="plain"> *</span><span class="identifier">dimr</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">left_operand</span><span class="plain">)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">dimrs</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_dim_rules</span><span class="plain">(</span><span class="identifier">left_operand</span><span class="plain">),</span>
|
|
<span class="identifier">dimr</span><span class="plain"> = (</span><span class="identifier">dimrs</span><span class="plain">)?(</span><span class="identifier">dimrs</span><span class="plain">-</span><span class="element">>multiplications</span><span class="plain">):</span><span class="identifier">NULL</span><span class="plain">,</span>
|
|
<span class="identifier">wn</span><span class="plain"> = (</span><span class="identifier">dimr</span><span class="plain">)?(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">dimr</span><span class="plain">-</span><span class="element">>name</span><span class="plain">)):-1,</span>
|
|
<span class="identifier">right_operand</span><span class="plain"> = (</span><span class="identifier">dimr</span><span class="plain">)?(</span><span class="identifier">dimr</span><span class="plain">-</span><span class="element">>right</span><span class="plain">):0,</span>
|
|
<span class="identifier">outcome_type</span><span class="plain"> = (</span><span class="identifier">dimr</span><span class="plain">)?(</span><span class="identifier">dimr</span><span class="plain">-</span><span class="element">>outcome</span><span class="plain">):0;</span>
|
|
<span class="identifier">dimr</span><span class="plain">;</span>
|
|
<span class="identifier">dimr</span><span class="plain"> = </span><span class="identifier">dimr</span><span class="plain">-</span><span class="element">>next</span><span class="plain">,</span>
|
|
<span class="identifier">wn</span><span class="plain"> = (</span><span class="identifier">dimr</span><span class="plain">)?(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">dimr</span><span class="plain">-</span><span class="element">>name</span><span class="plain">)):-1,</span>
|
|
<span class="identifier">right_operand</span><span class="plain"> = (</span><span class="identifier">dimr</span><span class="plain">)?(</span><span class="identifier">dimr</span><span class="plain">-</span><span class="element">>right</span><span class="plain">):0,</span>
|
|
<span class="identifier">outcome_type</span><span class="plain"> = (</span><span class="identifier">dimr</span><span class="plain">)?(</span><span class="identifier">dimr</span><span class="plain">-</span><span class="element">>outcome</span><span class="plain">):0)</span>
|
|
</pre>
|
|
<p class="inwebparagraph"><a id="SP18"></a><b>§18. </b>And this is where the user asks for a multiplication to come out in a
|
|
particular way:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::dim_set_multiplication</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">left</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">right</span><span class="plain">,</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">outcome</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::is_proper_constructor</span><span class="plain">(</span><span class="identifier">left</span><span class="plain">)) ||</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::is_proper_constructor</span><span class="plain">(</span><span class="identifier">right</span><span class="plain">)) ||</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::is_proper_constructor</span><span class="plain">(</span><span class="identifier">outcome</span><span class="plain">))) {</span>
|
|
<span class="identifier">KINDS_PROBLEM_HANDLER</span><span class="plain">(</span><span class="constant">DimensionNotBaseKOV_KINDERROR</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::Behaviour::is_quasinumerical</span><span class="plain">(</span><span class="identifier">left</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) ||</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::Behaviour::is_quasinumerical</span><span class="plain">(</span><span class="identifier">right</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) ||</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::Behaviour::is_quasinumerical</span><span class="plain">(</span><span class="identifier">outcome</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
|
|
<span class="identifier">KINDS_PROBLEM_HANDLER</span><span class="plain">(</span><span class="constant">NonDimensional_KINDERROR</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">Kinds::Dimensions::record_multiplication_rule</span><span class="plain">(</span><span class="identifier">left</span><span class="plain">, </span><span class="identifier">right</span><span class="plain">, </span><span class="identifier">outcome</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">left</span><span class="plain">, </span><span class="identifier">outcome</span><span class="plain">)) && (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">right</span><span class="plain">, </span><span class="identifier">K_number</span><span class="plain">))) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">right</span><span class="plain">, </span><span class="identifier">outcome</span><span class="plain">)) && (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">left</span><span class="plain">, </span><span class="identifier">K_number</span><span class="plain">))) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="functiontext">Kinds::Dimensions::make_unit_derivation</span><span class="plain">(</span><span class="identifier">left</span><span class="plain">, </span><span class="identifier">right</span><span class="plain">, </span><span class="identifier">outcome</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::dim_set_multiplication appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19"></a><b>§19. Unary operations. </b>All we need to know is which ones are unary, in fact, and:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::arithmetic_op_is_unary</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">op</span><span class="plain">) {</span>
|
|
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">op</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CUBEROOT_OPERATION</span><span class="plain">:</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">ROOT_OPERATION</span><span class="plain">:</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">REALROOT_OPERATION</span><span class="plain">:</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">UNARY_MINUS_OPERATION</span><span class="plain">:</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::arithmetic_op_is_unary is used in <a href="#SP40">§40</a>, <a href="#SP40_1">§40.1</a>, <a href="#SP40_2">§40.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20"></a><b>§20. Euclid's algorithm. </b>In my entire life, I believe this is the only time I have ever actually
|
|
used Euclid's algorithm for the GCD of two natural numbers. I've never
|
|
quite understood why textbooks take this as somehow the typical algorithm.
|
|
My maths students always find it a little oblique, despite the almost
|
|
trivial proof that it works. I find it hard to visualise myself, for that
|
|
matter. And then, consider that the average number of iterations τ_n,
|
|
in effect its running time, is known to be
|
|
τ_n = ((12log 2) / (π^2))log n + (4P + 5/2) + O(n^{-1/6+ε)
|
|
for any ε>0, where P is defined in terms of an integral, Euler's
|
|
constant, and an evaluation of the derivative of the Riemann zeta function
|
|
— see D. E. Knuth, `Evaluation of Porter's Constant', reprinted in
|
|
"Selected Papers on Analysis of Algorithms" (Stanford: CSLI Lecture Notes
|
|
102, 2000). In practice, a shade under log n steps, then, which is nicely
|
|
quick. But I don't look at the code and immediately see this, myself.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::gcd</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">m</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">n</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">m</span><span class="plain"><1) || (</span><span class="identifier">n</span><span class="plain"><1)) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"applied Kinds::Dimensions::gcd outside natural numbers"</span><span class="plain">);</span>
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">TRUE</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rem</span><span class="plain"> = </span><span class="identifier">m</span><span class="plain">%</span><span class="identifier">n</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rem</span><span class="plain"> == 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">n</span><span class="plain">;</span>
|
|
<span class="identifier">m</span><span class="plain"> = </span><span class="identifier">n</span><span class="plain">; </span><span class="identifier">n</span><span class="plain"> = </span><span class="identifier">rem</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::gcd is used in <a href="#SP21">§21</a>, 2/sav (<a href="2-sav.html#SP9_2_2">§9.2.2</a>, <a href="2-sav.html#SP21_1_2">§21.1.2</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21"></a><b>§21. </b>The sequence of operation here is to reduce the risk of integer overflows
|
|
when multiplying <code class="display"><span class="extract">m</span></code> by <code class="display"><span class="extract">n</span></code>.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::lcm</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">m</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">n</span><span class="plain">) {</span>
|
|
<span class="reserved">return</span><span class="plain"> (</span><span class="identifier">m</span><span class="plain">/</span><span class="functiontext">Kinds::Dimensions::gcd</span><span class="plain">(</span><span class="identifier">m</span><span class="plain">, </span><span class="identifier">n</span><span class="plain">))*</span><span class="identifier">n</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::lcm is used in <a href="#SP40_4">§40.4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP22"></a><b>§22. Unit sequences. </b>Given a fundamental type B, convert it to a unit sequence: B = B^1, so we
|
|
get a sequence with a single pair: ((B, 1)). Uniquely, "number" is born
|
|
derived and dimensionless, though, so that comes out as the empty sequence.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">unit_sequence</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::fundamental_unit_sequence</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">B</span><span class="plain">) {</span>
|
|
<span class="reserved">unit_sequence</span><span class="plain"> </span><span class="identifier">us</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">B</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
|
|
<span class="identifier">us</span><span class="element">.no_unit_pairs</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">us</span><span class="element">.unit_pairs</span><span class="plain">[0]</span><span class="element">.fund_unit</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">us</span><span class="element">.unit_pairs</span><span class="plain">[0]</span><span class="element">.power</span><span class="plain"> = 0; </span> <span class="comment">redundant, but appeases <code class="display"><span class="extract">gcc -O2</span></code></span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">us</span><span class="element">.no_unit_pairs</span><span class="plain"> = 1;</span>
|
|
<span class="identifier">us</span><span class="element">.unit_pairs</span><span class="plain">[0]</span><span class="element">.fund_unit</span><span class="plain"> = </span><span class="identifier">B</span><span class="plain">; </span><span class="identifier">us</span><span class="element">.unit_pairs</span><span class="plain">[0]</span><span class="element">.power</span><span class="plain"> = 1;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">us</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::fundamental_unit_sequence is used in 2/kc2 (<a href="2-kc2.html#SP7_1">§7.1</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP23"></a><b>§23. </b>As noted above, two units represent dimensionally equivalent physical
|
|
quantities if and only if they are identical, which makes comparison easy:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::compare_unit_sequences</span><span class="plain">(</span><span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">ik1</span><span class="plain">, </span><span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">ik2</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ik1</span><span class="plain"> == </span><span class="identifier">ik2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ik1</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">ik2</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ik1</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain"> != </span><span class="identifier">ik2</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">ik1</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">ik1</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.fund_unit</span><span class="plain">, </span><span class="identifier">ik2</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.fund_unit</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) ||</span>
|
|
<span class="plain">(</span><span class="identifier">ik1</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.power</span><span class="plain"> != </span><span class="identifier">ik2</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.power</span><span class="plain">))</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::compare_unit_sequences is used in <a href="#SP30_4">§30.4</a>, <a href="#SP40">§40</a>, <a href="#SP40_3">§40.3</a>, 2/kc (<a href="2-kc.html#SP10">§10</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP24"></a><b>§24. </b>We now have three fundamental operations we can perform on unit sequences.
|
|
First, we can multiply them: that is, we store in <code class="display"><span class="extract">result</span></code> the unit
|
|
sequence representing X_1^{s_1}X_2^{s_2}, where X_1 and X_2 are
|
|
represented by unit sequences <code class="display"><span class="extract">us1</span></code> and <code class="display"><span class="extract">us2</span></code>.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">So the case s_1 = s_2 = 1 represents multiplying X_1 by X_2, while
|
|
s_1 = 1, s_2 = -1 represents dividing X_1 by X_2. But we can also
|
|
raise to higher powers.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Our method relies on noting that
|
|
X_1 = T_{11}^{p_{11}}. T_{12}^{p_{12}}... T_{1n}^{p_{1n}},
|
|
X_2 = T_{21}^{p_{21}}. T_{22}^{p_{22}}... T_{2m}^{p_{2m}}
|
|
where T_{11} < T_{12} < ... < T_{1n} and T_{21}<T_{22}<...<T_{2m}. We
|
|
can therefore merge the two in a single pass.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">On each iteration of the loop the variables <code class="display"><span class="extract">i1</span></code> and <code class="display"><span class="extract">i2</span></code> are our current
|
|
read positions in each sequence, while we are currently looking at the
|
|
unit pairs (<code class="display"><span class="extract">t1</span></code>, <code class="display"><span class="extract">m1</span></code>) and (<code class="display"><span class="extract">t2</span></code>, <code class="display"><span class="extract">m2</span></code>). The following symmetrical
|
|
algorithm holds on to each pair until the one from the other sequence has had
|
|
a chance to catch up with it, because we always deal with the pair with the
|
|
numerically lower <code class="display"><span class="extract">t</span></code> first. This also proves that the <code class="display"><span class="extract">results</span></code> sequence comes
|
|
out in numerical order.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::multiply_unit_sequences</span><span class="plain">(</span><span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">us1</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">s1</span><span class="plain">, </span><span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">us2</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">s2</span><span class="plain">,</span>
|
|
<span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">result</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">result</span><span class="plain"> == </span><span class="identifier">us1</span><span class="plain">) || (</span><span class="identifier">result</span><span class="plain"> == </span><span class="identifier">us2</span><span class="plain">)) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"result must be different structure"</span><span class="plain">);</span>
|
|
|
|
<span class="identifier">result</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain"> = 0;</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i1</span><span class="plain"> = 0, </span><span class="identifier">i2</span><span class="plain"> = 0; </span> <span class="comment">read position in sequences 1, 2</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">t1</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">p1</span><span class="plain"> = 0; </span> <span class="comment">start with no current term from sequence 1</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">t2</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">p2</span><span class="plain"> = 0; </span> <span class="comment">start with no current term from sequence 2</span>
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">TRUE</span><span class="plain">) {</span>
|
|
<<span class="cwebmacro">If we have no current term from sequence 1, and it hasn't run out, fetch a new one</span> <span class="cwebmacronumber">24.1</span>><span class="character">;</span>
|
|
<<span class="cwebmacro">If we have no current term from sequence 2, and it hasn't run out, fetch a new one</span> <span class="cwebmacronumber">24.2</span>><span class="character">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">t1</span><span class="plain">, </span><span class="identifier">t2</span><span class="plain">)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">t1</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">break</span><span class="plain">; </span> <span class="comment">both sequences have now run out</span>
|
|
<<span class="cwebmacro">Both terms refer to the same fundamental unit, so combine these into the result</span> <span class="cwebmacronumber">24.3</span>><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<<span class="cwebmacro">The terms refer to different fundamental units, so copy the numerically lower one into the result</span> <span class="cwebmacronumber">24.4</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">KIND_CREATIONS</span><span class="plain">, </span><span class="string">"Multiplication: $Q * $Q = $Q\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">us1</span><span class="plain">, </span><span class="identifier">us2</span><span class="plain">, </span><span class="identifier">result</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::multiply_unit_sequences is used in <a href="#SP26_2">§26.2</a>, <a href="#SP30_2">§30.2</a>, <a href="#SP30_4">§30.4</a>, <a href="#SP40">§40</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP24_1"></a><b>§24.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">If we have no current term from sequence 1, and it hasn't run out, fetch a new one</span> <span class="cwebmacronumber">24.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">t1</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) && (</span><span class="identifier">us1</span><span class="plain">) && (</span><span class="identifier">i1</span><span class="plain"> < </span><span class="identifier">us1</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain">)) {</span>
|
|
<span class="identifier">t1</span><span class="plain"> = </span><span class="identifier">us1</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">i1</span><span class="plain">]</span><span class="element">.fund_unit</span><span class="plain">; </span><span class="identifier">p1</span><span class="plain"> = </span><span class="identifier">us1</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">i1</span><span class="plain">]</span><span class="element">.power</span><span class="plain">; </span><span class="identifier">i1</span><span class="plain">++;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP24">§24</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP24_2"></a><b>§24.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">If we have no current term from sequence 2, and it hasn't run out, fetch a new one</span> <span class="cwebmacronumber">24.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">t2</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) && (</span><span class="identifier">us2</span><span class="plain">) && (</span><span class="identifier">i2</span><span class="plain"> < </span><span class="identifier">us2</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain">)) {</span>
|
|
<span class="identifier">t2</span><span class="plain"> = </span><span class="identifier">us2</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">i2</span><span class="plain">]</span><span class="element">.fund_unit</span><span class="plain">; </span><span class="identifier">p2</span><span class="plain"> = </span><span class="identifier">us2</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">i2</span><span class="plain">]</span><span class="element">.power</span><span class="plain">; </span><span class="identifier">i2</span><span class="plain">++;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP24">§24</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP24_3"></a><b>§24.3. </b>So here the head of one sequence is T^{p_1} and the head of the other
|
|
is T^{p_2}, so in the product we ought to see (T^{p_1})^{s_1}.
|
|
(T^{p_2})^{s_2} = T^{p_1s_1+p_2s_2}. But we don't enter terms that have
|
|
cancelled out, that is, where p_1s_1+p_2s_2 = 0.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Both terms refer to the same fundamental unit, so combine these into the result</span> <span class="cwebmacronumber">24.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p1</span><span class="plain">*</span><span class="identifier">s1</span><span class="plain"> + </span><span class="identifier">p2</span><span class="plain">*</span><span class="identifier">s2</span><span class="plain">; </span> <span class="comment">combined power of <code class="display"><span class="extract">t1</span></code> = <code class="display"><span class="extract">t2</span></code></span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain"> != 0) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">result</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain"> == </span><span class="constant">MAX_BASE_UNITS_IN_SEQUENCE</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Trip a unit sequence overflow</span> <span class="cwebmacronumber">24.3.1</span>><span class="plain">;</span>
|
|
<span class="identifier">result</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">result</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain">]</span><span class="element">.fund_unit</span><span class="plain"> = </span><span class="identifier">t1</span><span class="plain">;</span>
|
|
<span class="identifier">result</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">result</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain">++]</span><span class="element">.power</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">t1</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">t2</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span> <span class="comment">dispose of both terms as dealt with</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP24">§24</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP24_4"></a><b>§24.4. </b>Otherwise we copy. By copying the numerically lower term, we can be sure
|
|
that it will never occur again in either sequence. So we can copy it straight
|
|
into the results.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The code is slightly warped by the fact that <code class="display"><span class="extract">UNKNOWN_NT</span></code>, representing the
|
|
end of the sequence, happens to be numerically lower than all the valid
|
|
kinds. We don't want to make use of facts like that, so we write code
|
|
to deal with <code class="display"><span class="extract">UNKNOWN_NT</span></code> explicitly.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">The terms refer to different fundamental units, so copy the numerically lower one into the result</span> <span class="cwebmacronumber">24.4</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">t2</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || ((</span><span class="identifier">t1</span><span class="plain"> != </span><span class="identifier">NULL</span><span class="plain">) && (</span><span class="functiontext">Kinds::Dimensions::kind_prior</span><span class="plain">(</span><span class="identifier">t1</span><span class="plain">, </span><span class="identifier">t2</span><span class="plain">)))) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">result</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain"> == </span><span class="constant">MAX_BASE_UNITS_IN_SEQUENCE</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Trip a unit sequence overflow</span> <span class="cwebmacronumber">24.3.1</span>><span class="plain">;</span>
|
|
<span class="identifier">result</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">result</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain">]</span><span class="element">.fund_unit</span><span class="plain"> = </span><span class="identifier">t1</span><span class="plain">;</span>
|
|
<span class="identifier">result</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">result</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain">++]</span><span class="element">.power</span><span class="plain"> = </span><span class="identifier">p1</span><span class="plain">*</span><span class="identifier">s1</span><span class="plain">;</span>
|
|
<span class="identifier">t1</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span> <span class="comment">dispose of the head of sequence 1 as dealt with</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">t1</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || ((</span><span class="identifier">t2</span><span class="plain"> != </span><span class="identifier">NULL</span><span class="plain">) && (</span><span class="functiontext">Kinds::Dimensions::kind_prior</span><span class="plain">(</span><span class="identifier">t2</span><span class="plain">, </span><span class="identifier">t1</span><span class="plain">)))) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">result</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain"> == </span><span class="constant">MAX_BASE_UNITS_IN_SEQUENCE</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Trip a unit sequence overflow</span> <span class="cwebmacronumber">24.3.1</span>><span class="plain">;</span>
|
|
<span class="identifier">result</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">result</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain">]</span><span class="element">.fund_unit</span><span class="plain"> = </span><span class="identifier">t2</span><span class="plain">;</span>
|
|
<span class="identifier">result</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">result</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain">++]</span><span class="element">.power</span><span class="plain"> = </span><span class="identifier">p2</span><span class="plain">*</span><span class="identifier">s2</span><span class="plain">;</span>
|
|
<span class="identifier">t2</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span> <span class="comment">dispose of the head of sequence 1 as dealt with</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"unit pairs disarrayed"</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP24">§24</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP24_3_1"></a><b>§24.3.1. </b>For reasons explained above, this is really never going to happen by
|
|
accident, but we'll be careful:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Trip a unit sequence overflow</span> <span class="cwebmacronumber">24.3.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">KINDS_PROBLEM_HANDLER</span><span class="plain">(</span><span class="constant">UnitSequenceOverflow_KINDERROR</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP24_3">§24.3</a>, <a href="#SP24_4">§24.4</a> (twice).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP25"></a><b>§25. </b>The second operation is taking roots.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Surprisingly, perhaps, it's much easier to compute sqrt(X) or
|
|
^{3} sqrt(X) for any unit X — it's just that it can't always be done.
|
|
Inform does not permit non-integer powers of units, so for instance
|
|
sqrt(time) does not exist, whereas sqrt(length^2.mass^{-2})
|
|
does. Square roots exist if each power in the sequence is even, cube roots
|
|
exist if each is divisible by 3. We return <code class="display"><span class="extract">TRUE</span></code> or <code class="display"><span class="extract">FALSE</span></code> according to
|
|
whether the root could be taken, and if <code class="display"><span class="extract">FALSE</span></code> then the contents of
|
|
<code class="display"><span class="extract">result</span></code> are undefined.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::root_unit_sequence</span><span class="plain">(</span><span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">us</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">pow</span><span class="plain">, </span><span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">result</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">us</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">*</span><span class="identifier">result</span><span class="plain"> = *</span><span class="identifier">us</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">result</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">result</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.power</span><span class="plain">) % </span><span class="identifier">pow</span><span class="plain"> != 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="identifier">result</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.power</span><span class="plain"> = (</span><span class="identifier">result</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.power</span><span class="plain">)/</span><span class="identifier">pow</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::root_unit_sequence is used in <a href="#SP40">§40</a>, <a href="#SP41">§41</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP26"></a><b>§26. </b>The final operation on unit sequences is substitution. Given a fundamental type
|
|
B, we substitute B = K_D into an existing unit sequence K_E. (This is
|
|
used when B is becoming a derived type — once we discover that B=K_D,
|
|
we are no longer allowed to keep B in any unit sequence.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We simply search for B^p, and if we find it, we remove it and then
|
|
multiply by K_D^p.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::dim_substitute</span><span class="plain">(</span><span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">existing</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">fundamental</span><span class="plain">, </span><span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">derived</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">, </span><span class="identifier">p</span><span class="plain"> = 0, </span><span class="identifier">found</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">existing</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">existing</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">existing</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.fund_unit</span><span class="plain">, </span><span class="identifier">fundamental</span><span class="plain">)) {</span>
|
|
<span class="identifier">p</span><span class="plain"> = </span><span class="identifier">existing</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.power</span><span class="plain">;</span>
|
|
<span class="identifier">found</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Remove the B term from the existing sequence</span> <span class="cwebmacronumber">26.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">found</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Multiply the existing sequence by a suitable power of B's derivation</span> <span class="cwebmacronumber">26.2</span>><span class="character">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::dim_substitute is used in <a href="#SP30_3">§30.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP26_1"></a><b>§26.1. </b>We shuffle the remaining terms in the sequence down by one, overwriting B:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Remove the B term from the existing sequence</span> <span class="cwebmacronumber">26.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">=</span><span class="identifier">i</span><span class="plain">; </span><span class="identifier">j</span><span class="plain"><</span><span class="identifier">existing</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain">-1; </span><span class="identifier">j</span><span class="plain">++)</span>
|
|
<span class="identifier">existing</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] = </span><span class="identifier">existing</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">+1];</span>
|
|
<span class="identifier">existing</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain">--;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP26">§26</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP26_2"></a><b>§26.2. </b>We now multiply by K_D^p.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Multiply the existing sequence by a suitable power of B's derivation</span> <span class="cwebmacronumber">26.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">unit_sequence</span><span class="plain"> </span><span class="identifier">result</span><span class="plain">;</span>
|
|
<span class="functiontext">Kinds::Dimensions::multiply_unit_sequences</span><span class="plain">(</span><span class="identifier">existing</span><span class="plain">, 1, </span><span class="identifier">derived</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">, &</span><span class="identifier">result</span><span class="plain">);</span>
|
|
<span class="plain">*</span><span class="identifier">existing</span><span class="plain"> = </span><span class="identifier">result</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP26">§26</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP27"></a><b>§27. </b>For reasons which will be explained below, a unit sequence also has
|
|
a scale factor associated with it:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::us_get_scaling_factor</span><span class="plain">(</span><span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">us</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">us</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> 1;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">us</span><span class="plain">-</span><span class="element">>scaling_factor</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::us_get_scaling_factor is used in 2/uk (<a href="2-uk.html#SP19">§19</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP28"></a><b>§28. </b>That just leaves, as usual, indexing...
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::index_unit_sequence</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">deriv</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">briefly</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">deriv</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">deriv</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain"> == 0) { </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"dimensionless"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain"><</span><span class="identifier">deriv</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">++) {</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">fundamental</span><span class="plain"> = </span><span class="identifier">deriv</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]</span><span class="element">.fund_unit</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">power</span><span class="plain"> = </span><span class="identifier">deriv</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]</span><span class="element">.power</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">briefly</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">>0) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"."</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"("</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
|
|
<span class="identifier">Kinds::Index::index_kind</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">fundamental</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="reserved">else</span>
|
|
<span class="functiontext">Kinds::Textual::write</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">fundamental</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">")"</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">power</span><span class="plain"> != 1) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<sup>%d</sup>"</span><span class="plain">, </span><span class="identifier">power</span><span class="plain">);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">>0) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" times "</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">power</span><span class="plain"> < 0) { </span><span class="identifier">power</span><span class="plain"> = -</span><span class="identifier">power</span><span class="plain">; </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"reciprocal of "</span><span class="plain">); }</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_name</span><span class="plain">(</span><span class="identifier">fundamental</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%W"</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
|
|
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">power</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> 1: </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 2: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" squared"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 3: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" cubed"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">default</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" to the power %d"</span><span class="plain">, </span><span class="identifier">power</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::index_unit_sequence is used in <a href="#SP32_2">§32.2</a>, 2/dk (<a href="2-dk.html#SP24_1">§24.1</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP29"></a><b>§29. </b>...and logging.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::log_unit_sequence</span><span class="plain">(</span><span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">deriv</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">deriv</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"<null-us>"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">deriv</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain"> == 0) { </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"dimensionless"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain"><</span><span class="identifier">deriv</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">++) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">>0) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"."</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"($u)"</span><span class="plain">, </span><span class="identifier">deriv</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]</span><span class="element">.fund_unit</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">deriv</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]</span><span class="element">.power</span><span class="plain"> != 1) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%d"</span><span class="plain">, </span><span class="identifier">deriv</span><span class="plain">-</span><span class="element">>unit_pairs</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]</span><span class="element">.power</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::log_unit_sequence appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP30"></a><b>§30. Performing derivations. </b>The following is called when the user specifies that L times R specifies
|
|
an O. These are required all to be quasinumerical: any of the three might
|
|
be either a fundamental unit (so far) or a derived unit (already).
|
|
</p>
|
|
|
|
<p class="inwebparagraph">If two or more are fundamental units, we have a choice. That is, suppose we have
|
|
created three kinds already: mass, acceleration, force. Then we read:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>Mass times acceleration specifies a force.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">We could make this true in any of three ways: keep M and A as fundamental units
|
|
and derive F from them, keep A and F as fundamental units and derive M from those,
|
|
or keep M and F while deriving A. Inform always chooses the most recently
|
|
created unit as the one to derive, on the grounds that the source text has
|
|
probably set things out with what the user thinks are the most fundamental
|
|
units first.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::make_unit_derivation</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">left</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">right</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">outcome</span><span class="plain">) {</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">terms</span><span class="plain">[3];</span>
|
|
<span class="identifier">terms</span><span class="plain">[0] = </span><span class="identifier">left</span><span class="plain">; </span><span class="identifier">terms</span><span class="plain">[1] = </span><span class="identifier">right</span><span class="plain">; </span><span class="identifier">terms</span><span class="plain">[2] = </span><span class="identifier">outcome</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">newest_term</span><span class="plain"> = -1;</span>
|
|
<<span class="cwebmacro">Find which (if any) of the three units is the newest-made fundamental unit</span> <span class="cwebmacronumber">30.1</span>><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">newest_term</span><span class="plain"> >= 0) {</span>
|
|
<span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">derivation</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Derive the newest one by rearranging the equation in terms of the other two</span> <span class="cwebmacronumber">30.2</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Substitute this new derivation to eliminate this fundamental unit from other sequences</span> <span class="cwebmacronumber">30.3</span>><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span>
|
|
<<span class="cwebmacro">Check this derivation to make sure it is redundant, not contradictory</span> <span class="cwebmacronumber">30.4</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::make_unit_derivation is used in <a href="#SP18">§18</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP30_1"></a><b>§30.1. </b>Data type IDs are allocated in creation order, so "newest" means largest ID.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Find which (if any) of the three units is the newest-made fundamental unit</span> <span class="cwebmacronumber">30.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">; </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">max</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><3; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::Dimensions::kind_prior</span><span class="plain">(</span><span class="identifier">max</span><span class="plain">, </span><span class="identifier">terms</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])) && (</span><span class="functiontext">Kinds::Behaviour::test_if_derived</span><span class="plain">(</span><span class="identifier">terms</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]) == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
|
|
<span class="identifier">newest_term</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">; </span><span class="identifier">max</span><span class="plain"> = </span><span class="identifier">terms</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">];</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP30">§30</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP30_2"></a><b>§30.2. </b>We need to ensure that the user's multiplication rule is henceforth true,
|
|
and we do that by fixing the newest unit to make it so.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Derive the newest one by rearranging the equation in terms of the other two</span> <span class="cwebmacronumber">30.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">kx</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">ky</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">sx</span><span class="plain"> = 0, </span><span class="identifier">sy</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">newest_term</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> 0: </span> <span class="comment">here L is newest and we derive L = R^{-1}O</span>
|
|
<span class="identifier">kx</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">terms</span><span class="plain">[1]); </span><span class="identifier">sx</span><span class="plain"> = -1;</span>
|
|
<span class="identifier">ky</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">terms</span><span class="plain">[2]); </span><span class="identifier">sy</span><span class="plain"> = 1;</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 1: </span> <span class="comment">here R is newest and we derive R = L^{-1}O</span>
|
|
<span class="identifier">kx</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">terms</span><span class="plain">[0]); </span><span class="identifier">sx</span><span class="plain"> = -1;</span>
|
|
<span class="identifier">ky</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">terms</span><span class="plain">[2]); </span><span class="identifier">sy</span><span class="plain"> = 1;</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 2: </span> <span class="comment">here O is newest and we derive O = LR</span>
|
|
<span class="identifier">kx</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">terms</span><span class="plain">[0]); </span><span class="identifier">sx</span><span class="plain"> = 1;</span>
|
|
<span class="identifier">ky</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">terms</span><span class="plain">[1]); </span><span class="identifier">sy</span><span class="plain"> = 1;</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">derivation</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">terms</span><span class="plain">[</span><span class="identifier">newest_term</span><span class="plain">]);</span>
|
|
<span class="reserved">unit_sequence</span><span class="plain"> </span><span class="identifier">result</span><span class="plain">;</span>
|
|
<span class="functiontext">Kinds::Dimensions::multiply_unit_sequences</span><span class="plain">(</span><span class="identifier">kx</span><span class="plain">, </span><span class="identifier">sx</span><span class="plain">, </span><span class="identifier">ky</span><span class="plain">, </span><span class="identifier">sy</span><span class="plain">, &</span><span class="identifier">result</span><span class="plain">);</span>
|
|
<span class="plain">*</span><span class="identifier">derivation</span><span class="plain"> = </span><span class="identifier">result</span><span class="plain">;</span>
|
|
<span class="functiontext">Kinds::Behaviour::now_derived</span><span class="plain">(</span><span class="identifier">terms</span><span class="plain">[</span><span class="identifier">newest_term</span><span class="plain">]);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP30">§30</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP30_3"></a><b>§30.3. </b>Later in Inform's run, when we start compiling code, many more unit sequences
|
|
will exist on a temporary basis — as part of the kinds for intermediate results
|
|
in calculations — but early on, when we're here, the only unit sequences made
|
|
are the derivations of the units. So it is easy to cover all of them.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Substitute this new derivation to eliminate this fundamental unit from other sequences</span> <span class="cwebmacronumber">30.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Behaviour::is_quasinumerical</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)) {</span>
|
|
<span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">existing</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="functiontext">Kinds::Dimensions::dim_substitute</span><span class="plain">(</span><span class="identifier">existing</span><span class="plain">, </span><span class="identifier">terms</span><span class="plain">[</span><span class="identifier">newest_term</span><span class="plain">], </span><span class="identifier">derivation</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP30">§30</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP30_4"></a><b>§30.4. </b>If we have AB = C but all three of A, B, C are already derived,
|
|
that puts us in a bind. Their definitions are fixed already, so we can't
|
|
simply force the equation to come true by fixing one of them. That means
|
|
either the derivation is redundant — because it's already true that
|
|
AB = C — or contradictory — because we know AB!= C. We silently
|
|
allow a redundancy, as it may have been put in for clarity, or so that
|
|
the user can check the consistency of his own definitions, or to make
|
|
the Kinds index page more helpful. But we must reject a contradiction.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Check this derivation to make sure it is redundant, not contradictory</span> <span class="cwebmacronumber">30.4</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">unit_sequence</span><span class="plain"> </span><span class="identifier">product</span><span class="plain">;</span>
|
|
<span class="functiontext">Kinds::Dimensions::multiply_unit_sequences</span><span class="plain">(</span>
|
|
<span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">terms</span><span class="plain">[0]), 1,</span>
|
|
<span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">terms</span><span class="plain">[1]), 1, &</span><span class="identifier">product</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Dimensions::compare_unit_sequences</span><span class="plain">(&</span><span class="identifier">product</span><span class="plain">,</span>
|
|
<span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">terms</span><span class="plain">[2])) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<span class="identifier">KINDS_PROBLEM_HANDLER</span><span class="plain">(</span><span class="constant">DimensionsInconsistent_KINDERROR</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP30">§30</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP31"></a><b>§31. Classifying the units. </b>Some of the derived units are dimensionless, others not. Number
|
|
is always dimensionless; and any unit whose derivation is the empty
|
|
unit sequence must be dimensionless.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::dimensionless</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">K_number</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">K_real_number</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Behaviour::is_quasinumerical</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::us_dimensionless</span><span class="plain">(</span><span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">));</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::us_dimensionless</span><span class="plain">(</span><span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">us</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">us</span><span class="plain">) && (</span><span class="identifier">us</span><span class="plain">-</span><span class="element">>no_unit_pairs</span><span class="plain"> == 0)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::dimensionless is used in <a href="#SP32_2">§32.2</a>, <a href="#SP33">§33</a>, <a href="#SP40_1">§40.1</a>, <a href="#SP41">§41</a>.</p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::us_dimensionless is used in <a href="#SP40_2">§40.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP32"></a><b>§32. </b>Using these definitions, we can now print analyses of the units into the
|
|
index and the debugging log.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::index_dimensional_rules</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">) {</span>
|
|
<span class="identifier">HTML_TAG</span><span class="plain">(</span><span class="string">"hr"</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Index the rubric about quasinumerical kinds</span> <span class="cwebmacronumber">32.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Index the table of quasinumerical kinds</span> <span class="cwebmacronumber">32.2</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Index the table of multiplication rules</span> <span class="cwebmacronumber">32.3</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::index_dimensional_rules appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP32_1"></a><b>§32.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Index the rubric about quasinumerical kinds</span> <span class="cwebmacronumber">32.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">, </span><span class="string">"calculator"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::begin_plain_html_table</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::first_html_column</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
|
|
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"border=0 src=inform:/doc_images/calc2.png"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&nbsp;"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Kinds of value marked with the <b>calculator symbol</b> are numerical - "</span>
|
|
<span class="string">"these are values we can add, multiply and so on. The range of these "</span>
|
|
<span class="string">"numbers depends on the Format setting for the project (Glulx format "</span>
|
|
<span class="string">"supports much higher numbers than Z-code)."</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::end_html_row</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::end_html_table</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP32">§32</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP32_2"></a><b>§32.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Index the table of quasinumerical kinds</span> <span class="cwebmacronumber">32.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::begin_plain_html_table</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
|
|
<span class="identifier">HTML::first_html_column</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<b>kind of value</b>"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::next_html_column</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<b>minimum</b>"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::next_html_column</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<b>maximum</b>"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::next_html_column</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<b>dimensions</b>"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::end_html_row</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Behaviour::is_quasinumerical</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::is_intermediate</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)) </span><span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="identifier">HTML::first_html_column</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
|
|
<span class="identifier">Kinds::Index::index_kind</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::next_html_column</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
|
|
<<span class="cwebmacro">Index the minimum positive value for a quasinumerical kind</span> <span class="cwebmacronumber">32.2.1</span>><span class="plain">;</span>
|
|
<span class="identifier">HTML::next_html_column</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
|
|
<<span class="cwebmacro">Index the maximum positive value for a quasinumerical kind</span> <span class="cwebmacronumber">32.2.2</span>><span class="plain">;</span>
|
|
<span class="identifier">HTML::next_html_column</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Dimensions::dimensionless</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<i>dimensionless</i>"</span><span class="plain">);</span>
|
|
<span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">deriv</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="functiontext">Kinds::Dimensions::index_unit_sequence</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">deriv</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">HTML::end_html_row</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">HTML::end_html_table</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP32">§32</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP32_2_1"></a><b>§32.2.1. </b>At run-time, the minimum positive value is of course <code class="display"><span class="extract">1</span></code>, but because of
|
|
scaling this can appear to be much lower.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Index the minimum positive value for a quasinumerical kind</span> <span class="cwebmacronumber">32.2.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">K_number</span><span class="plain">)) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"1"</span><span class="plain">);</span>
|
|
<span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_index_minimum_value</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) > 0) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">LiteralPatterns::index_value</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">,</span>
|
|
<span class="identifier">LiteralPatterns::list_of_literal_forms</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">), 1);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP32_2">§32.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP32_2_2"></a><b>§32.2.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Index the maximum positive value for a quasinumerical kind</span> <span class="cwebmacronumber">32.2.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">K_number</span><span class="plain">)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">TargetVMs::is_16_bit</span><span class="plain">(</span><span class="identifier">Task::vm</span><span class="plain">())) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"32767"</span><span class="plain">);</span>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"2147483647"</span><span class="plain">);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_index_maximum_value</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) > 0) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
|
|
<span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">TargetVMs::is_16_bit</span><span class="plain">(</span><span class="identifier">Task::vm</span><span class="plain">()))</span>
|
|
<span class="identifier">LiteralPatterns::index_value</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">,</span>
|
|
<span class="identifier">LiteralPatterns::list_of_literal_forms</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">), 32767);</span>
|
|
<span class="reserved">else</span>
|
|
<span class="identifier">LiteralPatterns::index_value</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">,</span>
|
|
<span class="identifier">LiteralPatterns::list_of_literal_forms</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">), 2147483647);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP32_2">§32.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP32_3"></a><b>§32.3. </b>This is simply a table of all the multiplications declared in the source
|
|
text, sorted into kind order of left and then right operand.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Index the table of multiplication rules</span> <span class="cwebmacronumber">32.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain">, *</span><span class="identifier">R</span><span class="plain">, *</span><span class="identifier">O</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">NP</span><span class="plain"> = 0, </span><span class="identifier">wn</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_MULTIPLICATIONS</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">O</span><span class="plain">, </span><span class="identifier">wn</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">NP</span><span class="plain">++ == 0) {</span>
|
|
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"This is how multiplication changes kinds:"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::begin_plain_html_table</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">HTML::first_html_column</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">wn</span><span class="plain"> >= 0) </span><span class="identifier">Index::link</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">wn</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::next_html_column</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
|
|
<span class="identifier">Kinds::Index::index_kind</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::begin_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"808080"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" x "</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::end_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="identifier">Kinds::Index::index_kind</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::begin_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"808080"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" = "</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::end_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="identifier">Kinds::Index::index_kind</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">O</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&nbsp;&nbsp;&nbsp;&nbsp;"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::next_html_column</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
|
|
<span class="identifier">LiteralPatterns::index_benchmark_value</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::begin_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"808080"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" x "</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::end_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="identifier">LiteralPatterns::index_benchmark_value</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::begin_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"808080"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" = "</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::end_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="identifier">LiteralPatterns::index_benchmark_value</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">O</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::end_html_row</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">NP</span><span class="plain"> > 0) { </span><span class="identifier">HTML::end_html_table</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">); </span><span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">); }</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP32">§32</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP33"></a><b>§33. </b>A simpler format for the debugging log, which is printed when we ask for
|
|
the internal "dimensions" test:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::log_unit_analysis</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Dimensionless: "</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = 0; </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Dimensions::dimensionless</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)) { </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain">++ > 0) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">", "</span><span class="plain">); </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$u"</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">); }</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">Base units: "</span><span class="plain">);</span>
|
|
<span class="identifier">c</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::Dimensions::dimensionless</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::Dimensions::kind_is_derived</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::Behaviour::is_quasinumerical</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)))</span>
|
|
<span class="plain">{ </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain">++ > 0) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">", "</span><span class="plain">); </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$u"</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">); }</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">Derived units:\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::Dimensions::kind_is_derived</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)) && (</span><span class="functiontext">Kinds::is_intermediate</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
|
|
<span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">deriv</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$u = $Q\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">deriv</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::kind_is_derived</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::is_intermediate</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::Behaviour::is_quasinumerical</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">)) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::Behaviour::test_if_derived</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">) == </span><span class="identifier">TRUE</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::Dimensions::dimensionless</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::log_unit_analysis appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::kind_is_derived appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP34"></a><b>§34. Scaling. </b>Recall that every quasinumerical kind U has a scale factor k_U, by
|
|
default 1 and always >= 1, such that the true value v is represented
|
|
at runtime as the I6 integer k_U v. For instance, if length is measured
|
|
in metres but has a scale factor of 1000 then the I6 integer 1 means the
|
|
true value 1mm, 10 means 1cm, 1000 means 1m. This I6 integer is called
|
|
the scaled value s, and to reiterate, s = k_U v.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Scaled values are convenient, and they have no effect on how we add, subtract,
|
|
approximate (that is, round off) or take remainder after division. If we
|
|
have true values v_1 and v_2 with scaled values s_1 and s_2,
|
|
and s_o is the scaled value for true value v_1+v_2, then
|
|
</p>
|
|
|
|
<p class="inwebparagraph"> s_1 + s_2 = k_Uv_1 + k_Uv_2 = k_U(v_1+v_2) = s_o.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">So ordinary I6 <code class="display"><span class="extract">+</span></code> at run-time correctly adds scaled values. But that's
|
|
not true for all operations, and this is where we deal with that.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP35"></a><b>§35. </b>First, multiplication. This time the values v_1 and v_2 may have
|
|
different kinds, which we'll call X and Y, and the result in general
|
|
will be a third kind, which we'll call O (for outcome). Then:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"> s_1s_2 = k_Xv_1. k_Yv_2 = k_Ov_1v_2.(((k_Xk_Y) / (k_O))) = s_o.(((k_Xk_Y) / (k_O)))
|
|
</p>
|
|
|
|
<p class="inwebparagraph">so that simply multiplying the scaled values produces an answer which is
|
|
too large by a factor of k_Xk_Y/k_O. We need to correct for that, which
|
|
we do either by dividing by this factor or multiplying by its reciprocal.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">This is all a little delicate since rounding errors may be an issue and
|
|
since k_Xk_Y/k_O is itself evaluated in integer arithmetic. In an ideal
|
|
world we might use the same k for many units (e.g., k=1000 throughout)
|
|
and then of course this cancels to just 1000. But in practice people
|
|
won't always do this — they may use some Babylonian, base 60, units, such
|
|
as minutes and degrees, for instance, where k=3600 would be more natural.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::kind_rescale_multiplication</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindx</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindy</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">kindx</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">kindy</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindo</span><span class="plain"> = </span><span class="functiontext">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">, </span><span class="identifier">kindy</span><span class="plain">, </span><span class="constant">TIMES_OPERATION</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kindo</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_X</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_Y</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindy</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_O</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindo</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_X</span><span class="plain">*</span><span class="identifier">k_Y</span><span class="plain"> > </span><span class="identifier">k_O</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"/%d"</span><span class="plain">, (</span><span class="identifier">k_X</span><span class="plain">*</span><span class="identifier">k_Y</span><span class="plain">/</span><span class="identifier">k_O</span><span class="plain">));</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_X</span><span class="plain">*</span><span class="identifier">k_Y</span><span class="plain"> < </span><span class="identifier">k_O</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"*%d"</span><span class="plain">, (</span><span class="identifier">k_O</span><span class="plain">/</span><span class="identifier">k_X</span><span class="plain">/</span><span class="identifier">k_Y</span><span class="plain">));</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::kind_rescale_multiplication_emit_op</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindx</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindy</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">kindx</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">kindy</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindo</span><span class="plain"> = </span><span class="functiontext">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">, </span><span class="identifier">kindy</span><span class="plain">, </span><span class="constant">TIMES_OPERATION</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kindo</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_X</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_Y</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindy</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_O</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindo</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_X</span><span class="plain">*</span><span class="identifier">k_Y</span><span class="plain"> > </span><span class="identifier">k_O</span><span class="plain">) { </span><span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">DIVIDE_BIP</span><span class="plain">); </span><span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">()); }</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_X</span><span class="plain">*</span><span class="identifier">k_Y</span><span class="plain"> < </span><span class="identifier">k_O</span><span class="plain">) { </span><span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">TIMES_BIP</span><span class="plain">); </span><span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">()); }</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::kind_rescale_multiplication_emit_factor</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindx</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindy</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">kindx</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">kindy</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindo</span><span class="plain"> = </span><span class="functiontext">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">, </span><span class="identifier">kindy</span><span class="plain">, </span><span class="constant">TIMES_OPERATION</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kindo</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_X</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_Y</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindy</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_O</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindo</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_X</span><span class="plain">*</span><span class="identifier">k_Y</span><span class="plain"> > </span><span class="identifier">k_O</span><span class="plain">) { </span><span class="identifier">Produce::val</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) (</span><span class="identifier">k_X</span><span class="plain">*</span><span class="identifier">k_Y</span><span class="plain">/</span><span class="identifier">k_O</span><span class="plain">)); </span><span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">()); }</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_X</span><span class="plain">*</span><span class="identifier">k_Y</span><span class="plain"> < </span><span class="identifier">k_O</span><span class="plain">) { </span><span class="identifier">Produce::val</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) (</span><span class="identifier">k_O</span><span class="plain">/</span><span class="identifier">k_X</span><span class="plain">/</span><span class="identifier">k_Y</span><span class="plain">)); </span><span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">()); }</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::kind_rescale_multiplication appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::kind_rescale_multiplication_emit_op appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::kind_rescale_multiplication_emit_factor appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP36"></a><b>§36. </b>Second, division, which is similar.
|
|
((s_1) / (s_2)) = ((k_Xv_1) / (k_Yv_2)) = k_O((v_1) / (v_2)).(((k_X) / (k_Ok_Y)))
|
|
= s_o.(((k_X) / (k_Ok_Y))right)
|
|
so this time the excess to correct is a factor of k_X/k_Ok_Y.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::kind_rescale_division</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindx</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindy</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">kindx</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">kindy</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindo</span><span class="plain"> = </span><span class="functiontext">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">, </span><span class="identifier">kindy</span><span class="plain">, </span><span class="constant">DIVIDE_OPERATION</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kindo</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_X</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_Y</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindy</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_O</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindo</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_Y</span><span class="plain"> > </span><span class="identifier">k_X</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"*%d"</span><span class="plain">, (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_Y</span><span class="plain">/</span><span class="identifier">k_X</span><span class="plain">));</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_Y</span><span class="plain"> < </span><span class="identifier">k_X</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"/%d"</span><span class="plain">, (</span><span class="identifier">k_X</span><span class="plain">/</span><span class="identifier">k_O</span><span class="plain">/</span><span class="identifier">k_Y</span><span class="plain">));</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::kind_rescale_division_emit_op</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindx</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindy</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">kindx</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">kindy</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindo</span><span class="plain"> = </span><span class="functiontext">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">, </span><span class="identifier">kindy</span><span class="plain">, </span><span class="constant">DIVIDE_OPERATION</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kindo</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_X</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_Y</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindy</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_O</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindo</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_Y</span><span class="plain"> > </span><span class="identifier">k_X</span><span class="plain">) { </span><span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">TIMES_BIP</span><span class="plain">); </span><span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">()); }</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_Y</span><span class="plain"> < </span><span class="identifier">k_X</span><span class="plain">) { </span><span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">DIVIDE_BIP</span><span class="plain">); </span><span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">()); }</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::kind_rescale_division_emit_factor</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindx</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindy</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">kindx</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">kindy</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindo</span><span class="plain"> = </span><span class="functiontext">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">, </span><span class="identifier">kindy</span><span class="plain">, </span><span class="constant">DIVIDE_OPERATION</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kindo</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_X</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_Y</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindy</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_O</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindo</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_Y</span><span class="plain"> > </span><span class="identifier">k_X</span><span class="plain">) { </span><span class="identifier">Produce::val</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_Y</span><span class="plain">/</span><span class="identifier">k_X</span><span class="plain">)); </span><span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">()); }</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_Y</span><span class="plain"> < </span><span class="identifier">k_X</span><span class="plain">) { </span><span class="identifier">Produce::val</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) (</span><span class="identifier">k_X</span><span class="plain">/</span><span class="identifier">k_O</span><span class="plain">/</span><span class="identifier">k_Y</span><span class="plain">)); </span><span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">()); }</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::kind_rescale_division appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::kind_rescale_division_emit_op appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::kind_rescale_division_emit_factor appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP37"></a><b>§37. </b>Third, the taking of pth roots, at any rate for p=2 or p=3.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::kind_rescale_root</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindx</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">power</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kindx</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindo</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">power</span><span class="plain"> == 2) </span><span class="identifier">kindo</span><span class="plain"> = </span><span class="functiontext">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="constant">ROOT_OPERATION</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">power</span><span class="plain"> == 3) </span><span class="identifier">kindo</span><span class="plain"> = </span><span class="functiontext">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="constant">CUBEROOT_OPERATION</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kindo</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_X</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_O</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindo</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">power</span><span class="plain"> == 2) </span><<span class="cwebmacro">Apply a scaling correction for square roots</span> <span class="cwebmacronumber">37.1</span>>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">power</span><span class="plain"> == 3) </span><<span class="cwebmacro">Apply a scaling correction for cube roots</span> <span class="cwebmacronumber">37.2</span>>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"can only scale square and cube roots"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::kind_rescale_root appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP37_1"></a><b>§37.1. </b>For square roots,
|
|
sqrt(s) = sqrt(k_Xv) = sqrt(k_X) sqrt(v) = k_O sqrt(v).
|
|
((( sqrt(k_X)) / (k_O))) = s_o .
|
|
((( sqrt(k_X)) / (k_O)))
|
|
and now the overestimate is a factor of k = sqrt(k_X)/k_O. However,
|
|
rather than calculating k sqrt(x) we calculate sqrt(k^2 x), since
|
|
this way accuracy losses in taking the square root are much reduced.
|
|
Therefore this scaling operating is to be performed inside the root
|
|
function, not outside, and it scales by k^2 not k:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Apply a scaling correction for square roots</span> <span class="cwebmacronumber">37.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain"> > </span><span class="identifier">k_X</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"*%d"</span><span class="plain">, (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain">/</span><span class="identifier">k_X</span><span class="plain">));</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain"> < </span><span class="identifier">k_X</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"/%d"</span><span class="plain">, (</span><span class="identifier">k_X</span><span class="plain">/</span><span class="identifier">k_O</span><span class="plain">/</span><span class="identifier">k_O</span><span class="plain">));</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP37">§37</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP37_2"></a><b>§37.2. </b>For cube roots,
|
|
curt(s) = curt(k_Xv) = curt(k_X) curt(v) = k_O curt(v).
|
|
((( curt(k_X)) / (k_O))) = s_o.
|
|
((( curt(k_X)) / (k_O)))
|
|
and the overestimate is k = curt(k_X)/k_O. Scaling once again within
|
|
the rooting function, we scale by k^3:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Apply a scaling correction for cube roots</span> <span class="cwebmacronumber">37.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain"> > </span><span class="identifier">k_X</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"*%d"</span><span class="plain">, (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain">/</span><span class="identifier">k_X</span><span class="plain">));</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain"> < </span><span class="identifier">k_X</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"/%d"</span><span class="plain">, (</span><span class="identifier">k_X</span><span class="plain">/</span><span class="identifier">k_O</span><span class="plain">/</span><span class="identifier">k_O</span><span class="plain">/</span><span class="identifier">k_O</span><span class="plain">));</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP37">§37</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP38"></a><b>§38. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::kind_rescale_root_emit_op</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindx</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">power</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kindx</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindo</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">power</span><span class="plain"> == 2) </span><span class="identifier">kindo</span><span class="plain"> = </span><span class="functiontext">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="constant">ROOT_OPERATION</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">power</span><span class="plain"> == 3) </span><span class="identifier">kindo</span><span class="plain"> = </span><span class="functiontext">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="constant">CUBEROOT_OPERATION</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kindo</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_X</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_O</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindo</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">power</span><span class="plain"> == 2) </span><<span class="cwebmacro">Emit a scaling correction for square roots</span> <span class="cwebmacronumber">38.1</span>>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">power</span><span class="plain"> == 3) </span><<span class="cwebmacro">Emit a scaling correction for cube roots</span> <span class="cwebmacronumber">38.2</span>>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"can only scale square and cube roots"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::kind_rescale_root_emit_op appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP38_1"></a><b>§38.1. </b>For square roots,
|
|
sqrt(s) = sqrt(k_Xv) = sqrt(k_X) sqrt(v) = k_O sqrt(v).
|
|
((( sqrt(k_X)) / (k_O))) = s_o .
|
|
((( sqrt(k_X)) / (k_O)))
|
|
and now the overestimate is a factor of k = sqrt(k_X)/k_O. However,
|
|
rather than calculating k sqrt(x) we calculate sqrt(k^2 x), since
|
|
this way accuracy losses in taking the square root are much reduced.
|
|
Therefore this scaling operating is to be performed inside the root
|
|
function, not outside, and it scales by k^2 not k:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Emit a scaling correction for square roots</span> <span class="cwebmacronumber">38.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain"> > </span><span class="identifier">k_X</span><span class="plain">) { </span><span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">TIMES_BIP</span><span class="plain">); </span><span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">()); }</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain"> < </span><span class="identifier">k_X</span><span class="plain">) { </span><span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">DIVIDE_BIP</span><span class="plain">); </span><span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">()); }</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP38">§38</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP38_2"></a><b>§38.2. </b>For cube roots,
|
|
curt(s) = curt(k_Xv) = curt(k_X) curt(v) = k_O curt(v).
|
|
((( curt(k_X)) / (k_O))) = s_o.
|
|
((( curt(k_X)) / (k_O)))
|
|
and the overestimate is k = curt(k_X)/k_O. Scaling once again within
|
|
the rooting function, we scale by k^3:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Emit a scaling correction for cube roots</span> <span class="cwebmacronumber">38.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain"> > </span><span class="identifier">k_X</span><span class="plain">) { </span><span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">TIMES_BIP</span><span class="plain">); </span><span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">()); }</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain"> < </span><span class="identifier">k_X</span><span class="plain">) { </span><span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">DIVIDE_BIP</span><span class="plain">); </span><span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">()); }</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP38">§38</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP39"></a><b>§39. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Kinds::Dimensions::kind_rescale_root_emit_factor</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindx</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">power</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kindx</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">kindo</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">power</span><span class="plain"> == 2) </span><span class="identifier">kindo</span><span class="plain"> = </span><span class="functiontext">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="constant">ROOT_OPERATION</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">power</span><span class="plain"> == 3) </span><span class="identifier">kindo</span><span class="plain"> = </span><span class="functiontext">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="constant">CUBEROOT_OPERATION</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">kindo</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_X</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindx</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k_O</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">kindo</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">power</span><span class="plain"> == 2) </span><<span class="cwebmacro">Emit factor for a scaling correction for square roots</span> <span class="cwebmacronumber">39.1</span>>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">power</span><span class="plain"> == 3) </span><<span class="cwebmacro">Emit factor for a scaling correction for cube roots</span> <span class="cwebmacronumber">39.2</span>>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"can only scale square and cube roots"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::kind_rescale_root_emit_factor appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP39_1"></a><b>§39.1. </b>For square roots,
|
|
sqrt(s) = sqrt(k_Xv) = sqrt(k_X) sqrt(v) = k_O sqrt(v).
|
|
((( sqrt(k_X)) / (k_O))) = s_o .
|
|
((( sqrt(k_X)) / (k_O)))
|
|
and now the overestimate is a factor of k = sqrt(k_X)/k_O. However,
|
|
rather than calculating k sqrt(x) we calculate sqrt(k^2 x), since
|
|
this way accuracy losses in taking the square root are much reduced.
|
|
Therefore this scaling operating is to be performed inside the root
|
|
function, not outside, and it scales by k^2 not k:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Emit factor for a scaling correction for square roots</span> <span class="cwebmacronumber">39.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain"> > </span><span class="identifier">k_X</span><span class="plain">) { </span><span class="identifier">Produce::val</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain">/</span><span class="identifier">k_X</span><span class="plain">)); </span><span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">()); }</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain"> < </span><span class="identifier">k_X</span><span class="plain">) { </span><span class="identifier">Produce::val</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) (</span><span class="identifier">k_X</span><span class="plain">/</span><span class="identifier">k_O</span><span class="plain">/</span><span class="identifier">k_O</span><span class="plain">)); </span><span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">()); }</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP39">§39</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP39_2"></a><b>§39.2. </b>For cube roots,
|
|
curt(s) = curt(k_Xv) = curt(k_X) curt(v) = k_O curt(v).
|
|
((( curt(k_X)) / (k_O))) = s_o.
|
|
((( curt(k_X)) / (k_O)))
|
|
and the overestimate is k = curt(k_X)/k_O. Scaling once again within
|
|
the rooting function, we scale by k^3:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Emit factor for a scaling correction for cube roots</span> <span class="cwebmacronumber">39.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain"> > </span><span class="identifier">k_X</span><span class="plain">) { </span><span class="identifier">Produce::val</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain">/</span><span class="identifier">k_X</span><span class="plain">)); </span><span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">()); }</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain">*</span><span class="identifier">k_O</span><span class="plain"> < </span><span class="identifier">k_X</span><span class="plain">) { </span><span class="identifier">Produce::val</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) (</span><span class="identifier">k_X</span><span class="plain">/</span><span class="identifier">k_O</span><span class="plain">/</span><span class="identifier">k_O</span><span class="plain">/</span><span class="identifier">k_O</span><span class="plain">)); </span><span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">()); }</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP39">§39</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP40"></a><b>§40. Arithmetic on kinds. </b>We are finally able to provide our central routine, the one providing a service
|
|
for the rest of Inform. Given <code class="display"><span class="extract">K1</span></code> and <code class="display"><span class="extract">K2</span></code>, we return the kind resulting
|
|
from applying arithmetic operation <code class="display"><span class="extract">op</span></code>, or <code class="display"><span class="extract">NULL</span></code> if the operation cannot
|
|
meaningfully be applied. In the case where <code class="display"><span class="extract">op</span></code> is a unary operation, <code class="display"><span class="extract">K2</span></code>
|
|
has no significance and should be <code class="display"><span class="extract">NULL</span></code>.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The kinds here are called operands, because they are what will be operated on.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K1</span><span class="plain">, </span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K2</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">op</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K1</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::Dimensions::arithmetic_op_is_unary</span><span class="plain">(</span><span class="identifier">op</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) && (</span><span class="identifier">K2</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">operand1</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">operand1</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">operand2</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">K2</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::Dimensions::arithmetic_op_is_unary</span><span class="plain">(</span><span class="identifier">op</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) && (</span><span class="identifier">operand2</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">unit_sequence</span><span class="plain"> </span><span class="identifier">result</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">op</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">PLUS_OPERATION</span><span class="plain">:</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">MINUS_OPERATION</span><span class="plain">:</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">EQUALS_OPERATION</span><span class="plain">:</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">APPROXIMATION_OPERATION</span><span class="plain">:</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Dimensions::compare_unit_sequences</span><span class="plain">(</span><span class="identifier">operand1</span><span class="plain">, </span><span class="identifier">operand2</span><span class="plain">)) {</span>
|
|
<span class="identifier">result</span><span class="plain"> = *</span><span class="identifier">operand1</span><span class="plain">;</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">UNARY_MINUS_OPERATION</span><span class="plain">:</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">REMAINDER_OPERATION</span><span class="plain">:</span>
|
|
<span class="identifier">result</span><span class="plain"> = *</span><span class="identifier">operand1</span><span class="plain">;</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">ROOT_OPERATION</span><span class="plain">:</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Dimensions::root_unit_sequence</span><span class="plain">(</span><span class="identifier">operand1</span><span class="plain">, 2, &</span><span class="identifier">result</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">REALROOT_OPERATION</span><span class="plain">:</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Dimensions::root_unit_sequence</span><span class="plain">(</span><span class="identifier">operand1</span><span class="plain">, 2, &</span><span class="identifier">result</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CUBEROOT_OPERATION</span><span class="plain">:</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Dimensions::root_unit_sequence</span><span class="plain">(</span><span class="identifier">operand1</span><span class="plain">, 3, &</span><span class="identifier">result</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">TIMES_OPERATION</span><span class="plain">:</span>
|
|
<span class="functiontext">Kinds::Dimensions::multiply_unit_sequences</span><span class="plain">(</span><span class="identifier">operand1</span><span class="plain">, 1, </span><span class="identifier">operand2</span><span class="plain">, 1, &</span><span class="identifier">result</span><span class="plain">);</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">DIVIDE_OPERATION</span><span class="plain">:</span>
|
|
<span class="functiontext">Kinds::Dimensions::multiply_unit_sequences</span><span class="plain">(</span><span class="identifier">operand1</span><span class="plain">, 1, </span><span class="identifier">operand2</span><span class="plain">, -1, &</span><span class="identifier">result</span><span class="plain">);</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">default</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<<span class="cwebmacro">Handle calculations entirely between dimensionless units more delicately</span> <span class="cwebmacronumber">40.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Handle the case of a dimensionless result</span> <span class="cwebmacronumber">40.2</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Identify the result as a known kind, if possible</span> <span class="cwebmacronumber">40.3</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">And otherwise create a kind as the intermediate result of a calculation</span> <span class="cwebmacronumber">40.4</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::arithmetic_on_kinds is used in <a href="#SP35">§35</a>, <a href="#SP36">§36</a>, <a href="#SP37">§37</a>, <a href="#SP38">§38</a>, <a href="#SP39">§39</a>, <a href="#SP41">§41</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP40_1"></a><b>§40.1. </b>If <code class="display"><span class="extract">result</span></code> is the empty unit sequence, we'll identify it as a number,
|
|
because number is the lowest type ID representing a dimensionless unit.
|
|
Usually that's good: for instance, it says that a frequency times a time
|
|
is a number, and not some more exotic dimensionless quantity like an angle.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">But it's not so good when the calculation is not really physical at all, but
|
|
purely mathematical, and all we are doing is working on dimensionless units.
|
|
For instance, if take an angle θ and double it to 2θ, we don't
|
|
want Inform to say the result is number — we want 2θ to be
|
|
another angle. So we make an exception.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Handle calculations entirely between dimensionless units more delicately</span> <span class="cwebmacronumber">40.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Dimensions::arithmetic_op_is_unary</span><span class="plain">(</span><span class="identifier">op</span><span class="plain">)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">op</span><span class="plain"> == </span><span class="constant">REALROOT_OPERATION</span><span class="plain">) && (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">, </span><span class="identifier">K_number</span><span class="plain">)))</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K_real_number</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Dimensions::dimensionless</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">K1</span><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::Dimensions::dimensionless</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">)) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::Dimensions::dimensionless</span><span class="plain">(</span><span class="identifier">K2</span><span class="plain">))) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K2</span><span class="plain">, </span><span class="identifier">K_number</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">K1</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">, </span><span class="identifier">K_number</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">K2</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">, </span><span class="identifier">K2</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">K1</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP40">§40</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP40_2"></a><b>§40.2. </b>It's also possible to get a dimensionless result by, for example, dividing
|
|
a mass by another mass, and we need to be careful to keep track of whether
|
|
we're using real or integer arithmetic: 1500.0m divided by 10.0m must be
|
|
150.0, not 150.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Handle the case of a dimensionless result</span> <span class="cwebmacronumber">40.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Dimensions::us_dimensionless</span><span class="plain">(&</span><span class="identifier">result</span><span class="plain">)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Dimensions::arithmetic_op_is_unary</span><span class="plain">(</span><span class="identifier">op</span><span class="plain">)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::FloatingPoint::uses_floating_point</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">K_real_number</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K_number</span><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Kinds::FloatingPoint::uses_floating_point</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">)) ||</span>
|
|
<span class="plain">(</span><span class="functiontext">Kinds::FloatingPoint::uses_floating_point</span><span class="plain">(</span><span class="identifier">K2</span><span class="plain">))) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">K_real_number</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">K_number</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP40">§40</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP40_3"></a><b>§40.3. </b>If we've produced the right combination of fundamental units to make one of the
|
|
named units, then we return that as an atomic kind. For instance, maybe we
|
|
divided a velocity by a time, and now we find that we have m.
|
|
s^{-2}, which turns out to have a name: acceleration.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Identify the result as a known kind, if possible</span> <span class="cwebmacronumber">40.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_BASE_KINDS</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Dimensions::compare_unit_sequences</span><span class="plain">(&</span><span class="identifier">result</span><span class="plain">,</span>
|
|
<span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)))</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">R</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP40">§40</a>, <a href="#SP41">§41</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP40_4"></a><b>§40.4. </b>Otherwise the <code class="display"><span class="extract">result</span></code> is a unit sequence which doesn't have a name, so
|
|
we store it as an intermediate kind, representing a temporary value living
|
|
only for the duration of a calculation.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">A last little wrinkle is: how we should scale this? For results like an
|
|
acceleration, something defined in the source text, we know how accurate the
|
|
author wants us to be. But these intermediate kinds are not defined, and we
|
|
don't know for sure what the author would want. It seems wise to set
|
|
k >= k_X and k>= k_Y, so that we have at least as much detail as
|
|
the calculation would have had within each operand kind. So perhaps we should
|
|
put k = max(k_X, k_Y). But in fact we will choose k = <code class="display"><span class="extract">Kinds::Dimensions::lcm(k_X, k_Y)</span></code>,
|
|
the least common multiple, so that any subsequent divisions will cancel
|
|
correctly and we won't lose too much information through integer rounding.
|
|
(In practice this will probably either be the same as max(k_X, k_Y)
|
|
or will multiply by 6, since <code class="display"><span class="extract">Kinds::Dimensions::lcm(60, 1000) == 6000</span></code> and so on.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The same unit sequence can have different scalings each time it appears as
|
|
an intermediate calculation. We could get to m^2. kg
|
|
either as m.kg times m, or as m^2 times
|
|
kg, or many other ways, and we'll get different scalings depending
|
|
on the route. This is why the <code class="display"><span class="extract">unit_sequence</span></code> structure has a
|
|
<code class="display"><span class="extract">scaling_factor</span></code> field; the choice of scale factor does not depend on
|
|
the physics but on the arithmetic method being used.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">And otherwise create a kind as the intermediate result of a calculation</span> <span class="cwebmacronumber">40.4</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">result</span><span class="element">.scaling_factor</span><span class="plain"> = </span><span class="functiontext">Kinds::Dimensions::lcm</span><span class="plain">(</span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">K1</span><span class="plain">), </span><span class="functiontext">Kinds::Behaviour::scale_factor</span><span class="plain">(</span><span class="identifier">K2</span><span class="plain">));</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Kinds::intermediate_construction</span><span class="plain">(&</span><span class="identifier">result</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP40">§40</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP41"></a><b>§41. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="functiontext">Kinds::Dimensions::to_rational_power</span><span class="plain">(</span><span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">n</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">m</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">n</span><span class="plain"> < 1) || (</span><span class="identifier">m</span><span class="plain"> < 1)) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"bad rational power"</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Dimensions::dimensionless</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">F</span><span class="plain">;</span>
|
|
<span class="reserved">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">K_number</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">op</span><span class="plain"> = </span><span class="constant">TIMES_OPERATION</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">n</span><span class="plain"> < 0) { </span><span class="identifier">n</span><span class="plain"> = -</span><span class="identifier">n</span><span class="plain">; </span><span class="identifier">op</span><span class="plain"> = </span><span class="constant">DIVIDE_OPERATION</span><span class="plain">; }</span>
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">n</span><span class="plain"> > 0) {</span>
|
|
<span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Kinds::Dimensions::arithmetic_on_kinds</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">F</span><span class="plain">, </span><span class="identifier">op</span><span class="plain">);</span>
|
|
<span class="identifier">n</span><span class="plain">--;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">m</span><span class="plain"> == 1) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">K</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">unit_sequence</span><span class="plain"> </span><span class="identifier">result</span><span class="plain">;</span>
|
|
<span class="reserved">unit_sequence</span><span class="plain"> *</span><span class="identifier">operand</span><span class="plain"> = </span><span class="functiontext">Kinds::Behaviour::get_dimensional_form</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Kinds::Dimensions::root_unit_sequence</span><span class="plain">(</span><span class="identifier">operand</span><span class="plain">, </span><span class="identifier">m</span><span class="plain">, &</span><span class="identifier">result</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Identify the result as a known kind, if possible</span> <span class="cwebmacronumber">40.3</span>><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Kinds::Dimensions::to_rational_power appears nowhere else.</p>
|
|
|
|
<hr class="tocbar">
|
|
<ul class="toc"><li><a href="2-dk.html">Back to 'Describing Kinds'</a></li><li><a href="2-fv.html">Continue with 'Floating-Point Values'</a></li></ul><hr class="tocbar">
|
|
<!--End of weave-->
|
|
</main>
|
|
</body>
|
|
</html>
|
|
|