% This file is part of crlibm, the correctly rounded mathematical library,
% which has been developed by the Arénaire project at École normale supérieure
% de Lyon.
%
% Copyright (C) 2004-2011 David Defour, Catherine Daramy-Loirat,
% Florent de Dinechin, Matthieu Gallet, Nicolas Gast, Christoph Quirin Lauter,
% and Jean-Michel Muller
%
% This library is free software; you can redistribute it and/or
% modify it under the terms of the GNU Lesser General Public
% License as published by the Free Software Foundation; either
% version 2.1 of the License, or (at your option) any later version.
%
% This library is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
% Lesser General Public License for more details.
%
% You should have received a copy of the GNU Lesser General Public
% License along with this library; if not, write to the Free Software
% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA


This chapter is contributed by Ch. Q. Lauter.

WARNING: This chapter is out-of-sync with the code. The function was
completely rewritten using machine-generated polynomials. Gappa proofs
were automatically generated, too, and are available in the
\texttt{gappa/asin} directory. This chapter will be updated soon.

\section{Overview of the algorithm\label{sec:asin-overview}}
The arcsine $\arcsin\left( x \right) = \sum\limits_{i=0}^{\infty}
\frac{\left( 2i - 1 \right)!!}{\left(2i+1\right) \cdot \left( 2i
\right)!!} \cdot x^{2i+1}$ is defined on the domain $x \in \left[ -1;
1 \right]$. It is a odd function: $\arcsin\left(-x\right) =
-\arcsin\left( x \right)$. Its value in $0$ is $\arcsin\left( 0
\right) = 0$. Its derivative tends to infinity when $x$ tends to $1$:
$\lim\limits_{x \rightarrow 1} \left( \frac{d}{dx} \arcsin
\right)\left(x\right) = \infty$; the function's value in $1$ is
nevertheless finite: $\arcsin\left( 1 \right) = \frac{\pi}{2}$.  There
is no simple additive or multiplicative decomposition of this
function.

A correctly rounded implementation of $\arcsin$ must provide an
accuracy of at least $126$ bits for $\left \vert x \right \vert \leq
2^{-18}$ and of at least $118$ bits for the rest of the definition
domain in the accurate phase \cite{DinDefLau2004LIP}.

The algorithm chosen principally consists of a piecewise polynomial
approximation either of the function itself or of a asymptotic
development of the function. More precisely, the following is done:
\begin{itemize}
\item Special cases, such as $\left \vert x \right \vert > 1$, $x = \pm \infty$, $x = \nan$, are handled.
\item The sign of the argument $x$ is stripped off because
$\arcsin\left(x\right) = \sgn\left(x\right) \cdot \arcsin\left( \left
\vert x \right \vert \right)$. We will suppose in the following, that
$x$ stands for a positive argument, $x \geq 0$.
\item The argument is classified in one of $10$ subdomains of $\left[
0; 1 \right]$.  This means an integer $i \in \left[0\dots9\right]$ is
computed such that $x \in I_i$ where
$$\bigcup\limits_{i=0}^9 I_i = \left[0; 1 \right]$$
$$i \not= j \Rightarrow I_i \cap I_j = \emptyset$$
$$i < j \Rightarrow \forall x_i \in I_i, x_j \in I_j \mbox{ . } x_i < x_j$$
\item If $i = 0$, $\arcsin$ is directly approximated as 
$$\arcsin\left( x \right) \approx x + x^3 \cdot p_0\left( x^2 \right)$$
\item If $1 \leq i \leq 8$, an interval midpoint value $m_i
\approx \frac{\inf I_i + \sup I_i}{2}$ is read in a table.  The function is
then approximated as
$$\arcsin\left( x \right) \approx \arcsin\left( m_i \right) +  \left(x - m_i \right) \cdot p_i\left( x - m_i \right)$$
\item If $i = 9$, $\arcsin$ is approximated as 
$$\arcsin\left( x \right) \approx p_9\left( 1 - x \right) \cdot \sqrt{2 - 2\cdot x} + \frac{\pi}{2}$$
\end{itemize}
The polynomials $p_i$, $1 \leq i \leq 8$, for the middle intervals are
all of the same degree and, loaded from a table, can be evaluated in
the same computation path. The polynomials $p_0$ and $p_9$ are of
different degree. So there are three distinct paths in the code. In
the following, they are referred to as the low, middle and high path.

Concerning the quick and accurate phase of the implementation, it must
mentioned that code and cache size considerations do not allow for
using different coefficient tables for the quick phase polynomials
$p_{i\mbox{\tiny ~quick}}$ as for the accurate phase polynomials
$p_{i\mbox{\tiny ~accurate}}$ that are obviously longer and must contain
more accurately stored coefficients. So the quick phase polynomials are
simply the accurate phase polynomials truncated to some degree and simplified 
by omitting low significance components of the coefficients.

The double precision midpoint values $m_i \in \F$ for the middle path
intervals $I_i$, $1 \leq i \leq 8$, are chosen such that a
double-double approximation $asinm_{i\hi} + asinm_{i\lo}$ of
$\arcsin\left( m_i \right)$ is accurate to at least $121$ bits. This
allows for saving up memory in the tables used.

The intervals $I_i$ are not uniformly distributed. This has the
disadvantage that the computation of $i$ cannot be done by simple
bitmasks on the arcsine's argument $x$ but that a dichotomy must be
performed. On the other hand, this is the only way of using
polynomials for the same degree for all middle intervals without
wasting accuracy for the lower ones. In fact, the derivative of
$\arcsin$ grows over-polynomially, which means that the polynomial
degrees must increase for equally sized reduced arguments in order to
achieve the same approximation error. 

The decomposition of the domain $\left[0;1\right]$ into the $I_i$s is
relatively ad-hoc. The given implementation uses:
$$I_i = \left[bound_i;bound_{i+1}\right]$$
with
\begin{eqnarray*}
bound_0 & = & 0 \\
bound_1 & = & 0.184999942779541015625  \\
bound_2 & = & 0.2997171878814697265625  \\
bound_3 & = & 0.40296268463134765625  \\
bound_4 & = & 0.4932067394256591796875  \\
bound_5 & = & 0.5696849822998046875  \\
bound_6 & = & 0.639662265777587890625  \\
bound_7 & = & 0.696256160736083984375 \\
bound_8 & = & 0.741760730743408203125  \\
bound_9 & = & 0.77999973297119140625  \\
bound_{10} & = & 1 
\end{eqnarray*}
One remarks that in order to simplify the dichotomy for computing $i$,
the bounds of the intervals are chosen all such that the low order
word of the double precision numbers they are stored in are $0$. See
\ref{sec:asinargred}, page \pageref{sec:asinargred} for more precise
considerations on that subject.

Let be
$$z_i = \left \lbrace \begin{array}{ll} x & \mbox{ if } i = 0 \\
x - m_i & \mbox{ if } 1 \leq i \leq 8 \\
1 - x & \mbox{ if } i = 9 \end{array} \right.$$
This value $z_i$ is the argument to the polynomial $p_i$. With the given interval bounds, it is bounded by 

$$\left \vert z_1 \right \vert  \leq  2^{-2.434403}$$
$$\left \vert z_2 \right \vert  \leq  2^{-4.123846}$$
$$\left \vert z_3 \right \vert  \leq  2^{-4.275849}$$
$$\left \vert z_4 \right \vert  \leq  2^{-4.470024}$$
$$\left \vert z_5 \right \vert  \leq  2^{-4.708807}$$
$$\left \vert z_6 \right \vert  \leq  2^{-4.836970}$$
$$\left \vert z_7 \right \vert  \leq  2^{-5.143210}$$
$$\left \vert z_8 \right \vert  \leq  2^{-5.457845}$$
$$\left \vert z_9 \right \vert  \leq  2^{-5.708811}$$
$$\left \vert z_{10} \right \vert  \leq  2^{-2.184423}$$

The degrees of the polynomials $p_i$ and the number of double (D),
double-double (DD) and triple-double (TD) coefficients stored in the
table are listed below. Here the degree of the polynomial is the
highest exponent of the monomial whose coefficient is not equal to
$0$. We repeat that the $p_i$ are such that
$$\arcsin\left( x \right) \approx x + x^3 \cdot p_0\left( x^2 \right)$$
$$\arcsin\left( x \right) \approx \arcsin\left( m_i \right) + \left(x
- m_i \right) \cdot p_i\left( x - m_i \right), \mbox{~~} 1 \leq i \leq
8$$
$$\arcsin\left( x \right) \approx p_9\left( 1 - x \right) \cdot \sqrt{2 - 2\cdot x} + \frac{\pi}{2}$$

\begin{center}
\begin{tabular}{|l|l|l|l|l|l|l|l|}
\hline
$i$ & quick phase & accurate phase & D quick & DD quick & D accur. & DD accur. & TD accur. \\
\hline
\hline
$0$ & 8 & 17 & 5 & 4 & 7 & 6 & 5 \\ 
\hline
$1\dots8$ & 13 & 34 & 8 & 6 & 20 & 9 & 6 \\ 
\hline
$9$ & 18 & 28 & 10 & 8 & 12 & 9 & 8 \\ 
\hline
\end{tabular}
\end{center}
Remark that the listing does not account neither for the $8$
double-double values representing approximations to $\arcsin\left( m_i
\right)$ nor for the $8$ double precision numbers $m_i$.

Taking into account also these values, the overall table size for both
quick and accurate phase is 4640 bytes. Some additional values, for
example the triple-double $PiHalf_\hi + PiHalf_\mi + PiHalf_\lo
\approx \frac{\pi}{2}$, interval bounds or table indices, are directly
compiled into the code. Their overall size is 100 bytes.

\section{Special case handling, interval discrimination and argument reduction}\label{sec:asinargred}
As already mentioned, $\arcsin$ is only defined on the domain $\left[
  -1; 1 \right]$. For other arguments, including $\pm \infty$ and
$\nan$, $\nan$ must be returned. This is implemented in the code as
follows: the sign of $x$ is stripped off by integer computations and
stored in variable {\tt sign}. Than, $\left \vert x \right \vert$ is
compared to $1$ by integer comparisons.
\begin{lstlisting}[caption={Handling special cases - definition domain},firstnumber=1]
/* Transform the argument into integer */
xdb.d = x;

/* Special case handling */

/* Strip off the sign of argument x */
if (xdb.i[HI] & 0x80000000) sign = -1; else sign = 1;
xdb.i[HI] &= 0x7fffffff;

/* asin is defined on -1 <= x <= 1, elsewhere it is NaN */
if ((xdb.i[HI] > 0x3ff00000) || ((xdb.i[HI] == 0x3ff00000) && (xdb.i[LO] != 0x00000000))) {
  return (x-x)/0.0;    /* return NaN */
}
\end{lstlisting}

Concerning subnormals in argument and in result of the function, the
following is to be mentioned.  The Taylor series of $\arcsin$
developed in $0$ is $$\arcsin\left( x \right) = x \cdot \left( 1 +
\frac{1}{6} \cdot x^2 + \sum\limits_{n=2}^\infty \frac{\left( 2n - 1
\right)!!}{\left(2n\right)!! \cdot \left( 2n + 1 \right)} \cdot
x^{2n}\right)$$ It is easy to check that $\sum\limits_{n=2}^\infty
\frac{\left( 2n - 1 \right)!!}{\left(2n\right)!! \cdot \left( 2n + 1
\right)} \cdot x^{2n} < \frac{1}{3} \cdot x^2$ for $\left \vert x
\right \vert < \frac{1}{2}$. So for $\left \vert x \right \vert \leq
2^{-28}$, one gets $\arcsin\left( x \right) \leq x \cdot \left( 1 +
\frac{1}{2} \cdot x^2 \right) \leq x \cdot \left( 1 + 2^{-57} \right)
< x + \frac{1}{2} \mUlp\left(x\right)$. So the rounding can be decided
without even computing the cubic term of the Taylor
development. Thus subnormals in argument and in result can be avoided
by performing a simple test on the absolute value of $x$. In
particular, since $\sum\limits_{n=1}^\infty \frac{\left( 2n - 1
\right)!!}{\left(2n\right)!! \cdot \left( 2n + 1 \right)} \cdot
x^{2n}$ is an even function, the sign of the truncation rest is known,
which allows for simplifications in the directed rounding modes. Here,
only some special care is needed for the case where $x$ is exactly
equal to $0$.  

The test and the rounding are implemented as follows. Let us first
consider the round-to-nearest case:
\begin{lstlisting}[caption={Handling special cases - rounding (to nearest)},firstnumber=1]
if (xdb.i[HI] < 0x3e300000) {
  return x;
}
\end{lstlisting}
In the round-upward case, a correction of $x$ is potentially
necessary. We implement:
\begin{lstlisting}[caption={Handling special cases - rounding (upwards)},firstnumber=1]
/* If x == 0 then we got the algebraic result arcsin(0) = 0
   If x < 0 then the truncation rest is negative but less than 
   1 ulp; we round upwards by returning x
*/
if (x <= 0) return x;
/* Otherwise the rest is positive, less than 1 ulp and the
   image is not algebraic 
   We return x + 1ulp
*/
xdb.l++;
return xdb.d;
\end{lstlisting}
The other directed rounding cases are analogous to the round-upwards
case.

For the discrimination of the argument $\left \vert x \right \vert$ in
the 10 possible approximation intervals $I_i$, the following technique
is used. The intervals at the definition domain borders $I_0$ and
$I_9$ are first filtered out by tests checking the high order word of
$x$ against the corresponding bounds. If $x$ is found to be in one of
these two intervals, the function is approximated in quick and if
needed in accurate phase and the correctly rounded value is
returned. In any case, the two intervals have particular properties in
comparison to the other 8 middle intervals, so this technique should
not be considered as a performance disadvantage. The polynomial
coefficients' indices in the main coefficient table are fixed in this
case and directly compiled into the code via macros.

If $x$ does not fall in one of the both border intervals $I_0$ and
$I_9$, the corresponding interval $I_i$, $1 \leq i \leq 8$ is computed
by a 3-level dichotomy on the bounds $bound_2 \dots bound_8$.  Its
result is not a number $i$ in $1 \leq i \leq 8$ but an index {\tt i}
to the main coefficient table. Beginning at the point indexed, the
table reads the midpoint value $m_i$ and the polynomial coefficients
for the corresponding interval $I_i$. 

The correponding code is the following:
\begin{lstlisting}[caption={Interval discrimination},firstnumber=1]
/* Recast x */
x = xdb.d;

/* Find correspondant interval and compute index to the table
   We start by filtering the two special cases around 0 and 1
*/

if (xdb.i[HI] < BOUND1) {

(*@-- Compute quick and potentially accurate phase polynomial approximation $p_0$ and return --@*)

}

if (xdb.i[HI] > BOUND9) {

(*@-- Reduce the argument, compute quick and potentially accurate
phase approximation using $p_9$, reconstruct and return --@*)
}

/* General 8 main intervals 
   We can already suppose that BOUND1 <= x <= BOUND9
*/

if (xdb.i[HI] < BOUND5) {
  if (xdb.i[HI] < BOUND3) {
    if (xdb.i[HI] < BOUND2) i = TBLIDX2; else i = TBLIDX3;
  } else {
    if (xdb.i[HI] < BOUND4) i = TBLIDX4; else i = TBLIDX5;
  }
} else {
  if (xdb.i[HI] < BOUND7) {
    if (xdb.i[HI] < BOUND6) i = TBLIDX6; else i = TBLIDX7;
  } else {
    if (xdb.i[HI] < BOUND8) i = TBLIDX8; else i = TBLIDX9;
  }
}

(*@-- Reduce the argument, compute quick and potentially accurate~
phase polynomial approximation $p_i$ and return --@*)
\end{lstlisting}

In the case of $x$ being classified in either the middle or the higher
intervals $I_i$, $1 \leq i \leq 9$, an argument reduction is to be
performed. Let us consider it first for the high path interval $I_9$
and then for the middle path intervals $I_i$, $1 \leq i \leq 8$. In
both cases, we will show that the argument reduction is mathematically
exact and that it may not produce a subnormal different from $0$.

In the high path, we know that $1 \geq x > bound_9 > 0.77$. The
argument reduction to be performed is $z = 1 - x$. Since $\frac{1}{2}
\leq x \leq 2$ is verified, we can implement it exactly thanks to
Sterbenz' lemma. If $x$ is exactly equal to $1$ is produces exactly
$0$. Otherwise, it may not produce a subnormal, because $x \leq 1 -
\frac{1}{2} \cdot \mUlp\left( 1 \right) \leq 1 - 2^{-53}$. Thus $z = 1
- x > 2^{-53} > 2^{-1021}$.

In the middle path intervals, the argument reduction to be performed
is $z_i = x - m_i$. Since $\left \vert z \right \vert \leq 0.058$ and
$x \geq 0.18$, Sterbenz' lemma is verified in each interval $I_i$ and
we can still implement the argument reduction exactly in double
precision arithmetic. Since, $x > 0.18 > \frac{1}{8}$, a similar
argument as the one given above shows that the result of the reduction
is either exactly $0$ or a non-subnormal double precision number.

The value $m_i$ is read in the main table at the index {\tt i}
computed by the interval discrimination phase. We implement thus:
\begin{lstlisting}[caption={Argument reduction},firstnumber=1]
/* Argument reduction 
   i points to the interval midpoint value in the table
*/
z = x - tbl[i];
\end{lstlisting}

Concerning the higher path interval $I_9$ where $\arcsin$ is
approximated as
$$\arcsin\left( x \right) \approx p_9\left( 1 - x \right) \cdot
\sqrt{2 - 2\cdot x} + \frac{\pi}{2}$$ let us remark that $2 - 2\cdot x
= 2 \cdot z$ can also be computed exactly. Trivially, since $z$ less
than $2^{1023}$, the multiplication by a positive integer power of $2$
is errorfree. If $z$ is not exactly $0$, its result may not be
subnormal because $z$ cannot.

Since the argument reduction has been shown to be exact, its result
can clearly be reused in the accurate phase.

\section{Polynomial approximation and reconstruction}\label{sec:asinpolynomial}
\subsection{Quick phase polynomial approximation and reconstruction}\label{subsec:asinquickpolynomial}
As already mentioned, the quick phase polynomials $p_{i\mbox{\tiny ~quick}}$ 
are truncated versions of the accurate phase polynomials
$p_{i\mbox{\tiny ~accurate}}$ with coefficients rounded from
triple-double to double-double or from double-double to double. This
means simply that not all coefficients are read and used.
\subsubsection{Low path - interval $I_0$}
The polynomial $p_{0\mbox{\tiny ~quick}}$ approximates $\arcsin$ in the interval $I_0$ as follows:
$$\arcsin\left( x \right) \approx x + x^3 \cdot p_{0\mbox{\tiny ~quick}}\left( x^2 \right)$$
It is of degree $8$ with $5$ double-double and $4$ double precision
coefficients. 

For arguments $\left \vert x \right \vert \leq 2^{-10}$, the
polynomial needs not be evaluated fully to provide enough accuracy. 
Here, only its constant and linear term are evaluated. So we get in this case
$$\arcsin\left( x \right) \approx x + x^3 \cdot \left( \left( c_{0\hi} + c_{0\lo} \right) + 
  x^2 \cdot \left( c_{1\hi} + c_{1\lo} \right) \right)$$ This special
path yields to a significant performance gain on average. In fact,
since floating point numbers are not equispaced but distributed
logarithmatically around $0$, speeding up a function for low arguments
is worth it.

The square of $x$, $x^2$ can be computed exactly by use of a \Mul~
sequence, which will produce a double-double $xSq_\hi + xSq_\lo =
x^2$. The polynomial $p_{0\mbox{\tiny ~quick}}\left( xSq_\hi + xSq_\lo
\right)$ is evaluated using Horner's scheme and neglecting $xSq_\lo$
for the $8$ higher degree coefficients if these need to be evaluated. 

The double-double precision Horner steps are implemented the
double-double multiply-and-add macros \MulAddDD~ and \MulAddDdD~ (see
section \ref{sec:double-double-horner}, page
\pageref{sec:double-double-horner}). It is easy to check that the
preconditions on the arguments of these macros are verified: $x^2$ is
bounded by $x^2 \leq \left(2^{-2.434403}\right)^2 \leq 2^{-4}$ in this
path. Further, in the order of the Horner evaluation, the coefficients
$c_i$ of the polynomial are stricly increasing in magnitude and all
less than $1$.  Concerning the accuracy of this operations, see
section \ref{subsec:asinquickphaseaccu}, page
\pageref{subsec:asinquickphaseaccu}.

Including the test $\left \vert x \right \vert \stackrel{?}{\leq} 2^{-10}$, the code computing 
an approximation $t_{5\hi} + t_{5\lo} \approx p_{0\mbox{\tiny ~quick}}\left( x^2 \right)$ reads:
\begin{lstlisting}[caption={Low path quick phase polynomial approximation (higher degrees)},firstnumber=1]
Mul12(&xSqh,&xSql,x,x);

tmp4 = tbl[3];
tmp5 = tbl[4];
t4h = tmp4;
t4l = tmp5;
if (xdb.i[HI] > EXTRABOUND) {
  /* Double precision evaluation */
  highPoly = tbl[15] + xSqh * (tbl[17] + xSqh * (tbl[19] + xSqh * (tbl[21] + xSqh * tbl[23])));

  /* Double-double precision evaluation */
  Mul12(&tt1h,&tt1l,xSqh,highPoly);
  Add22(&t1h,&t1l,tbl[12],tbl[13],tt1h,tt1l);
  
  MulAdd212(&t2h,&t2l,tbl[9],tbl[10],xSqh,t1h,t1l);
  MulAdd212(&t3h,&t3l,tbl[6],tbl[7],xSqh,t2h,t2l);
  MulAdd22(&t4h,&t4l,tmp4,tmp5,xSqh,xSql,t3h,t3l);
}

MulAdd22(&t5h,&t5l,tbl[0],tbl[1],xSqh,xSql,t4h,t4l);
\end{lstlisting}
Once $t_{5\hi} + t_{5\lo}$ are computed, they must be multiplied by
$x^3$ and the result must be added to $x$.  The value $x^3$ is
computed approximatively as a double-double $xCube_\hi + xCube_\lo$ by
multiplying $x$ by $xSq_\hi + xSq_\lo = x^2$. This value $xCube_\hi +
xCube_\lo$ is than multiplied by $t_{5\hi} + t_{5\lo}$, yielding to
$tt_{6\hi} + tt_{6\lo}$. The last addition implying $x$ and $tt_{6\hi}
+ tt_{6\lo}$ is implemented in an ad-hoc way by means of two exact
additions and a double precision addition on the lower part of the
addition of the higher significant parts. The code reads:
\begin{lstlisting}[caption={Low path quick phase polynomial approximation (lower degrees)},firstnumber=1]
Mul122(&xCubeh,&xCubel,x,xSqh,xSql);
Mul22(&tt6h,&tt6l,xCubeh,xCubel,t5h,t5l);

Add12(tmp1,tmp2,x,tt6h);
tmp3 = tmp2 + tt6l;
Add12(polyh,polyl,tmp1,tmp3);
\end{lstlisting} 
The obtained polynomial approximation value is then multiplied by the
sign of $x$ the argument reduction had stripped off and the rounding
test is performed.  If it fails, the accurate phase is launched; see
section \ref{sec:asinacculowpath}, page \pageref{sec:asinacculowpath},
for its implementation.  The code for the last steps in
round-to-nearest mode is given below. The code for the direct rounding
modes is analogous. One remarks that the rounding test constants,
computed by the corresponding Maple scripts in function of the
relative error bounds to be shown in section
\ref{subsec:asinquickphaseaccu}, page
\pageref{subsec:asinquickphaseaccu}, are stored also in double
precision and also read from the main table.
\begin{lstlisting}[caption={Low path quick phase rounding test},firstnumber=1]
/* Multiply by sign */
asinh = sign * polyh;
asinm = sign * polyl;

/* Rounding test 
   The RN rounding constant is at tbl[34]
*/
if(asinh == (asinh + (asinm * tbl[34]))) 
  return asinh;

/* Launch accurate phase */
\end{lstlisting} 

\subsubsection{Middle path - interval $I_i$, $1 \leq i \leq 8$}
In the quick phase middle path, i.e. for arguments $x \in I_i$, $1
\leq i \leq 8$, $\arcsin$ is approximated by the polynomial
$p_{i\mbox{\tiny ~quick}}$ as follows:
$$\arcsin\left( x \right) \approx \arcsin\left( m_i \right) + z_i \cdot p_{i\mbox{\tiny ~quick}}\left( z_i \right)$$
where $z_i = x - m_i$ is a double precision number.  Further an
approximation $asm_{i\hi} + asm_{i\lo}$ to $\arcsin\left( m_i \right)$
is used. It is read in the main table at {\tt tbl[i+1]} and {\tt
  tbl[i+2]} where {\tt i} is the index computed at the interval
discrimination phase.  The polynomial $p_{i\mbox{\tiny ~quick}}$ is of
degree $13$ with $6$ double-double and $8$ double coefficients.  It is
always evaluated completely by means of Horner's scheme. Once again,
the \MulAddDdD~ operator allows for evaluating the $5$ last
double-double steps. The first double-double step is evaluated in a
more ad-hoc way because of the entering only double precision current
intermediate result. The preconditions for the \MulAddDdD~ operator
can again be checked easily: $z_i$ is bounded in magnitude by
$2^{-4.123846}$, the coefficients increase in the order of Horner's
scheme evaluation and are all less than $1$. So in each step, the
product of $z_i$ and the current value is less than $\frac{1}{4}$ the
next coefficient as asked for by the precondition.  The multiplication
of the result of the polynomial $p_{i\mbox{\tiny ~quick}}$ by $z_i$
and the addition of $asm_{i\hi} + asm_{i\lo}$ can also be considered
as a Horner step and are therefore implemented using the \MulAddDdD~
macro, too. 

The corresponding evaluation code reads thus:
\begin{lstlisting}[caption={Middle path quick phase polynomial approximation},firstnumber=1]
highPoly = tbl[i+21] + z * (tbl[i+23] + z * (tbl[i+25] + z * (
           tbl[i+27] + z * (tbl[i+29] + z * (tbl[i+31] + z * ( 
           tbl[i+33] + z *  tbl[i+35]))))));
  
Mul12(&tt1h,&tt1l,z,highPoly);
Add22(&t1h,&t1l,tbl[i+18],tbl[i+19],tt1h,tt1l);

MulAdd212(&t2h,&t2l,tbl[i+15],tbl[i+16],z,t1h,t1l);
MulAdd212(&t3h,&t3l,tbl[i+12],tbl[i+13],z,t2h,t2l);
MulAdd212(&t4h,&t4l,tbl[i+9],tbl[i+10],z,t3h,t3l);
MulAdd212(&t5h,&t5l,tbl[i+6],tbl[i+7],z,t4h,t4l);
MulAdd212(&t6h,&t6l,tbl[i+3],tbl[i+4],z,t5h,t5l);
MulAdd212(&polyh,&polyl,tbl[i+1],tbl[i+2],z,t6h,t6l);
\end{lstlisting} 
One remarks that in this case, since the polynomial evaluation code is
the same for all intervals $I_i$, $1 \leq i \leq 8$, the coefficients
read in the table are not at fixed indices but indexed by {\tt i},
value computed in the interval discrimination phase. 

The result of this approximation whose accuracy will be analysed in
section \ref{subsec:asinquickphaseaccu}, page
\pageref{subsec:asinquickphaseaccu}, is then multiplied by the sign of
the the original argument and submitted to the rounding test whose
rounding constant is read in the main table dependingly on the
interval $I_i$. The corresponding code for round-to-nearest is given
below. The directed rounding cases are analogous.
\begin{lstlisting}[caption={Middle path quick phase rounding test},firstnumber=1]
asinh = sign * polyh;
asinm = sign * polyl;

/* Rounding test 
   The RN rounding constant is at tbl[i+59]
*/
if(asinh == (asinh + (asinm * tbl[i+59]))) 
  return asinh;

/* Launch accurate phase */
\end{lstlisting} 

\subsubsection{High path - interval $I_9$}
In the high path $\arcsin$ is approximated as 
$$\arcsin\left( x \right) \approx p_{9\mbox{\tiny ~quick}}\left( z \right) \cdot \sqrt{2 \cdot z} + \frac{\pi}{2}$$
Herein, $z = 1 - x$ is the exactly computed double precision reduced
argument. The constant $\frac{\pi}{2}$ is approximated by the
double-double number $PiHalf_\hi + PiHalf_\mi = \frac{\pi}{2} \cdot
\left( 1 + \epsilon \right)$ with $\left \vert \epsilon \right \vert
\leq 2^{-109}$. It has already been shown that $z$ and $twoZ = 2 \cdot
z$ can be computed exactly. The square root $\sqrt{2 \cdot z}$ is
approximated in double-double precision using the \SqrtD~ macro
operator described in section \ref{subsection:sqrt}, page
\pageref{subsection:sqrt}. 

The polynomial $p_{9\mbox{\tiny ~quick}}$ has degree $18$ with $9$
double-double and $10$ double precision coefficients. Its constant
term is exactly $-1$, so this coefficient is not stored in the table.
It is always evaluated completely. Horner's scheme is used and
implemented by means of the \MulAddDdD~ operator whose precodnitions
can once again easily be verified by an analogous argument as the one
given above for low and middle paths. 

The corresponding code reads:
\begin{lstlisting}[caption={High path quick phase polynomial approximation},firstnumber=1]
highPoly = tbl[TBLIDX10+24] + z * (tbl[TBLIDX10+26] + z * (tbl[TBLIDX10+28] + z * (
           tbl[TBLIDX10+30] + z * (tbl[TBLIDX10+32] + z * (tbl[TBLIDX10+34] + z * (
           tbl[TBLIDX10+36] + z * (tbl[TBLIDX10+38] + z * (tbl[TBLIDX10+40] + z * 
           tbl[TBLIDX10+42]))))))));

Mul12(&tt1h,&tt1l,z,highPoly);
Add22(&t1h,&t1l,tbl[TBLIDX10+21],tbl[TBLIDX10+22],tt1h,tt1l);

MulAdd212(&t2h,&t2l,tbl[TBLIDX10+18],tbl[TBLIDX10+19],z,t1h,t1l);
MulAdd212(&t3h,&t3l,tbl[TBLIDX10+15],tbl[TBLIDX10+16],z,t2h,t2l);
MulAdd212(&t4h,&t4l,tbl[TBLIDX10+12],tbl[TBLIDX10+13],z,t3h,t3l);
MulAdd212(&t5h,&t5l,tbl[TBLIDX10+9],tbl[TBLIDX10+10],z,t4h,t4l);
MulAdd212(&t6h,&t6l,tbl[TBLIDX10+6],tbl[TBLIDX10+7],z,t5h,t5l);
MulAdd212(&t7h,&t7l,tbl[TBLIDX10+3],tbl[TBLIDX10+4],z,t6h,t6l);
MulAdd212(&t8h,&t8l,tbl[TBLIDX10+0],tbl[TBLIDX10+1],z,t7h,t7l);
MulAdd212(&polyh,&polyl,-1,0,z,t8h,t8l);
\end{lstlisting} 

The result $poly_\hi + poly_\lo$ of the polynomial approximation is
multiplied by $sqrtz_\hi + sqrtz_\lo$, the double-double approximation
of $\sqrt{2 \cdot z}$ by the double-double multiplication
operator \MulDD~ and then added to $PiHalf_\hi + PiHalf_\mi$ using the
double-double addition operator \AddDD. In this addition no
catastrophic cancellation can occur: since $x > 0.78 >
\frac{\sqrt{2}}{2}$ in this interval, the result of the addition, a
good approximation to $\arcsin\left( x \right)$ will always be greater
than $\frac{\pi}{4}$ as per the monotony of arcsine.  So $pTimesS_\hi
+ pTimesS_\lo \approx p_{9\mbox{\tiny ~quick}}\left( z \right) \cdot
\sqrt{2 \cdot z}$ will always be less than $\frac{1}{2} \cdot \left(
  PiHalf_\hi + PiHalf_\mi \right)$. In this argumentation,
approximation errors can be neglected since the bound to be shown is
not tight at all.

The corresponding implementation is the following:
\begin{lstlisting}[caption={High path: square root extraction and reconstruction},firstnumber=1]
twoZ = 2 * z;
sqrt12(&sqrtzh,&sqrtzl,twoZ);                                                         

/* Multiply p(z) by sqrt(2*z) and add Pi/2 */

Mul22(&pTimesSh,&pTimesSl,polyh,polyl,sqrtzh,sqrtzl);                    
Add22(&allh,&alll,PIHALFH,PIHALFM,pTimesSh,pTimesSl);       
\end{lstlisting} 

In this path, too, the obtained result is multiplied by the sign which
had stripped off from the function's argument $x$ and submitted to the
rounding test using a rounding constant read in the main table. The
code reads for round-to-nearest mode:
\begin{lstlisting}[caption={Multiplication of the function's sign, rounding test (round-to-nearest)},firstnumber=1]
asinh = sign * allh;
asinm = sign * alll;

/* Rounding test 
   The RN rounding constant is at tbl[TBLIDX10+54]
*/
if(asinh == (asinh + (asinm * tbl[TBLIDX10+54]))) 
  return asinh;

/* Launch accurate phase */
\end{lstlisting} 
\subsection{Accurate phase polynomial approximation and reconstruction}\label{subsec:asinaccupolynomial}
As already mentioned, in the accurate phase, the polynomials
$p_{i\mbox{\tiny ~accurate}}$ for the different intervals $I_i$ whose
coefficient are stored in the main table, are evaluated completely.
This evaluation is done in double, double-double and triple-double
precision using mainly Horner's scheme.

The accurate phase is implemented in three different {\tt C} functions
corresponding to the low, middle and high paths. These functions
return a triple-double approximate $asin_\hi + asin_\mi + asin_\lo$ to
$\arcsin$ which is accurate enough that the correct rounded result for
$\arcsin$ is obtained when rounding the approximate.  The final
rounding for itself is implemented in the four functions containing
the quick phase code and the call to the accurate phase for the four
possible rounding modes. In round-to-nearest mode, for the high path
the code reads:
\begin{lstlisting}[caption={Final rounding of the accurate phase result (RN)},firstnumber=1]
/* Launch accurate phase */

asin_accurate_higher(&asinh,&asinm,&asinl,z,sign);

ReturnRoundToNearest3(asinh,asinm,asinl); 
\end{lstlisting}
For the other rounding modes and evaluation paths the code is
completely analogous.

\subsubsection{Low path - interval $I_0$\label{sec:asinacculowpath}}
For the low path, the polynomial $p_{0\mbox{\tiny ~accurate}}$
approximates $\arcsin$ as follows:
$$\arcsin\left( x \right) \approx x + x^3 \cdot p_{0\mbox{\tiny ~accurate}}\left( x^2 \right)$$
is of degree $17$ with $7$ double precision coefficients and Horner
steps, $6$ double-double coefficients and steps and $5$ triple-double
coefficients and steps. It reuses the value $xSq_\hi + xSq_\lo = x^2$
which has already been computed in the quick phase. The lower
significant term $xSq_\lo$ is neglected for the first $8$ double
precision (and early double-double precision) steps. The double-double
Horner steps are implemented using the \MulAddDD~ sequence. The
triple-double steps used separate \AddTT~ and \MulTT~ macros. The
value $x^3$ is computed out of $x$ and $x^2$ in triple-double
precision using the \MuldDT~ operator. It is multiplied by the
polynomial's result in triple-double by a \MulTT. The resulting
triple-double is added to $x$ using the \AdddTT~ macro.

In addition to the final renormalization which is needed before
correct rounding to double precision is performed, one intermediate
renormalization is necessary. Otherwise overlap in the triple-double
intermediate values would deteriorate the accuracy to much. See
section \ref{subsec:asinaccuratephaseaccu}, page
\pageref{subsec:asinaccuratephaseaccu} for the overlap bounding.

The code of the low path accurate phase polynomial approximation is
the following:
\begin{lstlisting}[caption={Low path accurate phase polynomial approximation},firstnumber=1]
highPoly = tbl[28] + xSqh * (tbl[29] + xSqh * (tbl[30] + xSqh * (tbl[31] + xSqh * (tbl[32] + xSqh * tbl[33]))));

/* Double-double computations */

Mul12(&tt1h,&tt1l,xSqh,highPoly);
Add22(&t1h,&t1l,tbl[27],0,tt1h,tt1l);

MulAdd22(&t2h,&t2l,tbl[25],tbl[26],xSqh,xSql,t1h,t1l);
MulAdd22(&t3h,&t3l,tbl[23],tbl[24],xSqh,xSql,t2h,t2l);
MulAdd22(&t4h,&t4l,tbl[21],tbl[22],xSqh,xSql,t3h,t3l);
MulAdd22(&t5h,&t5l,tbl[19],tbl[20],xSqh,xSql,t4h,t4l);
MulAdd22(&t6h,&t6l,tbl[17],tbl[18],xSqh,xSql,t5h,t5l);
MulAdd22(&t7h,&t7l,tbl[15],tbl[16],xSqh,xSql,t6h,t6l);

/* Triple-double computations */

Mul23(&tt8h,&tt8m,&tt8l,xSqh,xSql,t7h,t7l);                            
Add33(&t8h,&t8m,&t8l,tbl[12],tbl[13],tbl[14],tt8h,tt8m,tt8l);          
Mul233(&tt9h,&tt9m,&tt9l,xSqh,xSql,t8h,t8m,t8l);                       
Add33(&t9h,&t9m,&t9l,tbl[9],tbl[10],tbl[11],tt9h,tt9m,tt9l);           
Mul233(&tt10h,&tt10m,&tt10l,xSqh,xSql,t9h,t9m,t9l);                    
Add33(&t10h,&t10m,&t10l,tbl[6],tbl[7],tbl[8],tt10h,tt10m,tt10l);       
Mul233(&tt11hover,&tt11mover,&tt11lover,xSqh,xSql,t10h,t10m,t10l);     

Renormalize3(&tt11h,&tt11m,&tt11l,tt11hover,tt11mover,tt11lover);      

Add33(&t11h,&t11m,&t11l,tbl[3],tbl[4],tbl[5],tt11h,tt11m,tt11l);       
Mul233(&tt12h,&tt12m,&tt12l,xSqh,xSql,t11h,t11m,t11l);                 
Add33(&t12h,&t12m,&t12l,tbl[0],tbl[1],tbl[2],tt12h,tt12m,tt12l);       

Mul123(&xCubeh,&xCubem,&xCubel,x,xSqh,xSql);                           

Mul33(&tt13h,&tt13m,&tt13l,xCubeh,xCubem,xCubel,t12h,t12m,t12l);       
Add133(&t13h,&t13m,&t13l,x,tt13h,tt13m,tt13l);                         

Renormalize3(&polyh,&polym,&polyl,t13h,t13m,t13l);                     
*asinh = sign * polyh;
*asinm = sign * polym;
*asinl = sign * polyl;
\end{lstlisting} 

\subsubsection{Middle path - interval $I_i$, $1 \leq i \leq 8$}
For the middle path for $x \in I_i$, $1 \leq i \leq 8$, we use the
following polynomial approximation by $p_{i \mbox{\tiny ~accurate}}$:
$$\arcsin\left( x \right) \approx \left( asm_{i\hi} + asm_{i\lo} \right) + 
z_i \cdot p_{i \mbox{\tiny ~accurate}}\left( z_i\right)$$ where $z_i =
x - m_i$ and $asm_{i\hi} + asm_{i\lo} = \arcsin\left( m_i \right)
\cdot \left( 1 + \epsilon \right)$ with $\left \vert \epsilon \right
\vert \leq 2^{-121}$ by construction of $m_i$. 

The polynomial $p_{i \mbox{\tiny ~accurate}}$ is of degree $34$. In
order of decreasing monomial degrees, its coefficients are stored on
$20$ double precision numbers, $9$ double-double precision numbers and
$6$ triple-double precision numbers. It is completely evaluated using
Horner's scheme using the same intermediate precision for the
computation as the one used for the coefficients. The last
multiplication by $z$ and the addition of $asm_{i\hi} + asm_{i\lo}$
can be considered as an additional Horner step and is of course
performed in triple-double precision.

The double-double precision steps are implemented using the
\MulAddDdD~ macro. The triple-double steps use separate addition and
multiplication operators. In particular, \AddTT~ and \MuldTT~ come at
hand. Overall, two triple-double renormalizations are necessary: one
before final rounding can be performed and one other for avoiding a
too great overlap in the components of the intermediate triple-double
values. See section \ref{subsec:asinaccuratephaseaccu}, page
\pageref{subsec:asinaccuratephaseaccu} for the overlap bounding.

The coefficients of the polynomial $p_{i \mbox{\tiny ~accurate}}$ and
the value $asm_{i\hi} + asm_{i\lo}$ are read in the main table using
the index {\tt i} computated at the interval discrimination phase. The
reduced argument $z_i$ has already been computed exactly at the quick
phase and can be reused.

The implementation of the accurate phase middle path polynomial approximation reads:
\begin{lstlisting}[caption={Middle path accurate phase polynomial approximation},firstnumber=1]
highPoly = tbl[i+39] + z * (tbl[i+40] + z * (tbl[i+41] + z * (tbl[i+42] + z * (
           tbl[i+43] + z * (tbl[i+44] + z * (tbl[i+45] + z * (tbl[i+46] + z * (
           tbl[i+47] + z * (tbl[i+48] + z * (tbl[i+49] + z * (tbl[i+50] + z * (
           tbl[i+51] + z * (tbl[i+52] + z * (tbl[i+53] + z * (tbl[i+54] + z * (
           tbl[i+55] + z * (tbl[i+56] + z * (tbl[i+57] + z * tbl[i+58]))))))))))))))))));


/* Double-double computations */

Mul12(&tt1h,&tt1l,z,highPoly);
Add22(&t1h,&t1l,tbl[i+37],tbl[i+38],tt1h,tt1l);

MulAdd212(&t2h,&t2l,tbl[i+35],tbl[i+36],z,t1h,t1l);
MulAdd212(&t3h,&t3l,tbl[i+33],tbl[i+34],z,t2h,t2l);
MulAdd212(&t4h,&t4l,tbl[i+31],tbl[i+32],z,t3h,t3l);
MulAdd212(&t5h,&t5l,tbl[i+29],tbl[i+30],z,t4h,t4l);
MulAdd212(&t6h,&t6l,tbl[i+27],tbl[i+28],z,t5h,t5l);
MulAdd212(&t7h,&t7l,tbl[i+25],tbl[i+26],z,t6h,t6l);
MulAdd212(&t8h,&t8l,tbl[i+23],tbl[i+24],z,t7h,t7l);
MulAdd212(&t9h,&t9l,tbl[i+21],tbl[i+22],z,t8h,t8l);

/* Triple-double computations */

Mul123(&tt10h,&tt10m,&tt10l,z,t9h,t9l);                                    
Add33(&t10h,&t10m,&t10l,tbl[i+18],tbl[i+19],tbl[i+20],tt10h,tt10m,tt10l);  
Mul133(&tt11h,&tt11m,&tt11l,z,t10h,t10m,t10l);                             
Add33(&t11h,&t11m,&t11l,tbl[i+15],tbl[i+16],tbl[i+17],tt11h,tt11m,tt11l);  
Mul133(&tt12h,&tt12m,&tt12l,z,t11h,t11m,t11l);                             
Add33(&t12h,&t12m,&t12l,tbl[i+12],tbl[i+13],tbl[i+14],tt12h,tt12m,tt12l);  
Mul133(&tt13hover,&tt13mover,&tt13lover,z,t12h,t12m,t12l);                 

Renormalize3(&tt13h,&tt13m,&tt13l,tt13hover,tt13mover,tt13lover);          

Add33(&t13h,&t13m,&t13l,tbl[i+9],tbl[i+10],tbl[i+11],tt13h,tt13m,tt13l);   
Mul133(&tt14h,&tt14m,&tt14l,z,t13h,t13m,t13l);                             
Add33(&t14h,&t14m,&t14l,tbl[i+6],tbl[i+7],tbl[i+8],tt14h,tt14m,tt14l);     
Mul133(&tt15h,&tt15m,&tt15l,z,t14h,t14m,t14l);                             
Add33(&t15h,&t15m,&t15l,tbl[i+3],tbl[i+4],tbl[i+5],tt15h,tt15m,tt15l);     
Mul133(&tt16h,&tt16m,&tt16l,z,t15h,t15m,t15l);                             
Add233(&t16h,&t16m,&t16l,tbl[i+1],tbl[i+2],tt16h,tt16m,tt16l);             

Renormalize3(&polyh,&polym,&polyl,t16h,t16m,t16l);                         
*asinh = sign * polyh;
*asinm = sign * polym;
*asinl = sign * polyl;
\end{lstlisting} 

\subsubsection{High path - interval $I_9$}
On the high path interval $I_9$, computing the approximation for
$\arcsin$ means evaluating the polynomial $p_{9 \mbox{\tiny~accurate}}\left( z \right)$ 
and calculating a triple-double approximation to $\sqrt{2 \cdot z}$ 
where $z$ is the reduced argument. The function can then be 
reconstructed as follows:
$$\arcsin\left( x \right) \approx p_{9 \mbox{\tiny~accurate}}\left( z \right) \cdot \sqrt{2\cdot z} + 
\left( PiHalf_\hi + PiHalf_\mi + PiHalf_\lo \right)$$ where
$PiHalf_\hi + PiHalf_\mi + PiHalf_\lo = \frac{\pi}{2} \cdot \left( 1 +
  \epsilon \right)$, $\left \vert \epsilon \right \vert \leq 2^{-164}$

The polynomial $p_{9 \mbox{\tiny~accurate}}\left( z \right)$ is of
degree $28$ with $12$ double precision, $9$ double-double precision
and $8$ triple-double precision coefficients. The intermediate
precisions used correspond to the precision the coefficients are
stored in. The polynomial is completely evaluated in Horner's scheme.
Once again, for doing so, the \MulAddDdD~ macro is used for the
double-double steps whilst the triple-double stage is implemented by
means of separate additions and multiplications mainly expressed with
\AddTT~ and \MuldTT~ operators. 

The square root extraction yielding to the triple-double approximate
$sqrtz_\hi + sqrtz_\mi + sqrtz_\lo = \sqrt{2 \cdot z } \cdot
\left( 1 + \epsilon \right)$ is implemented using the \SqrtT~ macro.
Unfortunately, this means recomputing some steps of the square root
extraction already computed in the quick phase in the \SqrtD~ macro.
The choice made is motivated by implementatory reasons.

The multiplication of the polynomial's value and of the square root is
performed in triple-double precision by means of the \MulTT~ macro.
The following addition with the triple-double approximate of
$\frac{\pi}{2}$ is implemented using the \AddTT~ operator. 

Overall, three renormalizations are needed. One of them renormalizes
the final result, two allow for sufficient overlap bounding. Remark
that the square root extraction by \SqrtT~ comprises an additional
renormalization; see section \ref{subsection:sqrt}, page
\pageref{subsection:sqrt} for further details.  The overlap bounds
will be given in section \ref{subsec:asinaccuratephaseaccu}, page
\pageref{subsec:asinaccuratephaseaccu}.

The code implementing this accurate phase path is the following:
\begin{lstlisting}[caption={High path accurate phase polynomial approximation},firstnumber=1]
highPoly = tbl[TBLIDX10+42] + z * (tbl[TBLIDX10+43] + z * (tbl[TBLIDX10+44] + z * (
           tbl[TBLIDX10+45] + z * (tbl[TBLIDX10+46] + z * (tbl[TBLIDX10+47] + z * (
           tbl[TBLIDX10+48] + z * (tbl[TBLIDX10+49] + z * (tbl[TBLIDX10+50] + z * (
           tbl[TBLIDX10+51] + z * (tbl[TBLIDX10+52] + z *  tbl[TBLIDX10+53]))))))))));

/* Double-double computations */

Mul12(&tt1h,&tt1l,z,highPoly);
Add22(&t1h,&t1l,tbl[TBLIDX10+40],tbl[TBLIDX10+41],tt1h,tt1l);

MulAdd212(&t2h,&t2l,tbl[TBLIDX10+38],tbl[TBLIDX10+39],z,t1h,t1l);
MulAdd212(&t3h,&t3l,tbl[TBLIDX10+36],tbl[TBLIDX10+37],z,t2h,t2l);
MulAdd212(&t4h,&t4l,tbl[TBLIDX10+34],tbl[TBLIDX10+35],z,t3h,t3l);
MulAdd212(&t5h,&t5l,tbl[TBLIDX10+32],tbl[TBLIDX10+33],z,t4h,t4l);
MulAdd212(&t6h,&t6l,tbl[TBLIDX10+30],tbl[TBLIDX10+31],z,t5h,t5l);
MulAdd212(&t7h,&t7l,tbl[TBLIDX10+28],tbl[TBLIDX10+29],z,t6h,t6l);
MulAdd212(&t8h,&t8l,tbl[TBLIDX10+26],tbl[TBLIDX10+27],z,t7h,t7l);
MulAdd212(&t9h,&t9l,tbl[TBLIDX10+24],tbl[TBLIDX10+25],z,t8h,t8l);

/* Triple-double computations */

Mul123(&tt10h,&tt10m,&tt10l,z,t9h,t9l);                                                        
Add33(&t10h,&t10m,&t10l,tbl[TBLIDX10+21],tbl[TBLIDX10+22],tbl[TBLIDX10+23],tt10h,tt10m,tt10l); 
Mul133(&tt11h,&tt11m,&tt11l,z,t10h,t10m,t10l);                                                 
Add33(&t11h,&t11m,&t11l,tbl[TBLIDX10+18],tbl[TBLIDX10+19],tbl[TBLIDX10+20],tt11h,tt11m,tt11l); 
Mul133(&tt12h,&tt12m,&tt12l,z,t11h,t11m,t11l);                                                 
Add33(&t12h,&t12m,&t12l,tbl[TBLIDX10+15],tbl[TBLIDX10+16],tbl[TBLIDX10+17],tt12h,tt12m,tt12l); 
Mul133(&tt13h,&tt13m,&tt13l,z,t12h,t12m,t12l);                                                 
Add33(&t13hover,&t13mover,&t13lover,
                        tbl[TBLIDX10+12],tbl[TBLIDX10+13],tbl[TBLIDX10+14],tt13h,tt13m,tt13l); 

Renormalize3(&t13h,&t13m,&t13l,t13hover,t13mover,t13lover);                                    

Mul133(&tt14h,&tt14m,&tt14l,z,t13h,t13m,t13l);                                                 
Add33(&t14h,&t14m,&t14l,tbl[TBLIDX10+9],tbl[TBLIDX10+10],tbl[TBLIDX10+11],tt14h,tt14m,tt14l);  
Mul133(&tt15h,&tt15m,&tt15l,z,t14h,t14m,t14l);                                                 
Add33(&t15h,&t15m,&t15l,tbl[TBLIDX10+6],tbl[TBLIDX10+7],tbl[TBLIDX10+8],tt15h,tt15m,tt15l);    
Mul133(&tt16h,&tt16m,&tt16l,z,t15h,t15m,t15l);                                                 
Add33(&t16h,&t16m,&t16l,tbl[TBLIDX10+3],tbl[TBLIDX10+4],tbl[TBLIDX10+5],tt16h,tt16m,tt16l);     
Mul133(&tt17hover,&tt17mover,&tt17lover,z,t16h,t16m,t16l);                                     

Renormalize3(&tt17h,&tt17m,&tt17l,tt17hover,tt17mover,tt17lover);                              

Add33(&t17h,&t17m,&t17l,tbl[TBLIDX10+0],tbl[TBLIDX10+1],tbl[TBLIDX10+2],tt17h,tt17m,tt17l);    

Mul133(&tt18h,&tt18m,&tt18l,z,t17h,t17m,t17l);                                                 
Add133(&polyh,&polym,&polyl,-1,tt18h,tt18m,tt18l);                                             

/* Compute sqrt(2*z) as a triple-double */

twoZ = 2 * z;
sqrt13(&sqrtzh,&sqrtzm,&sqrtzl,twoZ);                                                           

/* Multiply p(z) by sqrt(2*z) and add Pi/2 */

Mul33(&pTimesSh,&pTimesSm,&pTimesSl,polyh,polym,polyl,sqrtzh,sqrtzm,sqrtzl);                    
Add33(&allhover,&allmover,&alllover,PIHALFH,PIHALFM,PIHALFL,pTimesSh,pTimesSm,pTimesSl);        

/* Renormalize and multiply by sign */
Renormalize3(&allh,&allm,&alll,allhover,allmover,alllover);                                     
*asinh = sign * allh;
*asinm = sign * allm;
*asinl = sign * alll;
\end{lstlisting} 

\section{Accuracy bounds}\label{sec:asinaccuracy}

\subsection{Quick phase accuracy}\label{subsec:asinquickphaseaccu}

TODO: see possibly available Gappa files meanwhile


\subsection{Accurate phase accuracy}\label{subsec:asinaccuratephaseaccu}

TODO: see possibly available Gappa files meanwhile


\section{Timings and memory consumption}\label{sec:asintimingmemory}
The given implementation of the arcsine uses tables and constants that
consume 4740 bytes of memory. This values are fully shared between
quick and accurate phase. The code size, including the tables, is
about 22 kbytes when compiled to PowerPC machine code. The quick phase
code for one rounding mode needs about 1.5 kbytes without the table.
This means that there are about 12 kbytes of code for the accurate
phase, which is shared between all rounding modes.

Concerning the timing, we compare our implementation to IBM's {\tt
  libultim} and to MPFR. The values are given in arbitrary units and
obtained on a IBM Power 5 processor with gcc 3.3.3 on a Linux Kernel
2.6.5. The timings on other systems are comparable.
\begin{center}
\begin{tabular}{|l|r|r|}
 \hline
  Library                       &     avg time  & max time \\
 \hline
 \hline
 \texttt{MPFR}   &   6322    & 83415        \\ 
 \hline
 \texttt{crlibm} portable using triple-double      &        45    & 300        \\ 
 \hline
 default \texttt{libm} (IBM's {\tt libultim})  &        23    & 206239      \\ 
 \hline
\end{tabular}
\end{center}
It is worth mentioning that IBM's library uses about 20 kbytes of
tables for its mere quick phase.

%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "crlibm" 
%%% End: 
