\par
\subsection{{\tt DV} : {\tt double} vector methods}
\label{subsection:Utilities:proto:DV}
\par
%=======================================================================
\begin{enumerate}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double * DVinit ( int n, double val ) ;
\end{verbatim}
\index{DVinit@{\tt DVinit()}}
This is the allocator and initializer method for {\tt double} vectors.
Storage for an array with size {\tt n} is found and each
entry is filled with {\tt val}.
A pointer to the array is returned.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double * DVinit2 ( int n ) ;
\end{verbatim}
\index{DVinit2@{\tt DVinit2()}}
This is an allocator method for {\tt double} vectors.
Storage for an array with size {\tt n} is found.
A pointer to the array is returned.
Note, on return, there will likely be garbage in the array.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVfree ( int vec[] ) ;
\end{verbatim}
\index{DVfree@{\tt DVfree()}}
This method releases the storage taken by {\tt vec[]}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVfprintf ( FILE *fp, int n, double y[] ) ;
\end{verbatim}
\index{DVfprintf@{\tt DVfprintf()}}
This method prints {\tt n} entries in {\tt y[]} to file {\tt fp}.
The format is new line followed by lines of six {\tt double}'s in
{\tt "\%12.4e"} format.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DVfscanf ( FILE *fp, int n, double y[] ) ;
\end{verbatim}
\index{DVfscanf@{\tt DVfscanf()}}
This method scans in {\tt double}'s from file {\tt fp} and places them
in the array {\tt y[]}.
It tries to read in {\tt n} {\tt double}'s, and returns the number
that were actually read.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVadd ( int n, double y[], double x[] ) ;
\end{verbatim}
\index{DVadd@{\tt DVadd()}}
This method adds {\tt n} entries from {\tt x[]} to {\tt y[]},
i.e.,
{\tt y[i] += x[i]} for {\tt 0 <= i < n}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVaxpy ( int n, double y[], double alpha, double x[] ) ;
\end{verbatim}
\index{DVaxpy@{\tt DVaxpy()}}
This method adds a scaled multiple of {\tt n} entries from {\tt x[]}
into {\tt y[]},
i.e.,
{\tt y[i] += alpha * x[i]} for {\tt 0 <= i < n}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVaxpy2 ( int n, double z[], double a, double x[],
               double b, double y[] ) ;
\end{verbatim}
\index{DVaxpy@{\tt DVaxpy()}}
This method adds a scaled multiple of two vectors {\tt x[]}
and {\tt y[]} to another vector {\tt z[]}, i.e.,
i.e.,
{\tt z[i] += a * x[i] + b * y[i]} for {\tt 0 <= i < n}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVaxpy33 ( int n, double y0[], double y1[], double y2[],
                double alpha, double x0[], double x1[], double x2[] ) ;
\end{verbatim}
\index{DVaxpy33@{\tt DVaxpy33()}}
This method computes this computation.
\begin{verbatim}
y0[] = y0[] + alpha[0] * x0[] + alpha[1] * x1[] + alpha[2] * x2[]
y1[] = y1[] + alpha[3] * x0[] + alpha[4] * x1[] + alpha[5] * x2[]
y2[] = y2[] + alpha[6] * x0[] + alpha[7] * x1[] + alpha[8] * x2[]
\end{verbatim}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVaxpy32 ( int n, double y0[], double y1[], double y2[],
                double alpha, double x0[], double x1[] ) ;
\end{verbatim}
\index{DVaxpy32@{\tt DVaxpy32()}}
This method computes this computation.
\begin{verbatim}
y0[] = y0[] + alpha[0] * x0[] + alpha[1] * x1[]
y1[] = y1[] + alpha[2] * x0[] + alpha[3] * x1[]
y2[] = y2[] + alpha[4] * x0[] + alpha[5] * x1[]
\end{verbatim}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVaxpy31 ( int n, double y0[], double y1[], double y2[],
                double alpha, double x0[], double x1[] ) ;
\end{verbatim}
\index{DVaxpy31@{\tt DVaxpy31()}}
This method computes this computation.
\begin{verbatim}
y0[] = y0[] + alpha[0] * x0[]
y1[] = y1[] + alpha[1] * x0[]
y2[] = y2[] + alpha[2] * x0[]
\end{verbatim}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVaxpy23 ( int n, double y0[], double y1[],
                double alpha, double x0[], double x1[], double x2[] ) ;
\end{verbatim}
\index{DVaxpy23@{\tt DVaxpy23()}}
This method computes this computation.
\begin{verbatim}
y0[] = y0[] + alpha[0] * x0[] + alpha[1] * x1[] + alpha[2] * x2[]
y1[] = y1[] + alpha[3] * x0[] + alpha[4] * x1[] + alpha[5] * x2[]
\end{verbatim}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVaxpy22 ( int n, double y0[], double y1[],
                double alpha, double x0[], double x1[] ) ;
\end{verbatim}
\index{DVaxpy22@{\tt DVaxpy22()}}
This method computes this computation.
\begin{verbatim}
y0[] = y0[] + alpha[0] * x0[] + alpha[1] * x1[]
y1[] = y1[] + alpha[2] * x0[] + alpha[3] * x1[]
\end{verbatim}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVaxpy21 ( int n, double y0[], double y1[], double alpha, double x0[] ) ;
\end{verbatim}
\index{DVaxpy21@{\tt DVaxpy21()}}
This method computes this computation.
\begin{verbatim}
y0[] = y0[] + alpha[0] * x0[]
y1[] = y1[] + alpha[1] * x0[]
\end{verbatim}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVaxpy13 ( int n, double y0[],
                double alpha, double x0[], double x1[], double x2[] ) ;
\end{verbatim}
\index{DVaxpy13@{\tt DVaxpy13()}}
This method computes this computation.
\begin{verbatim}
y0[] = y0[] + alpha[0] * x0[] + alpha[1] * x1[] + alpha[2] * x2[]
\end{verbatim}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVaxpy12 ( int n, double y0[], double alpha, double x0[], double x1[] ) ;
\end{verbatim}
\index{DVaxpy12@{\tt DVaxpy12()}}
This method computes this computation.
\begin{verbatim}
y0[] = y0[] + alpha[0] * x0[] + alpha[1] * x1[]
\end{verbatim}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVaxpy11 ( int n, double y0[], double alpha, double x0[] ) ;
\end{verbatim}
\index{DVaxpy11@{\tt DVaxpy11()}}
This method computes this computation.
\begin{verbatim}
y0[] = y0[] + alpha[0] * x0[]
\end{verbatim}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVaxpyi ( int n, double y[], int index[], double alpha, double x[] ) ;
\end{verbatim}
\index{DVaxpyi@{\tt DVaxpyi()}}
This method scatteradds
a scaled multiple of {\tt n} entries from {\tt x[]}
into {\tt y[]},
i.e.,
{\tt y[index[i]] += alpha * x[i]} for {\tt 0 <= i < n}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVcompress ( int n1, double x1[], double y1[],
                  int n2, double x2[], double y2[] ) ;
\end{verbatim}
\index{DVcompress@{\tt DVcompress()}}
Given a pair of arrays {\tt x1[n1]} and {\tt y1[n1]},
fill {\tt x2[n2]} and {\tt y2[n2]} with a subset of the
{\tt (x1[j],y1[j]} entries whose distribution is an approximation.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVcopy ( int n, double y[], double x[] ) ;
\end{verbatim}
\index{DVcopy@{\tt DVcopy()}}
This method copies {\tt n} entries from {\tt x[]} to {\tt y[]},
i.e.,
{\tt y[i] = x[i]} for {\tt 0 <= i < n}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DVdot ( int n, double y[], double x[] ) ;
\end{verbatim}
\index{DVdot@{\tt DVdot()}}
This method returns the dot product of the vector {\tt x[]} and
{\tt y[]},
i.e., return
$\sum_{\tt i = 0}^{\tt n-1} ({\tt x[i] * y[i]})$.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DVdot33 ( int n, double row0[], double row1[], double row2[],
              double col0[], double col1[], double col2[], double sums[] ) ;
\end{verbatim}
\index{DVdot33@{\tt DVdot33()}}
This method computes nine dot products.
\par
\begin{tabular}{lll}
$\displaystyle{\tt sums[0]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row0[i] * col0[i]}$ &
$\displaystyle{\tt sums[1]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row0[i] * col1[i]}$ &
$\displaystyle{\tt sums[2]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row0[i] * col2[i]}$ \\
$\displaystyle{\tt sums[3]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row1[i] * col0[i]}$ &
$\displaystyle{\tt sums[4]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row1[i] * col1[i]}$ &
$\displaystyle{\tt sums[5]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row1[i] * col2[i]}$ \\
$\displaystyle{\tt sums[6]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row2[i] * col0[i]}$ &
$\displaystyle{\tt sums[7]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row2[i] * col1[i]}$ &
$\displaystyle{\tt sums[8]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row2[i] * col2[i]}$
\end{tabular}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DVdot32 ( int n, double row0[], double row1[], double row2[],
              double col0[], double col1[], double sums[] ) ;
\end{verbatim}
\index{DVdot32@{\tt DVdot32()}}
This method computes six dot products.
\par
\begin{tabular}{ll}
$\displaystyle{\tt sums[0]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row0[i] * col0[i]}$ &
$\displaystyle{\tt sums[1]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row0[i] * col1[i]}$ \\
$\displaystyle{\tt sums[2]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row1[i] * col0[i]}$ &
$\displaystyle{\tt sums[3]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row1[i] * col1[i]}$ \\
$\displaystyle{\tt sums[4]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row2[i] * col0[i]}$ &
$\displaystyle{\tt sums[5]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row2[i] * col1[i]}$
\end{tabular}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DVdot31 ( int n, double row0[], double row1[], double row2[],
              double col0[], double sums[] ) ;
\end{verbatim}
\index{DVdot31@{\tt DVdot31()}}
This method computes three dot products.
\par
\begin{tabular}{l}
$\displaystyle{\tt sums[0]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row0[i] * col0[i]}$ \\
$\displaystyle{\tt sums[1]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row1[i] * col0[i]}$ \\
$\displaystyle{\tt sums[2]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row2[i] * col0[i]}$
\end{tabular}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DVdot23 ( int n, double row0[], double row1[],
              double col0[], double col1[], double col2[], double sums[] ) ;
\end{verbatim}
\index{DVdot23@{\tt DVdot23()}}
This method computes six dot products.
\par
\begin{tabular}{lll}
$\displaystyle{\tt sums[0]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row0[i] * col0[i]}$ &
$\displaystyle{\tt sums[1]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row0[i] * col1[i]}$ &
$\displaystyle{\tt sums[2]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row0[i] * col2[i]}$ \\
$\displaystyle{\tt sums[3]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row1[i] * col0[i]}$ &
$\displaystyle{\tt sums[4]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row1[i] * col1[i]}$ &
$\displaystyle{\tt sums[5]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row1[i] * col2[i]}$
\end{tabular}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DVdot22 ( int n, double row0[], double row1[],
              double col0[], double col1[], double sums[] ) ;
\end{verbatim}
\index{DVdot22@{\tt DVdot22()}}
This method computes four dot products.
\par
\begin{tabular}{ll}
$\displaystyle{\tt sums[0]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row0[i] * col0[i]}$ &
$\displaystyle{\tt sums[1]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row0[i] * col1[i]}$ \\
$\displaystyle{\tt sums[2]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row1[i] * col0[i]}$ &
$\displaystyle{\tt sums[3]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row1[i] * col1[i]}$
\end{tabular}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DVdot21 ( int n, double row0[], double row1[],
              double col0[], double sums[] ) ;
\end{verbatim}
\index{DVdot21@{\tt DVdot21()}}
This method computes two dot products.
\par
\begin{tabular}{l}
$\displaystyle{\tt sums[0]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row0[i] * col0[i]}$ \\
$\displaystyle{\tt sums[1]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row1[i] * col0[i]}$
\end{tabular}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DVdot13 ( int n, double row0[],
              double col0[], double col1[], double col2[], double sums[] ) ;
\end{verbatim}
\index{DVdot13@{\tt DVdot13()}}
This method computes six dot products.
\par
\begin{tabular}{lll}
$\displaystyle{\tt sums[0]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row0[i] * col0[i]}$ &
$\displaystyle{\tt sums[1]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row0[i] * col1[i]}$ &
$\displaystyle{\tt sums[2]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row0[i] * col2[i]}$
\end{tabular}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DVdot12 ( int n, double row0[], double row1[],
              double col0[], double col1[], double sums[] ) ;
\end{verbatim}
\index{DVdot12@{\tt DVdot12()}}
This method computes two dot products.
\par
\begin{tabular}{ll}
$\displaystyle{\tt sums[0]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row0[i] * col0[i]}$ &
$\displaystyle{\tt sums[1]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row0[i] * col1[i]}$
\end{tabular}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DVdot11 ( int n, double row0[], double col0[], double sums[] ) ;
\end{verbatim}
\index{DVdot11@{\tt DVdot11()}}
This method computes one dot product.
\par
\begin{tabular}{l}
$\displaystyle{\tt sums[0]}
               = \sum_{\tt i = 0}^{\tt n-1} {\tt row0[i] * col0[i]}$
\end{tabular}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
int DVdoti ( int n, double y[], int index[], double x[] ) ;
\end{verbatim}
\index{DVdoti@{\tt DVdoti()}}
This method returns the indexed dot product
$\displaystyle \sum_{{\tt i=0}}^{{\tt n-1}} {\tt y[index[i]] * x[i]}$.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVfill ( int n, double y[], double val ) ;
\end{verbatim}
\index{DVfill@{\tt DVfill()}}
This method fills {\tt n} entries in {\tt y[]} with {\tt val},
i.e.,
{\tt y[i] = val} for {\tt 0 <= i < n}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVgather ( int n, double y[], double x[], int index[] ) ;
\end{verbatim}
\index{DVgather@{\tt DVgather()}}
{\tt y[i] = x[index[i]]} for {\tt 0 <= i < n}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVgatherAddZero ( int n, double y[], double x[], int index[] ) ;
\end{verbatim}
\index{DVgatherAddZero@{\tt DVgatherAddZero()}}
{\tt y[i] += x[index[i]]} and
{\tt x[index[i]] = 0}
for {\tt 0 <= i < n}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVgatherZero ( int n, double y[], double x[], int index[] ) ;
\end{verbatim}
\index{DVgatherZero@{\tt DVgatherZero()}}
{\tt y[i] = x[index[i]]} and
{\tt x[index[i]] = 0}
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVinvPerm ( int n, double y[], int index[] ) ;
\end{verbatim}
\index{DVinvPerm@{\tt DVinvPerm()}}
This method permutes the vector y as follows.
i.e.,
{\tt y[index[i]] := y[i]}.
See {\tt DVperm()} for a similar function.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double DVmax ( int n, double y[], int *ploc ) ;
\end{verbatim}
\index{DVmax@{\tt DVmax()}}
This method returns the maximum entry in {\tt y[0:n-1]}
and puts the first location where it was found into the address
{\tt ploc}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double DVmaxabs ( int n, double y[], int *ploc ) ;
\end{verbatim}
\index{DVmaxabs@{\tt DVmaxabs()}}
This method returns the maximum magnitude of entries in
{\tt y[0:n-1]} and puts the first location where
it was found into the address {\tt ploc}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double DVmin ( int n, double y[], int *ploc ) ;
\end{verbatim}
\index{DVmin@{\tt DVmin()}}
This method returns the minimum entry in {\tt y[0:n-1]}
and puts the first location where it was found into the address
{\tt ploc}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double DVminabs ( int n, double y[], int *ploc ) ;
\end{verbatim}
\index{DVminabs@{\tt DVminabs()}}
This method returns the minimum magnitude of entries in
{\tt y[0:n-1]} and puts the first location where
it was found into the address {\tt ploc}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVperm ( int n, double y[], int index[] ) ;
\end{verbatim}
\index{DVperm@{\tt DVperm()}}
This method permutes the vector y as follows.
i.e.,
{\tt y[i] := y[index[i]]}.
See {\tt DVinvPerm()} for a similar function.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVramp ( int n, double y[], double start, double inc ) ;
\end{verbatim}
\index{DVramp@{\tt DVramp()}}
This method fills {\tt n} entries in {\tt y[]} with
values
{\tt start},
{\tt start + inc},
{\tt start + 2*inc},
{\tt start + 3*inc}, etc.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVscale ( int n, double y[], double alpha ) ;
\end{verbatim}
\index{DVscale@{\tt DVscale()}}
This method scales a vector {\tt y[]} by {\tt alpha},
i.e.,
{\tt y[i] *= alpha}.
for {\tt 0 <= i < n}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVscale2 ( int n, double x[], double y[],
                double a, double b, double c, double d ) ;
\end{verbatim}
\index{DVscale@{\tt DVscale()}}
This method scales two vectors {\tt y[]} by a $2 \times 2$ matrix,
i.e.,
$$
\left \lbrack \begin{array}{ccc}
{\tt x[0]} & \ldots & {\tt x[n-1]} \\
{\tt y[0]} & \ldots & {\tt y[n-1]}
\end{array} \right \rbrack
:=
\left \lbrack \begin{array}{cc}
{\tt a} & {\tt b} \\
{\tt c} & {\tt d}
\end{array} \right \rbrack
\left \lbrack \begin{array}{ccc}
{\tt x[0]} & \ldots & {\tt x[n-1]} \\
{\tt y[0]} & \ldots & {\tt y[n-1]}
\end{array} \right \rbrack.
$$
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVscatter ( int n, double y[], int index[], double x[] ) ;
\end{verbatim}
\index{DVscatter@{\tt DVscatter()}}
This method scatters {\tt n} entries of {\tt x[]} into {\tt y[]}
as follows,
{\tt y[index[i]] = x[i]}
for {\tt 0 <= i < n}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVscatterAdd ( int n, double y[], int index[], double x[] ) ;
\end{verbatim}
\index{DVscatterAdd@{\tt DVscatterAdd()}}
This method scatters/adds {\tt n} entries of {\tt x[]} into {\tt y[]}
as follows,
{\tt y[index[i]] += x[i]}
for {\tt 0 <= i < n}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVscatterAddZero ( int n, double y[], int index[], double x[] ) ;
\end{verbatim}
\index{DVscatterAddZero@{\tt DVscatterAddZero()}}
This method scatters/adds {\tt n} entries of {\tt x[]} into {\tt y[]}
as follows,
{\tt y[index[i]] += x[i]}
for {\tt 0 <= i < n},
and then zeros the entries in {\tt x[*]}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVscatterZero ( int n, double y[], int index[], double x[] ) ;
\end{verbatim}
\index{DVscatterZero@{\tt DVscatterZero()}}
This method scatters {\tt n} entries of {\tt x[]} into {\tt y[]}
as follows,
{\tt y[index[i]] = x[i]}
for {\tt 0 <= i < n}
and then zeros the entries in {\tt x[*]}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVsub ( int n, double y[], double x[] ) ;
\end{verbatim}
\index{DVsub@{\tt DVsub()}}
This method subtracts {\tt n} entries from {\tt x[]} to {\tt y[]},
i.e.,
{\tt y[i] -= x[i]}
for {\tt 0 <= i < n}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double DVsum ( int n, double y[] ) ;
\end{verbatim}
\index{DVsum@{\tt DVsum()}}
This method returns the sum of the first {\tt n} entries
in the vector {\tt x[]},
i.e., return
$\sum_{\tt i = 0}^{\tt n-1} {\tt x[i]}$.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
double DVsumabs ( int n, double y[] ) ;
\end{verbatim}
\index{DVsumabs@{\tt DVsumabs()}}
This method returns the sum of the absolute values of the
first {\tt n} entries in the vector {\tt x[]},
i.e., return
$\sum_{\tt i = 0}^{\tt n-1} {\tt abs(x[i])}$.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVswap ( int n, double y[], double x[] ) ;
\end{verbatim}
\index{DVswap@{\tt DVswap()}}
This method swaps the {\tt x[]} and {\tt y[]} vectors as follows.
i.e.,
{\tt y[i] := x[i]} and
{\tt x[i] := y[i]}
for {\tt 0 <= i < n}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVzero ( int n, double y[] ) ;
\end{verbatim}
\index{DVzero@{\tt DVzero()}}
This method zeroes {\tt n} entries in {\tt y[]},
i.e.,
{\tt y[i] = 0}
for {\tt 0 <= i < n}.
%-----------------------------------------------------------------------
\item
\begin{verbatim}
void DVshuffle ( int n, double y[], int seed ) ;
\end{verbatim}
\index{DVshuffle@{\tt DVshuffle()}}
This method shuffles the first {\tt n} entries in {\tt y[]}.
The value {\tt seed} is the seed to a random number generator,
and one can get repeatable behavior by repeating {\tt seed}.
%-----------------------------------------------------------------------
\end{enumerate}


\section{Specification of $\lambda_Q$} \label{spec}

In this section we give the language specification of $\lambda_Q$, including the syntax, typing rules and syntactic sugars.
The syntax and typing rules of the quantum circuit are similar to Qwire \cite{qwire}.
The operational semantics are not given in this section.
Instead, we give a transformation from $\lambda_Q$ to $QASM$ in the section of frontend, which gives semantics to each syntax of $\lambda_Q$.
Interested readers can refer to the operational semantics of simply-typed $\lambda$-calculus and Qwire.

\subsection{Syntax}
The syntax of the traditional part (terms, values, types) is an extended version of simply-typed $\lambda$-calcus with $\trun\ C$ and $\kappa \ p:W . C$, which are used to interact with the quantum part.
The syntax of the quantum part (circuits, wire types, wire patterns, gates, gate types) is similar to the syntax of Qwire.
% \mycomment{twh}{modify syntax (especially gate)}

\begin{longtable}[c]{lclr}
  % \caption{syntax}
  \label{tab:table1}\\
  \toprule
  $t$ &$::=$ &  &\textbf{terms}: \\
      & &$x$ &variable\\
      & &$\unit$ &constant unit\\
      & &$\true$ &constant true\\
      & &$\false$ &constant false\\
      & &$\lambda\ x:T.t$ &function abstraction\\
      & &$t\ t$ &function application\\
      & &$(t, t)$ &pair\\
      & &$t.1$ &first projection\\
      & &$t.2$ &second projection\\
      & &$\tif\ t\ \tthen\ t\ \telse\ t$ &conditional\\
      & &$\trun\ C$ &static lifting\\
      & &$\kappa \ p:W . C$ &circuit abstraction\\
      % & &0 &constant zero\\
      % & &succ $t$ &successor\\
      % & &pred $t$ &predecessor\\
      % & &iszero $t$ & zero test\\
  \\

  $v$ &$::=$ &  &\textbf{values}: \\
      & &$\lambda\ x:T.t$ &abstraction value\\
      & &$(v, v)$ &pair value\\
      & &$\unit$ &unit value\\
      & &$\true$ &true value\\
      & &$\false$ &false value\\
      & &$\kappa\ p:W . C$ &circuit value\\
  \\

  $T$ &$::=$ &  &\textbf{types}: \\
      & &$\Unit$ &unit type\\
      & &$\Bool$ &boolean type \\
      & &$T\times T$ &product type\\
      & &$T\to T$ &function type\\
      & &$T\leadsto T$ &circuit type\\
      % & &Nat &type of natural numbers\\
      % & &Vector $t$ &type family of vectors\\
  \\

  $\Gamma$ &$::=$ &  &\textbf{contexts}: \\
      & &$\varnothing$ &empty context\\
      & &$\Gamma,x:T$ &term variable binding\\
  \\

  $W$ &$::=$ &  &\textbf{wire types}: \\
      & &$\One$ &wire unit type\\
      & &$\Bit$ &bit type \\
      & &$\Qubit$ &qubit type \\
      & &$W \otimes W$ &wire product type \\
  \\

  $p$ &$::=$ &  &\textbf{wire patterns}: \\
      & &$()$ &empty\\
      & &$w$ &wire variable \\
      & &$(p,p)$ &wire pair \\
  \\

  $C$ &$::=$ &  &\textbf{circuits}: \\
      & &$\toutput\ p$ &output a pattern \\
      & &$p_2 \from \gate\ g\ p_1 ; C$ &gate application \\
      & &$p \from C ; C$ &circuit composition \\
      & &$x \hookleftarrow \lift\ p ; C$ &dynamic lifting \\
      & &$\capp\ t\ \mathtt{to}\  p$ &circuit application \\
  \\

  $g$ &$::=$ &  &\textbf{gates}: \\
      & &$\new_0$ &generate a bit 0 \\
      & &$\new_1$ &generate a bit 1 \\
      & &$\init_0$ &generate a qubit 0 \\
      & &$\init_1$ &generate a qubit 1 \\
      & &$\meas$ &measurement gate \\
      & &$\discard$ &disgard gate \\
      & &$\Ha$ &Hadamard gate \\
      & &$\X$ &Pauli-X gate \\
      & &$\Z$ &Pauli-Z gate \\
      & &$\CNOT$ &CNOT gate \\
  \\

  $G$ &$::=$ &  &\textbf{gate types}:\\
      & &$\mathcal{G}(W, W)$ &simple gate type\\
  \\

  $\Omega$ &$::=$ &  &\textbf{wire contexts}: \\
      & &$\varnothing$ &empty context\\
      & &$\Omega,w:W$ &wire variable binding\\
  \\
  % TODO: add the condition of well-formed contexts

  \bottomrule

\end{longtable}

\subsection{Typing Rules} \label{typing}
The main feature of the language design of $\lambda_Q$ is to use linear type system to guarantee no quantum bit is used twice or not used at all.
To state the type inference rules of $\lambda_Q$, we first need to define what is a \textbf{well-formed wire context}, which is used to maintain variables used by quantum circuit in the calculus.
This context is actually corresponding to the context of linear variables in the traditional linear type system.
\begin{Def}[Well-formed Wire Contexts]
  A wire context $\Omega$ is well-formed, if there are no duplicate wire variables in it.
  For simplicity, we always assume the wire contexts are well-formed in the following contexts. And when we write $\Omega_1, \Omega_2$, we require $\Omega_1$ and $\Omega_2$ to be disjoint to preserve the well-formedness.
\end{Def}

Since there are some different kinds of terms: ($\lambda$-)terms, wire patterns, gates and circuits, we have defined several different typing relations for each of them.
\begin{itemize}
  \item $\Omega \vdash p : W$ is the typing relation for patterns.
  \item $\Gamma ; \Omega \vdash C : W$ is the typing relation for circuits;
  \item $\Gamma \vdash t:T$ is the typing relation for ($\lambda$-)terms;
  \item $g : G$ is the typing relation for gates.
\end{itemize}

\subsubsection{Typing rules for gates}
Note that since we only support built-in gates, the typing rules for gates are extremely simple, just assigning a type to each built-in gate.

\noindent \textbf{Typing rules for gates}: $\boxed{g : G}$

~

\renewcommand\arraystretch{2.5}
\begin{longtable}[c]{cr}
  $ \infer{\new_0 : \calG(\One, \Bit)}{}$ & \\
  $ \infer{\new_1 : \calG(\One, \Bit)}{}$ & \\
  $ \infer{\init_0 : \calG(\One, \Qubit)}{}$ & \\
  $ \infer{\init_1 : \calG(\One, \Qubit)}{}$ & \\
  $ \infer{\meas : \calG(\Qubit, \Bit)}{}$ & \\
  $ \infer{\discard : \calG(\Bit, \One)}{}$ & \\
  $ \infer{\Ha : \calG(\Qubit, \Qubit)}{}$ & \\
  $ \infer{\X : \calG(\Qubit, \Qubit)}{}$ & \\
  $ \infer{\Z : \calG(\Qubit, \Qubit)}{}$ & \\
  $ \infer{\CNOT : \calG((\Qubit, \Qubit), (\Qubit, \Qubit))}{}$ & \\
\end{longtable}

\subsubsection{Typing rules for patterns}
The patterns are used to construct complex gates.
Patterns are destructed when doing pattern matching in gate application, circuit composition and dynamic lifting.

\noindent \textbf{Typing rules for patterns}: $\boxed{\Omega \vdash p : W}$
\renewcommand\arraystretch{2.5}
\begin{longtable}[c]{cr}
  $ \infer{\varnothing \vdash ():One}{}$ & \\
  $ \infer{w:W \vdash w:W}{}$ & \\
  $ \infer{\Omega_1, \Omega_2 \vdash (p_1,p_2):W_1\otimes W_2}{\Omega_1 \vdash p_1 : W_1  &\Omega_2 \vdash p_2 : W_2} $ & \\
\end{longtable}

\subsubsection{Typing rules for circuits}
The typing rules for circuit uses linear type. The context $\Gamma$ is for normal (traditional) variables and the context $\Omega$ is for linear (quantum) variables.

\noindent \textbf{Typing rules for circuits}: $\boxed{\Gamma;\Omega\vdash C:W}$

\renewcommand\arraystretch{3}
\begin{longtable}[c]{cr}
  $\infer{\Gamma;\Omega\vdash \toutput\ p:W}{\Omega\vdash p : W}$ &(C-OUTPUT)\\
  $\infer{\Gamma;\Omega_1,\Omega\vdash p_2 \from \gate\ g\ p_1 ; C:W}{g:\calG(W_1, W_2) &\Omega_1\vdash p_1:W_1 &\Omega_2\vdash p_2:W_2 &\Gamma ; \Omega_2,\Omega \vdash C:W}$ &(C-GATE)\\
  $\infer{\Gamma;\Omega_1,\Omega_2\vdash p \from C ; C':W'}{\Gamma;\Omega_1\vdash C:W &\Omega \vdash p:W &\Gamma;\Omega,\Omega_2 \vdash C':W'}$ &(C-COMPOSE)\\
  $\infer{\Gamma;\Omega,\Omega'\vdash x \hookleftarrow \lift\ p ; C:W'}{\Omega\vdash p:W &\Gamma,x:|W|;\Omega' \vdash C:W'}$ &(C-LIFT)\\
  $\infer{\Gamma;\Omega\vdash \capp\ t\ \mathtt{to}\ p : W_2}{\Gamma\vdash t:W_1\leadsto W_2 &\Omega\vdash p:W_1}$ &(C-CAPP)\\

\end{longtable}

\subsubsection{Typing rules for terms}

\noindent \textbf{Typing rules for ($\lambda$-)terms}: $\boxed{\Gamma\vdash t:T}$

\renewcommand\arraystretch{3}
\begin{longtable}[c]{cr}
  $\infer{\Gamma\vdash \trun\ C : |W| }{\Gamma;\varnothing \vdash C:W}$ &(T-RUN)\\
  $\infer{\Gamma\vdash \kappa\ p:W_1 . C: W_1\leadsto W_2 }{\Omega\vdash p:W_1 &\Gamma;\Omega\vdash C:W_2}$ &(T-CABS)\\
  $\infer{\Gamma\vdash x:T}{x:T\in \Gamma}$ &(T-VAR)\\
  $\infer{\Gamma\vdash \lambda\ x:T_1.t_2 : T_1\to T_2}{\Gamma,x:T_1 \vdash t_2:T_2}$ &(T-ABS)\\
  $\infer{\Gamma\vdash t_1\ t_2 : T_{12}}{\Gamma\vdash t_1:T_{11}\to T_{12} & \Gamma\vdash t_2:T_{11}}$ &(T-APP)\\
  $\infer{\Gamma\vdash\true : Bool}{}$ &(T-TRUE)\\
  $\infer{\Gamma\vdash\false : Bool}{}$ &(T-FALSE)\\
  $\infer{\tif\ t_1\ \tthen\ t_2\ \telse\ t_3 : T}{\Gamma\vdash t_1:\Bool &\Gamma\vdash t_2:T &\Gamma\vdash t_3:T}$ &(T-IF)\\
  $\infer{\Gamma\vdash\unit : Unit}{}$ &(T-UNIT)\\
  $\infer{\Gamma\vdash (t_1,t_2) : T_1\times T_2}{\Gamma\vdash t_1:T_1 &\Gamma\vdash t_2:T_2}$ &(T-PAIR)\\
  $\infer{\Gamma\vdash t.1 : T_1}{\Gamma\vdash t : T_1\times T_2}$ &(T-FST)\\
  $\infer{\Gamma\vdash t.2 : T_2}{\Gamma\vdash t : T_1\times T_2}$ &(T-SEC)\\
\end{longtable}

% \begin{longtable}[c]{cr}
%   $\infer{\Gamma\vdash x:T}{x:T\in\Gamma &\Gamma\vdash T::*}$ &(T-VAR)\\
%   $\infer{\Gamma\vdash \lambda x:S.t\ :\Pi x:S.T}{\Gamma\vdash S::* &\Gamma,x:S\vdash t:T}$ &(T-ABS)\\
%   $\infer{\Gamma \vdash t_1\ t_2 : [x\mapsto t_2]T}{\Gamma\vdash t_1:\Pi x:S.T &\Gamma\vdash t_2:S}$ &(T-APP)\\
%   $\infer{\Gamma\vdash (t_1,t_2:\Sigma x:S.T)\ :\Sigma x:S.T}{\Gamma \vdash t_1:S &\Gamma\vdash t_2:[x\mapsto t_1]T}$ &(T-PAIR)\\
%   $\infer{\Gamma\vdash t.1:S}{\Gamma\vdash t:\Sigma x:S.T}$ &(T-PROJ1)\\
%   $\infer{\Gamma\vdash t.2:[x\mapsto t.1]T}{\Gamma\vdash t:\Sigma x:S.T}$ &(T-PROJ2)\\
%   $\infer{\Gamma\vdash t:T'}{\Gamma\vdash t:T &\Gamma\vdash T\equiv T'::*}$ &(T-CONV)\\
% \end{longtable}

\subsection{Syntactic Sugar}
In programming languages, it is useful to design some syntactic sugar to make it easier for programmer to programming.
We introduce a syntactic sugar to $\lambda_Q$ to abstract one common form of gate application.
$$p \from \gate\ g\ p;\toutput\ p \ =\ \gate'\ g\ p$$


\section{Experiments}%
\label{sec:experiments}

We use a custom implementation in C++ of all algorithm.

We used almost the same setup of the first grid presented by \citeauthor{comp_mcts_mo}\cite{comp_mcts_mo}.
Only we considered one precise setup to compare multiple algorithms.
We consider a \gls{twm} problem on a \(8 \times 8\) grid.
We consider \(2\) firefighter team.
The rewards of cells start at \(-1\) on the bottom left corner and increase by the by \(-1\) for each cell between a cell and the bottom left corner according to the manhattan distance.
Only neighbors cell can ignite each other with a probability of \(0.06\).
Firefighter teams have a \(0.8\) probability to extinguish any burning cell.
We then follow the following procedure to obtain a root state

\begin{enumerate}
    \item Initialize all the cells with \(66\) fuel.
    \item Ignite the bottom left corner.
    \item Let the fire propagate with no cost for \(66\) turn.
    \item Scale down the amount of fuel on each cell by \(.06\) to avoid too long computation
\end{enumerate}

We use the same algorithm on \(100\) different root states, obtain by the previous procedure.
We then aggregate the results together to have an average value.
We used different algorithms:

\begin{itemize}
    \item random: select a random action among legal ones every turn.
    \item \gls{uct} with \(60\) seconds of search time and an exploration parameter \(c\) equal to 1.
    \item \gls{grave} with 60 seconds of search time, an \textit{bias}  of \(0.01\) and a \textit{ref} equal to 50.
    \item \gls{nrpa} with a root level 2 and 25 iterations per level.
    \item \gls{snrpa} with a root level 2 and 25 iterations per level and 100 playount at level 0.
\end{itemize}

All algortihms are rerun every turn, allowing us to use \gls{nrpa} by taking the first action in the returned sequence.
We also included a version of the \gls{snrpa} called \textit{srnpa\_os} which is not rerun every turn but run only once on the root state.
We then take the returned sequence and use it just like in a \gls{snrpa} playout.
This allow us to use the \gls{snrpa} with a level of 3 and 50 iteration per level with 100 playout at level 0 while still having a reasonable time of computation.

The figure \ref{fig:results} presents the aggragated results of a 100 run for each algorithm with the parameters presented before.
The blue and yellow bar shows respectively the average highest reward obtainable from the root state and the average lowest reward obtainable from the root state.
These two values are computed before running the algorithm by considering the best case scenario and the worst one.

\begin{figure}[htpb]
    \centering
    \includegraphics[width=0.8\linewidth]{./src/figures/moustache.png}
    \caption{Results on 100 simulation for different algorithm as described in section~\ref{sub:results} for different algorithms}
    \label{fig:results}
\end{figure}

The results show that the \gls{snrpa} performs significately better than other algorithm.
We find strange that \gls{grave} algorithm performs so poorly and we extend the possibility of a non-wanted behaviour due to a code mistakes but we could not find one.
The \gls{nrpa} still performs better than the random algorithm which suggest that good sequences might be close to what the \gls{snrpa} find.

We wanted to see how the number of playout at level 0 impact the performance of the \gls{snrpa}.
We run, on the same setup as experiment 1 (see section~\ref{ssub:experiment_1}), 100 times the \gls{snrpa} with the same parameters.
Only one had 100 playout at level 0 and the other had 1000.

The results are shown in figure~\ref{fig:results_snrpa_playout}.
It shows that a bigger number of playouts tends to improve vastly the performance of the algorithm for a computation cost that does not increase that vastly.
The playout of the \gls{snrpa} are much simpler than the playout of the \gls{nrpa} and are computed much more faster.

\begin{figure}[htpb]
    \centering
    \includegraphics[width=0.8\linewidth]{./src/figures/moustache_snrpa.png}
    \caption{Comparison between a \gls{snrpa} with 100 playout at level 0 and a \gls{snrpa} with a 1000}
    \label{fig:results_snrpa_playout}
\end{figure}

The \gls{snrpa} seems to perform very well on this setup of grid.
It would be interesting to test it on other setup and problems, even on non stochastic ones where the \gls{nrpa} perform very well.
By lack of computational power and time we will most likely presents these tests later on another paper.


\documentclass{paper}

\usepackage[utf8x]{inputenc}
\usepackage{amsmath}
\usepackage{booktabs}
\usepackage{tikz}

\usetikzlibrary{shapes,calc,through,intersections,angles,quotes}

\title{Tilt constraint for look around}

\begin{document}

\section{Forward}

\begin{tikzpicture}[]
  \def\r{3}
  \node at (0, 0)[circle,fill,inner sep=1] (c) {};
  \node[label=right:eye] at (8, -1.5)[circle,fill,inner sep=1] (p1) {};
  \coordinate (p2) at (40:\r);

  \node[label=below left:ctr] at (0:\r)[circle,fill,inner sep=1] (p3) {};

  \node [name path=Circle1,draw,circle through=(p2)] at (c) {};
  \draw (p2) -- (p1);
  \draw (p2) -- node[above] {$r$} (c);
  \draw[dashed] (p2) -- (40:\r*2) coordinate (p5);
  \draw (p1) -- node[below] {$d$} (p3);
  \draw[] (c) -- node[above] {$r$} (p3);
  \coordinate (p4) at ($(p3) + (5,0)$);
  \coordinate (p6) at (intersection of p3--p4 and p1--p2);

  \draw[] (p3) -- node[above] {$L$} (p6);
  \draw[dashed] (p6) -- (p4);

  \pic [draw, <->, "\tiny $\Delta\rho$", angle eccentricity=1.3, angle radius=30] {angle = p2--p1--p3};
  \pic [draw, <->, "\tiny $\alpha$", angle eccentricity=1.2, angle radius=25] {angle = p1--p3--p4};

  \pic [draw, <->, "\tiny $\Omega$", angle eccentricity=1.5, angle radius=15] {angle = p1--p2--p5};

  \pic [draw, <->, "\tiny $\Delta\rho + \alpha$", angle eccentricity=1.8, angle radius=20] {angle = p1--p6--p4};
\end{tikzpicture}\vspace{1em}

Calculate center tilt angle measured at the virtual sphere when applying
a look around tilt angle.

\begin{table}[h!tb]
  \centering
  \begin{tabular}{l l}
  \toprule
  \textbf{Variable} & \textbf{Description} \\
  \midrule
  $r$ & Earth radius \\
  $d$ & Distance from eye to center \\
  $\alpha$ & Current tilt angle at center \\
  $\Delta \rho$ & Look around angle delta \\
  \bottomrule
  \end{tabular}
\end{table}

\begingroup
\addtolength{\jot}{0.5em}
\begin{align*}
  \frac{L}{\sin{\left(\Delta\rho\right)}} & = \frac{d}{\sin{\left(\pi - \Delta\rho - \alpha\right)}} = \frac{d}{\sin{\left(\Delta\rho + \alpha\right)}} \\
  L & = d \frac{\sin{\left(\Delta\rho\right)}}{\sin{\left(\Delta\rho + \alpha\right)}} \\
  \frac{\sin{\left(\Omega\right)}}{r + L} & = \frac{\sin{\left(\Delta\rho + \alpha\right)}}{r} \\
  \Omega & = \sin^{-1}{\left( \sin{\left(\Delta \rho + \alpha\right)} + \frac{d}{r} \sin{\left(\Delta \rho\right)} \right)}
\end{align*}
\endgroup

\section{Inverse}

\begin{tikzpicture}[]
  \def\r{3}
  \node at (0, 0)[circle,fill,inner sep=1] (c) {};
  \node[label=right:eye] at (8, -1.5)[circle,fill,inner sep=1] (p1) {};
  \coordinate (p2) at (40:\r);

  \node[label=below left:ctr] at (0:\r)[circle,fill,inner sep=1] (p3) {};

  \node [name path=Circle1,draw,circle through=(p2)] at (c) {};
  \draw (p2) -- (p1);
  \draw (p2) -- node[above] {$r$} (c);
  \draw[dashed] (p2) -- (40:\r*2) coordinate (p5);
  \draw (p1) -- (p3);
  \draw[] (c) -- node[above] {$r$} (p3);
  \coordinate (p4) at ($(p3) + (5,0)$);
  \coordinate (p6) at (intersection of p3--p4 and p1--p2);

  \draw[dashed] (p3) -- (p4);

  \draw[] (c) -- node[below] {$e$} (p1);

  \pic [draw, <->, "\tiny $\Delta\rho$", angle eccentricity=1.3, angle radius=30] {angle = p2--p1--p3};
  \pic [draw, <->, "\tiny $\alpha$", angle eccentricity=1.2, angle radius=25] {angle = p1--p3--p4};

  \pic [draw, <->, "\tiny $\Omega$", angle eccentricity=1.5, angle radius=15] {angle = p1--p2--p5};

  \pic [draw, <->, "\tiny $\alpha_2$", angle eccentricity=1.15, angle radius=50] {angle = p2--p1--c};
  \pic [draw, <->, "\tiny $\alpha_1$", angle eccentricity=1.12, angle radius=64] {angle = p3--p1--c};
\end{tikzpicture}\vspace{1em}

Calculate look around tilt delta to achieve a specific center tilt angle
measured at the virtual sphere.

\begin{table}[h!tb]
  \centering
  \begin{tabular}{l l}
  \toprule
  \textbf{Variable} & \textbf{Description} \\
  \midrule
  $r$ & Earth radius \\
  $d$ & Distance from eye to center \\
  $e$ & Distance from eye to earth center \\
  $\alpha$ & Desired tilt angle when meeting constraint \\
  $\Omega$ & Current tilt angle at center \\
  \bottomrule
  \end{tabular}
\end{table}

\begingroup
\addtolength{\jot}{1em}
\begin{align*}
  \frac{\sin{\left(\alpha_1\right)}}{r} & = \frac{\sin{\left(\alpha\right)}}{e},~~~~
  \alpha_1 = \sin^{-1}{\left(\frac{r}{e} \sin{\left(\alpha\right)}\right)} \\
  \frac{\sin{\left(\alpha_2\right)}}{r} & = \frac{\sin{\left(\Omega\right)}}{e},~~~~
  \alpha_2 = \sin^{-1}{\left(\frac{r}{e} \sin{\left(\Omega\right)}\right)} \\
  \Delta \rho & = \alpha_2 - \alpha_1 =
  \sin^{-1}{\left(\frac{r}{e} \sin{\left(\Omega\right)}\right)} - \sin^{-1}{\left(\frac{r}{e} \sin{\left(\alpha\right)}\right)}
\end{align*}
\endgroup

\end{document}