OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [trunk/] [fp/] [implementation/] [arith/] [mmix-arith.tex] - Rev 274

Go to most recent revision | Compare with Previous | Blame | View Log

\input cwebmac
% This file is part of the MMIXware package (c) Donald E Knuth 1999
% This material goes at the beginning of all MMIXware CWEB files
 
\def\topofcontents{
  \leftline{\sc\today\ at \hours}\bigskip\bigskip
  \centerline{\titlefont\title}}
 
\font\ninett=cmtt9
\def\botofcontents{\vskip 0pt plus 1filll
    \ninerm\baselineskip10pt
    \noindent\copyright\ 1999 Donald E. Knuth
    \bigskip\noindent
    This file may be freely copied and distributed, provided that
    no changes whatsoever are made. All users are asked to help keep
    the {\ninett MMIX}ware files consistent and ``uncorrupted,''
    identical everywhere in the world. Changes are permissible only
    if the modified file is given a new name, different from the names of
    existing files in the {\ninett MMIX}ware package,
    and only if the modified file is clearly identified
    as not being part of that package.
    (The {\ninett CWEB} system has a ``change file'' facility by
    which users can easily make minor alterations without modifying
    the master source files in any way. Everybody is supposed to use
    change files instead of changing the files.)
    The author has tried his best to produce correct and useful programs,
    in order to help promote computer science research,
    but no warranty of any kind should be assumed.}
 
 
\def\title{MMIX-ARITH}
 
\def\MMIX{\.{MMIX}}
\def\MMIXAL{\.{MMIXAL}}
\def\Hex#1{\hbox{$^{\scriptscriptstyle\#}$\tt#1}} % experimental hex constant
\def\dts{\mathinner{\ldotp\ldotp}}
\def\<#1>{\hbox{$\langle\,$#1$\,\rangle$}}\let\is=\longrightarrow
\def\ff{\\{ff\kern-.05em}}
 
 
 
 
\N{1}{1}Introduction. The subroutines below are used to simulate 64-bit \MMIX\
arithmetic on an old-fashioned 32-bit computer---like the one the author
had when he wrote \MMIXAL\ and the first \MMIX\ simulators in 1998 and 1999.
All operations are fabricated from 32-bit arithmetic, including
a full implementation of the IEEE floating point standard,
assuming only that the \CEE/ compiler has a 32-bit unsigned integer type.
 
Some day 64-bit machines will be commonplace and the awkward manipulations of
the present program will look quite archaic. Interested readers who have such
computers will be able to convert the code to a pure 64-bit form without
difficulty, thereby obtaining much faster and simpler routines. Meanwhile,
however, we can simulate the future and hope for continued progress.
 
This program module has a simple structure, intended to make it
suitable for loading with \MMIX\ simulators and assemblers.
 
\Y\B\8\#\&{include} \.{<stdio.h>}\6
\8\#\&{include} \.{<string.h>}\6
\8\#\&{include} \.{<ctype.h>}\6
\X2:Stuff for \CEE/ preprocessor\X\7
\&{typedef} \&{enum} ${}\{{}$\5
\1${}\\{false},\39{}$\\{true}\5
\2${}\}{}$ \&{bool};\7
\X3:Tetrabyte and octabyte type definitions\X\6
\X36:Other type definitions\X\6
\X4:Global variables\X\6
\X5:Subroutines\X\par
\fi
 
\M{2}Subroutines of this program are declared first with a prototype,
as in {\mc ANSI C}, then with an old-style \CEE/ function definition.
Here are some preprocessor commands that make this work correctly with both
new-style and old-style compilers.
 
\Y\B\4\X2:Stuff for \CEE/ preprocessor\X${}\E{}$\6
\8\#\&{ifdef} \.{\_\_STDC\_\_}\6
\8\#\&{define} \.{ARGS}(\\{list}) \5\\{list}\6
\8\#\&{else}\6
\8\#\&{define} \.{ARGS}(\\{list}) \5(\,)\6
\8\#\&{endif}\par
\U1.\fi
 
\M{3}The definition of type \&{tetra} should be changed, if necessary, so that
it represents an unsigned 32-bit integer.
 
\Y\B\4\X3:Tetrabyte and octabyte type definitions\X${}\E{}$\6
\&{typedef} \&{unsigned} \&{int} \&{tetra};\C{ for systems conforming to the
LP-64 data model }\6
\&{typedef} \&{struct} ${}\{{}$\1\6
\&{tetra} \|h${},{}$ \|l;\2\6
${}\}{}$ \&{octa};\C{ two tetrabytes make one octabyte }\par
\U1.\fi
 
\M{4}\B\D$\\{sign\_bit}$ \5
((\&{unsigned}) \T{\^80000000})\par
\Y\B\4\X4:Global variables\X${}\E{}$\6
\&{octa} \\{zero\_octa};\C{ \PB{$\\{zero\_octa}.\|h\K\\{zero\_octa}.\|l\K%
\T{0}$} }\6
\&{octa} \\{neg\_one}${}\K\{{-}\T{1},\39{-}\T{1}\}{}$;\C{ \PB{$\\{neg\_one}.\|h%
\K\\{neg\_one}.\|l\K{-}\T{1}$} }\6
\&{octa} \\{inf\_octa}${}\K\{\T{\^7ff00000},\39\T{0}\}{}$;\C{ floating point $+%
\infty$ }\6
\&{octa} \\{standard\_NaN}${}\K\{\T{\^7ff80000},\39\T{0}\}{}$;\C{ floating
point NaN(.5) }\6
\&{octa} \\{aux};\C{ auxiliary output of a subroutine }\6
\&{bool} \\{overflow};\C{ set by certain subroutines for signed arithmetic }\par
\As9, 30, 32, 69\ETs75.
\U1.\fi
 
\M{5}It's easy to add and subtract octabytes, if we aren't terribly
worried about speed.
 
\Y\B\4\X5:Subroutines\X${}\E{}$\6
\&{octa} \\{oplus}\,\,${}\.{ARGS}((\&{octa},\39\&{octa})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{oplus}(\|y,\39\|z{}$)\C{ compute $y+z$ }\1\1\6
\&{octa} \|y${},{}$ \|z;\2\2\6
${}\{{}$\5
\1\&{octa} \|x;\7
${}\|x.\|h\K\|y.\|h+\|z.\|h{}$;\5
${}\|x.\|l\K\|y.\|l+\|z.\|l;{}$\6
\&{if} ${}(\|x.\|l<\|y.\|l){}$\1\5
${}\|x.\|h\PP;{}$\2\6
\&{return} \|x;\6
\4${}\}{}$\2\7
\&{octa} \\{ominus}\,\,${}\.{ARGS}((\&{octa},\39\&{octa})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{ominus}(\|y,\39\|z{}$)\C{ compute $y-z$ }\1\1\6
\&{octa} \|y${},{}$ \|z;\2\2\6
${}\{{}$\5
\1\&{octa} \|x;\7
${}\|x.\|h\K\|y.\|h-\|z.\|h{}$;\5
${}\|x.\|l\K\|y.\|l-\|z.\|l;{}$\6
\&{if} ${}(\|x.\|l>\|y.\|l){}$\1\5
${}\|x.\|h\MM;{}$\2\6
\&{return} \|x;\6
\4${}\}{}$\2\par
\As6, 7, 8, 12, 13, 24, 25, 26, 27, 28, 29, 31, 34, 37, 38, 39, 40, 41, 44, 46,
50, 54, 60, 61, 62, 68, 82, 85, 86, 88, 89, 91\ETs93.
\U1.\fi
 
\M{6}In the following subroutine, \PB{\\{delta}} is a signed quantity that is
assumed to fit in a signed tetrabyte.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{octa} \\{incr}\,\,${}\.{ARGS}((\&{octa},\39\&{int})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{incr}(\|y,\39\\{delta}{}$)\C{ compute $y+\delta$ }\1%
\1\6
\&{octa} \|y;\6
\&{int} \\{delta};\2\2\6
${}\{{}$\5
\1\&{octa} \|x;\7
${}\|x.\|h\K\|y.\|h{}$;\5
${}\|x.\|l\K\|y.\|l+\\{delta};{}$\6
\&{if} ${}(\\{delta}\G\T{0}){}$\5
${}\{{}$\1\6
\&{if} ${}(\|x.\|l<\|y.\|l){}$\1\5
${}\|x.\|h\PP;{}$\2\6
\4${}\}{}$\5
\2\&{else} \&{if} ${}(\|x.\|l>\|y.\|l){}$\1\5
${}\|x.\|h\MM;{}$\2\6
\&{return} \|x;\6
\4${}\}{}$\2\par
\fi
 
\M{7}Left and right shifts are only a bit more difficult.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{octa} \\{shift\_left}\,\,${}\.{ARGS}((\&{octa},\39\&{int})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{shift\_left}(\|y,\39\|s{}$)\C{ shift left by $s$
bits, where $0\le s\le64$ }\1\1\6
\&{octa} \|y;\6
\&{int} \|s;\2\2\6
${}\{{}$\1\6
\&{while} ${}(\|s\G\T{32}){}$\1\5
${}\|y.\|h\K\|y.\|l,\39\|y.\|l\K\T{0},\39\|s\MRL{-{\K}}\T{32};{}$\2\6
\&{if} (\|s)\5
${}\{{}$\5
\1\&{register} \&{tetra} \\{yhl}${}\K\|y.\|h\LL\|s,{}$ \\{ylh}${}\K\|y.\|l\GG(%
\T{32}-\|s);{}$\7
${}\|y.\|h\K\\{yhl}+\\{ylh}{}$;\5
${}\|y.\|l\MRL{{\LL}{\K}}\|s;{}$\6
\4${}\}{}$\2\6
\&{return} \|y;\6
\4${}\}{}$\2\7
\&{octa} \\{shift\_right}\,\,${}\.{ARGS}((\&{octa},\39\&{int},\39\&{int})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{shift\_right}(\|y,\39\|s,\39\|u{}$)\C{ shift right,
arithmetically if $u=0$ }\1\1\6
\&{octa} \|y;\6
\&{int} \|s${},{}$ \|u;\2\2\6
${}\{{}$\1\6
\&{while} ${}(\|s\G\T{32}){}$\1\5
${}\|y.\|l\K\|y.\|h,\39\|y.\|h\K(\|u\?\T{0}:{-}(\|y.\|h\GG\T{31})),\39\|s%
\MRL{-{\K}}\T{32};{}$\2\6
\&{if} (\|s)\5
${}\{{}$\5
\1\&{register} \&{tetra} \\{yhl}${}\K\|y.\|h\LL(\T{32}-\|s),{}$ \\{ylh}${}\K%
\|y.\|l\GG\|s;{}$\7
${}\|y.\|h\K(\|u\?\T{0}:({-}(\|y.\|h\GG\T{31}))\LL(\T{32}-\|s))+(\|y.\|h\GG%
\|s){}$;\5
${}\|y.\|l\K\\{yhl}+\\{ylh};{}$\6
\4${}\}{}$\2\6
\&{return} \|y;\6
\4${}\}{}$\2\par
\fi
 
\N{1}{8}Multiplication. We need to multiply two unsigned 64-bit integers,
obtaining
an unsigned 128-bit product. It is easy to do this on a 32-bit machine
by using Algorithm 4.3.1M of {\sl Seminumerical Algorithms}, with $b=2^{16}$.
 
The following subroutine returns the lower half of the product, and
puts the upper half into a global octabyte called \PB{\\{aux}}.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{octa} \\{omult}\,\,${}\.{ARGS}((\&{octa},\39\&{octa})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{omult}(\|y,\39\|z){}$\1\1\6
\&{octa} \|y${},{}$ \|z;\2\2\6
${}\{{}$\1\6
\&{register} \&{int} \|i${},{}$ \|j${},{}$ \|k;\6
\&{tetra} \|u[\T{4}]${},{}$ \|v[\T{4}]${},{}$ \|w[\T{8}];\6
\&{register} \&{tetra} \|t;\6
\&{octa} \\{acc};\7
\X10:Unpack the multiplier and multiplicand to \PB{\|u} and \PB{\|v}\X;\6
\&{for} ${}(\|j\K\T{0};{}$ ${}\|j<\T{4};{}$ ${}\|j\PP){}$\1\5
${}\|w[\|j]\K\T{0};{}$\2\6
\&{for} ${}(\|j\K\T{0};{}$ ${}\|j<\T{4};{}$ ${}\|j\PP){}$\1\6
\&{if} ${}(\R\|v[\|j]){}$\1\5
${}\|w[\|j+\T{4}]\K\T{0};{}$\2\6
\&{else}\5
${}\{{}$\1\6
\&{for} ${}(\|i\K\|k\K\T{0};{}$ ${}\|i<\T{4};{}$ ${}\|i\PP){}$\5
${}\{{}$\1\6
${}\|t\K\|u[\|i]*\|v[\|j]+\|w[\|i+\|j]+\|k;{}$\6
${}\|w[\|i+\|j]\K\|t\AND\T{\^ffff},\39\|k\K\|t\GG\T{16};{}$\6
\4${}\}{}$\2\6
${}\|w[\|j+\T{4}]\K\|k;{}$\6
\4${}\}{}$\2\2\6
\X11:Pack \PB{\|w} into the outputs \PB{\\{aux}} and \PB{\\{acc}}\X;\6
\&{return} \\{acc};\6
\4${}\}{}$\2\par
\fi
 
\M{9}\B\X4:Global variables\X${}\mathrel+\E{}$\6
\&{extern} \&{octa} \\{aux};\C{ secondary output of subroutines with multiple
outputs }\6
\&{extern} \&{bool} \\{overflow};\par
\fi
 
\M{10}\B\X10:Unpack the multiplier and multiplicand to \PB{\|u} and \PB{\|v}%
\X${}\E{}$\6
$\|u[\T{3}]\K\|y.\|h\GG\T{16},\39\|u[\T{2}]\K\|y.\|h\AND\T{\^ffff},\39\|u[%
\T{1}]\K\|y.\|l\GG\T{16},\39\|u[\T{0}]\K\|y.\|l\AND\T{\^ffff};{}$\6
${}\|v[\T{3}]\K\|z.\|h\GG\T{16},\39\|v[\T{2}]\K\|z.\|h\AND\T{\^ffff},\39\|v[%
\T{1}]\K\|z.\|l\GG\T{16},\39\|v[\T{0}]\K\|z.\|l\AND\T{\^ffff}{}$;\par
\U8.\fi
 
\M{11}\B\X11:Pack \PB{\|w} into the outputs \PB{\\{aux}} and \PB{\\{acc}}\X${}%
\E{}$\6
$\\{aux}.\|h\K(\|w[\T{7}]\LL\T{16})+\|w[\T{6}],\39\\{aux}.\|l\K(\|w[\T{5}]\LL%
\T{16})+\|w[\T{4}];{}$\6
${}\\{acc}.\|h\K(\|w[\T{3}]\LL\T{16})+\|w[\T{2}],\39\\{acc}.\|l\K(\|w[\T{1}]\LL%
\T{16})+\|w[\T{0}]{}$;\par
\U8.\fi
 
\M{12}Signed multiplication has the same lower half product as unsigned
multiplication. The signed upper half product is obtained with at most two
further subtractions, after which the result has overflowed if and only if
the upper half is unequal to 64 copies of the sign bit in the lower half.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{octa} \\{signed\_omult}\,\,${}\.{ARGS}((\&{octa},\39\&{octa})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{signed\_omult}(\|y,\39\|z){}$\1\1\6
\&{octa} \|y${},{}$ \|z;\2\2\6
${}\{{}$\1\6
\&{octa} \\{acc};\7
${}\\{acc}\K\\{omult}(\|y,\39\|z);{}$\6
\&{if} ${}(\|y.\|h\AND\\{sign\_bit}){}$\1\5
${}\\{aux}\K\\{ominus}(\\{aux},\39\|z);{}$\2\6
\&{if} ${}(\|z.\|h\AND\\{sign\_bit}){}$\1\5
${}\\{aux}\K\\{ominus}(\\{aux},\39\|y);{}$\2\6
${}\\{overflow}\K(\\{aux}.\|h\I\\{aux}.\|l\V(\\{aux}.\|h\XOR(\\{aux}.\|h\GG%
\T{1})\XOR(\\{acc}.\|h\AND\\{sign\_bit})));{}$\6
\&{return} \\{acc};\6
\4${}\}{}$\2\par
\fi
 
\N{1}{13}Division. Long division of an unsigned 128-bit integer by an unsigned
64-bit integer is, of course, one of the most challenging routines
needed for \MMIX\ arithmetic. The following program, based on
Algorithm 4.3.1D of {\sl Seminumerical Algorithms}, computes
octabytes $q$ and $r$ such that $(2^{64}x+y)=qz+r$ and $0\le r<z$,
given octabytes $x$, $y$, and~$z$, assuming that $x<z$.
(If $x\ge z$, it simply sets $q=x$ and $r=y$.)
The quotient~$q$ is returned by the subroutine;
the remainder~$r$ is stored in \PB{\\{aux}}.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{octa} \\{odiv}\,\,${}\.{ARGS}((\&{octa},\39\&{octa},\39\&{octa})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{odiv}(\|x,\39\|y,\39\|z){}$\1\1\6
\&{octa} \|x${},{}$ \|y${},{}$ \|z;\2\2\6
${}\{{}$\1\6
\&{register} \&{int} \|i${},{}$ \|j${},{}$ \|k${},{}$ \|n${},{}$ \|d;\6
\&{tetra} \|u[\T{8}]${},{}$ \|v[\T{4}]${},{}$ \|q[\T{4}]${},{}$ \\{mask}${},{}$
\\{qhat}${},{}$ \\{rhat}${},{}$ \\{vh}${},{}$ \\{vmh};\6
\&{register} \&{tetra} \|t;\6
\&{octa} \\{acc};\7
\X14:Check that \PB{$\|x<\|z$}; otherwise give trivial answer\X;\6
\X15:Unpack the dividend and divisor to \PB{\|u} and \PB{\|v}\X;\6
\X16:Determine the number of significant places \PB{\|n} in the divisor \PB{%
\|v}\X;\6
\X17:Normalize the divisor\X;\6
\&{for} ${}(\|j\K\T{3};{}$ ${}\|j\G\T{0};{}$ ${}\|j\MM){}$\1\5
\X20:Determine the quotient digit \PB{\|q[\|j]}\X;\2\6
\X18:Unnormalize the remainder\X;\6
\X19:Pack \PB{\|q} and \PB{\|u} to \PB{\\{acc}} and \PB{\\{aux}}\X;\6
\&{return} \\{acc};\6
\4${}\}{}$\2\par
\fi
 
\M{14}\B\X14:Check that \PB{$\|x<\|z$}; otherwise give trivial answer\X${}\E{}$%
\6
\&{if} ${}(\|x.\|h>\|z.\|h\V(\|x.\|h\E\|z.\|h\W\|x.\|l\G\|z.\|l)){}$\5
${}\{{}$\1\6
${}\\{aux}\K\|y{}$;\5
\&{return} \|x;\6
\4${}\}{}$\2\par
\U13.\fi
 
\M{15}\B\X15:Unpack the dividend and divisor to \PB{\|u} and \PB{\|v}\X${}\E{}$%
\6
$\|u[\T{7}]\K\|x.\|h\GG\T{16},\39\|u[\T{6}]\K\|x.\|h\AND\T{\^ffff},\39\|u[%
\T{5}]\K\|x.\|l\GG\T{16},\39\|u[\T{4}]\K\|x.\|l\AND\T{\^ffff};{}$\6
${}\|u[\T{3}]\K\|y.\|h\GG\T{16},\39\|u[\T{2}]\K\|y.\|h\AND\T{\^ffff},\39\|u[%
\T{1}]\K\|y.\|l\GG\T{16},\39\|u[\T{0}]\K\|y.\|l\AND\T{\^ffff};{}$\6
${}\|v[\T{3}]\K\|z.\|h\GG\T{16},\39\|v[\T{2}]\K\|z.\|h\AND\T{\^ffff},\39\|v[%
\T{1}]\K\|z.\|l\GG\T{16},\39\|v[\T{0}]\K\|z.\|l\AND\T{\^ffff}{}$;\par
\U13.\fi
 
\M{16}\B\X16:Determine the number of significant places \PB{\|n} in the divisor
\PB{\|v}\X${}\E{}$\6
\&{for} ${}(\|n\K\T{4};{}$ ${}\|v[\|n-\T{1}]\E\T{0};{}$ ${}\|n\MM){}$\1\5
;\2\par
\U13.\fi
 
\M{17}We shift \PB{\|u} and \PB{\|v} left by \PB{\|d} places, where \PB{\|d} is
chosen to
make $2^{15}\le v_{n-1}<2^{16}$.
 
\Y\B\4\X17:Normalize the divisor\X${}\E{}$\6
$\\{vh}\K\|v[\|n-\T{1}];{}$\6
\&{for} ${}(\|d\K\T{0};{}$ ${}\\{vh}<\T{\^8000};{}$ ${}\|d\PP,\39\\{vh}\MRL{{%
\LL}{\K}}\T{1}){}$\1\5
;\2\6
\&{for} ${}(\|j\K\|k\K\T{0};{}$ ${}\|j<\|n+\T{4};{}$ ${}\|j\PP){}$\5
${}\{{}$\1\6
${}\|t\K(\|u[\|j]\LL\|d)+\|k;{}$\6
${}\|u[\|j]\K\|t\AND\T{\^ffff},\39\|k\K\|t\GG\T{16};{}$\6
\4${}\}{}$\2\6
\&{for} ${}(\|j\K\|k\K\T{0};{}$ ${}\|j<\|n;{}$ ${}\|j\PP){}$\5
${}\{{}$\1\6
${}\|t\K(\|v[\|j]\LL\|d)+\|k;{}$\6
${}\|v[\|j]\K\|t\AND\T{\^ffff},\39\|k\K\|t\GG\T{16};{}$\6
\4${}\}{}$\2\6
${}\\{vh}\K\|v[\|n-\T{1}];{}$\6
${}\\{vmh}\K(\|n>\T{1}\?\|v[\|n-\T{2}]:\T{0}){}$;\par
\U13.\fi
 
\M{18}\B\X18:Unnormalize the remainder\X${}\E{}$\6
$\\{mask}\K(\T{1}\LL\|d)-\T{1};{}$\6
\&{for} ${}(\|j\K\T{3};{}$ ${}\|j\G\|n;{}$ ${}\|j\MM){}$\1\5
${}\|u[\|j]\K\T{0};{}$\2\6
\&{for} ${}(\|k\K\T{0};{}$ ${}\|j\G\T{0};{}$ ${}\|j\MM){}$\5
${}\{{}$\1\6
${}\|t\K(\|k\LL\T{16})+\|u[\|j];{}$\6
${}\|u[\|j]\K\|t\GG\|d,\39\|k\K\|t\AND\\{mask};{}$\6
\4${}\}{}$\2\par
\U13.\fi
 
\M{19}\B\X19:Pack \PB{\|q} and \PB{\|u} to \PB{\\{acc}} and \PB{\\{aux}}\X${}%
\E{}$\6
$\\{acc}.\|h\K(\|q[\T{3}]\LL\T{16})+\|q[\T{2}],\39\\{acc}.\|l\K(\|q[\T{1}]\LL%
\T{16})+\|q[\T{0}];{}$\6
${}\\{aux}.\|h\K(\|u[\T{3}]\LL\T{16})+\|u[\T{2}],\39\\{aux}.\|l\K(\|u[\T{1}]\LL%
\T{16})+\|u[\T{0}]{}$;\par
\U13.\fi
 
\M{20}\B\X20:Determine the quotient digit \PB{\|q[\|j]}\X${}\E{}$\6
${}\{{}$\1\6
\X21:Find the trial quotient, $\hat q$\X;\6
\X22:Subtract $b^j\hat q v$ from \PB{\|u}\X;\6
\X23:If the result was negative, decrease $\hat q$ by 1\X;\6
${}\|q[\|j]\K\\{qhat};{}$\6
\4${}\}{}$\2\par
\U13.\fi
 
\M{21}\B\X21:Find the trial quotient, $\hat q$\X${}\E{}$\6
$\|t\K(\|u[\|j+\|n]\LL\T{16})+\|u[\|j+\|n-\T{1}];{}$\6
${}\\{qhat}\K\|t/\\{vh},\39\\{rhat}\K\|t-\\{vh}*\\{qhat};{}$\6
\&{if} ${}(\|n>\T{1}){}$\1\6
\&{while} ${}(\\{qhat}\E\T{\^10000}\V\\{qhat}*\\{vmh}>(\\{rhat}\LL\T{16})+\|u[%
\|j+\|n-\T{2}]){}$\5
${}\{{}$\1\6
${}\\{qhat}\MM,\39\\{rhat}\MRL{+{\K}}\\{vh};{}$\6
\&{if} ${}(\\{rhat}\G\T{\^10000}){}$\1\5
\&{break};\2\6
\4${}\}{}$\2\2\par
\U20.\fi
 
\M{22}After this step, \PB{$\|u[\|j+\|n]$} will either equal \PB{\|k} or \PB{$%
\|k-\T{1}$}. The
true value of~\PB{\|u} would be obtained by subtracting~\PB{\|k} from \PB{$\|u[%
\|j+\|n]$};
but we don't have to fuss over \PB{$\|u[\|j+\|n]$}, because it won't be
examined later.
 
\Y\B\4\X22:Subtract $b^j\hat q v$ from \PB{\|u}\X${}\E{}$\6
\&{for} ${}(\|i\K\|k\K\T{0};{}$ ${}\|i<\|n;{}$ ${}\|i\PP){}$\5
${}\{{}$\1\6
${}\|t\K\|u[\|i+\|j]+\T{\^ffff0000}-\|k-\\{qhat}*\|v[\|i];{}$\6
${}\|u[\|i+\|j]\K\|t\AND\T{\^ffff},\39\|k\K\T{\^ffff}-(\|t\GG\T{16});{}$\6
\4${}\}{}$\2\par
\U20.\fi
 
\M{23}The correction here occurs only rarely, but it can be necessary---for
example, when dividing the number \Hex{7fff800100000000} by \Hex{800080020005}.
 
\Y\B\4\X23:If the result was negative, decrease $\hat q$ by 1\X${}\E{}$\6
\&{if} ${}(\|u[\|j+\|n]\I\|k){}$\5
${}\{{}$\1\6
${}\\{qhat}\MM;{}$\6
\&{for} ${}(\|i\K\|k\K\T{0};{}$ ${}\|i<\|n;{}$ ${}\|i\PP){}$\5
${}\{{}$\1\6
${}\|t\K\|u[\|i+\|j]+\|v[\|i]+\|k;{}$\6
${}\|u[\|i+\|j]\K\|t\AND\T{\^ffff},\39\|k\K\|t\GG\T{16};{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\U20.\fi
 
\M{24}Signed division can be reduced to unsigned division in a tedious
but straightforward manner. We assume that the divisor isn't zero.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{octa} \\{signed\_odiv}\,\,${}\.{ARGS}((\&{octa},\39\&{octa})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{signed\_odiv}(\|y,\39\|z){}$\1\1\6
\&{octa} \|y${},{}$ \|z;\2\2\6
${}\{{}$\1\6
\&{octa} \\{yy}${},{}$ \\{zz}${},{}$ \|q;\6
\&{register} \&{int} \\{sy}${},{}$ \\{sz};\7
\&{if} ${}(\|y.\|h\AND\\{sign\_bit}){}$\1\5
${}\\{sy}\K\T{2},\39\\{yy}\K\\{ominus}(\\{zero\_octa},\39\|y);{}$\2\6
\&{else}\1\5
${}\\{sy}\K\T{0},\39\\{yy}\K\|y;{}$\2\6
\&{if} ${}(\|z.\|h\AND\\{sign\_bit}){}$\1\5
${}\\{sz}\K\T{1},\39\\{zz}\K\\{ominus}(\\{zero\_octa},\39\|z);{}$\2\6
\&{else}\1\5
${}\\{sz}\K\T{0},\39\\{zz}\K\|z;{}$\2\6
${}\|q\K\\{odiv}(\\{zero\_octa},\39\\{yy},\39\\{zz});{}$\6
${}\\{overflow}\K\\{false};{}$\6
\&{switch} ${}(\\{sy}+\\{sz}){}$\5
${}\{{}$\1\6
\4\&{case} \T{2}${}+\T{1}{}$:\5
${}\\{aux}\K\\{ominus}(\\{zero\_octa},\39\\{aux});{}$\6
\&{if} ${}(\|q.\|h\E\\{sign\_bit}){}$\1\5
${}\\{overflow}\K\\{true};{}$\2\6
\4\&{case} \T{0}${}+\T{0}{}$:\5
\&{return} \|q;\6
\4\&{case} \T{2}${}+\T{0}{}$:\5
\&{if} ${}(\\{aux}.\|h\V\\{aux}.\|l){}$\1\5
${}\\{aux}\K\\{ominus}(\\{zz},\39\\{aux});{}$\2\6
\&{goto} \\{negate\_q};\6
\4\&{case} \T{0}${}+\T{1}{}$:\5
\&{if} ${}(\\{aux}.\|h\V\\{aux}.\|l){}$\1\5
${}\\{aux}\K\\{ominus}(\\{aux},\39\\{zz});{}$\2\6
\4\\{negate\_q}:\5
\&{if} ${}(\\{aux}.\|h\V\\{aux}.\|l){}$\1\5
\&{return} \\{ominus}${}(\\{neg\_one},\39\|q);{}$\2\6
\&{else}\1\5
\&{return} \\{ominus}${}(\\{zero\_octa},\39\|q);{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\fi
 
\N{1}{25}Bit fiddling. The bitwise operators of \MMIX\ are fairly easy to
implement directly, but three of them occur often enough to deserve
packaging as subroutines.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{octa} \\{oand}\,\,${}\.{ARGS}((\&{octa},\39\&{octa})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{oand}(\|y,\39\|z{}$)\C{ compute $y\land z$ }\1\1\6
\&{octa} \|y${},{}$ \|z;\2\2\6
${}\{{}$\5
\1\&{octa} \|x;\7
${}\|x.\|h\K\|y.\|h\AND\|z.\|h{}$;\5
${}\|x.\|l\K\|y.\|l\AND\|z.\|l;{}$\6
\&{return} \|x;\6
\4${}\}{}$\2\7
\&{octa} \\{oandn}\,\,${}\.{ARGS}((\&{octa},\39\&{octa})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{oandn}(\|y,\39\|z{}$)\C{ compute $y\land\bar z$ }\1\1%
\6
\&{octa} \|y${},{}$ \|z;\2\2\6
${}\{{}$\5
\1\&{octa} \|x;\7
${}\|x.\|h\K\|y.\|h\AND\CM\|z.\|h{}$;\5
${}\|x.\|l\K\|y.\|l\AND\CM\|z.\|l;{}$\6
\&{return} \|x;\6
\4${}\}{}$\2\7
\&{octa} \\{oxor}\,\,${}\.{ARGS}((\&{octa},\39\&{octa})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{oxor}(\|y,\39\|z{}$)\C{ compute $y\oplus z$ }\1\1\6
\&{octa} \|y${},{}$ \|z;\2\2\6
${}\{{}$\5
\1\&{octa} \|x;\7
${}\|x.\|h\K\|y.\|h\XOR\|z.\|h{}$;\5
${}\|x.\|l\K\|y.\|l\XOR\|z.\|l;{}$\6
\&{return} \|x;\6
\4${}\}{}$\2\par
\fi
 
\M{26}Here's a fun way to count the number of bits in a tetrabyte.
[This classical trick is called the ``Gillies--Miller method
for sideways addition'' in {\sl The Preparation of Programs
for an Electronic Digital Computer\/} by Wilkes, Wheeler, and
Gill, second edition (Reading, Mass.:\ Addison--Wesley, 1957),
191--193. Some of the tricks used here were suggested by
Balbir Singh, Peter Rossmanith, and Stefan Schwoon.]
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{int} \\{count\_bits}\,\,\.{ARGS}((\&{tetra}));\5
\hbox{}\6{}\&{int} \\{count\_bits}(\|x)\1\1\6
\&{tetra} \|x;\2\2\6
${}\{{}$\1\6
\&{register} \&{int} \\{xx}${}\K\|x;{}$\7
${}\\{xx}\K\\{xx}-((\\{xx}\GG\T{1})\AND\T{\^55555555});{}$\6
${}\\{xx}\K(\\{xx}\AND\T{\^33333333})+((\\{xx}\GG\T{2})\AND\T{\^33333333});{}$\6
${}\\{xx}\K(\\{xx}+(\\{xx}\GG\T{4}))\AND\T{\^0f0f0f0f};{}$\6
${}\\{xx}\K\\{xx}+(\\{xx}\GG\T{8});{}$\6
\&{return} ${}(\\{xx}+(\\{xx}\GG\T{16}))\AND\T{\^ff};{}$\6
\4${}\}{}$\2\par
\fi
 
\M{27}To compute the nonnegative byte differences of two given tetrabytes,
we can carry out the following 20-step branchless computation:
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{tetra} \\{byte\_diff}\,\,${}\.{ARGS}((\&{tetra},\39\&{tetra})){}$;\5
\hbox{}\6{}\&{tetra} ${}\\{byte\_diff}(\|y,\39\|z){}$\1\1\6
\&{tetra} \|y${},{}$ \|z;\2\2\6
${}\{{}$\1\6
\&{register} \&{tetra} \|d${}\K(\|y\AND\T{\^00ff00ff})+\T{\^01000100}-(\|z\AND%
\T{\^00ff00ff});{}$\6
\&{register} \&{tetra} \|m${}\K\|d\AND\T{\^01000100};{}$\6
\&{register} \&{tetra} \|x${}\K\|d\AND(\|m-(\|m\GG\T{8}));{}$\7
${}\|d\K((\|y\GG\T{8})\AND\T{\^00ff00ff})+\T{\^01000100}-((\|z\GG\T{8})\AND\T{%
\^00ff00ff});{}$\6
${}\|m\K\|d\AND\T{\^01000100};{}$\6
\&{return} \|x${}+((\|d\AND(\|m-(\|m\GG\T{8})))\LL\T{8});{}$\6
\4${}\}{}$\2\par
\fi
 
\M{28}To compute the nonnegative wyde differences of two tetrabytes,
another trick leads to a 15-step branchless computation.
(Research problem: Can \PB{\\{count\_bits}}, \PB{\\{byte\_diff}}, or \PB{%
\\{wyde\_diff}} be done
with fewer operations?)
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{tetra} \\{wyde\_diff}\,\,${}\.{ARGS}((\&{tetra},\39\&{tetra})){}$;\5
\hbox{}\6{}\&{tetra} ${}\\{wyde\_diff}(\|y,\39\|z){}$\1\1\6
\&{tetra} \|y${},{}$ \|z;\2\2\6
${}\{{}$\1\6
\&{register} \&{tetra} \|a${}\K((\|y\GG\T{16})-(\|z\GG\T{16}))\AND\T{%
\^10000};{}$\6
\&{register} \&{tetra} \|b${}\K((\|y\AND\T{\^ffff})-(\|z\AND\T{\^ffff}))\AND\T{%
\^10000};{}$\7
\&{return} \|y${}-(\|z\XOR((\|y\XOR\|z)\AND(\|b-\|a-(\|b\GG\T{16}))));{}$\6
\4${}\}{}$\2\par
\fi
 
\M{29}The last bitwise subroutine we need is the most interesting:
It implements \MMIX's \.{MOR} and \.{MXOR} operations.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{octa} \\{bool\_mult}\,\,${}\.{ARGS}((\&{octa},\39\&{octa},\39\&{bool})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{bool\_mult}(\|y,\39\|z,\39\\{xor}){}$\1\1\6
\&{octa} \|y${},{}$ \|z;\C{ the operands }\6
\&{bool} \\{xor};\C{ do we do xor instead of or? }\2\2\6
${}\{{}$\1\6
\&{octa} \|o${},{}$ \|x;\6
\&{register} \&{tetra} \|a${},{}$ \|b${},{}$ \|c;\6
\&{register} \&{int} \|k;\7
\&{for} ${}(\|k\K\T{0},\39\|o\K\|y,\39\|x\K\\{zero\_octa};{}$ ${}\|o.\|h\V\|o.%
\|l;{}$ ${}\|k\PP,\39\|o\K\\{shift\_right}(\|o,\39\T{8},\39\T{1})){}$\1\6
\&{if} ${}(\|o.\|l\AND\T{\^ff}){}$\5
${}\{{}$\1\6
${}\|a\K((\|z.\|h\GG\|k)\AND\T{\^01010101})*\T{\^ff};{}$\6
${}\|b\K((\|z.\|l\GG\|k)\AND\T{\^01010101})*\T{\^ff};{}$\6
${}\|c\K(\|o.\|l\AND\T{\^ff})*\T{\^01010101};{}$\6
\&{if} (\\{xor})\1\5
${}\|x.\|h\MRL{{\XOR}{\K}}\|a\AND\|c,\39\|x.\|l\MRL{{\XOR}{\K}}\|b\AND\|c;{}$\2%
\6
\&{else}\1\5
${}\|x.\|h\MRL{{\OR}{\K}}\|a\AND\|c,\39\|x.\|l\MRL{{\OR}{\K}}\|b\AND\|c;{}$\2\6
\4${}\}{}$\2\2\6
\&{return} \|x;\6
\4${}\}{}$\2\par
\fi
 
\N{1}{30}Floating point packing and unpacking. Standard IEEE floating binary
numbers pack a sign, exponent, and fraction into a tetrabyte
or octabyte. In this section we consider basic subroutines that
convert between IEEE format and the separate unpacked components.
 
\Y\B\4\D$\.{ROUND\_OFF}$ \5
\T{1}\par
\B\4\D$\.{ROUND\_UP}$ \5
\T{2}\par
\B\4\D$\.{ROUND\_DOWN}$ \5
\T{3}\par
\B\4\D$\.{ROUND\_NEAR}$ \5
\T{4}\par
\Y\B\4\X4:Global variables\X${}\mathrel+\E{}$\6
\&{int} \\{cur\_round};\C{ the current rounding mode }\par
\fi
 
\M{31}The \PB{\\{fpack}} routine takes an octabyte $f$, a raw exponent~$e$,
and a sign~\PB{\|s}, and packs them
into the floating binary number that corresponds to
$\pm2^{e-1076}f$, using a given rounding mode.
The value of $f$ should satisfy $2^{54}\le f\le 2^{55}$.
 
Thus, for example, the floating binary number $+1.0=\Hex{3ff0000000000000}$
is obtained when $f=2^{54}$, $e=\Hex{3fe}$, and \PB{$\|s\K\.{'+'}$}.
The raw exponent~$e$ is usually one less than
the final exponent value; the leading bit of~$f$ is essentially added
to the exponent. (This trick works nicely for subnormal numbers, when
$e<0$, or in cases where the value of $f$ is rounded upwards to $2^{55}$.)
 
Exceptional events are noted by oring appropriate bits into
the global variable \PB{\\{exceptions}}. Special considerations apply to
underflow, which is not fully specified by Section 7.4 of the IEEE standard:
Implementations of the standard are free to choose between two definitions
of ``tininess'' and two definitions of ``accuracy loss.''
\MMIX\ determines tininess {\it after\/} rounding, hence a result with
$e<0$ is not necessarily tiny; \MMIX\ treats accuracy loss as equivalent
to inexactness. Thus, a result underflows if and only if
it is tiny and either (i)~it is inexact or (ii)~the underflow trap is enabled.
The \PB{\\{fpack}} routine sets \PB{\.{U\_BIT}} in \PB{\\{exceptions}} if and
only if the result is
tiny, \PB{\.{X\_BIT}} if and only if the result is inexact.
 
\Y\B\4\D$\.{X\_BIT}$ \5
$(\T{1}\LL\T{8}{}$)\C{ floating inexact }\par
\B\4\D$\.{Z\_BIT}$ \5
$(\T{1}\LL\T{9}{}$)\C{ floating division by zero }\par
\B\4\D$\.{U\_BIT}$ \5
$(\T{1}\LL\T{10}{}$)\C{ floating underflow }\par
\B\4\D$\.{O\_BIT}$ \5
$(\T{1}\LL\T{11}{}$)\C{ floating overflow }\par
\B\4\D$\.{I\_BIT}$ \5
$(\T{1}\LL\T{12}{}$)\C{ floating invalid operation }\par
\B\4\D$\.{W\_BIT}$ \5
$(\T{1}\LL\T{13}{}$)\C{ float-to-fix overflow }\par
\B\4\D$\.{V\_BIT}$ \5
$(\T{1}\LL\T{14}{}$)\C{ integer overflow }\par
\B\4\D$\.{D\_BIT}$ \5
$(\T{1}\LL\T{15}{}$)\C{ integer divide check }\par
\B\4\D$\.{E\_BIT}$ \5
$(\T{1}\LL\T{18}{}$)\C{ external (dynamic) trap bit }\par
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{octa} \\{fpack}\,\,${}\.{ARGS}((\&{octa},\39\&{int},\39\&{char},\39%
\&{int})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{fpack}(\|f,\39\|e,\39\|s,\39\|r){}$\1\1\6
\&{octa} \|f;\C{ the normalized fraction part }\6
\&{int} \|e;\C{ the raw exponent }\6
\&{char} \|s;\C{ the sign }\6
\&{int} \|r;\C{ the rounding mode }\2\2\6
${}\{{}$\1\6
\&{octa} \|o;\7
\&{if} ${}(\|e>\T{\^7fd}){}$\1\5
${}\|e\K\T{\^7ff},\39\|o\K\\{zero\_octa};{}$\2\6
\&{else}\5
${}\{{}$\1\6
\&{if} ${}(\|e<\T{0}){}$\5
${}\{{}$\1\6
\&{if} ${}(\|e<{-}\T{54}){}$\1\5
${}\|o.\|h\K\T{0},\39\|o.\|l\K\T{1};{}$\2\6
\&{else}\5
${}\{{}$\5
\1\&{octa} \\{oo};\7
${}\|o\K\\{shift\_right}(\|f,\39{-}\|e,\39\T{1});{}$\6
${}\\{oo}\K\\{shift\_left}(\|o,\39{-}\|e);{}$\6
\&{if} ${}(\\{oo}.\|l\I\|f.\|l\V\\{oo}.\|h\I\|f.\|h){}$\1\5
${}\|o.\|l\MRL{{\OR}{\K}}\T{1}{}$;\C{ sticky bit }\2\6
\4${}\}{}$\2\6
${}\|e\K\T{0};{}$\6
\4${}\}{}$\5
\2\&{else}\1\5
${}\|o\K\|f;{}$\2\6
\4${}\}{}$\2\6
\X33:Round and return the result\X;\6
\4${}\}{}$\2\par
\fi
 
\M{32}\B\X4:Global variables\X${}\mathrel+\E{}$\6
\&{int} \\{exceptions};\C{ bits possibly destined for rA }\par
\fi
 
\M{33}Everything falls together so nicely here, it's almost too good to be
true!
 
\Y\B\4\X33:Round and return the result\X${}\E{}$\6
\&{if} ${}(\|o.\|l\AND\T{3}){}$\1\5
${}\\{exceptions}\MRL{{\OR}{\K}}\.{X\_BIT};{}$\2\6
\&{switch} (\|r)\5
${}\{{}$\1\6
\4\&{case} \.{ROUND\_DOWN}:\5
\&{if} ${}(\|s\E\.{'-'}){}$\1\5
${}\|o\K\\{incr}(\|o,\39\T{3}){}$;\5
\2\&{break};\6
\4\&{case} \.{ROUND\_UP}:\5
\&{if} ${}(\|s\I\.{'-'}){}$\1\5
${}\|o\K\\{incr}(\|o,\39\T{3});{}$\2\6
\4\&{case} \.{ROUND\_OFF}:\5
\&{break};\6
\4\&{case} \.{ROUND\_NEAR}:\5
${}\|o\K\\{incr}(\|o,\39\|o.\|l\AND\T{4}\?\T{2}:\T{1}){}$;\5
\&{break};\6
\4${}\}{}$\2\6
${}\|o\K\\{shift\_right}(\|o,\39\T{2},\39\T{1});{}$\6
${}\|o.\|h\MRL{+{\K}}\|e\LL\T{20};{}$\6
\&{if} ${}(\|o.\|h\G\T{\^7ff00000}){}$\1\5
${}\\{exceptions}\MRL{{\OR}{\K}}\.{O\_BIT}+\.{X\_BIT}{}$;\C{ overflow }\2\6
\&{else} \&{if} ${}(\|o.\|h<\T{\^100000}){}$\1\5
${}\\{exceptions}\MRL{{\OR}{\K}}\.{U\_BIT}{}$;\C{ tininess }\2\6
\&{if} ${}(\|s\E\.{'-'}){}$\1\5
${}\|o.\|h\MRL{{\OR}{\K}}\\{sign\_bit};{}$\2\6
\&{return} \|o;\par
\U31.\fi
 
\M{34}Similarly, \PB{\\{sfpack}} packs a short float, from inputs
having the same conventions as \PB{\\{fpack}}.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{tetra} \\{sfpack}\,\,${}\.{ARGS}((\&{octa},\39\&{int},\39\&{char},\39%
\&{int})){}$;\5
\hbox{}\6{}\&{tetra} ${}\\{sfpack}(\|f,\39\|e,\39\|s,\39\|r){}$\1\1\6
\&{octa} \|f;\C{ the fraction part }\6
\&{int} \|e;\C{ the raw exponent }\6
\&{char} \|s;\C{ the sign }\6
\&{int} \|r;\C{ the rounding mode }\2\2\6
${}\{{}$\1\6
\&{register} \&{tetra} \|o;\7
\&{if} ${}(\|e>\T{\^47d}){}$\1\5
${}\|e\K\T{\^47f},\39\|o\K\T{0};{}$\2\6
\&{else}\5
${}\{{}$\1\6
${}\|o\K\\{shift\_left}(\|f,\39\T{3}).\|h;{}$\6
\&{if} ${}(\|f.\|l\AND\T{\^1fffffff}){}$\1\5
${}\|o\MRL{{\OR}{\K}}\T{1};{}$\2\6
\&{if} ${}(\|e<\T{\^380}){}$\5
${}\{{}$\1\6
\&{if} ${}(\|e<\T{\^380}-\T{25}){}$\1\5
${}\|o\K\T{1};{}$\2\6
\&{else}\5
${}\{{}$\5
\1\&{register} \&{tetra} \\{o0}${},{}$ \\{oo};\7
${}\\{o0}\K\|o;{}$\6
${}\|o\K\|o\GG(\T{\^380}-\|e);{}$\6
${}\\{oo}\K\|o\LL(\T{\^380}-\|e);{}$\6
\&{if} ${}(\\{oo}\I\\{o0}){}$\1\5
${}\|o\MRL{{\OR}{\K}}\T{1}{}$;\C{ sticky bit }\2\6
\4${}\}{}$\2\6
${}\|e\K\T{\^380};{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\X35:Round and return the short result\X;\6
\4${}\}{}$\2\par
\fi
 
\M{35}\B\X35:Round and return the short result\X${}\E{}$\6
\&{if} ${}(\|o\AND\T{3}){}$\1\5
${}\\{exceptions}\MRL{{\OR}{\K}}\.{X\_BIT};{}$\2\6
\&{switch} (\|r)\5
${}\{{}$\1\6
\4\&{case} \.{ROUND\_DOWN}:\5
\&{if} ${}(\|s\E\.{'-'}){}$\1\5
${}\|o\MRL{+{\K}}\T{3}{}$;\5
\2\&{break};\6
\4\&{case} \.{ROUND\_UP}:\5
\&{if} ${}(\|s\I\.{'-'}){}$\1\5
${}\|o\MRL{+{\K}}\T{3};{}$\2\6
\4\&{case} \.{ROUND\_OFF}:\5
\&{break};\6
\4\&{case} \.{ROUND\_NEAR}:\5
${}\|o\MRL{+{\K}}(\|o\AND\T{4}\?\T{2}:\T{1}){}$;\5
\&{break};\6
\4${}\}{}$\2\6
${}\|o\K\|o\GG\T{2};{}$\6
${}\|o\MRL{+{\K}}(\|e-\T{\^380})\LL\T{23};{}$\6
\&{if} ${}(\|o\G\T{\^7f800000}){}$\1\5
${}\\{exceptions}\MRL{{\OR}{\K}}\.{O\_BIT}+\.{X\_BIT}{}$;\C{ overflow }\2\6
\&{else} \&{if} ${}(\|o<\T{\^100000}){}$\1\5
${}\\{exceptions}\MRL{{\OR}{\K}}\.{U\_BIT}{}$;\C{ tininess }\2\6
\&{if} ${}(\|s\E\.{'-'}){}$\1\5
${}\|o\MRL{{\OR}{\K}}\\{sign\_bit};{}$\2\6
\&{return} \|o;\par
\U34.\fi
 
\M{36}The \PB{\\{funpack}} routine is, roughly speaking, the opposite of \PB{%
\\{fpack}}.
It takes a given floating point number~$x$ and separates out its
fraction part~$f$, exponent~$e$, and sign~$s$. It clears \PB{\\{exceptions}}
to zero. It returns the type of value found: \PB{\\{zro}}, \PB{\\{num}}, \PB{%
\\{inf}},
or \PB{\\{nan}}. When it returns \PB{\\{num}},
it will have set $f$, $e$, and~$s$
to the values from which \PB{\\{fpack}} would produce the original number~$x$
without exceptions.
 
\Y\B\4\D$\\{zero\_exponent}$ \5
$({-}\T{1000}{}$)\C{ zero is assumed to have this exponent }\par
\Y\B\4\X36:Other type definitions\X${}\E{}$\6
\&{typedef} \&{enum} ${}\{{}$\1\6
${}\\{zro},\39\\{num},\39\\{inf},\39\\{nan}{}$\2\6
${}\}{}$\5
\&{ftype};\par
\A59.
\U1.\fi
 
\M{37}\B\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{ftype} \\{funpack}\,\,${}\.{ARGS}((\&{octa},\39{}$\&{octa} ${}{*},\39{}$%
\&{int} ${}{*},\39{}$\&{char} ${}{*})){}$;\5
\hbox{}\6{}\&{ftype} ${}\\{funpack}(\|x,\39\|f,\39\|e,\39\|s){}$\1\1\6
\&{octa} \|x;\C{ the given floating point value }\6
\&{octa} ${}{*}\|f{}$;\C{ address where the fraction part should be stored }\6
\&{int} ${}{*}\|e{}$;\C{ address where the exponent part should be stored }\6
\&{char} ${}{*}\|s{}$;\C{ address where the sign should be stored }\2\2\6
${}\{{}$\1\6
\&{register} \&{int} \\{ee};\7
${}\\{exceptions}\K\T{0};{}$\6
${}{*}\|s\K(\|x.\|h\AND\\{sign\_bit}\?\.{'-'}:\.{'+'});{}$\6
${}{*}\|f\K\\{shift\_left}(\|x,\39\T{2});{}$\6
${}\|f\MG\|h\MRL{\AND{\K}}\T{\^3fffff};{}$\6
${}\\{ee}\K(\|x.\|h\GG\T{20})\AND\T{\^7ff};{}$\6
\&{if} (\\{ee})\5
${}\{{}$\1\6
${}{*}\|e\K\\{ee}-\T{1};{}$\6
${}\|f\MG\|h\MRL{{\OR}{\K}}\T{\^400000};{}$\6
\&{return} ${}(\\{ee}<\T{\^7ff}\?\\{num}:\|f\MG\|h\E\T{\^400000}\W\R\|f\MG\|l\?%
\\{inf}:\\{nan});{}$\6
\4${}\}{}$\2\6
\&{if} ${}(\R\|x.\|l\W\R\|f\MG\|h){}$\5
${}\{{}$\1\6
${}{*}\|e\K\\{zero\_exponent}{}$;\5
\&{return} \\{zro};\6
\4${}\}{}$\2\6
\&{do}\5
${}\{{}$\5
\1${}\\{ee}\MM{}$;\5
${}{*}\|f\K\\{shift\_left}({*}\|f,\39\T{1}){}$;\5
${}\}{}$\2\5
\&{while} ${}(\R(\|f\MG\|h\AND\T{\^400000}));{}$\6
${}{*}\|e\K\\{ee}{}$;\5
\&{return} \\{num};\6
\4${}\}{}$\2\par
\fi
 
\M{38}\B\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{ftype} \\{sfunpack}\,\,${}\.{ARGS}((\&{tetra},\39{}$\&{octa} ${}{*},\39{}$%
\&{int} ${}{*},\39{}$\&{char} ${}{*})){}$;\5
\hbox{}\6{}\&{ftype} ${}\\{sfunpack}(\|x,\39\|f,\39\|e,\39\|s){}$\1\1\6
\&{tetra} \|x;\C{ the given floating point value }\6
\&{octa} ${}{*}\|f{}$;\C{ address where the fraction part should be stored }\6
\&{int} ${}{*}\|e{}$;\C{ address where the exponent part should be stored }\6
\&{char} ${}{*}\|s{}$;\C{ address where the sign should be stored }\2\2\6
${}\{{}$\1\6
\&{register} \&{int} \\{ee};\7
${}\\{exceptions}\K\T{0};{}$\6
${}{*}\|s\K(\|x\AND\\{sign\_bit}\?\.{'-'}:\.{'+'});{}$\6
${}\|f\MG\|h\K(\|x\GG\T{1})\AND\T{\^3fffff},\39\|f\MG\|l\K\|x\LL\T{31};{}$\6
${}\\{ee}\K(\|x\GG\T{23})\AND\T{\^ff};{}$\6
\&{if} (\\{ee})\5
${}\{{}$\1\6
${}{*}\|e\K\\{ee}+\T{\^380}-\T{1};{}$\6
${}\|f\MG\|h\MRL{{\OR}{\K}}\T{\^400000};{}$\6
\&{return} ${}(\\{ee}<\T{\^ff}\?\\{num}:(\|x\AND\T{\^7fffffff})\E\T{\^7f800000}%
\?\\{inf}:\\{nan});{}$\6
\4${}\}{}$\2\6
\&{if} ${}(\R(\|x\AND\T{\^7fffffff})){}$\5
${}\{{}$\1\6
${}{*}\|e\K\\{zero\_exponent}{}$;\5
\&{return} \\{zro};\6
\4${}\}{}$\2\6
\&{do}\5
${}\{{}$\5
\1${}\\{ee}\MM{}$;\5
${}{*}\|f\K\\{shift\_left}({*}\|f,\39\T{1}){}$;\5
${}\}{}$\2\5
\&{while} ${}(\R(\|f\MG\|h\AND\T{\^400000}));{}$\6
${}{*}\|e\K\\{ee}+\T{\^380}{}$;\5
\&{return} \\{num};\6
\4${}\}{}$\2\par
\fi
 
\M{39}Since \MMIX\ downplays 32-bit operations, it uses \PB{\\{sfpack}} and %
\PB{\\{sfunpack}}
only when loading and storing short floats, or when converting
from fixed point to floating point.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{octa} \\{load\_sf}\,\,\.{ARGS}((\&{tetra}));\5
\hbox{}\6{}\&{octa} \\{load\_sf}(\|z)\1\1\6
\&{tetra} \|z;\C{ 32 bits to be loaded into a 64-bit register }\2\2\6
${}\{{}$\1\6
\&{octa} \|f${},{}$ \|x;\5
\&{int} \|e;\5
\&{char} \|s;\5
\&{ftype} \|t;\7
${}\|t\K\\{sfunpack}(\|z,\39{\AND}\|f,\39{\AND}\|e,\39{\AND}\|s);{}$\6
\&{switch} (\|t)\5
${}\{{}$\1\6
\4\&{case} \\{zro}:\5
${}\|x\K\\{zero\_octa}{}$;\5
\&{break};\6
\4\&{case} \\{num}:\5
\&{return} \\{fpack}${}(\|f,\39\|e,\39\|s,\39\.{ROUND\_OFF});{}$\6
\4\&{case} \\{inf}:\5
${}\|x\K\\{inf\_octa}{}$;\5
\&{break};\6
\4\&{case} \\{nan}:\5
${}\|x\K\\{shift\_right}(\|f,\39\T{2},\39\T{1}){}$;\5
${}\|x.\|h\MRL{{\OR}{\K}}\T{\^7ff00000}{}$;\5
\&{break};\6
\4${}\}{}$\2\6
\&{if} ${}(\|s\E\.{'-'}){}$\1\5
${}\|x.\|h\MRL{{\OR}{\K}}\\{sign\_bit};{}$\2\6
\&{return} \|x;\6
\4${}\}{}$\2\par
\fi
 
\M{40}\B\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{tetra} \\{store\_sf}\,\,\.{ARGS}((\&{octa}));\5
\hbox{}\6{}\&{tetra} \\{store\_sf}(\|x)\1\1\6
\&{octa} \|x;\C{ 64 bits to be loaded into a 32-bit word }\2\2\6
${}\{{}$\1\6
\&{octa} \|f;\5
\&{tetra} \|z;\5
\&{int} \|e;\5
\&{char} \|s;\5
\&{ftype} \|t;\7
${}\|t\K\\{funpack}(\|x,\39{\AND}\|f,\39{\AND}\|e,\39{\AND}\|s);{}$\6
\&{switch} (\|t)\5
${}\{{}$\1\6
\4\&{case} \\{zro}:\5
${}\|z\K\T{0}{}$;\5
\&{break};\6
\4\&{case} \\{num}:\5
\&{return} \\{sfpack}${}(\|f,\39\|e,\39\|s,\39\\{cur\_round});{}$\6
\4\&{case} \\{inf}:\5
${}\|z\K\T{\^7f800000}{}$;\5
\&{break};\6
\4\&{case} \\{nan}:\5
\&{if} ${}(\R(\|f.\|h\AND\T{\^200000})){}$\5
${}\{{}$\1\6
${}\|f.\|h\MRL{{\OR}{\K}}\T{\^200000}{}$;\5
${}\\{exceptions}\MRL{{\OR}{\K}}\.{I\_BIT}{}$;\C{ NaN was signaling }\6
\4${}\}{}$\2\6
${}\|z\K\T{\^7f800000}\OR(\|f.\|h\LL\T{1})\OR(\|f.\|l\GG\T{31}){}$;\5
\&{break};\6
\4${}\}{}$\2\6
\&{if} ${}(\|s\E\.{'-'}){}$\1\5
${}\|z\MRL{{\OR}{\K}}\\{sign\_bit};{}$\2\6
\&{return} \|z;\6
\4${}\}{}$\2\par
\fi
 
\N{1}{41}Floating multiplication and division.
The hardest fixed point operations were multiplication and division;
but these two operations are the {\it easiest\/} to implement in floating point
arithmetic, once their fixed point counterparts are available.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{octa} \\{fmult}\,\,${}\.{ARGS}((\&{octa},\39\&{octa})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{fmult}(\|y,\39\|z){}$\1\1\6
\&{octa} \|y${},{}$ \|z;\2\2\6
${}\{{}$\1\6
\&{ftype} \\{yt}${},{}$ \\{zt};\6
\&{int} \\{ye}${},{}$ \\{ze};\6
\&{char} \\{ys}${},{}$ \\{zs};\6
\&{octa} \|x${},{}$ \\{xf}${},{}$ \\{yf}${},{}$ \\{zf};\6
\&{register} \&{int} \\{xe};\6
\&{register} \&{char} \\{xs};\7
${}\\{yt}\K\\{funpack}(\|y,\39{\AND}\\{yf},\39{\AND}\\{ye},\39{\AND}\\{ys});{}$%
\6
${}\\{zt}\K\\{funpack}(\|z,\39{\AND}\\{zf},\39{\AND}\\{ze},\39{\AND}\\{zs});{}$%
\6
${}\\{xs}\K\\{ys}+\\{zs}-\.{'+'}{}$;\C{ will be \PB{\.{'-'}} when the result is
negative }\6
\&{switch} ${}(\T{4}*\\{yt}+\\{zt}){}$\5
${}\{{}$\1\6
\hbox{\4}\X42:The usual NaN cases\X;\6
\4\&{case} \T{4}${}*\\{zro}+\\{zro}{}$:\5
\&{case} \T{4}${}*\\{zro}+\\{num}{}$:\5
\&{case} \T{4}${}*\\{num}+\\{zro}{}$:\5
${}\|x\K\\{zero\_octa}{}$;\5
\&{break};\6
\4\&{case} \T{4}${}*\\{num}+\\{inf}{}$:\5
\&{case} \T{4}${}*\\{inf}+\\{num}{}$:\5
\&{case} \T{4}${}*\\{inf}+\\{inf}{}$:\5
${}\|x\K\\{inf\_octa}{}$;\5
\&{break};\6
\4\&{case} \T{4}${}*\\{zro}+\\{inf}{}$:\5
\&{case} \T{4}${}*\\{inf}+\\{zro}{}$:\5
${}\|x\K\\{standard\_NaN};{}$\6
${}\\{exceptions}\MRL{{\OR}{\K}}\.{I\_BIT}{}$;\5
\&{break};\6
\4\&{case} \T{4}${}*\\{num}+\\{num}{}$:\5
\X43:Multiply nonzero numbers and \PB{\&{return}}\X;\6
\4${}\}{}$\2\6
\&{if} ${}(\\{xs}\E\.{'-'}){}$\1\5
${}\|x.\|h\MRL{{\OR}{\K}}\\{sign\_bit};{}$\2\6
\&{return} \|x;\6
\4${}\}{}$\2\par
\fi
 
\M{42}\B\X42:The usual NaN cases\X${}\E{}$\6
\4\&{case} \T{4}${}*\\{nan}+\\{nan}{}$:\5
\&{if} ${}(\R(\|y.\|h\AND\T{\^80000})){}$\1\5
${}\\{exceptions}\MRL{{\OR}{\K}}\.{I\_BIT}{}$;\C{ \PB{\|y} is signaling }\2\6
\4\&{case} \T{4}${}*\\{zro}+\\{nan}{}$:\5
\&{case} \T{4}${}*\\{num}+\\{nan}{}$:\5
\&{case} \T{4}${}*\\{inf}+\\{nan}{}$:\6
\&{if} ${}(\R(\|z.\|h\AND\T{\^80000})){}$\1\5
${}\\{exceptions}\MRL{{\OR}{\K}}\.{I\_BIT},\39\|z.\|h\MRL{{\OR}{\K}}\T{%
\^80000};{}$\2\6
\&{return} \|z;\6
\4\&{case} \T{4}${}*\\{nan}+\\{zro}{}$:\5
\&{case} \T{4}${}*\\{nan}+\\{num}{}$:\5
\&{case} \T{4}${}*\\{nan}+\\{inf}{}$:\6
\&{if} ${}(\R(\|y.\|h\AND\T{\^80000})){}$\1\5
${}\\{exceptions}\MRL{{\OR}{\K}}\.{I\_BIT},\39\|y.\|h\MRL{{\OR}{\K}}\T{%
\^80000};{}$\2\6
\&{return} \|y;\par
\Us41, 44, 46\ETs93.\fi
 
\M{43}\B\X43:Multiply nonzero numbers and \PB{\&{return}}\X${}\E{}$\6
$\\{xe}\K\\{ye}+\\{ze}-\T{\^3fd}{}$;\C{ the raw exponent }\6
${}\|x\K\\{omult}(\\{yf},\39\\{shift\_left}(\\{zf},\39\T{9}));{}$\6
\&{if} ${}(\\{aux}.\|h\G\T{\^400000}){}$\1\5
${}\\{xf}\K\\{aux};{}$\2\6
\&{else}\1\5
${}\\{xf}\K\\{shift\_left}(\\{aux},\39\T{1}),\39\\{xe}\MM;{}$\2\6
\&{if} ${}(\|x.\|h\V\|x.\|l){}$\1\5
${}\\{xf}.\|l\MRL{{\OR}{\K}}\T{1}{}$;\C{ adjust the sticky bit }\2\6
\&{return} \\{fpack}${}(\\{xf},\39\\{xe},\39\\{xs},\39\\{cur\_round}){}$;\par
\U41.\fi
 
\M{44}\B\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{octa} \\{fdivide}\,\,${}\.{ARGS}((\&{octa},\39\&{octa})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{fdivide}(\|y,\39\|z){}$\1\1\6
\&{octa} \|y${},{}$ \|z;\2\2\6
${}\{{}$\1\6
\&{ftype} \\{yt}${},{}$ \\{zt};\6
\&{int} \\{ye}${},{}$ \\{ze};\6
\&{char} \\{ys}${},{}$ \\{zs};\6
\&{octa} \|x${},{}$ \\{xf}${},{}$ \\{yf}${},{}$ \\{zf};\6
\&{register} \&{int} \\{xe};\6
\&{register} \&{char} \\{xs};\7
${}\\{yt}\K\\{funpack}(\|y,\39{\AND}\\{yf},\39{\AND}\\{ye},\39{\AND}\\{ys});{}$%
\6
${}\\{zt}\K\\{funpack}(\|z,\39{\AND}\\{zf},\39{\AND}\\{ze},\39{\AND}\\{zs});{}$%
\6
${}\\{xs}\K\\{ys}+\\{zs}-\.{'+'}{}$;\C{ will be \PB{\.{'-'}} when the result is
negative }\6
\&{switch} ${}(\T{4}*\\{yt}+\\{zt}){}$\5
${}\{{}$\1\6
\hbox{\4}\X42:The usual NaN cases\X;\6
\4\&{case} \T{4}${}*\\{zro}+\\{inf}{}$:\5
\&{case} \T{4}${}*\\{zro}+\\{num}{}$:\5
\&{case} \T{4}${}*\\{num}+\\{inf}{}$:\5
${}\|x\K\\{zero\_octa}{}$;\5
\&{break};\6
\4\&{case} \T{4}${}*\\{num}+\\{zro}{}$:\5
${}\\{exceptions}\MRL{{\OR}{\K}}\.{Z\_BIT};{}$\6
\4\&{case} \T{4}${}*\\{inf}+\\{num}{}$:\5
\&{case} \T{4}${}*\\{inf}+\\{zro}{}$:\5
${}\|x\K\\{inf\_octa}{}$;\5
\&{break};\6
\4\&{case} \T{4}${}*\\{zro}+\\{zro}{}$:\5
\&{case} \T{4}${}*\\{inf}+\\{inf}{}$:\5
${}\|x\K\\{standard\_NaN};{}$\6
${}\\{exceptions}\MRL{{\OR}{\K}}\.{I\_BIT}{}$;\5
\&{break};\6
\4\&{case} \T{4}${}*\\{num}+\\{num}{}$:\5
\X45:Divide nonzero numbers and \PB{\&{return}}\X;\6
\4${}\}{}$\2\6
\&{if} ${}(\\{xs}\E\.{'-'}){}$\1\5
${}\|x.\|h\MRL{{\OR}{\K}}\\{sign\_bit};{}$\2\6
\&{return} \|x;\6
\4${}\}{}$\2\par
\fi
 
\M{45}\B\X45:Divide nonzero numbers and \PB{\&{return}}\X${}\E{}$\6
$\\{xe}\K\\{ye}-\\{ze}+\T{\^3fd}{}$;\C{ the raw exponent }\6
${}\\{xf}\K\\{odiv}(\\{yf},\39\\{zero\_octa},\39\\{shift\_left}(\\{zf},\39%
\T{9}));{}$\6
\&{if} ${}(\\{xf}.\|h\G\T{\^800000}){}$\5
${}\{{}$\1\6
${}\\{aux}.\|l\MRL{{\OR}{\K}}\\{xf}.\|l\AND\T{1};{}$\6
${}\\{xf}\K\\{shift\_right}(\\{xf},\39\T{1},\39\T{1});{}$\6
${}\\{xe}\PP;{}$\6
\4${}\}{}$\2\6
\&{if} ${}(\\{aux}.\|h\V\\{aux}.\|l){}$\1\5
${}\\{xf}.\|l\MRL{{\OR}{\K}}\T{1}{}$;\C{ adjust the sticky bit }\2\6
\&{return} \\{fpack}${}(\\{xf},\39\\{xe},\39\\{xs},\39\\{cur\_round}){}$;\par
\U44.\fi
 
\N{1}{46}Floating addition and subtraction. Now for the bread-and-butter
operation, the sum of two floating point numbers.
It is not terribly difficult, but many cases need to be handled carefully.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{octa} \\{fplus}\,\,${}\.{ARGS}((\&{octa},\39\&{octa})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{fplus}(\|y,\39\|z){}$\1\1\6
\&{octa} \|y${},{}$ \|z;\2\2\6
${}\{{}$\1\6
\&{ftype} \\{yt}${},{}$ \\{zt};\6
\&{int} \\{ye}${},{}$ \\{ze};\6
\&{char} \\{ys}${},{}$ \\{zs};\6
\&{octa} \|x${},{}$ \\{xf}${},{}$ \\{yf}${},{}$ \\{zf};\6
\&{register} \&{int} \\{xe}${},{}$ \|d;\6
\&{register} \&{char} \\{xs};\7
${}\\{yt}\K\\{funpack}(\|y,\39{\AND}\\{yf},\39{\AND}\\{ye},\39{\AND}\\{ys});{}$%
\6
${}\\{zt}\K\\{funpack}(\|z,\39{\AND}\\{zf},\39{\AND}\\{ze},\39{\AND}\\{zs});{}$%
\6
\&{switch} ${}(\T{4}*\\{yt}+\\{zt}){}$\5
${}\{{}$\1\6
\hbox{\4}\X42:The usual NaN cases\X;\6
\4\&{case} \T{4}${}*\\{zro}+\\{num}{}$:\5
\&{return} \\{fpack}${}(\\{zf},\39\\{ze},\39\\{zs},\39\.{ROUND\_OFF}){}$;\5
\&{break};\C{ may underflow }\6
\4\&{case} \T{4}${}*\\{num}+\\{zro}{}$:\5
\&{return} \\{fpack}${}(\\{yf},\39\\{ye},\39\\{ys},\39\.{ROUND\_OFF}){}$;\5
\&{break};\C{ may underflow }\6
\4\&{case} \T{4}${}*\\{inf}+\\{inf}{}$:\5
\&{if} ${}(\\{ys}\I\\{zs}){}$\5
${}\{{}$\1\6
${}\\{exceptions}\MRL{{\OR}{\K}}\.{I\_BIT}{}$;\5
${}\|x\K\\{standard\_NaN}{}$;\5
${}\\{xs}\K\\{zs}{}$;\5
\&{break};\6
\4${}\}{}$\2\6
\4\&{case} \T{4}${}*\\{num}+\\{inf}{}$:\5
\&{case} \T{4}${}*\\{zro}+\\{inf}{}$:\5
${}\|x\K\\{inf\_octa}{}$;\5
${}\\{xs}\K\\{zs}{}$;\5
\&{break};\6
\4\&{case} \T{4}${}*\\{inf}+\\{num}{}$:\5
\&{case} \T{4}${}*\\{inf}+\\{zro}{}$:\5
${}\|x\K\\{inf\_octa}{}$;\5
${}\\{xs}\K\\{ys}{}$;\5
\&{break};\6
\4\&{case} \T{4}${}*\\{num}+\\{num}{}$:\5
\&{if} ${}(\|y.\|h\I(\|z.\|h\XOR\T{\^80000000})\V\|y.\|l\I\|z.\|l){}$\1\5
\X47:Add nonzero numbers and \PB{\&{return}}\X;\2\6
\4\&{case} \T{4}${}*\\{zro}+\\{zro}{}$:\5
${}\|x\K\\{zero\_octa};{}$\6
${}\\{xs}\K(\\{ys}\E\\{zs}\?\\{ys}:\\{cur\_round}\E\.{ROUND\_DOWN}\?\.{'-'}:%
\.{'+'}){}$;\5
\&{break};\6
\4${}\}{}$\2\6
\&{if} ${}(\\{xs}\E\.{'-'}){}$\1\5
${}\|x.\|h\MRL{{\OR}{\K}}\\{sign\_bit};{}$\2\6
\&{return} \|x;\6
\4${}\}{}$\2\par
\fi
 
\M{47}\B\X47:Add nonzero numbers and \PB{\&{return}}\X${}\E{}$\6
${}\{{}$\5
\1\&{octa} \|o${},{}$ \\{oo};\7
\&{if} ${}(\\{ye}<\\{ze}\V(\\{ye}\E\\{ze}\W(\\{yf}.\|h<\\{zf}.\|h\V(\\{yf}.\|h%
\E\\{zf}.\|h\W\\{yf}.\|l<\\{zf}.\|l)))){}$\1\5
\X48:Exchange \PB{\|y} with \PB{\|z}\X;\2\6
${}\|d\K\\{ye}-\\{ze};{}$\6
${}\\{xs}\K\\{ys},\39\\{xe}\K\\{ye};{}$\6
\&{if} (\|d)\1\5
\X49:Adjust for difference in exponents\X;\2\6
\&{if} ${}(\\{ys}\E\\{zs}){}$\5
${}\{{}$\1\6
${}\\{xf}\K\\{oplus}(\\{yf},\39\\{zf});{}$\6
\&{if} ${}(\\{xf}.\|h\G\T{\^800000}){}$\1\5
${}\\{xe}\PP,\39\|d\K\\{xf}.\|l\AND\T{1},\39\\{xf}\K\\{shift\_right}(\\{xf},\39%
\T{1},\39\T{1}),\39\\{xf}.\|l\MRL{{\OR}{\K}}\|d;{}$\2\6
\4${}\}{}$\5
\2\&{else}\5
${}\{{}$\1\6
${}\\{xf}\K\\{ominus}(\\{yf},\39\\{zf});{}$\6
\&{if} ${}(\\{xf}.\|h\G\T{\^800000}){}$\1\5
${}\\{xe}\PP,\39\|d\K\\{xf}.\|l\AND\T{1},\39\\{xf}\K\\{shift\_right}(\\{xf},\39%
\T{1},\39\T{1}),\39\\{xf}.\|l\MRL{{\OR}{\K}}\|d;{}$\2\6
\&{else}\5
\1\&{while} ${}(\\{xf}.\|h<\T{\^400000}){}$\1\5
${}\\{xe}\MM,\39\\{xf}\K\\{shift\_left}(\\{xf},\39\T{1});{}$\2\2\6
\4${}\}{}$\2\6
\&{return} \\{fpack}${}(\\{xf},\39\\{xe},\39\\{xs},\39\\{cur\_round});{}$\6
\4${}\}{}$\2\par
\U46.\fi
 
\M{48}\B\X48:Exchange \PB{\|y} with \PB{\|z}\X${}\E{}$\6
${}\{{}$\1\6
${}\|o\K\\{yf},\39\\{yf}\K\\{zf},\39\\{zf}\K\|o;{}$\6
${}\|d\K\\{ye},\39\\{ye}\K\\{ze},\39\\{ze}\K\|d;{}$\6
${}\|d\K\\{ys},\39\\{ys}\K\\{zs},\39\\{zs}\K\|d;{}$\6
\4${}\}{}$\2\par
\Us47\ET51.\fi
 
\M{49}Proper rounding requires two bits to the right of the fraction delivered
to~\PB{\\{fpack}}. The first is the true next bit of the result;
the other is a ``sticky'' bit, which is nonzero if any further bits of the
true result are nonzero. Sticky rounding to an integer takes
$x$ into the number $\lfloor x/2\rfloor+\lceil x/2\rceil$.
 
Some subtleties need to be observed here, in order to
prevent the sticky bit from being shifted left. If we did not
shift \PB{\\{yf}} left~1 before shifting \PB{\\{zf}} to the right, an incorrect
answer would be obtained in certain cases---for example, if
$\PB{\\{yf}}=2^{54}$, $\PB{\\{zf}}=2^{54}+2^{53}-1$, $d=52$.
 
\Y\B\4\X49:Adjust for difference in exponents\X${}\E{}$\6
${}\{{}$\1\6
\&{if} ${}(\|d\Z\T{2}){}$\1\5
${}\\{zf}\K\\{shift\_right}(\\{zf},\39\|d,\39\T{1}){}$;\C{ exact result }\2\6
\&{else} \&{if} ${}(\|d>\T{53}){}$\1\5
${}\\{zf}.\|h\K\T{0},\39\\{zf}.\|l\K\T{1}{}$;\C{ tricky but OK }\2\6
\&{else}\5
${}\{{}$\1\6
\&{if} ${}(\\{ys}\I\\{zs}){}$\1\5
${}\|d\MM,\39\\{xe}\MM,\39\\{yf}\K\\{shift\_left}(\\{yf},\39\T{1});{}$\2\6
${}\|o\K\\{zf};{}$\6
${}\\{zf}\K\\{shift\_right}(\|o,\39\|d,\39\T{1});{}$\6
${}\\{oo}\K\\{shift\_left}(\\{zf},\39\|d);{}$\6
\&{if} ${}(\\{oo}.\|l\I\|o.\|l\V\\{oo}.\|h\I\|o.\|h){}$\1\5
${}\\{zf}.\|l\MRL{{\OR}{\K}}\T{1};{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\U47.\fi
 
\M{50}The comparison of floating point numbers with respect to $\epsilon$
shares some of the characteristics of floating point addition/subtraction.
In some ways it is simpler, and in other ways it is more difficult;
we might as well deal with it now. % anyways
 
Subroutine \PB{$\\{fepscomp}(\|y,\|z,\|e,\|s)$} returns 2 if \PB{\|y}, \PB{%
\|z}, or \PB{\|e} is a NaN
or \PB{\|e} is negative. It returns 1 if \PB{$\|s\K\T{0}$} and $y\approx z\
(e)$ or if
\PB{$\|s\I\T{0}$} and $y\sim z\ (e)$,
as defined in Section~4.2.2 of {\sl Seminumerical Algorithms\/};
otherwise it returns~0.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{int} \\{fepscomp}\,\,${}\.{ARGS}((\&{octa},\39\&{octa},\39\&{octa},\39%
\&{int})){}$;\5
\hbox{}\6{}\&{int} ${}\\{fepscomp}(\|y,\39\|z,\39\|e,\39\|s){}$\1\1\6
\&{octa} \|y${},{}$ \|z${},{}$ \|e;\C{ the operands }\6
\&{int} \|s;\C{ test similarity? }\2\2\6
${}\{{}$\1\6
\&{octa} \\{yf}${},{}$ \\{zf}${},{}$ \\{ef}${},{}$ \|o${},{}$ \\{oo};\6
\&{int} \\{ye}${},{}$ \\{ze}${},{}$ \\{ee};\6
\&{char} \\{ys}${},{}$ \\{zs}${},{}$ \\{es};\6
\&{register} \&{int} \\{yt}${},{}$ \\{zt}${},{}$ \\{et}${},{}$ \|d;\7
${}\\{et}\K\\{funpack}(\|e,\39{\AND}\\{ef},\39{\AND}\\{ee},\39{\AND}\\{es});{}$%
\6
\&{if} ${}(\\{es}\E\.{'-'}){}$\1\5
\&{return} \T{2};\2\6
\&{switch} (\\{et})\5
${}\{{}$\1\6
\4\&{case} \\{nan}:\5
\&{return} \T{2};\6
\4\&{case} \\{inf}:\5
${}\\{ee}\K\T{10000};{}$\6
\4\&{case} \\{num}:\5
\&{case} \\{zro}:\5
\&{break};\6
\4${}\}{}$\2\6
${}\\{yt}\K\\{funpack}(\|y,\39{\AND}\\{yf},\39{\AND}\\{ye},\39{\AND}\\{ys});{}$%
\6
${}\\{zt}\K\\{funpack}(\|z,\39{\AND}\\{zf},\39{\AND}\\{ze},\39{\AND}\\{zs});{}$%
\6
\&{switch} ${}(\T{4}*\\{yt}+\\{zt}){}$\5
${}\{{}$\1\6
\4\&{case} \T{4}${}*\\{nan}+\\{nan}{}$:\5
\&{case} \T{4}${}*\\{nan}+\\{inf}{}$:\5
\&{case} \T{4}${}*\\{nan}+\\{num}{}$:\5
\&{case} \T{4}${}*\\{nan}+\\{zro}{}$:\5
\&{case} \T{4}${}*\\{inf}+\\{nan}{}$:\5
\&{case} \T{4}${}*\\{num}+\\{nan}{}$:\5
\&{case} \T{4}${}*\\{zro}+\\{nan}{}$:\5
\&{return} \T{2};\6
\4\&{case} \T{4}${}*\\{inf}+\\{inf}{}$:\5
\&{return} ${}(\\{ys}\E\\{zs}\V\\{ee}\G\T{1023});{}$\6
\4\&{case} \T{4}${}*\\{inf}+\\{num}{}$:\5
\&{case} \T{4}${}*\\{inf}+\\{zro}{}$:\5
\&{case} \T{4}${}*\\{num}+\\{inf}{}$:\5
\&{case} \T{4}${}*\\{zro}+\\{inf}{}$:\5
\&{return} ${}(\|s\W\\{ee}\G\T{1022});{}$\6
\4\&{case} \T{4}${}*\\{zro}+\\{zro}{}$:\5
\&{return} \T{1};\6
\4\&{case} \T{4}${}*\\{zro}+\\{num}{}$:\5
\&{case} \T{4}${}*\\{num}+\\{zro}{}$:\5
\&{if} ${}(\R\|s){}$\1\5
\&{return} \T{0};\2\6
\4\&{case} \T{4}${}*\\{num}+\\{num}{}$:\5
\&{break};\6
\4${}\}{}$\2\6
\X51:Compare two numbers with respect to epsilon and \PB{\&{return}}\X;\6
\4${}\}{}$\2\par
\fi
 
\M{51}The relation $y\approx z\ (\epsilon)$ reduces to
$y\sim z\ (\epsilon/2^d)$, if $d$~is the difference between the
larger and smaller exponents of $y$ and~$z$.
 
\Y\B\4\X51:Compare two numbers with respect to epsilon and \PB{\&{return}}\X${}%
\E{}$\6
\X52:Unsubnormalize \PB{\|y} and \PB{\|z}, if they are subnormal\X;\6
\&{if} ${}(\\{ye}<\\{ze}\V(\\{ye}\E\\{ze}\W(\\{yf}.\|h<\\{zf}.\|h\V(\\{yf}.\|h%
\E\\{zf}.\|h\W\\{yf}.\|l<\\{zf}.\|l)))){}$\1\5
\X48:Exchange \PB{\|y} with \PB{\|z}\X;\2\6
\&{if} ${}(\\{ze}\E\\{zero\_exponent}){}$\1\5
${}\\{ze}\K\\{ye};{}$\2\6
${}\|d\K\\{ye}-\\{ze};{}$\6
\&{if} ${}(\R\|s){}$\1\5
${}\\{ee}\MRL{-{\K}}\|d;{}$\2\6
\&{if} ${}(\\{ee}\G\T{1023}){}$\1\5
\&{return} \T{1};\C{ if $\epsilon\ge2$, $z\in N_\epsilon(y)$ }\2\6
\X53:Compute the difference of fraction parts, \PB{\|o}\X;\6
\&{if} ${}(\R\|o.\|h\W\R\|o.\|l){}$\1\5
\&{return} \T{1};\2\6
\&{if} ${}(\\{ee}<\T{968}){}$\1\5
\&{return} \T{0};\C{ if $y\ne z$ and $\epsilon<2^{-54}$, $y\not\sim z$ }\2\6
\&{if} ${}(\\{ee}\G\T{1021}){}$\1\5
${}\\{ef}\K\\{shift\_left}(\\{ef},\39\\{ee}-\T{1021});{}$\2\6
\&{else}\1\5
${}\\{ef}\K\\{shift\_right}(\\{ef},\39\T{1021}-\\{ee},\39\T{1});{}$\2\6
\&{return} \|o${}.\|h<\\{ef}.\|h\V(\|o.\|h\E\\{ef}.\|h\W\|o.\|l\Z\\{ef}.%
\|l){}$;\par
\U50.\fi
 
\M{52}\B\X52:Unsubnormalize \PB{\|y} and \PB{\|z}, if they are subnormal\X${}%
\E{}$\6
\&{if} ${}(\\{ye}<\T{0}\W\\{yt}\I\\{zro}){}$\1\5
${}\\{yf}\K\\{shift\_left}(\|y,\39\T{2}),\39\\{ye}\K\T{0};{}$\2\6
\&{if} ${}(\\{ze}<\T{0}\W\\{zt}\I\\{zro}){}$\1\5
${}\\{zf}\K\\{shift\_left}(\|z,\39\T{2}),\39\\{ze}\K\T{0}{}$;\2\par
\U51.\fi
 
\M{53}At this point $y\sim z$ if and only if
$$\PB{\\{yf}}+(-1)^{[ys=zs]}\PB{\\{zf}}/2^d\le 2^{ee-1021}\PB{\\{ef}}=2^{55}%
\epsilon.$$
We need to evaluate this relation without overstepping the bounds of
our simulated 64-bit registers.
 
When $d>2$, the difference of fraction parts might not fit exactly
in an octabyte;
in that case the numbers are not similar unless $\epsilon>3/8$,
and we replace the difference by the ceiling of the
true result. When $\epsilon<1/8$, our program essentially replaces
$2^{55}\epsilon$ by $\lfloor2^{55}\epsilon\rfloor$. These
truncations are not needed simultaneously. Therefore the logic
is justified by the facts that, if $n$ is an integer, we have
$x\le n$ if and only if $\lceil x\rceil\le n$;
$n\le x$ if and only if $n\le\lfloor x\rfloor$. (Notice that the
concept of ``sticky bit'' is {\it not\/} appropriate here.)
 
\Y\B\4\X53:Compute the difference of fraction parts, \PB{\|o}\X${}\E{}$\6
\&{if} ${}(\|d>\T{54}){}$\1\5
${}\|o\K\\{zero\_octa},\39\\{oo}\K\\{zf};{}$\2\6
\&{else}\1\5
${}\|o\K\\{shift\_right}(\\{zf},\39\|d,\39\T{1}),\39\\{oo}\K\\{shift\_left}(%
\|o,\39\|d);{}$\2\6
\&{if} ${}(\\{oo}.\|h\I\\{zf}.\|h\V\\{oo}.\|l\I\\{zf}.\|l){}$\5
${}\{{}$\C{ truncated result, hence $d>2$ }\1\6
\&{if} ${}(\\{ee}<\T{1020}){}$\1\5
\&{return} \T{0};\C{ difference is too large for similarity }\2\6
${}\|o\K\\{incr}(\|o,\39\\{ys}\E\\{zs}\?\T{0}:\T{1}){}$;\C{ adjust for ceiling
}\6
\4${}\}{}$\2\6
${}\|o\K(\\{ys}\E\\{zs}\?\\{ominus}(\\{yf},\39\|o):\\{oplus}(\\{yf},\39%
\|o)){}$;\par
\U51.\fi
 
\N{1}{54}Floating point output conversion.
The \PB{\\{print\_float}} routine converts an octabyte to a floating decimal
representation that will be input as precisely the same value.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{static} \&{void} \\{bignum\_times\_ten}\,\,${}\.{ARGS}((\\{bignum}*));{}$\6
\&{static} \&{void} \\{bignum\_dec}\,\,${}\.{ARGS}((\\{bignum}*,\\{bignum}*,%
\&{tetra}));{}$\6
\&{static} \&{int} \\{bignum\_compare}\,\,${}\.{ARGS}((\\{bignum}*,%
\\{bignum}*));{}$\6
\&{void} \\{print\_float}\,\,\.{ARGS}((\&{octa}));\5
\hbox{}\6{}\&{void} \\{print\_float}(\|x)\1\1\6
\&{octa} \|x;\2\2\6
${}\{{}$\1\6
\X56:Local variables for \PB{\\{print\_float}}\X;\6
\&{if} ${}(\|x.\|h\AND\\{sign\_bit}){}$\1\5
\\{printf}(\.{"-"});\2\6
\X55:Extract the exponent \PB{\|e} and determine the fraction interval $[f\dts
g]$ or $(f\dts g)$\X;\6
\X63:Store $f$ and $g$ as multiprecise integers\X;\6
\X64:Compute the significant digits \PB{\|s} and decimal exponent \PB{\|e}\X;\6
\X67:Print the significant digits with proper context\X;\6
\4${}\}{}$\2\par
\fi
 
\M{55}One way to visualize the problem being solved here is to consider
the vastly simpler case in which there are only 2-bit exponents
and 2-bit fractions. Then the sixteen possible 4-bit combinations
have the following interpretations:
$$\def\\{\;\dts\;}
\vbox{\halign{#\qquad&$#$\hfil\cr
0000&[0\\0.125]\cr
0001&(0.125\\0.375)\cr
0010&[0.375\\0.625]\cr
0011&(0.625\\0.875)\cr
0100&[0.875\\1.125]\cr
0101&(1.125\\1.375)\cr
0110&[1.375\\1.625]\cr
0111&(1.625\\1.875)\cr
1000&[1.875\\2.25]\cr
1001&(2.25\\2.75)\cr
1010&[2.75\\3.25]\cr
1011&(3.25\\3.75)\cr
1100&[3.75\\\infty]\cr
1101&\rm NaN(0\\0.375)\cr
1110&\rm NaN[0.375\\0.625]\cr
1111&\rm NaN(0.625\\1)\cr}}$$
Notice that the interval is closed, $[f\dts g]$, when the fraction part
is even; it is open, $(f\dts g)$, when the fraction part is odd.
The printed outputs for these sixteen values, if we actually were
dealing with such short exponents and fractions, would be
\.{0.}, \.{.2}, \.{.5}, \.{.7}, \.{1.}, \.{1.2}, \.{1.5}, \.{1.7},
\.{2.}, \.{2.5}, \.{3.}, \.{3.5}, \.{Inf}, \.{NaN.2}, \.{NaN}, \.{NaN.8},
respectively.
 
\Y\B\4\X55:Extract the exponent \PB{\|e} and determine the fraction interval
$[f\dts g]$ or $(f\dts g)$\X${}\E{}$\6
$\|f\K\\{shift\_left}(\|x,\39\T{1});{}$\6
${}\|e\K\|f.\|h\GG\T{21};{}$\6
${}\|f.\|h\MRL{\AND{\K}}\T{\^1fffff};{}$\6
\&{if} ${}(\R\|f.\|h\W\R\|f.\|l){}$\1\5
\X57:Handle the special case when the fraction part is zero\X\2\6
\&{else}\5
${}\{{}$\1\6
${}\|g\K\\{incr}(\|f,\39\T{1});{}$\6
${}\|f\K\\{incr}(\|f,\39{-}\T{1});{}$\6
\&{if} ${}(\R\|e){}$\1\5
${}\|e\K\T{1}{}$;\C{ subnormal }\2\6
\&{else} \&{if} ${}(\|e\E\T{\^7ff}){}$\5
${}\{{}$\1\6
\\{printf}(\.{"NaN"});\6
\&{if} ${}(\|g.\|h\E\T{\^100000}\W\|g.\|l\E\T{1}){}$\1\5
\&{return};\C{ the ``standard'' NaN }\2\6
${}\|e\K\T{\^3ff}{}$;\C{ extreme NaNs come out OK even without adjusting \PB{%
\|f} or \PB{\|g} }\6
\4${}\}{}$\5
\2\&{else}\1\5
${}\|f.\|h\MRL{{\OR}{\K}}\T{\^200000},\39\|g.\|h\MRL{{\OR}{\K}}\T{\^200000};{}$%
\2\6
\4${}\}{}$\2\par
\U54.\fi
 
\M{56}\B\X56:Local variables for \PB{\\{print\_float}}\X${}\E{}$\6
\&{octa} \|f${},{}$ \|g;\C{ lower and upper bounds on the fraction part }\6
\&{register} \&{int} \|e;\C{ exponent part }\6
\&{register} \&{int} \|j${},{}$ \|k;\C{ all purpose indices }\par
\A66.
\U54.\fi
 
\M{57}The transition points between exponents correspond to powers of~2. At
such points the interval extends only half as far to the left of that
power of~2 as it does to the right. For example, in the 4-bit minifloat numbers
considered above, case 1000 corresponds to the interval $[1.875\;\dts\;2.25]$.
 
\Y\B\4\X57:Handle the special case when the fraction part is zero\X${}\E{}$\6
${}\{{}$\1\6
\&{if} ${}(\R\|e){}$\5
${}\{{}$\1\6
\\{printf}(\.{"0."});\5
\&{return};\6
\4${}\}{}$\2\6
\&{if} ${}(\|e\E\T{\^7ff}){}$\5
${}\{{}$\1\6
\\{printf}(\.{"Inf"});\5
\&{return};\6
\4${}\}{}$\2\6
${}\|e\MM;{}$\6
${}\|f.\|h\K\T{\^3fffff},\39\|f.\|l\K\T{\^ffffffff};{}$\6
${}\|g.\|h\K\T{\^400000},\39\|g.\|l\K\T{2};{}$\6
\4${}\}{}$\2\par
\U55.\fi
 
\M{58}We want to find the ``simplest'' value in the interval corresponding
to the given number, in the sense that it has fewest significant
digits when expressed in decimal notation. Thus, for example,
if the floating point number can be described by a relatively
short string such as `\.{.1}' or `\.{37e100}', we want to discover that
representation.
 
The basic idea is to generate the decimal representations of the
two endpoints of the interval, outputting the leading digits where
both endpoints agree, then making a final decision at the first place where
they disagree.
 
The ``simplest'' value is not always unique. For example, in the
case of 4-bit minifloat numbers we could represent the bit pattern 0001 as
either \.{.2} or \.{.3}, and we could represent 1001 in five equally short
ways: \.{2.3} or \.{2.4} or \.{2.5} or \.{2.6} or \.{2.7}. The
algorithm below tries to choose the middle possibility in such cases.
 
[A solution to the analogous problem for fixed-point representations,
without the additional complication of round-to-even, was used by
the author in the program for \TeX; see {\sl Beauty is Our Business\/}
(Springer, 1990), 233--242.]
 
Suppose we are given two fractions $f$ and $g$, where $0\le f<g<1$, and
we want to compute the shortest decimal in the closed interval $[f\dts g]$.
If $f=0$, we are done. Otherwise let $10f=d+f'$ and $10g=e+g'$, where
$0\le f'<1$ and $0\le g'<1$. If $d<e$, we can terminate by outputting
any of the digits $d+1$, \dots,~$e$; otherwise we output the
common digit $d=e$, and repeat the process on the fractions $0\le f'<g'<1$.
A similar procedure works with respect to the open interval $(f\dts g)$.
 
\fi
 
\M{59}The program below carries out the stated algorithm by using
multiprecision
arithmetic on 77-place integers with 28 bits each. This choice
facilitates multiplication by~10, and allows us to deal with the whole range of
floating binary numbers using fixed point arithmetic. We keep track of
the leading and trailing digit positions so that trivial operations on
zeros are avoided.
 
If \PB{\|f} points to a \&{bignum}, its radix-$2^{28}$ digits are
\PB{$\|f\MG\\{dat}[\T{0}]$} through \PB{$\|f\MG\\{dat}[\T{76}]$}, from most
significant to least significant.
We assume that all digit positions are zero unless they lie in the
subarray between indices \PB{$\|f\MG\|a$} and \PB{$\|f\MG\|b$}, inclusive.
Furthermore, both \PB{$\|f\MG\\{dat}[\|f\MG\|a]$} and \PB{$\|f\MG\\{dat}[\|f\MG%
\|b]$} are nonzero,
unless \PB{$\|f\MG\|a\K\|f\MG\|b\K\\{bignum\_prec}-\T{1}$}.
 
The \&{bignum} data type can be used with any radix less than
$2^{32}$; we will use it later with radix~$10^9$. The \PB{\\{dat}} array
is made large enough to accommodate both applications.
 
\Y\B\4\D$\\{bignum\_prec}$ \5
\T{157}\C{ would be 77 if we cared only about \PB{\\{print\_float}} }\par
\Y\B\4\X36:Other type definitions\X${}\mathrel+\E{}$\6
\&{typedef} \&{struct} ${}\{{}$\1\6
\&{int} \|a;\C{ index of the most significant digit }\6
\&{int} \|b;\C{ index of the least significant digit; must be $\ge a$ }\6
\&{tetra} \\{dat}[\\{bignum\_prec}];\C{ the digits; undefined except between %
\PB{\|a} and \PB{\|b} }\2\6
${}\}{}$ \&{bignum};\par
\fi
 
\M{60}Here, for example, is how we go from $f$ to $10f$, assuming that
overflow will not occur and that the radix is $2^{28}$:
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{static} \&{void} \\{bignum\_times\_ten}(\|f)\1\1\6
\&{bignum} ${}{*}\|f;\2\2{}$\6
${}\{{}$\1\6
\&{register} \&{tetra} ${}{*}\|p,{}$ ${}{*}\|q;{}$\6
\&{register} \&{tetra} \|x${},{}$ \\{carry};\7
\&{for} ${}(\|p\K{\AND}\|f\MG\\{dat}[\|f\MG\|b],\39\|q\K{\AND}\|f\MG\\{dat}[\|f%
\MG\|a],\39\\{carry}\K\T{0};{}$ ${}\|p\G\|q;{}$ ${}\|p\MM){}$\5
${}\{{}$\1\6
${}\|x\K{*}\|p*\T{10}+\\{carry};{}$\6
${}{*}\|p\K\|x\AND\T{\^fffffff};{}$\6
${}\\{carry}\K\|x\GG\T{28};{}$\6
\4${}\}{}$\2\6
${}{*}\|p\K\\{carry};{}$\6
\&{if} (\\{carry})\1\5
${}\|f\MG\|a\MM;{}$\2\6
\&{if} ${}(\|f\MG\\{dat}[\|f\MG\|b]\E\T{0}\W\|f\MG\|b>\|f\MG\|a){}$\1\5
${}\|f\MG\|b\MM;{}$\2\6
\4${}\}{}$\2\par
\fi
 
\M{61}And here is how we test whether $f<g$, $f=g$, or $f>g$, using any
radix whatever:
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{static} \&{int} ${}\\{bignum\_compare}(\|f,\39\|g){}$\1\1\6
\&{bignum} ${}{*}\|f,{}$ ${}{*}\|g;\2\2{}$\6
${}\{{}$\1\6
\&{register} \&{tetra} ${}{*}\|p,{}$ ${}{*}\\{pp},{}$ ${}{*}\|q,{}$ ${}{*}%
\\{qq};{}$\7
\&{if} ${}(\|f\MG\|a\I\|g\MG\|a){}$\1\5
\&{return} \|f${}\MG\|a>\|g\MG\|a\?{-}\T{1}:\T{1};{}$\2\6
${}\\{pp}\K{\AND}\|f\MG\\{dat}[\|f\MG\|b],\39\\{qq}\K{\AND}\|g\MG\\{dat}[\|g\MG%
\|b];{}$\6
\&{for} ${}(\|p\K{\AND}\|f\MG\\{dat}[\|f\MG\|a],\39\|q\K{\AND}\|g\MG\\{dat}[\|g%
\MG\|a];{}$ ${}\|p\Z\\{pp};{}$ ${}\|p\PP,\39\|q\PP){}$\5
${}\{{}$\1\6
\&{if} ${}({*}\|p\I{*}\|q){}$\1\5
\&{return} ${}{*}\|p<{*}\|q\?{-}\T{1}:\T{1};{}$\2\6
\&{if} ${}(\|q\E\\{qq}){}$\1\5
\&{return} \|p${}<\\{pp};{}$\2\6
\4${}\}{}$\2\6
\&{return} ${}{-}\T{1};{}$\6
\4${}\}{}$\2\par
\fi
 
\M{62}The following subroutine subtracts $g$ from~$f$, assuming that
$f\ge g>0$ and using a given radix.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{static} \&{void} ${}\\{bignum\_dec}(\|f,\39\|g,\39\|r){}$\1\1\6
\&{bignum} ${}{*}\|f,{}$ ${}{*}\|g;{}$\6
\&{tetra} \|r;\C{ the radix }\2\2\6
${}\{{}$\1\6
\&{register} \&{tetra} ${}{*}\|p,{}$ ${}{*}\|q,{}$ ${}{*}\\{qq};{}$\6
\&{register} \&{int} \|x${},{}$ \\{borrow};\7
\&{while} ${}(\|g\MG\|b>\|f\MG\|b){}$\1\5
${}\|f\MG\\{dat}[\PP\|f\MG\|b]\K\T{0};{}$\2\6
${}\\{qq}\K{\AND}\|g\MG\\{dat}[\|g\MG\|a];{}$\6
\&{for} ${}(\|p\K{\AND}\|f\MG\\{dat}[\|g\MG\|b],\39\|q\K{\AND}\|g\MG\\{dat}[\|g%
\MG\|b],\39\\{borrow}\K\T{0};{}$ ${}\|q\G\\{qq};{}$ ${}\|p\MM,\39\|q\MM){}$\5
${}\{{}$\1\6
${}\|x\K{*}\|p-{*}\|q-\\{borrow};{}$\6
\&{if} ${}(\|x\G\T{0}){}$\1\5
${}\\{borrow}\K\T{0},\39{*}\|p\K\|x;{}$\2\6
\&{else}\1\5
${}\\{borrow}\K\T{1},\39{*}\|p\K\|x+\|r;{}$\2\6
\4${}\}{}$\2\6
\&{for} ( ; \\{borrow}; ${}\|p\MM){}$\1\6
\&{if} ${}({*}\|p){}$\1\5
${}\\{borrow}\K\T{0},\39{*}\|p\K{*}\|p-\T{1};{}$\2\6
\&{else}\1\5
${}{*}\|p\K\|r-\T{1};{}$\2\2\6
\&{while} ${}(\|f\MG\\{dat}[\|f\MG\|a]\E\T{0}){}$\5
${}\{{}$\1\6
\&{if} ${}(\|f\MG\|a\E\|f\MG\|b){}$\5
${}\{{}$\C{ the result is zero }\1\6
${}\|f\MG\|a\K\|f\MG\|b\K\\{bignum\_prec}-\T{1},\39\|f\MG\\{dat}[\\{bignum%
\_prec}-\T{1}]\K\T{0};{}$\6
\&{return};\6
\4${}\}{}$\2\6
${}\|f\MG\|a\PP;{}$\6
\4${}\}{}$\2\6
\&{while} ${}(\|f\MG\\{dat}[\|f\MG\|b]\E\T{0}){}$\1\5
${}\|f\MG\|b\MM;{}$\2\6
\4${}\}{}$\2\par
\fi
 
\M{63}Armed with these subroutines, we are ready to solve the problem.
The first task is to put the numbers into \&{bignum} form.
If the exponent is \PB{\|e}, the number destined for digit \PB{\\{dat}[\|k]}
will
consist of the rightmost 28 bits of the given fraction after it has
been shifted right $c-e-28k$ bits, for some constant~$c$.
We choose $c$ so that,
when $e$ has its maximum value \Hex{7ff}, the leading digit will
go into position \PB{\\{dat}[\T{1}]}, and so that when the number to be printed
is exactly~1 the integer part of~$g$ will also be exactly~1.
 
\Y\B\4\D$\\{magic\_offset}$ \5
\T{2112}\C{ the constant $c$ that makes it work }\par
\B\4\D$\\{origin}$ \5
\T{37}\C{ the radix point follows \PB{\\{dat}[\T{37}]} }\par
\Y\B\4\X63:Store $f$ and $g$ as multiprecise integers\X${}\E{}$\6
$\|k\K(\\{magic\_offset}-\|e)/\T{28};{}$\6
${}\ff.\\{dat}[\|k-\T{1}]\K\\{shift\_right}(\|f,\39\\{magic\_offset}+\T{28}-%
\|e-\T{28}*\|k,\39\T{1}).\|l\AND\T{\^fffffff};{}$\6
${}\\{gg}.\\{dat}[\|k-\T{1}]\K\\{shift\_right}(\|g,\39\\{magic\_offset}+\T{28}-%
\|e-\T{28}*\|k,\39\T{1}).\|l\AND\T{\^fffffff};{}$\6
${}\ff.\\{dat}[\|k]\K\\{shift\_right}(\|f,\39\\{magic\_offset}-\|e-\T{28}*\|k,%
\39\T{1}).\|l\AND\T{\^fffffff};{}$\6
${}\\{gg}.\\{dat}[\|k]\K\\{shift\_right}(\|g,\39\\{magic\_offset}-\|e-\T{28}*%
\|k,\39\T{1}).\|l\AND\T{\^fffffff};{}$\6
${}\ff.\\{dat}[\|k+\T{1}]\K\\{shift\_left}(\|f,\39\|e+\T{28}*\|k-(\\{magic%
\_offset}-\T{28})).\|l\AND\T{\^fffffff};{}$\6
${}\\{gg}.\\{dat}[\|k+\T{1}]\K\\{shift\_left}(\|g,\39\|e+\T{28}*\|k-(\\{magic%
\_offset}-\T{28})).\|l\AND\T{\^fffffff};{}$\6
${}\ff.\|a\K(\ff.\\{dat}[\|k-\T{1}]\?\|k-\T{1}:\|k);{}$\6
${}\ff.\|b\K(\ff.\\{dat}[\|k+\T{1}]\?\|k+\T{1}:\|k);{}$\6
${}\\{gg}.\|a\K(\\{gg}.\\{dat}[\|k-\T{1}]\?\|k-\T{1}:\|k);{}$\6
${}\\{gg}.\|b\K(\\{gg}.\\{dat}[\|k+\T{1}]\?\|k+\T{1}:\|k){}$;\par
\U54.\fi
 
\M{64}If $e$ is sufficiently small, the fractions $f$ and $g$ will be less
than~1,
and we can use the stated algorithm directly. Of course, if $e$ is
extremely small, a lot of leading zeros need to be lopped off; in the
worst case, we may have to multiply $f$ and~$g$ by~10 more than 300 times.
But hey, we don't need to do that extremely often, and computers are
pretty fast nowadays.
 
In the small-exponent case, the computation always terminates before
$f$ becomes zero, because the interval endpoints are fractions with
denominator $2^t$ for some $t>50$.
 
The invariant relations \PB{$\ff.\\{dat}[\ff.\|a]\I\T{0}$} and \PB{$\\{gg}.%
\\{dat}[\\{gg}.\|a]\I\T{0}$} are
not maintained by the computation here, when \PB{$\ff.\|a\K\\{origin}$} or %
\PB{$\\{gg}.\|a\K\\{origin}$}.
But no harm is done, because \PB{\\{bignum\_compare}} is not used.
 
\Y\B\4\X64:Compute the significant digits \PB{\|s} and decimal exponent \PB{%
\|e}\X${}\E{}$\6
\&{if} ${}(\|e>\T{\^401}){}$\1\5
\X65:Compute the significant digits in the large-exponent case\X\2\6
\&{else}\5
${}\{{}$\C{ if \PB{$\|e\Z\T{\^401}$} we have \PB{$\\{gg}.\|a\G\\{origin}$} and %
\PB{$\\{gg}.\\{dat}[\\{origin}]\Z\T{8}$} }\1\6
\&{if} ${}(\ff.\|a>\\{origin}){}$\1\5
${}\ff.\\{dat}[\\{origin}]\K\T{0};{}$\2\6
\&{for} ${}(\|e\K\T{1},\39\|p\K\|s;{}$ ${}\\{gg}.\|a>\\{origin}\V\ff.\\{dat}[%
\\{origin}]\E\\{gg}.\\{dat}[\\{origin}];{}$ \,)\5
${}\{{}$\1\6
\&{if} ${}(\\{gg}.\|a>\\{origin}){}$\1\5
${}\|e\MM;{}$\2\6
\&{else}\1\5
${}{*}\|p\PP\K\ff.\\{dat}[\\{origin}]+\.{'0'},\39\ff.\\{dat}[\\{origin}]\K%
\T{0},\39\\{gg}.\\{dat}[\\{origin}]\K\T{0};{}$\2\6
${}\\{bignum\_times\_ten}({\AND}\ff);{}$\6
${}\\{bignum\_times\_ten}({\AND}\\{gg});{}$\6
\4${}\}{}$\2\6
${}{*}\|p\PP\K((\ff.\\{dat}[\\{origin}]+\T{1}+\\{gg}.\\{dat}[\\{origin}])\GG%
\T{1})+\.{'0'}{}$;\C{ the middle digit }\6
\4${}\}{}$\2\6
${}{*}\|p\K\.{'\\0'}{}$;\C{ terminate the string \PB{\|s} }\par
\U54.\fi
 
\M{65}When \PB{\|e} is large, we use the stated algorithm by considering $f$
and
$g$ to be fractions whose denominator is a power of~10.
 
An interesting case arises when the number to be converted is
\Hex{44ada56a4b0835bf}, since the interval turns out to be
$$ (69999999999999991611392\ \ \dts\ \ 70000000000000000000000).$$
If this were a closed interval, we could simply give the answer
\.{7e22}; but the number \.{7e22} actually corresponds to
\Hex{44ada56a4b0835c0}
because of the round-to-even rule. Therefore the correct answer is, say,
\.{6.9999999999999995e22}. This example shows that we need a slightly
different strategy in the case of open intervals; we cannot simply
look at the first position in which the endpoints have different
decimal digits. Therefore we change the invariant relation to $0\le f<g\le 1$,
when open intervals are involved,
and we do not terminate the process when $f=0$ or $g=1$.
 
\Y\B\4\X65:Compute the significant digits in the large-exponent case\X${}\E{}$\6
${}\{{}$\5
\1\&{register} \&{int} \\{open}${}\K\|x.\|l\AND\T{1};{}$\7
${}\\{tt}.\\{dat}[\\{origin}]\K\T{10};{}$\6
${}\\{tt}.\|a\K\\{tt}.\|b\K\\{origin};{}$\6
\&{for} ${}(\|e\K\T{1};{}$ ${}\\{bignum\_compare}({\AND}\\{gg},\39{\AND}\\{tt})%
\G\\{open};{}$ ${}\|e\PP){}$\1\5
${}\\{bignum\_times\_ten}({\AND}\\{tt});{}$\2\6
${}\|p\K\|s;{}$\6
\&{while} (\T{1})\5
${}\{{}$\1\6
${}\\{bignum\_times\_ten}({\AND}\ff);{}$\6
${}\\{bignum\_times\_ten}({\AND}\\{gg});{}$\6
\&{for} ${}(\|j\K\.{'0'};{}$ ${}\\{bignum\_compare}({\AND}\ff,\39{\AND}\\{tt})%
\G\T{0};{}$ ${}\|j\PP){}$\1\5
${}\\{bignum\_dec}({\AND}\ff,\39{\AND}\\{tt},\39\T{\^10000000}),\39\\{bignum%
\_dec}({\AND}\\{gg},\39{\AND}\\{tt},\39\T{\^10000000});{}$\2\6
\&{if} ${}(\\{bignum\_compare}({\AND}\\{gg},\39{\AND}\\{tt})\G\\{open}){}$\1\5
\&{break};\2\6
${}{*}\|p\PP\K\|j;{}$\6
\&{if} ${}(\ff.\|a\E\\{bignum\_prec}-\T{1}\W\R\\{open}){}$\1\5
\&{goto} \\{done};\C{ $f=0$ in a closed interval }\2\6
\4${}\}{}$\2\6
\&{for} ${}(\|k\K\|j;{}$ ${}\\{bignum\_compare}({\AND}\\{gg},\39{\AND}\\{tt})\G%
\\{open};{}$ ${}\|k\PP){}$\1\5
${}\\{bignum\_dec}({\AND}\\{gg},\39{\AND}\\{tt},\39\T{\^10000000});{}$\2\6
${}{*}\|p\PP\K(\|j+\T{1}+\|k)\GG\T{1}{}$;\C{ the middle digit }\6
\4\\{done}:\5
;\6
\4${}\}{}$\2\par
\U64.\fi
 
\M{66}The length of string~\PB{\|s} will be at most 17. For if $f$ and $g$
agree to 17 places, we have $g/f<1+10^{-16}$; but the
ratio $g/f$ is always $\ge(1+2^{-52}+2^{-53})/(1+2^{-52}-2^{-53})
>1+2\times10^{-16}$.
 
\Y\B\4\X56:Local variables for \PB{\\{print\_float}}\X${}\mathrel+\E{}$\6
\&{bignum} ${}\ff,{}$ \\{gg};\C{ fractions or numerators of fractions }\6
\&{bignum} \\{tt};\C{ power of ten (used as the denominator) }\6
\&{char} \|s[\T{18}];\6
\&{register} \&{char} ${}{*}\|p{}$;\par
\fi
 
\M{67}At this point the significant digits are in string \PB{\|s}, and \PB{$%
\|s[\T{0}]\I\.{'0'}$}.
If we put a decimal point at the left of~\PB{\|s}, the result should
be multiplied by $10^e$.
 
We prefer the output `\.{300.}' to the form `\.{3e2}', and we prefer
`\.{.03}' to `\.{3e-2}'. In general, the output will use an
explicit exponent only if the alternative would take more than
18~characters.
 
\Y\B\4\X67:Print the significant digits with proper context\X${}\E{}$\6
\&{if} ${}(\|e>\T{17}\V\|e<{}$(\&{int}) \\{strlen}(\|s)${}-\T{17}){}$\1\5
${}\\{printf}(\.{"\%c\%s\%se\%d"},\39\|s[\T{0}],\39(\|s[\T{1}]\?\.{"."}:%
\.{""}),\39\|s+\T{1},\39\|e-\T{1});{}$\2\6
\&{else} \&{if} ${}(\|e<\T{0}){}$\1\5
${}\\{printf}(\.{".\%0*d\%s"},\39{-}\|e,\39\T{0},\39\|s);{}$\2\6
\&{else} \&{if} ${}(\\{strlen}(\|s)\G\|e){}$\1\5
${}\\{printf}(\.{"\%.*s.\%s"},\39\|e,\39\|s,\39\|s+\|e);{}$\2\6
\&{else}\1\5
${}\\{printf}(\.{"\%s\%0*d."},\39\|s,\39\|e-{}$(\&{int}) \\{strlen}(\|s)${},\39%
\T{0}){}$;\2\par
\U54.\fi
 
\N{1}{68}Floating point input conversion. Going the other way, we want to
be able to convert a given decimal number into its floating binary
equivalent. The following syntax is supported:
$$\vbox{\halign{$#$\hfil\cr
\<digit>\is\.0\mid\.1\mid\.2\mid\.3\mid\.4\mid
\.5\mid\.6\mid\.7\mid\.8\mid\.9\cr
\<digit string>\is\<digit>\mid\<digit string>\<digit>\cr
\<decimal string>\is\<digit string>\..\mid\..\<digit string>\mid
\<digit string>\..\<digit string>\cr
\<optional sign>\is\<empty>\mid\.+\mid\.-\cr
\<exponent>\is\.e\<optional sign>\<digit string>\cr
\<optional exponent>\is\<empty>\mid\<exponent>\cr
\<floating magnitude>\is\<digit string>\<exponent>\mid
\<decimal string>\<optional exponent>\mid\cr
\hskip12em          \.{Inf}\mid\.{NaN}\mid\.{NaN.}\<digit string>\cr
\<floating constant>\is\<optional sign>\<floating magnitude>\cr
\<decimal constant>\is\<optional sign>\<digit string>\cr
}}$$
For example, `\.{-3.}' is the floating constant \Hex{c008000000000000}%
\thinspace;
`\.{1e3}' and `\.{1000}' are both equivalent to \Hex{408f400000000000}%
\thinspace;
`\.{NaN}' and `\.{+NaN.5}' are both equivalent to \Hex{7ff8000000000000}.
 
The \PB{\\{scan\_const}} routine looks at a given string and finds the
longest initial substring that matches the syntax of either \<decimal
constant> or \<floating constant>. It puts the corresponding value
into the global octabyte variable~\PB{\\{val}}; it also puts the position of
the first
unscanned character in the global pointer variable \PB{\\{next\_char}}.
It returns 1 if a floating constant was found, 0~if a decimal constant
was found, $-1$ if nothing was found. A decimal constant that doesn't
fit in an octabyte is computed modulo~$2^{64}$.
 
The value of \PB{\\{exceptions}} set by \PB{\\{scan\_const}} is not necessarily
correct.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{static} \&{void} \\{bignum\_double}\,\,\.{ARGS}((\&{bignum} ${}{*}));{}$\6
\&{int} \\{scan\_const}\,\,\.{ARGS}((\&{char} ${}{*})){}$;\5
\hbox{}\6{}\&{int} \\{scan\_const}(\|s)\1\1\6
\&{char} ${}{*}\|s;\2\2{}$\6
${}\{{}$\1\6
\X70:Local variables for \PB{\\{scan\_const}}\X;\6
${}\\{val}.\|h\K\\{val}.\|l\K\T{0};{}$\6
${}\|p\K\|s;{}$\6
\&{if} ${}({*}\|p\E\.{'+'}\V{*}\|p\E\.{'-'}){}$\1\5
${}\\{sign}\K{*}\|p\PP{}$;\5
\2\&{else}\1\5
${}\\{sign}\K\.{'+'};{}$\2\6
\&{if} ${}(\\{strncmp}(\|p,\39\.{"NaN"},\39\T{3})\E\T{0}){}$\1\5
${}\\{NaN}\K\\{true},\39\|p\MRL{+{\K}}\T{3};{}$\2\6
\&{else}\1\5
${}\\{NaN}\K\\{false};{}$\2\6
\&{if} ${}((\\{isdigit}({*}\|p)\W\R\\{NaN})\V({*}\|p\E\.{'.'}\W\\{isdigit}({*}(%
\|p+\T{1})))){}$\1\5
\X73:Scan a number and \PB{\&{return}}\X;\2\6
\&{if} (\\{NaN})\1\5
\X71:Return the standard NaN\X;\2\6
\&{if} ${}(\\{strncmp}(\|p,\39\.{"Inf"},\39\T{3})\E\T{0}){}$\1\5
\X72:Return infinity\X;\2\6
\4\\{no\_const\_found}:\5
${}\\{next\_char}\K\|s{}$;\5
\&{return} ${}{-}\T{1};{}$\6
\4${}\}{}$\2\par
\fi
 
\M{69}\B\X4:Global variables\X${}\mathrel+\E{}$\6
\&{octa} \\{val};\C{ value returned by \PB{\\{scan\_const}} }\6
\&{char} ${}{*}\\{next\_char}{}$;\C{ pointer returned by \PB{\\{scan\_const}} }%
\par
\fi
 
\M{70}\B\X70:Local variables for \PB{\\{scan\_const}}\X${}\E{}$\6
\&{register} \&{char} ${}{*}\|p,{}$ ${}{*}\|q{}$;\C{ for string manipulations }%
\6
\&{register} \&{bool} \\{NaN};\C{ are we processing a NaN? }\6
\&{int} \\{sign};\C{ \PB{\.{'+'}} or \PB{\.{'-'}} }\par
\As76\ET81.
\U68.\fi
 
\M{71}\B\X71:Return the standard NaN\X${}\E{}$\6
${}\{{}$\1\6
${}\\{next\_char}\K\|p;{}$\6
${}\\{val}.\|h\K\T{\^600000},\39\\{exp}\K\T{\^3fe};{}$\6
\&{goto} \\{packit};\6
\4${}\}{}$\2\par
\U68.\fi
 
\M{72}\B\X72:Return infinity\X${}\E{}$\6
${}\{{}$\1\6
${}\\{next\_char}\K\|p+\T{3};{}$\6
\&{goto} \\{make\_it\_infinite};\6
\4${}\}{}$\2\par
\U68.\fi
 
\M{73}We saw above that a string of at most 17 digits is enough to characterize
a floating point number, for purposes of output. But a much longer buffer
for digits is needed when we're doing input. For example, consider the
borderline quantity $(1+2^{-53})/2^{1022}$; its decimal expansion, when
written out exactly, is a number with more than 750 significant digits:
\.{2.2250738585...8125e-308}.
If {\it any one\/} of those digits is increased, or if
additional nonzero digits are added as in
\.{2.2250738585...81250000001e-308},
the rounded value is supposed to change from \Hex{0010000000000000}
to \Hex{0010000000000001}.
 
We assume here that the user prefers a perfectly correct answer to
a speedy almost-correct one, so we implement the most general case.
 
\Y\B\4\X73:Scan a number and \PB{\&{return}}\X${}\E{}$\6
${}\{{}$\1\6
\&{for} ${}(\|q\K\\{buf0},\39\\{dec\_pt}\K{}$(\&{char} ${}{*}){}$ \T{0}; ${}%
\\{isdigit}({*}\|p);{}$ ${}\|p\PP){}$\5
${}\{{}$\1\6
${}\\{val}\K\\{oplus}(\\{val},\39\\{shift\_left}(\\{val},\39\T{2})){}$;\C{
multiply by 5 }\6
${}\\{val}\K\\{incr}(\\{shift\_left}(\\{val},\39\T{1}),\39{*}\|p-\.{'0'});{}$\6
\&{if} ${}(\|q>\\{buf0}\V{*}\|p\I\.{'0'}){}$\1\6
\&{if} ${}(\|q<\\{buf\_max}){}$\1\5
${}{*}\|q\PP\K{*}\|p;{}$\2\6
\&{else} \&{if} ${}({*}(\|q-\T{1})\E\.{'0'}){}$\1\5
${}{*}(\|q-\T{1})\K{*}\|p;{}$\2\2\6
\4${}\}{}$\2\6
\&{if} (\\{NaN})\1\5
${}{*}\|q\PP\K\.{'1'};{}$\2\6
\&{if} ${}({*}\|p\E\.{'.'}){}$\1\5
\X74:Scan a fraction part\X;\2\6
${}\\{next\_char}\K\|p;{}$\6
\&{if} ${}({*}\|p\E\.{'e'}\W\R\\{NaN}){}$\1\5
\X77:Scan an exponent\X\2\6
\&{else}\1\5
${}\\{exp}\K\T{0};{}$\2\6
\&{if} (\\{dec\_pt})\1\5
\X78:Return a floating point constant\X;\2\6
\&{if} ${}(\\{sign}\E\.{'-'}){}$\1\5
${}\\{val}\K\\{ominus}(\\{zero\_octa},\39\\{val});{}$\2\6
\&{return} \T{0};\6
\4${}\}{}$\2\par
\U68.\fi
 
\M{74}\B\X74:Scan a fraction part\X${}\E{}$\6
${}\{{}$\1\6
${}\\{dec\_pt}\K\|q;{}$\6
${}\|p\PP;{}$\6
\&{for} ${}(\\{zeros}\K\T{0};{}$ ${}\\{isdigit}({*}\|p);{}$ ${}\|p\PP){}$\1\6
\&{if} ${}({*}\|p\E\.{'0'}\W\|q\E\\{buf0}){}$\1\5
${}\\{zeros}\PP;{}$\2\6
\&{else} \&{if} ${}(\|q<\\{buf\_max}){}$\1\5
${}{*}\|q\PP\K{*}\|p;{}$\2\6
\&{else} \&{if} ${}({*}(\|q-\T{1})\E\.{'0'}){}$\1\5
${}{*}(\|q-\T{1})\K{*}\|p;{}$\2\2\6
\4${}\}{}$\2\par
\U73.\fi
 
\M{75}The buffer needs room for eight digits of padding at the left, followed
by up to $1022+53-307$ significant digits, followed by a ``sticky'' digit
at position \PB{$\\{buf\_max}-\T{1}$}, and eight more digits of padding.
 
\Y\B\4\D$\\{buf0}$ \5
$(\\{buf}+\T{8}{}$)\par
\B\4\D$\\{buf\_max}$ \5
$(\\{buf}+\T{777}{}$)\par
\Y\B\4\X4:Global variables\X${}\mathrel+\E{}$\6
\&{static} \&{char} \\{buf}[\T{785}]${}\K\.{"00000000"}{}$;\C{ where we put
significant input digits }\par
\fi
 
\M{76}\B\X70:Local variables for \PB{\\{scan\_const}}\X${}\mathrel+\E{}$\6
\&{register} \&{char} ${}{*}\\{dec\_pt}{}$;\C{ position of decimal point in %
\PB{\\{buf}} }\6
\&{register} \&{int} \\{exp};\C{ scanned exponent; later used for raw binary
exponent }\6
\&{register} \&{int} \\{zeros};\C{ leading zeros removed after decimal point }%
\par
\fi
 
\M{77}Here we don't advance \PB{\\{next\_char}} and force a decimal point until
we
know that a syntactically correct exponent exists.
 
The code here will convert extra-large inputs like
`\.{9e+9999999999999999}' into $\infty$ and extra-small inputs into zero.
Strange inputs like `\.{-00.0e9999999}' must also be accommodated.
 
\Y\B\4\X77:Scan an exponent\X${}\E{}$\6
${}\{{}$\5
\1\&{register} \&{char} \\{exp\_sign};\7
${}\|p\PP;{}$\6
\&{if} ${}({*}\|p\E\.{'+'}\V{*}\|p\E\.{'-'}){}$\1\5
${}\\{exp\_sign}\K{*}\|p\PP{}$;\5
\2\&{else}\1\5
${}\\{exp\_sign}\K\.{'+'};{}$\2\6
\&{if} ${}(\\{isdigit}({*}\|p)){}$\5
${}\{{}$\1\6
\&{for} ${}(\\{exp}\K{*}\|p\PP-\.{'0'};{}$ ${}\\{isdigit}({*}\|p);{}$ ${}\|p%
\PP){}$\1\6
\&{if} ${}(\\{exp}<\T{1000}){}$\1\5
${}\\{exp}\K\T{10}*\\{exp}+{*}\|p-\.{'0'};{}$\2\2\6
\&{if} ${}(\R\\{dec\_pt}){}$\1\5
${}\\{dec\_pt}\K\|q,\39\\{zeros}\K\T{0};{}$\2\6
\&{if} ${}(\\{exp\_sign}\E\.{'-'}){}$\1\5
${}\\{exp}\K{-}\\{exp};{}$\2\6
${}\\{next\_char}\K\|p;{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\U73.\fi
 
\M{78}\B\X78:Return a floating point constant\X${}\E{}$\6
${}\{{}$\1\6
\X79:Move the digits from \PB{\\{buf}} to \PB{$\ff$}\X;\6
\X83:Determine the binary fraction and binary exponent\X;\6
\4\\{packit}:\5
\X84:Pack and round the answer\X;\6
\&{return} \T{1};\6
\4${}\}{}$\2\par
\U73.\fi
 
\M{79}Now we get ready to compute the binary fraction bits, by putting the
scanned input digits into a multiprecision fixed-point
accumulator \PB{$\ff$} that spans the full necessary range.
After this step, the number that we want to convert to floating binary
will appear in \PB{$\ff.\\{dat}[\ff.\|a]$}, \PB{$\ff.\\{dat}[\ff.\|a+\T{1}]$}, %
\dots,
\PB{$\ff.\\{dat}[\ff.\|b]$}.
The radix-$10^9$ digit in ${\it ff}[36-k]$ is understood to be multiplied
by $10^{9k}$, for $36\ge k\ge-120$.
 
\Y\B\4\X79:Move the digits from \PB{\\{buf}} to \PB{$\ff$}\X${}\E{}$\6
$\|x\K\\{buf}+\T{341}+\\{zeros}-\\{dec\_pt}-\\{exp};{}$\6
\&{if} ${}(\|q\E\\{buf0}\V\|x\G\T{1413}){}$\5
${}\{{}$\1\6
\4\\{make\_it\_zero}:\5
${}\\{exp}\K{-}\T{99999}{}$;\5
\&{goto} \\{packit};\6
\4${}\}{}$\2\6
\&{if} ${}(\|x<\T{0}){}$\5
${}\{{}$\1\6
\4\\{make\_it\_infinite}:\5
${}\\{exp}\K\T{99999}{}$;\5
\&{goto} \\{packit};\6
\4${}\}{}$\2\6
${}\ff.\|a\K\|x/\T{9};{}$\6
\&{for} ${}(\|p\K\|q;{}$ ${}\|p<\|q+\T{8};{}$ ${}\|p\PP){}$\1\5
${}{*}\|p\K\.{'0'}{}$;\C{ pad with trailing zeros }\2\6
${}\|q\K\|q-\T{1}-(\|q+\T{341}+\\{zeros}-\\{dec\_pt}-\\{exp})\MOD\T{9}{}$;\C{
compute stopping place in \PB{\\{buf}} }\6
\&{for} ${}(\|p\K\\{buf0}-\|x\MOD\T{9},\39\|k\K\ff.\|a;{}$ ${}\|p\Z\|q\W\|k\Z%
\T{156};{}$ ${}\|p\MRL{+{\K}}\T{9},\39\|k\PP){}$\1\5
\X80:Put the 9-digit number \PB{${*}\|p$}\thinspace\dots\thinspace\PB{${*}(\|p+%
\T{8})$} into \PB{$\ff.\\{dat}[\|k]$}\X;\2\6
${}\ff.\|b\K\|k-\T{1};{}$\6
\&{for} ${}(\|x\K\T{0};{}$ ${}\|p\Z\|q;{}$ ${}\|p\MRL{+{\K}}\T{9}){}$\1\6
\&{if} ${}(\\{strncmp}(\|p,\39\.{"000000000"},\39\T{9})\I\T{0}){}$\1\5
${}\|x\K\T{1};{}$\2\2\6
${}\ff.\\{dat}[\T{156}]\MRL{+{\K}}\|x{}$;\C{ nonzero digits that fall off the
right are sticky }\6
\&{while} ${}(\ff.\\{dat}[\ff.\|b]\E\T{0}){}$\1\5
${}\ff.\|b\MM{}$;\2\par
\U78.\fi
 
\M{80}\B\X80:Put the 9-digit number \PB{${*}\|p$}\thinspace\dots\thinspace%
\PB{${*}(\|p+\T{8})$} into \PB{$\ff.\\{dat}[\|k]$}\X${}\E{}$\6
${}\{{}$\1\6
\&{for} ${}(\|x\K{*}\|p-\.{'0'},\39\\{pp}\K\|p+\T{1};{}$ ${}\\{pp}<\|p+%
\T{9};{}$ ${}\\{pp}\PP){}$\1\5
${}\|x\K\T{10}*\|x+{*}\\{pp}-\.{'0'};{}$\2\6
${}\ff.\\{dat}[\|k]\K\|x;{}$\6
\4${}\}{}$\2\par
\U79.\fi
 
\M{81}\B\X70:Local variables for \PB{\\{scan\_const}}\X${}\mathrel+\E{}$\6
\&{register} \&{int} \|k${},{}$ \|x;\6
\&{register} \&{char} ${}{*}\\{pp};{}$\6
\&{bignum} ${}\ff,{}$ \\{tt};\par
\fi
 
\M{82}Here's a subroutine that is dual to \PB{\\{bignum\_times\_ten}}. It
changes $f$
to~$2f$, assuming that overflow will not occur and that the radix is $10^9$.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{static} \&{void} \\{bignum\_double}(\|f)\1\1\6
\&{bignum} ${}{*}\|f;\2\2{}$\6
${}\{{}$\1\6
\&{register} \&{tetra} ${}{*}\|p,{}$ ${}{*}\|q;{}$\6
\&{register} \&{int} \|x${},{}$ \\{carry};\7
\&{for} ${}(\|p\K{\AND}\|f\MG\\{dat}[\|f\MG\|b],\39\|q\K{\AND}\|f\MG\\{dat}[\|f%
\MG\|a],\39\\{carry}\K\T{0};{}$ ${}\|p\G\|q;{}$ ${}\|p\MM){}$\5
${}\{{}$\1\6
${}\|x\K{*}\|p+{*}\|p+\\{carry};{}$\6
\&{if} ${}(\|x\G\T{1000000000}){}$\1\5
${}\\{carry}\K\T{1},\39{*}\|p\K\|x-\T{1000000000};{}$\2\6
\&{else}\1\5
${}\\{carry}\K\T{0},\39{*}\|p\K\|x;{}$\2\6
\4${}\}{}$\2\6
${}{*}\|p\K\\{carry};{}$\6
\&{if} (\\{carry})\1\5
${}\|f\MG\|a\MM;{}$\2\6
\&{if} ${}(\|f\MG\\{dat}[\|f\MG\|b]\E\T{0}\W\|f\MG\|b>\|f\MG\|a){}$\1\5
${}\|f\MG\|b\MM;{}$\2\6
\4${}\}{}$\2\par
\fi
 
\M{83}\B\X83:Determine the binary fraction and binary exponent\X${}\E{}$\6
$\\{val}\K\\{zero\_octa};{}$\6
\&{if} ${}(\ff.\|a>\T{36}){}$\5
${}\{{}$\1\6
\&{for} ${}(\\{exp}\K\T{\^3fe};{}$ ${}\ff.\|a>\T{36};{}$ ${}\\{exp}\MM){}$\1\5
${}\\{bignum\_double}({\AND}\ff);{}$\2\6
\&{for} ${}(\|k\K\T{54};{}$ \|k; ${}\|k\MM){}$\5
${}\{{}$\1\6
\&{if} ${}(\ff.\\{dat}[\T{36}]){}$\5
${}\{{}$\1\6
\&{if} ${}(\|k\G\T{32}){}$\1\5
${}\\{val}.\|h\MRL{{\OR}{\K}}\T{1}\LL(\|k-\T{32}){}$;\5
\2\&{else}\1\5
${}\\{val}.\|l\MRL{{\OR}{\K}}\T{1}\LL\|k;{}$\2\6
${}\ff.\\{dat}[\T{36}]\K\T{0};{}$\6
\&{if} ${}(\ff.\|b\E\T{36}){}$\1\5
\&{break};\C{ break if \PB{$\ff$} now zero }\2\6
\4${}\}{}$\2\6
${}\\{bignum\_double}({\AND}\ff);{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\5
\2\&{else}\5
${}\{{}$\1\6
${}\\{tt}.\|a\K\\{tt}.\|b\K\T{36},\39\\{tt}.\\{dat}[\T{36}]\K\T{2};{}$\6
\&{for} ${}(\\{exp}\K\T{\^3fe};{}$ ${}\\{bignum\_compare}({\AND}\ff,\39{\AND}%
\\{tt})\G\T{0};{}$ ${}\\{exp}\PP){}$\1\5
${}\\{bignum\_double}({\AND}\\{tt});{}$\2\6
\&{for} ${}(\|k\K\T{54};{}$ \|k; ${}\|k\MM){}$\5
${}\{{}$\1\6
${}\\{bignum\_double}({\AND}\ff);{}$\6
\&{if} ${}(\\{bignum\_compare}({\AND}\ff,\39{\AND}\\{tt})\G\T{0}){}$\5
${}\{{}$\1\6
\&{if} ${}(\|k\G\T{32}){}$\1\5
${}\\{val}.\|h\MRL{{\OR}{\K}}\T{1}\LL(\|k-\T{32}){}$;\5
\2\&{else}\1\5
${}\\{val}.\|l\MRL{{\OR}{\K}}\T{1}\LL\|k;{}$\2\6
${}\\{bignum\_dec}({\AND}\ff,\39{\AND}\\{tt},\39\T{1000000000});{}$\6
\&{if} ${}(\ff.\|a\E\\{bignum\_prec}-\T{1}){}$\1\5
\&{break};\C{ break if \PB{$\ff$} now zero }\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\&{if} ${}(\|k\E\T{0}){}$\1\5
${}\\{val}.\|l\MRL{{\OR}{\K}}\T{1}{}$;\C{ add sticky bit if \PB{$\ff$} nonzero
}\2\par
\U78.\fi
 
\M{84}We need to be careful that the input `\.{NaN.999999999999999999999}'
doesn't
get rounded up; it is supposed to yield \Hex{7fffffffffffffff}.
 
Although the input `\.{NaN.0}' is illegal, strictly speaking, we silently
convert it to \Hex{7ff0000000000001}---a number that would be
output as `\.{NaN.0000000000000002}'.
 
\Y\B\4\X84:Pack and round the answer\X${}\E{}$\6
$\\{val}\K\\{fpack}(\\{val},\39\\{exp},\39\\{sign},\39\.{ROUND\_NEAR});{}$\6
\&{if} (\\{NaN})\5
${}\{{}$\1\6
\&{if} ${}((\\{val}.\|h\AND\T{\^7fffffff})\E\T{\^40000000}){}$\1\5
${}\\{val}.\|h\MRL{{\OR}{\K}}\T{\^7fffffff},\39\\{val}.\|l\K\T{\^ffffffff};{}$%
\2\6
\&{else} \&{if} ${}((\\{val}.\|h\AND\T{\^7fffffff})\E\T{\^3ff00000}\W\R\\{val}.%
\|l){}$\1\5
${}\\{val}.\|h\MRL{{\OR}{\K}}\T{\^40000000},\39\\{val}.\|l\K\T{1};{}$\2\6
\&{else}\1\5
${}\\{val}.\|h\MRL{{\OR}{\K}}\T{\^40000000};{}$\2\6
\4${}\}{}$\2\par
\U78.\fi
 
\N{1}{85}Floating point remainders. In this section we implement the remainder
of the floating point operations---one of which happens to be the
operation of taking the remainder.
 
The easiest task remaining is to compare two floating point quantities.
Routine \PB{\\{fcomp}} returns $-1$~if~$y<z$, 0~if~$y=z$, $+1$~if~$y>z$, and
$+2$~if $y$ and~$z$ are unordered.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{int} \\{fcomp}\,\,${}\.{ARGS}((\&{octa},\39\&{octa})){}$;\5
\hbox{}\6{}\&{int} ${}\\{fcomp}(\|y,\39\|z){}$\1\1\6
\&{octa} \|y${},{}$ \|z;\2\2\6
${}\{{}$\1\6
\&{ftype} \\{yt}${},{}$ \\{zt};\6
\&{int} \\{ye}${},{}$ \\{ze};\6
\&{char} \\{ys}${},{}$ \\{zs};\6
\&{octa} \\{yf}${},{}$ \\{zf};\6
\&{register} \&{int} \|x;\7
${}\\{yt}\K\\{funpack}(\|y,\39{\AND}\\{yf},\39{\AND}\\{ye},\39{\AND}\\{ys});{}$%
\6
${}\\{zt}\K\\{funpack}(\|z,\39{\AND}\\{zf},\39{\AND}\\{ze},\39{\AND}\\{zs});{}$%
\6
\&{switch} ${}(\T{4}*\\{yt}+\\{zt}){}$\5
${}\{{}$\1\6
\4\&{case} \T{4}${}*\\{nan}+\\{nan}{}$:\5
\&{case} \T{4}${}*\\{zro}+\\{nan}{}$:\5
\&{case} \T{4}${}*\\{num}+\\{nan}{}$:\5
\&{case} \T{4}${}*\\{inf}+\\{nan}{}$:\5
\&{case} \T{4}${}*\\{nan}+\\{zro}{}$:\5
\&{case} \T{4}${}*\\{nan}+\\{num}{}$:\5
\&{case} \T{4}${}*\\{nan}+\\{inf}{}$:\5
\&{return} \T{2};\6
\4\&{case} \T{4}${}*\\{zro}+\\{zro}{}$:\5
\&{return} \T{0};\6
\4\&{case} \T{4}${}*\\{zro}+\\{num}{}$:\5
\&{case} \T{4}${}*\\{num}+\\{zro}{}$:\5
\&{case} \T{4}${}*\\{zro}+\\{inf}{}$:\5
\&{case} \T{4}${}*\\{inf}+\\{zro}{}$:\5
\&{case} \T{4}${}*\\{num}+\\{num}{}$:\5
\&{case} \T{4}${}*\\{num}+\\{inf}{}$:\5
\&{case} \T{4}${}*\\{inf}+\\{num}{}$:\5
\&{case} \T{4}${}*\\{inf}+\\{inf}{}$:\6
\&{if} ${}(\\{ys}\I\\{zs}){}$\1\5
${}\|x\K\T{1};{}$\2\6
\&{else} \&{if} ${}(\|y.\|h>\|z.\|h){}$\1\5
${}\|x\K\T{1};{}$\2\6
\&{else} \&{if} ${}(\|y.\|h<\|z.\|h){}$\1\5
${}\|x\K{-}\T{1};{}$\2\6
\&{else} \&{if} ${}(\|y.\|l>\|z.\|l){}$\1\5
${}\|x\K\T{1};{}$\2\6
\&{else} \&{if} ${}(\|y.\|l<\|z.\|l){}$\1\5
${}\|x\K{-}\T{1};{}$\2\6
\&{else}\1\5
\&{return} \T{0};\2\6
\&{break};\6
\4${}\}{}$\2\6
\&{return} ${}(\\{ys}\E\.{'-'}\?{-}\|x:\|x);{}$\6
\4${}\}{}$\2\par
\fi
 
\M{86}Several \MMIX\ operations act on a single floating point number and
accept an arbitrary rounding mode. For example, consider the
operation of rounding to the nearest floating point integer:
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{octa} \\{fintegerize}\,\,${}\.{ARGS}((\&{octa},\39\&{int})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{fintegerize}(\|z,\39\|r){}$\1\1\6
\&{octa} \|z;\C{ the operand }\6
\&{int} \|r;\C{ the rounding mode }\2\2\6
${}\{{}$\1\6
\&{ftype} \\{zt};\6
\&{int} \\{ze};\6
\&{char} \\{zs};\6
\&{octa} \\{xf}${},{}$ \\{zf};\7
${}\\{zt}\K\\{funpack}(\|z,\39{\AND}\\{zf},\39{\AND}\\{ze},\39{\AND}\\{zs});{}$%
\6
\&{if} ${}(\R\|r){}$\1\5
${}\|r\K\\{cur\_round};{}$\2\6
\&{switch} (\\{zt})\5
${}\{{}$\1\6
\4\&{case} \\{nan}:\5
\&{if} ${}(\R(\|z.\|h\AND\T{\^80000})){}$\5
${}\{{}$\5
\1${}\\{exceptions}\MRL{{\OR}{\K}}\.{I\_BIT}{}$;\5
${}\|z.\|h\MRL{{\OR}{\K}}\T{\^80000}{}$;\5
${}\}{}$\2\6
\4\&{case} \\{inf}:\5
\&{case} \\{zro}:\5
\&{return} \|z;\6
\4\&{case} \\{num}:\5
\X87:Integerize and \PB{\&{return}}\X;\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\fi
 
\M{87}\B\X87:Integerize and \PB{\&{return}}\X${}\E{}$\6
\&{if} ${}(\\{ze}\G\T{1074}){}$\1\5
\&{return} \\{fpack}${}(\\{zf},\39\\{ze},\39\\{zs},\39\.{ROUND\_OFF}){}$;\C{
already an integer }\2\6
\&{if} ${}(\\{ze}\Z\T{1020}){}$\1\5
${}\\{xf}.\|h\K\T{0},\39\\{xf}.\|l\K\T{1};{}$\2\6
\&{else}\5
${}\{{}$\5
\1\&{octa} \\{oo};\7
${}\\{xf}\K\\{shift\_right}(\\{zf},\39\T{1074}-\\{ze},\39\T{1});{}$\6
${}\\{oo}\K\\{shift\_left}(\\{xf},\39\T{1074}-\\{ze});{}$\6
\&{if} ${}(\\{oo}.\|l\I\\{zf}.\|l\V\\{oo}.\|h\I\\{zf}.\|h){}$\1\5
${}\\{xf}.\|l\MRL{{\OR}{\K}}\T{1}{}$;\C{ sticky bit }\2\6
\4${}\}{}$\2\6
\&{switch} (\|r)\5
${}\{{}$\1\6
\4\&{case} \.{ROUND\_DOWN}:\5
\&{if} ${}(\\{zs}\E\.{'-'}){}$\1\5
${}\\{xf}\K\\{incr}(\\{xf},\39\T{3}){}$;\5
\2\&{break};\6
\4\&{case} \.{ROUND\_UP}:\5
\&{if} ${}(\\{zs}\I\.{'-'}){}$\1\5
${}\\{xf}\K\\{incr}(\\{xf},\39\T{3});{}$\2\6
\4\&{case} \.{ROUND\_OFF}:\5
\&{break};\6
\4\&{case} \.{ROUND\_NEAR}:\5
${}\\{xf}\K\\{incr}(\\{xf},\39\\{xf}.\|l\AND\T{4}\?\T{2}:\T{1}){}$;\5
\&{break};\6
\4${}\}{}$\2\6
${}\\{xf}.\|l\MRL{\AND{\K}}\T{\^fffffffc};{}$\6
\&{if} ${}(\\{ze}\G\T{1022}){}$\1\5
\&{return} \\{fpack}${}(\\{shift\_left}(\\{xf},\39\T{1074}-\\{ze}),\39\\{ze},%
\39\\{zs},\39\.{ROUND\_OFF});{}$\2\6
\&{if} ${}(\\{xf}.\|l){}$\1\5
${}\\{xf}.\|h\K\T{\^3ff00000},\39\\{xf}.\|l\K\T{0};{}$\2\6
\&{if} ${}(\\{zs}\E\.{'-'}){}$\1\5
${}\\{xf}.\|h\MRL{{\OR}{\K}}\\{sign\_bit};{}$\2\6
\&{return} \\{xf};\par
\U86.\fi
 
\M{88}To convert floating point to fixed point, we use \PB{\\{fixit}}.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{octa} \\{fixit}\,\,${}\.{ARGS}((\&{octa},\39\&{int})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{fixit}(\|z,\39\|r){}$\1\1\6
\&{octa} \|z;\C{ the operand }\6
\&{int} \|r;\C{ the rounding mode }\2\2\6
${}\{{}$\1\6
\&{ftype} \\{zt};\6
\&{int} \\{ze};\6
\&{char} \\{zs};\6
\&{octa} \\{zf}${},{}$ \|o;\7
${}\\{zt}\K\\{funpack}(\|z,\39{\AND}\\{zf},\39{\AND}\\{ze},\39{\AND}\\{zs});{}$%
\6
\&{if} ${}(\R\|r){}$\1\5
${}\|r\K\\{cur\_round};{}$\2\6
\&{switch} (\\{zt})\5
${}\{{}$\1\6
\4\&{case} \\{nan}:\5
\&{case} \\{inf}:\5
${}\\{exceptions}\MRL{{\OR}{\K}}\.{I\_BIT}{}$;\5
\&{return} \|z;\6
\4\&{case} \\{zro}:\5
\&{return} \\{zero\_octa};\6
\4\&{case} \\{num}:\5
\&{if} ${}(\\{funpack}(\\{fintegerize}(\|z,\39\|r),\39{\AND}\\{zf},\39{\AND}%
\\{ze},\39{\AND}\\{zs})\E\\{zro}){}$\1\5
\&{return} \\{zero\_octa};\2\6
\&{if} ${}(\\{ze}\Z\T{1076}){}$\1\5
${}\|o\K\\{shift\_right}(\\{zf},\39\T{1076}-\\{ze},\39\T{1});{}$\2\6
\&{else}\5
${}\{{}$\1\6
\&{if} ${}(\\{ze}>\T{1085}\V(\\{ze}\E\T{1085}\W(\\{zf}.\|h>\T{\^400000}\V%
\3{-1}(\\{zf}.\|h\E\T{\^400000}\W(\\{zf}.\|l\V\\{zs}\I\.{'-'}))))){}$\1\5
${}\\{exceptions}\MRL{{\OR}{\K}}\.{W\_BIT};{}$\2\6
\&{if} ${}(\\{ze}\G\T{1140}){}$\1\5
\&{return} \\{zero\_octa};\2\6
${}\|o\K\\{shift\_left}(\\{zf},\39\\{ze}-\T{1076});{}$\6
\4${}\}{}$\2\6
\&{return} ${}(\\{zs}\E\.{'-'}\?\\{ominus}(\\{zero\_octa},\39\|o):\|o);{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\fi
 
\M{89}Going the other way, we can specify not only a rounding mode but whether
the given fixed point octabyte is signed or unsigned, and whether the
result should be rounded to short precision.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{octa} \\{floatit}\,\,${}\.{ARGS}((\&{octa},\39\&{int},\39\&{int},\39%
\&{int})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{floatit}(\|z,\39\|r,\39\|u,\39\|p){}$\1\1\6
\&{octa} \|z;\C{ octabyte to float }\6
\&{int} \|r;\C{ rounding mode }\6
\&{int} \|u;\C{ unsigned? }\6
\&{int} \|p;\C{ short precision? }\2\2\6
${}\{{}$\1\6
\&{int} \|e;\5
\&{char} \|s;\6
\&{register} \&{int} \|t;\7
${}\\{exceptions}\K\T{0};{}$\6
\&{if} ${}(\R\|z.\|h\W\R\|z.\|l){}$\1\5
\&{return} \\{zero\_octa};\2\6
\&{if} ${}(\R\|r){}$\1\5
${}\|r\K\\{cur\_round};{}$\2\6
\&{if} ${}(\R\|u\W(\|z.\|h\AND\\{sign\_bit})){}$\1\5
${}\|s\K\.{'-'},\39\|z\K\\{ominus}(\\{zero\_octa},\39\|z){}$;\5
\2\&{else}\1\5
${}\|s\K\.{'+'};{}$\2\6
${}\|e\K\T{1076};{}$\6
\&{while} ${}(\|z.\|h<\T{\^400000}){}$\1\5
${}\|e\MM,\39\|z\K\\{shift\_left}(\|z,\39\T{1});{}$\2\6
\&{while} ${}(\|z.\|h\G\T{\^800000}){}$\5
${}\{{}$\1\6
${}\|e\PP;{}$\6
${}\|t\K\|z.\|l\AND\T{1};{}$\6
${}\|z\K\\{shift\_right}(\|z,\39\T{1},\39\T{1});{}$\6
${}\|z.\|l\MRL{{\OR}{\K}}\|t;{}$\6
\4${}\}{}$\2\6
\&{if} (\|p)\1\5
\X90:Convert to short float\X;\2\6
\&{return} \\{fpack}${}(\|z,\39\|e,\39\|s,\39\|r);{}$\6
\4${}\}{}$\2\par
\fi
 
\M{90}\B\X90:Convert to short float\X${}\E{}$\6
${}\{{}$\1\6
\&{register} \&{int} \\{ex};\5
\&{register} \&{tetra} \|t;\7
${}\|t\K\\{sfpack}(\|z,\39\|e,\39\|s,\39\|r);{}$\6
${}\\{ex}\K\\{exceptions};{}$\6
${}\\{sfunpack}(\|t,\39{\AND}\|z,\39{\AND}\|e,\39{\AND}\|s);{}$\6
${}\\{exceptions}\K\\{ex};{}$\6
\4${}\}{}$\2\par
\U89.\fi
 
\M{91}The square root operation is more interesting.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{octa} \\{froot}\,\,${}\.{ARGS}((\&{octa},\39\&{int})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{froot}(\|z,\39\|r){}$\1\1\6
\&{octa} \|z;\C{ the operand }\6
\&{int} \|r;\C{ the rounding mode }\2\2\6
${}\{{}$\1\6
\&{ftype} \\{zt};\6
\&{int} \\{ze};\6
\&{char} \\{zs};\6
\&{octa} \|x${},{}$ \\{xf}${},{}$ \\{rf}${},{}$ \\{zf};\6
\&{register} \&{int} \\{xe}${},{}$ \|k;\7
\&{if} ${}(\R\|r){}$\1\5
${}\|r\K\\{cur\_round};{}$\2\6
${}\\{zt}\K\\{funpack}(\|z,\39{\AND}\\{zf},\39{\AND}\\{ze},\39{\AND}\\{zs});{}$%
\6
\&{if} ${}(\\{zs}\E\.{'-'}\W\\{zt}\I\\{zro}){}$\1\5
${}\\{exceptions}\MRL{{\OR}{\K}}\.{I\_BIT},\39\|x\K\\{standard\_NaN};{}$\2\6
\&{else}\5
\1\&{switch} (\\{zt})\5
${}\{{}$\1\6
\4\&{case} \\{nan}:\5
\&{if} ${}(\R(\|z.\|h\AND\T{\^80000})){}$\1\5
${}\\{exceptions}\MRL{{\OR}{\K}}\.{I\_BIT},\39\|z.\|h\MRL{{\OR}{\K}}\T{%
\^80000};{}$\2\6
\&{return} \|z;\6
\4\&{case} \\{inf}:\5
\&{case} \\{zro}:\5
${}\|x\K\|z{}$;\5
\&{break};\6
\4\&{case} \\{num}:\5
\X92:Take the square root and \PB{\&{return}}\X;\6
\4${}\}{}$\2\2\6
\&{if} ${}(\\{zs}\E\.{'-'}){}$\1\5
${}\|x.\|h\MRL{{\OR}{\K}}\\{sign\_bit};{}$\2\6
\&{return} \|x;\6
\4${}\}{}$\2\par
\fi
 
\M{92}The square root can be found by an adaptation of the old pencil-and-paper
method. If $n=\lfloor\sqrt s\rfloor$, where $s$ is an integer,
we have $s=n^2+r$ where $0\le r\le2n$;
this invariant can be maintained if we replace $s$ by $4s+(0,1,2,3)$
and $n$ by $2n+(0,1)$. The following code implements this idea with
$2n$ in~\PB{\\{xf}} and $r$ in~\PB{\\{rf}}. (It could easily be made to run
about
twice as fast.)
 
\Y\B\4\X92:Take the square root and \PB{\&{return}}\X${}\E{}$\6
$\\{xf}.\|h\K\T{0},\39\\{xf}.\|l\K\T{2};{}$\6
${}\\{xe}\K(\\{ze}+\T{\^3fe})\GG\T{1};{}$\6
\&{if} ${}(\\{ze}\AND\T{1}){}$\1\5
${}\\{zf}\K\\{shift\_left}(\\{zf},\39\T{1});{}$\2\6
${}\\{rf}.\|h\K\T{0},\39\\{rf}.\|l\K(\\{zf}.\|h\GG\T{22})-\T{1};{}$\6
\&{for} ${}(\|k\K\T{53};{}$ \|k; ${}\|k\MM){}$\5
${}\{{}$\1\6
${}\\{rf}\K\\{shift\_left}(\\{rf},\39\T{2}){}$;\5
${}\\{xf}\K\\{shift\_left}(\\{xf},\39\T{1});{}$\6
\&{if} ${}(\|k\G\T{43}){}$\1\5
${}\\{rf}\K\\{incr}(\\{rf},\39(\\{zf}.\|h\GG(\T{2}*(\|k-\T{43})))\AND\T{3});{}$%
\2\6
\&{else} \&{if} ${}(\|k\G\T{27}){}$\1\5
${}\\{rf}\K\\{incr}(\\{rf},\39(\\{zf}.\|l\GG(\T{2}*(\|k-\T{27})))\AND\T{3});{}$%
\2\6
\&{if} ${}((\\{rf}.\|l>\\{xf}.\|l\W\\{rf}.\|h\G\\{xf}.\|h)\V\\{rf}.\|h>\\{xf}.%
\|h){}$\5
${}\{{}$\1\6
${}\\{xf}.\|l\PP{}$;\5
${}\\{rf}\K\\{ominus}(\\{rf},\39\\{xf}){}$;\5
${}\\{xf}.\|l\PP;{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\&{if} ${}(\\{rf}.\|h\V\\{rf}.\|l){}$\1\5
${}\\{xf}.\|l\PP{}$;\C{ sticky bit }\2\6
\&{return} \\{fpack}${}(\\{xf},\39\\{xe},\39\.{'+'},\39\|r){}$;\par
\U91.\fi
 
\M{93}And finally, the genuine floating point remainder. Subroutine \PB{%
\\{fremstep}}
either calculates $y\,{\rm rem}\,z$ or reduces $y$ to a smaller number
having the same remainder with respect to~$z$. In the latter case
the \PB{\.{E\_BIT}} is set in \PB{\\{exceptions}}. A third parameter, \PB{%
\\{delta}},
gives a decrease in exponent that is acceptable for incomplete results;
if \PB{\\{delta}} is sufficiently large, say 2500, the correct result will
always be obtained in one step of \PB{\\{fremstep}}.
 
\Y\B\4\X5:Subroutines\X${}\mathrel+\E{}$\6
\&{octa} \\{fremstep}\,\,${}\.{ARGS}((\&{octa},\39\&{octa},\39\&{int})){}$;\5
\hbox{}\6{}\&{octa} ${}\\{fremstep}(\|y,\39\|z,\39\\{delta}){}$\1\1\6
\&{octa} \|y${},{}$ \|z;\6
\&{int} \\{delta};\2\2\6
${}\{{}$\1\6
\&{ftype} \\{yt}${},{}$ \\{zt};\6
\&{int} \\{ye}${},{}$ \\{ze};\6
\&{char} \\{xs}${},{}$ \\{ys}${},{}$ \\{zs};\6
\&{octa} \|x${},{}$ \\{xf}${},{}$ \\{yf}${},{}$ \\{zf};\6
\&{register} \&{int} \\{xe}${},{}$ \\{thresh}${},{}$ \\{odd};\7
${}\\{yt}\K\\{funpack}(\|y,\39{\AND}\\{yf},\39{\AND}\\{ye},\39{\AND}\\{ys});{}$%
\6
${}\\{zt}\K\\{funpack}(\|z,\39{\AND}\\{zf},\39{\AND}\\{ze},\39{\AND}\\{zs});{}$%
\6
\&{switch} ${}(\T{4}*\\{yt}+\\{zt}){}$\5
${}\{{}$\1\6
\hbox{\4}\X42:The usual NaN cases\X;\6
\4\&{case} \T{4}${}*\\{zro}+\\{zro}{}$:\5
\&{case} \T{4}${}*\\{num}+\\{zro}{}$:\5
\&{case} \T{4}${}*\\{inf}+\\{zro}{}$:\5
\&{case} \T{4}${}*\\{inf}+\\{num}{}$:\5
\&{case} \T{4}${}*\\{inf}+\\{inf}{}$:\5
${}\|x\K\\{standard\_NaN};{}$\6
${}\\{exceptions}\MRL{{\OR}{\K}}\.{I\_BIT}{}$;\5
\&{break};\6
\4\&{case} \T{4}${}*\\{zro}+\\{num}{}$:\5
\&{case} \T{4}${}*\\{zro}+\\{inf}{}$:\5
\&{case} \T{4}${}*\\{num}+\\{inf}{}$:\5
\&{return} \|y;\6
\4\&{case} \T{4}${}*\\{num}+\\{num}{}$:\5
\X94:Remainderize nonzero numbers and \PB{\&{return}}\X;\6
\4\\{zero\_out}:\5
${}\|x\K\\{zero\_octa};{}$\6
\4${}\}{}$\2\6
\&{if} ${}(\\{ys}\E\.{'-'}){}$\1\5
${}\|x.\|h\MRL{{\OR}{\K}}\\{sign\_bit};{}$\2\6
\&{return} \|x;\6
\4${}\}{}$\2\par
\fi
 
\M{94}If there's a huge difference in exponents and the remainder is nonzero,
this computation will take a long time. One could compute
$(2^ny)\,{\rm rem}\,z$ much more quickly for large~$n$ by using $O(\log n)$
multiplications modulo~$z$, but the floating remainder operation isn't
important enough to justify such expensive hardware.
 
Results of floating remainder are always exact, so the rounding mode
is immaterial.
 
\Y\B\4\X94:Remainderize nonzero numbers and \PB{\&{return}}\X${}\E{}$\6
$\\{odd}\K\T{0}{}$;\C{ will be 1 if we've subtracted an odd multiple of~$z$
from $y$ }\6
${}\\{thresh}\K\\{ye}-\\{delta};{}$\6
\&{if} ${}(\\{thresh}<\\{ze}){}$\1\5
${}\\{thresh}\K\\{ze};{}$\2\6
\&{while} ${}(\\{ye}\G\\{thresh}){}$\1\5
\X95:Reduce \PB{$(\\{ye},\\{yf})$} by a multiple of \PB{\\{zf}}; \PB{\&{goto} %
\\{zero\_out}} if the remainder is zero, \PB{\&{goto} \\{try\_complement}} if
appropriate\X;\2\6
\&{if} ${}(\\{ye}\G\\{ze}){}$\5
${}\{{}$\1\6
${}\\{exceptions}\MRL{{\OR}{\K}}\.{E\_BIT}{}$;\5
\&{return} \\{fpack}${}(\\{yf},\39\\{ye},\39\\{ys},\39\.{ROUND\_OFF});{}$\6
\4${}\}{}$\2\6
\&{if} ${}(\\{ye}<\\{ze}-\T{1}){}$\1\5
\&{return} \\{fpack}${}(\\{yf},\39\\{ye},\39\\{ys},\39\.{ROUND\_OFF});{}$\2\6
${}\\{yf}\K\\{shift\_right}(\\{yf},\39\T{1},\39\T{1});{}$\6
\4\\{try\_complement}:\5
${}\\{xf}\K\\{ominus}(\\{zf},\39\\{yf}),\39\\{xe}\K\\{ze},\39\\{xs}\K\.{'+'}+%
\.{'-'}-\\{ys};{}$\6
\&{if} ${}(\\{xf}.\|h>\\{yf}.\|h\V(\\{xf}.\|h\E\\{yf}.\|h\W(\\{xf}.\|l>\\{yf}.%
\|l\V(\\{xf}.\|l\E\\{yf}.\|l\W\R\\{odd})))){}$\1\5
${}\\{xf}\K\\{yf},\39\\{xs}\K\\{ys};{}$\2\6
\&{while} ${}(\\{xf}.\|h<\T{\^400000}){}$\1\5
${}\\{xe}\MM,\39\\{xf}\K\\{shift\_left}(\\{xf},\39\T{1});{}$\2\6
\&{return} \\{fpack}${}(\\{xf},\39\\{xe},\39\\{xs},\39\.{ROUND\_OFF}){}$;\par
\U93.\fi
 
\M{95}Here we are careful not to change the sign of \PB{\|y}, because a
remainder
of~0 is supposed to inherit the original sign of~\PB{\|y}.
 
\Y\B\4\X95:Reduce \PB{$(\\{ye},\\{yf})$} by a multiple of \PB{\\{zf}}; \PB{%
\&{goto} \\{zero\_out}} if the remainder is zero, \PB{\&{goto} \\{try%
\_complement}} if appropriate\X${}\E{}$\6
${}\{{}$\1\6
\&{if} ${}(\\{yf}.\|h\E\\{zf}.\|h\W\\{yf}.\|l\E\\{zf}.\|l){}$\1\5
\&{goto} \\{zero\_out};\2\6
\&{if} ${}(\\{yf}.\|h<\\{zf}.\|h\V(\\{yf}.\|h\E\\{zf}.\|h\W\\{yf}.\|l<\\{zf}.%
\|l)){}$\5
${}\{{}$\1\6
\&{if} ${}(\\{ye}\E\\{ze}){}$\1\5
\&{goto} \\{try\_complement};\2\6
${}\\{ye}\MM,\39\\{yf}\K\\{shift\_left}(\\{yf},\39\T{1});{}$\6
\4${}\}{}$\2\6
${}\\{yf}\K\\{ominus}(\\{yf},\39\\{zf});{}$\6
\&{if} ${}(\\{ye}\E\\{ze}){}$\1\5
${}\\{odd}\K\T{1};{}$\2\6
\&{while} ${}(\\{yf}.\|h<\T{\^400000}){}$\1\5
${}\\{ye}\MM,\39\\{yf}\K\\{shift\_left}(\\{yf},\39\T{1});{}$\2\6
\4${}\}{}$\2\par
\U94.\fi
 
\N{1}{96}Index.
 
\fi
 
 
\inx
\fin
\con
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.