\chapter{User-level Application Programming Interfaces}
\label{chapter:api}

This chapter documents the user-level application programming interfaces
(APIs) provided by \libflamens.



\section{Conventions}

Before describing the \libflame APIs, let us take a moment to introduce
and discuss some of the terminology that we use when discussing the
interfaces.
Besides introducing terms, we will, when appropriate, mention any
implicit assumptions we make.



\subsection{General terms}

\index{FLAME/C!terminology}

\begin{itemize}

\item
{\em Matrix v. object}.
Throughout this document we refer to both objects and matrices.
There are many instances when the two words are used interchangeably.
However, in other cases, the distinction is intentional.
In these cases,
an object refers to the data structure that represents the matrix (or vector
or scalar) in question while a matrix refers to a mathematical entity.
However, since we, as \libflame developers and users, are only concerned
with matrices as they are represented in computational environments, we
often attribute object-like qualities to matrices, such as
datatype, length (number of rows), and width (number of columns).

\item
{\em Real matrix}.
A real matrix is one that contains only real numbers.

\item
{\em Complex matrix}.
A complex matrix is one that contains complex numbers.
That is, every element in the matrix consists of a real and imaginary
component.

\item
{\em General matrix}.
A general matrix is one for which we make no special assumptions.
That is, we do not assume any special structure concerning the upper
or lower triangles, or the diagonal.
General matrices are sometimes referred to as ``full'' matrices because
algorithms that operate upon them must assume that each entry is non-zero.

\item
{\em Symmetric matrix}.
A symmetric matrix is a square matrix whose $ (i,j) $ entry is equal to its
$ (j,i) $.
In \libflamens, only the upper or lower triangle of a symmetric matrix 
is referenced.\footnote{
Symmetric, Hermitian, and triangular matrices use the same amount of
storage space as a general matrix with identical dimensions.
That is, \libflame does not attempt to save space by omitting the redundant
(symmetric), conjugated (Hermitian), or zero (triangular) entries in the
opposite triangle.
The user is free to initialize the opposite triangle of the matrix,
even if none of the computational routines will access it.
}

\item
{\em Hermitian matrix}.
A Hermitian matrix is a square complex matrix whose $ (i,j) $ entry is equal to
the conjugate of its $ (j,i) $.
As such, the diagonal of a Hermitian matrix is always real.
In \libflamens, only the upper or lower triangle of a Hermitian matrix is stored
or referenced.\footnotemark[\value{footnote}]

\item
{\em Triangular matrix}.
A matrix is lower triangular if all non-zero entries appear on or below the
diagonal, with entries above the diagonal equal to zero.
Likewise, a matrix is upper triangular if all non-zero entries appear on or
above the diagonal, with entires below the diagonal equal to zero.
Triangular matrices are by definition square.
In \libflamens, only the upper or lower triangle of a triangular matrix,
whichever contains the non-zero entries, is stored or
referenced.\footnotemark[\value{footnote}]

\item
{\em Trapezoidal matrix}.
A trapezoidal matrix is the rectangular analog of a triangular matrix.
The name ``trapezoidal'' describes the shape of the area of the matrix
containing non-zero entries.
Specifically, a matrix is lower trapezoidal if $ m > n $ and all non-zero
entries appear on or below the diagonal, with entries above the diagonal equal
to zero.
Likewise, a matrix is upper trapezoidal if $ m < n $ and all non-zero
entries appear on or above the diagonal, with entries below the diagonal equal
to zero.

\end{itemize}


\input{figs/40-types-and-const-values}




\subsection{Notation}

\index{FLAME/C!notational conventions}

\begin{itemize}

\item
{\em Matrices, vectors, and scalars}.
Throughout this text, we distinguish between matrices, vectors,
and scalars in the following manner.
Matrices are denoted by uppercase letters (examples: $ A $, $ B $, $ C $).
Vectors are denoted by lowercase letters (examples: $ v $, $ x $, $ y $).
Scalars are denoted by lowercase Greek letters (examples: $ \alpha $,
$ \beta $, $ \rho $).

It is worth pointing out that a reference to a matrix $ A $ does not
preclude $ A $ from being a vector or scalar in certain instances.
Similarly, a reference to a vector $ x $ does not preclude $ x $ from being
a $ 1 \by 1 $ scalar.
Thus, our choice of name reflects the most liberal assumptions we can make
about the linear algebra entity in question.

Whether an entity is referred to as a matrix, vector, or scalar carries
implications with respect to its dimensions.
Matrices are $ m \by n $ for $ m,n \ge 0 $ while vectors may either be
$ m \by 1 $ or $ 1 \by n $ for $ m,n \ge 0 $.\footnote{We allow matrices and
vectors with zero dimensions to facilitate matrix partitioning, which is a
fundamental concept present in all FLAME algorithms\cite{Recipe}.}
Scalars, however, are always $ 1 \by 1 $.

\item
{\em Conjugation and conjugate transposition}.
Within this document, we denote the complex conjugate transpose, or Hermitian
tranpose, of a matrix $ A $ as $ A^H $.
Similarly, we denote the conjugate of matrix $ A $ as $ \bar{A} $.

\item
{\em BLAS and LAPACK routine notation}.
Most operations implemented within the BLAS and LAPACK come in four separate
implementations, one for each of the four floating-point numerical datatypes.
These datatypes are usually encoded by the first letter of the routine name
For example, {\tt dgemm()} implements the general matrix-matrix muliply
({\sc gemm}) operation for real matrices stored in double-precision
floating-point format.
Some level-1 routines stray slightly from this convention to handle situations
where the datatypes of two arguments are expected to be different.
The {\tt zdscal()} routine implements a vector-scaling operation where a
double-precision complex vector is scaled by a double-precision real scalar.
In order to more easily refer to related families of routines, we use the
following notation:
\begin{itemize}
\item {\tt ?}: Used as a placeholder for the letter that identifies the
datatype expected by the routine: ({\tt s}, {\tt d}, {\tt c}, or {\tt z}).
Example: {\tt ?gemm()} refers to the four level-3 BLAS routines that implement
the {\sc gemm} operation: {\tt sgemm()}, {\tt dgemm()}, {\tt cgemm()}, and
{\tt zgemm()}.
\item {\tt *}: Used as a placeholder for the letter or letters that identify
the datatypes expected by the routine.
The {\tt *} character is used for only a handful of level-1 operations that
require more than one letter to encode all datatype instances of the routine.
Example: {\tt *scal()} refers to the six level-1 BLAS routines that implement
the {\sc scal} operation: {\tt sscal()}, {\tt dscal()} {\tt cscal()},
{\tt csscal()}, {\tt zscal()}, and {\tt zdscal()}.
\end{itemize}
%The {\tt ?} and {\tt *} symbols will be familiar to those who use
%pattern-matching in UNIX/Linux shells such as {\tt bash} or {\tt tcsh}.

\item
{\em Routine name qualifiers}.
%The BLAS employs an easy-to-follow naming scheme to label its routine
%names.\cite{???}
%For example, the {\tt dsyrk()} routine implements a {\bf d}ouble-precision
%real {\bf sy}mmetric {\bf r}ank-{\bf k} update ({\sc syrk}) operation.
%Likewise, the {\tt ctrmm} routine implements a single-precision {\bf c}omplex
%{\bf tr}iangular {\bf m}atrix-{\bf m}atrix multiplication ({\sc trmm})
%operation.
%However, in the course of developing \libflamens, we found ourselves implementing
%extended variations of these operations.
In the course of developing \libflamens, we found ourselves implementing
extended variations of several BLAS operations.
In order to distinguish these similar but distinct operations from their
original counterparts, we use the following letters to encode the specific
manner in which the operation was extended:
\begin{itemize}
\item {\tt r}: Includes an uplo argument.
\item {\tt t}: Includes a trans argument.
\item {\tt c}: Includes a conjugation argument.
\item {\tt s}: Utilizes additional scalars.
\item {\tt x}: Accumulates to a different matrix or vector object.
\end{itemize}
So, for example, the \libflame routine \flagemvcext implements
the same {\sc gemv} operation implemented by \flagemvextns, except
that it allows the user to optionally conjugate the $ x $ vector argument.
Likewise, the routine \flatrmvsxext implements an operation
similar to the {\sc trmv} operation implemented in \flatrmvextns,
except that it allows the user to use additional scalars and accumulate
the result into a separate vector rather that overwrite the contents
of one of the original input arguments.

\item
{\em Constraints}.
Some interface descriptions contain a section describing constraints
placed on the implementation.
These contraints may be imposed by the operation (e.g. ``The length of
vector $ x $ must be equal to the length of vector $ y $.'') or by
the interface (e.g. ``The datatype of $ A $ must not be \flaconstantns.'')
These constraints correspond to internal safety checks performed by
\libflamens.
If one of these checks fails, then the implementation invokes
{\tt abort()}.\footnote{The \libflame developers understand that this
behavior is overkill.
Some might argue in favor of handling fatal errors through return values.
We do not believe that offloading the burden of error checking to the
user is the right answer.
However, \libflame may in the future offer a query routine that allows
the application to query whether the library has encountered an error.
}

Some things that would otherwise qualify as an operation constraint
are not listed explicitly as constraints, but rather implied by the
operation description (e.g. That $ x $ is defined as a vector.)
These implicit constraints often still correspond to safety checks.

\item
{\em Types.}
Table \ref{fig:types-and-const-values} lists all constant types
and valid type values defined by \libflamens.

\index{API!section descriptions}
\item
{\em API descriptions.}
The API descriptions in this document may contain various combinations
of the following sections:
\begin{itemize}
\item
\textpurpose.
Provides a general overview of the function, and/or a description of the
mathematical operation that the function implements.
\item
\textnotes.
Describes additional information of a general nature.
\item
\textifacenotes.
Describes additional information concerning the function interface.
\item
\textimplnotes.
Describes additional information concerning the function's implementation
within \libflamens.
\item
\textdevnotes.
This section is usually a note to developers, often a reminder of needed
attention to a function that needs improvement.
\item
\textmoreinfo.
Usually this section appears in documentation for a function that is very
similar to another function, and points the reader elsewhere for further
details of the operation being implemented. 
\item
\textrvalue.
A brief characterization of the type and value returned by the function.
\item
\textcaveats.
Contains warnings to the user on the function's usage.
\item
\textchecks.
A list of constraints on the function, including constraints imposed by the
operation specification and its implementation within \libflamens.
These constraints almost always correspond to checks that are performed at
runtime.
\item
\textparams.
A list of function parameters with brief descriptions.
\end{itemize}

\end{itemize}




\subsection{Objects}

\index{FLAME/C!object concepts}

\begin{itemize}

\item
{\em Numerical datatype}.
The numerical datatype, or just datatype, of a matrix is a constant stored in
the matrix object that determines the both the floating-point precision and the
domain of the elements within the matrix.
The constants \flafloat and \fladouble identify matrix objects created to
store single precision real and double precision real values, respectively.
Likewise, \flacomplex and \fladoublecomplex identify matrix objects created
to store single precision complex and double precision complex values,
respectively.
We also include \flaint in the category of numerical datatypes; however,
we exclude \flaint when referring to {\em floating-point} numerical datatypes,
or more simply, floating-point datatypes.

\item
{\em Leading dimension}.
The ``leading dimension'' of a matrix object refers to the distance in memory
that separates adjacent columns (for column-major storage) or rows (for
row-major storage).
In this document, we prefer to identify the row and column strides explicitly
to remove ambiguity as to the storage format.
A row stride of 1 implies that the matrix is stored in column-major order,
and likewise a column stride of 1 implies row-major storage.
A matrix stored in column-major order often has a column stride equal to
the $ m $ dimension, though it could be larger.
Similarly, a row-major matrix will have a row stride equal to or greater than
the $ n $ dimension.
It is also quite common for a matrix object to refer to a submatrix
of a larger matrix, in which case the row or column stride will exceed the
$ m $ or $ n $ dimensions, respectively, for column- and row-major cases.

\item
{\em Row vectors v. column vectors}.
A row vector is a vector with an $ m $ dimension of one, while a column
vector is a vector with an $ n $ dimension of one.
Given a column-major storage scheme, column vectors are contiguous in
memory while row vectors typically have a non-unit increment.
Hoewver, sometimes vectors are created individually (ie: they do not
exist as part of a larger matrix) in which case
they may be interpreted as either row or column vectors.
Vectors should be assumed to be column vectors unless otherwise qualified.

\item
{\em Indices}.
The interfaces in \libflame largely circumvent indices altogether.
However, in some cases, indices are unavoidable.
Furthermore, we use indices when describing some of the mathematical
operations implemented in \libflamens.
Unless otherwise indicated, the user should assume that all indices
start with zero.

\item
{\em Conformal dimensions}.
Various API descriptions use the term ``conformal'' to describe a requirement
on the dimensions of two matrices.
Matrices $ A $ and $ B $ are said to have conformal dimensions if
$ A $ and $ B $ are both $ m \by n $.

\item
{\em Storage}.
\libflame interfaces with three kinds of matrix storage schemes:
\begin{itemize}
\item {\bf Flat objects.} The primary means of storing matrices in
\libflame is within ``flat'' matrix objects.
These objects store their numerical contents in either row- or column-major
order, depending on the row and column strides given when the object is
created.
Most \libflame functions operate on flat objects.
\item {\bf Conventional matrix buffers.} Many legacy applications interface
to their matrices by indexing directly into the matrix buffer.
These so-called conventional matrices are essentially identical to a
row-major or column-major flat object, except that the matrix properties are
not encapsulated in a \libflame object.
To compute with conventional matrices, the user must first ``attach'' the
matrix buffer and other information to a ``bufferless'' object.
The user may then compute with the object as if it were a created natively
within \libflame and subsequently access the results directy via the buffer
address.
See the descriptions for \flaobjcreatewithoutbuffer and \flaobjattachbuffer
for more information on interfacing with matrices stored convetionally.
\item {\bf Hierarchical objects.} It is often advantageous to store a matrix
by blocks that are contiguous in memory.
When used within an algorithm-by-blocks, this storage scheme provides additional
spatial locality when compared to conventional/flat matrix storage.
The details of the hierarchical storage scheme, however, are intentionally
hidden from the user.
See Section \ref{sec:flash} for more information on the motivation for
hierarchical storage and the \libflame APIs for creating and manipulating
hierarchical objects.
\end{itemize}

\item
{\em Transposition}.
Many routines in \libflame allow the user to optionally transpose one or
more arguments as part of the operation.
For example, the {\sc gemm} operation allows the user to transpose
matrix $ A $, or matrix $ B $, or both.
It is worth mentioning that this kind of transposition does not actually
change the contents of matrices $ A $ or $ B $.
In these situations, the transposition is performed as part of the algorithm.
In very few cases does the computation actually transpose the contents of
a matrix, and these exceptions should be clear from the interface description.
%That is, the algorithm adjusts itself to induce the desired computation
%so that the final result is equivalent to invoking the routine with a
%matrix whose content were already transposed in memory.

\item
{\em Global scalar constants}.
Many functions within \libflame require the user to provide a $ 1 \by 1 $
object to serve as a scaling factor in the operation in question.
The {\sc gemm} operation, for example, has two of these scalars, $ \alpha $
and $ \beta $.
For convenience, \libflame defines the following global objects to represent
commonly used scalars: \flaminusonens, \flazerons, \flaonens, \flatwons.
These global scalar may be used wherever an operation reads, but does not
write to or update, a scalar object.
We've placed safeguards in most \libflame functions that would prevent the
user from changing these global scalar objects.
Still, the user should consider them to be constant and should never attempt
to update or overwrite them.

\end{itemize}



%\item
%{\em Reading from and writing to matrix objects}.
%describe matrix being referenced, updated, overwritten

%\begin{itemize}
%\item
%all \flaobj objects that are arguments to \libflame functions are considered
%valid and properly initialized unless otherwise specified.
%\item
%{\tt dim\_t} is used in place of {\tt unsigned int}.
%%\item
%%describe briefly the various sections within flaspec.
%\item
%should [not] be v. must/may [not] be 
%\item
%%objects, or flat objects, are ones created for use with the FLAME/C API.
%%hierarchical object is one created for use with the FLASH API.
%%if object is not qualified, it is assumed flat.
%%flash object synonymous with hierarchical object, or, an object which is
%%able to store matrices hierarchically, as blocks.
%%in this context, ``flat'' matrices will be synonymous with ``FLAME objects'',
%%or, objects which are created with the standard FLAME interface.
%\end{itemize}




\index{routines!FLAME/C|see{FLAME/C functions}}
\index{routines!FLASH|see{FLASH functions}}
\index{routines!SuperMatrix|see{SuperMatrix functions}}





\section{FLAME/C Basics}





\subsection{Initialization and finalization}





% --- FLA_Init() ---------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Init( void );
\end{verbatim}
\index{FLAME/C functions!\flainitns}
\purpose{
Initialize the library.
}
\notes{
This function must be invoked before any other \libflame functions.
}
\end{flaspec}

% --- FLA_Finalize() -----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Finalize( void );
\end{verbatim}
\index{FLAME/C functions!\flafinalizens}
\purpose{
Release all internal library resources.
After \flafinalize returns, \libflame functions should not be used
until \flainit is called again.
}
\notes{
This function should be invoked when your application is finished using
\libflamens.
}
\end{flaspec}

% --- FLA_Initialized() --------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLA_Initialized( void );
\end{verbatim}
\index{FLAME/C functions!\flainitializedns}
\purpose{
Check if the library is initialized.
}
\rvalue{
A boolean value:
\true if \libflame is currently initialized;
\false otherwise.
}
\end{flaspec}








\subsection{Object creation and destruction}


%%% General remarks:

%Using an uninitialized object as the argument to functions which assume they
%will be provided valid objects, including query routines and computational
%functions, will result in undefined behavior.



% --- FLA_Obj_create() ---------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Obj_create( FLA_Datatype datatype, dim_t m, dim_t n,
                          dim_t rs, dim_t cs, FLA_Obj* obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjcreatens}
\purpose{
Create a new object from an uninitialized \flaobj structure.
Upon returning, \obj points to a valid heap-allocated $ m \by n $
object whose elements are of numerical type \datatypens.
}
\notes{
Currently, \libflame supports both column-major storage and row-major
storage, but {\em not} general storage (that is, storage in which neither rows
nor columns are stored contiguously in memory).
In most cases, the user should create objects according to the following
policy: if column-major storage is desired, \rs should be set to $ 1 $ and
\cs should be set to $ m $;
otherwise, if row-major storage is desired, \rs should be set to $ n $
and cs should be set to $ 1 $.
Invoking \flaobjcreate with both \rs and \cs equal to zero is interpreted
as a request for the default storage scheme, which is currently column-major
storage.
}
\rvalue{
\flasuccess
}
\begin{checks}
\checkitem
\rs and \cs must either both be zero, or non-zero.
Also, one of the two strides must be equal to $ 1 $.
If \rs is equal to $ 1 $, then \cs must be at least $ m $;
otherwise, if \cs is equal to $ 1 $, then \rs must be at least $ n $.
\itemvsp
\checkitem
\trans may not be \flaconjtranspose or \flaconjnotransposens.
\itemvsp
\checkitem
The datatype of $ B $ may not be \flaconstantns.
\end{checks}
\begin{params}
\parameter{\fladatatype}{datatype}{A constant corresponding to the numerical datatype requested.} 
\parameter{\dimt}{m}{The number of rows to be created in new object.}
\parameter{\dimt}{n}{The number of columns to be created in the new object.}
\parameter{\dimt}{rs}{The row stride of the underlying data buffer in new object.}
\parameter{\dimt}{cs}{The column stride of the underlying data buffer in new object.}
\parminout{\flaobjp}{obj}{A pointer to an uninitialized \flaobjns.}
                         {A pointer to a new \flaobj parameterized by {\tt m}, {\tt n}, and {\tt datatype}.}
\end{params}
\end{flaspec}

% --- FLA_Obj_create_conf_to() -------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Obj_create_conf_to( FLA_Trans trans, FLA_Obj obj_cur, FLA_Obj* obj_new );
\end{verbatim}
\index{FLAME/C functions!\flaobjcreateconftons}
\purpose{
Create a new object \objnew with the same datatype and dimensions as an
existing object \objcurns.
The user may optionally create \objnew with the $ m $ and $ n $ dimensions
transposed by specifying \flatranspose for the \trans argument.
After \objnew is created, it must be initialized before it is used in any
computation which reads its numerical data.
}
\notes{
The caller may use \flaconjnotranspose and \flaconjtranspose for the \trans
argument.
The conjugation component of these values is ignored and thus for this
routine they are effectively equivalent to \flanotranspose and \flatransposens,
respectively.
}
\notes{
The new object, \objnewns, is created with similar storage properties as 
\objcurns.
For example, if \objcur is stored in column-major order, then \objnew is
created with column-major order as well.
However, the object is created with a minimal leading dimension (the column
stride for column-major storage, or the row stride for row-major storage),
such that there is no excess storage beyond the bounds of the matrix.
}
\rvalue{
\flasuccess
}
\begin{params}
\parameter{\flatrans}{trans}{Indicates whether to create the object pointed to by \objnew with transposed dimensions.} 
\parameter{\flaobj}{obj\_cur}{An existing \flaobjns.}
\parminout{\flaobjp}{obj\_new}{A pointer to an uninitialized \flaobjns.}
                              {A pointer to a new \flaobj parameterized by the datatype and dimensions of \objcurns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_create_copy_of() -------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Obj_create_copy_of( FLA_Trans trans, FLA_Obj obj_cur, FLA_Obj* obj_new );
\end{verbatim}
\index{FLAME/C functions!\flaobjcreatecopyofns}
\purpose{
Create a new object \objnew with the same datatype and dimensions as an
existing object \objcurns.
The user may optionally create \objnew with the $ m $ and $ n $ dimensions
transposed by specifying \flatranspose for the \trans argument.
After \objnew is created, it is initialized with the contents of \objcurns,
applying a transposition according to \transns.
}
\notes{
The caller may use \flaconjnotranspose and \flaconjtranspose for the \trans
argument.
The conjugation component of these values is ignored and thus for this
routine they are effectively equivalent to \flanotranspose and \flatransposens,
respectively.
}
\notes{
The new object, \objnewns, is created with similar storage properties as 
\objcurns.
For example, if \objcur is stored in column-major order, then \objnew is
created with column-major order as well.
However, the object is created with a minimal leading dimension (the column
stride for column-major storage, or the row stride for row-major storage),
such that there is no excess storage beyond the bounds of the matrix.
}
\rvalue{
\flasuccess
}
\begin{params}
\parameter{\flatrans}{trans}{Indicates whether to create the object pointed to by \objnew with transposed dimensions.} 
\parameter{\flaobj}{obj\_cur}{An existing \flaobjns.}
\parminout{\flaobjp}{obj\_new}{A pointer to an uninitialized \flaobjns.}
                              {A pointer to a new \flaobj parameterized by the datatype and dimensions of \objcur with its numerical contents identical to that of \objcurns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_free() -----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Obj_free( FLA_Obj* obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjfreens}
\purpose{
Release all resources allocated to an object.
This includes the object resources as well as the data buffer associated with
the object.
Upon returning, \obj points to a structure which is, for all intents and
purposes, uninitialized.
}
\rvalue{
\flasuccess
}
\begin{params}
\parminout{\flaobjp}{obj}{A pointer to a valid \flaobjns.}
                         {A pointer to an uninitialized \flaobjns.}
\end{params}
\end{flaspec}





\subsection{General query functions}





% --- FLA_Obj_datatype() -------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Datatype FLA_Obj_datatype( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjdatatypens}
\purpose{
Query the numerical datatype of an object.
}
\rvalue{
One of \{\flaintns, \flafloatns, \fladoublens, \flacomplexns, \fladoublecomplexns,
\flaconstantns\}.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_length() ---------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLA_Obj_length( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjlengthns}
\purpose{
Query the number of rows in a view into an object.
}
\rvalue{
An unsigned integer value of type \dimtns.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_width() ----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLA_Obj_width( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjwidthns}
\purpose{
Query the number of columns in a view into an object.
}
\rvalue{
An unsigned integer value of type \dimtns.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_min_dim() --------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLA_Obj_min_dim( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjmindimns}
\purpose{
Query the smaller of the object view's length and width dimensions.
}
\rvalue{
An unsigned integer value of type \dimtns.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_max_dim() --------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLA_Obj_max_dim( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjmaxdimns}
\purpose{
Query the larger of the object view's length and width dimensions.
}
\rvalue{
An unsigned integer value of type \dimtns.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_vector_dim() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLA_Obj_vector_dim( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjvectordimns}
\purpose{
If \obj is a column or row vector, then return the number of elements in the
vector.
Otherwise, return to object view's length.
}
\rvalue{
An unsigned integer value of type \dimtns.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_vector_inc() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLA_Obj_vector_inc( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjvectorincns}
\purpose{
If \obj is a column or row vector, then return the stride, or increment, that
separates elements of the vector in memory.
Otherwise, return $ 1 $.
}
\rvalue{
An unsigned integer value of type \dimtns.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_show() -----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Obj_show( char* header, FLA_Obj obj, char* format, char* footer );
\end{verbatim}
\index{FLAME/C functions!\flaobjshowns}
\purpose{
Display the numerical values contained in the object view \objns.
The string {\tt header} is output first (followed by a newline), then
formatted contents of \objns, and finally the string {\tt footer}
(followed by a newline).
The string {\tt format} should contain a {\tt printf()}-style format string
that describes how to output each element of the matrix.
Note that {\tt format} must be set according to the numerical contents of
\objns.
For example, if the datatype of \obj is \fladoublens, the user may choose
to use {\tt "\%11.3e"} as the {\tt format} string.
If the object were of type \fladoublecomplexns, the user would use the same
format string, however, internally it would be duplicated to denote both
real and imaginary components (ie: {\tt "\%11.3e + \%11.3e"}).
}
\rvalue{
\flasuccess
}
\begin{params}
\parameter{\charp}{header}{A pointer to a string to precede the formatted output of \objns.}
\parameter{\flaobj}{obj}{An \flaobjns.}
\parameter{\charp}{format}{A pointer to a {\tt printf()}-style format string.}
\parameter{\charp}{footer}{A pointer to a string to proceed the formatted output of \objns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_fshow() ----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Obj_fshow( FILE* file, char* header, FLA_Obj obj, char* format,
                         char* footer );
\end{verbatim}
\index{FLAME/C functions!\flaobjfshowns}
\purpose{
Display the numerical values contained in \objns.
\flaobjfshow and \flaobjshow are identical except that the former prints its
output to a file stream whereas the latter prints to standard output.
}
\notes{
The user must ensure that the file stream corresponding to {\tt file} has been
opened and is writable, and also that an error has not occured on a previous
write.
}
\rvalue{
\flasuccess
}
\implnotes{
\flaobjfshow uses {\tt fprintf()} to write output to {\tt file}.
It is possible that one of these write requests will cause an error that
prevents subsequent invocations of {\tt fprintf()} from succeeding.
As it is currently implemented, \flaobjfshow does {\em not} report such
errors.
}
\begin{params}
\parameter{\filep}{file}{A file pointer returned via {\tt fopen()}.}
\parameter{\charp}{header}{A pointer to a string to precede the formatted output of \objns.}
\parameter{\flaobj}{obj}{An \flaobjns.}
\parameter{\charp}{format}{A pointer to a {\tt printf()}-style format string.}
\parameter{\charp}{footer}{A pointer to a string to proceed the formatted output of \objns.}
\end{params}
\end{flaspec}




\subsection{Interfacing with conventional matrix arrays}





% --- FLA_Obj_create_without_buffer() ------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Obj_create_without_buffer( FLA_Datatype datatype, dim_t m, dim_t n,
                                         FLA_Obj* obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjcreatewithoutbufferns}
\purpose{
Create a new object, except without any internal numerical data buffer.
Before using the object the user must attach a valid buffer with
\flaobjattachbufferns or allocate a new buffer for the object via
\flaobjcreatebufferns.
}
\notes{
The object's datatype will have already been
set when \flaobjcreatewithoutbuffer returns.
Thus, if the user plans on attaching a buffer via \flaobjattachbufferns,
he must take care to create the object with the datatype corresponding to
the numerical values contained in the buffer he plans on attaching.
}
\rvalue{
\flasuccess
}
\begin{params}
\parameter{\fladatatype}{datatype}{A constant corresponding to the numerical datatype requested.} 
\parameter{\dimt}{m}{The number of rows to be created in new object.}
\parameter{\dimt}{n}{The number of columns to be created in the new object.}
\parminout{\flaobjp}{obj}{A pointer to an uninitialized \flaobjns.}
                         {A pointer to a new, bufferless \flaobj parameterized by {\tt m}, {\tt n},
                          and {\tt datatype}.}
\end{params}
\end{flaspec}

% --- FLA_Obj_create_buffer() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Obj_create_buffer( dim_t rs, dim_t cs, FLA_Obj* obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjcreatebufferns}
\purpose{
Allocate a new buffer for an object that was previously created via
\flaobjcreatewithoutbufferns.
The function uses \rs and \cs to set the row and column strides, respectively,
which will be used when subsequent functions access the matrix elements.
}
\notes{
Currently, one of \rs and \cs must be unit, corresponding to either
column-major or row-major storage.
Passing zero for both parameters is interpreted as a request for the
default storage scheme, with is column-major.
}
\rvalue{
\flasuccess
}
\begin{params}
\parameter{\dimt}{rs}{The row stride of the matrix buffer that will be allocated.}
\parameter{\dimt}{cs}{The column stride of the matrix buffer that will be allocated.}
\parminout{\flaobjp}{obj}{A pointer to a valid \flaobj that was created without a buffer.}
                         {A pointer to a valid \flaobj with a buffer large enough to
                          encapsulate an $ m \times n $ matrix, according to row and
                          column strides \rs and \csns, where $ m $, $ n $, and
                          the datatype were previously determined via
                          \flaobjcreatewithoutbufferns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_free_without_buffer() --------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Obj_free_without_buffer( FLA_Obj* obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjfreewithoutbufferns}
\purpose{
Release all resources allocated to an object, but do not release
the buffer attached to the object.
Upon returning, \obj points to a structure which is, for all intents and
purposes, uninitialized.
}
\rvalue{
\flasuccess
}
\begin{params}
\parminout{\flaobjp}{obj}{A pointer to a valid \flaobjns.}
                         {A pointer to an uninitialized \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_free_buffer() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Obj_free_buffer( FLA_Obj* obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjfreebufferns}
\purpose{
Release only the buffer memory associated with an object.
The rest of the object is left untouched.
After calling this routine, the user should ensure 
that the rest of the object is freed via \flaobjfreewithoutbufferns.
}
\notes{
When freeing the buffer and object separately, the buffer
{\em must} be freed first.
That is, \flaobjfreebuffer must be called before \flaobjfreewithoutbufferns.
}
\rvalue{
\flasuccess
}
\begin{params}
\parminout{\flaobjp}{obj}{A pointer to a valid \flaobjns.}
                         {A pointer to a bufferless \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_attach_buffer() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Obj_attach_buffer( void* buffer, dim_t rs, dim_t cs, FLA_Obj* obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjattachbufferns}
\purpose{
Attach a user-allocated region of memory to an object that was created
with \flaobjcreatewithoutbufferns.
This routine is useful when the user, either by preference or necessity,
wishes to allocate and/or initialize memory for linear algebra objects before
encapsulating the data within an object structure.
Note that it is important that the user submit the correct row and column
strides \rs and \csns, which, combined with the $ m $ and $ n $ dimensions
submitted when the object was created, will determine what region of memory
is accessible.
A row or column stride which is inadvertantly set too large may result in
memory accesses outside of the intended region during subsequent computation,
which will likely cause undefined behavior.
}
\notes{
When you are finished using an \flaobj with an attached buffer, you should
free it with \flaobjfreewithoutbufferns.
However, you are still responsible for freeing the memory pointed to
by \buffer using {\tt free()} or whatever memory deallocation function
your system provides.
Alternatively, you may call \flaobjfree if you wish to free both the
previously allocated buffer and the \flaobj itself.
}
\rvalue{
\flasuccess
}
\begin{checks}
\checkitem
\rs and \cs must either both be zero, or non-zero.
Also, one of the two strides must be equal to $ 1 $.
If \rs is equal to $ 1 $, then \cs must be at least $ m $;
otherwise, if \cs is equal to $ 1 $, then \rs must be at least $ n $.
\end{checks}
\begin{params}
\parameter{\voidp}{buffer}{A valid region of memory allocated by the user. Typically,
                           the address to this memory is obtained dynamically through
                           a system function such as {\tt malloc()}, but the memory
                           may also be statically allocated.}
\parameter{\dimt}{rs}{The row stride of the matrix stored conventionally in
                      \bufferns.}
\parameter{\dimt}{cs}{The column stride of the matrix stored conventionally in
                      \bufferns.}
\parminout{\flaobjp}{obj}{A pointer to a valid \flaobj that was created without a buffer.}
                         {A pointer to a valid \flaobj that encapsulates the data in
                          \bufferns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_buffer_at_view() -------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void* FLA_Obj_buffer_at_view( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjbufferatviewns}
\purpose{
Query the starting address of an object view's underlying numerical data
buffer.
The address of the view is computed according to current row and column
offset of the object view, and is {\em not} necessarily the starting address
of the overall object.
}
\notes{
Since the address returned by \flaobjbufferatview is of type \voidpns,
the user must typecast it to one of the five numerical datatypes supported
by the library (int, float, double, complex, double complex).
The correct typecast may be determined with \flaobjdatatypens.
}
\rvalue{
A pointer of type \voidpns.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_row_stride() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLA_Obj_row_stride( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjrowstridens}
\purpose{
Query the row stride associated with the object's underlying element data
buffer.
The row stride is the number of elements that separates matrix element
$ (r,c) $ from element $ (r+1,c) $.
}
\notes{
\libflame supports both row- and column-major storage for matrix objects.
When a matrix object is stored in column-major order, its row stride is,
by definition, equal to 1.
Likewise, when a matrix object is stored in row-major order, its column
stride is by definition equal to 1.
}
\rvalue{
An unsigned integer value of type \dimtns.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_col_stride() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLA_Obj_col_stride( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjcolstridens}
\purpose{
Query the column stride associated with the object's underlying element data
buffer.
The column stride is the number of elements that separates matrix element
$ (r,c) $ from element $ (r,c+1) $.
}
\notes{
\libflame supports both row- and column-major storage for matrix objects.
When a matrix object is stored in column-major order, its row stride is,
by definition, equal to 1.
Likewise, when a matrix object is stored in row-major order, its column
stride is by definition equal to 1.
}
\rvalue{
An unsigned integer value of type \dimtns.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Copy_buffer_to_object() ----------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Copy_buffer_to_object( FLA_Trans trans, dim_t m, dim_t n, void* A,
                                     dim_t rs, dim_t cs, dim_t i, dim_t j, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flacopybuffertoobjectns}
\purpose{
Copy the contents of an $ m \by n $ conventional row- or column-major matrix
$ A $ with row and column strides \rs and \cs into the submatrix $ B_{ij} $
whose top-left element is the $ (i,j) $ entry of $ B $.
The \trans argument may be used to optionally transpose the matrix during
the copy.
}
\notes{
The user should ensure that the numerical datatype used in $ A $ is the same
as the datatype used when $ B $ was created.
}
\rvalue{
\flasuccess
}
\begin{checks}
\checkitem
If \trans equals \flanotransposens, then $ B $ must be at least $ i+m \by j+n $; otherwise,
if \trans equals \flatransposens, then $ B $ must be at least $ i+n \by j+m $.
\itemvsp
\checkitem
\rs and \cs must either both be zero, or non-zero.
Also, one of the two strides must be equal to $ 1 $.
If \rs is equal to $ 1 $, then \cs must be at least $ m $;
otherwise, if \cs is equal to $ 1 $, then \rs must be at least $ n $.
\itemvsp
\checkitem
\trans may not be \flaconjtranspose or \flaconjnotransposens.
\itemvsp
\checkitem
The datatype of $ B $ may not be \flaconstantns.
\end{checks}
\begin{params}
\parameter{\flatrans}{trans}{Indicates whether to transpose the matrix $ A $ during the copy.}
\parameter{\dimt}{m}{The number of rows to copy from $ A $ to $ B_{ij} $.}
\parameter{\dimt}{n}{The number of columns to copy from $ A $ to $ B_{ij} $.}
\parameter{\voidp}{A}{A pointer to the first element in $ A $.}
\parameter{\dimt}{rs}{The row stride of $ A $.}
\parameter{\dimt}{cs}{The column stride of $ A $.}
\parameter{\dimt}{i}{The row offset in $ B $ of the submatrix $ B_{ij} $.}
\parameter{\dimt}{j}{The column offset in $ B $ of the submatrix $ B_{ij} $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Copy_object_to_buffer() ----------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Copy_object_to_buffer( FLA_Trans trans, dim_t i, dim_t j, FLA_Obj A,
                                     dim_t m, dim_t n, void* B, dim_t rs, dim_t cs );
\end{verbatim}
\index{FLAME/C functions!\flacopyobjecttobufferns}
\purpose{
Copy the contents of an $ m \by n $ submatrix $ A_{ij} $ whose top-left element
is the $ (i,j) $ entry of $ A $ into a conventional row- or column-major matrix
$ B $ with row and column strides \rs and \csns.
The \trans argument may be used to optionally transpose the submatrix during
the copy.
}
\notes{
The user should be aware of the numerical datatype of $ A $ and then access
$ B $ accordingly.
}
\rvalue{
\flasuccess
}
\begin{checks}
\checkitem
If \trans equals \flanotransposens, then $ A $ must be at least $ i+m \by j+n $; otherwise,
if \trans equals \flatransposens, then $ A $ must be at least $ i+n \by j+m $.
\itemvsp
\checkitem
\rs and \cs must either both be zero, or non-zero.
Also, one of the two strides must be equal to $ 1 $.
If \rs is equal to $ 1 $, then \cs must be at least $ m $;
otherwise, if \cs is equal to $ 1 $, then \rs must be at least $ n $.
\itemvsp
\checkitem
\trans may not be \flaconjtranspose or \flaconjnotransposens.
\itemvsp
\checkitem
The datatype of $ A $ may not be \flaconstantns.
\end{checks}
\begin{params}
\parameter{\flatrans}{trans}{Indicates whether to transpose the submatrix $ A_{ij} $ during the copy.}
\parameter{\dimt}{i}{The row offset in $ A $ of the submatrix $ A_{ij} $.}
\parameter{\dimt}{j}{The column offset in $ A $ of the submatrix $ A_{ij} $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\dimt}{m}{The number of rows to copy from $ A_{ij} $ to $ B $.}
\parameter{\dimt}{n}{The number of columns to copy from $ A_{ij} $ to $ B $.}
\parameter{\voidp}{B}{A pointer to the first element in $ B $.}
\parameter{\dimt}{rs}{The row stride of $ B $.}
\parameter{\dimt}{cs}{The column stride of $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Axpy_buffer_to_object() ----------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Axpy_buffer_to_object( FLA_Trans trans, FLA_Obj alpha,
                                     dim_t m, dim_t n, void* A, dim_t rs, dim_t cs,
                                     dim_t i, dim_t j, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaaxpybuffertoobjectns}
\purpose{
Perform one of the following operations:
\begin{eqnarray*}
B_{ij} & := & B_{ij} + \alpha A \\
B_{ij} & := & B_{ij} + \alpha A^T
\end{eqnarray*}
where $ \alpha $ is a scalar, $ A $ is an $ m \by n $ conventional row- or
column-major matrix with row and column strides \rs and \csns, and $ B_{ij} $
is the submatrix whose top-left element is the $ (i,j) $ entry of $ B $.
The \trans argument may be used to optionally transpose $ A $ during the
operation.
}
\notes{
The user should ensure that the numerical datatype used in $ A $ is the same
as the datatype used when $ B $ was created.
}
\rvalue{
\flasuccess
}
\begin{checks}
\checkitem
If \trans equals \flanotransposens, then $ B $ must be at least $ i+m \by j+n $; otherwise,
if \trans equals \flatransposens, then $ B $ must be at least $ i+n \by j+m $.
\itemvsp
\checkitem
\rs and \cs must either both be zero, or non-zero.
Also, one of the two strides must be equal to $ 1 $.
If \rs is equal to $ 1 $, then \cs must be at least $ m $;
otherwise, if \cs is equal to $ 1 $, then \rs must be at least $ n $.
\itemvsp
\checkitem
\trans may not be \flaconjtranspose or \flaconjnotransposens.
\itemvsp
\checkitem
The datatype of $ B $ may not be \flaconstantns.
\end{checks}
\begin{params}
\parameter{\flatrans}{trans}{Indicates whether to transpose the matrix $ A $ during the operation.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\dimt}{m}{The number of rows in $ A $ and $ B_{ij} $ referenced by the operation.}
\parameter{\dimt}{n}{The number of columns in $ A $ and $ B_{ij} $ referenced by the operation.}
\parameter{\voidp}{A}{A pointer to the first element in $ A $.}
\parameter{\dimt}{rs}{The row stride of $ A $.}
\parameter{\dimt}{cs}{The column stride of $ A $.}
\parameter{\dimt}{i}{The row offset in $ B $ of the submatrix $ B_{ij} $.}
\parameter{\dimt}{j}{The column offset in $ B $ of the submatrix $ B_{ij} $.}
\parameter{\flaobj}{B}{An \flaobj representing $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Axpy_object_to_buffer() ----------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Axpy_object_to_buffer( FLA_Trans trans, FLA_Obj alpha,
                                     dim_t i, dim_t j, FLA_Obj A,
                                     dim_t m, dim_t n, void* B, dim_t rs, dim_t cs );
\end{verbatim}
\index{FLAME/C functions!\flaaxpyobjecttobufferns}
\purpose{
Perform one of the following operations:
\begin{eqnarray*}
B & := & B + \alpha A_{ij} \\
B & := & B + \alpha A_{ij}^T
\end{eqnarray*}
where $ \alpha $ is a scalar, $ A_{ij} $ is the submatrix whose top-left
element is the $ (i,j) $ entry of $ A $, and $ B $ is an $ m \by n $
conventional row- or column-major matrix with row and column strides \rs
and \csns.
The \trans argument may be used to optionally transpose $ A_{ij} $ during
the operation.
}
\notes{
The user should be aware of the numerical datatype of $ A $ and then access
$ B $ accordingly.
}
\rvalue{
\flasuccess
}
\begin{checks}
\checkitem
If \trans equals \flanotransposens, then $ A $ must be at least $ i+m \by j+n $; otherwise,
if \trans equals \flatransposens, then $ A $ must be at least $ i+n \by j+m $.
\itemvsp
\checkitem
\rs and \cs must either both be zero, or non-zero.
Also, one of the two strides must be equal to $ 1 $.
If \rs is equal to $ 1 $, then \cs must be at least $ m $;
otherwise, if \cs is equal to $ 1 $, then \rs must be at least $ n $.
\itemvsp
\checkitem
\trans may not be \flaconjtranspose or \flaconjnotransposens.
\itemvsp
\checkitem
The datatype of $ A $ may not be \flaconstantns.
\end{checks}
\begin{params}
\parameter{\flatrans}{trans}{Indicates whether to transpose the matrix $ B $ during the operation.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\dimt}{i}{The row offset in $ A $ of the submatrix $ A_{ij} $.}
\parameter{\dimt}{j}{The column offset in $ A $ of the submatrix $ A_{ij} $.}
\parameter{\flaobj}{A}{An \flaobj representing $ A $.}
\parameter{\dimt}{m}{The number of rows in $ A_{ij} $ and $ B $ referenced by the operation.}
\parameter{\dimt}{n}{The number of columns in $ A_{ij} $ and $ B $ referenced by the operation.}
\parameter{\voidp}{B}{A pointer to the first element in $ B $.}
\parameter{\dimt}{rs}{The row stride of $ B $.}
\parameter{\dimt}{cs}{The column stride of $ B $.}
\end{params}
\end{flaspec}



\subsection{More query functions}



% --- FLA_Obj_datatype_proj_to_real() ------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Datatype FLA_Obj_datatype_proj_to_real( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjdatatypeprojtorealns}
\purpose{
Query the real projection of an object's datatype.
If the object datatype is single precision (ie: \flafloat or \flacomplexns)
then \flafloat is returned;
otherwise, \fladouble is returned.
}
\rvalue{
One of \{\flafloatns, \fladoublens\}.
}
\begin{checks}
\checkitem
The numerical datatype of \obj must be floating-point, and must not be
\flaconstantns.
\end{checks}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_datatype_proj_to_complex() ---------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Datatype FLA_Obj_datatype_proj_to_complex( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjdatatypeprojtocomplexns}
\purpose{
Query the complex projection of an object's datatype.
If the object datatype is single precision (ie: \flafloat or \flacomplexns)
then \flacomplex is returned;
otherwise, \fladoublecomplex is returned.
}
\rvalue{
One of \{\flacomplexns, \fladoublecomplexns\}.
}
\begin{checks}
\checkitem
The numerical datatype of \obj must be floating-point, and must not be
\flaconstantns.
\end{checks}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_is_int() ---------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLA_Obj_is_int( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjisintns}
\purpose{
Check if an object contains integer values.
}
\rvalue{
A boolean value:
\true if the datatype of \obj is \flaintns;
\false otherwise.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_is_floating_point() ----------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLA_Obj_is_floating_point( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjisfloatingpointns}
\purpose{
Check if an object contains floating-point (non-integer) numerical values.
}
\rvalue{
A boolean value:
\true if the datatype of \obj is \flafloatns, \fladoublens, \flacomplexns,
or \fladoublecomplexns;
\false otherwise.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_is_constant() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLA_Obj_is_constant( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjisconstantns}
\purpose{
Check if an object is one of the standard \libflame constants.
}
\rvalue{
A boolean value:
\true if the datatype of \obj is \flaconstantns;
\false otherwise.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_is_real() --------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLA_Obj_is_real( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjisrealns}
\purpose{
Check if an object contains real numerical values.
}
\rvalue{
A boolean value:
\true if the datatype of \obj is \flafloat or \fladoublens;
\false otherwise.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_is_complex() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLA_Obj_is_complex( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjiscomplexns}
\purpose{
Check if an object contains complex numerical values.
}
\rvalue{
A boolean value:
\true if the datatype of \obj is \flacomplex or \fladoublecomplexns;
\false otherwise.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_is_single_precision() --------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLA_Obj_is_single_precision( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjissingleprecisionns}
\purpose{
Check if an object uses a single-precision floating-point datatype.
}
\rvalue{
A boolean value:
\true if the datatype of \obj is \flafloat or \flacomplexns;
\false otherwise.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_is_double_precision() --------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLA_Obj_is_double_precision( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjisdoubleprecisionns}
\purpose{
Check if an object uses a double-precision floating-point datatype.
}
\rvalue{
A boolean value:
\true if the datatype of \obj is \fladouble or \fladoublecomplexns;
\false otherwise.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_is_scalar() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLA_Obj_is_scalar( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjisscalarns}
\purpose{
Check if an object is $ 1 \by 1 $.
}
\rvalue{
A boolean value:
\true if the row and column dimensions of \obj are equal to $ 1 $;
\false otherwise.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_is_vector() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLA_Obj_is_vector( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjisvectorns}
\purpose{
Check if an object is $ 1 \by n $ or $ m \by 1 $.
}
\rvalue{
A boolean value:
\true if either the row or column dimension of \obj is equal to 1;
\false otherwise.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_has_zero_dim() ---------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLA_Obj_has_zero_dim( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjhaszerodimns}
\purpose{
Check if an object is $ 0 \by n $ or $ m \by 0 $.
}
\rvalue{
A boolean value:
\true if either the row or column dimension of \obj is equal to 0;
\false otherwise.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_is_conformal_to() ------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLA_Obj_is_conformal_to( FLA_Trans trans, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaobjisconformaltons}
\purpose{
Check if $ A $ and $ B $ have conformal dimensions.
That is, check if the length and width of $ A $ are equal to the length and
width of $ B $, respectively.
The \trans argument may be used to perform the check as if $ A $ were
transposed.
}
\rvalue{
A boolean value:
\true if the row and column dimensions of $ A $ are equal to the row and column
dimensions of $ B $, modulo a possible transposition of $ A $;
\false otherwise.
}
\begin{params}
\parameter{\flatrans}{trans}{Indicates whether to perform the check as if $ A $ were transposed.}
\parameter{\flaobj}{A}{An \flaobjns.}
\parameter{\flaobj}{B}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_is() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLA_Obj_is( FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaobjisns}
\purpose{
Check if $ A $ and $ B $ refer to the same underlying object.
}
\rvalue{
A boolean value:
\true if $ A $ and $ B $ are the same object;
\false otherwise.
}
\devnotes{
This function needs to be reimplemented. Right now, it will return
true even if two disjoint views to the same object are passed in.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobjns.}
\parameter{\flaobj}{B}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_equals() ---------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLA_Obj_equals( FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaobjequalsns}
\purpose{
Check if $ A $ and $ B $ contain the same numerical values, element-wise.
}
\rvalue{
A boolean value:
\true if $ A $ and $ B $ are equal;
\false otherwise.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobjns.}
\parameter{\flaobj}{B}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_extract_real_scalar() --------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Obj_extract_real_scalar( FLA_Obj alpha, double* val );
\end{verbatim}
\index{FLAME/C functions!\flaobjextractrealscalarns}
\purpose{
Copy the numerical element of real scalar $ \alpha $ into the address
specified by \valns.
If object $ \alpha $ is not a scalar (ie: contains more than one element),
the value of the top-left element is copied instead.
}
\begin{checks}
\checkitem
The numerical datatype of $ \alpha $ must be floating-point and real.
\end{checks}
\begin{params}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\cdoublep}{val}{The address of the location to which to store the value of $ \alpha $.}
\end{params}
\end{flaspec}

% --- FLA_Obj_extract_complex_scalar() -----------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Obj_extract_complex_scalar( FLA_Obj alpha, dcomplex* val );
\end{verbatim}
\index{FLAME/C functions!\flaobjextractcomplexscalarns}
\purpose{
Copy the numerical element of complex scalar $ \alpha $ into the address
specified by \valns.
If object $ \alpha $ is not a scalar (ie: contains more than one element),
the value of the top-left element is copied instead.
}
\begin{checks}
\checkitem
The numerical datatype of $ \alpha $ must be floating-point and complex.
\end{checks}
\begin{params}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\cdoublep}{val}{The address of the location to which to store the value of $ \alpha $.}
\end{params}
\end{flaspec}

% --- FLA_Obj_extract_real_part() ----------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Obj_extract_real_part( FLA_Obj alpha, FLA_Obj beta );
\end{verbatim}
\index{FLAME/C functions!\flaobjextractrealpartns}
\purpose{
Copy the real component of scalar $ \alpha $ into a real scalar $ \beta $.
If $ \alpha $ is real, then its contents are simply copied into $ \beta $.
}
\begin{checks}
\checkitem
The numerical datatype of $ \alpha $ must be floating-point.
\itemvsp
\checkitem
The numerical datatype of $ \beta $ must be real and must not be \flaconstantns.
\itemvsp
\checkitem
The precision of the datatype of $ \alpha $ must be equal to that of $ \beta $.
\end{checks}
\begin{params}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\end{params}
\end{flaspec}

% --- FLA_Obj_extract_imag_part() ----------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Obj_extract_imag_part( FLA_Obj alpha, FLA_Obj beta );
\end{verbatim}
\index{FLAME/C functions!\flaobjextractimagpartns}
\purpose{
Copy the imaginary component of scalar $ \alpha $ into a real scalar $ \beta $.
If $ \alpha $ is real, then $ \beta $ is set to zero.
}
\begin{checks}
\checkitem
The numerical datatype of $ \alpha $ must be floating-point.
\itemvsp
\checkitem
The numerical datatype of $ \beta $ must be real and must not be \flaconstantns.
\itemvsp
\checkitem
The precision of the datatype of $ \alpha $ must be equal to that of $ \beta $.
\end{checks}
\begin{params}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\end{params}
\end{flaspec}

% --- FLA_Obj_buffer_is_null() -------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLA_Obj_buffer_is_null( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjbufferisnullns}
\purpose{
Check if an object's data buffer is \fnull and therefore currently un-allocated.
The function will also return \true if the object itself has not yet been
created.
}
\rvalue{
A boolean value:
\true if either the object is unallocated or the object has a \fnull buffer;
\false otherwise.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Submatrix_at() -------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void* FLA_Submatrix_at( FLA_Datatype datatype, void* buffer, dim_t i, dim_t j,
                        dim_t rs, dim_t cs );
\end{verbatim}
\index{FLAME/C functions!\flasubmatrixatns}
\purpose{
Compute the starting address of a submatrix whose top-left element is the
$ (i,j) $ element within the conventional row- or column-major order
matrix stored in \buffer with row and column strides \rs and \csns.
}
\rvalue{
The starting address of the requested submatrix.
}
\begin{params}
\parameter{\fladatatype}{datatype}{A constant corresponding to the numerical datatype of the data stored in \bufferns.} 
\parameter{\voidp}{buffer}{A pointer to a matrix stored in row- or column-major order.}
\parameter{\dimt}{i}{The row offset of the requested submatrix.}
\parameter{\dimt}{j}{The column offset of the requested submatrix.}
\parameter{\dimt}{rs}{The row stride of the matrix stored in \bufferns.}
\parameter{\dimt}{cs}{The column stride of the matrix stored in \bufferns.}
\end{params}
\end{flaspec}





\subsection{Assignment/Update functions}





% --- FLA_Set() ----------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Set( FLA_Obj alpha, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flasetns}
\purpose{
Set every element in $ A $ to $ \alpha $.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatype of $ A $.
\end{checks}
\begin{params}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Setr() ---------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Setr( FLA_Uplo, FLA_Obj alpha, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flasetrns}
\purpose{
Set every element in the upper or lower triangle of $ A $ to $ \alpha $.
The triangle that is modified is determined by \uplons.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatype of $ A $.
\end{checks}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Set_diag() -----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Set_diag( FLA_Obj alpha, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flasetdiagns}
\purpose{
Set all diagonal elements of $ A $ to $ \alpha $.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatype of $ A $.
\end{checks}
\begin{params}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Set_to_identity() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Set_to_identity( FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flasettoidentityns}
\purpose{
Set a matrix to be the identity matrix:
\begin{eqnarray*}
A & := & I_n
\end{eqnarray*}
where $ A $ is an $ n \by n $ general matrix.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must not be \flaconstantns.
\itemvsp
\checkitem
$ A $ must be square.
\end{checks}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Add_to_diag() --------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Add_to_diag( void *alpha, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flaaddtodiagns}
\purpose{
Add $ \alpha $ to the diagonal elements of $ A $.
}
\notes{
The datatype of $ A $ should match the datatype of the value pointed to
by \falphans.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point and must not be
\flaconstantns.
\itemvsp
\checkitem
\falpha must not be \fnullns.
\end{checks}
\begin{params}
\parameter{\voidp}{alpha}{A pointer to a scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Shift_diag() ---------------------------------------------------------
% --- FLASH_Shift_diag() -------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Shift_diag( FLA_Conj conj, FLA_Obj alpha, FLA_Obj A );
void FLASH_Shift_diag( FLA_Conj conj, FLA_Obj alpha, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flashiftdiagns}
\index{FLASH functions!\flashshiftdiagns}
\purpose{
Add $ \alpha $ (or $ \bar \alpha $) to the diagonal elements of $ A $.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point and must not be
\flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatype of $ A $ if $ A $ is real and the precision of $ A $ if
$ A $ is complex.
\end{checks}
\begin{params}
\parameter{\flaconj}{conj}{Indicates whether the operation proceeds as if $ alpha $ were conjugated.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Scale_diag() ---------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Scale_diag( FLA_Conj conj, FLA_Obj alpha, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flascalediagns}
\purpose{
Scale the diagonal elements of $ A $ by $ \alpha $ (or $ \bar \alpha $).
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point and must not be
\flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatype of $ A $ if $ A $ is real and the precision of $ A $ if
$ A $ is complex.
\end{checks}
\begin{params}
\parameter{\flaconj}{conj}{Indicates whether the operation proceeds as if $ alpha $ were conjugated.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Obj_set_real_part() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Obj_set_real_part( FLA_Obj alpha, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaobjsetrealpartns}
\purpose{
Copy the value of real scalar $ \alpha $ into the real component of matrix
$ B $.
If $ B $ is real, then the value in $ \alpha $ is simply copied into
all elements of $ B $.
}
\begin{checks}
\checkitem
The numerical datatype of $ \alpha $ must be real.
\itemvsp
\checkitem
The numerical datatype of $ B $ must be floating-point and must not be
\flaconstantns.
\itemvsp
\checkitem
The precision of the datatype of $ \alpha $ must be equal to that of $ B $.
\end{checks}
\begin{params}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{B}{An \flaobj representing scalar $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Obj_set_imag_part() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Obj_set_imag_part( FLA_Obj alpha, FLA_Obj beta );
\end{verbatim}
\index{FLAME/C functions!\flaobjsetimagpartns}
\purpose{
Copy the value of real scalar $ \alpha $ into the imaginary components of
matrix $ B $.
If $ B $ is real, then no operation is performed.
}
\begin{checks}
\checkitem
The numerical datatype of $ \alpha $ must be real.
\itemvsp
\checkitem
The numerical datatype of $ B $ must be floating-point and must not be
\flaconstantns.
\itemvsp
\checkitem
The precision of the datatype of $ \alpha $ must be equal to that of $ B $.
\end{checks}
\begin{params}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{B}{An \flaobj representing scalar $ B $.}
\end{params}
\end{flaspec}





\subsection{Math-related functions}





% --- FLA_Absolute_value() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Absolute_value( FLA_Obj alpha );
\end{verbatim}
\index{FLAME/C functions!\flaabsolutevaluens}
\purpose{
Compute the absolute value (or complex norm) of a complex scalar:
\begin{eqnarray*}
\alpha & := &  |\alpha|
\end{eqnarray*}
where $ \alpha $ is a complex scalar and $ |\alpha| $ is defined as
\begin{eqnarray*}
|\alpha| & = & \sqrt{ \alpha\bar{\alpha} }
\end{eqnarray*}
%Upon completion, the absolute square $ |\alpha|^2 $ overwrites the original
%value of $ \alpha $ in \falphans.
}
\notes{
If $ \alpha $ is real, then the operation reduces to
\begin{eqnarray*}
\alpha & := & | \alpha |
\end{eqnarray*}
}
\begin{checks}
\checkitem
The numerical datatype of $ \alpha $ must be floating-point and must not be
\flaconstantns.
\end{checks}
\begin{params}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\end{params}
\end{flaspec}

% --- FLA_Absolute_square() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Absolute_square( FLA_Obj alpha );
\end{verbatim}
\index{FLAME/C functions!\flaabsolutesquarens}
\purpose{
Compute the absolute square (or squared norm) of a complex scalar:
\begin{eqnarray*}
\alpha & := &  |\alpha|^2
\end{eqnarray*}
where $ \alpha $ is a complex scalar and $ |\alpha|^2 $ is defined as
\begin{eqnarray*}
|\alpha|^2 & = & \alpha\bar{\alpha}
\end{eqnarray*}
%Upon completion, the absolute square $ |\alpha|^2 $ overwrites the original
%value of $ \alpha $ in \falphans.
}
\notes{
If $ \alpha $ is real, then the operation reduces to
\begin{eqnarray*}
\alpha & := &  \alpha^2
\end{eqnarray*}
}
\begin{checks}
\checkitem
The numerical datatype of $ \alpha $ must be floating-point and must not be
\flaconstantns.
\end{checks}
\begin{params}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\end{params}
\end{flaspec}

% --- FLA_Conjugate() ----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Conjugate( FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flaconjugatefns}
\purpose{
Conjugate a matrix:
\begin{eqnarray*}
A & := & \bar{A}
\end{eqnarray*}
where $ A $ is a general matrix.
}
\notes{
If $ A $ is real, then the function has no effect.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\end{checks}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\scalns.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Conjugate_t() --------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Conjugate_r( FLA_Uplo uplo, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flaconjugaterns}
\purpose{
Conjugate the lower or upper triangular portion of a matrix $ A $.
}
\notes{
If $ A $ is real, then the function has no effect.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\end{checks}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\scalns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Transpose() ----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Transpose( FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flatransposefns}
\purpose{
Transpose a matrix:
\begin{eqnarray*}
A & := & A^T
\end{eqnarray*}
where $ A $ is a general matrix.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
$ A $ must be square.
\end{checks}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\swapns.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Invert() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Invert( FLA_Conj conj, FLA_Obj x );
\end{verbatim}
\index{FLAME/C functions!\flainvertns}
\purpose{
Invert each element of a vector:
\begin{eqnarray*}
\chi_{i} & := & \chi_{i}^{-1}
\end{eqnarray*}
where $ \chi_{i} $ is the $ i $th element of vector $ x $.
If \conj is \flaconjugatens, then each element is also conjugated:
\begin{eqnarray*}
\chi_{i} & := & \bar{\chi_{i}}^{-1}
\end{eqnarray*}
}
\begin{checks}
\checkitem
The numerical datatype of $ \alpha $ must be floating-point and must not be
\flaconstantns.
\itemvsp
\checkitem
$ x $ must be a vector (or a scalar).
\end{checks}
\begin{params}
\parameter{\flaconj}{conj}{Indicates whether to compute the conjugate of the inverse.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\end{params}
\end{flaspec}

% --- FLA_Max_abs_value() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Max_abs_value( FLA_Obj A, FLA_Obj amax );
\end{verbatim}
\index{FLAME/C functions!\flamaxabsvaluens}
\purpose{
Find the maximum absolute value of all elements of a matrix:
\begin{eqnarray*}
A_{max} & := & \max_{ij}{| \alpha_{ij} |}
\end{eqnarray*}
where $ A_{max} $ is a scalar and $ \alpha_{ij} $ is the $ (i,j) $
element of general matrix $ A $.
Upon completion, the maximum absolute value $ A_{max} $ is stored
to \amaxns.
}
\notes{
If $ A $ is complex, then $ | \alpha_{ij} | $ is evaluated as the complex norm,
which, for any complex number $ z $, is defined as
\begin{eqnarray*}
| z | & = & | x + iy | \\
      & = & \sqrt{ x^2 + iy^2 }
\end{eqnarray*}
where $ x $ and $ y $ are the real and imaginary components, respectively, of
$ z $.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point and must not be
\flaconstantns.
\itemvsp
\checkitem
The numerical datatype of $ A_{max} $ must be real and must not be
\flaconstantns.
\itemvsp
\checkitem
The precision of the datatype of $ A_{max} $ must be equal to that of $ A $.
\end{checks}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{amax}{An \flaobj representing scalar $ A_{max} $.}
\end{params}
\end{flaspec}

% --- FLA_Max_elemwise_diff() --------------------------------------------------
% --- FLASH_Max_elemwise_diff() ------------------------------------------------

\begin{flaspec}
\begin{verbatim}
double FLA_Max_elemwise_diff( FLA_Obj A, FLA_Obj B );
double FLASH_Max_elemwise_diff( FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flamaxelemwisediffns}
\index{FLASH functions!\flashmaxelemwisediffns}
\purpose{
Find and return the maximum element-wise absolute difference between
two matrices,
\begin{equation*}
\max_{i,j}{| \alpha_{ij} - \beta_{ij} |}
\end{equation*}
where $ \alpha_{ij} $ and $ \beta_{ij} $ are the $ (i,j) $ elements of
matrices $ A $ and $ B $, respectively.
}
\notes{
If $ A $ and $ B $ are complex, then they are treated as real matrices
for the purposes of computing the maximum absolute difference.
That is, the real and imaginary components of $ A_{ij} $ are compared
with the real and imaginary components of $ B_{ij} $, respectively.
}
\rvalue{
A positive double-precision floating-point value.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ B $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The dimensions of $ A $ and $ B $ must be conformal.
\end{checks}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Mult_add() -----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Mult_add( FLA_Obj alpha, FLA_Obj beta, FLA_Obj gamma );
\end{verbatim}
\index{FLAME/C functions!\flamultaddns}
\purpose{
Multiply two scalars and add the result to a third scalar:
\begin{eqnarray*}
\gamma & := &  \gamma + \alpha \beta
\end{eqnarray*}
where $ \alpha $, $ \beta $, and $ \gamma $ are scalars.
}
\begin{checks}
\checkitem
The numerical datatype of $ \alpha $, $ \beta $, and $ \gamma $ must be
floating-point. Also, the datatype of $ \gamma $ must not be \flaconstantns.
\end{checks}
\begin{params}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{gamma}{An \flaobj representing scalar $ \gamma $.}
\end{params}
\end{flaspec}

% --- FLA_Negate() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Negate( FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flanegatens}
\purpose{
Negate a matrix:
\begin{eqnarray*}
A & := & - A
\end{eqnarray*}
where $ A $ is a general matrix.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point and must not be
\flaconstantns.
\end{checks}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\scalns.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Norm1() --------------------------------------------------------------
% --- FLASH_Norm1() ------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Norm1( FLA_Obj A, FLA_Obj norm1 );
void FLASH_Norm1( FLA_Obj A, FLA_Obj norm1 );
\end{verbatim}
\index{FLAME/C functions!\flanormons}
\index{FLASH functions!\flashnormons}
\purpose{
Compute the maximum absolute column sum norm of a matrix:
\begin{eqnarray*}
\|A\|_1 & := &  \max_{j}\sum_{i=0}^{n-1} |\alpha_{ij}|
\end{eqnarray*}
where $ \|A\|_1 $ is a scalar and $ \alpha_{ij} $ is the $ (i,j) $
element of general matrix $ A $.
Upon completion, the maximum absolute column sum norm $ \|A\|_1 $ is stored
to \normons.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point and must not be
\flaconstantns.
\itemvsp
\checkitem
The numerical datatype of \normo must be real and must not be
\flaconstantns.
\itemvsp
\checkitem
The precision of the datatype of \normo must be equal to that of $ A $.
\end{checks}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\asumns.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{norm1}{An \flaobj representing scalar $ \|A\|_1 $.}
\end{params}
\end{flaspec}

% --- FLA_Norm_inf() -----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Norm_inf( FLA_Obj A, FLA_Obj norminf );
\end{verbatim}
\index{FLAME/C functions!\flanorminfns}
\purpose{
Compute the maximum absolute row sum norm of a matrix:
\begin{eqnarray*}
\|A\|_{\infty} & := &  \max_{i}\sum_{i=0}^{n-1} |\alpha_{ij}|
\end{eqnarray*}
where $ \|A\|_{\infty} $ is a scalar and $ \alpha_{ij} $ is the $ (i,j) $
element of general matrix $ A $.
Upon completion, the maximum absolute row sum norm $ \|A\|_{\infty} $ is stored
to \norminfns.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point and must not be
\flaconstantns.
\itemvsp
\checkitem
The numerical datatype of \norminf must be real and must not be
\flaconstantns.
\itemvsp
\checkitem
The precision of the datatype of \norminf must be equal to that of $ A $.
\end{checks}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\asumns.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{norminf}{An \flaobj representing scalar $ \|A\|_{\infty} $.}
\end{params}
\end{flaspec}

% --- FLA_Norm_frob() ----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Norm_frob( FLA_Obj A, FLA_Obj norm );
\end{verbatim}
\index{FLAME/C functions!\flanormfrobns}
\purpose{
Compute the Frobenius norm of a matrix:
\begin{eqnarray*}
\|A\|_{F} & := &  \sqrt{ \sum_{j=0}^{n-1} \sum_{i=0}^{m-1} |\alpha_{ij}|^2 }
\end{eqnarray*}
where $ \|A\|_{F} $ is a scalar and $ \alpha_{ij} $ is the $ (i,j) $
element of general matrix $ A $.
Upon completion, the Frobenius norm $ \|A\|_{F} $ is stored
to \normns.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point and must not be
\flaconstantns.
\itemvsp
\checkitem
The numerical datatype of \norm must be real and must not be
\flaconstantns.
\itemvsp
\checkitem
The precision of the datatype of \norm must be equal to that of $ A $.
\end{checks}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{norm}{An \flaobj representing scalar $ \|A\|_{F} $.}
\end{params}
\end{flaspec}

% --- FLA_Scal_elemwise() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Scal_elemwise( FLA_Trans trans, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flascalelemwisens}
\purpose{
Perform an element-wise scale of matrix $ B $ by matrix $ A $:
\begin{eqnarray*}
%\beta_{ij} & \becomes & \alpha_{ij} \beta_{ij} \hspace{0.4in} \forall i,j \in M,N
\beta_{ij} & \becomes & \alpha_{ij} \beta_{ij} \hspace{0.4in} \forall i,j \in \{ 0,\dots,m-1 \},\{ 0,\dots,n-1 \}
\end{eqnarray*}
where $ \alpha_{ij} $ and $ \beta_{ij} $ are the $ (i,j) $ elements within
matrices $ A $ and $ B $, respectively.
%, and $ M $ and $ N $ are the sets of
%integers $ \{ 0,\dots,m-1 \} $ and $ \{ 0,\dots,n-1 \} $, respectively.
The \trans argument allows the computation to proceed as if
$ A $ were conjugated and/or transposed.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ B $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ A $ and $ B $ are vectors, then their lengths must be equal. Otherwise,
if \trans equals \flanotranspose or \flaconjnotransposens, then the dimensions
of $ A $ and $ B $ must be conformal; otherwise, if \trans equals
\flatranspose or \flaconjtransposens, then the dimensions of $ A^T $ and $ B $
must be conformal.
\end{checks}
\begin{params}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if $ A $ were conjugated and/or transposed.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Sqrt() ---------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Sqrt( FLA_Obj alpha );
\end{verbatim}
\index{FLAME/C functions!\flasqrtns}
\purpose{
Compute the square root of a scalar:
\begin{eqnarray*}
\alpha & := &  \sqrt{\alpha}
\end{eqnarray*}
where $ \alpha $ is a positive real scalar.
}
\rvalue{
\flasuccess if $ \alpha $ is non-negative on entry; otherwise \flafailurens.
}
\begin{checks}
\checkitem
The numerical datatype of $ \alpha $ must be real and must not be
\flaconstantns.
\end{checks}
\begin{params}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\end{params}
\end{flaspec}

% --- FLA_Random_matrix() ------------------------------------------------------
% --- FLASH_Random_matrix() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Random_matrix( FLA_Obj A );
void FLASH_Random_matrix( FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flarandommatrixns}
\index{FLASH functions!\flashrandommatrixns}
\purpose{
Overwrite a matrix $ A $ with a random matrix.
}
\notes{
If $ A $ is complex, then elements are set by assigning separate random values
to real and imaginary components.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\end{checks}
\implnotes{
The random numbers obtained are unseeded and therefore deterministic.
Random numbers are obtained from the C standard library function
{\tt rand()}, scaled by {\tt RAND\_MAX}, and shifted to result in a uniform
distribution over the interval $ [-1.0,1.0) $.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Random_herm_matrix() -------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Random_herm_matrix( FLA_Uplo uplo, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flarandomhermmatrixns}
\purpose{
Overwrite a matrix $ A $ with a random Hermitian matrix, ie: a matrix $ A $
such that
\begin{eqnarray*}
A & = & A^H
\end{eqnarray*}
The \uplo argument indicates whether the lower or upper triangle of $ A $
is initially stored by the operation.
}
\notes{
If $ A $ is real, then the operation results in a random symmetric matrix.
If $ A $ is complex, then elements are set by assigning separate random values
to real and imaginary components.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\end{checks}
\implnotes{
The random numbers obtained are unseeded and therefore deterministic.
Random numbers are obtained from the C standard library function
{\tt rand()}, scaled by {\tt RAND\_MAX}, and shifted to result in a uniform
distribution over the interval $ [-1.0,1.0) $.
}
\implnotes{
Currently, the value of \uplo does not determine which triangle is
written to.
In either case, the specified triangle is randomized and then
conjugate-transposed into the other.
However, a future implementation of \flarandomhermmatrix
may only store to the triangle specified by \uplons.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is stored during the operation. This argument has no net effect on the operation.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Random_symm_matrix() -------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Random_symm_matrix( FLA_Uplo uplo, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flarandomsymmmatrixns}
\purpose{
Overwrite a matrix $ A $ with a random symmetric matrix, ie: a matrix $ A $
such that
\begin{eqnarray*}
A & = & A^T
\end{eqnarray*}
The \uplo argument indicates whether the lower or upper triangle of $ A $
is initially stored by the operation.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\end{checks}
\implnotes{
The random numbers obtained are unseeded and therefore deterministic.
Random numbers are obtained from the C standard library function
{\tt rand()}, scaled by {\tt RAND\_MAX}, and shifted to result in a uniform
distribution over the interval $ [-1.0,1.0) $.
}
\implnotes{
Currently, the value of \uplo does not determine which triangle is
written to.
In either case, the specified triangle is randomized and then
transposed into the other.
However, a future implementation of \flarandomsymmmatrix
may only store to the triangle specified by \uplons.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is stored during the operation. This argument has no net effect on the operation.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Random_spd_matrix() --------------------------------------------------
% --- FLASH_Random_spd_matrix() ------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Random_spd_matrix( FLA_Uplo uplo, FLA_Obj A );
void FLASH_Random_spd_matrix( FLA_Uplo uplo, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flarandomspdmatrixns}
\index{FLASH functions!\flashrandomspdmatrixns}
\purpose{
Overwrite a matrix $ A $ with a random symmetric positive definite matrix
if $ A $ is real, or a random Hermitian positive definite matrix if $ A $
is complex.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is stored by the operation.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\end{checks}
\implnotes{
The random numbers obtained are unseeded and therefore deterministic.
Random numbers are obtained from the C standard library function
{\tt rand()}, scaled by {\tt RAND\_MAX}, and shifted to result in a uniform
distribution over the interval $ [-1.0,1.0) $.
}
\implnotes{
If \uplo is \flalowertriangularns, then the random matrix $ A $ is computed
as
\begin{eqnarray*}
A & := & R R^H
\end{eqnarray*}
where $ R $ is a lower triangular.
Otherwise, if \uplo is \flauppertriangularns, the matrix is computed as
\begin{eqnarray*}
A & := & R^H R
\end{eqnarray*}
where $ R $ is a upper triangular.
In either case, $ R $ is generated by \flarandomtrimatrix to have a
unit diagonal.
}
%\implnotes{
%Currently, the value of \uplo has no net effect, as in both cases the entire
%matrix is randomized
%However, a future implementation of \flarandomspdmatrix
%may only store to the triangle specified by \uplons.
%}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is stored during the operation. This argument is currently ignored.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Random_tri_matrix() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Random_tri_matrix( FLA_Uplo uplo, FLA_Diag diag, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flarandomtrimatrixns}
\purpose{
Overwrite a matrix $ A $ with a random triangular matrix.
The \uplo argument indicates whether $ A $ will be lower or upper
triangular.
The off-diagonal elements of the triangle specified by \uplo are normalized
by the order of $ A $ (for numerical reasons), and the opposite triangle is
explicitly set to zero.
The \diag argument indicates how the diagonal of the matrix is set;
\flazerodiag will set all diagonal entries to zero, \flaunitdiag will set
diagonal entries to one, and \flanonunitdiag will assign the diagonal random
values.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\end{checks}
\implnotes{
The random numbers obtained are unseeded and therefore deterministic.
Random numbers are obtained from the C standard library function
{\tt rand()}, scaled by {\tt RAND\_MAX}, and shifted to result in a uniform
distribution over the interval $ [-1.0,1.0) $.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is stored during the operation. This argument is currently ignored.}
\parameter{\fladiag}{diag}{Indicates whether the diagonal of $ A $ is set to be zero, unit, or non-unit (random).}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Random_unitary_matrix() ----------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Random_unitary_matrix( FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flarandomunitarymatrixns}
\purpose{
Overwrite a matrix $ A $ with a random unitary matrix.
}
\implnotes{
\flarandomunitarymatrix forms a random unitary matrix by first creating
a random matrix via \flarandommatrix and then performing a QR factorization
on this matrix via \flaqrutns.
The Householder transforms associatd with the factorization are then
applied to the identity matrix in such a way that minimizes the
number of computations that must take place.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\end{checks}
\implnotes{
The random numbers obtained are unseeded and therefore deterministic.
Random numbers are obtained from the C standard library function
{\tt rand()}, scaled by {\tt RAND\_MAX}, and shifted to result in a uniform
distribution over the interval $ [-1.0,1.0) $.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Symmetrize() ---------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Symmetrize( FLA_Uplo uplo, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flasymmetrizens}
\purpose{
Transform a general matrix $ A $ into a symmetric matrix by copying the
transpose of one triangle into the other triangle.
The \uplo argument indicates which triangle of $ A $ is preserved and copied.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
$ A $ must be square.
\end{checks}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\copyxns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is preserved and transposed into the other triangle.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Hermitianize() -------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Hermitianize( FLA_Uplo uplo, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flahermitianizens}
\purpose{
Transform a general complex matrix $ A $ into a Hermitian matrix by
conjugate-transposing one triangle into the other triangle and then zeroing the
imaginary components of the diagonal entries.
The \uplo argument indicates which triangle of $ A $ is preserved and
conjugate-transposed.
}
\notes{
If $ A $ is real, then \flahermitianize behaves exactly as
\flasymmetrizens.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
$ A $ must be square.
\end{checks}
\implnotes{
This function uses external implementations of the level-1 BLAS routines
\copyx and \scalns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is preserved and conjugate-transposed into the other triangle.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Triangularize() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Triangularize( FLA_Uplo uplo, FLA_Diag diag, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flatriangularizens}
\purpose{
Transform a general matrix $ A $ into a triangular matrix by perserving
one triangle and zeroing the other triangle.
The \uplo argument indicates which triangle of $ A $ is preserved.
The \diag argument indicates whether to change the diagonal of the matrix;
\flazerodiag will set all diagonal entries to zero, \flaunitdiag will set
diagonal entries to one, and \flanonunitdiag will leave the diagonal unchanged.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
$ A $ must be square.
\end{checks}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is preserved.}
\parameter{\fladiag}{diag}{Indicates whether the diagonal of $ A $ is set to be zero, unit, or left unchanged.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}





\subsection{Miscellaneous functions}





% --- FLA_Check_error_level() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
unsigned int FLA_Check_error_level( void );
\end{verbatim}
\index{FLAME/C functions!\flacheckerrorlevelns}
\purpose{
Query the current level of internal error and parameter checking in
\libflamens.
Valid return values are \flafullerrorcheckingns, \flaminerrorcheckingns,
and \flanoerrorcheckingns.
}
\notes{
Error and parameter checking will have a small but sometimes noticeable
impact on performance.
We recommend full error checking for all users except those who are
performing benchmarks who have already tested their code with error
checking fully enabled.
Use reduced error checking at your own risk, and be aware that your application
may exhibit nondeterministic behavior if an error does arise.
}
\rvalue{
An unsigned integer:
\flafullerrorchecking if error and parameter checking is fully enabled;
\flaminerrorchecking if minimal error and parameter checking is enabled;
\flanoerrorchecking if error and parameter checking is completely disabled.
}
\end{flaspec}

% --- FLA_Check_error_level_set() ----------------------------------------------

\begin{flaspec}
\begin{verbatim}
unsigned int FLA_Check_error_level_set( unsigned int level );
\end{verbatim}
\index{FLAME/C functions!\flacheckerrorlevelsetns}
\purpose{
Set the level of internal error and parameter checking in \libflame to
{\tt level}.
Valid values for {\tt level} are \flafullerrorcheckingns,
\flaminerrorcheckingns, and \flanoerrorcheckingns.
The function returns the {\em previous} level of error checking regardless
of whether the new value actually caused a change in the level.
}
\rvalue{
An unsigned integer:
\flafullerrorchecking if error and parameter checking was fully enabled;
\flaminerrorchecking if minimal error and parameter checking was enabled;
\flanoerrorchecking if error and parameter checking was completely disabled.
}
\begin{params}
\parameter{\cuint}{level}{The value corresponding to the desired error checking level.}
\end{params}
\end{flaspec}

% --- FLA_Memory_leak_counter_set() --------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLA_Memory_leak_counter_set( FLA_Bool new_status );
\end{verbatim}
\index{FLAME/C functions!\flamemoryleakcountersetns}
\purpose{
Set whether the memory leak counter is enabled or disabled.
When enabled, the internal memory allocation functions \flamalloc and \flafree
increment and decrement, respectively, an internal counter to keep track of
outstanding number of memory regions still allocated.
A positive number indicates a conventional memory leak while a negative number
suggests that at least one region of allocated memory was freed more than
once.\footnote{This latter kind of memory leak is more difficult to encounter
since most modern C library implementations will disallow freeing the same
memory address twice, usually by posting a fatal error.}
If the counter is enabled upon entering \flafinalizens, the counter value is
output to standard error.
The function returns the {\em previous} status of the memory leak counter,
regardless of whether {\tt new\_status} actually caused a change in the status.
}
\notes{
If multithreading was enabled at runtime, the update of the internal memory
counter is protected by a lock.
Some applications that are intensive in object creation and destruction may
wish to disable the memory leak counter to ensure maximum performance.
Of course, this is only advisable if you are confident that your application
has no existing memory leaks
}
\rvalue{
A boolean value:
\true if the memory leak counter is currently enabled;
\false otherwise.
}
\begin{params}
\parameter{\flabool}{new\_status}{A boolean value that either enables (\true) or disables (\false) \libflame memory leak counter.}
\end{params}
\end{flaspec}

% --- FLA_Print_message() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Print_message( char* message, char* filename, unsigned int line );
\end{verbatim}
\index{FLAME/C functions!\flaprintmessagens}
\purpose{
Print a message to standard output. The function interface assumes that the
user will also want to print out the name of the file and the line number on
which the \flaprintmessage invocation appears.
}
\devnotes{
This function is most often used internally when outputing error messages
just before the library aborts.
However, it is general enough to be used by application programmers as well.
}
\begin{params}
\parameter{\charp}{message}{A pointer to a string containing the message to output.}
\parameter{\charp}{filename}{A pointer to a string containing the name of the file. This is typically obtained via the C preprocessor macro {\tt \_\_FILE\_\_}.}
\parameter{\int}{line}{An unsigned integer containing the line number that contained the invocation of \flaprintmessagens. This is typically obtained via the C preprocessor macro {\tt \_\_LINE\_\_}.}
\end{params}
\end{flaspec}

% --- FLA_Abort() --------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Abort( void );
\end{verbatim}
\index{FLAME/C functions!\flaabortns}
\purpose{
Abort execution of the application and output a corresponding message to
standard error.
}
\implnotes{
This function currently is implemented with the standard C library
function {\tt abort()}, which is often implemented by raising a {\tt SIGABRT}
signal.
This usually allows the user to quickly perform a backtrace of the function
stack in a debugger without setting breakpoints.
}
\end{flaspec}

% --- FLA_Clock() --------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
double FLA_Clock( void );
\end{verbatim}
\index{FLAME/C functions!\flaclockns}
\purpose{
Return a value representing the amount of time, in seconds, that has elapsed
since an implementation-defined Epoch.
The difference in successive return values may be used to determine elapsed
wall clock time.
}
\rvalue{
A double-precision floating-point value.
}
\implnotes{
When possible, this routine uses architecture-specific code in order to
achieve the highest possible precision.
If one of the common architectures is not detected, then the implementation
uses {\tt gettimeofday()}, which provides microsecond accuracy.
The user may force the use of this more portable {\tt gettimeofday()}
timer function at configure-time with the configure option
{\tt --enable-portable-timer}.
For Microsoft Windows builds (ie: when {\tt FLA\_ENABLE\_WINDOWS\_BUILD} is
defined) \flaclock is implemented in terms of {\tt QueryPerformanceCounter()}
and {\tt QueryPerformanceFrequency()}.
}
\end{flaspec}





\subsection{Advanced query routines}
\label{sec:advanced-query}





% --- FLA_Obj_row_offset() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLA_Obj_row_offset( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjrowoffsetns}
\purpose{
Query the row offset of an object view \objns.
}
\notes{
This routine should only be used by advanced users and developers.
}
\rvalue{
An unsigned integer value of type \dimtns.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_col_offset() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLA_Obj_col_offset( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjcoloffsetns}
\purpose{
Query the column offset of an object view \objns.
}
\notes{
This routine should only be used by advanced users and developers.
}
\rvalue{
An unsigned integer value of type \dimtns.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_base_length() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLA_Obj_base_length( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjbaselengthns}
\purpose{
Query the number of rows in the base object of \objns.
In other words, query the number of rows in the object \obj as it was
originally allocated.
}
\notes{
This routine should only be used by advanced users and developers.
}
\rvalue{
An unsigned integer value of type \dimtns.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_base_width() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLA_Obj_base_width( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjbasewidthns}
\purpose{
Query the number of columns in the base object of \objns.
In other words, query the number of columns in the object \obj as it was
originally allocated.
}
\notes{
This routine should only be used by advanced users and developers.
}
\rvalue{
An unsigned integer value of type \dimtns.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_base_buffer() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void* FLA_Obj_base_buffer( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjbasebufferns}
\purpose{
Query the starting address of the base object underlying numerical data
buffer.
The address of the object is the address that was returned by \flamalloc
when the object was created and {\em not} necessarily the same as the
starting address of the object's view.
}
\notes{
Since the address returned by \flaobjbasebuffer is of type \voidpns,
the user must typecast it to one of the five numerical datatypes supported
by the library (int, float, double, complex, double complex).
The correct typecast may be determined with \flaobjdatatypens.
}
\notes{
This routine should only be used by advanced users and developers.
}
\rvalue{
A pointer of type \voidpns.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_datatype_size() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
size_t FLA_Obj_datatype_size( FLA_Datatype datatype );
\end{verbatim}
\index{FLAME/C functions!\flaobjdatatypesizens}
\purpose{
Query the size, in bytes, of an \fladatatype value.
}
\rvalue{
An unsigned integer value of type \sizetns.
}
\caveats{
This is primarily a developer routine and should only be used by people who
know what they are doing.
}
\begin{params}
\parameter{\fladatatype}{datatype}{An \fladatatype value.}
\end{params}
\end{flaspec}

% --- FLA_Obj_elemtype() -------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Elemtype FLA_Obj_elemtype( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjelemtypens}
\purpose{
Query the type of the elements contained within an object.
}
\notes{
An object of element type \flascalar is also referred to as a ``flat'' object.
By contrast, an object of element type \flamatrix is considered hierarchical
with a depth of at least one.
More information on hierarchical matricies may be found in Section
\ref{sec:flash}.
}
\rvalue{
One of \{\flascalarns, \flamatrixns\}.
}
\caveats{
This is primarily a developer routine and should only be used by people who
know what they are doing.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLA_Obj_elem_size() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
size_t FLA_Obj_elem_size( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjelemsizens}
\purpose{
Query the size, in bytes, of the elements within an \flaobjns.
}
\rvalue{
An unsigned integer value of type \sizetns.
}
\caveats{
This is primarily a developer routine and should only be used by people who
know what they are doing.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}









\section{Managing Views}





\subsection{Vertical partitioning}





% --- FLA_Part_2x1() -----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Part_2x1( FLA_Obj A,  FLA_Obj* AT,
                                    FLA_Obj* AB,
                        dim_t  mb,  FLA_Side side );
\end{verbatim}
\index{FLAME/C functions!\flaparttwobyonens}
\purpose{
Partition a matrix $ A $ into top and bottom side views where the side
indicated by \side has \mb rows.
}
\rvalue{
\flasuccess
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobjns.}
\parminout{\flaobjp}{AT}{A pointer to an uninitialized \flaobjns.}
                        {A pointer to an \flaobj view into the top side of \Ans.}
\parminout{\flaobjp}{AB}{A pointer to an uninitialized \flaobjns.}
                        {A pointer to an \flaobj view into the bottom side of \Ans.}
\parameter{\dimt}{mb}{The number of rows to extract.}
\parameter{\flaside}{side}{The side to which to extract {\tt mb} rows.}
\end{params}
\end{flaspec}

% --- FLA_Repart_2x1_to_3x1() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Repart_2x1_to_3x1( FLA_Obj AT,  FLA_Obj* A0,
                                              FLA_Obj* A1,
                                 FLA_Obj AB,  FLA_Obj* A2,
                                 dim_t   mb,  FLA_Side side );
\end{verbatim}
\index{FLAME/C functions!\flareparttwobyonetothreebyonens}
\purpose{
Repartition a $ 2 \by 1 $ partitioning of matrix $ A $ into a $ 3 \by 1 $
partitioning where \mb rows are split from the side indicated by \sidens.
}
\rvalue{
\flasuccess
}
\begin{params}
\parameter{\flaobj}{AT, AB}{\flaobj structures that were partitioned via \flaparttwobyonens.}
\parminout{\flaobjp}{A0...A2}{Pointers to uninitialized \flaobj structures.}
                             {Pointers to \flaobj views into \ATns and \ABns.}
\parameter{\dimt}{mb}{The number of rows to extract.}
\parameter{\flaside}{side}{The side from which to extract {\tt mb} rows.}
\end{params}
\end{flaspec}

% --- FLA_Cont_with_3x1_to_2x1() -----------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Cont_with_3x1_to_2x1( FLA_Obj* AT,  FLA_Obj A0,
                                                  FLA_Obj A1,
                                    FLA_Obj* AB,  FLA_Obj A2,
                                                  FLA_Side side );
\end{verbatim}
\index{FLAME/C functions!\flacontwiththreebyonetotwobyonens}
\purpose{
Update the $ 2 \by 1 $ partitioning of matrix $ A $ by moving the boundaries
so that $ A_{1} $ is shifted to the side indicated by \sidens.
}
\rvalue{
\flasuccess
}
\begin{params}
\parminout{\flaobjp}{AT, AB}{Pointers to \flaobj structures that were partitioned via \flaparttwobyone that do not yet reflect the repartitioning.}
                            {Pointers to \flaobj structures that were partitioned via \flaparttwobyone that reflect the new matrix boundaries.}
\parameter{\flaobj}{A0...A2}{\flaobj structures that were repartitioned via \flareparttwobyonetothreebyonens.}
\parameter{\flaside}{side}{The side to which to shift the {\tt mb} rows of {\tt A1}.}
\end{params}
\end{flaspec}





\subsection{Horizontal partitioning}





% --- FLA_Part_1x2() -----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Part_1x2( FLA_Obj A,  FLA_Obj* AL, FLA_Obj* AR,
                                    dim_t    nb, FLA_Side side );
\end{verbatim}
\index{FLAME/C functions!\flapartonebytwons}
\purpose{
Partition a matrix $ A $ into left and right side views where the side
indicated by \side has \nb columns.
%Partition an object into a $ 1 \by 2 $ set of matrix views, extracting
%{\tt nb} columns to the side specified by \sidens.
}
\rvalue{
\flasuccess
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobjns.}
\parminout{\flaobjp}{AL}{A pointer to an uninitialized \flaobjns.}
                        {A pointer to an \flaobj view into the left side of \Ans.}
\parminout{\flaobjp}{AR}{A pointer to an uninitialized \flaobjns.}
                        {A pointer to an \flaobj view into the right side of \Ans.}
\parameter{\dimt}{nb}{The number of columns to extract.}
\parameter{\flaside}{side}{The side to which to extract {\tt nb} columns.}
\end{params}
\end{flaspec}

% --- FLA_Repart_1x2_to_1x3() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Repart_1x2_to_1x3( FLA_Obj  AL,              FLA_Obj  AR,
                                 FLA_Obj* A0, FLA_Obj* A1, FLA_Obj* A2,
                                              dim_t    nb, FLA_Side side );
\end{verbatim}
\index{FLAME/C functions!\flarepartonebytwotoonebythreens}
\purpose{
Repartition a $ 1 \by 2 $ partitioning of matrix $ A $ into a $ 1 \by 3 $
partitioning where \nb columns are split from the side indicated by \sidens.
}
\rvalue{
\flasuccess
}
\begin{params}
\parameter{\flaobj}{AL, AR}{\flaobj structures that were partitioned via \flapartonebytwons.}
\parminout{\flaobjp}{A0...A2}{Pointers to uninitialized \flaobj structures.}
                             {Pointers to \flaobj views into \ALns and \ARns.}
\parameter{\dimt}{nb}{The number of columns to extract.}
\parameter{\flaside}{side}{The side from which to extract {\tt nb} columns.}
\end{params}
\end{flaspec}

% --- FLA_Cont_with_1x3_to_1x2() -----------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Cont_with_1x3_to_1x2( FLA_Obj* AL,              FLA_Obj* AR,
                                    FLA_Obj  A0, FLA_Obj  A1, FLA_Obj  A2,
                                                              FLA_Side side );
\end{verbatim}
\index{FLAME/C functions!\flacontwithonebythreetoonebytwons}
\purpose{
Update the $ 1 \by 2 $ partitioning of matrix $ A $ by moving the boundaries
so that $ A_{1} $ is shifted to the side indicated by \sidens.
}
\rvalue{
\flasuccess
}
\begin{params}
\parminout{\flaobjp}{AL, AR}{Pointers to \flaobj structures that were partitioned via \flapartonebytwo that do not yet reflect the repartitioning.}
                            {Pointers to \flaobj structures that were partitioned via \flapartonebytwo that reflect the new matrix boundaries.}
\parameter{\flaobj}{A0...A2}{\flaobj structures that were repartitioned via \flarepartonebytwotoonebythreens.}
\parameter{\flaside}{side}{The side to which to shift the {\tt nb} columns of {\tt A1}.}
\end{params}
\end{flaspec}





\subsection{Bidirectional partitioning}





% --- FLA_Part_2x2() -----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Part_2x2( FLA_Obj A,  FLA_Obj* ATL, FLA_Obj* ATR,
                                    FLA_Obj* ABL, FLA_Obj* ABR,
                        dim_t  mb,  dim_t     nb, FLA_Quadrant quadrant );
\end{verbatim}
\index{FLAME/C functions!\flaparttwobytwons}
\purpose{
Partition a matrix $ A $ into four quadrant views where the quadrant indicated
by \quadrant is $ \mb \by \nbns $.
%Partition an object into a $ 2 \by 2 $ set of matrix views, extracting
%{\tt mb} rows and {\tt nb} columns to the quadrant specified by \quadrantns.
}
\rvalue{
\flasuccess
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobjns.}
\parminout{\flaobjp}{ATL...ABR}{Pointers to uninitialized \flaobj structures.}
                               {Pointers to \flaobj views into the four quadrants of \Ans.}
\parameter{\dimt}{mb}{The number of rows to extract.}
\parameter{\dimt}{nb}{The number of columns to extract.}
\parameter{\flaquadrant}{quadrant}{The quadrant to which to extract {\tt mb} rows and
                                   {\tt nb columns}.}
\end{params}
\end{flaspec}

% --- FLA_Repart_2x2_to_3x3() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Repart_2x2_to_3x3(
                  FLA_Obj ATL, FLA_Obj ATR,  FLA_Obj* A00, FLA_Obj* A01, FLA_Obj* A02,
                                             FLA_Obj* A10, FLA_Obj* A11, FLA_Obj* A12,
                  FLA_Obj ABL, FLA_Obj ABR,  FLA_Obj* A20, FLA_Obj* A21, FLA_Obj* A22,
                  dim_t   mb,  dim_t    nb,  FLA_Quadrant quadrant );
\end{verbatim}
\index{FLAME/C functions!\flareparttwobytwotothreebythreens}
\purpose{
Repartition a $ 2 \by 2 $ partitioning of matrix $ A $ into a $ 3 \by 3 $
partitioning where $ \mb \by \nb $ submatrix $ A_{11} $ is split from the
quadrant indicated by \quadrantns.
}
\rvalue{
\flasuccess
}
\begin{params}
\parameter{\flaobj}{ATL...ABR}{\flaobj structures that were partitioned via \flaparttwobytwons.}
\parminout{\flaobjp}{A00...A22}{Pointers to uninitialized \flaobj structures.}
                               {Pointers to \flaobj views into \ATLns, \ATRns, \ABLns, and \ABRns.}
%\parameter{\flaobj}{ATL}{An \flaobj that was partitioned via {\tt FLA\_Part\_2x2()}.}
%\parameter{\flaobj}{ATR}{An \flaobj that was partitioned via {\tt FLA\_Part\_2x2()}.}
%\parameter{\flaobj}{ABL}{An \flaobj that was partitioned via {\tt FLA\_Part\_2x2()}.}
%\parameter{\flaobj}{ABR}{An \flaobj that was partitioned via {\tt FLA\_Part\_2x2()}.}
%\parminout{\flaobjp}{A00}{A pointer to an uninitialized \flaobjns.}
%                         {A pointer to a view into \ATLns.}
%\parminout{\flaobjp}{A10}{A pointer to an uninitialized \flaobjns.}
%                         {A pointer to a view into either \ATL or \ABLns, depending on \quadrantns.}
%\parminout{\flaobjp}{A20}{A pointer to an uninitialized \flaobjns.}
%                         {A pointer to a view into \ABLns.}
%\parminout{\flaobjp}{A01}{A pointer to an uninitialized \flaobjns.}
%                         {A pointer to a view into either \ATL or \ATRns, depending on \quadrantns.}
%\parminout{\flaobjp}{A11}{A pointer to an uninitialized \flaobjns.}
%                         {A pointer to a view into one of \{\ATLns, \ATRns, \ABLns, \ABRns\}, depending on \quadrantns.}
%\parminout{\flaobjp}{A21}{A pointer to an uninitialized \flaobjns.}
%                         {A pointer to a view into either \ABL or \ABRns, depending on \quadrantns.}
%\parminout{\flaobjp}{A02}{A pointer to an uninitialized \flaobjns.}
%                         {A pointer to a view into \ATRns.}
%\parminout{\flaobjp}{A12}{A pointer to an uninitialized \flaobjns.}
%                         {A pointer to a view into either \ATR or \ABRns, depending on \quadrantns.}
%\parminout{\flaobjp}{A22}{A pointer to an uninitialized \flaobjns.}
%                         {A pointer to a view into \ABRns.}
%\parminout{\flaobjp}{A22}{A pointer to an uninitialized \flaobjns.}
%                         {A pointer to a view into the bottom-right quadrant of \Ans.}
\parameter{\dimt}{mb}{The number of rows to extract.}
\parameter{\dimt}{nb}{The number of columns to extract.}
\parameter{\flaquadrant}{quadrant}{The quadrant from which to shift the {\tt mb} rows and
                                   {\tt nb} columns of {\tt A11}.}
\end{params}
\end{flaspec}

% --- FLA_Cont_with_3x3_to_2x2() -----------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Cont_with_3x3_to_2x2(
                   FLA_Obj* ATL, FLA_Obj* ATR,  FLA_Obj A00, FLA_Obj A01, FLA_Obj A02,
                                                FLA_Obj A10, FLA_Obj A11, FLA_Obj A12,
                   FLA_Obj* ABL, FLA_Obj* ABR,  FLA_Obj A20, FLA_Obj A21, FLA_Obj A22,
                   FLA_Quadrant quadrant );
\end{verbatim}
\index{FLAME/C functions!\flacontwiththreebythreetotwobytwons}
\purpose{
Update the $ 2 \by 2 $ partitioning of matrix $ A $ by moving the boundaries
so that $ A_{11} $ is shifted to the quadrant indicated by \quadrantns.
}
\rvalue{
\flasuccess
}
\begin{params}
\parminout{\flaobjp}{ATL...ABR}{Pointers to \flaobj structures that were partitioned via \flaparttwobytwo that do not yet reflect the repartitioning.}
                               {Pointers to \flaobj structures that were partitioned via \flaparttwobytwo that reflect the new matrix boundaries.}
\parameter{\flaobj}{A00...A22}{\flaobj structures that were repartitioned via \flareparttwobytwotothreebythreens.}
\parameter{\flaquadrant}{quadrant}{The quadrant to which to shift the {\tt mb} rows and
                                   {\tt nb} columns of {\tt A11}.}
\end{params}
\end{flaspec}





\subsection{Merging views}





% --- FLA_Merge_2x1() ----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Merge_2x1( FLA_Obj AT,
                         FLA_Obj AB,  FLA_Obj* A );
\end{verbatim}
\index{FLAME/C functions!\flamergetwobyonens}
\purpose{
Merge a $ 2 \by 1 $ set of adjacent matrix views into a single view.
}
\begin{checks}
\checkitem
\AT and \AB must be views into the same object.
\itemvsp
\checkitem
\AT and \AB must be vertically adjacent and vertically aligned.
\itemvsp
\checkitem
\AT and \AB must have an equal number of columns.
\end{checks}
\rvalue{
\flasuccess
}
\begin{params}
\parameter{\flaobj}{AT, AB}{Valid \flaobj views eligible for merging.}
\parminout{\flaobjp}{A}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to an \flaobj view that represents the
                        merging of \AL and \ARns.}
\end{params}
\end{flaspec}

% --- FLA_Merge_1x2() ----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Merge_1x2( FLA_Obj AL, FLA_Obj  AR,  FLA_Obj* A );
\end{verbatim}
\index{FLAME/C functions!\flamergeonebytwons}
\purpose{
Merge a $ 1 \by 2 $ set of adjacent matrix views into a single view.
}
\begin{checks}
\checkitem
\AL and \AR must be views into the same object.
\itemvsp
\checkitem
\AL and \AR must be horizontally adjacent and horizontally aligned.
\itemvsp
\checkitem
\AL and \AR must have an equal number of rows.
\end{checks}
\rvalue{
\flasuccess
}
\begin{params}
\parameter{\flaobj}{AL, AR}{Valid \flaobj views eligible for merging.}
\parminout{\flaobjp}{A}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to an \flaobj view that represents the
                        merging of \AT and \ABns.}
\end{params}
\end{flaspec}

% --- FLA_Merge_2x2() ----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Merge_2x2( FLA_Obj ATL, FLA_Obj ATR,
                         FLA_Obj ABL, FLA_Obj ABR,  FLA_Obj* A );
\end{verbatim}
\index{FLAME/C functions!\flamergetwobytwons}
\purpose{
Merge a $ 2 \by 2 $ set of adjacent matrix views into a single view.
}
\begin{checks}
\checkitem
\ATLns, \ATRns, \ABLns, and \ABR must be views into the same object.
\itemvsp
\checkitem
The number of rows in \ATL and \ABL must equal that of \ATR and \ABRns, respectively.
\itemvsp
\checkitem
The number of columns in \ATL and \ATR must equal that of \ABL and \ABR, respectively.
\itemvsp
\checkitem
\ATL and \ATR must be vertically adjacent and vertically aligned to
\ABL and \ABRns, respectively.
\itemvsp
\checkitem
\ATL and \ABL must be horizontally adjacent and horizontally aligned to
\ATR and \ABRns, respectively.
\end{checks}
\rvalue{
\flasuccess
}
\begin{params}
\parameter{\flaobj}{ATL...ABR}{Valid \flaobj views to be merged.}
\parminout{\flaobjp}{A}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to an \flaobj view that represents the
                        merging of {\tt ATL}, {\tt ABL}, {\tt ATR}, and {\tt ABR}.}
\end{params}
\end{flaspec}













%\pagebreak[4]
\section{FLASH}
\label{sec:flash}




\subsection{Motivation}

\index{FLASH!description}

Traditionally, dense matrices are stored in column-major order (or,
alternatively, in row-major order).
That is, matrices are stored as a sequence of columns, with the elements of
the $ j $th column is stored contiguously, beginning at memory location $ l_{dim}j $,
where $ l_{dim} $ is the leading dimension of the matrix.
This particular storage scheme works fine for matrices small enough to fit in
the processor's level-2 cache \cite{Goto,Goto:2008:AHP}.
However, for larger matrices, the larger leading dimensions result in
attenuated performance.
The cause is primarly due to lack of spacial locality across columns and
increased TLB misses from accessing a larger region of memory \cite{Goto}.

Alternative data storage schemes have been explored thoroughly.
In particular, storage-by-blocks has shown promise as a storage scheme
capable of delivering higher performance.
The idea, in principle, is straightforward: instead of storing the entire
matrix column-major order, store individual blocks of the matrix
contiguously.\footnote{Presumably, each of these individual blocks would be
stored in column-major order, but row-major order is also possible.
Actually, the exact storage scheme of the blocks is not important, as long
as they are stored in a manner that is compatible with the computational
kernels that will operate upon the blocks.}
When paired with an algorithm that performs its computation on individual
blocks, this storage scheme can reduce cache and TLB misses and result in
better performance.

However, at the time of this writing, storage-by-blocks is not widely used.
The most likely reason stems from the difficulty of indexing directly into the
submatrices.
Storage-by-blocks tends to require complicated indexing expressions, which
further obfuscates the algorithm as expressed in its implementation.
This inability to easily index into the matrix makes it difficult to
even initialize the matrix, let alone implement an algorithm that operate
upon it.
Thus, the unpleasantness of storage-by-blocks is felt by both the library
implementor and the user alike.

The FLAME project presents a solution to this problem in \cite{FLASH:TR}.
As an extension to \libflamens, the FLASH API provides a set of interfaces
that allows a user to create, initialize, and compute with matrices
stored by blocks.
More generally, FLASH provides an interfaces for managing hierarchical
matricies, which, when set to contain one level of hierarchy, allows us
to easily implement storage-by-blocks.
For now, FLASH only supports one level of hierarchy, but in principle
multiple levels have potential applications for out-of-core computation
and sparse matrix storage.
The FLAME project intends to investigate these possibilities in future
research.



\subsection{Concepts}

\index{FLASH!terminology}

This section is devoted to introducing and defining various concepts that will
reoccur throughout our descriptions of the FLASH API.

\begin{itemize}

\item
{\em Conventional object}.
Conventional objects, also known as ``flat'' objects, are those which are
created using the traditional FLAME/C API.
In \libflamens, flat objects store their numerical data contiguously, in
column-major.

\item
{\em Hierarchy}.
The hierarchy of a matrix refers to the internal tree-like structure of
object that represents and stores the matrix.

\item
{\em Hierarchical object}.
Hierarchical objects, also referred to as objects ``stored by blocks'',
are those which are created using the FLASH API.
Hierachical objects contain a matrix hierarchy.
%, though a flat
%object may be considered a degenerate special case of this group.

\item
{\em Block}.
A block is a submatrix numerical data which is typically a part of a
larger hierarchical matrix.
Individual blocks almost always use a column-major storage scheme.

%\item
%{\em Storage-by-blocks}.
%Referring to an object that uses storage-by-blocks is generally synonymous
%with a hierarchical object.

\item
{\em Node}.
Since matrix hierarchies resemble trees, we sometimes use ``node'' as a synonym
to refer to objects within a matrix hierarchy.

\item
{\em Element}.
Elements are the immediate constituent members of a matrix object.
The nature of an object's elements is determined by the element type,
which may be either \flascalar or \flamatrixns.
The former identifies a matrix object which contains numerical data while
the later refers to a matrix object whose elements are themselves references
to other submatrix objects.

\item
{\em Leaf object}.
The leaf object is an object in a matrix hierarchy that encapsulates a
submatrix whose elements contains actual numerical data (ie: an object which
encapsulates a block).
Leaf objects always have an element type of \flascalarns.

\item
{\em Non-leaf object}.
A non-leaf object is an object in a matrix hierarchy that encapsulates
a submatrix whose elements contains references to other objects.
Non-leaf objects always have an element type of \flamatrixns.
In \libflamens, non-leaf objects store their elements in column-major order.

\item
{\em Child object}.
Child objects are those objects referred to by the elements contained
within a non-leaf object.
Child objects may contain additional levels of hierarchy (if they are
of element type \flamatrixns) or they may encapsulate numerical data
(if they are of element type \flascalarns).
Only non-leaf objects may have child objects.

\item
{\em Root object}.
The root object of a matrix hierarchy corresponds to the top-level stucture
that is visible to the user.
When a root object is also a leaf object, then the matrix has no hierarchy
and thus is effectively equivalent to a matrix object stored conventionally
in column-major order.

\item
{\em Depth}.
The depth of a matrix hierarchy is defined as the distance from the
root object to any leaf object\footnote{Currently, the FLASH API assumes that
all leaf objects are equidistant from the root. This may change in a future
revision.}.
A depth of zero means the object has no hierarchy. 

\item
{\em Level}.
A level in a hierarchy refers to all objects that are some constant distance
from the root.
Level 0 refers to the root object, level 1 refers to the childen of the root
object, and so on.

\item
{\em Element length}.
The element length, also referred to as simply ``the length'', of an object
refers to the number of element rows within
the object, where these elements may be contiguous blocks or references to
deeper portions of the matrix hierarchy.

\item
{\em Element width}.
The element width, also referred to as simply ``the width'', of an object
refers to the number of element columns within the object.
The semantics are otherwise identical to that of element length.

\item
{\em Scalar length}.
The scalar length of a hierarchical object refers to the number of rows in the
matrix that the object represents.
We distinguish between this from the element length of the object, which refers
to the
number of rows of elements in the object {\em at that level} in the hierarchy.
Put another way, the scalar length is a property of the matrix as a mathematical
entity, while the element length is a property of an individual node within the
hierarchy that represents the matrix.
As such, the user is typically only concerned with the scalar length of an
object, while developers of \libflame must routinely query both the scalar length
and element length of hierarchical objects. 

\item
{\em Scalar width}.
The scalar width of a hierarchical object refers to the number of columns in
the matrix that the object represents.
The semantics are otherwise identical to those of scalar length. 

\item
{\em Blocksize}.
The blocksize is a property of a non-leaf object, and refers to the element
dimensions of its child objects.
Specifically, it refers to the element length and width of the child objects,
{\em not} the element length and width.
The blocksize(s) used by a hierarchical object are set when the object is
created and may not be subsequently changed.

\item
{\em Hierarchical conformality}.
Two objects $ A $ and $ B $ are hierarchically conformal when the following
conditions are satisfied:
\begin{itemize}
\item
The depth of $ A $ is equal to the depth of $ B $.
\item
For every level in the hierarchies of both objects, the element length and/or
width of $ A $ equals the corresponding dimension of $ B $.
Whether only the element lengths are equal, or only the element widths are
equal, or that they are both equal, depends on the context.
In a matrix-matrix multiply operation $ C = C + A B $, hierarchical
conformality requires, for every level, that: the element length of $ A $
must equal the element length of $ C $; the element width of $ A $ equal
the element length of $ B $; and the element width of $ B $ equal the
element width of $ C $.
Alternately, in the context of the triangular matrix multiply operation
$ B := L B $, where $ L $ is a lower triangular matrix, hierarchical
conformality only requires the element length (which equals the element
width because $ L $ is square) of $ L $ equal the element length of $ B $.
\end{itemize}
Almost all FLASH functions that involve two matrix arguments require that
the matrices be hierarchically conformal.
\end{itemize}


\subsection{Interoperability with FLAME/C}

\index{FLASH!interoperability with FLAME/C}

The FLASH API is an extension to the base FLAME/C interfaces.
That is, from the perspective of the library developer, FLASH employs much
of the internal machinery present in the FLAME/C framework.
However, objects that are created as hierarchical objects via any of the
FLASH object creation routines should {\em not} be used with any of the base
FLAME/C interfaces except by developers and other experts who know what they
are doing.
The FLASH API includes a basic but complete set of routines for creating,
destroying, querying, and managing hierarchical objects.
The API also provides computational routines that support the matrices
stored by blocks.
As a general rule of thumb, once a hierarchical object has been created
the user should only use that object with routines that begin with the
{\tt FLASH\_} prefix.

The FLASH API, as written, should accept flat matrix objects without any
problems.
When a flat matrix is passed into a FLASH routine, the underlying implementation
simply invokes the appropriate code for a flat matrix object.

The remaining subsections, \ref{sec:flash-obj-creation} through
\ref{sec:flash-obj-query}, document the core set of APIs provided by
FLASH.
The computational routines are documented alongside their conventional
FLAME/C brethren in Section \ref{sec:front-ends}.


\subsection{Object creation and destruction}
\label{sec:flash-obj-creation}

% --- FLASH_Obj_create() -------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Obj_create( FLA_Datatype datatype, dim_t m, dim_t n, dim_t depth,
                       dim_t* b_mn, FLA_Obj* H );
\end{verbatim}
\index{FLASH functions!\flashobjcreatens}
\purpose{
Create a new hierarchical object from an uninitialized \flaobj structure.
Upon returning, $ H $ points to a valid heap-allocated object that refers to a
$ m \by n $ matrix of numerical datatype \datatypens.
Furthermore, $ H $ will have a hierarchical depth of \depth and the value in
\bmni will specify the square blocksizes for the $ i+1 $th level of the
hierarchy.
Only the first \depth values of \bmn will be referenced.
}
\notes{
If $ \depth > 0 $, the matrix will be hierarchical.
In this case, the dimensions of the root matrix are not explicitly
specified and instead are determined by the blocksizes at each hierarchical
level combined with the dimensions of the overall hierarchical matrix.
If $ \depth = 0 $, the matrix will be flat and have no hierarchy, in
which case the dimensions of the root matrix are the same as the dimensions
of the overall matrix.
}
\begin{checks}
\checkitem
Neither $ m $ nor $ n $ may be zero.
\itemvsp
\checkitem
\datatype may not be \flaconstantns.
\itemvsp
\checkitem
The pointer arguments \bmn and {\tt H} must not be \fnullns.
\itemvsp
\checkitem
Each of the first \depth values in \bmn must be greater than zero.
\end{checks}
\implnotes{
\flashobjcreate creates hierarchical objects with leaf and non-leaf nodes
in column-major order.
}
\begin{params}
\parameter{\fladatatype}{datatype}{A constant corresponding to the numerical datatype requested.} 
\parameter{\dimt}{m}{The number of rows to be created in new object.}
\parameter{\dimt}{n}{The number of columns to be created in the new object.}
\parameter{\dimt}{depth}{The number of levels to create in the hierarchy of $ H $.}
\parameter{\dimt}{b\_mn}{A pointer to an array of \depth values to be used as blocksizes in creating the matrix hierarchy of $ H $.}
\parminout{\flaobjp}{H}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj parameterized by \datatypens, {\tt m}, {\tt n}, \depthns, and \bmnns.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_create_ext() ---------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Obj_create_ext( FLA_Datatype datatype, dim_t m, dim_t n, dim_t depth,
                           dim_t* b_m, dim_t* b_n, FLA_Obj* H );
\end{verbatim}
\index{FLASH functions!\flashobjcreateextns}
\purpose{
Create a new hierarchical object from an uninitialized \flaobj structure.
Upon returning, $ H $ points to a valid heap-allocated object that refers to a
$ m \by n $ matrix of numerical datatype \datatypens.
Furthermore, $ H $ will have a hierarchical depth of \depth and the values in
\bmi and \bni will specify the blocksizes in the row and column dimension,
respectively, for the $ i+1 $th level of the hierarchy.
Only the first \depth values of \bm and \bn will be referenced.
}
\notes{
If $ \depth > 0 $, the matrix will be hierarchical.
In this case, the dimensions of the root matrix are not explicitly
specified and instead are determined by the row and column blocksizes at
each hierarchical level combined with the dimensions of the overall
hierarchical matrix.
If $ \depth = 0 $, the matrix will be flat and have no hierarchy, in
which case the dimensions of the root matrix are the same as the dimensions
of the overall matrix.
}
\begin{checks}
\checkitem
Neither $ m $ nor $ n $ may be zero.
\itemvsp
\checkitem
\datatype may not be \flaconstantns.
\itemvsp
\checkitem
The pointer arguments \bmns, \bnns, and {\tt H} must not be
\fnullns.
\itemvsp
\checkitem
Each of the first \depth values in \bm and \bn must be greater than zero.
\end{checks}
\implnotes{
\flashobjcreateext creates hierarchical objects with leaf and non-leaf nodes
in column-major order.
}
\begin{params}
\parameter{\fladatatype}{datatype}{A constant corresponding to the numerical datatype requested.} 
\parameter{\dimt}{m}{The number of rows to be created in new object.}
\parameter{\dimt}{n}{The number of columns to be created in the new object.}
\parameter{\dimt}{depth}{The number of levels to create in the hierarchy of $ H $.}
\parameter{\dimt}{b\_m}{A pointer to an array of \depth values to be used as the row dimensions of the blocksizes needed when creating the matrix hierarchy of $ H $.}
\parameter{\dimt}{b\_n}{A pointer to an array of \depth values to be used as the column dimensions of the blocksizes needed when creating the matrix hierarchy of $ H $.}
\parminout{\flaobjp}{H}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj parameterized by \datatypens, {\tt m}, {\tt n}, \depthns, \bmns, and \bnns.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_create_conf_to() -----------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Obj_create_conf_to( FLA_Trans trans, FLA_Obj H_cur, FLA_Obj* H_new );
\end{verbatim}
\index{FLASH functions!\flashobjcreateconftons}
\purpose{
Create a new hierarchical object with the same datatype, dimensions, depth,
and blocksizes as an existing hierarchical object.
The user may optionally create the object pointed to by \Hnew with the $ m $
and $ n $ dimensions transposed by specifying \flatranspose for the \trans
argument.
}
\notes{
This function does not initialize the contents of \Hnewns.
}
\begin{checks}
\checkitem
\trans may not be \flaconjtranspose or \flaconjnotransposens.
\end{checks}
\begin{params}
\parameter{\flatrans}{trans}{Indicates whether to create the object pointed to by \Hnew with transposed dimensions.} 
\parameter{\flaobj}{H\_cur}{An existing hierarchical \flaobjns.}
\parminout{\flaobjp}{H\_new}{A pointer to an uninitialized \flaobjns.}
                            {A pointer to a new hierarchical \flaobj parameterized by the datatype, dimensions, depth, and blocksizes of \Hcurns.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_create_copy_of() -----------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Obj_create_copy_of( FLA_Trans trans, FLA_Obj H_cur, FLA_Obj* H_new );
\end{verbatim}
\index{FLASH functions!\flashobjcreatecopyofns}
\purpose{
Create a new hierarchical object with the same datatype, dimensions, depth,
and blocksizes as an existing hierarchical object.
The user may optionally create the object pointed to by \Hnew with the $ m $
and $ n $ dimensions transposed by specifying \flatranspose for the \trans
argument.
After \Hnew is created, it is initialized with the contents of \Hcurns,
applying a transposition according to \transns.
}
\begin{checks}
\checkitem
\trans may not be \flaconjtranspose or \flaconjnotransposens.
\end{checks}
\begin{params}
\parameter{\flatrans}{trans}{Indicates whether to create the object pointed to by \Hnew with transposed dimensions.} 
\parameter{\flaobj}{H\_cur}{An existing hierarchical \flaobjns.}
\parminout{\flaobjp}{H\_new}{A pointer to an uninitialized \flaobjns.}
                            {A pointer to a new hierarchical \flaobj parameterized by the datatype, dimensions, depth, and blocksizes of \Hcur with its numerical contents identical to that of \Hcurns.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_free() ---------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Obj_free( FLA_Obj* H );
\end{verbatim}
\index{FLASH functions!\flashobjfreens}
\purpose{
Release all resources allocated to a hierarchical object.
\flashobjfree must only be used with objects that were allocated
with \flashobjcreatens, \flashobjcreateconftons,
\flashobjcreatehierconftoflatns, or
\flashobjcreatehiercopyofflatns.
Upon returning, {\tt H} points to a structure which is, for all intents and
purposes, uninitialized.
}
\notes{
If the object was created with \flashobjcreatewithoutbufferns,
you should free the object with \flashobjfreewithoutbufferns.
}
\begin{params}
\parminout{\flaobjp}{H}{A pointer to a valid hierarchical \flaobjns.}
                       {A pointer to an uninitialized \flaobjns.}
\end{params}
\end{flaspec}




\subsection{Interfacing with flat matrix objects}

% --- FLASH_Obj_create_hier_conf_to_flat() -------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Obj_create_hier_conf_to_flat( FLA_Trans trans, FLA_Obj F, dim_t depth,
                                         dim_t* b_mn, FLA_Obj* H );
\end{verbatim}
\index{FLASH functions!\flashobjcreatehierconftoflatns}
\purpose{
Create a new hierarchical object $ H $ with the same datatype and dimensions
as an existing flat object $ F $.
The function will create $ H $ with a matrix hierarchy specified by
the depth and blocksize arguments \depth and \bmnns.
The user may optionally create $ H $ with the $ m $ and $ n $ dimensions
transposed by specifying \flatranspose for the \trans argument.
}
\notes{
This function does not initialize the contents of $ H $.
}
\begin{checks}
\checkitem
\trans may not be \flaconjtranspose or \flaconjnotransposens.
\itemvsp
\checkitem
The pointer arguments \bmn and {\tt H} must not be \fnullns.
\itemvsp
\checkitem
Each of the first \depth values in \bmn must be greater than zero.
\end{checks}
\begin{params}
\parameter{\flatrans}{trans}{Indicates whether to create the object pointed to by $ H $ with transposed dimensions.} 
\parameter{\flaobj}{F}{An existing flat \flaobj representing matrix $ F $.}
\parameter{\dimt}{depth}{The number of levels to create in the hierarchy of $ H $.}
\parameter{\dimt}{b\_mn}{A pointer to an array of \depth values to be used as blocksizes in creating the matrix hierarchy of $ H $.}
\parminout{\flaobjp}{H}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj parameterized by the datatype and dimensions of $ F $, \depthns, and \bmnns.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_create_hier_conf_to_flat_ext() ---------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Obj_create_hier_conf_to_flat_ext( FLA_Trans trans, FLA_Obj F, dim_t depth,
                                             dim_t* b_m, dim_t* b_n, FLA_Obj* H );
\end{verbatim}
\index{FLASH functions!\flashobjcreatehierconftoflatextns}
\purpose{
Create a new hierarchical object $ H $ with the same datatype and dimensions
as an existing flat object $ F $.
The function will create $ H $ with a matrix hierarchy specified by
the depth and blocksize arguments \depthns, \bmns, and \bnns.
The user may optionally create $ H $ with the $ m $ and $ n $ dimensions
transposed by specifying \flatranspose for the \trans argument.
}
\notes{
This function does not initialize the contents of $ H $.
}
\begin{checks}
\checkitem
\trans may not be \flaconjtranspose or \flaconjnotransposens.
\itemvsp
\checkitem
The pointer arguments \bmns, \bnns, and {\tt H} must not be \fnullns.
\itemvsp
\checkitem
Each of the first \depth values in \bm and \bn must be greater than zero.
\end{checks}
\begin{params}
\parameter{\flatrans}{trans}{Indicates whether to create the object pointed to by $ H $ with transposed dimensions.} 
\parameter{\flaobj}{F}{An existing flat \flaobj representing matrix $ F $.}
\parameter{\dimt}{depth}{The number of levels to create in the hierarchy of $ H $.}
\parameter{\dimt}{b\_m}{A pointer to an array of \depth values to be used as the row dimensions of the blocksizes needed when creating the matrix hierarchy of $ H $.}
\parameter{\dimt}{b\_n}{A pointer to an array of \depth values to be used as the column dimensions of the blocksizes needed when creating the matrix hierarchy of $ H $.}
\parminout{\flaobjp}{H}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj parameterized by the datatype and dimensions of $ F $, \depthns, \bmns, and \bnns.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_create_hier_copy_of_flat() -------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Obj_create_hier_copy_of_flat( FLA_Obj F, dim_t depth,
                                         dim_t* b_mn, FLA_Obj* H );
\end{verbatim}
\index{FLASH functions!\flashobjcreatehiercopyofflatns}
\purpose{
Create a new hierarchical object $ H $ with the same datatype and dimensions
as an existing flat object $ F $ and then copy the numerical contents of
$ F $ to $ H $.
The function will create $ H $ with a matrix hierarchy specified by
the depth and blocksize arguments \depth and \bmnns.
}
\begin{checks}
\checkitem
The pointer arguments \bmn and {\tt H} must not be \fnullns.
\itemvsp
\checkitem
Each of the first \depth values in \bmn must be greater than zero.
\end{checks}
\begin{params}
\parameter{\flaobj}{F}{An existing flat \flaobj representing matrix $ F $.}
\parameter{\dimt}{depth}{The number of levels to create in the hierarchy of $ H $.}
\parameter{\dimt}{b\_mn}{A pointer to an array of \depth values to be used as blocksizes in creating the matrix hierarchy of $ H $.}
\parminout{\flaobjp}{H}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj parameterized by the datatype and dimensions of $ F $, \depthns, and \bmnns, and which contains the contents of the flat matrix $ F $.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_create_hier_copy_of_flat_ext() ---------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Obj_create_hier_copy_of_flat_ext( FLA_Obj F, dim_t depth,
                                             dim_t* b_m, dim_t* b_n, FLA_Obj* H );
\end{verbatim}
\index{FLASH functions!\flashobjcreatehiercopyofflatextns}
\purpose{
Create a new hierarchical object $ H $ with the same datatype and dimensions
as an existing flat object $ F $ and then copy the numerical contents of
$ F $ to $ H $.
The function will create $ H $ with a matrix hierarchy specified by
the depth and blocksize arguments \depthns, \bmns, and \bnns.
}
\begin{checks}
\checkitem
The pointer arguments \bmns, \bnns, and {\tt H} must not be \fnullns.
\itemvsp
\checkitem
Each of the first \depth values in \bm and \bn must be greater than zero.
\end{checks}
\begin{params}
\parameter{\flaobj}{F}{An existing flat \flaobj representing matrix $ F $.}
\parameter{\dimt}{depth}{The number of levels to create in the hierarchy of $ H $.}
\parameter{\dimt}{b\_m}{A pointer to an array of \depth values to be used as the row dimensions of the blocksizes needed when creating the matrix hierarchy of $ H $.}
\parameter{\dimt}{b\_n}{A pointer to an array of \depth values to be used as the column dimensions of the blocksizes needed when creating the matrix hierarchy of $ H $.}
\parminout{\flaobjp}{H}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj parameterized by the datatype and dimensions of $ F $, \depthns, \bmns, and \bnns, and which contains the contents of the flat matrix $ F $.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_create_flat_conf_to_hier() -------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Obj_create_flat_conf_to_hier( FLA_Trans trans, FLA_Obj H, FLA_Obj* F );
\end{verbatim}
\index{FLASH functions!\flashobjcreateflatconftohierns}
\purpose{
Create a new flat object $ F $ with the same datatype and dimensions
as an existing flat object $ H $.
The user may optionally create $ F $ with the $ m $ and $ n $ dimensions
transposed by specifying \flatranspose for the \trans argument.
}
\notes{
This function does not initialize the contents of $ F $.
}
\begin{checks}
\checkitem
\trans may not be \flaconjtranspose or \flaconjnotransposens.
\itemvsp
\checkitem
The pointer argument {\tt F} must not be \fnullns.
\end{checks}
\begin{params}
\parameter{\flatrans}{trans}{Indicates whether to create the object pointed to by $ F $ with transposed dimensions.} 
\parameter{\flaobj}{H}{An existing hierarchical \flaobj representing matrix $ H $.}
\parminout{\flaobjp}{F}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new flat \flaobj parameterized by the datatype and dimensions of $ F $.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_create_flat_copy_of_hier() -------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Obj_create_flat_copy_of_hier( FLA_Obj H, FLA_Obj* F );
\end{verbatim}
\index{FLASH functions!\flashobjcreateflatcopyofhierns}
\purpose{
Create a new flat object $ F $ with the same datatype and dimensions
as an existing hierarchical object $ H $ and then copy the numerical
contents of $ F $ to $ H $.
}
\begin{checks}
\checkitem
The pointer argument {\tt F} must not be \fnullns.
\end{checks}
\begin{params}
\parameter{\flaobj}{H}{An existing hierarchical \flaobj representing matrix $ H $.}
\parminout{\flaobjp}{F}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new flat \flaobj parameterized by the datatype and dimensions of $ F $, and which contains the contents of the hierarchical matrix $ F $.}
\end{params}
\end{flaspec}

% --- FLASH_Copy_buffer_to_hier() ----------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Copy_buffer_to_hier( dim_t m, dim_t n, void* F, dim_t rs, dim_t cs,
                                dim_t i, dim_t j, FLA_Obj H );
\end{verbatim}
\index{FLASH functions!\flashcopybuffertohierns}
\purpose{
Copy the contents of an conventional column-major matrix $ F $ with row and
column strides \rs and \cs into the submatrix $ H_{ij} $ whose top-left element
is the $ (i,j) $ entry of hierarchical matrix $ H $, where both $ F $ and
$ H_{ij} $ are $ m \by n $.
}
\notes{
The user should ensure that the numerical datatype used in $ F $ is the same
as the datatype used when $ H $ was created.
}
\begin{checks}
\checkitem
The numerical datatype of $ H $ must not be \flaconstantns.
\itemvsp
\checkitem
$ H $ must be at least $ i+m \by j+n $.
\itemvsp
\checkitem
\rs and \cs must either both be zero, or non-zero.
Also, one of the two strides must be equal to $ 1 $.
If \rs is equal to $ 1 $, then \cs must be at least $ m $;
otherwise, if \cs is equal to $ 1 $, then \rs must be at least $ n $.
\itemvsp
\checkitem
The pointer argument {\tt F} must not be \fnullns.
\end{checks}
\begin{params}
\parameter{\dimt}{m}{The number of rows to copy from $ F $ to $ H_{ij} $.}
\parameter{\dimt}{n}{The number of columns to copy from $ F $ to $ H_{ij} $.}
\parameter{\voidp}{F}{A pointer to the first element in conventional column-major matrix $ F $.}
\parameter{\dimt}{rs}{The row stride of $ F $.}
\parameter{\dimt}{cs}{The column stride of $ F $.}
\parameter{\dimt}{i}{The row offset in $ H $ of the submatrix $ H_{ij} $.}
\parameter{\dimt}{j}{The column offset in $ H $ of the submatrix $ H_{ij} $.}
\parameter{\flaobj}{H}{A hierarchical \flaobj representing matrix $ H $.}
\end{params}
\end{flaspec}

% --- FLASH_Copy_hier_to_buffer() ----------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Copy_hier_to_buffer( dim_t i, dim_t j, FLA_Obj H,
                                dim_t m, dim_t n, void* F, dim_t rs, dim_t cs );
\end{verbatim}
\index{FLASH functions!\flashcopyhiertobufferns}
\purpose{
Copy the contents of the submatrix $ H_{ij} $ whose top-left element is the
$ (i,j) $ entry of hierarchical matrix $ H $ into an conventional column-major
matrix $ F $ with row and column strides \rs and \csns, where both $ H_{ij} $
and $ F $ are $ m \by n $.
}
\notes{
The user should be aware of the numerical datatype of $ H $ and then access
$ F $ accordingly.
}
\begin{checks}
\checkitem
The numerical datatype of $ H $ must not be \flaconstantns.
\itemvsp
\checkitem
$ H $ must be at least $ i+m \by j+n $.
\itemvsp
\checkitem
\rs and \cs must either both be zero, or non-zero.
Also, one of the two strides must be equal to $ 1 $.
If \rs is equal to $ 1 $, then \cs must be at least $ m $;
otherwise, if \cs is equal to $ 1 $, then \rs must be at least $ n $.
\itemvsp
\checkitem
The pointer argument {\tt F} must not be \fnullns.
\end{checks}
\begin{params}
\parameter{\dimt}{i}{The row offset in $ H $ of the submatrix $ H_{ij} $.}
\parameter{\dimt}{j}{The column offset in $ H $ of the submatrix $ H_{ij} $.}
\parameter{\flaobj}{H}{A hierarchical \flaobj representing matrix $ H $.}
\parameter{\dimt}{m}{The number of rows to copy from $ H_{ij} $ to $ F $.}
\parameter{\dimt}{n}{The number of columns to copy from $ H_{ij} $ to $ F $.}
\parameter{\voidp}{F}{A pointer to the first element in conventional column-major matrix $ F $.}
\parameter{\dimt}{rs}{The row stride of $ F $.}
\parameter{\dimt}{cs}{The column stride of $ F $.}
\end{params}
\end{flaspec}

% --- FLASH_Copy_flat_to_hier() ------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Copy_flat_to_hier( FLA_Obj F, dim_t i, dim_t j, FLA_Obj H );
\end{verbatim}
\index{FLASH functions!\flashcopyflattohierns}
\purpose{
Copy the contents of a flat matrix $ F $ into the submatrix $ H_{ij} $ whose
top-left element is the $ (i,j) $ entry of hierarchical matrix $ H $, where
both $ F $ and $ H_{ij} $ are  $ m \by\ n $.
}
\begin{checks}
\checkitem
The numerical datatypes of $ F $ and $ H $ must be identical and
must not be \flaconstantns.
\itemvsp
\checkitem
$ H $ must be at least $ i+m \by j+n $.
\end{checks}
\begin{params}
\parameter{\flaobj}{F}{A flat \flaobj representing matrix $ F $.}
\parameter{\dimt}{i}{The row offset in $ H $ of the submatrix $ H_{ij} $.}
\parameter{\dimt}{j}{The column offset in $ H $ of the submatrix $ H_{ij} $.}
\parameter{\flaobj}{H}{A hierarchical \flaobj representing matrix $ H $.}
\end{params}
\end{flaspec}

% --- FLASH_Copy_hier_to_flat() ------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Copy_hier_to_flat( dim_t i, dim_t j, FLA_Obj H, FLA_Obj F );
\end{verbatim}
\index{FLASH functions!\flashcopyhiertoflatns}
\purpose{
Copy the contents of the submatrix $ H_{ij} $ whose top-left element is the
$ (i,j) $ entry of hierarchical matrix $ H $ into a flat matrix $ F $, where
both $ H_{ij} $ and $ F $ are  $ m \by\ n $.
}
\begin{checks}
\checkitem
The numerical datatypes of $ F $ and $ H $ must be identical and
must not be \flaconstantns.
\itemvsp
\checkitem
$ H $ must be at least $ i+m \by j+n $.
\end{checks}
\begin{params}
\parameter{\dimt}{i}{The row offset in $ H $ of the submatrix $ H_{ij} $.}
\parameter{\dimt}{j}{The column offset in $ H $ of the submatrix $ H_{ij} $.}
\parameter{\flaobj}{H}{A hierarchical \flaobj representing matrix $ H $.}
\parameter{\flaobj}{F}{A flat \flaobj representing matrix $ F $.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_hierarchify() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Obj_hierarchify( FLA_Obj F, FLA_Obj H );
\end{verbatim}
\index{FLASH functions!\flashobjhierarchifyns}
\purpose{
Copy the contents of a flat matrix $ F $ into a hierarchical matrix $ H $,
where both $ H $ and $ F $ are $ m \by n $.
}
\begin{checks}
\checkitem
The numerical datatypes of $ F $ and $ H $ must be identical and
must not be \flaconstantns.
\itemvsp
\checkitem
$ H $ must be at least $ m \by n $.
\end{checks}
\implnotes{
This function is currently implemented as: \\
\parbox{4in}{\hspace{4mm}{\tt FLASH\_Copy\_subobject\_to\_object( F, 0, 0, H );}}
}
\begin{params}
\parameter{\flaobj}{F}{A flat \flaobj representing matrix $ F $.}
\parameter{\flaobj}{H}{A hierarchical \flaobj representing matrix $ H $.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_flatten() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Obj_flatten( FLA_Obj H, FLA_Obj F );
\end{verbatim}
\index{FLASH functions!\flashobjflattenns}
\purpose{
Copy the contents of a hierarchical matrix $ H $ into a flat matrix $ F $,
where both $ H $ and $ F $ are $ m \by n $.
}
\begin{checks}
\checkitem
The numerical datatypes of $ F $ and $ H $ must be identical and
must not be \flaconstantns.
\itemvsp
\checkitem
$ H $ must be at least $ m \by n $.
\end{checks}
\implnotes{
This function is currently implemented as: \\
\parbox{4in}{\hspace{4mm}{\tt FLASH\_Copy\_object\_to\_subobject( 0, 0, F, H );}}
}
\begin{params}
\parameter{\flaobj}{H}{A hierarchical \flaobj representing matrix $ H $.}
\parameter{\flaobj}{F}{A flat \flaobj representing matrix $ F $.}
\end{params}
\end{flaspec}






\subsection{Interfacing with conventional matrix arrays}

% --- FLASH_Obj_create_without_buffer() ----------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Obj_create_without_buffer( FLA_Datatype datatype, dim_t m, dim_t n,
                                      dim_t depth, dim_t* b_mn, FLA_Obj* H );
\end{verbatim}
\index{FLASH functions!\flashobjcreatewithoutbufferns}
\purpose{
Create a new hierarchical object from an uninitialized \flaobj structure,
just as with \flashobjcreatens, except without any internal numerical
data buffer.
Before using the object, the user must attach a valid buffer with
\flashobjattachbufferns.
}
\begin{checks}
\checkitem
Neither $ m $ nor $ n $ may be zero.
\itemvsp
\checkitem
\datatype may not be \flaconstantns.
\itemvsp
\checkitem
The pointer arguments \bmn and {\tt H} must not be \fnullns.
\itemvsp
\checkitem
Each of the first \depth values in \bmn must be greater than zero.
\end{checks}
\begin{params}
\parameter{\fladatatype}{datatype}{A constant corresponding to the numerical datatype requested.} 
\parameter{\dimt}{m}{The number of rows to be created in new object.}
\parameter{\dimt}{n}{The number of columns to be created in the new object.}
\parameter{\dimt}{depth}{The number of levels of hierarchy in the object that represents matrix $ H $.}
\parameter{\dimt}{b\_mn}{A pointer to an array of \depth values to be used as blocksizes in creating the matrix hierarchy of $ H $.}
\parminout{\flaobjp}{H}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new, bufferless hierarchical \flaobj parameterized by {\tt m}, {\tt n}, \depthns, \bmnns, and \datatypens.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_create_without_buffer_ext() ------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Obj_create_without_buffer_ext( FLA_Datatype datatype, dim_t m, dim_t n,
                                          dim_t depth, dim_t* b_m, dim_t* b_n,
                                          FLA_Obj* H );
\end{verbatim}
\index{FLASH functions!\flashobjcreatewithoutbufferextns}
\purpose{
Create a new hierarchical object from an uninitialized \flaobj structure,
just as with \flashobjcreateextns, except without any internal numerical
data buffer.
Before using the object, the user must attach a valid buffer with
\flashobjattachbufferns.
}
\begin{checks}
\checkitem
Neither $ m $ nor $ n $ may be zero.
\itemvsp
\checkitem
\datatype may not be \flaconstantns.
\itemvsp
\checkitem
The pointer arguments \bmns, \bnns, and {\tt H} must not be \fnullns.
\itemvsp
\checkitem
Each of the first \depth values in \bm and \bn must be greater than zero.
\end{checks}
\begin{params}
\parameter{\fladatatype}{datatype}{A constant corresponding to the numerical datatype requested.} 
\parameter{\dimt}{m}{The number of rows to be created in new object.}
\parameter{\dimt}{n}{The number of columns to be created in the new object.}
\parameter{\dimt}{depth}{The number of levels of hierarchy in the object that represents matrix $ H $.}
\parameter{\dimt}{b\_m}{A pointer to an array of \depth values to be used as the row dimensions of the blocksizes needed when creating the matrix hierarchy of $ H $.}
\parameter{\dimt}{b\_n}{A pointer to an array of \depth values to be used as the column dimensions of the blocksizes needed when creating the matrix hierarchy of $ H $.}
\parminout{\flaobjp}{H}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new, bufferless hierarchical \flaobj parameterized by {\tt m}, {\tt n}, \depthns, \bmns, \bnns, and \datatypens.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_free_without_buffer() ------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Obj_free_without_buffer( FLA_Obj* H );
\end{verbatim}
\index{FLASH functions!\flashobjfreewithoutbufferns}
\purpose{
Release all resources allocated to a hierarchical object that was created
without a data buffer.
\flashobjfreewithoutbuffer should be used only with objects
that were allocated \flashobjcreatewithoutbufferns.
Upon returning, \obj points to a structure which is, for all intents and
purposes, uninitialized.
}
\notes{
If the object was created with \flashobjcreate or
\flashobjcreateconftons, you should free the object with
\flashobjfreens.
}
\begin{params}
\parminout{\flaobjp}{H}{A pointer to a valid hierarchical \flaobjns.}
                       {A pointer to an uninitialized \flaobjns.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_attach_buffer() ------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Obj_attach_buffer( void* buffer, dim_t rs, dim_t cs, FLA_Obj* H );
\end{verbatim}
\index{FLASH functions!\flashobjattachbufferns}
\purpose{
Attach a user-allocated region of memory to a hierarchical object that was
created with \flashobjcreatewithoutbufferns.
This routine is useful when the user, either by preference or necessity,
wishes to allocate and/or initialize memory for linear algebra objects before
encapsulating the data within a hierarchical object structure.
Note that it is important that the user submit the correct row and column
strides \rs and \csns, which, combined with the $ m $ and $ n $ dimensions
submitted when the object was created, will determine what region of memory is
accessible.
A leading dimension which is inadvertantly set too large may result in memory
accesses outside of the intended region during subsequent computation, which
will likely cause undefined behavior.
}
\notes{
When you are finished using a hierarchical \flaobj with an attached buffer, you
should free it with \flashobjfreewithoutbufferns.
However, you are still responsible for freeing the memory pointed to
by \buffer using {\tt free()} or whatever memory deallocation function
your system provides.
}
\begin{checks}
\checkitem
\rs and \cs must either both be zero, or non-zero.
Also, one of the two strides must be equal to $ 1 $.
If \rs is equal to $ 1 $, then \cs must be at least $ m $;
otherwise, if \cs is equal to $ 1 $, then \rs must be at least $ n $.
\end{checks}
\caveats{
This routine is not an ideal way to retrofit hierarchical storage into
your application.
The problem is that a ``native'' hierarchical object, one which was created
with its own data buffer, will contain leaf objects that refer to blocks
that are contiguous in memory, which provides performance benefits in the
way of spacial locality.
If a user creates a hierarchical object without a buffer and then attaches
an existing matrix stored conventionally, the memory referred to by 
individual leaf objects will not be contiguous due to the large leading
dimension (row or column stride) of the conventional matrix.
Therefore, we highly encourage users to create hierarchical matrices
one of two other ways:
\begin{itemize}
\item
Use \flashobjcreate and then initialize the matrix elements
incrementally, one submatrix at a time, with
\flashcopyflattohier or
\flashcopybuffertohierns.
\itemvsp
\item
Use \flashobjcreatehiercopyofflat to create a
hierarchical object and initialize it with the contents of an existing
flat object.
\end{itemize}
}
\begin{params}
\parameter{\voidp}{buffer}{A valid region of memory allocated by the user. Typically,
                           the address to this memory is obtained dynamically through
                           a system function such as {\tt malloc()}, but the memory
                           may also be statically allocated.}
\parameter{\dimt}{rs}{The row stride of the matrix stored conventionally in \bufferns.}
\parameter{\dimt}{cs}{The column stride of the matrix stored conventionally in \bufferns.}
\parminout{\flaobjp}{H}{A pointer to a valid hierarchical \flaobj that was created without a buffer.}
                       {A pointer to a valid hierarchical \flaobj that encapsulates the data in
                        \bufferns.}
\end{params}
\end{flaspec}






\subsection{Object query functions}
\label{sec:flash-obj-query}

% --- FLASH_Obj_datatype() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Datatype FLASH_Obj_datatype( FLA_Obj H );
\end{verbatim}
\index{FLASH functions!\flashobjdatatypens}
\purpose{
Query the numerical datatype of $ H $.
This corresponds to the numerical datatype of the data stored
at the leaves of the matrix hierarchy.
}
\notes{
Using \flashobjdatatype on a flat matrix will return the same
value as \flaobjdatatypens.
}
\rvalue{
A constant of type \fladatatypens.
}
\begin{params}
\parameter{\flaobj}{H}{An \flaobj representing matrix $ H $.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_scalar_length() ------------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLASH_Obj_scalar_length( FLA_Obj H );
\end{verbatim}
\index{FLASH functions!\flashobjscalarlengthns}
\purpose{
Query the scalar length of object view $ H $.
That is, query the number of rows in the view represented by $ H $.
}
\notes{
Using \flashobjscalarlength on a flat matrix will always return
the correct value (ie: the same as that returned by \flaobjlengthns).
However, using \flaobjlength on a hierarchical matrix will return
the number of rows of child objects within the the top level of the hierarchy
of $ H $.
The user should be aware of the difference, as the latter situation
is usually only of interest to developers.
}
\rvalue{
An unsigned integer value of type \dimt representing the number of rows in
$ H $.
}
\begin{params}
\parameter{\flaobj}{H}{An \flaobj representing matrix $ H $.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_scalar_width() -------------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLASH_Obj_scalar_width( FLA_Obj H );
\end{verbatim}
\index{FLASH functions!\flashobjscalarwidthns}
\purpose{
Query the scalar width of object view $ H $.
That is, query the number of columns in the view represented by $ H $.
}
\notes{
Using \flashobjscalarwidth on a flat matrix will always return
the correct value (ie: the same as that returned by \flaobjwidthns).
However, using \flaobjwidth on a hierarchical matrix will return
the number of columns of child objects within the the top level of the hierarchy
of $ H $.
The user should be aware of the difference, as the latter situation
is usually only of interest to developers.
}
\rvalue{
An unsigned integer value of type \dimt representing the number of columns in
$ H $.
}
\begin{params}
\parameter{\flaobj}{H}{An \flaobj representing matrix $ H $.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_depth() --------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLASH_Obj_depth( FLA_Obj H );
\end{verbatim}
\index{FLASH functions!\flashobjdepthns}
\purpose{
Query the depth of the object representing matrix $ H $.
This corresponds to the number of links between the root the hierarchy
and the leaf objects.
A depth of zero indicates that $ H $ is a flat matrix.
}
\notes{
Using \flashobjdepth on a flat matrix will always return $ 0 $.
}
\implnotes{
This routine assumes that all leaves are equidistant from the root
object $ H $.
}
\rvalue{
An unsigned integer value of type \dimt representing the depth of the hierarchy
within the object representing matrix $ H $.
}
\begin{params}
\parameter{\flaobj}{H}{An \flaobj representing matrix $ H $.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_blocksizes() ---------------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLASH_Obj_blocksizes( FLA_Obj H, dim_t* b_m, dim_t* b_n );
\end{verbatim}
\index{FLASH functions!\flashobjblocksizesns}
\purpose{
Query the row and column blocksizes used at each level of hierarchy within the
object that represents matrix $ H $ and store the values within the array
pointed to by \bm and \bnns.
The number of values stored to \bm and \bn will be equal to the depth
of $ H $, which is returned by the function.
}
\notes{
If $ H $ is a flat matrix, then no values are written to \bm or \bn
and zero is returned.
It is important that the length of the \bm and \bn arrays be sufficiently
large to handle the depth of $ H $.
}
\rvalue{
An unsigned integer value of type \dimt representing the depth of $ H $ and
number of blocksizes stored to the \bm and \bn arrays.
}
\begin{params}
\parameter{\flaobj}{H}{An \flaobj representing matrix $ H $.}
\parameter{\dimtp}{b\_m}{A pointer to an array of unsigned integers in which to store the row blocksizes of the matrix hierarchy of $ H $.}
\parameter{\dimtp}{b\_n}{A pointer to an array of unsigned integers in which to store the column blocksizes of the matrix hierarchy of $ H $.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_scalar_min_dim() -----------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLASH_Obj_scalar_min_dim( FLA_Obj obj );
\end{verbatim}
\index{FLASH functions!\flashobjscalarmindimns}
\purpose{
Query the smaller of the hierarchical object view's scalar length and width
dimensions.
}
\notes{
Using \flashobjscalarmindim on a flat matrix will return the same
value as \flaobjmindimns.
}
\rvalue{
An unsigned integer value of type \dimtns.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_scalar_max_dim() -----------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLASH_Obj_scalar_max_dim( FLA_Obj obj );
\end{verbatim}
\index{FLASH functions!\flashobjscalarmaxdimns}
\purpose{
Query the larger of the hierarchical object view's scalar length and width
dimensions.
}
\notes{
Using \flashobjscalarmaxdim on a flat matrix will return the same
value as \flaobjmaxdimns.
}
\rvalue{
An unsigned integer value of type \dimtns.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_base_scalar_length() -------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLASH_Obj_base_scalar_length( FLA_Obj H );
\end{verbatim}
\index{FLASH functions!\flashobjbasescalarlengthns}
\purpose{
Query the scalar length of the base object within $ H $.
That is, query the number of rows in the matrix represented by the object
$ H $ as it was originally allocated.
}
\notes{
Using \flashobjbasescalarlength on a flat matrix will return the same
value as \flaobjbaselengthns.
}
\rvalue{
An unsigned integer value of type \dimt representing the number of rows in
the base object of $ H $.
}
\begin{params}
\parameter{\flaobj}{H}{An \flaobj representing matrix $ H $.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_base_scalar_width() --------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLASH_Obj_base_scalar_width( FLA_Obj H );
\end{verbatim}
\index{FLASH functions!\flashobjbasescalarwidthns}
\purpose{
Query the scalar width of the base object within $ H $.
That is, query the number of columns in the matrix represented by the object
$ H $ as it was originally allocated.
}
\notes{
Using \flashobjbasescalarwidth on a flat matrix will return the same
value as \flaobjbasewidthns.
}
\rvalue{
An unsigned integer value of type \dimt representing the number of columns in
the base object of $ H $.
}
\begin{params}
\parameter{\flaobj}{H}{An \flaobj representing matrix $ H $.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_scalar_row_offset() --------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLASH_Obj_scalar_row_offset( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjrowoffsetns}
\purpose{
Query the scalar row offset of an object view \objns.
That is, query the row offset of the view relative to the top-left
corner of the underlying hierarchical matrix.
}
\notes{
Using \flashobjscalarrowoffset on a flat matrix will return the same
value as \flaobjrowoffsetns.
}
\notes{
This routine should only be used by advanced users and developers.
}
\rvalue{
An unsigned integer value of type \dimtns.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}

% --- FLASH_Obj_scalar_col_offset() --------------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLASH_Obj_scalar_col_offset( FLA_Obj obj );
\end{verbatim}
\index{FLAME/C functions!\flaobjcoloffsetns}
\purpose{
Query the scalar column offset of an object view \objns.
That is, query the column offset of the view relative to the top-left
corner of the underlying hierarchical matrix.
}
\notes{
Using \flashobjscalarcoloffset on a flat matrix will return the same
value as \flaobjcoloffsetns.
}
\notes{
This routine should only be used by advanced users and developers.
}
\rvalue{
An unsigned integer value of type \dimtns.
}
\begin{params}
\parameter{\flaobj}{obj}{An \flaobjns.}
\end{params}
\end{flaspec}





\subsection{Managing Views}
\label{sec:flash-views}




\subsubsection{Vertical partitioning}




% --- FLASH_Part_create_2x1() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLASH_Part_create_2x1( FLA_Obj A,  FLA_Obj* AT,
                                             FLA_Obj* AB,
                                 dim_t  mb,  FLA_Side side );
\end{verbatim}
\index{FLASH functions!\flashpartcreatetwobyonens}
\purpose{
Partition a hierarchical matrix $ A $ into top and bottom side views where
the side indicated by \side has \mb rows.
}
\notes{
Unlike with \flaparttwobyonens, the two views created by
\flashpartcreatetwobyone must be explicitly freed by a corresponding call to
\flashpartfreetwobyonens.
}
\implnotes{
This function performs a deep copy of the matrix hierarchy of $ A $ but
creates leaf nodes that simply refer back to the original data in $ A $.
}
\rvalue{
\flasuccess
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobjns.}
\parminout{\flaobjp}{AT}{A pointer to an uninitialized \flaobjns.}
                        {A pointer to a hierarchical \flaobj view into the top side of \Ans.}
\parminout{\flaobjp}{AB}{A pointer to an uninitialized \flaobjns.}
                        {A pointer to a hierarchical \flaobj view into the bottom side of \Ans.}
\parameter{\dimt}{mb}{The number of rows to extract.}
\parameter{\flaside}{side}{The side to which to extract {\tt mb} rows.}
\end{params}
\end{flaspec}

% --- FLASH_Part_free_2x1() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLASH_Part_free_2x1( FLA_Obj* AT, FLA_Obj* AB );
\end{verbatim}
\index{FLASH functions!\flashpartfreetwobyonens}
\purpose{
Free the top and bottom side views that were previously created by
\flashpartcreatetwobyonens.
}
\rvalue{
\flasuccess
}
\begin{params}
\parminout{\flaobjp}{AT}{A pointer to a valid hierarchical \flaobj view.}
                        {A pointer to an uninitialized \flaobjns.}
\parminout{\flaobjp}{AB}{A pointer to a valid hierarchical \flaobj view.}
                        {A pointer to an uninitialized \flaobjns.}
\end{params}
\end{flaspec}



\subsubsection{Horizontal partitioning}




% --- FLASH_Part_create_1x2() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLASH_Part_create_1x2( FLA_Obj A,  FLA_Obj* AL, FLA_Obj* AR,
                                             dim_t    nb, FLA_Side side );
\end{verbatim}
\index{FLASH functions!\flashpartcreateonebytwons}
\purpose{
Partition a hierarchical matrix $ A $ into left and right side views where
the side indicated by \side has \nb columns.
}
\notes{
Unlike with \flapartonebytwons, the two views created by
\flashpartcreateonebytwo must be explicitly freed by a corresponding call to
\flashpartfreeonebytwons.
}
\implnotes{
This function performs a deep copy of the matrix hierarchy of $ A $ but
creates leaf nodes that simply refer back to the original data in $ A $.
}
\rvalue{
\flasuccess
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobjns.}
\parminout{\flaobjp}{AL}{A pointer to an uninitialized \flaobjns.}
                        {A pointer to a hierarchical \flaobj view into the left side of \Ans.}
\parminout{\flaobjp}{AR}{A pointer to an uninitialized \flaobjns.}
                        {A pointer to a hierarchical \flaobj view into the right side of \Ans.}
\parameter{\dimt}{nb}{The number of columns to extract.}
\parameter{\flaside}{side}{The side to which to extract {\tt nb} columns.}
\end{params}
\end{flaspec}

% --- FLASH_Part_free_1x2() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLASH_Part_free_1x2( FLA_Obj* AL, FLA_Obj* AR );
\end{verbatim}
\index{FLASH functions!\flashpartfreeonebytwons}
\purpose{
Free the left and right side views that were previously created by
\flashpartcreateonebytwons.
}
\rvalue{
\flasuccess
}
\begin{params}
\parminout{\flaobjp}{AL}{A pointer to a valid hierarchical \flaobj view.}
                        {A pointer to an uninitialized \flaobjns.}
\parminout{\flaobjp}{AR}{A pointer to a valid hierarchical \flaobj view.}
                        {A pointer to an uninitialized \flaobjns.}
\end{params}
\end{flaspec}




\subsubsection{Bidirectional partitioning}




% --- FLASH_Part_create_2x2() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLASH_Part_create_2x2( FLA_Obj A,  FLA_Obj* ATL, FLA_Obj* ATR,
                                             FLA_Obj* ABL, FLA_Obj* ABR,
                                 dim_t  mb,  dim_t     nb, FLA_Quadrant quadrant );
\end{verbatim}
\index{FLASH functions!\flaparttwobytwons}
\purpose{
Partition a hierarchical matrix $ A $ into four quadrant views where the
quadrant indicated by \quadrant is $ \mb \by \nbns $.
}
\notes{
Unlike with \flaparttwobytwons, the four quadrant views created by
\flashpartcreatetwobytwo must be explicitly freed by a corresponding call to
\flashpartfreetwobytwons.
}
\implnotes{
This function performs a deep copy of the matrix hierarchy of $ A $ but
creates leaf nodes that simply refer back to the original data in $ A $.
}
\rvalue{
\flasuccess
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobjns.}
\parminout{\flaobjp}{ATL...ABR}{Pointers to uninitialized \flaobj structures.}
                               {Pointers to hierarchical \flaobj views into the four quadrants of \Ans.}
\parameter{\dimt}{mb}{The number of rows to extract.}
\parameter{\dimt}{nb}{The number of columns to extract.}
\parameter{\flaquadrant}{quadrant}{The quadrant to which to extract {\tt mb} rows and
                                   {\tt nb columns}.}
\end{params}
\end{flaspec}

% --- FLASH_Part_free_2x2() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLASH_Part_free_2x2( FLA_Obj* ATL, FLA_Obj* ATR,
                               FLA_Obj* ABL, FLA_Obj* ABR );
\end{verbatim}
\index{FLASH functions!\flashpartfreetwobytwons}
\purpose{
Free the quadrant views that were previously created by
\flashpartcreatetwobytwons.
}
\rvalue{
\flasuccess
}
\begin{params}
\parminout{\flaobjp}{ATL}{A pointer to a valid hierarchical \flaobj view.}
                         {A pointer to an uninitialized \flaobjns.}
\parminout{\flaobjp}{ABL}{A pointer to a valid hierarchical \flaobj view.}
                         {A pointer to an uninitialized \flaobjns.}
\parminout{\flaobjp}{ATR}{A pointer to a valid hierarchical \flaobj view.}
                         {A pointer to an uninitialized \flaobjns.}
\parminout{\flaobjp}{ABR}{A pointer to a valid hierarchical \flaobj view.}
                         {A pointer to an uninitialized \flaobjns.}
\end{params}
\end{flaspec}



\subsection{Utility functions}
\label{sec:flash-utility-functions}




\subsubsection{Miscellaneous functions}



% --- FLA_Obj_show() -----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLASH_Obj_show( char* header, FLA_Obj H, char* format, char* footer );
\end{verbatim}
\index{FLASH functions!\flashobjshowns}
\purpose{
Display the numerical values contained in the hierarchical object view $ H $.
The string {\tt header} is output first (followed by a newline), then
formatted contents of \objns, and finally the string {\tt footer}
(followed by a newline).
The string {\tt format} should contain a {\tt printf()}-style format string
that describes how to output each element of the matrix.
Note that {\tt format} must be set according to the numerical contents of
\objns.
For example, if the datatype of \obj is \fladoublens, the user may choose
to use {\tt "\%11.3e"} as the {\tt format} string.
Similarly, if the object datatype were \fladoublecomplexns, the user would
want to use something like {\tt "\%11.3e + \%11.3e"} in order to denote
the real and imaginary components.
}
\notes{
Using \flashobjshow on a flat matrix object will yield the same output as
using \flaobjshowns.
}
\rvalue{
\flasuccess
}
\begin{params}
\parameter{\charp}{header}{A pointer to a string to precede the formatted output of \objns.}
\parameter{\charp}{format}{A pointer to a {\tt printf()}-style format string.}
\parameter{\flaobj}{obj}{A hierarchical \flaobjns.}
\parameter{\charp}{footer}{A pointer to a string to proceed the formatted output of \objns.}
\end{params}
\end{flaspec}










\section{SuperMatrix}
\label{sec:supermatrix}

\index{SuperMatrix!description}


\subsection{Overview}

SuperMatrix is an extension to the FLAME/C and FLASH APIs that enables
task-level parallel execution via algoriths-by-blocks
\cite{spaa2007}.
The SuperMatrix runtime system itself is dependency-aware, and therefore
is a major step forward when compared to more primitive workqueuing-based
solutions \cite{workqueuing2008}.

The mechanism works as follows.
Subproblems within a FLAME algorithm implementation are replaced, via macros,
with calls to a routine that enqueues all pertinent information about the
subproblem onto a global task queue.
This information includes a function pointer to the computational routine
that would normally execute the subproblem and references to the subproblem's
arguments.
The algorithm is then run sequentially, at which time the subproblem instances,
or tasks, are enqueued.
As tasks are enqueued, a dependency graph is incrementally constructed, which
tracks flow, anti-, and output dependencies between tasks.
After enqueuing is complete, the SuperMatrix runtime system is invoked.
Tasks marked as ``ready'' are dequeued by independent threads and executed.
When a task is complete, the dependency graph is updated, and unexecuted tasks
are marked as ready as soon as all of their dependencies are satisfied.
This process continues until all tasks have been executed.

A computational routine parallelized by SuperMatrix uses the same algorithmic
variant implementations employed by sequential FLAME/C and sequential FLASH
routines.
For interested developers or other curious readers, you may find a discussion
of the mechanism that makes this reuse of code possible in Section
\ref{sec:cntl-trees}.

The interface to the SuperMatrix mechanism and characteristics of its \libflame
implementation have been thoroughly documented in the literature
\cite{SuperMatrix:PPoPP08,spaa2007}.
Please see these texts for futher information regarding SuperMatrix.




\subsection{API}

In this subsection we document all of the \libflame interfaces needed to use
SuperMatrix in your application.
The developer-level interfaces are documented in Section \ref{sec:sm-dev}.



% --- FLASH_Queue_enable() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLASH_Queue_enable( void );
\end{verbatim}
\index{SuperMatrix functions!\flashqueueenablens}
\purpose{
Enable SuperMatrix.
By enabling SuperMatrix, the user enables algorithm-level shared memory
parallelism within FLASH-based computational routines.
If SuperMatrix is already enabled, the function has no effect.
}
\notes{
If SuperMatrix was enabled at configure-time, \flainit will call
this function, and thus the user does not need to invoke it unless
SuperMatrix was temporarily disabled via \flashqueuedisablens.
If SuperMatrix was disabled at configure-time, the function aborts with an
error message.
}
\rvalue{
\flasuccess if successful or if SuperMatrix is already enabled; \flafailure if
the function was called from within a parallel region (ie: after
\flashqueuebegin and before \flashqueueendns).
}
\end{flaspec}

% --- FLASH_Queue_disable() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLASH_Queue_disable( void );
\end{verbatim}
\index{SuperMatrix functions!\flashqueuedisablens}
\purpose{
Disable SuperMatrix.
By disabling SuperMatrix, the user disables algorithm-level shared memory
parallelism within FLASH-based computational routines.
When SuperMatrix is disabled, these routines revert back to executing
sequentially, though they still expect hierarchical storage.
If SuperMatrix is already disabled, the function has no effect.
}
\notes{
If SuperMatrix was enabled at configure-time, the user should only invoke
this function if he wants to temporariliy disable SuperMatrix in order to
run sequential FLASH implementations.
If SuperMatrix was disabled at configure-time, the function unconditionally
returns \flasuccessns.
}
\rvalue{
\flasuccess if successful or if SuperMatrix was disabled at configure-time;
\flafailure if the function was called from within a parallel region (ie: after
\flashqueuebegin and before \flashqueueendns).
}
\end{flaspec}

% --- FLASH_Queue_get_enabled() ------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLASH_Queue_get_enabled( void );
\end{verbatim}
\index{SuperMatrix functions!\flashqueuegetenabledns}
\purpose{
Query whether SuperMatrix is currently enabled.
}
\notes{
If SuperMatrix was disabled at configure-time, the function unconditionally
returns \falsens.
}
\rvalue{
\true if SuperMatrix was enabled at configure-time and is also currently
enabled;
\false if SuperMatrix was disabled at configure-time or if SuperMatrix
was enabled at configure-time but is currently disabled.
}
\end{flaspec}

% --- FLASH_Queue_begin() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Queue_begin( void );
\end{verbatim}
\index{SuperMatrix functions!\flashqueuebeginns}
\purpose{
Mark the beginning of a parallel region.
The parallel region continues until the user invokes \flashqueueendns.
}
\notes{
Any FLASH computational routines found in a parallel region will be parallelized
in a way that overlaps the tasks' computation in whatever order the scheduler
sees fit while still observing dependencies between tasks.
}
\end{flaspec}

% --- FLASH_Queue_end() --------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Queue_end( void );
\end{verbatim}
\index{SuperMatrix functions!\flashqueueendns}
\purpose{
Mark the end of a parallel region.
The parallel region begins when the user invokes \flashqueuebeginns.
}
\notes{
Any FLASH computational routines found in a parallel region will be parallelized
in a way that overlaps the tasks' computation in whatever order the scheduler
sees fit while still observing dependencies between tasks.
}
\end{flaspec}

% --- FLASH_Queue_set_num_threads() --------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Queue_set_num_threads( unsigned int n_threads );
\end{verbatim}
\index{SuperMatrix functions!\flashqueuesetnumthreadsns}
\purpose{
Set the number of threads that SuperMatrix will use when executing tasks in
parallel.
}
\notes{
This routine does not immediately cause SuperMatrix to spawn any threads.
}
\begin{params}
\parameter{\uint}{n\_threads}{An unsigned integer representing the number of threads to be requested upon parallel execution.}
\end{params}
\end{flaspec}

% --- FLASH_Queue_get_num_threads() --------------------------------------------

\begin{flaspec}
\begin{verbatim}
unsigned int FLASH_Queue_get_num_threads( void );
\end{verbatim}
\index{SuperMatrix functions!\flashqueuegetnumthreadsns}
\purpose{
Query the number of threads that SuperMatrix is currently set to use when
executing tasks in parallel.
}
\rvalue{
An unsigned integer representing the number of threads that SuperMatrix is
currently set to use in parallel execution.
}
\end{flaspec}

% --- FLASH_Queue_set_verbose_output() -----------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Queue_set_verbose_output( FLASH_Verbose verbose );
\end{verbatim}
\index{SuperMatrix functions!\flashqueuesetverboseoutputns}
\purpose{
Set or disable verboseness in SuperMatrix, particularly with regard
to the dependency graph as it is generated.
Three constant values are accepted for {\tt verbose}:
\begin{itemize}
\item
\flashqueueverbosenonens.
Verbose mode is disabled altogether.
\item
\flashqueueverbosereadablens.
Human-readable dependency information is printed to standard output as
execution progresses.
\item
\flashqueueverbosegraphvizns.
Dependency information is printed to standard output in the DOT language
format, which is readable by the {\tt graphviz} utility.
\end{itemize}
}
\begin{params}
\parameter{\flashverbose}{verbose}{A value that sets or disables SuperMatrix verbosity.}
\end{params}
\end{flaspec}

% --- FLASH_Queue_get_verbose_output() -----------------------------------------

\begin{flaspec}
\begin{verbatim}
FLASH_Verbose FLASH_Queue_get_verbose_output( void );
\end{verbatim}
\index{SuperMatrix functions!\flashqueuegetverboseoutputns}
\purpose{
Query the current status of verbosity in SuperMatrix.
}
\rvalue{
A constant value of type \flashverbosens.
}
\end{flaspec}

% --- FLASH_Queue_set_sorting() ------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Queue_set_sorting( FLA_Bool sorting );
\end{verbatim}
\index{SuperMatrix functions!\flashqueuesetsortingns}
\purpose{
Enable or disable task sorting in SuperMatrix.
When sorting is enabled, SuperMatrix will sort its queue of ready-and-waiting
tasks according to some heuristic.
}
\begin{params}
\parameter{\flabool}{sorting}{A boolean value that either enables (\true) or disables (\false) SuperMatrix task sorting.}
\end{params}
\end{flaspec}

% --- FLASH_Queue_get_sorting() ------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLASH_Queue_get_sorting( void );
\end{verbatim}
\index{SuperMatrix functions!\flashqueuegetsortingns}
\purpose{
Query the current status of task sorting in SuperMatrix.
}
\rvalue{
A boolean value; \true if SuperMatrix is currently set to sort tasks prior to
execution, \false otherwise.
}
\end{flaspec}

% --- FLASH_Queue_set_data_affinity() ------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Queue_set_data_affinity( FLASH_Data_aff data_aff );
\end{verbatim}
\index{SuperMatrix functions!\flashqueuesetdataaffinityns}
\purpose{
Set the style of data affinity for use in SuperMatrix execution.
This setting determines that manner in which blocks are assigned and bound
to threads (if at all).
Five constant values are accepted for {\tt data\_aff}:
\begin{itemize}
\item
\flashqueueaffinitynonens.
Data affinity is disabled altogether, allowing threads to execute tasks
regardless of which blocks they update.
\itemvsp
\item
\flashqueueaffinitytdblockcyclicns.
Blocks are assigned and bound to threads in a two-dimensional block cyclic
manner.
\itemvsp
\item
\flashqueueaffinityodrowblockcyclicns.
Blocks are assigned and bound to threads in a one-dimensional block cyclic
manner within rows.
\itemvsp
\item
\flashqueueaffinityodcolumnblockcyclicns.
Blocks are assigned and bound to threads in a one-dimensional block cyclic
manner within columns.
\itemvsp
\item
\flashqueueaffinityroundrobinns.
Blocks are assigned and bound to threads in a round-robin manner.
\end{itemize}
}
\notes{
This feature is different but complimentary to CPU affinity implemented by
some operating system schedulers, including the process scheduler present in
the Linux kernel as of version 2.6.25.
CPU affinity binds processes (and threads) to individual processors, or
processor cores.
Data affinity binds matrix blocks to individual threads.
The idea behind using them together is to improve performance by reducing the
need for matrix blocks to be migrate between CPU caches as the tasks are
executed.  
}
\caveats{
The data affinity mode associated with \flashqueueaffinityroundrobin has not
yet been implemented.
}
\begin{params}
\parameter{\int}{data\_aff}{A constant value that specifies the kind of data affinity to use during parallel execution.}
\end{params}
\end{flaspec}

% --- FLASH_Queue_get_data_affinity() ------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLASH_Data_aff FLASH_Queue_get_data_affinity( void );
\end{verbatim}
\index{SuperMatrix functions!\flashqueuegetdataaffinityns}
\purpose{
Query the current status of data affinity in SuperMatrix.
}
\rvalue{
A constant value of type \flashdataaffns.
}
\end{flaspec}

% --- FLASH_Queue_enable_gpu() -------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLASH_Queue_enable_gpu( void );
\end{verbatim}
\index{SuperMatrix functions!\flashqueueenablegpuns}
\purpose{
Enable run-time support for GPU execution.
When enabled, SuperMatrix tasks that are GPU-supported are executed on GPUs,
while all other tasks are run on the CPU.
}
\rvalue{
\flasuccess if SuperMatrix is enabled and a parallel region has not yet
begun;
\flafailure otherwise.
}
\end{flaspec}

% --- FLASH_Queue_disable_gpu() ------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLASH_Queue_disable_gpu( void );
\end{verbatim}
\index{SuperMatrix functions!\flashqueuedisablegpuns}
\purpose{
Disable run-time support for GPU execution.
When disabled, all SuperMatrix tasks are run on the CPU.
}
\rvalue{
\flasuccess if a parallel region has not yet begun;
\flafailure otherwise.
}
\end{flaspec}

% --- FLASH_Queue_get_enabled_gpu() --------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Bool FLASH_Queue_get_enabled_gpu( void );
\end{verbatim}
\index{SuperMatrix functions!\flashqueuegetenabledgpuns}
\purpose{
Query whether GPU execution is currently enabled.
}
\notes{
If SuperMatrix is currently disabled, the function returns \false regardless
of whether GPU execution was previously enabled.
}
\rvalue{
\true if SuperMatrix and GPU execution are both enabled;
\false if SuperMatrix is disabled, or if SuperMatrix is enabled but GPU
execution is disabled.
}
\end{flaspec}

% --- FLASH_Queue_set_gpu_num_blocks() -----------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Queue_set_gpu_num_blocks( dim_t n_blocks );
\end{verbatim}
\index{SuperMatrix functions!\flashqueuesetgpunumblocksns}
\purpose{
Set the number of storage blocks maintained by each GPU.
}
\notes{
If the user encounters a run-time error reporting that an attempt to allocate
memory on the GPU failed, it may be necessary to set \nblocks
to a lower value. 
}
\begin{params}
\parameter{\dimt}{n\_blocks}{An unsigned integer representing the number of blocks maintained by each GPU.}
\end{params}
\end{flaspec}

% --- FLASH_Queue_get_gpu_num_blocks() -----------------------------------------

\begin{flaspec}
\begin{verbatim}
dim_t FLASH_Queue_get_gpu_num_blocks( void );
\end{verbatim}
\index{SuperMatrix functions!\flashqueuegetgpunumblocksns}
\purpose{
Query the number of storage blocks maintained by each GPU.
}
\rvalue{
An unsigned integer representing the number of blocks maintained by each GPU.
}
\end{flaspec}







\subsection{Integration with FLASH front-ends}

\index{SuperMatrix!integration with FLASH}
\index{SuperMatrix!preconditions for enabling}

SuperMatrix is invoked through the same FLASH front-end functions that
are documented in Section \ref{sec:front-ends}.\footnote{If a FLASH front-end
does not exist for a particular operation, this means that the corresponding
SuperMatrix implementation also does not yet exist.}
In order to enable the parallelized implementations, the following
conditions must be met:
\begin{itemize}

\item
Multithreading must be enabled at configure-time.
This is accomplished by running configure with the
{\tt --enable-multithreading=openmp} or
{\tt --enable-multithreading=pthreads} option, depending on which multithreading
implementation is desired.

\item
SuperMatrix must be enabled at configure-time.
This is accomplished by running configure with the
{\tt --enable-supermatrix} option.

\item
SuperMatrix must be enabled at runtime.
If SuperMatrix was enabled at configure-time, then it is automatically enabled
at runtime by \flainit and therefore the user does not need to take
any further action.
However, SuperMatrix may be disabled at runtime manually through
\flashqueuedisablens, which causes all FLASH-based
computational routines to revert to executing sequentially.
Subsequently, the user can make the parallelized implementations available
again by simply calling the \flashqueueenable
routine.

\end{itemize}

SuperMatrix implementations may be run in an overlapped manner by enclosing
the computational invocations with \flashqueuebegin and
\flashqueueendns.
Please see Section \ref{sec:sm-examples} concrete examples of how to
use this and other features of SuperMatrix.










\section{Front-ends}
\label{sec:front-ends}





This section documents the interfaces to the featured computational routines 
provided by \libflamens.
We refer to these interfaces as {\em front-ends}, because they form the
primary set of APIs for use by users at the application-level.
None of these routines are direct wrappers to external implementations.%
\footnote{
There are two exceptions to this: \flatrmmsx and \flatrsmsxns.
These routines {\em are} in fact direct wrappers to external implemenations,
as \libflame does not contain native implemenations of the \trmmsx and
\trsmsx operations.
These routines are also convenient for those who do not wish to call the
somewhat longer functions named \flatrmmsxext and \flatrsmsxextns.
}
All computational front-ends employ FLAME algorithmic variants in some
capacity, either to produce a blocked algorithm or an algorithm-by-blocks,
the latter of which uses hierarchical storage and may be executed either
sequentially or in parallel.
For more information on the mechanisms behind hierarchical storage and
parallel execution, please see
Sections \ref{sec:flash} and \ref{sec:supermatrix}, respectively.

\subsection{BLAS operations}



\subsubsection{Level-1 BLAS}

% --- FLA_Amax() ---------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Amax( FLA_Obj x, FLA_Obj i );
\end{verbatim}
\index{FLAME/C functions!\flaamaxns}
\purpose{
Find the index $ i $ of the element of $ x $ which has the maximum
absolute value, where $ x $ is a general vector and $ i $ is a scalar.
If the maximum absolute value is shared by more than one element, then
the element whose index is highest is chosen.
}
\begin{checks}
\checkitem
The numerical datatype of $ x $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
The numerical datatype of $ i $ must be integer, and must not be
\flaconstantns.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flaamaxextns.
}
\begin{params}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{i}{An \flaobj representing scalar $ i $.}
\end{params}
\end{flaspec}

% --- FLA_Asum() ---------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Asum( FLA_Obj x, FLA_Obj norm1 );
\end{verbatim}
\index{FLAME/C functions!\flaasumns}
\purpose{
Compute the 1-norm of a vector:
\begin{eqnarray*}
\|x\|_1 & := &  \sum_{i=0}^{n-1} |\chi_i|
\end{eqnarray*}
where $ \|x\|_1 $ is a scalar and $ \chi_{i} $ is the $ i $th element of
general vector $ x $ of length $ n $.
Upon completion, the 1-norm $ \|x\|_1 $ is stored to \normons.
}
\implnotes{
This function is implemented as a wrapper to \flaasumextns.
}
\begin{checks}
\checkitem
The numerical datatype of $ x $ must be floating-point and must not be
\flaconstantns.
\itemvsp
\checkitem
The numerical datatype of \normo must be real and must not be
\flaconstantns.
\itemvsp
\checkitem
The precision of the datatype of \normo must be equal to that of $ x $.
\end{checks}
\begin{params}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{norm1}{An \flaobj representing scalar $ \|x\|_1 $.}
\end{params}
\end{flaspec}

% --- FLA_Axpy() ---------------------------------------------------------------
% --- FLASH_Axpy() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Axpy( FLA_Obj alpha, FLA_Obj A, FLA_Obj B );
void FLASH_Axpy( FLA_Obj alpha, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaaxpyns}
\index{FLASH functions!\flashaxpyns}
\purpose{
Perform an {\sc axpy} operation:
\begin{eqnarray*}
B & := & B + \alpha A
\end{eqnarray*}
where $ \alpha $ is a scalar, and $ A $ and $ B $ are general matrices.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ B $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatypes of $ A $ and $ B $.
\itemvsp
\checkitem
The dimensions of $ A $ and $ B $ must be conformal.
\end{checks}
\ifacenotes{
\flaaxpy expects $ A $ and $ B $ to be flat matrix objects.
}
\implnotes{
\flaaxpy simply invokes the external BLAS wrapper \flaaxpyextns.
\flashaxpy uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc axpy} operation into subproblems
expressed in terms of individual blocks of $ A $ and $ B $ and then
invokes \flaaxpyext to perform the computation on these blocks.
}
\begin{params}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Axpyt() --------------------------------------------------------------
% --- FLASH_Axpyt() ------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Axpyt( FLA_Trans trans, FLA_Obj alpha, FLA_Obj A, FLA_Obj B );
void FLASH_Axpyt( FLA_Trans trans, FLA_Obj alpha, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaaxpytns}
\index{FLASH functions!\flashaxpytns}
\purpose{
Perform one of the following extended {\sc axpy} operations:
\begin{eqnarray*}
B & := & B + \alpha A \\
B & := & B + \alpha A^T \\
B & := & B + \alpha \bar{A} \\
B & := & B + \alpha A^H
\end{eqnarray*}
where $ \alpha $ is a scalar, and $ A $ and $ B $ are general matrices.
The \trans argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
}
\notes{
If $ A $ and $ B $ are vectors, \flaaxpyt will implicitly and
automatically perform the transposition necessary to achieve conformal
dimensions regardless of the value of \transns.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ B $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatypes of $ A $ and $ B $.
\itemvsp
\checkitem
If $ A $ and $ B $ are vectors, then their lengths must be equal. Otherwise,
if \trans equals \flanotranspose or \flaconjnotransposens, then the dimensions
of $ A $ and $ B $ must be conformal; otherwise, if \trans equals
\flatranspose or \flaconjtransposens, then the dimensions of $ A^T $ and $ B $
must be conformal.
\end{checks}
\ifacenotes{
\flaaxpyt expects $ A $ and $ B $ to be flat matrix objects.
}
\implnotes{
\flaaxpyt simply invokes the external BLAS wrapper \flaaxpytextns.
\flashaxpyt uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the extended {\sc axpy} operation
into subproblems
expressed in terms of individual blocks of $ A $ and $ B $ and then
invokes \flaaxpytext to perform the computation on these blocks.
}
\begin{params}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if $ A $ were conjugated and/or transposed.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Axpyrt() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Axpyrt( FLA_Uplo uplo, FLA_Trans trans, FLA_Obj alpha, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaaxpyrtns}
\purpose{
Perform one of the following extended {\sc axpy} operations:
\begin{eqnarray*}
B & := & B + \alpha A        \\
B & := & B + \alpha A^T      \\
B & := & B + \alpha \bar{A}  \\
B & := & B + \alpha A^H
\end{eqnarray*}
where $ A $ and $ B $ are triangular (or trapezoidal) matrices.
The \uplo argument indicates whether the lower or upper triangle of $ B $
is updated by the operation.
The \trans argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
Note that the \uplo and \trans arguments together determine which triangle
of $ A $ is read and which triangle of $ B $ is updated.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ B $ must be identical,
and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatypes of $ X $ and $ Y $.
\itemvsp
\checkitem
If \trans equals \flanotranspose or \flaconjnotransposens, then the dimensions
of $ A $ and $ B $ must be conformal; otherwise, if \trans equals
\flatranspose or \flaconjtransposens, then the dimensions of $ A^T $ and $ B $
must be conformal.
\end{checks}
\ifacenotes{
\flaaxpyrt expects $ A $ and $ B $ to be flat matrix objects.
}
\implnotes{
This function is implemented as a wrapper to \flaaxpyrtextns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangles of $ A $ and $ B $ are referenced and updated during the operation.}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if $ A $ were conjugated and/or transposed.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Axpys() --------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Axpys( FLA_Obj alpha0, FLA_Obj alpha1, FLA_Obj A, FLA_Obj beta, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaaxpysns}
\purpose{
Perform the following extended {\sc axpy} operation:
\begin{eqnarray*}
B & := & \beta B + \alpha_0 \alpha_1 A
\end{eqnarray*}
where $ \alpha_0 $, $ \alpha_1 $ and $ \beta $ are scalars, and $ A $ and $ B $
are general matrices.
}
\notes{
If $ A $ and $ B $ are vectors, \flaaxpys will implicitly and
automatically perform the transposition necessary to achieve conformal
dimensions.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ B $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha_0 $, $ \alpha_1 $, and $ \beta $ are not of datatype \flaconstantns,
then they must match the datatypes of $ A $ and $ B $.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flaaxpysextns.
}
\begin{params}
\parameter{\flaobj}{alpha0}{An \flaobj representing scalar $ \alpha_0 $.}
\parameter{\flaobj}{alpha1}{An \flaobj representing scalar $ \alpha_1 $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Copy() ---------------------------------------------------------------
% --- FLASH_Copy() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Copy( FLA_Obj A, FLA_Obj B );
void FLASH_Copy( FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flacopyns}
\index{FLASH functions!\flashcopyns}
\purpose{
Copy the numerical contents of matrix $ A $ to matrix $ B $.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ B $ must be identical and
must not be \flaconstantns.
\itemvsp
\checkitem
The dimensions of $ A $ and $ B $ must be conformal.
\end{checks}
\ifacenotes{
\flacopy expects $ A $ and $ B $ to be flat matrix objects.
}
\implnotes{
\flacopy simply invokes the external BLAS wrapper \flacopyextns.
\flashcopy uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc copy} operation into subproblems
expressed in terms of individual blocks of $ A $ and $ B $ and then
invokes \flacopyext to perform the computation on these blocks.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Copyr() --------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Copyr( FLA_Uplo uplo, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flacopyrns}
\purpose{
Perform an extended copy operation on triangular matrices $ A $ and $ B $:
\begin{eqnarray*}
B & := & A
\end{eqnarray*}
where $ A $ and $ B $ are triangular (or trapezoidal) matrices.
The \uplo argument indicates whether the lower or upper triangles of $ A $
and $ B $ are referenced and updated by the operation.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ B $ must be identical,
and must not be \flaconstantns.
\itemvsp
\checkitem
The dimensions of $ A $ and $ B $ must be conformal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flacopyrextns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangles of $ A $ and $ B $ are referenced and updated during the operation.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Copyrt() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Copyrt( FLA_Uplo uplo, FLA_Trans trans, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flacopyrtns}
\purpose{
Perform an extended copy operation on triangular matrices $ A $ and $ B $:
\begin{eqnarray*}
B & := & A        \\
B & := & A^T      \\
B & := & \bar{A}  \\
B & := & A^H
\end{eqnarray*}
where $ A $ and $ B $ are triangular (or trapezoidal) matrices.
The \uplo argument indicates whether the lower or upper triangle of $ B $
is updated by the operation.
The \trans argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
Note that the \uplo and \trans arguments together determine which triangle
of $ A $ is read and which triangle of $ B $ is overwritten.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ B $ must be identical,
and must not be \flaconstantns.
\itemvsp
\checkitem
The dimensions of $ A $ and $ B $ must be conformal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flacopyrtextns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangles of $ A $ and $ B $ are referenced and updated during the operation.}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if $ A $ were conjugated and/or transposed.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Copyt() --------------------------------------------------------------
% --- FLASH_Copyt() ------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Copyt( FLA_Trans trans, FLA_Obj A, FLA_Obj B );
void FLASH_Copyt( FLA_Trans trans, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flacopytns}
\index{FLASH functions!\flashcopytns}
\purpose{
Copy the numerical contents of $ A $ to $ B $ with one of the following
extended copy operations:
\begin{eqnarray*}
B & := & A \\
B & := & A^T \\
B & := & \bar{A} \\
B & := & A^H
\end{eqnarray*}
where $ A $ and $ B $ are general matrices.
The \trans argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
}
\notes{
If $ A $ and $ B $ are vectors, \flacopyt will implicitly and
automatically perform the transposition necessary to achieve conformal
dimensions regardless of the value of \transns.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ B $ must be identical,
and must not be \flaconstantns.
\itemvsp
\checkitem
If $ A $ and $ B $ are vectors, then their lengths must be equal. Otherwise,
if \trans equals \flanotranspose or \flaconjnotransposens, then the
dimensions of $ A $ and $ B $ must be conformal; otherwise, if \trans equals
\flatranspose or \flaconjtransposens, then the dimensions of $ A^T $ and
$ B $ must be conformal.
\end{checks}
\ifacenotes{
\flacopyt expects $ A $ and $ B $ to be flat matrix objects.
}
\implnotes{
\flacopyt simply invokes the external BLAS wrapper \flacopytextns.
\flashcopyt uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the extended copy operation into
subproblems
expressed in terms of individual blocks of $ A $ and $ B $ and then
invokes \flacopytext to perform the computation on these blocks.
}
\begin{params}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if $ A $ were conjugated and/or transposed.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Dot() ----------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Dot( FLA_Obj x, FLA_Obj y, FLA_Obj rho );
\end{verbatim}
\index{FLAME/C functions!\fladotns}
\purpose{
Perform a dot (inner) product operation between two vectors:
\begin{eqnarray*}
\rho := \sum_{i=0}^{n-1} \chi_i \psi_i
\end{eqnarray*}
where $ \rho $ is a scalar, and $ \chi_i $ and $ \psi_i $ are the $ i $th
elements of general vectors $ x $ and $ y $, respectively, where both vectors
are of length $ n $.
Upon completion, the dot product $ \rho $ is stored to \frhons.
}
\begin{checks}
\checkitem
The numerical datatypes of $ x $, $ y $, and $ \rho $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The lengths of vectors $ x $ and $ y $ must be equal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \fladotextns.
}
\begin{params}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{y}{An \flaobj representing vector $ y $.}
\parameter{\flaobj}{rho}{An \flaobj representing scalar $ \rho $.}
\end{params}
\end{flaspec}

% --- FLA_Dotc() ---------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Dotc( FLA_Conj conj, FLA_Obj x, FLA_Obj y, FLA_Obj rho );
\end{verbatim}
\index{FLAME/C functions!\fladotcns}
\purpose{
Perform one of the following extended dot product operations:
\begin{eqnarray*}
\rho := \sum_{i=0}^{n-1} \chi_i \psi_i \\
\rho := \sum_{i=0}^{n-1} \bar{\chi_i} \psi_i
\end{eqnarray*}
where $ \rho $ is a scalar, and $ \chi_i $ and $ \psi_i $ are the $ i $th
elements of general vectors $ x $ and $ y $, respectively, where both vectors
are of length $ n $.
Upon completion, the dot product $ \rho $ is stored to \frhons.
The \conj argument allows the computation to proceed as if $ x $ were
conjugated.
}
\notes{
If $ x $, $ y $, and $ \rho $ are real, the value of \conj is ignored and
\fladotc behaves exactly as \fladotns.
}
\begin{checks}
\checkitem
The numerical datatypes of $ x $, $ y $, and $ \rho $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The lengths of vectors $ x $ and $ y $ must be equal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \fladotcextns.
}
\begin{params}
\parameter{\flaconj}{conj}{Indicates whether to conjugate the intermediate element-wise terms of the dot product.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{y}{An \flaobj representing vector $ y $.}
\parameter{\flaobj}{rho}{An \flaobj representing scalar $ \rho $.}
\end{params}
\end{flaspec}

% --- FLA_Dots() ---------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Dots( FLA_Obj alpha, FLA_Obj x, FLA_Obj y, FLA_Obj beta, FLA_Obj rho );
\end{verbatim}
\index{FLAME/C functions!\fladotsns}
\purpose{
Perform the following extended dot product operation between two vectors:
\begin{eqnarray*}
\rho := \beta \rho + \alpha \sum_{i=0}^{n-1} \chi_i \psi_i
\end{eqnarray*}
where $ \alpha $, $ \beta $, and $ \rho $ are scalars, and $ \chi_i $ and
$ \psi_i $ are the $ i $th elements of general vectors $ x $ and $ y $,
respectively, where both vectors are of length $ n $.
Upon completion, the dot product $ \rho $ is stored to \frhons.
}
\begin{checks}
\checkitem
The numerical datatypes of $ x $, $ y $, and $ \rho $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ x $, $ y $, and $ \rho $.
\itemvsp
\checkitem
The lengths of vectors $ x $ and $ y $ must be equal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \fladotsextns.
}
\begin{params}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{y}{An \flaobj representing vector $ y $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{rho}{An \flaobj representing scalar $ \rho $.}
\end{params}
\end{flaspec}

% --- FLA_Dotcs() --------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Dotcs( FLA_Conj conj, FLA_Obj alpha, FLA_Obj x, FLA_Obj y,
                FLA_Obj beta, FLA_Obj rho );
\end{verbatim}
\index{FLAME/C functions!\fladotcsns}
\purpose{
Perform one of the following extended dot product operations between two
vectors:
\begin{eqnarray*}
\rho := \beta \rho + \alpha \sum_{i=0}^{n-1} \chi_i \psi_i \\
\rho := \beta \rho + \alpha \sum_{i=0}^{n-1} \bar{\chi_i} \psi_i
\end{eqnarray*}
where $ \alpha $, $ \beta $, and $ \rho $ are scalars, and $ \chi_i $ and
$ \psi_i $ are the $ i $th elements of general vectors $ x $ and $ y $,
respectively, where both vectors are of length $ n $.
Upon completion, the dot product $ \rho $ is stored to \frhons.
The \conj argument allows the computation to proceed as if $ x $ were
conjugated.
}
\notes{
If $ x $, $ y $, and $ \rho $ are real, the value of \conj is ignored and
\fladotcs behaves exactly as \fladotsns.
}
\begin{checks}
\checkitem
The numerical datatypes of $ x $, $ y $, and $ \rho $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ x $, $ y $, and $ \rho $.
\itemvsp
\checkitem
The lengths of vectors $ x $ and $ y $ must be equal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \fladotcsextns.
}
\begin{params}
\parameter{\flaconj}{conj}{Indicates whether the operation proceeds as if $ x $ and $ y $ were conjugated.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{y}{An \flaobj representing vector $ y $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{rho}{An \flaobj representing scalar $ \rho $.}
\end{params}
\end{flaspec}

% --- FLA_Dot2s() --------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Dot2s( FLA_Obj alpha, FLA_Obj x, FLA_Obj y, FLA_Obj beta, FLA_Obj rho );
\end{verbatim}
\index{FLAME/C functions!\fladottsns}
\purpose{
Perform the following extended dot product operation between two vectors:
\begin{eqnarray*}
\rho := \beta \rho + \alpha \sum_{i=0}^{n-1} \chi_i \psi_i + \bar{\alpha} \sum_{i=0}^{n-1} \chi_i \psi_i
\end{eqnarray*}
where $ \alpha $, $ \beta $, and $ \rho $ are scalars, and $ \chi_i $ and
$ \psi_i $ are the $ i $th elements of general vectors $ x $ and $ y $,
respectively, where both vectors are of length $ n $.
Upon completion, the dot product $ \rho $ is stored to \frhons.
}
\notes{
Though this operation may be reduced to:
\begin{eqnarray*}
\rho := \beta \rho + \left( \alpha + \bar{\alpha} \right) \sum_{i=0}^{n-1} \chi_i \psi_i
\end{eqnarray*}
it is expressed above in unreduced form to allow a more clear contrast to
\fladottcsns.
}
\begin{checks}
\checkitem
The numerical datatypes of $ x $, $ y $, and $ \rho $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ x $, $ y $, and $ \rho $.
\itemvsp
\checkitem
The lengths of vectors $ x $ and $ y $ must be equal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \fladottsextns.
}
\begin{params}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{y}{An \flaobj representing vector $ y $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{rho}{An \flaobj representing scalar $ \rho $.}
\end{params}
\end{flaspec}

% --- FLA_Dot2cs() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Dot2cs( FLA_Conj conj, FLA_Obj alpha, FLA_Obj x, FLA_Obj y,
                 FLA_Obj beta, FLA_Obj rho );
\end{verbatim}
\index{FLAME/C functions!\fladottcsns}
\purpose{
Perform one of the following extended dot product operations between two
vectors:
\begin{eqnarray*}
\rho := \beta \rho + \alpha \sum_{i=0}^{n-1} \chi_i \psi_i + \bar{\alpha} \sum_{i=0}^{n-1} \chi_i \psi_i \\
\rho := \beta \rho + \alpha \sum_{i=0}^{n-1} \bar{\chi_i} \psi_i + \bar{\alpha} \sum_{i=0}^{n-1} \bar{\psi_i} \chi_i
\end{eqnarray*}
where $ \alpha $, $ \beta $, and $ \rho $ are scalars, and $ \chi_i $ and
$ \psi_i $ are the $ i $th elements of general vectors $ x $ and $ y $,
respectively, where both vectors are of length $ n $.
Upon completion, the dot product $ \rho $ is stored to \frhons.
The \conj argument allows the computation to proceed as if $ x $ were
conjugated.
}
\notes{
If $ x $, $ y $, and $ \rho $ are real, the value of \conj is ignored and
\fladottcs behaves exactly as \fladottsns.
}
\begin{checks}
\checkitem
The numerical datatypes of $ x $, $ y $, and $ \rho $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ x $, $ y $, and $ \rho $.
\itemvsp
\checkitem
The lengths of vectors $ x $ and $ y $ must be equal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \fladottcsextns.
}
\begin{params}
\parameter{\flaconj}{conj}{Indicates whether the operation proceeds as if $ x $ and $ y $ were conjugated.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{y}{An \flaobj representing vector $ y $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{rho}{An \flaobj representing scalar $ \rho $.}
\end{params}
\end{flaspec}

% --- FLA_Inv_scal() -----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Inv_scal( FLA_Obj alpha, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flainvscalns}
\purpose{
Perform an inverse scaling operation:
\begin{eqnarray*}
A & := & \alpha^{-1} A
\end{eqnarray*}
where $ \alpha $ is a scalar and $ A $ is a general matrix.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatype of $ A $ if $ A $ is real and the precision of $ A $ if
$ A $ is complex.
\itemvsp
\checkitem
$ \alpha $ may not be equal to zero.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flainvscalextns.
}
\begin{params}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Inv_scalc() ----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Inv_scalc( FLA_Conj conjalpha, FLA_Obj alpha, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flainvscalcns}
\purpose{
Perform one of the following extended inverse scaling operations:
\begin{eqnarray*}
A & := & \alpha^{-1} A \\
A & := & \bar{\alpha}^{-1} A
\end{eqnarray*}
where $ \alpha $ is a scalar and $ A $ is a general matrix.
The \conjalpha argument allows the computation to proceed as if $ \alpha $
were conjugated.
}
\notes{
If $ \alpha $ is real, the value of \conjalpha is ignored and \flainvscalc
behaves exactly as \flainvscalns.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatype of $ A $ if $ A $ is real and the precision of $ A $ if
$ A $ is complex.
\itemvsp
\checkitem
$ \alpha $ may not be equal to zero.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flainvscalcextns.
}
\begin{params}
\parameter{\flaconj}{conjalpha}{Indicates whether the operation proceeds as if $ \alpha $ were conjugated.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Nrm2() ---------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Nrm2( FLA_Obj x, FLA_Obj norm );
\end{verbatim}
\index{FLAME/C functions!\flanrmtns}
\purpose{
Compute the 2-norm of a vector:
\begin{eqnarray*}
\|x\|_2 & := &  \left( \sum_{i=0}^{n-1} |\chi_i|^2 \right)^{\frac{1}{2}}
\end{eqnarray*}
where $ \|x\|_2 $ is a scalar and $ \chi_i $ is the $ i $th element of
general vector $ x $ of length $ n $.
Upon completion, the 2-norm $ \|x\|_2 $ is stored to \normns.
}
\begin{checks}
\checkitem
The numerical datatype of $ x $ must be floating-point and must not be
\flaconstantns.
\itemvsp
\checkitem
The numerical datatype of \norm must be real and must not be \flaconstantns.
\itemvsp
\checkitem
The precision of the datatype of \norm must be equal to that of $ x $.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flanrmtextns.
}
\begin{params}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{norm}{An \flaobj representing scalar $ \|x\|_2 $.}
\end{params}
\end{flaspec}

% --- FLA_Scal() ---------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Scal( FLA_Obj alpha, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flascalns}
\purpose{
Perform a scaling operation:
\begin{eqnarray*}
A & := & \alpha A
\end{eqnarray*}
where $ \alpha $ is a scalar and $ A $ is a general matrix.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatype of $ A $ if $ A $ is real and the precision of $ A $ if
$ A $ is complex.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flascalextns.
}
\begin{params}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Scalc_external() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Scalc( FLA_Conj conjalpha, FLA_Obj alpha, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flascalcns}
\purpose{
Perform one of the following extended scaling operations:
\begin{eqnarray*}
A & := & \alpha A \\
A & := & \bar{\alpha} A
\end{eqnarray*}
where $ \alpha $ is a scalar and $ A $ is a general matrix.
The \conjalpha argument allows the computation to proceed as if $ \alpha $
were conjugated.
}
\notes{
If $ \alpha $ is real, the value of \conjalpha is ignored and \flascalc
behaves exactly as \flascalns.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatype of $ A $ if $ A $ is real and the precision of $ A $ if
$ A $ is complex.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flascalcextns.
}
\begin{params}
\parameter{\flaconj}{conjalpha}{Indicates whether the operation proceeds as if $ \alpha $ were conjugated.}
\parameter{\flaconj}{conjalpha}{Indicates whether the operation proceeds as if $ \alpha $ were conjugated.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Scalr() --------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Scalr( FLA_Uplo uplo, FLA_Obj alpha, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flascalrns}
\purpose{
Perform an extended scaling operation on the lower or upper triangle of a
matrix:
\begin{eqnarray*}
A & := & \alpha A
\end{eqnarray*}
where $ \alpha $ is a scalar and $ A $ is a general square matrix.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced and updated by the operation.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatype of $ A $ if $ A $ is real and the precision of $ A $ if
$ A $ is complex.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flascalrextns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced and updated during the operation.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Swap() ---------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Swap( FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaswapns}
\purpose{
Swap the contents of two general matrices $ A $ and $ B $.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ B $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The dimensions of $ A $ and $ B $ must be conformal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flaswapextns.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Swapt() --------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Swapt( FLA_Trans transab, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaswaptns}
\purpose{
Swap the contents of two general matrices $ A $ and $ B $.
If \transab is \flatranspose or \flaconjtransposens, the computation proceeds
as if only $ A $ (or only $ B $) were transposed.
Furthermore, if \transab is \flaconjnotranspose or \flaconjtransposens, both
$ A $ and $ B $ are conjugated after their contents are swapped.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ B $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If \transab equals \flanotranspose or \flaconjnotransposens, then the dimensions
of $ A $ and $ B $ must be conformal; otherwise, if \transab equals \flatranspose
or \flaconjtransposens, then the dimensions of $ A^T $ and $ B $ must be
conformal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flaswaptextns.
}
\begin{params}
\parameter{\flatrans}{transab}{Indicates whether the operation proceeds as if $ A $ and $ B $ were conjugated and/or transposed.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}









\subsubsection{Level-2 BLAS}

% --- FLA_Gemv() ---------------------------------------------------------------
% --- FLASH_Gemv() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Gemv( FLA_Trans transa, FLA_Obj alpha, FLA_Obj A, FLA_Obj x,
               FLA_Obj beta, FLA_Obj y );
void FLASH_Gemv( FLA_Trans transa, FLA_Obj alpha, FLA_Obj A, FLA_Obj x,
                 FLA_Obj beta, FLA_Obj y );
\end{verbatim}
\index{FLAME/C functions!\flagemvns}
\index{FLASH functions!\flashgemvns}
\purpose{
Perform one of the following general matrix-vector multiplication ({\sc gemv})
operations:
\begin{eqnarray*}
y & := & \beta y + \alpha A x \\
y & := & \beta y + \alpha A^T x \\
y & := & \beta y + \alpha \bar{A} x \\
y & := & \beta y + \alpha A^H x
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a general matrix, and
$ x $ and $ y $ are general vectors.
The \trans argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ x $, and $ y $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ A $, $ x $, and $ y $.
\itemvsp
\checkitem
The length of $ y $ and the number of rows in $ A $ (or $ A^T $ or $ A^H $)
must be equal, and the number of columns in $ A $ (or $ A^T $ or $ A^H $ ) and
the length of $ x $ must be equal.
\end{checks}
\ifacenotes{
\flagemv expects $ A $, $ x $, and $ y $ to be flat matrix objects.
}
\implnotes{
\flagemv invokes a single FLAME/C variant to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS.
\flashgemv uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc gemv} operation into subproblems
expressed in terms of individual blocks of $ A $ and subvectors of $ x $ and
$ y $ and then invokes \flagemvext to perform the computation on these blocks
and subvectors.
}
\begin{params}
\parameter{\flatrans}{transa}{Indicates whether the operation proceeds as if $ A $ were conjugated and/or transposed.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{y}{An \flaobj representing vector $ y $.}
\end{params}
\end{flaspec}

% --- FLA_Gemvc() --------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Gemvc( FLA_Trans transa, FLA_Conj conjx, FLA_Obj alpha,
                FLA_Obj A, FLA_Obj x, FLA_Obj beta, FLA_Obj y ); 
\end{verbatim}
\index{FLAME/C functions!\flagemvcns}
\purpose{
Perform one of the following extended general matrix-vector multiplication
({\sc gemv}) operations:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
y & := & \beta y + \alpha A x       & \hsp & y & := & \beta y + \alpha A \bar{x} \\[0.05in]
y & := & \beta y + \alpha A^T x     & \hsp & y & := & \beta y + \alpha A^T \bar{x} \\[0.05in]
y & := & \beta y + \alpha \bar{A} x & \hsp & y & := & \beta y + \alpha \bar{A} \bar{x} \\[0.05in]
y & := & \beta y + \alpha A^H x     & \hsp & y & := & \beta y + \alpha A^H \bar{x}
\end{array}
\end{math}
\end{center}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a general matrix, and
$ x $ and $ y $ are general vectors.
The \trans argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
Likewise, the \conjx argument allows the computation to proceed as if $ x $
were conjugated.
}
\notes{
The above matrix-vector operations implicitly assume $ x $ and $ y $ to be
column vectors.
However, since transposing a vector does not change the way its elements are
accessed, we may also express the above operations as:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
y_r & := & \beta y_r + \alpha x_r A^T     & \hsp & y_r & := & \beta y_r + \alpha \bar{x_r} A^T \\[0.05in]
y_r & := & \beta y_r + \alpha x_r A       & \hsp & y_r & := & \beta y_r + \alpha \bar{x_r} A \\[0.05in]
y_r & := & \beta y_r + \alpha x_r A^H     & \hsp & y_r & := & \beta y_r + \alpha \bar{x_r} A^H \\[0.05in]
y_r & := & \beta y_r + \alpha x_r \bar{A} & \hsp & y_r & := & \beta y_r + \alpha \bar{x_r} \bar{A}
\end{array}
\end{math}
\end{center}
respectively, where $ x_r $ and $ y_r $ are row vectors. \\
If $ A $, $ x $, and $ y $ are real, the value of \conjx is ignored and
\flagemvc behaves exactly as \flagemvns.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ x $, and $ y $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ A $, $ x $, and $ y $.
\itemvsp
\checkitem
The length of $ y $ and the number of rows in $ A $ (or $ A^T $ or $ A^H $)
must be equal, and the number of columns in $ A $ (or $ A^T $ or $ A^H $ ) and
the length of $ x $ must be equal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flagemvcextns.
}
\begin{params}
\parameter{\flatrans}{transa}{Indicates whether the operation proceeds as if $ A $ were conjugated and/or transposed.}
\parameter{\flaconj}{conjx}{Indicates whether the operation proceeds as if $ x $ were conjugated.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{y}{An \flaobj representing vector $ y $.}
\end{params}
\end{flaspec}

% --- FLA_Ger() ----------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Ger( FLA_Obj alpha, FLA_Obj x, FLA_Obj y, FLA_Obj A ); 
\end{verbatim}
\index{FLAME/C functions!\flagerns}
\purpose{
Perform a general rank-1 update ({\sc ger}) operation:
\begin{eqnarray*}
A & := & A + \alpha x y^T
\end{eqnarray*}
where $ \alpha $ is a scalar, $ A $ is a general matrix, and
$ x $ and $ y $ are general vectors.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ x $, and $ y $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatypes of $ A $, $ x $, and $ y $.
\itemvsp
\checkitem
The length of $ x $ and the number of rows in $ A $ must be equal, and the
length of $ y $ and the number of columns in $ A $ must be equal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flagerextns.
}
\begin{params}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{y}{An \flaobj representing vector $ y $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Gerc() ---------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Gerc( FLA_Conj conjx, FLA_Conj conjy, FLA_Obj alpha,
               FLA_Obj x, FLA_Obj y, FLA_Obj A ); 
\end{verbatim}
\index{FLAME/C functions!\flagercns}
\purpose{
Perform one of the following extended general rank-1 update ({\sc ger})
operations:
\begin{eqnarray*}
A & := & A + \alpha x y^T \\
A & := & A + \alpha x \bar{y}^T \\
A & := & A + \alpha \bar{x} y^T \\
A & := & A + \alpha \bar{x} \bar{y}^T
\end{eqnarray*}
where $ \alpha $ is a scalar, $ A $ is a general matrix, and
$ x $ and $ y $ are general vectors.
The \conjx and \conjy arguments allow the computation to proceed as if $ x $
and/or $ y $ were conjugated.
}
\notes{
If $ A $, $ x $, and $ y $ are real, the values of \conjx and \conjy are
ignored and \flagerc behaves exactly as \flagerns.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ x $, and $ y $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatypes of $ A $, $ x $, and $ y $.
\itemvsp
\checkitem
The length of $ x $ and the number of rows in $ A $ must be equal, and the
length of $ y $ and the number of columns in $ A $ must be equal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flagercextns.
}
\begin{params}
\parameter{\flaconj}{conjx}{Indicates whether the operation proceeds as if $ x $ were conjugated.}
\parameter{\flaconj}{conjy}{Indicates whether the operation proceeds as if $ y $ were conjugated.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{y}{An \flaobj representing vector $ y $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Hemv() ---------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Hemv( FLA_Uplo uplo, FLA_Obj alpha, FLA_Obj A, FLA_Obj x, 
               FLA_Obj beta, FLA_Obj y ); 
\end{verbatim}
\index{FLAME/C functions!\flahemvns}
\purpose{
Perform a Hermitian matrix-vector multiplication ({\sc hemv}) operation:
\begin{eqnarray*}
y & := & \beta y + \alpha A x
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a Hermitian
matrix, and $ x $ and $ y $ are general vectors.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
}
\notes{
When invoked with real objects, this function performs the {\sc symv}
operation.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ x $, and $ y $ must be identical and
must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ A $, $ x $, and $ y $.
\itemvsp
\checkitem
The length of $ x $, the length of $ y $, and the order of $ A $ must be equal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flahemvextns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{y}{An \flaobj representing vector $ y $.}
\end{params}
\end{flaspec}

% --- FLA_Hemvc() --------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Hemvc( FLA_Uplo uplo, FLA_Conj conj, FLA_Obj alpha,
                FLA_Obj A, FLA_Obj x, FLA_Obj beta, FLA_Obj y ); 
\end{verbatim}
\index{FLAME/C functions!\flahemvcns}
\purpose{
Perform one of the following extended Hermitian matrix-vector multiplication
({\sc hemv}) operations:
\begin{eqnarray*}
y & := & \beta y + \alpha A x \\
y & := & \beta y + \alpha \bar{A} x
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a Hermitian
matrix, and $ x $ and $ y $ are general vectors.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
The \conj argument allows the computation to proceed as if $ A $ were
conjugated.
}
\notes{
When invoked with real objects, this function performs the {\sc symv}
operation.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ x $, and $ y $ must be identical and
must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ A $, $ x $, and $ y $.
\itemvsp
\checkitem
The length of $ x $, the length of $ y $, and the order of $ A $ must be equal.
\itemvsp
\checkitem
\trans may not be \flaconjtranspose or \flaconjnotransposens.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flahemvcextns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flatrans}{conj}{Indicates whether the operation proceeds as if $ A $ were conjugated.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{y}{An \flaobj representing vector $ y $.}
\end{params}
\end{flaspec}

% --- FLA_Her() ----------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Her( FLA_Uplo uplo, FLA_Obj alpha, FLA_Obj x, FLA_Obj A ); 
\end{verbatim}
\index{FLAME/C functions!\flaherns}
\purpose{
Perform a Hermitian rank-1 update ({\sc her}) operation:
\begin{eqnarray*}
A & := & A + \alpha x x^H
\end{eqnarray*}
where $ \alpha $ is a scalar, $ A $ is a Hermitian matrix, and
$ x $ is a general vector.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced and updated by the operation.
}
\notes{
When invoked with real objects, this function performs the {\sc syr}
operation.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ x $ must be identical and
must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatypes of $ A $ and $ x $.
\itemvsp
\checkitem
The length of $ x $ and the order of $ A $ must be equal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flaherextns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced and updated during the operation.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Herc() ---------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Herc( FLA_Uplo uplo, FLA_Conj conj, FLA_Obj alpha, FLA_Obj x, FLA_Obj A ); 
\end{verbatim}
\index{FLAME/C functions!\flahercns}
\purpose{
Perform one of the following extended Hermitian rank-1 update
({\sc her}) operations:
\begin{eqnarray*}
A & := & A + \alpha x x^H \\
A & := & A + \alpha \bar{x} x^T
\end{eqnarray*}
where $ \alpha $ is a scalar, $ A $ is a Hermitian matrix, and
$ x $ is a general vector.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced and updated by the operation.
The \conj argument allows the computation of the conjugated rank-1 product
$ \bar{x} x^T $.

}
\notes{
When invoked with real objects, this function performs the {\sc syr}
operation.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ x $ must be identical and
must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatypes of $ A $ and $ x $.
\itemvsp
\checkitem
The length of $ x $ and the order of $ A $ must be equal.
\itemvsp
\checkitem
\trans may not be \flaconjtranspose or \flaconjnotransposens.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flahercextns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced and updated during the operation.}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if the rank-1 prodcut is conjugated.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Her2() ---------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Her2( FLA_Uplo uplo, FLA_Obj alpha, FLA_Obj x, FLA_Obj y, FLA_Obj A ); 
\end{verbatim}
\index{FLAME/C functions!\flahertns}
\purpose{
Perform a Hermitian rank-2 update ({\sc her2}) operation:
\begin{eqnarray*}
A & := & A + \alpha x y^H + \bar{\alpha} y x^H
\end{eqnarray*}
where $ \alpha $ is a scalar, $ A $ is a Hermitian matrix, and
$ x $ and $ y $ are general vectors.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced and updated by the operation.
}
\notes{
When invoked with real objects, this function performs the {\sc syr2}
operation.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ x $, and $ y $ must be identical and
must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatypes of $ A $, $ x $, and $ y $.
\itemvsp
\checkitem
The length of $ x $, the length of $ y $, and the order of $ A $ must be equal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flahertextns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{y}{An \flaobj representing vector $ y $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Her2c() --------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Her2c( FLA_Uplo uplo, FLA_Conj conj, FLA_Obj alpha, FLA_Obj x, FLA_Obj y,
                FLA_Obj A ); 
\end{verbatim}
\index{FLAME/C functions!\flahertcns}
\purpose{
Perform one of the following extended Hermitian rank-2 update
({\sc her2}) operations:
\begin{eqnarray*}
A & := & A + \alpha x y^H + \bar{\alpha} y x^H \\
A & := & A + \alpha \bar{x} y^T + \bar{\alpha} \bar{y} x^T
\end{eqnarray*}
where $ \alpha $ is a scalar, $ A $ is a Hermitian matrix, and
$ x $ and $ y $ are general vectors.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced and updated by the operation.
The \trans argument allows the computation of the conjugated rank-2 products
$ \bar{x} y^T $ and $ \bar{y} x^T $.
}
\notes{
When invoked with real objects, this function performs the {\sc syr2}
operation.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ x $, and $ y $ must be identical and
must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatypes of $ A $, $ x $, and $ y $.
\itemvsp
\checkitem
The length of $ x $, the length of $ y $, and the order of $ A $ must be equal.
\itemvsp
\checkitem
\trans may not be \flaconjtranspose or \flaconjnotransposens.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flahertcextns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if the rank-2 prodcuts are conjugated.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{y}{An \flaobj representing vector $ y $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Symv() ---------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Symv( FLA_Uplo uplo, FLA_Obj alpha, FLA_Obj A, FLA_Obj x,
               FLA_Obj beta, FLA_Obj y ); 
\end{verbatim}
\index{FLAME/C functions!\flasymvns}
\purpose{
Perform a symmetric matrix-vector multiplication ({\sc symv}) operation:
\begin{eqnarray*}
y & := & \beta y + \alpha A x
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a symmetric
matrix, and $ x $ and $ y $ are general vectors.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ x $, and $ y $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ A $, $ x $, and $ y $.
\itemvsp
\checkitem
The length of $ x $, the length of $ y $, and the order of $ A $ must
be equal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flasymvextns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{y}{An \flaobj representing vector $ y $.}
\end{params}
\end{flaspec}

% --- FLA_Syr() ----------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Syr( FLA_Uplo uplo, FLA_Obj alpha, FLA_Obj x, FLA_Obj A ); 
\end{verbatim}
\index{FLAME/C functions!\flasyrns}
\purpose{
Perform a symmetric rank-1 update ({\sc syr}) operation:
\begin{eqnarray*}
A & := & A + \alpha x x^T
\end{eqnarray*}
where $ \alpha $ is a scalar, $ A $ is a symmetric matrix, and
$ x $ is a general vector.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced and updated by the operation.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ x $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatypes of $ A $ and $ x $.
\itemvsp
\checkitem
The length of $ x $ and the order of $ A $ must be equal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flasyrextns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Syr2() ---------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Syr2( FLA_Uplo uplo, FLA_Obj alpha, FLA_Obj x, FLA_Obj y, FLA_Obj A ); 
\end{verbatim}
\index{FLAME/C functions!\flasyrtns}
\purpose{
Perform a symmetric rank-2 update ({\sc syr2}) operation:
\begin{eqnarray*}
A & := & A + \alpha x y^T + \alpha y x^T
\end{eqnarray*}
where $ \alpha $ is a scalar, $ A $ is a symmetric matrix, and
$ x $ and $ y $ are general vectors.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced and updated by the operation.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ x $, and $ y $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatypes of $ A $, $ x $, and $ y $.
\itemvsp
\checkitem
The length of $ x $, the length of $ y $, and the order of $ A $ must be equal.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flasyrtextns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{y}{An \flaobj representing vector $ y $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Trmv() ---------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Trmv( FLA_Uplo uplo, FLA_Trans transa, FLA_Diag diag, FLA_Obj A, FLA_Obj x );
\end{verbatim}
\index{FLAME/C functions!\flatrmvns}
\purpose{
Perform one of the following triangular matrix-vector multiplication
({\sc trmv}) operations:
\begin{eqnarray*}
x & := & A x \\
x & := & A^T x \\
x & := & \bar{A} x \\
x & := & A^H x
\end{eqnarray*}
where $ A $ is a triangular matrix and $ x $ is a general vector.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
The \transa argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
The \diag argument indicates whether the diagonal of $ A $ is unit or
non-unit.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ x $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The length of $ x $ and the order of $ A $ must be equal.
\itemvsp
\checkitem
\diag may not be \flazerodiagns.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flatrmvextns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flatrans}{transa}{Indicates whether the operation proceeds as if $ A $ were conjugated and/or transposed.}
\parameter{\fladiag}{diag}{Indicates whether the diagonal of $ A $ is unit or non-unit.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\end{params}
\end{flaspec}

% --- FLA_Trmvsx() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Trmvsx( FLA_Uplo uplo, FLA_Trans transa, FLA_Diag diag, FLA_Obj alpha,
                 FLA_Obj A, FLA_Obj x, FLA_Obj beta, FLA_Obj y );
\end{verbatim}
\index{FLAME/C functions!\flatrmvsxns}
\purpose{
Perform one of the following extended triangular matrix-vector multiplication
({\sc trmv}) operations:
\begin{eqnarray*}
y & := & \beta y + \alpha A x \\
y & := & \beta y + \alpha A^T x \\
y & := & \beta y + \alpha \bar{A} x \\
y & := & \beta y + \alpha A^H x
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a triangular matrix, and
$ x $ and $ y $ are general vectors.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
The \transa argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
The \diag argument indicates whether the diagonal of $ A $ is unit or
non-unit.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ x $, and $ y $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ A $, $ x $, and $ y $.
\itemvsp
\checkitem
The length of $ x $, the length of $ y $, and the order of $ A $ must be equal.
\itemvsp
\checkitem
\diag may not be \flazerodiagns.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flatrmvsxextns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flatrans}{transa}{Indicates whether the operation proceeds as if $ A $ were conjugated and/or transposed.}
\parameter{\fladiag}{diag}{Indicates whether the diagonal of $ A $ is unit or non-unit.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{y}{An \flaobj representing vector $ y $.}
\end{params}
\end{flaspec}

% --- FLA_Trsv() ---------------------------------------------------------------
% --- FLASH_Trsv() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Trsv( FLA_Uplo uplo, FLA_Trans transa, FLA_Diag diag, FLA_Obj A, FLA_Obj b );
void FLASH_Trsv( FLA_Uplo uplo, FLA_Trans transa, FLA_Diag diag, FLA_Obj A, FLA_Obj b );
\end{verbatim}
\index{FLAME/C functions!\flatrsvns}
\index{FLASH functions!\flashtrsvns}
\purpose{
Perform one of the following triangular solve ({\sc trsv}) operations:
\begin{eqnarray*}
A x       & = & b \\
A^T x     & = & b \\
\bar{A} x & = & b \\
A^H x     & = & b
\end{eqnarray*}
which, respectively, are solved by overwriting $ b $ with the contents of
the solution vector $ x $ as follows:
\begin{eqnarray*}
b & := & A^{-1} b \\
b & := & A^{-T} b \\
b & := & \bar{A}^{-1} b \\
b & := & A^{-H} b
\end{eqnarray*}
where $ A $ is a triangular matrix and $ x $ and $ b $ are general vectors.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
The \transa argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
The \diag argument indicates whether the diagonal of $ A $ is unit or
non-unit.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ b $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The length of $ b $ and the order of $ A $ must be equal.
\itemvsp
\checkitem
\diag may not be \flazerodiagns.
\end{checks}
\ifacenotes{
\flatrsv expects $ A $ and $ b $ to be flat matrix objects.
}
\implnotes{
\flatrsv invokes a single FLAME/C variant to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS.
\flashtrsv uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc trsv} operation into subproblems
expressed in terms of individual blocks of $ A $ and subvectors of $ b $ and
then invokes external BLAS to perform the computation on these blocks and
subvectors.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flatrans}{transa}{Indicates whether the operation proceeds as if $ A $ were conjugated and/or transposed.}
\parameter{\fladiag}{diag}{Indicates whether the diagonal of $ A $ is unit or non-unit.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{b}{An \flaobj representing vector $ b $.}
\end{params}
\end{flaspec}

% --- FLA_Trsvsx() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Trsvsx( FLA_Uplo uplo, FLA_Trans transa, FLA_Diag diag, FLA_Obj alpha,
                 FLA_Obj A, FLA_Obj b, FLA_Obj beta, FLA_Obj y );
\end{verbatim}
\index{FLAME/C functions!\flatrsvsxns}
\purpose{
Perform one of the following extended triangular solve ({\sc trsv}) operations:
\begin{eqnarray*}
y & := & \beta y + \alpha A^{-1} b \\
y & := & \beta y + \alpha A^{-T} b \\
y & := & \beta y + \alpha \bar{A}^{-1} b \\
y & := & \beta y + \alpha A^{-H} b
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a triangular matrix, and
$ b $ and $ y $ are general vectors.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
The \transa argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
The \diag argument indicates whether the diagonal of $ A $ is unit or
non-unit.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ b $, and $ y $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ A $, $ b $, and $ y $.
\itemvsp
\checkitem
The length of $ b $, the length of $ y $, and the order of $ A $ must be equal.
\itemvsp
\checkitem
\diag may not be \flazerodiagns.
\end{checks}
\implnotes{
This function is implemented as a wrapper to \flatrsvsxextns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flatrans}{transa}{Indicates whether the operation proceeds as if $ A $ were conjugated and/or transposed.}
\parameter{\fladiag}{diag}{Indicates whether the diagonal of $ A $ is unit or non-unit.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{b}{An \flaobj representing vector $ b $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{y}{An \flaobj representing vector $ y $.}
\end{params}
\end{flaspec}





























\subsubsection{Level-3 BLAS}
\label{sec:blas3-front-ends}

% --- FLA_Gemm() ---------------------------------------------------------------
% --- FLASH_Gemm() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Gemm( FLA_Trans transa, FLA_Trans transb, FLA_Obj alpha,
               FLA_Obj A, FLA_Obj B, FLA_Obj beta, FLA_Obj C );
void FLASH_Gemm( FLA_Trans transa, FLA_Trans transb, FLA_Obj alpha,
                 FLA_Obj A, FLA_Obj B, FLA_Obj beta, FLA_Obj C );
\end{verbatim}
\index{FLAME/C functions!\flagemmns}
\index{FLASH functions!\flashgemmns}
\purpose{
Perform one of the following general matrix-matrix multiplication ({\sc gemm})
operations:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
C & := & \beta C + \alpha A B         & \hsp & C & := & \beta C + \alpha \bar{A} B \\[0.05in]
C & := & \beta C + \alpha A B^T       & \hsp & C & := & \beta C + \alpha \bar{A} B^T \\[0.05in]
C & := & \beta C + \alpha A \bar{B}   & \hsp & C & := & \beta C + \alpha \bar{A} \bar{B} \\[0.05in]
C & := & \beta C + \alpha A B^H       & \hsp & C & := & \beta C + \alpha \bar{A} B^H \\[0.05in]
C & := & \beta C + \alpha A^T B       & \hsp & C & := & \beta C + \alpha A^H B \\[0.05in]
C & := & \beta C + \alpha A^T B^T     & \hsp & C & := & \beta C + \alpha A^H B^T \\[0.05in]
C & := & \beta C + \alpha A^T \bar{B} & \hsp & C & := & \beta C + \alpha A^H \bar{B} \\[0.05in]
C & := & \beta C + \alpha A^T B^H     & \hsp & C & := & \beta C + \alpha A^H B^H
\end{array}
\end{math}
\end{center}
where $ \alpha $ and $ \beta $ are scalars and $ A $, $ B $, and $ C $ are
general matrices.
The \transa and \transb arguments allows the computation to proceed as if
$ A $ and/or $ B $ were conjugated and/or transposed.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ B $, and $ C $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ A $, $ B $, and $ C $.
\itemvsp
\checkitem
The number of rows in $ C $ and the number of rows in $ A $ (or $ A^T $) must
be equal; the number of columns in $ C $ and the number of columns of $ B $
(or $ B^T $) must be equal; and the number of columns in $ A $ (or $ A^T $)
and the number of rows in $ B $ (or $ B^T $) must be equal.
\end{checks}
\ifacenotes{
\flagemm expects $ A $, $ B $, and $ C $ to be flat matrix objects.
}
\implnotes{
\flagemm invokes a single FLAME/C variant to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS.
\flashgemm uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc gemm} operation into subproblems
expressed in terms of individual blocks of $ A $, $ B $, and $ C $ and then
invokes \flagemmext to perform the computation on these blocks.
}
\begin{params}
\parameter{\flatrans}{transa}{Indicates whether the operation proceeds as if $ A $ were conjugated and/or transposed.}
\parameter{\flatrans}{transb}{Indicates whether the operation proceeds as if $ B $ were conjugated and/or transposed.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{C}{An \flaobj representing matrix $ C $.}
\end{params}
\end{flaspec}

% --- FLA_Hemm() ---------------------------------------------------------------
% --- FLASH_Hemm() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Hemm( FLA_Side side, FLA_Uplo uplo, FLA_Obj alpha,
               FLA_Obj A, FLA_Obj B, FLA_Obj beta, FLA_Obj C );
void FLASH_Hemm( FLA_Side side, FLA_Uplo uplo, FLA_Obj alpha,
                 FLA_Obj A, FLA_Obj B, FLA_Obj beta, FLA_Obj C );
\end{verbatim}
\index{FLAME/C functions!\flahemmns}
\index{FLASH functions!\flashhemmns}
\purpose{
Perform one of the following Hermitian matrix-matrix multiplication ({\sc hemm})
operations:
\begin{eqnarray*}
C & := & \beta C + \alpha A B \\
C & := & \beta C + \alpha B A
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a Hermitian matrix,
and $ B $ and $ C $ are general matrices.
The \side argument indicates whether matrix $ A $ is multiplied
on the left or the right side of $ B $.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
}
\notes{
When invoked with real objects, this function performs the {\sc symm}
operation.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ B $, and $ C $ must be identical and
must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ A $, $ B $, and $ C $.
\itemvsp
\checkitem
The dimensions of $ C $ and $ B $ must be conformal.
\itemvsp
\checkitem
If \side equals \flaleftns, then the number of rows in $ C $ and the order of
$ A $ must be equal; otherwise, if \side equals \flarightns, then the number
of columns in $ C $ and the order of $ A $ must be equal.
\end{checks}
\ifacenotes{
\flahemm expects $ A $, $ B $, and $ C $ to be flat matrix objects.
}
\implnotes{
\flahemm invokes a single FLAME/C variant to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS.
\flashhemm uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc hemm} operation into subproblems
expressed in terms of individual blocks of $ A $, $ B $, and $ C $ and then
invokes external BLAS to perform the computation on these blocks.
}
\begin{params}
\parameter{\flaside}{side}{Indicates whether $ A $ is multipled on the left or right side of $ B $.}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{C}{An \flaobj representing matrix $ C $.}
\end{params}
\end{flaspec}

% --- FLA_Herk() ---------------------------------------------------------------
% --- FLASH_Herk() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Herk( FLA_Uplo uplo, FLA_Trans trans, FLA_Obj alpha,
               FLA_Obj A, FLA_Obj beta, FLA_Obj C );
void FLASH_Herk( FLA_Uplo uplo, FLA_Trans trans, FLA_Obj alpha,
                 FLA_Obj A, FLA_Obj beta, FLA_Obj C );
\end{verbatim}
\index{FLAME/C functions!\flaherkns}
\index{FLASH functions!\flashherkns}
\purpose{
Perform one of the following Hermitian rank-k update ({\sc herk}) operations:
\begin{eqnarray*}
C & := & \beta C + \alpha A A^H \\
C & := & \beta C + \alpha A^H A
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ C $ is a Hermitian matrix,
and $ A $ is a general matrix.
The \uplo argument indicates whether the lower or upper triangle of $ C $
is referenced and updated by the operation.
The \trans argument allows the computation to proceed as if $ A $ were
conjugate-transposed, which results in the alternate rank-k product $ A^H A $.
}
\notes{
When invoked with real objects, this function performs the {\sc syrk}
operation.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ C $ must be identical and
must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
be real and match the precision of the datatypes of $ A $ and $ C $.
\itemvsp
\checkitem
If \trans equals \flanotransposens, then the order of matrix $ C $ and the
the number of rows in $ A $ must be equal; otherwise, if \trans equals
\flaconjtransposens, then the order of matrix $ C $ and the number of
columns in $ A $ must be equal.
\end{checks}
\ifacenotes{
\flaherk expects $ A $ and $ C $ to be flat matrix objects.
}
\implnotes{
\flaherk invokes a single FLAME/C variant to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS.
\flashherk uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc herk} operation into subproblems
expressed in terms of individual blocks of $ A $ and $ C $ and then
invokes external BLAS to perform the computation on these blocks.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ C $ is referenced during the operation.}
\parameter{\flatrans}{transa}{Indicates whether the operation proceeds as if $ A $ were conjugate-transposed.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{C}{An \flaobj representing matrix $ C $.}
\end{params}
\end{flaspec}

% --- FLA_Her2k() --------------------------------------------------------------
% --- FLASH_Her2k() ------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Her2k( FLA_Uplo uplo, FLA_Trans trans, FLA_Obj alpha,
                FLA_Obj A, FLA_Obj B, FLA_Obj beta, FLA_Obj C );
void FLASH_Her2k( FLA_Uplo uplo, FLA_Trans trans, FLA_Obj alpha,
                  FLA_Obj A, FLA_Obj B, FLA_Obj beta, FLA_Obj C );
\end{verbatim}
\index{FLAME/C functions!\flahertkns}
\index{FLASH functions!\flashhertkns}
\purpose{
Perform one of the following Hermitian rank-2k update ({\sc her2k}) operations:
\begin{eqnarray*}
C & := & \beta C + \alpha A B^H + \bar{\alpha} B A^H \\
C & := & \beta C + \alpha A^H B + \bar{\alpha} B^H A
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ C $ is a Hermitian matrix,
and $ A $ and $ B $ are general matrices.
The \uplo argument indicates whether the lower or upper triangle of $ C $
is referenced and updated by the operation.
The \trans argument allows the computation to proceed as if $ A $ and $ B $
were conjugate-transposed, which results in the alternate rank-2k products
$ A^H B $ and $ B^H A $.
}
\notes{
When invoked with real objects, this function performs the {\sc syr2k}
operation.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ B $, and $ C $ must be identical and
must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then their
datatypes must be real and complex, respectively, and match the precision
of the datatypes of $ A $, $ B $, and $ C $.
\itemvsp
\checkitem
The dimensions of $ A $ and $ B $ must be conformal.
\itemvsp
\checkitem
If \trans equals \flanotransposens, then the order of matrix $ C $ and the
the number of rows in $ A $ and $ B $ must be equal; otherwise, if \trans
equals \flaconjtransposens, then the order of matrix $ C $ and the number of
columns in $ A $ and $ B $ must be equal.
\end{checks}
\ifacenotes{
\flahertk expects $ A $, $ B $, and $ C $ to be flat matrix objects.
}
\implnotes{
\flahertk invokes a single FLAME/C variant to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS.
\flashhertk uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc her2k} operation into subproblems
expressed in terms of individual blocks of $ A $, $ B $, and $ C $ and then
invokes external BLAS to perform the computation on these blocks.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ C $ is referenced during the operation.}
\parameter{\flatrans}{transa}{Indicates whether the operation proceeds as if $ A $ and $ B $ were conjugate-transposed.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{C}{An \flaobj representing matrix $ C $.}
\end{params}
\end{flaspec}

% --- FLA_Symm() ---------------------------------------------------------------
% --- FLASH_Symm() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Symm( FLA_Side side, FLA_Uplo uplo, FLA_Obj alpha,
               FLA_Obj A, FLA_Obj B, FLA_Obj beta, FLA_Obj C );
void FLASH_Symm( FLA_Side side, FLA_Uplo uplo, FLA_Obj alpha,
                 FLA_Obj A, FLA_Obj B, FLA_Obj beta, FLA_Obj C );
\end{verbatim}
\index{FLAME/C functions!\flasymmns}
\index{FLASH functions!\flashsymmns}
\purpose{
Perform one of the following symmetric matrix-matrix multiplication ({\sc symm})
operations:
\begin{eqnarray*}
C & := & \beta C + \alpha A B \\
C & := & \beta C + \alpha B A
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a symmetric matrix, and
$ B $ and $ C $ are general matrices.
The \side argument indicates whether the symmetric matrix $ A $ is multiplied
on the left or the right side of $ B $.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ B $, and $ C $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ A $, $ B $, and $ C $.
\itemvsp
\checkitem
The dimensions of $ C $ and $ B $ must be conformal.
\itemvsp
\checkitem
If \side equals \flaleftns, then the number of rows in $ C $ and the order of
$ A $ must be equal; otherwise, if \side equals \flarightns, then the number
of columns in $ C $ and the order of $ A $ must be equal.
\end{checks}
\ifacenotes{
\flasymm expects $ A $, $ B $, and $ C $ to be flat matrix objects.
}
\implnotes{
\flasymm invokes a single FLAME/C variant to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS.
\flashsymm uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc symm} operation into subproblems
expressed in terms of individual blocks of $ A $, $ B $, and $ C $ and then
invokes external BLAS to perform the computation on these blocks.
}
\begin{params}
\parameter{\flaside}{side}{Indicates whether $ A $ is multipled on the left or right side of $ B $.}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{C}{An \flaobj representing matrix $ C $.}
\end{params}
\end{flaspec}

% --- FLA_Syrk() ---------------------------------------------------------------
% --- FLASH_Syrk() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Syrk( FLA_Uplo uplo, FLA_Trans trans, FLA_Obj alpha,
               FLA_Obj A, FLA_Obj beta, FLA_Obj C );
void FLASH_Syrk( FLA_Uplo uplo, FLA_Trans trans, FLA_Obj alpha,
                 FLA_Obj A, FLA_Obj beta, FLA_Obj C );
\end{verbatim}
\index{FLAME/C functions!\flasyrkns}
\index{FLASH functions!\flashsyrkns}
\purpose{
Perform one of the following symmetric rank-k update ({\sc syrk}) operations:
\begin{eqnarray*}
C & := & \beta C + \alpha A A^T \\
C & := & \beta C + \alpha A^T A
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ C $ is a symmetric matrix, and
$ A $ is a general matrix.
The \uplo argument indicates whether the lower or upper triangle of $ C $
is referenced and updated by the operation.
The \trans argument allows the computation to proceed as if $ A $ were
transposed, which results in the alternate rank-k product $ A^T A $.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ C $ must be identical and floating-point,
and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ A $ and $ C $.
\itemvsp
\checkitem
If \trans equals \flanotransposens, then the order of matrix $ C $ and the
the number of rows in $ A $ must be equal; otherwise, if \trans equals
\flatransposens, then the order of matrix $ C $ and the number of
columns in $ A $ must be equal.
\itemvsp
\checkitem
\trans may not be \flaconjtranspose or \flaconjnotransposens.
\end{checks}
\ifacenotes{
\flasyrk expects $ A $ and $ C $ to be flat matrix objects.
}
\implnotes{
\flasyrk invokes a single FLAME/C variant to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS.
\flashsyrk uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc syrk} operation into subproblems
expressed in terms of individual blocks of $ A $ and $ C $ and then
invokes external BLAS to perform the computation on these blocks.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ C $ is referenced during the operation.}
\parameter{\flatrans}{transa}{Indicates whether the operation proceeds as if $ A $ is transposed.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{C}{An \flaobj representing matrix $ C $.}
\end{params}
\end{flaspec}

% --- FLA_Syr2k() --------------------------------------------------------------
% --- FLASH_Syr2k() ------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Syr2k( FLA_Uplo uplo, FLA_Trans trans, FLA_Obj alpha,
                FLA_Obj A, FLA_Obj B, FLA_Obj beta, FLA_Obj C );
void FLASH_Syr2k( FLA_Uplo uplo, FLA_Trans trans, FLA_Obj alpha,
                  FLA_Obj A, FLA_Obj B, FLA_Obj beta, FLA_Obj C );
\end{verbatim}
\index{FLAME/C functions!\flasyrtkns}
\index{FLASH functions!\flashsyrtkns}
\purpose{
Perform one of the following symmetric rank-2k update ({\sc syr2k})
operations:
\begin{eqnarray*}
C & := & \beta C + \alpha A B^T + \alpha B A^T \\
C & := & \beta C + \alpha A^T B + \alpha B^T A
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ C $ is a symmetric matrix,
and $ A $ and $ B $ are general matrices.
The \uplo argument indicates whether the lower or upper triangle of $ C $
is referenced and updated by the operation.
The \trans argument allows the computation to proceed as if $ A $ and $ B $
were transposed, which results in the alternate rank-2k products
$ A^T B $ and $ B^T A $.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ B $, and $ C $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ A $, $ B $, and $ C $.
\itemvsp
\checkitem
The dimensions of $ A $ and $ B $ must be conformal.
\itemvsp
\checkitem
If \trans equals \flanotransposens, then the order of matrix $ C $ and the
the number of rows in $ A $ and $ B $ must be equal; otherwise, if \trans
equals \flatransposens, then the order of matrix $ C $ and the number of
columns in $ A $ and $ B $ must be equal.
\itemvsp
\checkitem
\trans may not be \flaconjtranspose or \flaconjnotransposens.
\end{checks}
\ifacenotes{
\flasyrtk expects $ A $, $ B $, and $ C $ to be flat matrix objects.
}
\implnotes{
\flasyrtk invokes a single FLAME/C variant to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS.
\flashsyrtk uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc syr2k} operation into subproblems
expressed in terms of individual blocks of $ A $, $ B $, and $ C $ and then
invokes external BLAS to perform the computation on these blocks.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ C $ is referenced during the operation.}
\parameter{\flatrans}{transa}{Indicates whether the operation proceeds as if $ A $ and $ B $ were transposed.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{C}{An \flaobj representing matrix $ C $.}
\end{params}
\end{flaspec}

% --- FLA_Trmm() ---------------------------------------------------------------
% --- FLASH_Trmm() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Trmm( FLA_Side side, FLA_Uplo uplo, FLA_Trans trans,
               FLA_Diag diag, FLA_Obj alpha, FLA_Obj A, FLA_Obj B );
void FLASH_Trmm( FLA_Side side, FLA_Uplo uplo, FLA_Trans trans,
                 FLA_Diag diag, FLA_Obj alpha, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flatrmmns}
\index{FLASH functions!\flashtrmmns}
\purpose{
Perform one of the following triangular matrix-matrix multiplication
({\sc trmm}) operations:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
B & := & \alpha A B       & \hsp & B & := & \alpha B A \\[0.05in]
B & := & \alpha A^T B     & \hsp & B & := & \alpha B A^T \\[0.05in]
B & := & \alpha \bar{A} B & \hsp & B & := & \alpha B \bar{A} \\[0.05in]
B & := & \alpha A^H B     & \hsp & B & := & \alpha B A^H
\end{array}
\end{math}
\end{center}
where $ \alpha $ is a scalar, $ A $ is a triangular matrix, and $ B $ is a
general matrix.
The \side argument indicates whether the triangular matrix $ A $ is
multiplied on the left or the right side of $ B $.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
The \trans argument may be used to perform the check as if $ A $ were
conjugated and/or transposed.
The \diag argument indicates whether the diagonal of $ A $ is unit or
non-unit.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ B $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatypes of $ A $ and $ B $.
\itemvsp
\checkitem
If \side equals \flaleftns, then the number of rows in $ B $ and the order of
$ A $ must be equal; otherwise, if \side equals \flarightns, then the number
of columns in $ B $ and the order of $ A $ must be equal.
\itemvsp
\checkitem
\diag may not be \flazerodiagns.
\end{checks}
\ifacenotes{
\flatrmm expects $ A $ and $ B $ to be flat matrix objects.
}
\implnotes{
\flatrmm invokes a single FLAME/C variant to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS.
\flashtrmm uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc trmm} operation into subproblems
expressed in terms of individual blocks of $ A $ and $ B $ and then
invokes external BLAS to perform the computation on these blocks.
}
\begin{params}
\parameter{\flaside}{side}{Indicates whether $ A $ is multipled on the left or right side of $ B $.}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if $ A $ were conjugated and/or transposed.}
\parameter{\fladiag}{diag}{Indicates whether the diagonal of $ A $ is unit or non-unit.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Trmmsx() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Trmmsx( FLA_Side side, FLA_Uplo uplo, FLA_Trans trans,
                 FLA_Diag diag, FLA_Obj alpha, FLA_Obj A, FLA_Obj B,  
                 FLA_Obj beta, FLA_Obj C );
\end{verbatim}
\index{FLAME/C functions!\flatrmmsxns}
\purpose{
Perform one of the following extended triangular matrix-matrix multiplication
operations:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
C & := & \beta C + \alpha A B       & \hsp & C & := & \beta C + \alpha B A \\[0.05in]
C & := & \beta C + \alpha A^T B     & \hsp & C & := & \beta C + \alpha B A^T \\[0.05in]
C & := & \beta C + \alpha \bar{A} B & \hsp & C & := & \beta C + \alpha B \bar{A} \\[0.05in]
C & := & \beta C + \alpha A^H B     & \hsp & C & := & \beta C + \alpha B A^H
\end{array}
\end{math}
\end{center}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a triangular matrix, and
$ B $ and $ C $ are general matrices.
The \side argument indicates whether the triangular matrix $ A $ is
multiplied on the left or the right side of $ B $.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
The \trans argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
The \diag argument indicates whether the diagonal of $ A $ is unit or
non-unit.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ B $, and $ C $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ A $, $ B $, and $ C $.
\itemvsp
\checkitem
If \side equals \flaleftns, then the number of rows in $ B $ and the order of
$ A $ must be equal; otherwise, if \side equals \flarightns, then the number
of columns in $ B $ and the order of $ A $ must be equal.
\itemvsp
\checkitem
The dimensions of $ B $ and $ C $ must be conformal.
\itemvsp
\checkitem
\diag may not be \flazerodiagns.
\end{checks}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\trmm along with the level-1 BLAS routines \copyxns, \scalns, and \axpyns.
}
\begin{params}
\parameter{\flaside}{side}{Indicates whether $ A $ is multipled on the left or right side of $ B $.}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if $ A $ were conjugated and/or transposed.}
\parameter{\fladiag}{diag}{Indicates whether the diagonal of $ A $ is unit or non-unit.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{C}{An \flaobj representing matrix $ C $.}
\end{params}
\end{flaspec}

% --- FLA_Trsm() ---------------------------------------------------------------
% --- FLASH_Trsm() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Trsm( FLA_Side side, FLA_Uplo uplo, FLA_Trans trans, FLA_Diag diag,
               FLA_Obj alpha, FLA_Obj A, FLA_Obj B );
void FLASH_Trsm( FLA_Side side, FLA_Uplo uplo, FLA_Trans trans, FLA_Diag diag,
                 FLA_Obj alpha, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flatrsmns}
\index{FLASH functions!\flashtrsmns}
\purpose{
Perform one of the following triangular solve with multiple right-hand
sides ({\sc trsm}) operations:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
A X       & = & \alpha B & \hsp & X A       & = & \alpha B \\[0.05in]
A^T X     & = & \alpha B & \hsp & X A^T     & = & \alpha B \\[0.05in]
\bar{A} X & = & \alpha B & \hsp & X \bar{A} & = & \alpha B \\[0.05in]
A^H X     & = & \alpha B & \hsp & X A^H     & = & \alpha B 
\end{array}
\end{math}
\end{center}
and overwrite $ B $ with the contents of the solution matrix $ X $ as follows:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
B & := & \alpha A^{-1} B       & \hsp & B & := & \alpha B A^{-1} \\[0.05in]
B & := & \alpha A^{-T} B       & \hsp & B & := & \alpha B A^{-T} \\[0.05in]
B & := & \alpha \bar{A}^{-1} B & \hsp & B & := & \alpha B \bar{A}^{-1} \\[0.05in]
B & := & \alpha A^{-H} B       & \hsp & B & := & \alpha B A^{-H}
\end{array}
\end{math}
\end{center}
where $ \alpha $ is a scalar, $ A $ is a triangular matrix, and $ X $ and
$ B $ are general matrices.
The \side argument indicates whether the triangular matrix $ A $ is
multiplied on the left or the right side of $ X $.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
The \trans argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
The \diag argument indicates whether the diagonal of $ A $ is unit or
non-unit.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ B $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ is not of datatype \flaconstantns, then it must
match the datatypes of $ A $ and $ B $.
\itemvsp
\checkitem
If \side equals \flaleftns, then the number of rows in $ B $ and the order of
$ A $ must be equal; otherwise, if \side equals \flarightns, then the number
of columns in $ B $ and the order of $ A $ must be equal.
\itemvsp
\checkitem
\diag may not be \flazerodiagns.
\end{checks}
\ifacenotes{
\flatrmm expects $ A $ and $ B $ to be flat matrix objects.
}
\implnotes{
\flatrsm invokes a single FLAME/C variant to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS.
\flashtrsm uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc trsm} operation into subproblems
expressed in terms of individual blocks of $ A $ and $ B $ and then
invokes external BLAS to perform the computation on these blocks.
}
\begin{params}
\parameter{\flaside}{side}{Indicates whether $ A $ is multipled on the left or right side of $ X $.}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if $ A $ were conjugated and/or transposed.}
\parameter{\fladiag}{diag}{Indicates whether the diagonal of $ A $ is unit or non-unit.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Trsmsx() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Trsmsx( FLA_Side side, FLA_Uplo uplo, FLA_Trans trans,
                 FLA_Diag diag, FLA_Obj alpha, FLA_Obj A, FLA_Obj B,
                 FLA_Obj beta, FLA_Obj C );
\end{verbatim}
\index{FLAME/C functions!\flatrsmsxns}
\purpose{
Perform one of the following extended triangular solve with multiple
right-hand sides ({\sc trsm}) operations:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
A X       & = & \alpha B & \hsp & X A       & = & \alpha B \\[0.05in]
A^T X     & = & \alpha B & \hsp & X A^T     & = & \alpha B \\[0.05in]
\bar{A} X & = & \alpha B & \hsp & X \bar{A} & = & \alpha B \\[0.05in]
A^H X     & = & \alpha B & \hsp & X A^H     & = & \alpha B 
\end{array}
\end{math}
\end{center}
and update $ C $ with the contents of the solution matrix $ X $ as follows:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
C & := & \beta C + \alpha A^{-1} B       & \hsp & C & := & \beta C + \alpha B A^{-1} \\[0.05in]
C & := & \beta C + \alpha A^{-T} B       & \hsp & C & := & \beta C + \alpha B A^{-T} \\[0.05in]
C & := & \beta C + \alpha \bar{A}^{-1} B & \hsp & C & := & \beta C + \alpha B \bar{A}^{-1} \\[0.05in]
C & := & \beta C + \alpha A^{-H} B       & \hsp & C & := & \beta C + \alpha B A^{-H} \\[0.05in]
\end{array}
\end{math}
\end{center}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a triangular matrix, and
$ X $, $ B $, and $ C $ are general matrices.
The \side argument indicates whether the triangular matrix $ A $ is
multiplied on the left or the right side of $ X $.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
The \trans argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
The \diag argument indicates whether the diagonal of $ A $ is unit or
non-unit.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ B $, and $ C $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ A $, $ B $, and $ C $.
\itemvsp
\checkitem
If \side equals \flaleftns, then the number of rows in $ B $ and the order of
$ A $ must be equal; otherwise, if \side equals \flarightns, then the number
of columns in $ B $ and the order of $ A $ must be equal.
\itemvsp
\checkitem
The dimensions of $ B $ and $ C $ must be conformal.
\itemvsp
\checkitem
\diag may not be \flazerodiagns.
\end{checks}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\trsm along with the level-1 BLAS routines \copyxns, \scalns, and \axpyns.
}
\begin{params}
\parameter{\flaside}{side}{Indicates whether $ A $ is multipled on the left or right side of $ X $.}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if $ A $ were conjugated and/or transposed.}
\parameter{\fladiag}{diag}{Indicates whether the diagonal of $ A $ is unit or non-unit.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{C}{An \flaobj representing matrix $ C $.}
\end{params}
\end{flaspec}











\subsection{LAPACK operations}
\label{sec:lapack-front-ends}

% --- FLA_Chol() ---------------------------------------------------------------
% --- FLASH_Chol() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Chol( FLA_Uplo uplo, FLA_Obj A );
FLA_Error FLASH_Chol( FLA_Uplo uplo, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flacholns}
\index{FLASH functions!\flashcholns}
\purpose{
Perform one of the following Cholesky factorizations ({\sc chol}):
\begin{eqnarray*}
A & \rightarrow & L L^T \\
A & \rightarrow & U^T U \\
A & \rightarrow & L L^H \\
A & \rightarrow & U^H U
\end{eqnarray*}
where $ A $ is positive definite.
If $ A $ is real, then it is assumed to be symmetric; otherwise, if $ A $ is
complex, then it is assumed to be Hermitian. 
The operation references and then overwrites the lower or upper triangle of
$ A $ with the Cholesky factor $ L $ or $ U $, depending on the value of 
\uplons.
}
\rvalue{
\flasuccess if the operation is successful; otherwise, if $ A $ is not
positive definite, a signed integer corresponding to the row/column index
at which the algorithm detected a negative or non-real entry along the
diagonal.
The row/column index is zero-based, and thus its possible range extends
inclusively from $ 0 $ to $ n - 1 $.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
$ A $ must be square.
\end{checks}
\ifacenotes{
\flachol expects $ A $ to be a flat matrix object.
}
\implnotes{
\flachol invokes one or more FLAME/C variants to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS routines.
\flashchol uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc chol} operation into subproblems
expressed in terms of individual blocks of $ A $ and then invokes external
BLAS routines to perform the computation on these blocks.
By default, the unblocked Cholesky subproblems are computed by internal
implementations.
However, if the {\tt external-lapack-for-subproblems} option is enabled at
configure-time, these subproblems are computed by external unblocked LAPACK
routines.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced and overwritten during the operation.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Chol_solve() ---------------------------------------------------------
% --- FLASH_Chol_solve() -------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Chol_solve( FLA_Uplo uplo, FLA_Obj A, FLA_Obj B, FLA_Obj X );
FLA_Error FLASH_Chol_solve( FLA_Uplo uplo, FLA_Obj A, FLA_Obj B, FLA_Obj X );
\end{verbatim}
\index{FLAME/C functions!\flacholsolvens}
\index{FLASH functions!\flashcholsolvens}
\purpose{
Solve one or more symmetric (or Hermitian) positive definite linear systems,
\begin{eqnarray*}
A X & = & B
\end{eqnarray*}
by applying the results of a Cholesky factorization stored in $ A $ to a set
of right-hand sides stored in $ B $.
Thus, the solution vectors overwrite $ X $ according to one of the following
operations:
\begin{eqnarray*}
X & := & L^{-T} L^{-1} B \\
X & := & U^{-1} U^{-T} B
\end{eqnarray*}
where $ L $ and $ U $ are the lower and upper triangles of $ A $.
The operation references only one triangle of $ A $, depending on the value
of \uplons.
This value for \uplo should be the same as the \uplo argument passed to
\flachol or \flashcholns.
}
\notes{
It is assumed that the prior Cholesky factorization which wrote to $ A $
completed successfully.
}
\rvalue{
\flasuccess
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ B $, and $ X $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
$ A $ must be square.
\itemvsp
\checkitem
The number of rows in $ B $ and $ X $ must be equal to the order of $ A $,
and the number of columns in $ B $ and $ X $ must be equal.
\end{checks}
\ifacenotes{
\flacholsolve expects $ A $, $ B $, and $ X $ to be flat matrix objects.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\parameter{\flaobj}{X}{An \flaobj representing matrix $ X $.}
\end{params}
\end{flaspec}

% --- FLA_LU_nopiv() -----------------------------------------------------------
% --- FLASH_LU_nopiv() ---------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_LU_nopiv( FLA_Obj A );
FLA_Error FLASH_LU_nopiv( FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flalunopivns}
\index{FLASH functions!\flashlunopivns}
\purpose{
Perform an LU factorization without pivoting ({\sc lunopiv}):
\begin{eqnarray*}
A & \rightarrow & L U
\end{eqnarray*}
where $ A $ is a general matrix, $ L $ is lower triangular (or lower
trapezoidal if $ m > n $) with a unit diagonal, and $ U $ is upper
triangular (or upper trapezoidal if $ m < n $).
The operation overwrites the strictly lower triangular portion of $ A $
with $ L $ and the upper triangular portion of $ A $ with $ U $.
The diagonal elements of $ L $ are not stored.
}
\notes{
The algorithms used by \flalunopiv and \flalunopiv do not
perform pivoting and are therefore numerically unstable.
Almost all applications should use \flalupiv or \flashlupiv
instead.
}
\rvalue{
\flasuccess if A is nonsingular; otherwise, a signed integer corresponding
to the row/column index of the first zero diagonal entry in $ U $.
The row/column index is zero-based, and thus its possible range extends
inclusively from $ 0 $ to $ \min(m,n) - 1 $.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
$ A $ must be square.
\end{checks}
\ifacenotes{
\flalunopiv expects $ A $ to be a flat matrix object.
}
\implnotes{
\flalunopiv invokes one or more FLAME/C variants to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS routines.
\flashlunopiv uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc lunopiv} operation into subproblems
expressed in terms of individual blocks of $ A $ and then invokes external
BLAS routines to perform the computation on these blocks.
By default, the unblocked LU factorization subproblems are computed by internal
implementations.
However, if the {\tt external-lapack-for-subproblems} option is enabled at
configure-time, these subproblems are computed by external unblocked LAPACK
routines.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_LU_piv() -------------------------------------------------------------
% --- FLASH_LU_piv() -----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_LU_piv( FLA_Obj A, FLA_Obj p );
FLA_Error FLASH_LU_piv( FLA_Obj A, FLA_Obj p );
\end{verbatim}
\index{FLAME/C functions!\flalupivns}
\index{FLASH functions!\flashlupivns}
\purpose{
Perform an LU factorization with partial row pivoting ({\sc lupiv}):
\begin{eqnarray*}
A & \rightarrow & P L U
\end{eqnarray*}
where $ A $ is a general matrix, $ L $ is lower triangular (or lower
trapezoidal if $ m > n $) with a unit diagonal, $ U $ is upper
triangular (or upper trapezoidal if $ m < n $), and $ P $ is a
permutation matrix, which is encoded into the pivot vector $ p $.
The operation overwrites the strictly lower triangular portion of $ A $
with $ L $ and the upper triangular portion of $ A $ with $ U $.
The diagonal elements of $ L $ are not stored.
}
\notes{
\flalupiv and \flashlupiv fill the pivot vector $ p $ differently than the
LAPACK routines \getrf and \getftns.
The latter routines fill the vector to indicate that row $ i $ of matrix $ A $
was permuted with row $ p_i $.
By contrast, the \libflame routines fill the vector to indicate that row $ i $
of matrix $ A $ was permuted with row $ p_i + i $.
In other words, an index value stored within the \libflame pivot vector
indicates a row swap {\em relative} to the current index, while the
corresponding LAPACK pivot vector contains {\em absolute} row indices (ie:
relative to the first row).
A secondary difference is that the LAPACK routines store index values ranging
from $ 1 $ to $ \min(m,n) $ while the corresponding \libflame routines store
indices ranging from $ 0 $ to $ \min(m,n)-1 $.
The user may convert back and forth between \libflame and LAPACK-style pivot
indices using the routine \flashiftpivotstons.
(However, this routine only works with flat pivot vectors, and thus a
hierarchically-stored pivot vector must first be flattened.)
}
\rvalue{
\flasuccess if A is nonsingular; otherwise, a signed integer corresponding
to the row/column index of the first zero diagonal entry in $ U $.
The row/column index is zero-based, and thus its possible range extends
inclusively from $ 0 $ to $ \min(m,n) - 1 $.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
The numerical datatype of $ p $ must be \flaintns.
\itemvsp
\checkitem
The length of $ p $ must be $ \min(m,n) $.
\end{checks}
\ifacenotes{
\flalupiv expects $ A $ to be a flat matrix object.
}
\implnotes{
\flalupiv invokes one or more FLAME/C variants to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS routines.
\flashlupiv uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc lupiv} operation into subproblems
expressed in terms of individual blocks (or panels of blocks) of $ A $ and
then invokes external BLAS routines to perform the computation on these blocks.
By default, the unblocked LU factorization subproblems are computed by internal
implementations.
However, if the {\tt external-lapack-for-subproblems} option is enabled at
configure-time, these subproblems are computed by external unblocked LAPACK
routines.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{p}{An \flaobj representing vector $ p $.}
\end{params}
\end{flaspec}

% --- FLA_LU_piv_solve() -------------------------------------------------------
% --- FLASH_LU_piv_solve() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_LU_piv_solve( FLA_Obj A, FLA_Obj p, FLA_Obj B, FLA_Obj X );
FLA_Error FLASH_LU_piv_solve( FLA_Obj A, FLA_Obj p, FLA_Obj B, FLA_Obj X );
\end{verbatim}
\index{FLAME/C functions!\flalupivsolvens}
\index{FLASH functions!\flashlupivsolvens}
\purpose{
Solve one or more general linear systems,
\begin{eqnarray*}
A X & = & B
\end{eqnarray*}
by applying the results of an LU factorization (with partial pivoting) stored
in $ A $ and $ p $ to a set of right-hand sides stored in $ B $.
Thus, the solution vectors overwrite $ X $ according to the following
operation:
\begin{eqnarray*}
X & := & U^{-1} L^{-1} P B
\end{eqnarray*}
where $ L $ is the strictly lower triangle (with unit diagonal) of $ A $,
$ U $ is the upper triangle of $ A $, and $ P $ represents the perumatation
matrix which applies the row interchanges encoded in the pivot vector $ p $.
}
\notes{
It is assumed that the prior LU factorization which wrote to $ A $
completed successfully.
}
\rvalue{
\flasuccess
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ B $, and $ X $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The numerical datatype of $ p $ must be \flaintns.
%\itemvsp
%\checkitem
%$ A $ must be square.
\itemvsp
\checkitem
The length of $ p $ must be $ \min(m,n) $ where $ A $ is $ m \by n $.
\itemvsp
\checkitem
The number of rows in $ B $ and $ X $ must be equal to the order of $ A $,
and the number of columns in $ B $ and $ X $ must be equal.
\end{checks}
\ifacenotes{
\flalupivsolve expects $ A $, $ p $, $ B $, and $ X $ to be flat matrix objects.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{p}{An \flaobj representing vector $ p $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\parameter{\flaobj}{X}{An \flaobj representing matrix $ X $.}
\end{params}
\end{flaspec}

% --- FLA_Apply_pivots() -------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Apply_pivots( FLA_Side side, FLA_Trans trans, FLA_Obj p, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flaapplypivotsns}
\purpose{
Apply a permutation matrix $ P $ to a matrix $ A $ ({\sc appiv}).
\begin{eqnarray*}
A & := & P A \\
A & := & P^T A \\
A & := & A P \\
A & := & A P^T
\end{eqnarray*}
where $ A $ is a general matrix and $ P $ is a permutation matrix corresponding
to the pivot vector $ p $.
}
\notes{
The pivot vector $ p $ must contain pivot values that conform to \libflame
pivot indexing.
If the pivot vector was filled using an LAPACK routine, it must first be
converted to \libflame pivot indexing with \flashiftpivotsto before it may be
used with \flaapplypivotsunbextns.
Please see the description for \flalupiv in Section \ref{sec:lapack-front-ends}
for details on the differences between LAPACK-style pivot vectors and \libflame
pivot vectors.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
The numerical datatype of $ p $ must be \flaintns.
\end{checks}
\ifacenotes{
\flaapplypivots expects $ A $ to be a flat matrix object.
}
\implnotes{
By default, the {\sc appiv} operation is performed by an internal
implementation.
However, if the {\tt external-lapack-for-subproblems} option is enabled at
configure-time, the operation is performed by an external unblocked LAPACK
routine.
}
\caveats{
This function is currently only implemented for applying $ P $
from the left (ie: \side equal to \flaleft and \trans equal to \flanotransposens).
}
\begin{params}
\parameter{\flaside}{side}{Indicates whether the operation proceeds as if the permutation matrix $ P $ is applied from the left or the right.}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if the permutation matrix $ P $ were transposed.}
\parameter{\flaobj}{p}{An \flaobj representing vector $ p $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLASH_LU_incpiv() --------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLASH_LU_incpiv( FLA_Obj A, FLA_Obj p, FLA_Obj L_inter );
\end{verbatim}
\index{FLASH functions!\flashluincpivns}
\purpose{
Perform an LU factorization with incremental pivoting ({\sc luincpiv}).
The operation is similar to that of LU with partial row pivoting, except
that the algorithm is SuperMatrix-aware.
As a consequence, the arguments must be hierarchical objects.
}
\notes{
It is {\em highly} recommended that the user create and initialize a flat object
containing the matrix to be factorized and then call
\flashluincpivcreatehiermatrices to create hierarchical matrices
$ A $, $ p $, and $ L_{inter} $ from the original flat matrix.
}
\rvalue{
\flasuccess if the operation is successful; otherwise, if $ A $ is singular,
a signed integer corresponding to the row/column index at which the algorithm
detected a zero entry along the diagonal.
The row/column index is zero-based, and thus its possible range extends
inclusively from $ 0 $ to $ \min(m,n) - 1 $.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ L_{inter} $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The numerical datatype of $ p $ must be \flaintns.
\itemvsp
\checkitem
$ A $ must be square.
\end{checks}
\ifacenotes{
In addition to the input matrix $ A $ and pivot vector $ p $, the function
requires an additional object $ L_{inter} $, which stores interim matrices
that are used in a subsequent forward substitution.
}
\caveats{
Currently, this function only supports matrices with hierarchical depths of
exactly 1.
}
\begin{params}
\parameter{\flaobj}{A}{A hierarchical \flaobj representing matrix $ A $.}
\parameter{\flaobj}{p}{A hierarchical \flaobj representing vector $ p $.}
\parameter{\flaobj}{L\_inter}{A hierarchical \flaobj representing matrix $ L_{inter} $.}
\end{params}
\end{flaspec}

% --- FLASH_LU_incpiv_solve() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLASH_LU_incpiv_solve( FLA_Obj A, FLA_Obj p, FLA_Obj L_inter,
                                 FLA_Obj B, FLA_Obj X );
\end{verbatim}
\index{FLASH functions!\flashluincpivsolvens}
\purpose{
Solve one or more general linear systems,
\begin{eqnarray*}
A X & = & B
\end{eqnarray*}
by applying the results of an LU factorization with incremental pivoting
stored in $ A $, $ p $, and $ L_{inter} $ to a set of right-hand sides
stored in $ B $.
Thus, the solution vectors overwrite $ X $ according to the following
operation:
\begin{eqnarray*}
X & := & U^{-1} L^{-1} P B
\end{eqnarray*}
where $ L $ is the strictly lower triangle (with unit diagonal) of $ A $,
$ U $ is the upper triangle of $ A $, and $ P $ represents the perumatation
matrix which applies the row interchanges encoded in the pivot vector $ p $.
}
\notes{
Note that \flashluincpivsolve may only be used in conjunction with matrices
that have been factorized via \flashluincpivns.
The output from \flalupiv is {\em not} compatible with this function.
}
\rvalue{
\flasuccess
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ L_{inter} $, $ B $, and $ X $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The numerical datatype of $ p $ must be \flaintns.
\itemvsp
\checkitem
$ A $ must be square.
\itemvsp
\checkitem
The number of rows in $ B $ and $ X $ must be equal to the number of
columns in $ A $,
and the number of columns in $ B $ and $ X $ must be equal.
\end{checks}
\caveats{
Currently, this function only supports matrices with hierarchical depths of
exactly 1.
}
\begin{params}
\parameter{\flaobj}{A}{A hierarchical \flaobj representing matrix $ A $.}
\parameter{\flaobj}{p}{A hierarchical \flaobj representing vector $ p $.}
\parameter{\flaobj}{L\_inter}{A hierarchical \flaobj representing matrix $ L_{inter} $.}
\parameter{\flaobj}{B}{A hierarchical \flaobj representing matrix $ B $.}
\parameter{\flaobj}{X}{A hierarchical \flaobj representing matrix $ X $.}
\end{params}
\end{flaspec}

% --- FLASH_FS_incpiv() --------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_FS_incpiv( FLA_Obj A, FLA_Obj p, FLA_Obj L_inter, FLA_Obj b );
\end{verbatim}
\index{FLASH functions!\flashfsincpivns}
\purpose{
Perform a forward substitution with the unit lower triangular $ L $ factor
(residing in the lower triangle of hierarchical matrix $ A $) and a right-hand
side vector $ b $, overwriting $ b $ with an intermediate vector $ y $.
\begin{eqnarray*}
y & := & L^{-1} b
\end{eqnarray*}
The matrix $ p $ contains the incremental pivot vectors that were used
during the LU factorization with incremental pivoting performed via
\flashluincpivns.
The matrix $ L_{inter} $ contains intermediate lower triangular factors computed
during the factorization, which are reused in the forward substitution.
Note that $ p $ and $ L_{inter} $ are hierarchical, and provided by
\flashluincpivns.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ L_{inter} $, and $ b $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The numerical datatype of $ p $ must be \flaintns.
\itemvsp
\checkitem
$ A $ must be square.
\end{checks}
\implnotes{
\flashfsincpiv uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the operation into subproblems
expressed in terms of individual blocks of $ A $, $ p $, $ L_{inter} $, and
$ b $ and then invokes external BLAS routines to perform the computation
on these blocks.
}
\caveats{
\flashfsincpiv currently only works for hierarchical matrices of depth 1 where
$ A $ refers to a single storage block.
}
\begin{params}
\parameter{\flaobj}{A}{A hierarchical \flaobj representing matrix $ A $.}
\parameter{\flaobj}{p}{A hierarchical \flaobj representing matrix $ p $.}
\parameter{\flaobj}{L\_inter}{A hierarchical \flaobj representing matrix $ L_{inter} $.}
\parameter{\flaobj}{b}{A hierarchical \flaobj representing vector $ b $.}
\end{params}
\end{flaspec}

% --- FLA_QR_UT() --------------------------------------------------------------
% --- FLASH_QR_UT() ------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_QR_UT( FLA_Obj A, FLA_Obj T );
void FLASH_QR_UT( FLA_Obj A, FLA_Obj T );
\end{verbatim}
\index{FLAME/C functions!\flaqrutns}
\index{FLASH functions!\flashqrutns}
\purpose{
Perform a QR factorization via the UT transform ({\sc qrut}):
\begin{eqnarray*}
A & \rightarrow & Q R
\end{eqnarray*}
where $ Q $ is an orthogonal matrix (or, a unitary matrix if $ A $ is complex)
and $ R $ is an upper triangular matrix.
The resulting Householder vectors associated with $ Q $ are stored column-wise
below the diagonal of $ A $ and should only be used with other UT transform
operations.
Upon completion, matrix $ T $ contains the triangular factors of the block
Householder transformations that were used in the factorization algorithm.
}
\notes{
The matrix factor $ Q $ determined by \flaqrut and \flashqrut is equal to
$ H_0 H_1 \cdots H_{k-1} $, where $ H_i $ is the Householder transformation
which annihilates the subdiagonal entries in the $ i $th column of the original
matrix $ A $.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ T $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
%The width of $ T $ must be $ \min(m,n) $ where $ A $ is $ m \by n $.
The width of $ T $ must be equal to the width of $ A $.
\end{checks}
\ifacenotes{
\flaqrut expects $ A $ and $ T $ to be flat matrix objects.
}
\implnotes{
\flaqrut invokes a single FLAME/C variant to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS routines.
The unblocked {\sc qrut} subproblems are computed by internal
implementations.
\flashqrut uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc qrut} operation into subproblems
expressed in terms of individual blocks (or panels of blocks) of $ A $ and
then invokes external BLAS routines to perform the computation on these blocks.
The unblocked {\sc qrut} subproblems are computed by internal
implementations.
(External LAPACK routines are not used, even when
{\tt external-lapack-for-subproblems} option is enabled.)
}
\implnotes{
For \flaqrut, the algorithmic blocksize is determined by
the length of $ T $.
When in doubt, create $ T $ via \flaqrutcreatetns.
}
\implnotes{
For \flashqrut, the algorithmic blocksize $ b $, which corresponds to the
scalar length a single block of T, must be equal to the storage blocksize
used in $ A $ and $ T $.
When in doubt, create $ T $ via \flashqrutcreatehiermatricesns.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\end{params}
\end{flaspec}

% --- FLA_QR_UT_solve() --------------------------------------------------------
% --- FLASH_QR_UT_solve() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_QR_UT_solve( FLA_Obj A, FLA_Obj T, FLA_Obj B, FLA_Obj X );
void FLASH_QR_UT_solve( FLA_Obj A, FLA_Obj T, FLA_Obj B, FLA_Obj X );
\end{verbatim}
\index{FLAME/C functions!\flaqrutsolvens}
\index{FLASH functions!\flashqrutsolvens}
\purpose{
Solve one or more general linear systems,
\begin{eqnarray*}
A X & = & B
\end{eqnarray*}
by applying the results of a QR factorization via the UT transform stored in
$ A $ and $ T $ to a set of right-hand sides stored in $ B $.
Thus, the solution vectors overwrite $ X $ according to the following
operation:
\begin{eqnarray*}
X & := & R^{-1} Q^{H} B
\end{eqnarray*}
where $ R $ is an upper triangular matrix, stored in $ A $, and $ Q $ is
an orthogonal (or unitary) matrix formed from the upper triangular
Householder factors in $ T $ and the Householder vectors stored column-wise
below the diagonal of $ A $.
}
\notes{
Note that \flaqrutsolve and \flashqrutsolve may only be used in conjunction
with matrices that have been factorized via \flaqrut and \flashqrutns,
respectively.
The output from \flashqrutinc is {\em not} compatible with these functions.
}
\rvalue{
\flasuccess
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ T $, $ B $, and $ X $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
%The width of $ T $ must be $ \min(m,n) $ where $ A $ is $ m \by n $.
The width of $ T $ must be equal to the width of $ A $.
\itemvsp
\checkitem
The number of rows in $ A $ and $ B $ must be equal,
the number of columns of $ A $ and the number of rows of $ X $ must be equal,
and the number of columns in $ X $ and $ B $ must be equal.
\end{checks}
\ifacenotes{
\flaqrutsolve expects $ A $, $ T $, $ B $, and $ X $ to be flat matrix objects.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\parameter{\flaobj}{X}{An \flaobj representing matrix $ X $.}
\end{params}
\end{flaspec}

% --- FLASH_QR_UT_inc() --------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_QR_UT_inc( FLA_Obj A, FLA_Obj TW );
\end{verbatim}
\index{FLASH functions!\flashqrutincns}
\purpose{
Perform an incremental QR factorization via the UT transform ({\sc qrutinc}).
The operation is similar to the operation implemented by \flaqrutns,
except that the algorithm is SuperMatrix-aware.
As a consequence, the arguments must be hierarchical objects.
}
\notes{
It is {\em highly} recommended that the user create and initialize a flat object
containing the matrix to be factorized and then call
\flashqrutinccreatehiermatrices to create hierarchical matrices
$ A $ and $ TW $ from the original flat matrix.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ TW $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
$ A $ must be square.
\itemvsp
\checkitem
$ A $ and $ TW $ must each have the same number of blocks in the row and column
dimensions.
\end{checks}
\ifacenotes{
In addition to the input matrix $ A $, the function requires an additional
matrix $ TW $ to hold the triangular factors of the block Householder
transformations computed for each storage block.
These transformations are used when applying $ Q $ (via \flashapplyqutincns).
The matrix $ TW $ also contains temporary workspace needed by the
incremental QR algorithm.
}
\implnotes{
\flashqrutinc uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc qrutinc} operation into subproblems
expressed in terms of individual blocks of $ A $ and then invokes external
BLAS routines to perform the computation on these blocks.
The unblocked {\sc qrut} subproblems are computed by internal
implementations.
(External LAPACK routines are not used, even when
{\tt external-lapack-for-subproblems} option is enabled.)
}
\implnotes{
Strictly speaking, the blocks in the lower triangle (including the diagonal)
of $ TW $ are used to store the block Householder transformations corresponding
to $ T $ in \flaqrut while the blocks in the upper triangle of $ TW $ are used
as workspace only.
}
\caveats{
Currently, this function only supports matrices with hierarchical depths of
exactly 1.
}
\begin{params}
\parameter{\flaobj}{A}{A hierarchical \flaobj representing matrix $ A $.}
\parameter{\flaobj}{TW}{A hierarchical \flaobj representing matrix $ TW $.}
\end{params}
\end{flaspec}

% --- FLASH_QR_UT_inc_solve() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_QR_UT_inc_solve( FLA_Obj A, FLA_Obj TW, FLA_Obj B, FLA_Obj X );
\end{verbatim}
\index{FLASH functions!\flashqrutincsolvens}
\purpose{
Solve one or more general linear systems,
\begin{eqnarray*}
A X & = & B
\end{eqnarray*}
by applying the results of an incremental QR factorization via the UT
transform stored in $ A $ and $ TW $ to a set of right-hand sides
stored in $ B $.
Thus, the solution vectors overwrite $ X $ according to the following
operation:
\begin{eqnarray*}
X & := & R^{-1} Q^{H} B
\end{eqnarray*}
where $ R $ is an upper triangular matrix, stored in $ A $, and $ Q $ is
an orthogonal (or unitary) matrix formed from the upper triangular
Householder factors in $ TW $ and the Householder vectors stored column-wise
below the diagonal of $ A $.
}
\notes{
Note that \flashqrutincsolve may only be used in conjunction with matrices
that have been factorized via \flashqrutincns.
The output from \flaqrut is {\em not} compatible with this function.
}
\rvalue{
\flasuccess
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ TW $, $ B $, and $ X $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
$ A $ must be square.
\itemvsp
\checkitem
$ A $ and $ TW $ must each have the same number of blocks in the row and column
dimensions.
\itemvsp
\checkitem
The number of rows in $ A $ and $ B $ must be equal,
the number of columns of $ A $ and the number of rows of $ X $ must be equal,
and the number of columns in $ X $ and $ B $ must be equal.
\end{checks}
\caveats{
Currently, this function only supports matrices with hierarchical depths of
exactly 1.
}
\begin{params}
\parameter{\flaobj}{A}{A hierarchical \flaobj representing matrix $ A $.}
\parameter{\flaobj}{TW}{A hierarchical \flaobj representing matrix $ TW $.}
\parameter{\flaobj}{B}{A hierarchical \flaobj representing matrix $ B $.}
\parameter{\flaobj}{X}{A hierarchical \flaobj representing matrix $ X $.}
\end{params}
\end{flaspec}

% --- FLA_LQ_UT() --------------------------------------------------------------
% --- FLASH_LQ_UT() ------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_LQ_UT( FLA_Obj A, FLA_Obj T );
void FLASH_LQ_UT( FLA_Obj A, FLA_Obj T );
\end{verbatim}
\index{FLAME/C functions!\flalqutns}
\index{FLASH functions!\flashlqutns}
\purpose{
Perform a LQ factorization via the UT transform ({\sc lqut}):
\begin{eqnarray*}
A & \rightarrow & L Q^H
\end{eqnarray*}
where $ Q $ is an orthogonal matrix (or, a unitary matrix if $ A $ is complex)
and $ L $ is an lower triangular matrix.
The resulting Householder vectors associated with $ Q $ are stored row-wise
above the diagonal of $ A $ and should only be used with other UT transform
operations.
Upon completion, matrix $ T $ contains the triangular factors of the block
Householder transformations that were used in the factorization algorithm.
}
\notes{
The matrix factor $ Q $ determined by \flalqut and \flashlqut is equal to
$ H_0 H_1 \cdots H_{k-1} $, where $ H_i $ is the Householder transformation
which annihilates the superdiagonal entries in the $ i $th row of the original
matrix $ A $.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ T $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The width of $ T $ must be equal to the length of $ A $.
\end{checks}
\ifacenotes{
\flaqrut expects $ A $ and $ T $ to be flat matrix objects.
}
\implnotes{
\flalqut invokes a single FLAME/C variant to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS routines.
The unblocked {\sc lqut} subproblems are computed by internal
implementations.
\flashlqut uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc lqut} operation into subproblems
expressed in terms of individual blocks (or panels of blocks) of $ A $ and
then invokes external BLAS routines to perform the computation on these blocks.
The unblocked {\sc lqut} subproblems are computed by internal
implementations.
(External LAPACK routines are not used, even when
{\tt external-lapack-for-subproblems} option is enabled.)
}
\implnotes{
For \flalqut, the algorithmic blocksize is determined by
the length of $ T $.
When in doubt, create $ T $ via \flalqutcreatetns.
}
\implnotes{
For \flashlqut, the algorithmic blocksize $ b $, which corresponds to the
scalar length a single block of T, must be equal to the storage blocksize
used in $ A $ and $ T $.
When in doubt, create $ T $ via \flashlqutcreatehiermatricesns.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\end{params}
\end{flaspec}

% --- FLA_LQ_UT_solve() --------------------------------------------------------
% --- FLASH_LQ_UT_solve() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_LQ_UT_solve( FLA_Obj A, FLA_Obj T, FLA_Obj B, FLA_Obj X );
void FLASH_LQ_UT_solve( FLA_Obj A, FLA_Obj T, FLA_Obj B, FLA_Obj X );
\end{verbatim}
\index{FLAME/C functions!\flalqutsolvens}
\index{FLASH functions!\flashlqutsolvens}
\purpose{
Solve one or more general linear systems,
\begin{eqnarray*}
A X & = & B
\end{eqnarray*}
by applying the results of a LQ factorization via the UT transform stored in
$ A $ and $ T $ to a set of right-hand sides stored in $ B $.
Thus, the solution vectors overwrite $ X $ according to the following
operation:
\begin{eqnarray*}
X & := & Q L^{-1} B
\end{eqnarray*}
where $ L $ is an lower triangular matrix, stored in $ A $, and $ Q $ is
an orthogonal (or unitary) matrix formed from the upper triangular
Householder factors in $ T $ and the Householder vectors stored row-wise
above the diagonal of $ A $.
}
\notes{
Note that \flalqutsolve and \flashlqutsolve may only be used in conjunction
with matrices that have been factorized via \flalqut and \flashlqutns,
respectively.
%The output from \flashlqutinc is {\em not} compatible with these functions.
}
\rvalue{
\flasuccess
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ T $, $ B $, and $ X $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The width of $ T $ must be equal to the length of $ A $.
\itemvsp
\checkitem
The number of rows in $ A $ and $ B $ must be equal,
the number of columns of $ A $ and the number of rows of $ X $ must be equal,
and the number of columns in $ X $ and $ B $ must be equal.
\end{checks}
\ifacenotes{
\flalqutsolve expects $ A $, $ T $, $ B $, and $ X $ to be flat matrix objects.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\parameter{\flaobj}{X}{An \flaobj representing matrix $ X $.}
\end{params}
\end{flaspec}

% --- FLASH_CAQR_UT_inc() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_CAQR_UT_inc( dim_t p, FLA_Obj A, FLA_Obj ATW, FLA_Obj R, FLA_Obj RTW );
\end{verbatim}
\index{FLASH functions!\flashcaqrutincns}
\purpose{
Perform an incremental communication-avoiding QR factorization via the
UT transform ({\sc caqrutinc}).
The operation is performed in two stages.
First, the input matrix $ A $ %and a conformal workspace matirx $ R $, are
is partitioned into $ p $ panels,
\[
A
\rightarrow
\left(
\begin{array}{c}
A_0 \\
A_1 \\
\vdots \\
A_{p-1}
\end{array}
\right)
%\quad
%R
%\rightarrow
%\left(
%\begin{array}{c}
%R_0 \\
%R_1 \\
%\vdots \\
%R_{p-1}
%\end{array}
%\right), 
\]
and incremental QR factorizations are performed on each submatrix $ A_i $,
with the resulting Householder vectors overwriting the blocks of $ A_i $
and the corresponding block Householder triangular factors stored to $ ATW $.
This results in $ p $ upper triangular factors overwriting the
upper triangles of $ A_i $.
In the second stage, the upper triangles of $ A_i $ are copied to
$ R_i $, and then $ R_1, \ldots, R_{p-1} $ are individually factored
against submatrix $ R_0 $ in a manner similar to that used in an incremental
QR factorization, except the upper triangular structure of each $ R_i $
submatrix is leveraged to avoid computing with implicit zeros.
The resulting Householder vectors of the second stage overwrite the various
blocks of $ R_1, \ldots, R_{p-1} $.
The algorithm is SuperMatrix-aware.
As a consequence, the arguments must be hierarchical objects.
}
\notes{
It is {\em highly} recommended that the user create and initialize a flat object
containing the matrix to be factorized and then call
\flashcaqrutinccreatehiermatrices to create hierarchical matrices
$ A $ and $ TW $ from the original flat matrix.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ ATW $, $ R $, and $ RTW $ must be identical
and floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
$ A $, $ ATW $, $ R $, and $ RTW $ must each have the same number of blocks
in the row and column dimensions.
\end{checks}
\ifacenotes{
In addition to the input matrix $ A $ and workspace/output matrix $ R $, the
function requires two additional matrices $ ATW $ and $ RTW $ to hold the
triangular factors of the block Householder transformations computed for
each storage block.
These transformations are used when applying the matrices $ Q_A $ and $ Q_R $
associated with the first and second factorization stages.
The matrices $ ATW $ and $ RTW $ also contain temporary workspace needed by
both stages.
}
\implnotes{
\flashcaqrutinc uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc caqrutinc} operation into subproblems
expressed in terms of individual blocks of $ A $ and then invokes external
BLAS routines to perform the computation on these blocks.
The unblocked {\sc caqrut} subproblems are computed by internal
implementations.
(External LAPACK routines are not used, even when
{\tt external-lapack-for-subproblems} option is enabled.)
}
\implnotes{
Strictly speaking, the blocks in the lower triangle (including the diagonal)
of $ ATW $ are used to store the block Householder transformations corresponding
to $ T $ in \flaqrut while the blocks in the upper triangle of $ ATW $ are used
as workspace only.
This is the case for $ RTW $ as well.
}
\caveats{
Currently, this function only supports matrices with hierarchical depths of
exactly 1.
}
\begin{params}
\parameter{\dimt}{p}{An unsigned integer representing the number of panels into which $ A $ is partitioned during the first stage of factorization.}
\parameter{\flaobj}{A}{A hierarchical \flaobj representing matrix $ A $.}
\parameter{\flaobj}{ATW}{A hierarchical \flaobj representing matrix $ ATW $.}
\parameter{\flaobj}{R}{A hierarchical \flaobj representing matrix $ R $.}
\parameter{\flaobj}{RTW}{A hierarchical \flaobj representing matrix $ RTW $.}
\end{params}
\end{flaspec}

% --- FLASH_CAQR_UT_inc_solve() ------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_CAQR_UT_inc_solve( dim_t p, FLA_Obj A, FLA_Obj ATW, FLA_Obj R, FLA_Obj RTW,
                              FLA_Obj B, FLA_Obj X );
\end{verbatim}
\index{FLASH functions!\flashcaqrutincsolvens}
\purpose{
Solve one or more general linear systems,
\begin{eqnarray*}
A X & = & B
\end{eqnarray*}
by applying the results of an incremental communication-avoiding QR
factorization via the UT
transform stored in $ A $ and $ ATW $, and $ R $ and $ RTW $,
to a set of right-hand sides stored in $ B $.
Thus, the solution vectors overwrite $ X $ according to the following
operation:
\begin{eqnarray*}
X & := & R_0^{-1} Q_R^{H} Q_A^{H} B
\end{eqnarray*}
where $ R_0 $ is the first upper triangular submatrix in $ R $, $ Q_A $ is
an orthogonal (or unitary) matrix formed from the upper triangular
Householder factors in $ ATW $ and the Householder vectors stored column-wise
below the diagonals of the $ p $ subpartitions of $ A $, and $ Q_R $ is
the orthogonal (or unitary) matrix formed from the upper triangular
Householder factors in $ RTW $ and the Householder vectors stored columnwise
in the upper triangles of the $ p $ subpartitions of $ R $.
}
\notes{
Note that \flashcaqrutincsolve may only be used in conjunction with matrices
that have been factorized via \flashcaqrutincns.
The output from \flaqrut and \flashqrutinc are {\em not} compatible with this
function.
}
\rvalue{
\flasuccess
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ ATW $, $ R $, $ RTW $, $ B $, and $ X $
must be identical and floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
$ A $, $ ATW $, $ R $, and $ RTW $ must each have the same number of blocks
in the row and column dimensions.
\itemvsp
\checkitem
The number of rows in $ A $ and $ B $ must be equal,
the number of columns of $ A $ and the number of rows of $ X $ must be equal,
and the number of columns in $ X $ and $ B $ must be equal.
\end{checks}
\caveats{
Currently, this function only supports matrices with hierarchical depths of
exactly 1.
}
\begin{params}
\parameter{\dimt}{p}{An unsigned integer representing the number of panels into which $ A $ is partitioned during the first stage of factorization.}
\parameter{\flaobj}{A}{A hierarchical \flaobj representing matrix $ A $.}
\parameter{\flaobj}{ATW}{A hierarchical \flaobj representing matrix $ ATW $.}
\parameter{\flaobj}{R}{A hierarchical \flaobj representing matrix $ R $.}
\parameter{\flaobj}{RTW}{A hierarchical \flaobj representing matrix $ RTW $.}
\parameter{\flaobj}{B}{A hierarchical \flaobj representing matrix $ B $.}
\parameter{\flaobj}{X}{A hierarchical \flaobj representing matrix $ X $.}
\end{params}
\end{flaspec}

% --- FLA_UDdate_UT() ----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_UDdate_UT( FLA_Obj R, FLA_Obj C, FLA_Obj D, FLA_Obj T );
\end{verbatim}
\index{FLAME/C functions!\flauddateutns}
\purpose{
Perform an up-and-downdate ({\sc uddateut}) of the upper
triangular factor $ R $ (via up-and-downdating UT transforms) that
arises from solving a linear least-squares problem, $ Ax = y $.
Note that such a problem
\begin{center}
\begin{math}
\begin{array}{ccc}
A x & = & y
\end{array}
\end{math}
\end{center}
is typically solved via one of two methods. In the first method, the
Cholesky factor $ R $ of $ A^H A $ is used to solve
\begin{center}
\begin{math}
\begin{array}{ccc}
A^H A x & = & A^H y \\
R^H R x & = &
\end{array}
\end{math}
\end{center}
In the second method, the QR factorization of $ A $ is used to solve
\begin{center}
\begin{math}
\begin{array}{ccc}
R x & = & Q^H y
\end{array}
\end{math}
\end{center}
Let us assume that we begin with $ A $ and $ y $ such that
\begin{center}
\begin{math}
\begin{array}{ccc}
\left(
\begin{array}{c | c}
A & y
\end{array}
\right)
& = &
\left(
\begin{array}{c | c}
B & b \\ \hline \hline
D & d
\end{array}
\right)
\end{array}
\end{math}
\end{center}
and $ R $ has already been computed, via one of the two methods above.
Let us further assume that we wish to update $ R $ to reflect a new
system consisting of $ \tilde A $ and $ \tilde y $ such that
\begin{center}
\begin{math}
\begin{array}{ccc}
\left(
\begin{array}{c | c}
\tilde A & \tilde y
\end{array}
\right)
& = &
\left(
\begin{array}{c | c}
B & b \\ \hline \hline
C & c
\end{array}
\right)
\end{array}
\end{math}
\end{center}
The {\sc uddateut} operation simultaneously (a) updates the upper
triangular factor $ R $ to include the contributions of $ C $ and (b)
downdates $ R $ to remove the contributions of $ D $ without explicitly
performing a new factorization (Cholesky or QR) using $ \tilde A $. 
Upon completion, the operation will have overwritten the $ j $th columns
of $ C $ and $ D $ with the vectors $ u_j $ and $ v_j $, respectively,
associated with the up-and-downdating Householder transforms $ G_j $ used
to annihilate the corresponding columns of $ C $ and $ D $.
Similarly, the operation sets matrix $ T $ to contain the upper triangular
factors of the block Householder transforms used in the up-and-downdate.
These triangular factors are re-used when applying the transforms to the
right-hand sides.
}
\notes{
This operation only up-and-downdates $ R $.
To up-and-downdate the right-hand side of a linear least-squares
system, use \flauddateutupdaterhsns.
}
\begin{checks}
\checkitem
The numerical datatypes of $ R $, $ C $, $ D $, and $ T $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
$ R $ must be square.
\itemvsp
\checkitem
The widths of $ R $, $ C $, $ D $, and $ T $ must be equal.
\end{checks}
\ifacenotes{
\flauddateut expects $ R $, $ C $, $ D $, and $ T $ to be flat matrix objects.
}
\implnotes{
\flauddateut invokes a single FLAME/C variant to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS routines.
The unblocked {\sc uddateut} subproblems are computed by internal
implementations.
(External LAPACK routines are not used, even when
{\tt external-lapack-for-subproblems} option is enabled.)
}
\implnotes{
The algorithmic blocksize $ b $ is determined by the length of $ T $.
When in doubt, create $ T $ via \flauddateutcreatetns.
}
\begin{params}
\parameter{\flaobj}{R}{An \flaobj representing matrix $ R $.}
\parameter{\flaobj}{C}{An \flaobj representing matrix $ C $.}
\parameter{\flaobj}{D}{An \flaobj representing matrix $ D $.}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\end{params}
\end{flaspec}

% --- FLA_UDdate_UT_update_rhs() -----------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_UDdate_UT_update_rhs( FLA_Obj T, FLA_Obj bR,
                               FLA_Obj C, FLA_Obj bC,
                               FLA_Obj D, FLA_Obj bD );
\end{verbatim}
\index{FLAME/C functions!\flauddateutupdaterhsns}
\purpose{
Perform an up-and-downdate of the right-hand maintained when solving a
linear least-squares system $ A x = y $.
Note that the right-hand side that is updated, $ b_R $, is initially
computed either as
\begin{center}
\begin{math}
\begin{array}{ccc}
A^H y & = & b_R
\end{array}
\end{math}
\end{center}
when the method of normal equations is used, or
\begin{center}
\begin{math}
\begin{array}{ccc}
Q^H y & = & b_R
\end{array}
\end{math}
\end{center}
when a QR factorization is used, where 
%\begin{center}
\begin{math}
\begin{array}{ccc}
y
& = &
\left(
\begin{array}{c}
b_B \\ \hline \hline
b_D
\end{array}
\right)
\end{array}
\end{math}.
%\end{center}
This operation assumes the user wishes to be able to solve a new system,
$ \tilde{A} x = \tilde{y} $, that would result in
$ \tilde{R}^H \tilde{R} x = \tilde{A}^H \tilde{y} $ (normal equations) or
$ \tilde{R} x = \tilde{Q}^H \tilde{y} $ (QR factorization),
where
%\begin{center}
\begin{math}
\begin{array}{ccc}
\tilde{y}
& = &
\left(
\begin{array}{c}
b_B \\ \hline \hline
b_C
\end{array}
\right)
\end{array}
\end{math}
%\end{center}
and $ \tilde{R} $ has already been computed from the original matrix $ R $
by \flauddateutns.
Thus, \flauddateutupdaterhs updates $ b_R $ such that it removes the
contributions of $ b_D $ and includes the contributions of of $ b_C $.
In other words, upon completion, $ b_R $ contains the values it would have
contained as if it had been computed via fully-formed $ \tilde{y} $ and
$ \tilde{A} $.
Note that the operation preserves the original values of $ b_C $ and $ b_D $.
}
\notes{
\flauddateutupdaterhs should be invoked using the $ C $, $ D $, and $ T $
matrices that were updated by the \flauddateut during the up-and-downdate
of the upper triangular factor $ R $.
Subsequent to the up-and-downdate of the right-hand side, the user may use
\flauddateutsolve to solve the updated system.
}
\begin{checks}
\checkitem
The numerical datatypes of $ T $, $ C $, $ D $, $ b_R $, $ b_C $, and $ b_D $
must be identical and floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The widths of $ T $, $ C $, and $ D $ must be equal.
\itemvsp
\checkitem
The widths of $ b_R $, $ b_C $, and $ b_D $ must be equal.
\itemvsp
\checkitem
The length of $ b_R $ must equal the width of $ T $;
the length of $ b_C $ must equal the length of $ C $;
and the length of $ b_D $ must equal the lenght of $ D $.
\end{checks}
\ifacenotes{
\flauddateut expects $ R $, $ C $, $ D $, and $ T $ to be flat matrix objects.
}
\implnotes{
\flauddateutupdaterhs is implemented as a convenience wrapper to
\flaapplyqudutcreateworkspace and \flaapplyqudutns.
}
\implnotes{
The algorithmic blocksize $ b $ is determined by the length of $ T $.
When in doubt, create $ T $ via \flauddateutcreatetns.
}
\begin{params}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\parameter{\flaobj}{b\_R}{An \flaobj representing matrix $ b_R $.}
\parameter{\flaobj}{C}{An \flaobj representing matrix $ C $.}
\parameter{\flaobj}{b\_C}{An \flaobj representing matrix $ b_C $.}
\parameter{\flaobj}{D}{An \flaobj representing matrix $ D $.}
\parameter{\flaobj}{b\_D}{An \flaobj representing matrix $ b_D $.}
\end{params}
\end{flaspec}

% --- FLA_UDdate_UT_solve() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_UDdate_UT_solve( FLA_Obj R, FLA_Obj bR, FLA_Obj x );
\end{verbatim}
\index{FLAME/C functions!\flauddateutsolvens}
\purpose{
Solve one or more linear least-squares systems using the upper triangular
factor $ R $ and the right-hand side $ b_R $.
Presumably the user has already up-and-downdated $ R $, via \flauddateutns,
and $ b_R $, via \flauddateutupdaterhsns.
}
\notes{
Note that \flauddateutsolve may only be used in conjunction with matrices
that have been factorized via \flauddateutns.
The output from \flashuddateutinc is {\em not} compatible with this function.
}
\rvalue{
\flasuccess
}
\begin{checks}
\checkitem
The numerical datatypes of $ R $, $ b_R $, and $ x $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The order of $ R $ and the length of $ b_R $ must be equal;
the width of $ b_R $ and the width of $ x $ must be equal.
\end{checks}
\ifacenotes{
\flauddateutsolve expects $ R $, $ b_R $, and $ x $ to be flat matrix objects.
}
\begin{params}
\parameter{\flaobj}{R}{An \flaobj representing matrix $ R $.}
\parameter{\flaobj}{b\_R}{An \flaobj representing matrix $ b_R $.}
\parameter{\flaobj}{x}{An \flaobj representing matrix $ x $.}
\end{params}
\end{flaspec}

% --- FLASH_UDdate_UT_inc() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_UDdate_UT_inc( FLA_Obj R, FLA_Obj C, FLA_Obj D, FLA_Obj T, FLA_Obj W );
\end{verbatim}
\index{FLASH functions!\flashuddateutincns}
\purpose{
Perform an incremental up-and-downdate ({\sc uddateutinc}) of the upper
triangular factor $ R $ (via up-and-downdating UT transforms) that arises
from solving a linear least-squares problem, $ Ax = y $.
The operation is similar to the operation implemented by \flauddateutns,
except that the algorithm is SuperMatrix-aware.
As a consequence, the arguments must be hierarchical objects.
}
\notes{
It is {\em highly} recommended that the user create and initialize flat objects
containing the matrices to be used in the up-and-downdate and then call
\flashuddateutinccreatehiermatrices to create hierarchical matrices
$ R $, $ C $, $ D $, $ T $, and $ W $ from the original flat matrices.
}
\begin{checks}
\checkitem
The numerical datatypes of $ R $, $ C $, $ D $, $ T $, and $ W $ must be
identical and floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
$ R $ must be square.
\itemvsp
\checkitem
The widths of $ R $, $ C $, $ D $, and $ T $ must be equal.
\itemvsp
\checkitem
The number of blocks in the column dimension of $ T $ must be equal to
the number of blocks in the column dimension of $ R $;
the number of blocks in the row dimension of $ T $ must be equal to
the greater of the number of blocks in the row dimension of $ C $ and $ D $.
\itemvsp
\checkitem
The block dimensions of $ W $ must be conformal to that of $ R $.
\end{checks}
\ifacenotes{
In addition to the input matrices $ R $, $ C $, and $ D $, the function
requires an additional matrix $ T $ to hold the upper triangular factors
of the block up-and-downdating UT Householder transformations computed
for each storage block.
These transformations are used when applying $ Q $ (via \flashapplyqudutincns).
The matrix $ W $ contains temporary workspace needed by the
incremental up-and-downdating algorithm.
}
\implnotes{
\flashuddateutinc uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc uddateutinc} operation into
subproblems expressed in terms of individual blocks of $ R $, $ C $, and
$ D $, and then invokes external BLAS routines to perform the computation
on these blocks.
The unblocked {\sc uddateut} subproblems are computed by internal
implementations.
(External LAPACK routines are not used, even when
{\tt external-lapack-for-subproblems} option is enabled.)
}
\caveats{
Currently, this function only supports matrices with hierarchical depths of
exactly 1.
}
\begin{params}
\parameter{\flaobj}{R}{A hierarchical \flaobj representing matrix $ R $.}
\parameter{\flaobj}{C}{A hierarchical \flaobj representing matrix $ C $.}
\parameter{\flaobj}{D}{A hierarchical \flaobj representing matrix $ D $.}
\parameter{\flaobj}{T}{A hierarchical \flaobj representing matrix $ T $.}
\parameter{\flaobj}{W}{A hierarchical \flaobj representing matrix $ W $.}
\end{params}
\end{flaspec}

% --- FLASH_UDdate_UT_inc_update_rhs() -----------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_UDdate_UT_inc_update_rhs( FLA_Obj T, FLA_Obj bR,
                                     FLA_Obj C, FLA_Obj bC,
                                     FLA_Obj D, FLA_Obj bD );
\end{verbatim}
\index{FLASH functions!\flashuddateutincupdaterhsns}
\purpose{
Perform an incremental up-and-downdate of the right-hand maintained when
solving a linear least-squares system $ A x = y $.
The operation is similar to the operation implemented by
\flauddateutupdaterhsns, except that the algorithm is SuperMatrix-aware.
As a consequence, the arguments must be hierarchical objects.
}
\notes{
\flashuddateutincupdaterhs should be invoked using the $ C $, $ D $, and $ T $
matrices that were updated by the \flashuddateutinc during the up-and-downdate
of the upper triangular factor $ R $.
Subsequent to the up-and-downdate of the right-hand side, the user may use
\flashuddateutincsolve to solve the updated system.
}
\begin{checks}
\checkitem
The numerical datatypes of $ T $, $ C $, $ D $, $ b_R $, $ b_C $, and $ b_D $
must be identical and floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The widths of $ T $, $ C $, and $ D $ must be equal.
\itemvsp
\checkitem
The widths of $ b_R $, $ b_C $, and $ b_D $ must be equal.
\itemvsp
\checkitem
The length of $ b_R $ must equal the width of $ T $;
the length of $ b_C $ must equal the length of $ C $;
and the length of $ b_D $ must equal the lenght of $ D $.
\end{checks}
\implnotes{
\flashuddateutincupdaterhs is implemented as a convenience wrapper to
\flashapplyqudutinccreateworkspace and \flashapplyqudutincns.
}
\begin{params}
\parameter{\flaobj}{T}{A hierarchical \flaobj representing matrix $ T $.}
\parameter{\flaobj}{b\_R}{A hierarchical \flaobj representing matrix $ b_R $.}
\parameter{\flaobj}{C}{A hierarchical \flaobj representing matrix $ C $.}
\parameter{\flaobj}{b\_C}{A hierarchical \flaobj representing matrix $ b_C $.}
\parameter{\flaobj}{D}{A hierarchical \flaobj representing matrix $ D $.}
\parameter{\flaobj}{b\_D}{A hierarchical \flaobj representing matrix $ b_D $.}
\end{params}
\end{flaspec}

% --- FLASH_UDdate_UT_inc_solve() ----------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_UDdate_UT_inc_solve( FLA_Obj R, FLA_Obj bR, FLA_Obj x );
\end{verbatim}
\index{FLASH functions!\flashuddateutincsolvens}
\purpose{
Solve one or more linear least-squares systems using the upper triangular
factor $ R $ and the right-hand side $ b_R $.
Presumably the user has already up-and-downdated $ R $, via \flashuddateutincns,
and $ b_R $, via \flashuddateutincupdaterhsns.
The operation is similar to the operation implemented by
\flauddateutsolvens, except that the algorithm is SuperMatrix-aware.
As a consequence, the arguments must be hierarchical objects.
}
\notes{
Note that \flashuddateutincsolve may only be used in conjunction with matrices
that have been factorized via \flashuddateutincns.
The output from \flauddateut is {\em not} compatible with this function.
}
\rvalue{
\flasuccess
}
\begin{checks}
\checkitem
The numerical datatypes of $ R $, $ b_R $, and $ x $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The order of $ R $ and the length of $ b_R $ must be equal;
the width of $ b_R $ and the width of $ x $ must be equal.
\end{checks}
\begin{params}
\parameter{\flaobj}{R}{A hierarchical \flaobj representing matrix $ R $.}
\parameter{\flaobj}{b\_R}{A hierarchical \flaobj representing matrix $ b_R $.}
\parameter{\flaobj}{x}{A hierarchical \flaobj representing matrix $ x $.}
\end{params}
\end{flaspec}

% --- FLA_Hess_UT() ------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Hess_UT( FLA_Obj A, FLA_Obj T );
\end{verbatim}
\index{FLAME/C functions!\flahessutns}
\purpose{
Perform a reduction to upper Hessenberg form via the UT transform ({\sc hessut})
\begin{eqnarray*}
A & \rightarrow & Q R Q^H
\end{eqnarray*}
where $ A $ is a general square matrix, $ Q $ is an orthogonal matrix (or, a
unitary matrix if $ A $ is complex) and $ R $ is an upper Hessenberg matrix
(zeroes below the first subdiagonal).
The resulting Householder vectors associated with $ Q $ are stored column-wise
below the first subdiagonal of $ A $ and should only be used with other UT
transform operations.
Upon completion, matrix $ T $ contains the upper triangular factors of the block
Householder transformations that were used in the reduction algorithm.
}
\notes{
When using \flahessutns, the Householder vectors associated with
matrix $ Q $ are stored, in which case $ Q $ is equal to
$ H_0 H_1 \cdots H_{k-2} $, where $ H_i^H $ is the Householder transformation
which annihilates entries below the first subdiagonal in the $ i $th column
of the original matrix $ A $.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ T $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
$ A $ must be square.
\itemvsp
\checkitem
The width of $ T $ must be $ n $ where $ A $ is $ n \by n $.
\end{checks}
\ifacenotes{
\flahessut expects $ A $ and $ T $ to be flat matrix objects.
}
\implnotes{
\flahessut invokes a single FLAME/C variant to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS routines.
The unblocked {\sc hessut} subproblems are computed by internal
implementations.
(External LAPACK routines are not used, even when
{\tt external-lapack-for-subproblems} option is enabled.)
}
\implnotes{
The algorithmic blocksize $ b $ is determined by the length of $ T $.
When in doubt, create $ T $ via \flahessutcreatetns.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\end{params}
\end{flaspec}

% --- FLA_Tridiag_UT() ---------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Tridiag_UT( FLA_Uplo uplo, FLA_Obj A, FLA_Obj T );
\end{verbatim}
\index{FLAME/C functions!\flatridiagutns}
\purpose{
Perform a reduction to tridiagonal form via the UT transform ({\sc tridiagut})
\begin{eqnarray*}
A & \rightarrow & Q R Q^H
\end{eqnarray*}
where $ A $ is a symmetric (or, if $ A $ is complex, Hermitian) matrix, $ Q $
is an orthogonal (or, if $ A $ is complex, unitary) matrix and $ R $ is a
tridiagonal matrix (zeroes below the first subdiagonal and above the first
superdiagonal).
Note, however, that \flatridiagut only reads and updates the triangle
specified by \uplons.
The resulting Householder vectors associated with $ Q $ are stored column-wise
below the first subdiagonal of $ A $ if \uplo is \flalowertriangular and
row-wise above the first superdiagonal if \uplo is \flauppertriangularns.
Upon completion, matrix $ T $ contains the upper triangular factors of the block
Householder transformations that were used in the reduction algorithm.
}
\notes{
If $ A $ is complex, the tridiagonal matrix that results from the reduction
operation contains complex sub- and super-diagonals (though, only one of which
is stored, as specified by \uplons).
The matrix may further be reduced to real tridiagonal form via
\flatridiagutrealifyns.
}
%\notes{
%If \uplo is \flalowertriangular, the Householder vectors associated with
%matrix $ Q $ are stored, in which case $ Q $ is equal to
%$ H_0 H_1 \cdots H_{k-2} $, where $ H_i^H $ is the Householder transformation
%which annihilates entries below the first subdiagonal in the $ i $th column
%of the original matrix $ A $.
%If \uplo is \flauppertriangular, the Householder vectors associated with
%matrix $ Q^H $ are stored, in which case $ Q^H $ is equal to
%$ H_{k-2}^H \cdots H_1^H H_0^H $, where $ H_i $ is the Householder transformation
%which annihilates entries above the first superdiagonal in the $ i $th row
%of the original matrix $ A $.
%}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ T $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
$ A $ must be square.
\itemvsp
\checkitem
The width of $ T $ must be $ n $ where $ A $ is $ n \by n $.
\end{checks}
\ifacenotes{
\flatridiagut expects $ A $ and $ T $ to be flat matrix objects.
}
\implnotes{
\flatridiagut invokes a single FLAME/C variant to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS routines.
The unblocked {\sc tridiagut} subproblems are computed by internal
implementations.
(External LAPACK routines are not used, even when
{\tt external-lapack-for-subproblems} option is enabled.)
}
\implnotes{
The algorithmic blocksize $ b $ is determined by the length of $ T $.
When in doubt, create $ T $ via \flatridiagutcreatetns.
}
%% \caveats{
%% \flatridiagut is currently only implemented for the cases where \uplo is
%% \flalowertriangularns.
%% }
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced and overwritten during the operation.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\end{params}
\end{flaspec}

% --- FLA_Bidiag_UT() ----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Bidiag_UT( FLA_Obj A, FLA_Obj TU, FLA_Obj TV );
\end{verbatim}
\index{FLAME/C functions!\flabidiagutns}
\purpose{
Perform a reduction to bidiagonal form via the UT transform ({\sc bidiagut})
\begin{eqnarray*}
A & \rightarrow & Q_U R Q_V^H
\end{eqnarray*}
where $ A $ is a general $ m \by n $ matrix, $ Q_U $ and $ Q_V $
are orthogonal (or, if $ A $ is complex, unitary) matrices, and $ R $ is a
bidiagonal matrix.
If $ m \ge n $, $ R $ is upper bidiagonal (zeroes below the diagonal and above
the first superdiagonal).
Otherwise, if $ m < n $, $ R $ is lower bidiagonal (zeroes above the diagonal
and below the first subdiagonal).
When $ R $ is upper bidiagonal, the resulting Householder vectors associated
with $ Q_U $ and $ Q_V $ are stored column-wise below the diagonal and row-wise
above the first superdiagonal, respectively.
When $ R $ is lower bidiagonal, the resulting Householder vectors associated
with $ Q_U $ and $ Q_V $ are stored column-wise below the first subdiagonal and
row-wise above the diagonal, respectively.
Upon completion, matrices $ T_U $ and $ T_V $ contain the upper triangular
factors of the block Householder transformations corresponding to $ Q_U $ and
$ Q_V $, respectively, that were used in the reduction algorithm.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ T_U $, and $ T_V $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The widths of $ T_U $ and $ T_V $ must be $ \min( m,n ) $.
\end{checks}
\ifacenotes{
\flabidiagut expects $ A $, $ T_U $, and $ T_V $ to be flat matrix objects.
}
\implnotes{
\flabidiagut invokes a single FLAME/C variant to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS routines.
The unblocked {\sc bidiagut} subproblems are computed by internal
implementations.
(External LAPACK routines are not used, even when
{\tt external-lapack-for-subproblems} option is enabled.)
}
\implnotes{
The algorithmic blocksize $ b $ is determined by the length of $ T_U $ and
$ T_V $.
When in doubt, create $ T_U $ and $ T_V $ via \flabidiagutcreatetns.
}
%% 
%% \caveats{
%% \flabidiagut is currently only implemented for the case where $ m \ge n $.
%% }
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{TU}{An \flaobj representing matrix $ T_U $.}
\parameter{\flaobj}{TV}{An \flaobj representing matrix $ T_V $.}
\end{params}
\end{flaspec}

% --- FLA_Apply_Q_UT() ---------------------------------------------------------
% --- FLASH_Apply_Q_UT() -------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Apply_Q_UT( FLA_Side side, FLA_Trans trans, FLA_Direct direct, FLA_Store storev,
                     FLA_Obj A, FLA_Obj T, FLA_Obj W, FLA_Obj B );
void FLASH_Apply_Q_UT( FLA_Side side, FLA_Trans trans, FLA_Direct direct, FLA_Store storev,
                       FLA_Obj A, FLA_Obj T, FLA_Obj W, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaapplyqutns}
\index{FLASH functions!\flashapplyqutns}
\purpose{
Apply a matrix $ Q $ (or $ Q^H $) to a general 
matrix $ B $ from either the left or the right ({\sc apqut}):
\begin{center}
\begin{math}
\begin{array}{cclcccl}
B & := & Q B       & \hsp & B & := & B Q   \\[0.05in]
B & := & Q^H B     & \hsp & B & := & B Q^H
\end{array}
\end{math}
\end{center}
where $ Q $ is the orthogonal (or, if $ A $ is complex, unitary) matrix
implicitly defined by the Householder vectors stored in matrix $ A $ and the
triangular factors stored in matrix $ T $ by \flaqrut (or \flashqrutns) or
\flalqutns (or \flashlqutns).
Matrix $ W $ is used as workspace.
The \side argument indicates whether $ Q $ is applied to $ B $ from the left
or the right.
The \trans argument indicates whether $ Q $ or $ Q^H $ is applied
to $ B $.
The \direct argument indicates whether $ Q $ is assumed to be the forward
product $ H_0 H_1 \cdots H_{k-1} $ or the backward product
$ H_{k-1} \cdots H_1 H_0 $ of Householder transforms, where $ k $ is the
width of $ T $.
The \storev argument indicates whether the Householder vectors which correspond
to $ H_0 H_1 \cdots H_{k-1} $ are stored column-wise (in the strictly lower
triangle, as computed by a QR factorization) or row-wise (in the strictly upper
triangle, as computed by an LQ factorization) in $ A $.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ T $, $ W $, and $ B $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If \side equals \flaleftns, then the number of rows in $ B $ and the order of
$ A $ must be equal; otherwise, if \side equals \flarightns, then the number
of columns in $ B $ and the order of $ A $ must be equal.
\itemvsp
\checkitem
If $ A $ is real, then \trans must be \flanotranspose or \flatransposens; 
otherwise if $ A $ is complex, then \trans must be \flanotranspose or
\flaconjtransposens.
\itemvsp
\checkitem
The dimensions of $ W $ must be $ m_T \by n_B $ where $ m_T $ is the number of
rows in $ T $ and $ n_B $ is the number of columns in $ B $.
\end{checks}
\ifacenotes{
\flaapplyqut expects $ A $, $ T $, $ W $, and $ B $ to be flat matrix objects.
}
\implnotes{
\flaapplyqut invokes one or more FLAME/C variants to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS routines.
\flashapplyqut invokes one or more FLAME/C variants to induce an
algorithm-by-blocks with subproblems performed by calling wrappers
to external BLAS routines.
}
\begin{params}
\parameter{\flaside}{side}{Indicates whether $ Q $ (or $ Q^H $) is multipled on the left or right side of $ B $.}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if $ Q $ were transposed (or conjugate-transposed).}
\parameter{\fladirect}{direct}{Indicates whether $ Q $ is formed from the forward or backward product of its constituent Householder reflectors.}
\parameter{\flastorev}{storev}{Indicates whether the vectors stored within $ A $ are stored column-wise or row-wise.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\parameter{\flaobj}{W}{An \flaobj representing matrix $ W $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}

% --- FLASH_Apply_Q_UT_inc() ---------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Apply_Q_UT_inc( FLA_Side side, FLA_Trans trans, FLA_Direct direct,
                           FLA_Store storev,
                           FLA_Obj A, FLA_Obj TW, FLA_Obj W, FLA_Obj B );
\end{verbatim}
\index{FLASH functions!\flashapplyqutincns}
\purpose{
Apply a matrix $ Q $ (or $ Q^H $) to a general 
matrix $ B $ from either the left or the right ({\sc apqutinc}):
\begin{center}
\begin{math}
\begin{array}{cclcccl}
B & := & Q B       & \hsp & B & := & B Q   \\[0.05in]
B & := & Q^H B     & \hsp & B & := & B Q^H
\end{array}
\end{math}
\end{center}
where $ Q $ is the orthogonal (or, if $ A $ is complex, unitary) matrix
implicitly defined by the Householder vectors stored in matrix $ A $ and the
triangular factors stored in matrix $ TW $ by \flashqrutincns.
Matrix $ W $ is used as workspace.
The \side argument indicates whether $ Q $ is applied to $ B $ from the left
or the right.
The \trans argument indicates whether $ Q $ or $ Q^H $ is applied
to $ B $.
The \direct argument indicates whether $ Q $ was computed as the forward product
$ H_0 H_1 \cdots H_{k-1} $ or the backward product $ H_{k-1} \cdots H_1 H_0 $.
The \storev argument indicates whether the Householder vectors which define
$ Q $ are stored column-wise (in the strictly lower triangle) or 
row-wise (in the strictly upper triangle) of $ A $.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ TW $, $ W $, and $ B $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If \side equals \flaleftns, then the number of rows in $ B $ and the order of
$ A $ must be equal; otherwise, if \side equals \flarightns, then the number
of columns in $ B $ and the order of $ A $ must be equal.
\itemvsp
\checkitem
If $ A $ is real, then \trans must be \flanotranspose or \flatransposens; 
otherwise if $ A $ is complex, then \trans must be \flanotranspose or
\flaconjtransposens.
\itemvsp
\checkitem
The dimensions of $ W $ must be $ m_{TW} \by n_B $ where $ m_{TW} $ is the
scalar length of a single block of $ TW $ and $ n_B $ is the scalar width of
$ B $.
\end{checks}
\implnotes{
\flashapplyqutinc uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc apqutinc} operation into subproblems
expressed in terms of individual blocks of $ A $, $ TW $, $ W $, and $ B $ and
then invokes external BLAS routines to perform the computation
on these blocks.
}
\caveats{
\flashapplyqutinc currently only works for hierarchical matrices of depth 1 where
$ A $ refers to a single storage block.
\flashapplyqutinc is currently only implemented for the cases where \side is
\flaleftns, \direct is \flaforwardns, and \storev is \flacolumnwisens.
}
\begin{params}
\parameter{\flaside}{side}{Indicates whether $ Q $ (or $ Q^H $) is multipled on the left or right side of $ B $.}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if $ Q $ were transposed (or conjugate-transposed).}
\parameter{\fladirect}{direct}{Indicates whether $ Q $ is formed from the forward or backward product of its constituent Householder reflectors.}
\parameter{\flastorev}{storev}{Indicates whether the vectors stored within $ A $ are stored column-wise or row-wise.}
\parameter{\flaobj}{A}{A hierarchical \flaobj representing matrix $ A $.}
\parameter{\flaobj}{TW}{A hierarchical \flaobj representing matrix $ TW $.}
\parameter{\flaobj}{W}{A hierarchical \flaobj representing matrix $ W $.}
\parameter{\flaobj}{B}{A hierarchical \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Apply_QUD_UT() -------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Apply_QUD_UT( FLA_Side side, FLA_Trans trans, FLA_Direct direct, FLA_Store storev,
                       FLA_Obj T, FLA_Obj W,
                                  FLA_Obj R,
                       FLA_Obj U, FLA_Obj C,
                       FLA_Obj V, FLA_Obj D );
\end{verbatim}
\index{FLAME/C functions!\flaapplyqudutns}
\purpose{
Apply a matrix $ Q^H $ to general matrices $ R $, $ C $, and $ D $ from the
left ({\sc apqudut}):
\begin{center}
\begin{math}
\begin{array}{ccc}
\left( 
\begin{array}{c}
R \\ \hline \hline 
C \\ \hline \hline
D
\end{array}
\right)
& \becomes &
Q^H
\left( 
\begin{array}{c}
R \\ \hline \hline 
C \\ \hline \hline
D
\end{array}
\right)
\end{array}
\end{math}
\end{center}
where $ Q $ is the orthogonal (or, if the matrices are complex, unitary)
matrix implicitly defined by the up-and-downdating UT Householder vectors
stored columnwise in $ U $ and $ V $ and the upper triangular factors
stored in matrix $ T $ by \flauddateutns.
Matrix $ W $ is used as workspace.
}
\begin{checks}
\checkitem
The numerical datatypes of $ T $, $ W $, $ R $, $ U $, $ C $, $ V $, and $ D $
must be identical and floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The number of columns in $ T $ must be equal to the number of columns in $ U $
and $ V $.
\itemvsp
\checkitem
The number of columns in $ W $ must be equal to the number of columns in $ R $.
\itemvsp
\checkitem
The number of rows in $ C $ and the number of rows in $ U $ must be equal; the
number of columns in $ C $ and the number of columns of $ R $ must be equal;
and the number of columns in $ U $ and the number of rows in $ R $ must be
equal.
\itemvsp
\checkitem
The number of rows in $ D $ and the number of rows in $ V $ must be equal; the
number of columns in $ D $ and the number of columns of $ R $ must be equal;
and the number of columns in $ V $ and the number of rows in $ R $ must be
equal.
\end{checks}
\ifacenotes{
\flaapplyqudut expects $ T $, $ W $, $ R $, $ U $, $ C $, $ V $, and $ D $ to
be flat matrix objects.
}
\implnotes{
\flaapplyqudut invokes one or more FLAME/C variants to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS routines.
}
\caveats{
\flaapplyqudut is currently only implemented for the case where \side is
\flaleftns, \trans is \flaconjtranspose (or \flatranspose for real matrices),
\direct is \flaforwardns, and \storev is \flacolumnwisens.
}
\begin{params}
\parameter{\flaside}{side}{Indicates whether $ Q $ (or $ Q^H $) is multipled on the left or right side of $ B $.}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if $ Q $ were transposed (or conjugate-transposed).}
\parameter{\fladirect}{direct}{Indicates whether $ Q $ is formed from the forward or backward product of its constituent Householder reflectors.}
\parameter{\flastorev}{storev}{Indicates whether the vectors stored within $ U $ and $ V $ are stored column-wise or row-wise.}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\parameter{\flaobj}{W}{An \flaobj representing matrix $ W $.}
\parameter{\flaobj}{R}{An \flaobj representing matrix $ R $.}
\parameter{\flaobj}{U}{An \flaobj representing matrix $ U $.}
\parameter{\flaobj}{C}{An \flaobj representing matrix $ C $.}
\parameter{\flaobj}{V}{An \flaobj representing matrix $ V $.}
\parameter{\flaobj}{D}{An \flaobj representing matrix $ D $.}
\end{params}
\end{flaspec}

% --- FLASH_Apply_QUD_UT_inc() -------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Apply_QUD_UT_inc( FLA_Side side, FLA_Trans trans,
                             FLA_Direct direct, FLA_Store storev,
                             FLA_Obj T, FLA_Obj W,
                                        FLA_Obj R,
                             FLA_Obj U, FLA_Obj C,
                             FLA_Obj V, FLA_Obj D );
\end{verbatim}
\index{FLASH functions!\flashapplyqudutincns}
\purpose{
Apply a matrix $ Q^H $ to general matrices $ R $, $ C $, and $ D $ from the
left ({\sc apqudutinc}):
\begin{center}
\begin{math}
\begin{array}{ccc}
\left( 
\begin{array}{c}
R \\ \hline \hline 
C \\ \hline \hline
D
\end{array}
\right)
& \becomes &
Q^H
\left( 
\begin{array}{c}
R \\ \hline \hline 
C \\ \hline \hline
D
\end{array}
\right)
\end{array}
\end{math}
\end{center}
where $ Q $ is the orthogonal (or, if the matrices are complex, unitary)
matrix implicitly defined by the up-and-downdating UT Householder vectors
stored columnwise in $ U $ and $ V $ and the upper triangular factors
stored in matrix $ T $ by \flashuddateutincns.
Matrix $ W $ is used as workspace.
The operation is similar to the operation implemented by
\flaapplyqudutns, except that the algorithm is SuperMatrix-aware.
As a consequence, the arguments must be hierarchical objects.
}
\begin{checks}
\checkitem
The numerical datatypes of $ T $, $ W $, $ R $, $ U $, $ C $, $ V $, and $ D $
must be identical and floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The number of columns in $ T $ must be equal to the number of columns in $ U $
and $ V $.
\itemvsp
\checkitem
The number of columns in $ W $ must be equal to the number of columns in $ R $.
\itemvsp
\checkitem
The number of rows in $ C $ and the number of rows in $ U $ must be equal; the
number of columns in $ C $ and the number of columns of $ R $ must be equal;
and the number of columns in $ U $ and the number of rows in $ R $ must be
equal.
\itemvsp
\checkitem
The number of rows in $ D $ and the number of rows in $ V $ must be equal; the
number of columns in $ D $ and the number of columns of $ R $ must be equal;
and the number of columns in $ V $ and the number of rows in $ R $ must be
equal.
\end{checks}
\implnotes{
\flashapplyqudutinc uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc apqudutinc} operation into subproblems
expressed in terms of individual blocks of $ A $ and then invokes external
BLAS routines to perform the computation on these blocks.
(External LAPACK routines are not used, even when
{\tt external-lapack-for-subproblems} option is enabled.)
}
\caveats{
\flashapplyqudutinc is currently only implemented for the case where \side is
\flaleftns, \trans is \flaconjtranspose (or \flatranspose for real matrices),
\direct is \flaforwardns, and \storev is \flacolumnwisens.
}
\begin{params}
\parameter{\flaside}{side}{Indicates whether $ Q $ (or $ Q^H $) is multipled on the left or right side of $ B $.}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if $ Q $ were transposed (or conjugate-transposed).}
\parameter{\fladirect}{direct}{Indicates whether $ Q $ is formed from the forward or backward product of its constituent Householder reflectors.}
\parameter{\flastorev}{storev}{Indicates whether the vectors stored within $ U $ and $ V $ are stored column-wise or row-wise.}
\parameter{\flaobj}{T}{A hierarchical \flaobj representing matrix $ T $.}
\parameter{\flaobj}{W}{A hierarchical \flaobj representing matrix $ W $.}
\parameter{\flaobj}{R}{A hierarchical \flaobj representing matrix $ R $.}
\parameter{\flaobj}{U}{A hierarchical \flaobj representing matrix $ U $.}
\parameter{\flaobj}{C}{A hierarchical \flaobj representing matrix $ C $.}
\parameter{\flaobj}{V}{A hierarchical \flaobj representing matrix $ V $.}
\parameter{\flaobj}{D}{A hierarchical \flaobj representing matrix $ D $.}
\end{params}
\end{flaspec}

% --- FLA_Ttmm() ---------------------------------------------------------------
% --- FLASH_Ttmm() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Ttmm( FLA_Uplo uplo, FLA_Obj A );
void FLASH_Ttmm( FLA_Uplo uplo, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flattmmns}
\index{FLASH functions!\flashttmmns}
\purpose{
Perform one of the following triangular-transpose matrix multiplies
({\sc ttmm}):
\begin{eqnarray*}
A & := & L^T L \\
A & := & U U^T \\
A & := & L^H L \\
A & := & U U^H
\end{eqnarray*}
where $ A $ is a triangular matrix with a real diagonal.
The operation references and then overwrites the lower or upper triangle of
$ A $ with one of the products specified above, depending on the value of \uplons.
}
\notes{
\flattmm may not be used for a general-purpose triangular matrix since
the function assumes that the diagonal of $ L $ (or $ U $) is real.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
\diag may not be \flazerodiagns.
\itemvsp
\checkitem
$ A $ must be square.
\end{checks}
\ifacenotes{
\flattmm expects $ A $ to be a flat matrix object.
}
\implnotes{
\flattmm invokes one or more FLAME/C variants to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS routines.
\flashttmm uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc ttmm} operation into subproblems
expressed in terms of individual blocks of $ A $ and then invokes external
BLAS routines to perform the computation on these blocks.
By default, the unblocked {\sc ttmm} subproblems are computed by internal
implementations.
However, if the {\tt external-lapack-for-subproblems} option is enabled at
configure-time, these subproblems are computed by external unblocked LAPACK
routines.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced and overwritten during the operation.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Trinv() --------------------------------------------------------------
% --- FLASH_Trinv() ------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Trinv( FLA_Uplo uplo, FLA_Diag diag, FLA_Obj A );
FLA_Error FLASH_Trinv( FLA_Uplo uplo, FLA_Diag diag, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flatrinvns}
\index{FLASH functions!\flashtrinvns}
\purpose{
Perform a triangular matrix inversion ({\sc trinv}):
\begin{eqnarray*}
A & := & A^{-1}
\end{eqnarray*}
where $ A $ is a general triangular matrix.
The operation references and then overwrites the lower or upper triangle of
$ A $ with its inverse, $ A^{-1} $, depending on the value of \uplons.
The \diag argument indicates whether the diagonal of $ A $ is unit or
non-unit.
}
\rvalue{
\flasuccess if the operation is successful; otherwise, if $ A $ is singular,
a signed integer corresponding to the row/column index at which the algorithm
detected a zero entry along the diagonal.
The row/column index is zero-based, and thus its possible range extends
inclusively from $ 0 $ to $ n - 1 $.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
\diag may not be \flazerodiagns.
\itemvsp
\checkitem
$ A $ must be square.
\end{checks}
\ifacenotes{
\flatrinv expects $ A $ to be a flat matrix object.
}
\implnotes{
\flatrinv invokes one or more FLAME/C variants to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS routines.
\flashtrinv uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc trinv} operation into subproblems
expressed in terms of individual blocks of $ A $ and then invokes external
BLAS routines to perform the computation on these blocks.
By default, the unblocked {\sc trinv} subproblems are computed by internal
implementations.
However, if the {\tt external-lapack-for-subproblems} option is enabled at
configure-time, these subproblems are computed by external unblocked LAPACK
routines.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced and overwritten during the operation.}
\parameter{\fladiag}{diag}{Indicates whether the diagonal of $ A $ is unit or non-unit.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_SPDinv() -------------------------------------------------------------
% --- FLASH_SPDinv() -----------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_SPDinv( FLA_Uplo uplo, FLA_Obj A );
void FLASH_SPDinv( FLA_Uplo uplo, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flaspdinvns}
\index{FLASH functions!\flashspdinvns}
\purpose{
Perform a positive definite matrix inversion ({\sc spdinv}):
\begin{eqnarray*}
A := A^{-1}
\end{eqnarray*}
where $ A $ is positive definite.
If $ A $ is real, then it is assumed to be symmetric; otherwise, if $ A $ is
complex, then it is assumed to be Hermitian. 
The operation references and then overwrites the lower or upper triangle of
$ A $ with the corresponding triangle of its inverse, $ A^{-1} $.
The triangle referenced and overwritten is determined by the value of \uplons.
}
\notes{
Given a real symmetric positive definite matrix $ A $, there exists a factor
$ L $ such that $ A = L L^T $.
Therefore,
\begin{eqnarray*}
A^{-1} & = & ( L L^T )^{-1} \\
       & = & L^{-T} L^{-1}
\end{eqnarray*}
Similarly, for a complex Hermitian positive definite matrix $ A $, there exists
a factor such that $ A = L L^H $:
\begin{eqnarray*}
A^{-1} & = & ( L L^H )^{-1} \\
       & = & L^{-H} L^{-1}
\end{eqnarray*}
From this, we observe that the inverse of symmetric positive
definite matrices may be computed by multiplying the inverse of the
the Cholesky factor $ L $ by its transpose, or in the case of Hermitian
positive definite matrices, its conjugate-transpose.
Similar observations may be made provided $ L = U^T $ and $ L = U^H $
for real and complex matrices, respectively.
}
\rvalue{
%\flasuccess if the operation is successful; otherwise, a signed integer
%corresponding to the row/column index that caused the operation to fail.
If $ A $ is not positive definite, then \flashspdinv
will return the row/column index at which the algorithm detected a negative
or non-real entry along the diagonal.
If the Cholesky factorization of $ A $ succeeds but the Cholesky factor is
found to be singular, then \flashspdinv will return the row/column
index at which the algorithm detected a zero entry along the diagonal.
In either case, the row/column index is zero-based, and thus its possible
range extends inclusively from $ 0 $ to $ n - 1 $.
Otherwise, \flashspdinv returns \flasuccess if the operation is successful.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
$ A $ must be square.
\end{checks}
\ifacenotes{
\flaspdinv expects $ A $ to be a flat matrix object.
}
\implnotes{
\flaspdinv is implemented in terms of \flacholns, \flatrinvns, and
\flattmmns.
\flashspdinv is implemented in terms of \flashcholns, \flashtrinvns, and
\flashttmmns.
}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced and overwritten during the operation.}
\parameter{\fladiag}{diag}{Indicates whether the diagonal of $ A $ is unit or non-unit.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Eig_gest() -----------------------------------------------------------
% --- FLASH_Eig_gest() ---------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Eig_gest( FLA_Inv inv, FLA_Uplo uplo, FLA_Obj A, FLA_Obj B );
void FLASH_Eig_gest( FLA_Inv inv, FLA_Uplo uplo, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaeiggestns}
\index{FLASH functions!\flasheiggestns}
\purpose{
Perform one of the following operations to reduce a symmetric- or
Hermitian-definite eigenproblem to standard form ({\sc eiggest}):
\begin{eqnarray*}
A & := & L^H A L \\
A & := & U A U^H \\
A & := & L A L^{-H} \\
A & := & U^{-H} A U
\end{eqnarray*}
where $ A $, on input and output, is symmetric (or Hermitian) and
$ B $ contains either a lower ($ L $) or upper ($ U $) triangular Cholesky
factor.
The value of \inv determines whether the operation, as expressed above,
requires an inversion of $ L $ or $ U $.
The value of \uplo determines which triangle of $ A $ is read on input,
which triangle of the symmetric (or Hermitian)
right-hand side is stored, and also which Cholesky factor
exists in $ B $.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ B $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
$ A $ and $ B $ must be square.
\end{checks}
\ifacenotes{
\flaeiggest expects $ A $ and $ B $ to be flat matrix objects.
}
\implnotes{
\flaeiggest invokes one or more FLAME/C variants to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS routines.
\flasheiggest uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc eiggest} operation into subproblems
expressed in terms of individual blocks of $ A $ and then invokes external
BLAS routines to perform the computation on these blocks.
By default, the unblocked {\sc eiggest} subproblems are computed by internal
implementations.
However, if the {\tt external-lapack-for-subproblems} option is enabled at
configure-time, these subproblems are computed by external unblocked LAPACK
routines.
}
\begin{params}
\parameter{\flainv}{inv}{Indicates whether the operation requires a multiplication by the inverse of $ L $ or $ U $.}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced and overwritten (and whether the lower or upper triangle of $ B $ is referenced) during the operation.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Sylv() ---------------------------------------------------------------
% --- FLASH_Sylv() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Sylv( FLA_Trans transa, FLA_Trans transb, FLA_Obj isgn,
               FLA_Obj A, FLA_Obj B, FLA_Obj C, FLA_Obj scale );
void FLASH_Sylv( FLA_Trans transa, FLA_Trans transb, FLA_Obj isgn,
                 FLA_Obj A, FLA_Obj B, FLA_Obj C, FLA_Obj scale );
\end{verbatim}
\index{FLAME/C functions!\flasylvns}
\index{FLASH functions!\flashsylvns}
\purpose{
Solve one of the following triangular Sylvester equations ({\sc sylv}):
\begin{center}
\begin{math}
\begin{array}{lclcc}
A   X & \pm & X B   & = & C \\
A   X & \pm & X B^T & = & C \\
A^T X & \pm & X B   & = & C \\
A^T X & \pm & X B^T & = & C \\
\end{array}
\end{math}
\end{center}
where $ A $ and $ B $ are real upper triangular matrices and $ C $ is a
real general matrix.
If $ A $, $ B $, and $ C $ are complex matrices, then the possible operations
are:
\begin{center}
\begin{math}
\begin{array}{lclcc}
A   X & \pm & X B   & = & C \\
A   X & \pm & X B^H & = & C \\
A^H X & \pm & X B   & = & C \\
A^H X & \pm & X B^H & = & C \\
\end{array}
\end{math}
\end{center}
where $ A $ and $ B $ are complex upper triangular matrices and $ C $ is a
complex general matrix.
The operation references and then overwrites matrix $ C $ with the solution
matrix $ X $.
The \isgn argument is a scalar integer object that indicates whether the
$ \pm $ sign between terms is a plus or a minus.
The \scale argument is not referenced and set to $ 1.0 $ upon completion.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ B $, and $ C $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The \isgn argument must be either \flaone or \flaminusonens.
\itemvsp
\checkitem
The numerical datatype of \scale must not \flaconstantns.
Furthermore, the precision of the datatype of \scale must be equal to that
of $ A $, $ B $, and $ C $.
\itemvsp
\checkitem
$ A $ and $ B $ must be square.
\itemvsp
\checkitem
The order of $ A $ and the order of $ B $ must be equal to the the number of
rows in $ C $ and the number of columns in $ C $, respectively.
\itemvsp
\checkitem
\trans may not be \flaconjnotranspose.
\end{checks}
\ifacenotes{
\flasylv expects $ A $, $ B $, and $ C $ to be flat matrix objects.
}
\implnotes{
\flasylv invokes one or more FLAME/C variants to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS routines.
\flashsylv uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc sylv} operation into subproblems
expressed in terms of individual blocks of $ A $, $ B $, and $ C $ and then
invokes external BLAS routines to perform the computation on these blocks.
By default, the unblocked {\sc sylv} subproblems are computed by internal
implementations.
However, if the {\tt external-lapack-for-subproblems} option is enabled at
configure-time, these subproblems are computed by external unblocked LAPACK
routines.
}
\begin{params}
\parameter{\flatrans}{transa}{Indicates whether the operation proceeds as if $ A $ were [conjugate] transposed.}
\parameter{\flatrans}{transb}{Indicates whether the operation proceeds as if $ B $ were [conjugate] transposed.}
\parameter{\flaobj}{isgn}{Indicates whether the terms of the Sylvester equation are added or subtracted.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\parameter{\flaobj}{C}{An \flaobj representing matrix $ C $.}
\parameter{\flaobj}{scale}{Not referenced; set to $ 1.0 $ upon exit.}
\end{params}
\end{flaspec}

% --- FLA_Lyap() ---------------------------------------------------------------
% --- FLASH_Lyap() -------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Lyap( FLA_Trans trans, FLA_Obj isgn, FLA_Obj A, FLA_Obj C, FLA_Obj scale );
void FLASH_Lyap( FLA_Trans trans, FLA_Obj isgn, FLA_Obj A, FLA_Obj C, FLA_Obj scale );
\end{verbatim}
\index{FLAME/C functions!\flalyapns}
\index{FLASH functions!\flashlyapns}
\purpose{
Solve one of the following triangular Lyapunov equations ({\sc lyap}):
\begin{center}
\begin{math}
\begin{array}{lclcc}
A   X & + & X A^T & = & \pm C \\
A^T X & + & X A   & = & \pm C \\
\end{array}
\end{math}
\end{center}
where $ A $ is upper triangular matrix and $ C $ is symmetric.
If $ A $ and $ C $ are complex matrices, then the possible operations
are:
\begin{center}
\begin{math}
\begin{array}{lclcc}
A   X & + & X A^H & = & \pm C \\
A^H X & + & X A   & = & \pm C \\
\end{array}
\end{math}
\end{center}
where $ A $ is upper triangular matrix and $ C $ is Hermitian.
The operation references and then overwrites the upper triangle of matrix
$ C $ with the upper triangle of the solution matrix $ X $, which is
also symmetric (or Hermitian).
The \trans argument determines whether the equation is solved with $ AX $
(\flanotransposens) or $ A^H X $ (\flatranspose or \flaconjtransposens).
The \isgn argument is a scalar integer object that indicates whether the
$ \pm $ sign is a plus or a minus.
The \scale argument is used as workspace.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ C $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The \isgn argument must be either \flaone or \flaminusonens.
\itemvsp
\checkitem
The numerical datatype of \scale must not \flaconstantns.
Furthermore, the precision of the datatype of \scale must be equal to that
of $ A $ and $ C $.
\itemvsp
\checkitem
The dimensions of $ A $ and $ C $ must be conformal.
\itemvsp
\checkitem
$ A $ and $ C $ must be square.
\itemvsp
\checkitem
\trans may not be \flaconjnotranspose.
\end{checks}
\ifacenotes{
\flalyap expects $ A $ and $ C $ to be flat matrix objects.
}
\implnotes{
\flalyap invokes one or more FLAME/C variants to induce a blocked algorithm
with subproblems performed by calling wrappers to external BLAS routines.
\flashlyap uses multiple FLAME/C algorithmic variants to form an
algorithm-by-blocks, which breaks the {\sc lyap} operation into subproblems
expressed in terms of individual blocks of $ A $ and $ C $ and then
invokes external BLAS routines to perform the computation on these blocks.
The unblocked {\sc lyap} subproblems are computed by internal
implementations.
(External LAPACK routines are not used, even when
{\tt external-lapack-for-subproblems} option is enabled.)
}
\caveats{
\flalyap and \flashlyap are currently only implemented for the case where
\trans is \flatranspose (or \flaconjtranspose).
}
\begin{params}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if the instance of $ A $ in the term $ AX $ were [conjugate] transposed.}
\parameter{\flaobj}{isgn}{Indicates whether the Lyapunov equation is solved with $ C $ or $ -C $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{C}{An \flaobj representing matrix $ C $.}
\parameter{\flaobj}{scale}{A scalar used as workspace.}
\end{params}
\end{flaspec}

% --- FLA_Hevd()----------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Hevd( FLA_Evd_type jobz, FLA_Uplo uplo, FLA_Obj A, FLA_Obj l );
\end{verbatim}
\index{FLAME/C functions!\flahevdns}
\purpose{
Perform a Hermitian eigenvalue decomposition ({\sc hevd}):
\begin{eqnarray*}
A & \rightarrow & U \Lambda U^H
\end{eqnarray*}
where $ \Lambda $ is a diagonal matrix whose elements contain the eigenvalues
of $ A $, and the columns of $ U $ contain the eigenvectors of $ A $.
The \jobz argument determines whether only eigenvalues (\flaevdwithoutvectorsns)
or both eigenvalues and eigenvectors (\flaevdwithvectorsns) are computed.
The \uplo argument determines whether $ A $ is stored in the lower or upper
triangle.
Upon completion, the eigenvalues are stored to the vector $ l $ in ascending
order, and the eigenvectors $ U $, if requested, overwrite matrix $ A $ such
that vector element $ l_j $ contains the eigenvalue corresponding to the
eigenvector stored in the $j$th column of $ U $.
If eigenvectors are not requested, then the triangle specified by \uplo is
destroyed.
}
\rvalue{
\flahevd returns the total number of Francis steps performed by the
underlying QR algorithm.
}
\caveats{
\flahevd is currently only implemented for the case where \jobz is
\flaevdwithvectorsns.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point and must not be
\flaconstantns.
\itemvsp
\checkitem
The numerical datatype of $ l $ must be real and must not be
\flaconstantns.
\itemvsp
\checkitem
The precision of the datatype of $ l $ must be equal to that of $ A $.
\itemvsp
\checkitem
$ l $ must be a contiguously-stored vector of length $ n $,
where $ A $ is $ n \times n $.
\end{checks}
\begin{params}
\parameter{\flaevdtype}{jobz}{Indicates whether only eigenvalues or both eigenvalues and eigenvectors are computed.}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is read during the operation.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{l}{An \flaobj representing vector $ l $.}
\end{params}
\end{flaspec}

% --- FLA_Svd() ----------------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Svd( FLA_Svd_type jobu, FLA_Svd_type jobv, FLA_Obj A, FLA_Obj s,
                   FLA_Obj U, FLA_Obj V );
\end{verbatim}
\index{FLAME/C functions!\flasvdns}
\purpose{
Perform a singular value decomposition ({\sc svd}):
\begin{eqnarray*}
A & \rightarrow & U \Sigma V^H
\end{eqnarray*}
where $ \Sigma $ is an $ m \times n $ diagonal matrix whose elements contain
the singular values of $ A $, $ U $ is an $ m \times m $ matrix whose columns
contain the left singular vectors of $ A $, and $ V $ is an $ n \times n $
matrix whose rows of $ V $ contain the right singular vectors of $ A $.
The \jobu and \jobv arguments determine if (and how many of) the left and
right singular vectors, respectively, are computed and where they are
stored.
The \jobu and \jobv arguments accept the following values:
\begin{itemize}
\item
\flasvdvectorsallns.
For \jobuns: compute all $ m $ columns of $ U $, storing the result in $ U $.
For \jobvns: compute all $ n $ columns of $ V $, storing the result in $ V $.
\item
\flasvdvectorsmincopyns.
For \jobuns: compute the first $ \min(m,n) $ columns of $ U $ and store them
in $ U $.
For \jobvns: compute the first $ \min(m,n) $ columns of $ V $ and store them
in $ V $.
\item
\flasvdvectorsminoverwritens.
For \jobuns: compute the first $ \min(m,n) $ columns of $ U $ and store them
in $ A $.
For \jobvns: compute the first $ \min(m,n) $ columns of $ V $ and store them
in $ A $.
Note that \jobu and \jobv cannot both be \flasvdvectorsminoverwritens.
\item
\flasvdvectorsnonens.
For \jobuns: no columns of $ U $ are computed.
For \jobvns: no columns of $ V $ are computed.
\end{itemize}
Upon completion, the $ \min(m,n) $ singular values of $ A $ are stored to
$ s $, sorted in descending order and singular vectors, if computed, are
stored to either $ A $ or $ U $ and $ V $, depending on the values of
\jobu and \jobvns.
If neither \jobu nor \jobv is \flasvdvectorsminoverwritens, then $ A $
is destroyed.
}
\rvalue{
\flasvd returns the total number of Francis steps performed by the
underlying QR algorithm.
}
\caveats{
\flasvd is currently only implemented for the case where \jobu and \jobv
are both \flasvdvectorsallns.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ U $, and $ V $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The numerical datatype of $ s $ must be real and must not be
\flaconstantns.
\itemvsp
\checkitem
The precision of the datatype of $ s $ must be equal to that of $ A $.
\itemvsp
\checkitem
$ e $ must be a contiguously-stored vector of length $ \min(m,n) $,
where $ A $ is $ m \times n $.
\itemvsp
\checkitem
$ U $ and $ V $ must be square.
\itemvsp
\checkitem
The order of $ U $ and the order of $ V $ must be equal to the the number of
rows in $ A $ and the number of columns in $ A $, respectively.
\end{checks}
\begin{params}
\parameter{\flasvdtype}{jobu}{Indicates whether the left singular vectors are computed, how many are computed, and where they are stored.}
\parameter{\flasvdtype}{jobv}{Indicates whether the right singular vectors are computed, how many are computed, and where they are stored.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{s}{An \flaobj representing vector $ s $.}
\parameter{\flaobj}{U}{An \flaobj representing matrix $ U $.}
\parameter{\flaobj}{V}{An \flaobj representing matrix $ V $.}
\end{params}
\end{flaspec}










\subsection{Utility functions}




% --- FLA_Apply_diag_matrix() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Apply_diag_matrix( FLA_Side side, FLA_Conj conj, FLA_Obj x, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flaapplydiagmatrixns}
\purpose{
Apply a diagonal matrix to a general matrix, where the diagonal is stored in a
vector ({\sc apdiagmv}):
\begin{eqnarray*}
A & := & D A \\
A & := & \bar{D} A \\
A & := & A D \\
A & := & A \bar{D}
\end{eqnarray*}
where $ D $ is a diagonal matrix whose diagonal is stored in vector $ x $ and
$ A $ is a general matrix.
The \side argument indicates whether the diagonal matrix $ D $ is multiplied
on the left or the right side of $ A $.
The \conj argument allows the computation to proceed as if $ D $ (ie: the
entries stored in $ x $) were conjugated.
}
\begin{checks}
\checkitem
The numerical datatypes of $ x $ and $ A $ must be floating-point
and must not be \flaconstantns.
\itemvsp
\checkitem
The precision of the datatype of $ x $ must be equal to that of $ A $.
\itemvsp
\checkitem
If \side equals \flaleftns, then the length of $ x $ and the number of
rows in $ A $ must be equal; otherwise, if \side equals \flarightns, then
the length of $ x $ must be equal to the number of columns in $ A $.
\end{checks}
\begin{params}
\parameter{\flaside}{side}{Indicates whether the operation proceeds as if the diagonal matrix $ D $ is applied from the left or the right.}
\parameter{\flaconj}{conj}{Indicates whether the operation proceeds as if the diagonal matrix $ D $ were conjugated.}
\parameter{\flaobj}{x}{An \flaobj representing vector $ x $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Shift_pivots_to() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Shift_pivots_to( FLA_Pivot_type ptype, FLA_Obj p );
\end{verbatim}
\index{FLAME/C functions!\flashiftpivotstons}
\purpose{
Convert a pivot vector from \libflame pivot indexing to LAPACK indexing,
or vice versa.
If $ p $ currently contains \libflame pivots, setting \ptype to
\flalapackpivots will update the contents of $ p $ to reflect the pivoting
style found in LAPACK.
Likewise, if $ p $ currently contains LAPACK pivots, setting \ptype to
\flanativepivots will update the contents of $ p $ to reflect the pivoting
style used natively within \libflame.
}
\notes{
The user should always be aware of the current state of the indexing style
used by $ p $.
There is nothing stopping the user from applying the shift in the wrong
direction.
For example, attempting to shift the pivot format from \libflame to LAPACK
when the vector already uses LAPACK pivot indexing will result in an undefined
format.
Please see the description for \flalupiv in Section \ref{sec:lapack-front-ends}
for details on the differences between LAPACK-style pivot vectors and \libflame
pivot vectors.
}
\begin{checks}
\checkitem
The numerical datatype of $ p $ must be integer, and must not be
\flaconstantns.
\end{checks}
\begin{params}
\parameter{\flapivottype}{ptype}{Indicates the desired pivot indexing.}
\parameter{\flaobj}{p}{An \flaobj representing vector $ p $.}
\end{params}
\end{flaspec}

% --- FLA_Form_perm_matrix() ---------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Form_perm_matrix( FLA_Obj p, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flaformpermmatrixns}
\purpose{
Explicitly form a permutation matrix $ P $ from a pivot vector $ p $ and then
store the contents of $ P $ into $ A $.
}
\notes{
This function assumes that $ p $ uses native \libflame pivots.
Please see the description for \flalupiv in Section \ref{sec:lapack-front-ends}
for details on the differences between LAPACK-style pivot vectors and \libflame
pivot vectors.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
The numerical datatype of $ p $ must be integer, and must not be
\flaconstantns.
\itemvsp
\checkitem
$ A $ must be square.
\itemvsp
\checkitem
The number of rows in $ p $ must be equal to the order of $ A $.
\end{checks}
\implnotes{
This function is currently implemented as: \\
\parbox{4in}{\hspace{4mm}{\tt FLA\_Obj\_set\_to\_identity( A );}}
\parbox{4in}{\hspace{4mm}{\tt FLA\_Apply\_pivots( FLA\_LEFT, FLA\_NO\_TRANSPOSE, p, A );}}
}
\begin{params}
\parameter{\flaobj}{p}{An \flaobj representing vector $ p $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Househ2_UT() ---------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Househ2_UT( FLA_Side side, FLA_Obj chi_1, FLA_Obj x2, FLA_Obj tau );
\end{verbatim}
\index{FLAME/C functions!\flahousehtutns}
\purpose{
Compute the UT Householder transform, otherwise known as the ``UT transform'',
\begin{eqnarray*}
H & = &
\left( I - \frac{1}{\tau}
\left(
\begin{array}{c}
1 \\
u_2
\end{array}
\right)
\left(
\begin{array}{c}
1 \\
u_2
\end{array}
\right)^H
\right)
\end{eqnarray*}
by computing $ \tau $ and $ u_2 $ such that one of the following equations is
satisfied:
\begin{eqnarray*}
H
\left(
\begin{array}{c}
\chi_1 \\
x_2
\end{array}
\right)
& = &
\left(
\begin{array}{c}
\alpha \\
0
\end{array}
\right)
\\
\left(
\begin{array}{cc}
\chi_1 & x_2^T \\
\end{array}
\right)
H
& = &
\left(
\begin{array}{cc}
\alpha & 0 \\
\end{array}
\right)
\end{eqnarray*}
where
\begin{eqnarray*}
\alpha & = & - \frac{\| x \|_2 \chi_1}{| \chi_1 |} \\
x & = & \left( \begin{array}{c}
\chi_1 \\
x_2
\end{array}
\right).
\end{eqnarray*}
The \side parameter determines whether the the transform generated by
the function annihilates the elements below $ \chi_1 $ in $ x $ (when
applied from the left) or the elements to the right of $ \chi_1 $ in
$ x^T $ (when applied from the right).
On input {\tt chi\_1} and {\tt x2} are assumed to hold $ \chi_1 $
and $ x_2 $ (or $ x_2^T $), respectively.
Upon completion, {\tt chi\_1}, {\tt x2}, and {\tt tau}
are overwritten by $ \alpha $, $ u_2 $ (or $ u_2^T $), and $ \tau $,
respectively.
}
\notes{
When \side is \flaleftns, the function computes $ u_2 $ as
\begin{eqnarray*}
u_2  & = & \frac{x_2}{\chi_1 - \alpha}
\end{eqnarray*}
and when \side is \flarightns, the function computes $ u_2 $ as
\begin{eqnarray*}
u_2  & = & \frac{\bar x_2}{\bar \chi_1 - \bar \alpha}
\end{eqnarray*}
In either case, $ \tau $ is subsequently computed as
\begin{eqnarray*}
\tau & = & \frac{1 + u_2^H u_2}{2} \\
\end{eqnarray*}
}
\begin{checks}
\checkitem
The numerical datatypes of $ \chi_1 $, $ x_2 $, and $ \tau $ must be identical
and floating-point, and must not be \flaconstantns.
\end{checks}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\nrmtns.
}
\begin{params}
\parameter{\flaobj}{chi\_1}{An \flaobj representing scalar $ \chi_1 $.}
\parameter{\flaobj}{x2}{An \flaobj representing vector $ x_2 $ or $ x_2^T $.}
\parameter{\flaobj}{tau}{An \flaobj representing scalar $ \tau $.}
\end{params}
\end{flaspec}

% --- FLA_Househ2s_UT() --------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Househ2s_UT( FLA_Side side, FLA_Obj chi_1, FLA_Obj x2,
                      FLA_Obj alpha, FLA_Obj gamma, FLA_Obj tau );
\end{verbatim}
\index{FLAME/C functions!\flahousehtsutns}
\purpose{
Compute scalars associated with the UT Householder transform, otherwise known
as the ``UT transform'',
\begin{eqnarray*}
H & = &
\left( I - \frac{1}{\tau}
\left(
\begin{array}{c}
1 \\
u_2
\end{array}
\right)
\left(
\begin{array}{c}
1 \\
u_2
\end{array}
\right)^H
\right)
\end{eqnarray*}
%by computing $ \tau $ and $ u_2 $ such that one of the following equations is
%satisfied:
%\begin{eqnarray*}
%H
%\left(
%\begin{array}{c}
%\chi_1 \\
%x_2
%\end{array}
%\right)
%& = &
%\left(
%\begin{array}{c}
%\alpha \\
%0
%\end{array}
%\right)
%\\
%\left(
%\begin{array}{cc}
%\chi_1 & x_2^T \\
%\end{array}
%\right)
%H
%& = &
%\left(
%\begin{array}{cc}
%\alpha & 0 \\
%\end{array}
%\right)
%\end{eqnarray*}
%where
%\begin{eqnarray*}
%\alpha & = & - \frac{\| x \|_2 \chi_1}{| \chi_1 |} \\
%x & = & \left( \begin{array}{c}
%\chi_1 \\
%x_2
%\end{array}
%\right).
%\end{eqnarray*}
On input {\tt chi\_1} and {\tt x2} are assumed to hold $ \chi_1 $
and $ x_2 $ (or $ x_2^T $), respectively.
Upon completion,
{\tt alpha}, {\tt gamma}, and {\tt tau} are
overwritten by $ \alpha $, $ \chi_1 - \alpha $, and $ \tau $, respectively.
Objects {\tt chi\_1} and {\tt x2} are only referenced and not stored.
}
\notes{
The routine does not need a \side parameter.
The difference in output between the \flaleft and \flaright cases comes
down to a conjugation of $ u_2 $, and thus the same scalars may be
computed regardless of whether the transform is being applied from
the left or the right.
}
\moreinfo{
This function is similar to that of \flahousehtutns.
Please see the description for \flahousehtut further details.
}
\begin{checks}
\checkitem
The numerical datatypes of $ \chi_1 $, $ x_2 $, and $ \tau $ must be identical
and floating-point, and must not be \flaconstantns.
\end{checks}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\nrmtns.
}
\begin{params}
\parameter{\flaobj}{chi\_1}{An \flaobj representing scalar $ \chi_1 $.}
\parameter{\flaobj}{x2}{An \flaobj representing vector $ x_2 $ or $ x_2^T $.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{gamma}{An \flaobj representing scalar $ \chi_1 - \alpha $.}
\parameter{\flaobj}{tau}{An \flaobj representing scalar $ \tau $.}
\end{params}
\end{flaspec}

% --- FLA_Househ3UD_UT() -------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Househ3UD_UT( FLA_Obj chi_0, FLA_Obj x1, FLA_Obj y2, FLA_Obj tau );
\end{verbatim}
\index{FLAME/C functions!\flahousehtudutns}
\purpose{
Compute the up-and-downdating UT Householder transform, otherwise known as
the ``up-and-downdating UT transform'',
\begin{eqnarray*}
H & = &
\left[
\left(
\begin{array}{c c c}
1 & 0       & 0 \\ 
0 & I_{m_C} & 0 \\
0 & 0       & I_{m_D}
\end{array} 
\right)
-
\frac{1}{\tau}
\left(
\begin{array}{c c c}
1 & 0       & 0 \\ 
0 & I_{m_C} & 0 \\
0 & 0       & -I_{m_D}
\end{array} 
\right)
\left( \begin{array}{c}
1 \\
u_1 \\
v_2
\end{array}
\right)
\left(
\begin{array}{c}
1 \\
u_1 \\
v_2
\end{array}
%\begin{array}{ccc}
%1 & u_1^H & v_1^H
%\end{array}
\right)^H
\right]
%\left( \begin{array}{c}
%\chi_0 \\
%x_1 \\
%y_1
%\end{array}
%\right)
% = 
%\left( \begin{array}{c}
%\hat \chi_0 \\
%0 \\
%0
%\end{array}
%\right)
\end{eqnarray*}
by computing $ \tau $, $ u_1 $, and $ v_2 $ such that the following equation is
satisfied:
\begin{eqnarray*}
H
\left(
\begin{array}{c}
\chi_0 \\
x_1 \\
y_2
\end{array}
\right)
& = &
\left(
\begin{array}{c}
\alpha \\
0 \\
0
\end{array}
\right)
\end{eqnarray*}
where
\begin{eqnarray*}
\alpha & = & - \frac{\lambda \chi_0}{| \chi_0 |} \\
\lambda & = & \sqrt{ \bar{\chi_0} \chi_0 + x_1^H x_1 - y_2^H y_2 }.
\end{eqnarray*}
On input {\tt chi\_0}, {\tt x1}, and {\tt y2} are assumed to hold
$ \chi_0 $, $ x_1 $, and $ y_2 $,
respectively, and upon completion they are overwritten by $ \alpha $,
$ u_1 $, and $ v_2 $, respectively.
}
\notes{
The function computes $ \tau $, $ u_1 $, and $ v_2 $ as:
\begin{eqnarray*}
\tau & = & \frac{1 + u_1^H u_1 - v_2^H v_2}{2} \\
u_1  & = & \frac{x_1}{\chi_0 - \alpha} \\
v_2  & = & -\frac{y_2}{\chi_0 - \alpha}
\end{eqnarray*}
}
\begin{checks}
\checkitem
The numerical datatypes of $ \chi_0 $, $ x_1 $, $ y_2 $, and $ \tau $ must be
identical and floating-point, and must not be \flaconstantns.
\end{checks}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\nrmtns.
}
\begin{params}
\parameter{\flaobj}{chi\_0}{An \flaobj representing scalar $ \chi_0 $.}
\parameter{\flaobj}{x1}{An \flaobj representing vector $ x_1 $.}
\parameter{\flaobj}{y2}{An \flaobj representing vector $ y_2 $.}
\parameter{\flaobj}{tau}{An \flaobj representing scalar $ \tau $.}
\end{params}
\end{flaspec}

% --- FLA_Accum_T_UT() ---------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Accum_T_UT( FLA_Direct direct, FLA_Store storev,
                     FLA_Obj V, FLA_Obj t, FLA_Obj T );
\end{verbatim}
\index{FLAME/C functions!\flaaccumtutns}
\purpose{
Compute one or more triangular factors $ T_j $ of a block Householder
transformation $ H_j $ from a set of Householder reflectors,
which were computed via the UT transform.
The Householder reflectors are given via the Householder vectors stored
in the strictly lower or strictly upper triangle of the $ m \by n $ matrix
$ V $ and the $ \tau $ scalar factors stored in vector $ t $ of length
$ k = \min(m,n) $.
The triangular factors $ T_j $ are stored horizontally within a
$ b \by k $ matrix $ T $ as:
\begin{eqnarray*}
T & = & \left(
\begin{array}{c | c | c | c} 
T_0 & T_1 & \cdots & T_{p-1}
\end{array}
\right)
\end{eqnarray*}
where $ p = \lceil k/b \rceil $.
All factors $ T_j $ are $ b \by b $, except $ T_{p-1} $ which may be
smaller if the remainder of $ k/b $ is nonzero.
}
\notes{
Each reflector is defined as $ H(i) = I - \frac{1}{\tau} v v^H $, where $ \tau $
is a scalar stored at the $ i $th element of vector $ t $ and and $ v $ is
a vector stored in matrix $ V $.
If \direct is \flaforwardns, then $ H $ is the forward product of $ k $
Householder reflectors, $ H(0) H(1) \cdots H(k-1) $, and $ T $ is upper
triangular upon completion.
If \direct is \flabackwardns, then $ H $ is the backward product of $ k $
Householder reflectors, $ H(k-1) \cdots H(1) H(0) $, and $ T $ is lower
triangular upon completion.
If \storev is \flacolumnwise, the vector which defines reflector
$ H(i) $ is assumed to be stored in the $ i $th column of $ V $, and
$ H = I - V T^{-1} V^H $,
where the order of $ H $ is equal to the number of rows in $ V $.
If \storev is \flarowwisens, the vector which defines reflector
$ H(i) $ is assumed to be stored in the $ i $th row of $ V $, and
$ H = I - V^H T^{-1} V $,
where the order of $ H $ is equal to the number of columns in $ V $.
The dimensions and storage layout of $ V $ depend on the values of \direct
and \storevns, which should be set according to how $ V $ was filled.
The following example, with $ k = 3 $ Householder reflectors and $ H $ of
order $ n = 5 $, illustrates the possible storage schemes for matrix
$ V $.
\begin{center}
\begin{math}
\begin{array}{clcc}
% & & \multicolumn{3}{c}{\storev}  \\
 & & \multicolumn{2}{c}{\storev}  \\
% & & \text{\flacolumnwisens} & & \text{\flarowwisens} \\
 & & \flacolumnwisens & \flarowwisens \\
%& & & & \\
& & & \\
\multirow{3}{*}{\raisebox{-16.5mm}{\rotatebox{90}{\direct}}}
&
\raisebox{-9.0mm}{\rotatebox{90}{\flaforwardns}}
& 
\begin{pmatrix}
1      &         &         \\
\nu_0  &  1      &         \\
\nu_0  &  \nu_1  &  1      \\
\nu_0  &  \nu_1  &  \nu_2  \\
\nu_0  &  \nu_1  &  \nu_2
\end{pmatrix}
%& &
&
\begin{pmatrix}
1    &  \nu_0  &  \nu_0  &  \nu_0  &  \nu_0  \\
     &  1      &  \nu_1  &  \nu_1  &  \nu_1  \\
     &         &  1      &  \nu_2  &  \nu_2
\end{pmatrix}
\\
% & & & & \\
 & & & \\
&
\raisebox{-10.0mm}{\rotatebox{90}{\flabackwardns}}
&
\begin{pmatrix}
\nu_0  &  \nu_1  &  \nu_2  \\
\nu_0  &  \nu_1  &  \nu_2  \\
1      &  \nu_1  &  \nu_2  \\
       &  1      &  \nu_2  \\
       &         &  1
\end{pmatrix}
%& &
&
\begin{pmatrix}
\nu_0  &  \nu_0  &  1      &         &     \\
\nu_1  &  \nu_1  &  \nu_1  &  1      &     \\
\nu_2  &  \nu_2  &  \nu_2  &  \nu_2  &  1
\end{pmatrix}
\\
\end{array}
\end{math}
\end{center}
Here, elements $ \nu_j $ for some constant $ j $ all belong to the same
vector $ v $ that defines the Householder reflector $ H(i) $.
Note that the unit diagonal elements are not stored, and the rest of
the matrix is not referenced.
}
\notes{
This function should only be used with matrices $ V $ and vectors $ t $ that
were filled by other UT transform operations, such as \flaqrut and
\flaqrutrecovertauns.
}
\begin{checks}
\checkitem
The numerical datatypes of $ V $, $ t $, and $ T $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The length of $ t $ and the width of $ T $ must be $ \min(m,n) $ where $ V $
is $ m \by n $.
\end{checks}
\ifacenotes{
Since \flaqrut and \flalqut provide $ T $ upon return, this routine is
rarely needed.
However, there may be occasions when the user wishes to save the $ \tau $
values of $ T $ to $ t $ (via \flaqrutrecovertauns), discard the matrix $ T $, and
then subsequently rebuild $ T $ from $ t $.
This routine facilitates the final step of such a process.
}
\caveats{
\flaaccumtut is currently only implemented for the two cases where \direct is
\flaforwardns.
}
\begin{params}
\parameter{\fladirect}{direct}{Indicates whether $ H $ is formed from the forward or backward product of its constituent Householder reflectors.}
\parameter{\flastorev}{storev}{Indicates whether the vectors stored within $ V $ are stored column-wise below the diagonal or row-wise above the diagonal.}
\parameter{\flaobj}{V}{An \flaobj representing matrix $ V $.}
\parameter{\flaobj}{t}{An \flaobj representing vector $ t $.}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\end{params}
\end{flaspec}

% --- FLA_Apply_H2_UT() --------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Apply_H2_UT( FLA_Side side, FLA_Obj tau, FLA_Obj u2, FLA_Obj a1, FLA_Obj A2 );
\end{verbatim}
\index{FLAME/C functions!\flaapplyhtutns}
\purpose{
Apply a single UT Householder transformation, $ H $, to a row vector
$ a_1^T $ and a matrix $ A_2 $ from the left,
\begin{eqnarray*}
\left(
\begin{array}{c}
a_1^T \\
A_2
\end{array}
\right)
&
:=
&
H
\left(
\begin{array}{c}
a_1^T \\
A_2
\end{array}
\right)
\end{eqnarray*}
or to a column vector $ a_1 $ and a matrix $ A_2 $ from the right,
\begin{eqnarray*}
\left(
\begin{array}{cc}
a_1 & A_2 \\
\end{array}
\right)
&
:=
&
\left(
\begin{array}{cc}
a_1 & A_2 \\
\end{array}
\right)
H
\end{eqnarray*}
where $ H $ is determined by the scalar $ \tau $ and vector $ u_2 $ computed by
\flahousehtutns.
The \side argument indicates whether the transform is applied from the left
or the right.
Note that $ a_1 $ and $ A_2 $ are typically either vertically
(if applying from the left) or horizontally (if applying from
the right) adjacent views into the same matrix object, though
this is not a requirement.
}
\begin{checks}
\checkitem
The numerical datatypes of $ \tau $, $ u_2 $, $ a_1 $, and $ A_2 $ must
be identical and floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If \side equals \flaleftns, then the length of $ u_2 $ and the number of
rows in $ A_2 $ must be equal; otherwise, if \side equals \flarightns, then
the length of $ u_2 $ must be equal to the number of columns in $ A_2 $.
\itemvsp
\checkitem
If \side equals \flaleftns, then the length of $ a_1^T $ and the number of
columns in $ A_2 $ must be equal; otherwise, if \side equals \flarightns, then
the length of $ a_1 $ must be equal to the number of rows in $ A_2 $.
\end{checks}
\begin{params}
\parameter{\flaside}{side}{Indicates whether the Householder transformation is applied from the left or the right.}
\parameter{\flaobj}{tau}{An \flaobj representing scalar $ \tau $.}
\parameter{\flaobj}{u2}{An \flaobj representing vector $ u_2 $.}
\parameter{\flaobj}{a1}{An \flaobj representing vector $ a_1 $.}
\parameter{\flaobj}{A2}{An \flaobj representing matrix $ A_2 $.}
\end{params}
\end{flaspec}

% --- FLA_QR_UT_create_T() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_QR_UT_create_T( FLA_Obj A, FLA_Obj* T );
\end{verbatim}
\index{FLAME/C functions!\flaqrutcreatetns}
\purpose{
Given an $ m \by n $ matrix $ A $ upon which the user intends to perform a QR
factorization via the UT transform, create a $ b \by k $ matrix $ T $
where $ b $ is chosen to be a reasonable blocksize and $ k = \min(m,n) $.
This matrix $ T $ is required as input to \flaqrut so that the
upper triangular factors of the block Householder transformations may be
accumulated during each iteration of the factorization algorithm.
Once created, $ T $ may be freed normally via \flaobjfreens.
This routine is provided in case the user is not comfortable choosing the
length of $ T $, and thus implicitly setting the algorithmic blocksize of
\flaqrutns.
}
\notes{
Matrix $ T $ is created so that its numerical datatype and storage format
(row- or column-major) is the same as that of $ A $.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\end{checks}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parminout{\flaobjp}{T}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new \flaobj parameterized by $ b $, $ k $, and the datatype of $ A $.}
\end{params}
\end{flaspec}

% --- FLA_QR_UT_recover_tau() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_QR_UT_recover_tau( FLA_Obj T, FLA_Obj t );
\end{verbatim}
\index{FLAME/C functions!\flaqrutrecovertauns}
\purpose{
Subsequent to a QR factorization via the UT transform,
recover the $ \tau $ values along the diagonals of the upper triangular
factors of the block Householder submatrices of $ T $ and store them to
a vector $ t $.
}
\notes{
This routine is rarely needed.
However, there may be occasions when the user wishes to save the $ \tau $
values of $ T $ to $ t $, discard the matrix $ T $, and then subsequently
rebuild $ T $ from $ t $ (via \flaaccumtutns).
This routine facilitates the first step of such a process.
}
\begin{checks}
\checkitem
The numerical datatypes of $ T $ and $ t $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The width of $ T $ must be equal to $ \dim(t) $.
\end{checks}
\begin{params}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\parameter{\flaobj}{t}{An \flaobj representing vector $ t $.}
\end{params}
\end{flaspec}

% --- FLA_QR_UT_form_Q() -------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_QR_UT_form_Q( FLA_Obj A, FLA_Obj T, FLA_Obj Q );
\end{verbatim}
\index{FLAME/C functions!\flaqrutformqns}
\purpose{
Form a unitary matrix $ Q $ from the Householder vectors stored below
the diagonal of $ A $ and the block Householder submatrices of $ T $:
\begin{eqnarray*}
Q & \becomes & H_{0} H_{1} \cdots H_{k-1}
\end{eqnarray*}
where $ H_{i} $ is the Householder transform associated with the 
Householder vector stored below the diagonal in the $i$th column
of $ A $.
}
\implnotes{
This operation is implemented such the minimum number of computations
are performed in forming $ Q $.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ T $, and $ Q $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The width of $ T $ must be equal to the width of $ A $.
\itemvsp
\checkitem
The dimension of $ Q $ must be equal to the number of rows in $ A $.
\end{checks}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\parameter{\flaobj}{Q}{An \flaobj representing matrix $ Q $.}
\end{params}
\end{flaspec}

% --- FLA_LQ_UT_create_T() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_LQ_UT_create_T( FLA_Obj A, FLA_Obj* T );
\end{verbatim}
\index{FLAME/C functions!\flalqutcreatetns}
\purpose{
Given an $ m \by n $ matrix $ A $ upon which the user intends to perform a LQ
factorization via the UT transform, create a $ b \by k $ matrix $ T $
where $ b $ is chosen to be a reasonable blocksize and $ k = \min(m,n) $.
This matrix $ T $ is required as input to \flalqut so that the
upper triangular factors of the block Householder transformations may be
accumulated during each iteration of the factorization algorithm.
Once created, $ T $ may be freed normally via \flaobjfreens.
This routine is provided in case the user is not comfortable choosing the
length of $ T $, and thus implicitly setting the algorithmic blocksize of
\flalqutns.
}
\notes{
Matrix $ T $ is created so that its numerical datatype and storage format
(row- or column-major) is the same as that of $ A $.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\end{checks}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parminout{\flaobjp}{T}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new \flaobj parameterized by $ b $, $ n $, and the datatype of $ A $.}
\end{params}
\end{flaspec}

% --- FLA_LQ_UT_recover_tau() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_LQ_UT_recover_tau( FLA_Obj T, FLA_Obj t );
\end{verbatim}
\index{FLAME/C functions!\flalqutrecovertauns}
\purpose{
Subsequent to an LQ factorization via the UT transform,
recover the $ \tau $ values along the diagonals of the upper triangular
factors of the block Householder submatrices of $ T $ and store them to
a vector $ t $.
}
\notes{
This routine is rarely needed.
However, there may be occasions when the user wishes to save the $ \tau $
values of $ T $ to $ t $, discard the matrix $ T $, and then subsequently
rebuild $ T $ from $ t $ (via \flaaccumtutns).
This routine facilitates the first step of such a process.
}
\begin{checks}
\checkitem
The numerical datatypes of $ T $ and $ t $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The width of $ T $ must be equal to $ \dim(t) $.
\end{checks}
\begin{params}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\parameter{\flaobj}{t}{An \flaobj representing vector $ t $.}
\end{params}
\end{flaspec}

% --- FLA_UDdate_UT_create_T() -------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_UDdate_UT_create_T( FLA_Obj R, FLA_Obj* T );
\end{verbatim}
\index{FLAME/C functions!\flauddateutcreatetns}
\purpose{
Given an $ n \by n $ matrix $ R $ that the user intends to up-and-downdate
via up-and-downdating UT transforms, create a $ b \by n $ matrix $ T $
where $ b $ is chosen to be a reasonable blocksize.
This matrix $ T $ is required as input to \flauddateut so that the
upper triangular factors of the block Householder transformations may be
accumulated during each iteration of the factorization algorithm.
Once created, $ T $ may be freed normally via \flaobjfreens.
This routine is provided in case the user is not comfortable choosing the
length of $ T $, and thus implicitly setting the algorithmic blocksize of
\flauddateutns.
}
\notes{
Matrix $ T $ is created so that its numerical datatype and storage format
(row- or column-major) is the same as that of $ R $.
}
\begin{checks}
\checkitem
The numerical datatype of $ R $ must be floating-point, and must not be
\flaconstantns.
\end{checks}
\begin{params}
\parameter{\flaobj}{R}{An \flaobj representing matrix $ R $.}
\parminout{\flaobjp}{T}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new \flaobj parameterized by $ b $, $ n $, and the datatype of $ A $.}
\end{params}
\end{flaspec}

% --- FLA_LQ_UT_form_Q() -------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_LQ_UT_form_Q( FLA_Obj A, FLA_Obj T, FLA_Obj Q );
\end{verbatim}
\index{FLAME/C functions!\flalqutformqns}
\purpose{
Form a unitary matrix $ Q $ from the Householder vectors stored above
the diagonal of $ A $ and the block Householder submatrices of $ T $:
\begin{eqnarray*}
Q & \becomes & H_{k-1} \cdots H_{1} H_{0}
\end{eqnarray*}
where $ H_{i} $ is the Householder transform associated with the 
Householder vector stored above the diagonal in the $i$th row
of $ A $.
}
\implnotes{
This operation is implemented such the minimum number of computations
are performed in forming $ Q $.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ T $, and $ Q $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The width of $ T $ must be equal to the length of $ A $.
\itemvsp
\checkitem
The dimension of $ Q $ must be equal to the number of columns in $ A $.
\end{checks}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\parameter{\flaobj}{Q}{An \flaobj representing matrix $ Q $.}
\end{params}
\end{flaspec}

% --- FLA_Hess_UT_create_T() ---------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Hess_UT_create_T( FLA_Obj A, FLA_Obj* T );
\end{verbatim}
\index{FLAME/C functions!\flahessutcreatetns}
\purpose{
Given an $ n \by n $ matrix $ A $ upon which the user intends to perform a
reduction to upper Hessenberg form, create a $ b \by n $ matrix $ T $
where $ b $ is chosen to be a reasonable blocksize.
This matrix $ T $ is required as input to \flahessut so that the
upper triangular factors of the block Householder transformations may be
accumulated during each iteration of the factorization algorithm.
Once created, $ T $ may be freed normally via \flaobjfreens.
This routine is provided in case the user is not comfortable choosing the
length of $ T $, and thus implicitly setting the algorithmic blocksize of
\flahessutns.
}
\notes{
Matrix $ T $ is created so that its numerical datatype and storage format
(row- or column-major) is the same as that of $ A $.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\end{checks}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parminout{\flaobjp}{T}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new \flaobj parameterized by $ b $, $ n $, and the datatype of $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Hess_UT_recover_tau() ------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Hess_UT_recover_tau( FLA_Obj T, FLA_Obj t );
\end{verbatim}
\index{FLAME/C functions!\flahessutrecovertauns}
\purpose{
Subsequent to a reduction to upper Hessenberg form via the UT transform,
recover the $ \tau $ values along the diagonals of the upper triangular
factors of the block Householder submatrices of $ T $ and store them to
a vector $ t $.
}
\notes{
This routine is rarely needed.
However, there may be occasions when the user wishes to save the $ \tau $
values of $ T $ to $ t $, discard the matrix $ T $, and then subsequently
rebuild $ T $ from $ t $ (via \flaaccumtutns).
This routine facilitates the first step of such a process.
}
\begin{checks}
\checkitem
The numerical datatypes of $ T $ and $ t $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The width of $ T $ must be equal to $ \dim(t) $.
\end{checks}
\begin{params}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\parameter{\flaobj}{t}{An \flaobj representing vector $ t $.}
\end{params}
\end{flaspec}

% --- FLA_Tridiag_UT_create_T() ------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Tridiag_UT_create_T( FLA_Obj A, FLA_Obj* T );
\end{verbatim}
\index{FLAME/C functions!\flatridiagutcreatetns}
\purpose{
Given an $ n \by n $ matrix $ A $ upon which the user intends to perform a
reduction to tridiagonal form via the UT transform, create a $ b \by n $ matrix
$ T $ where $ b $ is chosen to be a reasonable blocksize.
This matrix $ T $ is required as input to \flatridiagut so that the
upper triangular factors of the block Householder transformations may be
accumulated during each iteration of the reduction algorithm.
Once created, $ T $ may be freed normally via \flaobjfreens.
This routine is provided in case the user is not comfortable choosing the
length of $ T $, and thus implicitly setting the algorithmic blocksize of
\flatridiagutns.
}
\notes{
Matrix $ T $ is created so that its numerical datatype and storage format
(row- or column-major) is the same as that of $ A $.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\end{checks}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parminout{\flaobjp}{T}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new \flaobj parameterized by $ b $, $ n $, and the datatype of $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Tridiag_UT_recover_tau() ---------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Tridiag_UT_recover_tau( FLA_Obj T, FLA_Obj t );
\end{verbatim}
\index{FLAME/C functions!\flatridiagutrecovertauns}
\purpose{
Subsequent to a reduction to tridiagonal form via the UT transform,
recover the $ \tau $ values along the diagonals of the upper triangular
factors of the block Householder submatrices of $ T $ and store them to
a vector $ t $.
}
\notes{
This routine is rarely needed.
However, there may be occasions when the user wishes to save the $ \tau $
values of $ T $ to $ t $, discard the matrix $ T $, and then subsequently
rebuild $ T $ from $ t $ (via \flaaccumtutns).
This routine facilitates the first step of such a process.
}
\begin{checks}
\checkitem
The numerical datatypes of $ T $ and $ t $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The width of $ T $ must be equal to $ \dim(t) $.
\end{checks}
\begin{params}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\parameter{\flaobj}{t}{An \flaobj representing vector $ t $.}
\end{params}
\end{flaspec}

% --- FLA_Tridiag_UT_realify() -------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Tridiag_UT_realify( FLA_Uplo uplo, FLA_Obj A, FLA_Obj r );
\end{verbatim}
\index{FLAME/C functions!\flatridiagutrealifyns}
\purpose{
Subsequent to a reduction to tridiagonal form via the UT transform,
reduce matrix $ A $ to real tridiagonal form and store the scalars
used in the reduction in vector $ r $.
If the matrix datatype is real to begin with, then $ A $ is left
unchanged and the elements of $ r $ are set to one.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ r $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
$ A $ must be square.
\itemvsp
\checkitem
The length and width of $ A $ must be equal to $ \dim(r) $.
\end{checks}
\begin{params}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{r}{An \flaobj representing vector $ r $.}
\end{params}
\end{flaspec}

% --- FLA_Bidiag_UT_create_T() -------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Bidiag_UT_create_T( FLA_Obj A, FLA_Obj* TU, FLA_Obj* TV );
\end{verbatim}
\index{FLAME/C functions!\flabidiagutcreatetns}
\purpose{
Given an $ m \by n $ matrix $ A $ upon which the user intends to perform a
reduction to bidiagonal form via the UT transform, create $ b \by k $ matrices
$ T_U $ and $ T_V $ where $ b $ is chosen to be a reasonable blocksize and
$ k = \min(m,n) $.
These matrices $ T_U $ and $ T_V $ are required as input to \flabidiagut so
that the upper triangular factors of the block Householder transformations
may be accumulated during each iteration of the reduction algorithm.
Once created, $ T_U $ and $ T_V $ may be freed normally via \flaobjfreens.
This routine is provided in case the user is not comfortable choosing the
length of $ T_U $ and $ T_V $, and thus implicitly setting the algorithmic
blocksize of \flabidiagutns.
}
\notes{
Matrices $ T_U $ and $ T_V $ are created so that their numerical datatypes
and storage formats (row- or column-major) are the same as that of $ A $.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\end{checks}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parminout{\flaobjp}{TU}{A pointer to an uninitialized \flaobjns.}
                        {A pointer to a new \flaobj parameterized by $ b $, $ k $, and the datatype of $ A $.}
\parminout{\flaobjp}{TV}{A pointer to an uninitialized \flaobjns.}
                        {A pointer to a new \flaobj parameterized by $ b $, $ k $, and the datatype of $ A $.}
\end{params}
\end{flaspec}

% --- FLA_Bidiag_UT_recover_tau() ----------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Bidiag_UT_recover_tau( FLA_Obj TU, FLA_Obj TV, FLA_Obj tU, FLA_Obj tV );
\end{verbatim}
\index{FLAME/C functions!\flabidiagutrecovertauns}
\purpose{
Subsequent to a reduction to bidiagonal form via the UT transform,
recover the $ \tau $ values along the diagonals of the upper triangular
factors of the block Householder submatrices of $ T_U $ and $ T_V $ and
store them to vectors $ t_U $ and $ t_V $, respectively.
}
\notes{
This routine is rarely needed.
However, there may be occasions when the user wishes to save the $ \tau $
values of $ T_U $ and $ T_V $ to $ t_U $ and $ t_V $, discard the matrices
$ T_U $ and $ T_V $, and then subsequently rebuild $ T_U $ and $ T_V $ from
$ t_U $ and $ t_V $ (via \flaaccumtutns).
This routine facilitates the first step of such a process.
}
\begin{checks}
\checkitem
The numerical datatypes of $ T_U $, $ T_V $, $ t_U $, and $ t_V $ must be
identical and floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The width of $ T_U $ and must be equal $ \dim(t_U) $.
\itemvsp
\checkitem
The width of $ T_V $ and must be equal $ \dim(t_V) $.
\itemvsp
\checkitem
$ \dim(t_U) $ must equal $ \dim(t_V) $.
\end{checks}
\begin{params}
\parameter{\flaobj}{TU}{An \flaobj representing matrix $ T_U $.}
\parameter{\flaobj}{TV}{An \flaobj representing matrix $ T_V $.}
\parameter{\flaobj}{tU}{An \flaobj representing vector $ t_U $.}
\parameter{\flaobj}{tV}{An \flaobj representing vector $ t_V $.}
\end{params}
\end{flaspec}

% --- FLA_Bidiag_UT_realify() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Bidiag_UT_realify( FLA_Obj A, FLA_Obj rL, FLA_Obj rR );
\end{verbatim}
\index{FLAME/C functions!\flabidiagutrealifyns}
\purpose{
Subsequent to a reduction to bidiagonal form via the UT transform,
reduce matrix $ A $ to real bidiagonal form and store the left and
right scalars used in the reduction in vectors $ r_L $ and $ r_R $,
respectively.
If the matrix datatype is real to begin with, then $ A $ is left
unchanged and the elements of $ r_L $ and $ r_R $ are set to one.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ r_L $, and $ r_R $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The vector lengths of $ r_L $ and $ r_R $ must be $ \min(m,n) $ where $ A $
is $ m \by n $.
\end{checks}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{rL}{An \flaobj representing vector $ r_L $.}
\parameter{\flaobj}{rR}{An \flaobj representing vector $ r_R $.}
\end{params}
\end{flaspec}

% --- FLA_Apply_Q_UT_create_workspace() ----------------------------------------
% --- FLASH_Apply_Q_UT_create_workspace() --------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Apply_Q_UT_create_workspace( FLA_Obj T, FLA_Obj B, FLA_Obj* W );
void FLASH_Apply_Q_UT_create_workspace( FLA_Obj T, FLA_Obj B, FLA_Obj* W );
\end{verbatim}
\index{FLAME/C functions!\flaapplyqutcreateworkspacens}
\index{FLASH functions!\flashapplyqutcreateworkspacens}
\purpose{
Create a flat (or hierarchical) workspace matrix $ W $ needed when applying
$ Q $ or  $ Q^H $
to $ B $ via \flaapplyqut (or \flashapplyqutns).
Once created, $ W $ may be freed normally via \flaobjfree (or
\flashobjfreens).
}
\notes{
This function is provided as a convenience to users of \flaapplyqut and
\flashapplyqut so they do not need to worry about creating the workspace
matrix object $ W $ with the correct properties.
}
\begin{checks}
\checkitem
The numerical datatypes of $ T $ and $ B $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The pointer argument {\tt W} must not be \fnullns.
\end{checks}
\begin{params}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\parminout{\flaobjp}{W}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new \flaobj to represent matrix $ W $.}
\end{params}
\end{flaspec}

% --- FLA_Apply_QUD_UT_create_workspace() --------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Apply_QUD_UT_create_workspace( FLA_Obj T, FLA_Obj B, FLA_Obj* W );
\end{verbatim}
\index{FLAME/C functions!\flaapplyqudutcreateworkspacens}
\purpose{
Create a flat workspace matrix $ W $ needed when applying $ Q^H $
to $ B $ via \flaapplyqudutns.
Once created, $ W $ may be freed normally via \flaobjfreens.
}
\notes{
This function is provided as a convenience to users of \flaapplyqudut so they
do not need to worry about creating the workspace matrix object $ W $ with the
correct properties.
}
\begin{checks}
\checkitem
The numerical datatypes of $ T $ and $ B $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The pointer argument {\tt W} must not be \fnullns.
\end{checks}
\begin{params}
\parameter{\flaobj}{T}{An \flaobj representing matrix $ T $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\parminout{\flaobjp}{W}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new \flaobj to represent matrix $ W $.}
\end{params}
\end{flaspec}

% --- FLASH_LU_incpiv_create_hier_matrices() -----------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_LU_incpiv_create_hier_matrices( FLA_Obj A_flat, dim_t depth, dim_t* b_flash,
                                           dim_t b_alg, FLA_Obj* A, FLA_Obj* p,
                                           FLA_Obj* L );
\end{verbatim}
\index{FLASH functions!\flashluincpivcreatehiermatricesns}
\purpose{
Create a hierarchical matrix $ A $ conformal to a flat matrix $ A_{flat} $ and then
copy the contents of $ A_{flat} $ into $ A $.
The hierarchy of $ A $ is specified by the depth and square blocksize values
in \depth and \bflashns, respectively.
Also, create hierarchical matrix objects $ p $ and $ L $ with
proper datatypes, dimensions, and hierarchies relative to $ A $ so that the
objects may be used together with \flashluincpiv and \flashfsincpivns.
If \balg is greater than zero, it is used as the the width of the
storage blocks in $ L $, which determines the algorithmic blocksize
used in \flashluincpivns.
If \balg is zero, the width of the storage blocks in $ L $ is set to a
reasonable default value.
Once created, $ A $, $ p $, and $ L $ may be freed normally via
\flashobjfreens.
}
\notes{
This function is provided as a convenience to users of \flashluincpiv so they
do not need to worry about creating each auxiliary matrix object with the
correct properties.
}
\begin{checks}
\checkitem
The numerical datatype of $ A_{flat} $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
$ A_{flat} $ must be square.
\itemvsp
\checkitem
The pointer arguments \bflashns, {\tt A}, {\tt p}, and {\tt L}
must not be \fnullns.
\itemvsp
\checkitem
Each of the first \depth values in \bflash must be greater than zero.
\end{checks}
\caveats{
Currently, this function only supports hierarchical depths of exactly 1.
}
\begin{params}
\parameter{\flaobj}{A\_flat}{An \flaobj representing matrix $ A_{flat} $.}
\parameter{\dimt}{depth}{The number of levels to create in the matrix hierarchies of $ A $, $ p $, and $ L $.}
\parameter{\dimtp}{b\_flash}{A pointer to an array of \depth values to be used as blocksizes in creating the matrix hierarchies of $ A $, $ p $, and $ L $.}
\parameter{\dimt}{b\_alg}{The value to be used as the width of the storage blocks in $ L $ (ie: the number of columns in the leaves of $ L $), which determines the algorithmic blocksize used in \flashluincpiv and \flashfsincpivns, or zero if the user wishes to use a default value.}
\parminout{\flaobjp}{A}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj to represent matrix $ A $, conformal to and initialized with the contents of $ A_{flat} $.}
\parminout{\flaobjp}{p}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj to represent vector $ p $.}
\parminout{\flaobjp}{L}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj to represent matrix $ L $.}
\end{params}
\end{flaspec}

% --- FLASH_QR_UT_create_hier_matrices() ---------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_QR_UT_create_hier_matrices( FLA_Obj A_flat, dim_t depth, dim_t* b_flash,
                                       FLA_Obj* A, FLA_Obj* TW );
\end{verbatim}
\index{FLASH functions!\flashqrutcreatehiermatricesns}
\purpose{
Create a hierarchical matrix $ A $ conformal to a flat matrix $ A_{flat} $ and
then copy the contents of $ A_{flat} $ into $ A $.
The hierarchy of $ A $ is specified by the depth and square blocksize values
in \depth and \bflashns, respectively.
Also, create hierarchical matrix object $ TW $ with
proper datatype, dimensions, and hierarchy relative to $ A $ so that the
objects may be used together with \flashqrut and \flashapplyqutns.
Unlike with \flashqrutinccreatehiermatricesns, the algorithmic blocksize
specified by \balg must equal the storage blocksize, \bflashns.
Once created, $ A $ and $ TW $ may be freed normally via
\flashobjfreens.
}
\notes{
This function is provided as a convenience to users of \flashqrut so they
do not need to worry about creating the auxiliary $ TW $ matrix object with the
correct properties.
}
\begin{checks}
\checkitem
The numerical datatype of $ A_{flat} $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
$ A_{flat} $ must be square.
\itemvsp
\checkitem
The pointer arguments \bflashns, {\tt A}, and {\tt TW} must not be \fnullns.
\itemvsp
\checkitem
Each of the first \depth values in \bflash must be greater than zero.
\end{checks}
\caveats{
Currently, this function only supports hierarchical depths of exactly 1.
}
\begin{params}
\parameter{\flaobj}{A\_flat}{An \flaobj representing matrix $ A_{flat} $.}
\parameter{\dimt}{depth}{The number of levels to create in the matrix hierarchies of $ A $ and $ TW $.}
\parameter{\dimtp}{b\_flash}{A pointer to an array of \depth values to be used as blocksizes in creating the matrix hierarchies of $ A $ and $ TW $.}
\parminout{\flaobjp}{A}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj to represent matrix $ A $, conformal to and initialized with the contents of $ A_{flat} $.}
\parminout{\flaobjp}{TW}{A pointer to an uninitialized \flaobjns.}
                        {A pointer to a new hierarchical \flaobj to represent matrix $ TW $.}
\end{params}
\end{flaspec}

% --- FLASH_QR_UT_inc_create_hier_matrices() -----------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_QR_UT_inc_create_hier_matrices( FLA_Obj A_flat, dim_t depth, dim_t* b_flash,
                                           dim_t b_alg, FLA_Obj* A, FLA_Obj* TW );
\end{verbatim}
\index{FLASH functions!\flashqrutinccreatehiermatricesns}
\purpose{
Create a hierarchical matrix $ A $ conformal to a flat matrix $ A_{flat} $ and
then copy the contents of $ A_{flat} $ into $ A $.
The hierarchy of $ A $ is specified by the depth and square blocksize values
in \depth and \bflashns, respectively.
Also, create hierarchical matrix object $ TW $ with
proper datatype, dimensions, and hierarchy relative to $ A $ so that the
objects may be used together with \flashqrutinc and \flashapplyqutincns.
If \balg is greater than zero, it is used as the the length of the
storage blocks in $ TW $, which determines the algorithmic blocksize
used in \flashqrutincns.
If \balg is zero, the length of the storage blocks in $ TW $ is set to a
reasonable default value.
Once created, $ A $ and $ TW $ may be freed normally via
\flashobjfreens.
}
\notes{
This function is provided as a convenience to users of \flashqrutinc so they
do not need to worry about creating the auxiliary $ TW $ matrix object with the
correct properties.
}
\begin{checks}
\checkitem
The numerical datatype of $ A_{flat} $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
$ A_{flat} $ must be square.
\itemvsp
\checkitem
The pointer arguments \bflashns, {\tt A}, and {\tt TW} must not be \fnullns.
\itemvsp
\checkitem
Each of the first \depth values in \bflash must be greater than zero.
\end{checks}
\caveats{
Currently, this function only supports hierarchical depths of exactly 1.
}
\begin{params}
\parameter{\flaobj}{A\_flat}{An \flaobj representing matrix $ A_{flat} $.}
\parameter{\dimt}{depth}{The number of levels to create in the matrix hierarchies of $ A $ and $ TW $.}
\parameter{\dimtp}{b\_flash}{A pointer to an array of \depth values to be used as blocksizes in creating the matrix hierarchies of $ A $ and $ TW $.}
\parameter{\dimt}{b\_alg}{The value to be used as the length of the storage blocks in $ TW $ (ie: the number of rows in the leaves of $ TW $), which determines the algorithmic blocksize used in \flashqrutinc and \flashapplyqutincns, or zero if the user wishes to use a default value.}
\parminout{\flaobjp}{A}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj to represent matrix $ A $, conformal to and initialized with the contents of $ A_{flat} $.}
\parminout{\flaobjp}{TW}{A pointer to an uninitialized \flaobjns.}
                        {A pointer to a new hierarchical \flaobj to represent matrix $ TW $.}
\end{params}
\end{flaspec}

% --- FLASH_LQ_UT_create_hier_matrices() ---------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_LQ_UT_create_hier_matrices( FLA_Obj A_flat, dim_t depth, dim_t* b_flash,
                                       FLA_Obj* A, FLA_Obj* TW );
\end{verbatim}
\index{FLASH functions!\flashlqutcreatehiermatricesns}
\purpose{
Create a hierarchical matrix $ A $ conformal to a flat matrix $ A_{flat} $ and
then copy the contents of $ A_{flat} $ into $ A $.
The hierarchy of $ A $ is specified by the depth and square blocksize values
in \depth and \bflashns, respectively.
Also, create hierarchical matrix object $ TW $ with
proper datatype, dimensions, and hierarchy relative to $ A $ so that the
objects may be used together with \flashlqut and \flashapplyqutns.
%Unlike with \flashlqutinccreatehiermatricesns, the algorithmic blocksize
%specified by \balg must equal the storage blocksize, \bflashns.
%Once created, $ A $ and $ TW $ may be freed normally via
%\flashobjfreens.
}
\notes{
This function is provided as a convenience to users of \flashlqut so they
do not need to worry about creating the auxiliary $ TW $ matrix object with the
correct properties.
}
\begin{checks}
\checkitem
The numerical datatype of $ A_{flat} $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
$ A_{flat} $ must be square.
\itemvsp
\checkitem
The pointer arguments \bflashns, {\tt A}, and {\tt TW} must not be \fnullns.
\itemvsp
\checkitem
Each of the first \depth values in \bflash must be greater than zero.
\end{checks}
\caveats{
Currently, this function only supports hierarchical depths of exactly 1.
}
\begin{params}
\parameter{\flaobj}{A\_flat}{An \flaobj representing matrix $ A_{flat} $.}
\parameter{\dimt}{depth}{The number of levels to create in the matrix hierarchies of $ A $ and $ TW $.}
\parameter{\dimtp}{b\_flash}{A pointer to an array of \depth values to be used as blocksizes in creating the matrix hierarchies of $ A $ and $ TW $.}
\parminout{\flaobjp}{A}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj to represent matrix $ A $, conformal to and initialized with the contents of $ A_{flat} $.}
\parminout{\flaobjp}{TW}{A pointer to an uninitialized \flaobjns.}
                        {A pointer to a new hierarchical \flaobj to represent matrix $ TW $.}
\end{params}
\end{flaspec}

% --- FLASH_CAQR_UT_inc_create_hier_matrices() ---------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_CAQR_UT_inc_create_hier_matrices( dim_t p, FLA_Obj A_flat, dim_t depth,
                                             dim_t* b_flash, dim_t b_alg, FLA_Obj* A,
                                             FLA_Obj* ATW, FLA_Obj* R, FLA_Obj* RTW );
\end{verbatim}
\index{FLASH functions!\flashcaqrutinccreatehiermatricesns}
\purpose{
Create hierarchical matrices $ A $ and $ R $ conformal to a flat matrix
$ A_{flat} $ and then copy the contents of $ A_{flat} $ into $ A $.
The hierarchy of $ A $ is specified by the depth and square blocksize values
in \depth and \bflashns, respectively.
Also, create hierarchical matrix objects $ ATW $ and $ RTW $ with
proper datatype, dimensions, and hierarchy relative to $ A $ and $ R $ so that
the objects may be used together with \flashcaqrutincns.% and \flashapplycaqutincns.
If \balg is greater than zero, it is used as the the length of the
storage blocks in $ ATW $ and $ RTW $, which determines the algorithmic
blocksize used in \flashcaqrutincns.
If \balg is zero, the length of the storage blocks in $ ATW $ and $ RTW $ are
set to a reasonable default value.
Once created, $ A $, $ ATW $, $ R $, and $ RTW $ may be freed normally via
\flashobjfreens.
}
\notes{
This function is provided as a convenience to users of \flashcaqrutinc so they
do not need to worry about creating the auxiliary $ ATW $, $ R $, $ RTW $
matrix object with the correct properties.
}
\begin{checks}
\checkitem
The numerical datatype of $ A_{flat} $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
The pointer arguments \bflashns, {\tt A}, {\tt ATW}, {\tt R}, and {\tt RTW}
must not be \fnullns.
\itemvsp
\checkitem
Each of the first \depth values in \bflash must be greater than zero.
\end{checks}
\caveats{
Currently, this function only supports hierarchical depths of exactly 1.
}
\begin{params}
\parameter{\flaobj}{A\_flat}{An \flaobj representing matrix $ A_{flat} $.}
\parameter{\dimt}{depth}{The number of levels to create in the matrix hierarchies of $ A $, $ ATW $, $ R $, and $ RTW $.}
\parameter{\dimtp}{b\_flash}{A pointer to an array of \depth values to be used as blocksizes in creating the matrix hierarchies of $ A $, $ ATW $, $ R $, and $ RTW $.}
\parameter{\dimt}{b\_alg}{The value to be used as the length of the storage blocks in $ ATW $ and $ RTW $ (ie: the number of rows in the leaves of their hierachies), which determines the algorithmic blocksize used in \flashcaqrutincns, or zero if the user wishes to use a default value.}
\parminout{\flaobjp}{A}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj to represent matrix $ A $, conformal to and initialized with the contents of $ A_{flat} $.}
\parminout{\flaobjp}{ATW}{A pointer to an uninitialized \flaobjns.}
                         {A pointer to a new hierarchical \flaobj to represent matrix $ ATW $.}
\parminout{\flaobjp}{R}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj to represent matrix $ R $.}
\parminout{\flaobjp}{RTW}{A pointer to an uninitialized \flaobjns.}
                         {A pointer to a new hierarchical \flaobj to represent matrix $ RTW $.}
\end{params}
\end{flaspec}

% --- FLASH_UDdate_UT_inc_create_hier_matrices() -------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_UDdate_UT_inc_create_hier_matrices( FLA_Obj R_flat, FLA_Obj C_flat, FLA_Obj D_flat,
                                               dim_t depth, dim_t* b_flash, dim_t b_alg,
                                               FLA_Obj* R, FLA_Obj* C, FLA_Obj* D,
                                               FLA_Obj* T, FLA_Obj* W );
\end{verbatim}
\index{FLASH functions!\flashuddateutinccreatehiermatricesns}
\purpose{
Create hierarchical matrices $ R $, $ C $, and $ D $ conformal to a flat
matrices $ R_{flat} $, $ C_{flat} $, and $ D_{flat} $, respectively,
then copy the contents of the former into the latter.
The hierarchies of $ R $, $ C $, and $ D $ are specified by the depth and
square blocksize values in \depth and \bflashns, respectively.
Also, create hierarchical matrix objects $ T $ and $ W $ with
proper datatype, dimensions, and hierarchy relative to $ R $, $ C $, and $ D $
so that the objects may be used together with \flashuddateutinc and
\flashapplyqudutincns.
If \balg is greater than zero, it is used as the the length of the
storage blocks in $ T $ and $ W $, which determines the algorithmic blocksize
used in \flashuddateutincns.
If \balg is zero, the length of the storage blocks in $ T $ and $ W $ are set
to a reasonable default value.
Once created, $ R $, $ C $, $ D $, $ T $ and $ W $ may be freed normally via
\flashobjfreens.
}
\notes{
This function is provided as a convenience to users of \flashuddateutinc so they
do not need to worry about creating the auxiliary $ T $ and $ W $ matrix objects
with the correct properties.
}
\begin{checks}
\checkitem
The numerical datatypes of $ R_{flat} $, $ C_{flat} $, and $ D_{flat} $ must be
identical and floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The pointer arguments \bflashns, {\tt R}, {\tt C}, {\tt D}, {\tt T}, and {\tt W}
must not be \fnullns.
\itemvsp
\checkitem
Each of the first \depth values in \bflash must be greater than zero.
\end{checks}
\caveats{
Currently, this function only supports hierarchical depths of exactly 1.
}
\begin{params}
\parameter{\flaobj}{R\_flat}{An \flaobj representing matrix $ R_{flat} $.}
\parameter{\flaobj}{C\_flat}{An \flaobj representing matrix $ C_{flat} $.}
\parameter{\flaobj}{D\_flat}{An \flaobj representing matrix $ D_{flat} $.}
\parameter{\dimt}{depth}{The number of levels to create in the matrix hierarchies of $ A $ and $ TW $.}
\parameter{\dimtp}{b\_flash}{A pointer to an array of \depth values to be used as blocksizes in creating the matrix hierarchies of $ A $ and $ TW $.}
\parameter{\dimt}{b\_alg}{The value to be used as the length of the storage blocks in $ TW $ (ie: the number of rows in the leaves of $ TW $), which determines the algorithmic blocksize used in \flashqrutinc and \flashapplyqutincns, or zero if the user wishes to use a default value.}
\parminout{\flaobjp}{R}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj to represent matrix $ R $, conformal to and initialized with the contents of $ R_{flat} $.}
\parminout{\flaobjp}{C}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj to represent matrix $ C $, conformal to and initialized with the contents of $ C_{flat} $.}
\parminout{\flaobjp}{D}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj to represent matrix $ D $, conformal to and initialized with the contents of $ D_{flat} $.}
\parminout{\flaobjp}{T}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj to represent matrix $ T $.}
\parminout{\flaobjp}{W}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj to represent matrix $ W $.}
\end{params}
\end{flaspec}

% --- FLASH_Apply_Q_UT_inc_create_workspace() ----------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Apply_Q_UT_inc_create_workspace( FLA_Obj TW, FLA_Obj B, FLA_Obj* W );
\end{verbatim}
\index{FLASH functions!\flashapplyqutinccreateworkspacens}
\purpose{
Create a hierarchical workspace matrix $ W $ needed when applying $ Q $ or
$ Q^H $ to $ B $ via \flashapplyqutincns.
Once created, $ W $ may be freed normally via \flashobjfreens.
}
\notes{
This function is provided as a convenience to users of \flashapplyqutinc so they
do not need to worry about creating the workspace matrix object $ W $ with the
correct properties.
}
\begin{checks}
\checkitem
The numerical datatype of $ TW $ and $ B $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The pointer argument {\tt W} must not be \fnullns.
\end{checks}
\caveats{
Currently, this function only supports hierarchical depths of exactly 1.
}
\begin{params}
\parameter{\flaobj}{TW}{A hierarchical \flaobj representing matrix $ TW $.}
\parameter{\flaobj}{B}{A hierarchical \flaobj representing matrix $ B $.}
\parminout{\flaobjp}{W}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj to represent matrix $ W $.}
\end{params}
\end{flaspec}

% --- FLASH_Apply_QUD_UT_inc_create_workspace() --------------------------------

\begin{flaspec}
\begin{verbatim}
void FLASH_Apply_QUD_UT_inc_create_workspace( FLA_Obj T, FLA_Obj R, FLA_Obj* W );
\end{verbatim}
\index{FLASH functions!\flashapplyqudutinccreateworkspacens}
\purpose{
Create a hierarchical workspace matrix $ W $ needed when applying $ Q^H $
to $ R $, $ C $, and $ D $ via \flashapplyqudutincns.
Once created, $ W $ may be freed normally via \flashobjfreens.
}
\notes{
This function is provided as a convenience to users of \flashapplyqudutinc so
they do not need to worry about creating the workspace matrix object $ W $
with the correct properties.
}
\begin{checks}
\checkitem
The numerical datatypes of $ T $ and $ R $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The pointer argument {\tt W} must not be \fnullns.
\end{checks}
\caveats{
Currently, this function only supports hierarchical depths of exactly 1.
}
\begin{params}
\parameter{\flaobj}{T}{A hierarchical \flaobj representing matrix $ T $.}
\parameter{\flaobj}{R}{A hierarchical \flaobj representing matrix $ R $.}
\parminout{\flaobjp}{W}{A pointer to an uninitialized \flaobjns.}
                       {A pointer to a new hierarchical \flaobj to represent matrix $ W $.}
\end{params}
\end{flaspec}











\section{External wrappers}

This section documents the wrapper interfaces to the external implementations
of all operations supported within \libflamens.
We refer to these interfaces as {\em wrappers} because they wrap
the less aesthetically pleasing Fortran-77 interfaces of the BLAS and LAPACK
with easy-to-use functions that operate upon \libflame objects.
Furthermore, we refer to them as interfacing to {\em external} code because
they interface to implementations that reside outside of \libflamens.
Usually, these external implementations are provided by a separate BLAS and
LAPACK library at link-time.
However, they could be provided by some other source.
The user may even request, at configure-time, that \libflame be built to include
basic netlib implementations of all LAPACK-level operations supported within
the library.
The only requirement is that the external implementation adhere to the original
Fortran-77 BLAS or LAPACK interface.




\subsection{BLAS operations}




\subsubsection{Level-1 BLAS}


% --- FLA_Amax_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Amax_external( FLA_Obj x, FLA_Obj i );
\end{verbatim}
\index{FLAME/C functions!\flaamaxextns}
\purpose{
Find the index $ i $ of the element of $ x $ which has the maximum
absolute value, where $ x $ is a general vector and $ i $ is a scalar.
If the maximum absolute value is shared by more than one element, then
the element whose index is highest is chosen.
}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\amaxns.
}
\moreinfo{
This function is similar to that of \flaamaxns.
Please see the description for \flaamax for further details.
}
\end{flaspec}

% --- FLA_Asum_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Asum_external( FLA_Obj x, FLA_Obj norm1 );
\end{verbatim}
\index{FLAME/C functions!\flaasumextns}
\purpose{
Compute the 1-norm of a vector:
\begin{eqnarray*}
\|x\|_1 & := &  \sum_{i=0}^{n-1} |\chi_i|
\end{eqnarray*}
where $ \|x\|_1 $ is a scalar and $ \chi_{i} $ is the $ i $th element of
general vector $ x $ of length $ n $.
Upon completion, the 1-norm $ \|x\|_1 $ is stored to \normons.
}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\asumns.
}
\moreinfo{
This function is similar to that of \flaasumns.
Please see the description for \flaasum for further details.
}
\end{flaspec}

% --- FLA_Axpy_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Axpy_external( FLA_Obj alpha, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaaxpyextns}
\purpose{
Perform an {\sc axpy} operation:
\begin{eqnarray*}
B & := & B + \alpha A
\end{eqnarray*}
where $ \alpha $ is a scalar, and $ A $ and $ B $ are general matrices.
}
\notes{
If $ A $ and $ B $ are vectors, \flaaxpyext will implicitly and
automatically perform the transposition necessary to achieve conformal
dimensions.
}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\axpyns.
}
\moreinfo{
This function is similar to that of \flaaxpyns.
Please see the description for \flaaxpy for further details.
}
\end{flaspec}

% --- FLA_Axpyt_external() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Axpyt_external( FLA_Trans trans, FLA_Obj alpha, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaaxpytextns}
\purpose{
Perform one of the following extended {\sc axpy} operations:
\begin{eqnarray*}
B & := & B + \alpha A \\
B & := & B + \alpha A^T \\
B & := & B + \alpha \bar{A} \\
B & := & B + \alpha A^H
\end{eqnarray*}
where $ \alpha $ is a scalar, and $ A $ and $ B $ are general matrices.
The \trans argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
}
\notes{
If $ A $ and $ B $ are vectors, \flaaxpytext will implicitly and
automatically perform the transposition necessary to achieve conformal
dimensions regardless of the value of \transns.
}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\axpyns.
}
\moreinfo{
This function is similar to that of \flaaxpytns.
Please see the description for \flaaxpyt for further details.
}
\end{flaspec}

% --- FLA_Axpyrt_external() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Axpyrt_external( FLA_Uplo uplo, FLA_Trans trans, FLA_Obj alpha, FLA_Obj A,
                          FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaaxpyrtextns}
\purpose{
Perform one of the following extended {\sc axpy} operations:
\begin{eqnarray*}
B & := & B + \alpha A        \\
B & := & B + \alpha A^T      \\
B & := & B + \alpha \bar{A}  \\
B & := & B + \alpha A^H
\end{eqnarray*}
where $ A $ and $ B $ are triangular (or trapezoidal) matrices.
The \uplo argument indicates whether the lower or upper triangle of $ B $
is updated by the operation.
The \trans argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
Note that the \uplo and \trans arguments together determine which triangle
of $ A $ is read and which triangle of $ B $ is updated.
}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\axpyns.
}
\moreinfo{
This function is similar to that of \flaaxpyrtns.
Please see the description for \flaaxpyrt for further details.
}
\end{flaspec}

% --- FLA_Axpys_external() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Axpys_external( FLA_Obj alpha0, FLA_Obj alpha1, FLA_Obj A,
                         FLA_Obj beta, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaaxpysextns}
\purpose{
Perform the following extended {\sc axpy} operation:
\begin{eqnarray*}
B & := & \beta B + \alpha_0 \alpha_1 A
\end{eqnarray*}
where $ \alpha_0 $, $ \alpha_1 $ and $ \beta $ are scalars, and $ A $ and $ B $
are general matrices.
}
\notes{
If $ A $ and $ B $ are vectors, \flaaxpysext will implicitly and
automatically perform the transposition necessary to achieve conformal
dimensions.
}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\axpyns.
}
\moreinfo{
This function is similar to that of \flaaxpysns.
Please see the description for \flaaxpys for further details.
}
\end{flaspec}

% --- FLA_Copy_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Copy_external( FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flacopyextns}
\purpose{
Copy the numerical contents of $ A $ to $ B $:
\begin{eqnarray*}
B & := & A
\end{eqnarray*}
where $ A $ and $ B $ are general matrices.
}
\notes{
If $ A $ and $ B $ are vectors, \flacopyext will implicitly and
automatically perform the transposition necessary to achieve conformal
dimensions.
}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\copyxns.
}
\moreinfo{
This function is similar to that of \flacopyns.
Please see the description for \flacopy for further details.
}
\end{flaspec}

% --- FLA_Copyr_external() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Copyr_external( FLA_Uplo uplo, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flacopyrextns}
\purpose{
Perform an extended copy operation on the lower or upper triangles of
matrices $ A $ and $ B $:
\begin{eqnarray*}
B & := & A
\end{eqnarray*}
where $ A $ and $ B $ are triangular (or trapezoidal) matrices.
The \uplo argument indicates whether the lower or upper triangles of $ A $
and $ B $ are referenced and updated by the operation.
}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\copyxns.
}
\moreinfo{
This function is similar to that of \flacopyrns.
Please see the description for \flacopyr for further details.
}
\end{flaspec}

% --- FLA_Copyrt_external() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Copyrt_external( FLA_Uplo uplo, FLA_Trans trans, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flacopyrtextns}
\purpose{
Perform an extended copy operation on triangular matrices $ A $ and $ B $:
\begin{eqnarray*}
B & := & A        \\
B & := & A^T      \\
B & := & \bar{A}  \\
B & := & A^H
\end{eqnarray*}
where $ A $ and $ B $ are triangular (or trapezoidal) matrices.
The \uplo argument indicates whether the lower or upper triangle of $ B $
is updated by the operation.
The \trans argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
Note that the \uplo and \trans arguments together determine which triangle
of $ A $ is read and which triangle of $ B $ is overwritten.
}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\copyxns.
}
\moreinfo{
This function is similar to that of \flacopyrtns.
Please see the description for \flacopyrt for further details.
}
\end{flaspec}

% --- FLA_Copyt_external() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Copyt_external( FLA_Trans trans, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flacopytextns}
\purpose{
Copy the numerical contents of $ A $ to $ B $ with one of the following
extended operations:
\begin{eqnarray*}
B & := & A \\
B & := & A^T \\
B & := & \bar{A} \\
B & := & A^H
\end{eqnarray*}
where $ A $ and $ B $ are general matrices.
The \trans argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
}
\notes{
If $ A $ and $ B $ are vectors, \flacopytext will implicitly and
automatically perform the transposition necessary to achieve conformal
dimensions regardless of the value of \transns:
}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\copyxns.
}
\moreinfo{
This function is similar to that of \flacopytns.
Please see the description for \flacopyt for further details.
}
\end{flaspec}

% --- FLA_Dot_external() -------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Dot_external( FLA_Obj x, FLA_Obj y, FLA_Obj rho );
\end{verbatim}
\index{FLAME/C functions!\fladotextns}
\purpose{
Perform a dot (inner) product operation between two vectors:
\begin{eqnarray*}
\rho := \sum_{i=0}^{n-1} \chi_i \psi_i
\end{eqnarray*}
where $ \rho $ is a scalar, and $ \chi_i $ and $ \psi_i $ are the $ i $th
elements of general vectors $ x $ and $ y $, respectively, where both vectors
are of length $ n $.
Upon completion, the dot product $ \rho $ is stored to \frhons.
}
\implnotes{
This function uses external implementations of the level-1 BLAS routines
\dotx and \dotuns.
}
\moreinfo{
This function is similar to that of \fladotns.
Please see the description for \fladot for further details.
}
\end{flaspec}

% --- FLA_Dotc_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Dotc_external( FLA_Conj conj, FLA_Obj x, FLA_Obj y, FLA_Obj rho );
\end{verbatim}
\index{FLAME/C functions!\fladotcextns}
\purpose{
Perform one of the following extended dot product operations:
\begin{eqnarray*}
\rho := \sum_{i=0}^{n-1} \chi_i \psi_i \\
\rho := \sum_{i=0}^{n-1} \bar{\chi_i} \psi_i
\end{eqnarray*}
where $ \rho $ is a scalar, and $ \chi_i $ and $ \psi_i $ are the $ i $th
elements of general vectors $ x $ and $ y $, respectively, where both vectors
are of length $ n $.
Upon completion, the dot product $ \rho $ is stored to \frhons.
The \conj argument allows the computation to proceed as if $ x $ were
conjugated.
}
\notes{
If $ x $, $ y $, and $ \rho $ are real, the value of \conj is ignored and
\fladotcext behaves exactly as \fladotextns.
}
\implnotes{
This function uses external implementations of the level-1 BLAS routines
\dotxns, \dotuns, and \dotcns.
}
\moreinfo{
This function is similar to that of \fladotcns.
Please see the description for \fladotc for further details.
}
\end{flaspec}

% --- FLA_Dots_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Dots_external( FLA_Obj alpha, FLA_Obj x, FLA_Obj y,
                        FLA_Obj beta, FLA_Obj rho );
\end{verbatim}
\index{FLAME/C functions!\fladotsextns}
\purpose{
Perform the following extended dot product operation between two vectors:
\begin{eqnarray*}
\rho := \beta \rho + \alpha \sum_{i=0}^{n-1} \chi_i \psi_i
\end{eqnarray*}
where $ \alpha $, $ \beta $, and $ \rho $ are scalars, and $ \chi_i $ and
$ \psi_i $ are the $ i $th elements of general vectors $ x $ and $ y $,
respectively, where both vectors are of length $ n $.
Upon completion, the dot product $ \rho $ is stored to \frhons.
}
\implnotes{
This function uses external implementations of the level-1 BLAS routines
\dotx and \dotuns.
}
\moreinfo{
This function is similar to that of \fladotsns.
Please see the description for \fladots for further details.
}
\end{flaspec}

% --- FLA_Dotcs_external() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Dotcs_external( FLA_Conj conj, FLA_Obj alpha, FLA_Obj x, FLA_Obj y,
                         FLA_Obj beta, FLA_Obj rho );
\end{verbatim}
\index{FLAME/C functions!\fladotcsextns}
\purpose{
Perform one of the following extended dot product operations between two
vectors:
\begin{eqnarray*}
\rho := \beta \rho + \alpha \sum_{i=0}^{n-1} \chi_i \psi_i \\
\rho := \beta \rho + \alpha \sum_{i=0}^{n-1} \bar{\chi_i} \psi_i
\end{eqnarray*}
where $ \alpha $, $ \beta $, and $ \rho $ are scalars, and $ \chi_i $ and
$ \psi_i $ are the $ i $th elements of general vectors $ x $ and $ y $,
respectively, where both vectors are of length $ n $.
Upon completion, the dot product $ \rho $ is stored to \frhons.
The \conj argument allows the computation to proceed as if $ x $ were
conjugated.
}
\notes{
If $ x $, $ y $, and $ \rho $ are real, the value of \conj is ignored and
\fladotcsext behaves exactly as \fladotsextns.
}
\implnotes{
This function uses external implementations of the level-1 BLAS routines
\dotxns, \dotuns, and \dotcns.
}
\moreinfo{
This function is similar to that of \fladotcsns.
Please see the description for \fladotcs for further details.
}
\end{flaspec}

% --- FLA_Dot2s_external() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Dot2s_external( FLA_Obj alpha, FLA_Obj x, FLA_Obj y, FLA_Obj beta, FLA_Obj rho );
\end{verbatim}
\index{FLAME/C functions!\fladottsextns}
\purpose{
Perform the following extended dot product operation between two vectors:
\begin{eqnarray*}
\rho := \beta \rho + \alpha \sum_{i=0}^{n-1} \chi_i \psi_i + \bar{\alpha} \sum_{i=0}^{n-1} \chi_i \psi_i
\end{eqnarray*}
where $ \alpha $, $ \beta $, and $ \rho $ are scalars, and $ \chi_i $ and
$ \psi_i $ are the $ i $th elements of general vectors $ x $ and $ y $,
respectively, where both vectors are of length $ n $.
Upon completion, the dot product $ \rho $ is stored to \frhons.
}
\notes{
Though this operation may be reduced to:
\begin{eqnarray*}
\rho := \beta \rho + \left( \alpha + \bar{\alpha} \right) \sum_{i=0}^{n-1} \chi_i \psi_i
\end{eqnarray*}
it is expressed above in unreduced form to allow a more clear contrast to
\fladottcsextns.
}
\implnotes{
This function uses external implementations of the level-1 BLAS routines
\dotx and \dotuns.
}
\moreinfo{
This function is similar to that of \fladottsns.
Please see the description for \fladotts for further details.
}
\end{flaspec}

% --- FLA_Dot2cs_external() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Dot2cs_external( FLA_Conj conj, FLA_Obj alpha, FLA_Obj x, FLA_Obj y,
                          FLA_Obj beta, FLA_Obj rho );
\end{verbatim}
\index{FLAME/C functions!\fladottcsextns}
\purpose{
Perform one of the following extended dot product operations between two
vectors:
\begin{eqnarray*}
\rho := \beta \rho + \alpha \sum_{i=0}^{n-1} \chi_i \psi_i + \bar{\alpha} \sum_{i=0}^{n-1} \chi_i \psi_i \\
\rho := \beta \rho + \alpha \sum_{i=0}^{n-1} \bar{\chi_i} \psi_i + \bar{\alpha} \sum_{i=0}^{n-1} \bar{\psi_i} \chi_i
\end{eqnarray*}
where $ \alpha $, $ \beta $, and $ \rho $ are scalars, and $ \chi_i $ and
$ \psi_i $ are the $ i $th elements of general vectors $ x $ and $ y $,
respectively, where both vectors are of length $ n $.
Upon completion, the dot product $ \rho $ is stored to \frhons.
The \conj argument allows the computation to proceed as if $ x $ were
conjugated.
}
\notes{
If $ x $, $ y $, and $ \rho $ are real, the value of \conj is ignored and
\fladottcsext behaves exactly as \fladottsextns.
}
\implnotes{
This function uses external implementations of the level-1 BLAS routines
\dotxns, \dotuns, and \dotcns.
}
\moreinfo{
This function is similar to that of \fladottcsns.
Please see the description for \fladottcs for further details.
}
\end{flaspec}

% --- FLA_Inv_scal_external() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Inv_scal_external( FLA_Obj alpha, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flainvscalextns}
\purpose{
Perform an inverse scaling operation:
\begin{eqnarray*}
A & := & \alpha^{-1} A
\end{eqnarray*}
where $ \alpha $ is a scalar and $ A $ is a general matrix.
}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\scalns.
}
\moreinfo{
This function is similar to that of \flainvscalns.
Please see the description for \flainvscal for further details.
}
\end{flaspec}

% --- FLA_Inv_scalc_external() -------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Inv_scalc_external( FLA_Conj conjalpha, FLA_Obj alpha, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flainvscalcextns}
\purpose{
Perform one of the following extended inverse scaling operations:
\begin{eqnarray*}
A & := & \alpha^{-1} A \\
A & := & \bar{\alpha}^{-1} A
\end{eqnarray*}
where $ \alpha $ is a scalar and $ A $ is a general matrix.
The \conjalpha argument allows the computation to proceed as if $ \alpha $
were conjugated.
}
\notes{
If $ \alpha $ is real, the value of \conjalpha is ignored and \flainvscalcext
behaves exactly as \flainvscalextns.
}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\scalns.
}
\moreinfo{
This function is similar to that of \flainvscalcns.
Please see the description for \flainvscalc for further details.
}
\end{flaspec}

% --- FLA_Nrm2_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Nrm2_external( FLA_Obj x, FLA_Obj norm );
\end{verbatim}
\index{FLAME/C functions!\flanrmtextns}
\purpose{
Compute the 2-norm of a vector:
\begin{eqnarray*}
\|x\|_2 & := &  \left( \sum_{i=0}^{n-1} |\chi_i|^2 \right)^{\frac{1}{2}}
\end{eqnarray*}
where $ \|x\|_2 $ is a scalar and $ \chi_i $ is the $ i $th element of
general vector $ x $ of length $ n $.
Upon completion, the 2-norm $ \|x\|_2 $ is stored to \normns.
}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\nrmtns.
}
\moreinfo{
This function is similar to that of \flanrmtns.
Please see the description for \flanrmt for further details.
}
\end{flaspec}

% --- FLA_Scal_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Scal_external( FLA_Obj alpha, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flascalextns}
\purpose{
Perform a scaling operation:
\begin{eqnarray*}
A & := & \alpha A
\end{eqnarray*}
where $ \alpha $ is a scalar and $ A $ is a general matrix.
}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\scalns.
}
\moreinfo{
This function is similar to that of \flascalns.
Please see the description for \flascal for further details.
}
\end{flaspec}

% --- FLA_Scalc_external() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Scalc_external( FLA_Conj conjalpha, FLA_Obj alpha, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flascalcextns}
\purpose{
Perform one of the following extended scaling operations:
\begin{eqnarray*}
A & := & \alpha A \\
A & := & \bar{\alpha} A
\end{eqnarray*}
where $ \alpha $ is a scalar and $ A $ is a general matrix.
The \conjalpha argument allows the computation to proceed as if $ \alpha $
were conjugated.
}
\notes{
If $ \alpha $ is real, the value of \conjalpha is ignored and \flascalcext
behaves exactly as \flascalextns.
}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\scalns.
}
\moreinfo{
This function is similar to that of \flascalcns.
Please see the description for \flascalc for further details.
}
\end{flaspec}

% --- FLA_Scalr_external() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Scalr_external( FLA_Uplo uplo, FLA_Obj alpha, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flascalrextns}
\purpose{
Perform an extended scaling operation on the lower or upper triangle of a
matrix:
\begin{eqnarray*}
A & := & \alpha A
\end{eqnarray*}
where $ \alpha $ is a scalar and $ A $ is a general square matrix.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced and updated by the operation.
}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\scalns.
}
\moreinfo{
This function is similar to that of \flascalrns.
Please see the description for \flascalr for further details.
}
\end{flaspec}

% --- FLA_Swap_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Swap_external( FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaswapextns}
\purpose{
Swap the contents of two general matrices $ A $ and $ B $.
}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\swapns.
}
\moreinfo{
This function is similar to that of \flaswapns.
Please see the description for \flaswap for further details.
}
\end{flaspec}

% --- FLA_Swapt_external() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Swapt_external( FLA_Trans transab, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaswaptextns}
\purpose{
Swap the contents of two general matrices $ A $ and $ B $.
If \transab is \flatranspose or \flaconjtransposens, the computation proceeds
as if only $ A $ (or only $ B $) were transposed.
Furthermore, if \transab is \flaconjnotranspose or \flaconjtransposens, both
$ A $ and $ B $ are conjugated after their contents are swapped.
}
\implnotes{
This function uses an external implementation of the level-1 BLAS routine
\swapns.
}
\moreinfo{
This function is similar to that of \flaswaptns.
Please see the description for \flaswapt for further details.
}
\end{flaspec}





\subsubsection{Level-2 BLAS}



% --- FLA_Gemv_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Gemv_external( FLA_Trans transa, FLA_Obj alpha, FLA_Obj A, FLA_Obj x, 
                        FLA_Obj beta, FLA_Obj y ); 
\end{verbatim}
\index{FLAME/C functions!\flagemvextns}
\purpose{
Perform one of the following general matrix-vector multiplication operations:
\begin{eqnarray*}
y & := & \beta y + \alpha A x \\
y & := & \beta y + \alpha A^T x \\
y & := & \beta y + \alpha \bar{A} x \\
y & := & \beta y + \alpha A^H x
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a general matrix, and
$ x $ and $ y $ are general vectors.
The \trans argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
}
\notes{
The above matrix-vector operations implicitly assume $ x $ and $ y $ to be
column vectors.
However, since transposing a vector does not change the way its elements are
accessed, we may also express the above operations as:
\begin{eqnarray*}
y_r & := & \beta y_r + \alpha x_r A^T \\
y_r & := & \beta y_r + \alpha x_r A \\
y_r & := & \beta y_r + \alpha x_r A^H \\
y_r & := & \beta y_r + \alpha x_r \bar{A}
\end{eqnarray*}
respectively, where $ x_r $ and $ y_r $ are row vectors.
}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\gemvns.
}
\moreinfo{
This function is similar to that of \flagemvns.
Please see the description for \flagemv for further details.
}
\end{flaspec}

% --- FLA_Gemvc_external() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Gemvc_external( FLA_Trans transa, FLA_Conj conjx, FLA_Obj alpha,
                         FLA_Obj A, FLA_Obj x, FLA_Obj beta, FLA_Obj y ); 
\end{verbatim}
\index{FLAME/C functions!\flagemvcextns}
\purpose{
Perform one of the following extended general matrix-vector multiplication
operations:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
y & := & \beta y + \alpha A x       & \hsp & y & := & \beta y + \alpha A \bar{x} \\[0.05in]
y & := & \beta y + \alpha A^T x     & \hsp & y & := & \beta y + \alpha A^T \bar{x} \\[0.05in]
y & := & \beta y + \alpha \bar{A} x & \hsp & y & := & \beta y + \alpha \bar{A} \bar{x} \\[0.05in]
y & := & \beta y + \alpha A^H x     & \hsp & y & := & \beta y + \alpha A^H \bar{x}
\end{array}
\end{math}
\end{center}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a general matrix, and
$ x $ and $ y $ are general vectors.
The \trans argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
Likewise, the \conjx argument allows the computation to proceed as if $ x $
were conjugated.
}
\notes{
The above matrix-vector operations implicitly assume $ x $ and $ y $ to be
column vectors.
However, since transposing a vector does not change the way its elements are
accessed, we may also express the above operations as:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
y_r & := & \beta y_r + \alpha x_r A^T     & \hsp & y_r & := & \beta y_r + \alpha \bar{x_r} A^T \\[0.05in]
y_r & := & \beta y_r + \alpha x_r A       & \hsp & y_r & := & \beta y_r + \alpha \bar{x_r} A \\[0.05in]
y_r & := & \beta y_r + \alpha x_r A^H     & \hsp & y_r & := & \beta y_r + \alpha \bar{x_r} A^H \\[0.05in]
y_r & := & \beta y_r + \alpha x_r \bar{A} & \hsp & y_r & := & \beta y_r + \alpha \bar{x_r} \bar{A}
\end{array}
\end{math}
\end{center}
respectively, where $ x_r $ and $ y_r $ are row vectors. \\
If $ A $, $ x $, and $ y $ are real, the value of \conjx is ignored and
\flagemvcext behaves exactly as \flagemvextns.
}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\gemvns.
}
\moreinfo{
This function is similar to that of \flagemvcns.
Please see the description for \flagemvc for further details.
}
\end{flaspec}

% --- FLA_Ger_external() -------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Ger_external( FLA_Obj alpha, FLA_Obj x, FLA_Obj y, FLA_Obj A ); 
\end{verbatim}
\index{FLAME/C functions!\flagerextns}
\purpose{
Perform a general rank-1 update:
\begin{eqnarray*}
A & := & A + \alpha x y^T
\end{eqnarray*}
where $ \alpha $ is a scalar, $ A $ is a general matrix, and
$ x $ and $ y $ are general vectors.
}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\gerns.
}
\moreinfo{
This function is similar to that of \flagerns.
Please see the description for \flager for further details.
}
\end{flaspec}

% --- FLA_Gerc_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Gerc_external( FLA_Conj conjx, FLA_Conj conjy, FLA_Obj alpha,
                        FLA_Obj x, FLA_Obj y, FLA_Obj A ); 
\end{verbatim}
\index{FLAME/C functions!\flagercextns}
\purpose{
Perform one of the following extended general rank-1 updates:
\begin{eqnarray*}
A & := & A + \alpha x y^T \\
A & := & A + \alpha x \bar{y}^T \\
A & := & A + \alpha \bar{x} y^T \\
A & := & A + \alpha \bar{x} \bar{y}^T
\end{eqnarray*}
where $ \alpha $ is a scalar, $ A $ is a general matrix, and
$ x $ and $ y $ are general vectors.
The \conjx and \conjy arguments allow the computation to proceed as if $ x $
and/or $ y $ were conjugated.
}
\notes{
If $ A $, $ x $, and $ y $ are real, the values of \conjx and \conjy are
ignored and \flagercext behaves exactly as \flagerextns.
}
\implnotes{
This function uses external implementations of the level-3 BLAS routines
\gerns, \geruns, and \gercns.
}
\moreinfo{
This function is similar to that of \flagercns.
Please see the description for \flagerc for further details.
}
\end{flaspec}

% --- FLA_Hemv_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Hemv_external( FLA_Uplo uplo, FLA_Obj alpha, FLA_Obj A, FLA_Obj x, 
                        FLA_Obj beta, FLA_Obj y ); 
\end{verbatim}
\index{FLAME/C functions!\flahemvextns}
\purpose{
Perform a Hermitian matrix-vector multiplication ({\sc hemv}) operation:
\begin{eqnarray*}
y & := & \beta y + \alpha A x
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a Hermitian
matrix, and $ x $ and $ y $ are general vectors.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
}
\notes{
When invoked with real objects, this function performs the {\sc symv}
operation.
}
\implnotes{
This function uses external implementations of the level-3 BLAS routines
\hemv and \symvns.
}
\moreinfo{
This function is similar to that of \flahemvns.
Please see the description for \flahemv for further details.
}
\end{flaspec}

% --- FLA_Hemvc_external() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Hemvc_external( FLA_Uplo uplo, FLA_Conj conj, FLA_Obj alpha,
                         FLA_Obj A, FLA_Obj x, FLA_Obj beta, FLA_Obj y ); 
\end{verbatim}
\index{FLAME/C functions!\flahemvcextns}
\purpose{
Perform one of the following extended Hermitian matrix-vector multiplication
({\sc hemv}) operations:
\begin{eqnarray*}
y & := & \beta y + \alpha A x \\
y & := & \beta y + \alpha \bar{A} x
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a Hermitian
matrix, and $ x $ and $ y $ are general vectors.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
The \conj argument allows the computation to proceed as if $ A $ were
conjugated.
}
\notes{
When invoked with real objects, this function performs the {\sc symv}
operation.
}
\implnotes{
This function uses external implementations of the level-3 BLAS routines
\hemv and \symvns.
}
\moreinfo{
This function is similar to that of \flahemvcns.
Please see the description for \flahemvc for further details.
}
\end{flaspec}

% --- FLA_Her_external() -------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Her_external( FLA_Uplo uplo, FLA_Obj alpha, FLA_Obj x, FLA_Obj A ); 
\end{verbatim}
\index{FLAME/C functions!\flaherextns}
\purpose{
Perform a Hermitian rank-1 update ({\sc her}) operation:
\begin{eqnarray*}
A & := & A + \alpha x x^H
\end{eqnarray*}
where $ \alpha $ is a scalar, $ A $ is a Hermitian matrix, and
$ x $ is a general vector.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced and updated by the operation.
}
\notes{
When invoked with real objects, this function performs the {\sc her}
operation.
}
\implnotes{
This function uses external implementations of the level-3 BLAS routines
\her and \syrns.
}
\moreinfo{
This function is similar to that of \flaherns.
Please see the description for \flaher for further details.
}
\end{flaspec}

% --- FLA_Herc_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Herc_external( FLA_Uplo uplo, FLA_Conj conj, FLA_Obj alpha, FLA_Obj x,
                        FLA_Obj A ); 
\end{verbatim}
\index{FLAME/C functions!\flahercextns}
\purpose{
Perform one of the following extended Hermitian rank-1 update
({\sc her}) operations:
\begin{eqnarray*}
A & := & A + \alpha x x^H \\
A & := & A + \alpha \bar{x} x^T
\end{eqnarray*}
where $ \alpha $ is a scalar, $ A $ is a Hermitian matrix, and
$ x $ is a general vector.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced and updated by the operation.
The \conj argument allows the computation of the transposed rank-1 product
$ \bar{x} x^T $.
}
\notes{
When invoked with real objects, this function performs the {\sc her}
operation.
}
\implnotes{
This function uses external implementations of the level-3 BLAS routines
\her and \syrns.
}
\moreinfo{
This function is similar to that of \flahercns.
Please see the description for \flaherc for further details.
}
\end{flaspec}

% --- FLA_Her2_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Her2_external( FLA_Uplo uplo, FLA_Obj alpha, FLA_Obj x, FLA_Obj y,
                        FLA_Obj A ); 
\end{verbatim}
\index{FLAME/C functions!\flahertextns}
\purpose{
Perform a Hermitian rank-2 update ({\sc her2}) operation:
\begin{eqnarray*}
A & := & A + \alpha x y^H + \bar{\alpha} y x^H
\end{eqnarray*}
where $ \alpha $ is a scalar, $ A $ is a Hermitian matrix, and
$ x $ and $ y $ are general vectors.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced and updated by the operation.
}
\notes{
When invoked with real objects, this function performs the {\sc her2}
operation.
}
\implnotes{
This function uses external implementations of the level-3 BLAS routines
\hert and \syrtns.
}
\moreinfo{
This function is similar to that of \flahertns.
Please see the description for \flahert for further details.
}
\end{flaspec}

% --- FLA_Her2c_external() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Her2c_external( FLA_Uplo uplo, FLA_Conj conj, FLA_Obj alpha,
                         FLA_Obj x, FLA_Obj y, FLA_Obj A ); 
\end{verbatim}
\index{FLAME/C functions!\flahertcextns}
\purpose{
Perform one of the following extended Hermitian rank-2 update
({\sc her2}) operations:
\begin{eqnarray*}
A & := & A + \alpha x y^H + \bar{\alpha} y x^H \\
A & := & A + \alpha \bar{x} y^T + \bar{\alpha} \bar{y} x^T
\end{eqnarray*}
where $ \alpha $ is a scalar, $ A $ is a Hermitian matrix, and
$ x $ and $ y $ are general vectors.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced and updated by the operation.
The \conj argument allows the computation of the transposed rank-2 products
$ \bar{x} y^T $ and $ \bar{y} x^T $.
}
\notes{
When invoked with real objects, this function performs the {\sc her2}
operation.
}
\implnotes{
This function uses external implementations of the level-3 BLAS routines
\hert and \syrtns.
}
\moreinfo{
This function is similar to that of \flahertcns.
Please see the description for \flahertc for further details.
}
\end{flaspec}

% --- FLA_Symv_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Symv_external( FLA_Uplo uplo, FLA_Obj alpha, FLA_Obj A, FLA_Obj x, 
                        FLA_Obj beta, FLA_Obj y ); 
\end{verbatim}
\index{FLAME/C functions!\flasymvextns}
\purpose{
Perform a symmetric matrix-vector multiplication ({\sc symv}) operation:
\begin{eqnarray*}
y & := & \beta y + \alpha A x
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a symmetric
matrix, and $ x $ and $ y $ are general vectors.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\symvns.
}
\moreinfo{
This function is similar to that of \flasymvns.
Please see the description for \flasymv for further details.
}
\end{flaspec}

% --- FLA_Syr_external() -------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Syr_external( FLA_Uplo uplo, FLA_Obj alpha, FLA_Obj x, FLA_Obj A ); 
\end{verbatim}
\index{FLAME/C functions!\flasyrextns}
\purpose{
Perform a symmetric rank-1 update ({\sc syr}) operation:
\begin{eqnarray*}
A & := & A + \alpha x x^T
\end{eqnarray*}
where $ \alpha $ is a scalar, $ A $ is a symmetric matrix, and
$ x $ is a general vector.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced and updated by the operation.
}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\syrns.
}
\moreinfo{
This function is similar to that of \flasyrns.
Please see the description for \flasyr for further details.
}
\end{flaspec}

% --- FLA_Syr2_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Syr2_external( FLA_Uplo uplo, FLA_Obj alpha, FLA_Obj x, FLA_Obj y,
                        FLA_Obj A ); 
\end{verbatim}
\index{FLAME/C functions!\flasyrtextns}
\purpose{
Perform a symmetric rank-2 update ({\sc syr2}) operation:
\begin{eqnarray*}
A & := & A + \alpha x y^T + \alpha y x^T
\end{eqnarray*}
where $ \alpha $ is a scalar, $ A $ is a symmetric matrix, and
$ x $ and $ y $ are general vectors.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced and updated by the operation.
}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\syrtns.
}
\moreinfo{
This function is similar to that of \flasyrtns.
Please see the description for \flasyrt for further details.
}
\end{flaspec}

% --- FLA_Trmv_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Trmv_external( FLA_Uplo uplo, FLA_Trans transa, FLA_Diag diag, FLA_Obj A,
                        FLA_Obj x );
\end{verbatim}
\index{FLAME/C functions!\flatrmvextns}
\purpose{
Perform one of the following triangular matrix-vector multiplication
({\sc trmv}) operations:
\begin{eqnarray*}
x & := & A x \\
x & := & A^T x \\
x & := & \bar{A} x \\
x & := & A^H x
\end{eqnarray*}
where $ A $ is a triangular matrix and $ x $ is a general vector.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
The \transa argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
The \diag argument indicates whether the diagonal of $ A $ is unit or
non-unit.
}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\trmvns.
}
\moreinfo{
This function is similar to that of \flatrmvns.
Please see the description for \flatrmv for further details.
}
\end{flaspec}

% --- FLA_Trmvsx_external() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Trmvsx_external( FLA_Uplo uplo, FLA_Trans transa, FLA_Diag diag, FLA_Obj alpha,
                          FLA_Obj A, FLA_Obj x, FLA_Obj beta, FLA_Obj y );
\end{verbatim}
\index{FLAME/C functions!\flatrmvsxextns}
\purpose{
Perform one of the following extended triangular matrix-vector multiplication
({\sc trmv}) operations:
\begin{eqnarray*}
y & := & \beta y + \alpha A x \\
y & := & \beta y + \alpha A^T x \\
y & := & \beta y + \alpha \bar{A} x \\
y & := & \beta y + \alpha A^H x
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a triangular matrix, and
$ x $ and $ y $ are general vectors.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
The \transa argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
The \diag argument indicates whether the diagonal of $ A $ is unit or
non-unit.
}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\trmvns.
}
\moreinfo{
This function is similar to that of \flatrmvsxns.
Please see the description for \flatrmvsx for further details.
}
\end{flaspec}

% --- FLA_Trsv_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Trsv_external( FLA_Uplo uplo, FLA_Trans transa, FLA_Diag diag, FLA_Obj A,
                        FLA_Obj b );
\end{verbatim}
\index{FLAME/C functions!\flatrsvextns}
\purpose{
Perform one of the following triangular solve ({\sc trsv}) operations:
\begin{eqnarray*}
A x       & = & b \\
A^T x     & = & b \\
\bar{A} x & = & b \\
A^H x     & = & b
\end{eqnarray*}
which, respectively, are solved by overwriting $ b $ with the contents of
the solution vector $ x $ as follows:
\begin{eqnarray*}
b & := & A^{-1} b \\
b & := & A^{-T} b \\
b & := & \bar{A}^{-1} b \\
b & := & A^{-H} b
\end{eqnarray*}
where $ A $ is a triangular matrix and $ x $ and $ b $ are general vectors.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
The \transa argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
The \diag argument indicates whether the diagonal of $ A $ is unit or
non-unit.
}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\trsvns.
}
\moreinfo{
This function is similar to that of \flatrsvns.
Please see the description for \flatrsv for further details.
}
\end{flaspec}

% --- FLA_Trsvsx_external() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Trsvsx_external( FLA_Uplo uplo, FLA_Trans transa, FLA_Diag diag, FLA_Obj alpha,
                          FLA_Obj A, FLA_Obj b, FLA_Obj beta, FLA_Obj y );
\end{verbatim}
\index{FLAME/C functions!\flatrsvsxextns}
\purpose{
Perform one of the following extended triangular solve ({\sc trsv}) operations:
\begin{eqnarray*}
y & := & \beta y + \alpha A^{-1} b \\
y & := & \beta y + \alpha A^{-T} b \\
y & := & \beta y + \alpha \bar{A}^{-1} b \\
y & := & \beta y + \alpha A^{-H} b
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a triangular matrix, and
$ b $ and $ y $ are general vectors.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
The \transa argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
The \diag argument indicates whether the diagonal of $ A $ is unit or
non-unit.
}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\trsvns.
}
\moreinfo{
This function is similar to that of \flatrsvsxns.
Please see the description for \flatrsvsx for further details.
}
\end{flaspec}





\subsubsection{Level-3 BLAS}

% --- FLA_Gemm_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Gemm_external( FLA_Trans transa, FLA_Trans transb, FLA_Obj alpha,
                        FLA_Obj A, FLA_Obj B, FLA_Obj beta, FLA_Obj C );
\end{verbatim}
\index{FLAME/C functions!\flagemmextns}
\purpose{
Perform one of the following general matrix-matrix multiplication ({\sc gemm})
operations:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
C & := & \beta C + \alpha A B         & \hsp & C & := & \beta C + \alpha \bar{A} B \\[0.05in]
C & := & \beta C + \alpha A B^T       & \hsp & C & := & \beta C + \alpha \bar{A} B^T \\[0.05in]
C & := & \beta C + \alpha A \bar{B}   & \hsp & C & := & \beta C + \alpha \bar{A} \bar{B} \\[0.05in]
C & := & \beta C + \alpha A B^H       & \hsp & C & := & \beta C + \alpha \bar{A} B^H \\[0.05in]
C & := & \beta C + \alpha A^T B       & \hsp & C & := & \beta C + \alpha A^H B \\[0.05in]
C & := & \beta C + \alpha A^T B^T     & \hsp & C & := & \beta C + \alpha A^H B^T \\[0.05in]
C & := & \beta C + \alpha A^T \bar{B} & \hsp & C & := & \beta C + \alpha A^H \bar{B} \\[0.05in]
C & := & \beta C + \alpha A^T B^H     & \hsp & C & := & \beta C + \alpha A^H B^H
\end{array}
\end{math}
\end{center}
where $ \alpha $ and $ \beta $ are scalars and $ A $, $ B $, and $ C $ are
general matrices.
The \transa and \transb arguments allows the computation to proceed as if
$ A $ and/or $ B $ were conjugated and/or transposed.
}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\gemmns.
}
\moreinfo{
This function is similar to that of \flagemmns.
Please see the description for \flagemm for further details.
}
\end{flaspec}

% --- FLA_Hemm_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Hemm_external( FLA_Side side, FLA_Uplo uplo, FLA_Obj alpha,
                        FLA_Obj A, FLA_Obj B, FLA_Obj beta, FLA_Obj C );
\end{verbatim}
\index{FLAME/C functions!\flahemmextns}
\purpose{
Perform one of the following Hermitian matrix-matrix multiplication ({\sc hemm})
operations:
\begin{eqnarray*}
C & := & \beta C + \alpha A B \\
C & := & \beta C + \alpha B A
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a Hermitian matrix,
and $ B $ and $ C $ are general matrices.
The \side argument indicates whether matrix $ A $ is multiplied
on the left or the right side of $ B $.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
}
\implnotes{
This function uses external implementations of the level-3 BLAS routines
\hemm and \symmns.
}
\moreinfo{
This function is similar to that of \flahemmns.
Please see the description for \flahemm for further details.
}
\end{flaspec}

% --- FLA_Herk_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Herk_external( FLA_Uplo uplo, FLA_Trans trans, FLA_Obj alpha,
                        FLA_Obj A, FLA_Obj beta, FLA_Obj C );
\end{verbatim}
\index{FLAME/C functions!\flaherkextns}
\purpose{
Perform one of the following Hermitian rank-k update ({\sc herk}) operations:
\begin{eqnarray*}
C & := & \beta C + \alpha A A^H \\
C & := & \beta C + \alpha A^H A
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ C $ is a Hermitian matrix,
and $ A $ is a general matrix.
The \uplo argument indicates whether the lower or upper triangle of $ C $
is referenced and updated by the operation.
The \trans argument allows the computation to proceed as if $ A $ were
conjugate-transposed, which results in the alternate rank-k product $ A^H A $.
}
\implnotes{
This function uses external implementations of the level-3 BLAS routines
\herk and \syrkns.
}
\moreinfo{
This function is similar to that of \flaherkns.
Please see the description for \flaherk for further details.
}
\end{flaspec}

% --- FLA_Her2k_external() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Her2k_external( FLA_Uplo uplo, FLA_Trans trans, FLA_Obj alpha,
                         FLA_Obj A, FLA_Obj B, FLA_Obj beta, FLA_Obj C );
\end{verbatim}
\index{FLAME/C functions!\flahertkextns}
\purpose{
Perform one of the following Hermitian rank-2k update ({\sc her2k}) operations:
\begin{eqnarray*}
C & := & \beta C + \alpha A B^H + \bar{\alpha} B A^H \\
C & := & \beta C + \alpha A^H B + \bar{\alpha} B^H A
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ C $ is a Hermitian matrix,
and $ A $ and $ B $ are general matrices.
The \uplo argument indicates whether the lower or upper triangle of $ C $
is referenced and updated by the operation.
The \trans argument allows the computation to proceed as if $ A $ and $ B $
were conjugate-transposed, which results in the alternate rank-2k products
$ A^H B $ and $ B^H A $.
}
\implnotes{
This function uses external implementations of the level-3 BLAS routines
\hertk and \syrtkns.
}
\moreinfo{
This function is similar to that of \flahertkns.
Please see the description for \flahertk for further details.
}
\end{flaspec}

% --- FLA_Symm_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Symm_external( FLA_Side side, FLA_Uplo uplo, FLA_Obj alpha,
                        FLA_Obj A, FLA_Obj B, FLA_Obj beta, FLA_Obj C );
\end{verbatim}
\index{FLAME/C functions!\flasymmextns}
\purpose{
Perform one of the following symmetric matrix-matrix multiplication ({\sc symm})
operations:
\begin{eqnarray*}
C & := & \beta C + \alpha A B \\
C & := & \beta C + \alpha B A
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a symmetric matrix,
and $ B $ and $ C $ are general matrices.
The \side argument indicates whether the symmetric matrix $ A $ is multiplied
on the left or the right side of $ B $.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\symmns.
}
\moreinfo{
This function is similar to that of \flasymmns.
Please see the description for \flasymm for further details.
}
\end{flaspec}

% --- FLA_Syrk_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Syrk_external( FLA_Uplo uplo, FLA_Trans trans, FLA_Obj alpha,
                        FLA_Obj A, FLA_Obj beta, FLA_Obj C );
\end{verbatim}
\index{FLAME/C functions!\flasyrkextns}
\purpose{
Perform one of the following symmetric rank-k update ({\sc syrk}) operations:
\begin{eqnarray*}
C & := & \beta C + \alpha A A^T \\
C & := & \beta C + \alpha A^T A
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ C $ is a symmetric matrix,
and $ A $ is a general matrix.
The \uplo argument indicates whether the lower or upper triangle of $ C $
is referenced and updated by the operation.
The \trans argument allows the computation to proceed as if $ A $ were
transposed, which results in the alternate rank-k product $ A^T A $.
}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\syrkns.
}
\moreinfo{
This function is similar to that of \flasyrkns.
Please see the description for \flasyrk for further details.
}
\end{flaspec}

% --- FLA_Syr2k_external() -----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Syr2k_external( FLA_Uplo uplo, FLA_Trans trans, FLA_Obj alpha,
                         FLA_Obj A, FLA_Obj B, FLA_Obj beta, FLA_Obj C );
\end{verbatim}
\index{FLAME/C functions!\flasyrtkextns}
\purpose{
Perform one of the following symmetric rank-2k update ({\sc syr2k})
operations:
\begin{eqnarray*}
C & := & \beta C + \alpha A B^T + \alpha B A^T \\
C & := & \beta C + \alpha A^T B + \alpha B^T A
\end{eqnarray*}
where $ \alpha $ and $ \beta $ are scalars, $ C $ is a symmetric matrix,
and $ A $ and $ B $ are general matrices.
The \uplo argument indicates whether the lower or upper triangle of $ C $
is referenced and updated by the operation.
The \trans argument allows the computation to proceed as if $ A $ and $ B $
were transposed, which results in the alternate rank-2k products
$ A^T B $ and $ B^T A $.
}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\syrtkns.
}
\moreinfo{
This function is similar to that of \flasyrtkns.
Please see the description for \flasyrtk for further details.
}
\end{flaspec}

% --- FLA_Trmm_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Trmm_external( FLA_Side side, FLA_Uplo uplo, FLA_Trans trans,
                        FLA_Diag diag, FLA_Obj alpha, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flatrmmextns}
\purpose{
Perform one of the following triangular matrix-matrix multiplication
({\sc trmm}) operations:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
B & := & \alpha A B       & \hsp & B & := & \alpha B A \\[0.05in]
B & := & \alpha A^T B     & \hsp & B & := & \alpha B A^T \\[0.05in]
B & := & \alpha \bar{A} B & \hsp & B & := & \alpha B \bar{A} \\[0.05in]
B & := & \alpha A^H B     & \hsp & B & := & \alpha B A^H
\end{array}
\end{math}
\end{center}
where $ \alpha $ is a scalar, $ A $ is a triangular matrix, and
$ B $ is a general matrix.
The \side argument indicates whether the triangular matrix $ A $ is
multiplied on the left or the right side of $ B $.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
The \trans argument may be used to perform the check as if $ A $ were
conjugated and/or transposed.
The \diag argument indicates whether the diagonal of $ A $ is unit or
non-unit.
}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\trmmns.
}
\moreinfo{
This function is similar to that of \flatrmmns.
Please see the description for \flatrmm for further details.
}
\end{flaspec}

% --- FLA_Trmmsx_external() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Trmmsx_external( FLA_Side side, FLA_Uplo uplo, FLA_Trans trans,
                          FLA_Diag diag, FLA_Obj alpha, FLA_Obj A, FLA_Obj B,  
                          FLA_Obj beta, FLA_Obj C );
\end{verbatim}
\index{FLAME/C functions!\flatrmmsxextns}
\purpose{
Perform one of the following extended triangular matrix-matrix multiplication
operations:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
C & := & \beta C + \alpha A B       & \hsp & C & := & \beta C + \alpha B A \\[0.05in]
C & := & \beta C + \alpha A^T B     & \hsp & C & := & \beta C + \alpha B A^T \\[0.05in]
C & := & \beta C + \alpha \bar{A} B & \hsp & C & := & \beta C + \alpha B \bar{A} \\[0.05in]
C & := & \beta C + \alpha A^H B     & \hsp & C & := & \beta C + \alpha B A^H
\end{array}
\end{math}
\end{center}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a triangular matrix, and
$ B $ and $ C $ are general matrices.
The \side argument indicates whether the triangular matrix $ A $ is
multiplied on the left or the right side of $ B $.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
The \trans argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
The \diag argument indicates whether the diagonal of $ A $ is unit or
non-unit.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ B $, and $ C $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ A $, $ B $, and $ C $.
\itemvsp
\checkitem
If \side equals \flaleftns, then the number of rows in $ B $ and the order of
$ A $ must be equal; otherwise, if \side equals \flarightns, then the number
of columns in $ B $ and the order of $ A $ must be equal.
\itemvsp
\checkitem
The dimensions of $ B $ and $ C $ must be conformal.
\itemvsp
\checkitem
\diag may not be \flazerodiagns.
\end{checks}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\trmmns.
}
\begin{params}
\parameter{\flaside}{side}{Indicates whether $ A $ is multipled on the left or right side of $ B $.}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if $ A $ were conjugated and/or transposed.}
\parameter{\fladiag}{diag}{Indicates whether the diagonal of $ A $ is unit or non-unit.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{C}{An \flaobj representing matrix $ C $.}
\end{params}
\end{flaspec}

% --- FLA_Trsm_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Trsm_external( FLA_Side side, FLA_Uplo uplo, FLA_Trans trans, FLA_Diag diag,
                        FLA_Obj alpha, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flatrsmextns}
\purpose{
Perform one of the following triangular solve with multiple right-hand
sides ({\sc trsm}) operations:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
A X       & = & \alpha B & \hsp & X A       & = & \alpha B \\[0.05in]
A^T X     & = & \alpha B & \hsp & X A^T     & = & \alpha B \\[0.05in]
\bar{A} X & = & \alpha B & \hsp & X \bar{A} & = & \alpha B \\[0.05in]
A^H X     & = & \alpha B & \hsp & X A^H     & = & \alpha B 
\end{array}
\end{math}
\end{center}
and overwrite $ B $ with the contents of the solution matrix $ X $ as follows:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
B & := & \alpha A^{-1} B       & \hsp & B & := & \alpha B A^{-1} \\[0.05in]
B & := & \alpha A^{-T} B       & \hsp & B & := & \alpha B A^{-T} \\[0.05in]
B & := & \alpha \bar{A}^{-1} B & \hsp & B & := & \alpha B \bar{A}^{-1} \\[0.05in]
B & := & \alpha A^{-H} B       & \hsp & B & := & \alpha B A^{-H}
\end{array}
\end{math}
\end{center}
where $ \alpha $ is a scalar, $ A $ is a triangular matrix, and
$ X $ and $ B $ are general matrices.
The \side argument indicates whether the triangular matrix $ A $ is
multiplied on the left or the right side of $ X $.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
The \trans argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
The \diag argument indicates whether the diagonal of $ A $ is unit or
non-unit.
}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\trsmns.
}
\moreinfo{
This function is similar to that of \flatrsmns.
Please see the description for \flatrsm for further details.
}
\end{flaspec}

% --- FLA_Trsmsx_external() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Trsmsx_external( FLA_Side side, FLA_Uplo uplo, FLA_Trans trans,
                          FLA_Diag diag, FLA_Obj alpha, FLA_Obj A, FLA_Obj B,
                          FLA_Obj beta, FLA_Obj C );
\end{verbatim}
\index{FLAME/C functions!\flatrsmsxextns}
\purpose{
Perform one of the following extended triangular solve with multiple
right-hand sides ({\sc trsm}) operations:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
A X       & = & \alpha B & \hsp & X A       & = & \alpha B \\[0.05in]
A^T X     & = & \alpha B & \hsp & X A^T     & = & \alpha B \\[0.05in]
\bar{A} X & = & \alpha B & \hsp & X \bar{A} & = & \alpha B \\[0.05in]
A^H X     & = & \alpha B & \hsp & X A^H     & = & \alpha B 
\end{array}
\end{math}
\end{center}
and update $ C $ with the contents of the solution matrix $ X $ as follows:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
C & := & \beta C + \alpha A^{-1} B       & \hsp & C & := & \beta C + \alpha B A^{-1} \\[0.05in]
C & := & \beta C + \alpha A^{-T} B       & \hsp & C & := & \beta C + \alpha B A^{-T} \\[0.05in]
C & := & \beta C + \alpha \bar{A}^{-1} B & \hsp & C & := & \beta C + \alpha B \bar{A}^{-1} \\[0.05in]
C & := & \beta C + \alpha A^{-H} B       & \hsp & C & := & \beta C + \alpha B A^{-H} \\[0.05in]
\end{array}
\end{math}
\end{center}
where $ \alpha $ and $ \beta $ are scalars, $ A $ is a triangular matrix, and
$ X $, $ B $, and $ C $ are general matrices.
The \side argument indicates whether the triangular matrix $ A $ is
multiplied on the left or the right side of $ X $.
The \uplo argument indicates whether the lower or upper triangle of $ A $
is referenced by the operation.
The \trans argument allows the computation to proceed as if $ A $ were
conjugated and/or transposed.
The \diag argument indicates whether the diagonal of $ A $ is unit or
non-unit.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ B $, and $ C $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If $ \alpha $ and $ \beta $ are not of datatype \flaconstantns, then they must
match the datatypes of $ A $, $ B $, and $ C $.
\itemvsp
\checkitem
If \side equals \flaleftns, then the number of rows in $ B $ and the order of
$ A $ must be equal; otherwise, if \side equals \flarightns, then the number
of columns in $ B $ and the order of $ A $ must be equal.
\itemvsp
\checkitem
The dimensions of $ B $ and $ C $ must be conformal.
\itemvsp
\checkitem
\diag may not be \flazerodiagns.
\end{checks}
\implnotes{
This function uses an external implementation of the level-3 BLAS routine
\trsmns.
}
\begin{params}
\parameter{\flaside}{side}{Indicates whether $ A $ is multipled on the left or right side of $ X $.}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is referenced during the operation.}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if $ A $ were conjugated and/or transposed.}
\parameter{\fladiag}{diag}{Indicates whether the diagonal of $ A $ is unit or non-unit.}
\parameter{\flaobj}{alpha}{An \flaobj representing scalar $ \alpha $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\parameter{\flaobj}{beta}{An \flaobj representing scalar $ \beta $.}
\parameter{\flaobj}{C}{An \flaobj representing matrix $ C $.}
\end{params}
\end{flaspec}

















\subsection{LAPACK operations}

% --- FLA_Chol_unb_external() --------------------------------------------------
% --- FLA_Chol_blk_external() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Chol_blk_external( FLA_Uplo uplo, FLA_Obj A );
FLA_Error FLA_Chol_unb_external( FLA_Uplo uplo, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flacholblkextns}
\index{FLAME/C functions!\flacholunbextns}
\purpose{
Perform one of the following Cholesky factorizations ({\sc chol}):
\begin{eqnarray*}
A & \rightarrow & L L^T \\
A & \rightarrow & U^T U \\
A & \rightarrow & L L^H \\
A & \rightarrow & U^H U
\end{eqnarray*}
where $ A $ is positive definite.
If $ A $ is real, then it is assumed to be symmetric; otherwise, if $ A $ is
complex, then it is assumed to be Hermitian. 
The operation references and then overwrites the lower or upper triangle of
$ A $ with the Cholesky factor $ L $ or $ U $, depending on the value of 
\uplons.
}
\implnotes{
\flacholblkext and \flacholunbext perform their computation by calling
external implementations of the LAPACK routines \potrf and \potftns,
respectively.
The algorithmic variants employed by these routines, as well as the
blocksize used by \potrfns, are implementation-dependent.
}
\caveats{
\flacholblkext and \flacholunbext are available only if external LAPACK
interfaces were enabled at configure-time.
}
\moreinfo{
This function is similar to that of \flacholns.
Please see the description for \flachol for further details.
}
\end{flaspec}

% --- FLA_Trinv_unb_external() -------------------------------------------------
% --- FLA_Trinv_blk_external() -------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Trinv_blk_external( FLA_Uplo uplo, FLA_Diag diag, FLA_Obj A );
FLA_Error FLA_Trinv_unb_external( FLA_Uplo uplo, FLA_Diag diag, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flatrinvblkextns}
\index{FLAME/C functions!\flatrinvunbextns}
\purpose{
Perform a triangular matrix inversion ({\sc trinv}):
\begin{eqnarray*}
A := A^{-1}
\end{eqnarray*}
where $ A $ is a general triangular matrix.
The operation references and then overwrites the lower or upper triangle of
$ A $ with its inverse, $ A^{-1} $, depending on the value of \uplons.
The \diag argument indicates whether the diagonal of $ A $ is unit or
non-unit.
}
\implnotes{
\flatrinvblkext and \flatrinvunbext perform their computation by calling
external implementations of the LAPACK routines \trtri and \trtitns,
respectively.
The algorithmic variants employed by these routines, as well as the
blocksize used by \trtrins, are implementation-dependent.
}
\caveats{
\flatrinvblkext and \flatrinvunbext are available only if external LAPACK
interfaces were enabled at configure-time.
}
\moreinfo{
This function is similar to that of \flatrinvns.
Please see the description for \flatrinv for further details.
}
\end{flaspec}

% --- FLA_Ttmm_unb_external() --------------------------------------------------
% --- FLA_Ttmm_blk_external() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Ttmm_blk_external( FLA_Uplo uplo, FLA_Obj A );
void FLA_Ttmm_unb_external( FLA_Uplo uplo, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flattmmblkextns}
\index{FLAME/C functions!\flattmmunbextns}
\purpose{
Perform one of the following triangular-transpose matrix multiplies
({\sc ttmm}):
\begin{eqnarray*}
A & := & L^T L \\
A & := & U U^T \\
A & := & L^H L \\
A & := & U U^H
\end{eqnarray*}
where $ A $ is a triangular matrix with a real diagonal.
The operation references and then overwrites the lower or upper triangle of
$ A $ with its inverse, $ A^{-1} $, depending on the value of \uplons.
}
\implnotes{
\flattmmblkext and \flattmmunbext perform their computation by calling
external implementations of the LAPACK routines \lauum and \lauutns,
respectively.
The algorithmic variants employed by these routines, as well as the
blocksize used by \lauumns, are implementation-dependent.
}
\caveats{
\flattmmblkext and \flattmmunbext are available only if external LAPACK
interfaces were enabled at configure-time.
}
\moreinfo{
This function is similar to that of \flattmmns.
Please see the description for \flattmm for further details.
}
\end{flaspec}

% --- FLA_SPDinv_blk_external() ------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_SPDinv_blk_external( FLA_Uplo uplo, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flaspdinvblkextns}
\purpose{
Perform a positive definite matrix inversion ({\sc spdinv}):
\begin{eqnarray*}
A := A^{-1}
\end{eqnarray*}
where $ A $ is positive definite.
If $ A $ is real, then it is assumed to be symmetric; otherwise, if $ A $ is
complex, then it is assumed to be Hermitian. 
The operation references and then overwrites the lower or upper triangle of
$ A $ with its inverse, $ A^{-1} $, depending on the value of \uplons.
}
\implnotes{
\flaspdinvblkext performs its computation by calling external implementations
of the LAPACK routines \potrfns, \trtrins, and \lauumns.
The algorithmic variants and blocksizes used by these routines are
implementation-dependent.
}
\caveats{
\flaspdinvblkext is available only if external LAPACK
interfaces were enabled at configure-time.
}
\moreinfo{
This function is similar to that of \flaspdinvns.
Please see the description for \flaspdinv for further details.
}
\end{flaspec}

% --- FLA_LU_piv_blk_external() ------------------------------------------------
% --- FLA_LU_piv_unb_external() ------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_LU_piv_blk_external( FLA_Obj A, FLA_Obj p );
FLA_Error FLA_LU_piv_unb_external( FLA_Obj A, FLA_Obj p );
\end{verbatim}
\index{FLAME/C functions!\flalupivblkextns}
\index{FLAME/C functions!\flalupivunbextns}
\purpose{
Perform an LU factorization with partial row pivoting ({\sc lupiv}):
\begin{eqnarray*}
A & \rightarrow & P L U
\end{eqnarray*}
where $ A $ is a general matrix, $ L $ is lower triangular (or lower
trapezoidal if $ m > n $) with a unit diagonal, $ U $ is upper
triangular (or upper trapezoidal if $ m < n $), and $ P $ is a
permutation matrix.
The operation overwrites the strictly lower triangular portion of $ A $
with $ L $ and the upper triangular portion of $ A $ with $ U $.
The diagonal elements of $ L $ are not stored.
}
\implnotes{
\flalupivblkext and \flalupivunbext perform their computation by calling
external implementations of the LAPACK routines \getrf and \getftns,
respectively.
The algorithmic variants employed by these routines, as well as the
blocksize used by \getrfns, are implementation-dependent.
}
\caveats{
\flalupivblkext and \flalupivunbext are available only if external LAPACK
interfaces were enabled at configure-time.
}
\moreinfo{
This function is similar to that of \flalunopivns.
Please see the description for \flalunopiv for further details.
}
\end{flaspec}

% --- FLA_QR_blk_external() ----------------------------------------------------
% --- FLA_QR_unb_external() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_QR_blk_external( FLA_Obj A, FLA_Obj t );
void FLA_QR_unb_external( FLA_Obj A, FLA_Obj t );
\end{verbatim}
\index{FLAME/C functions!\flaqrblkextns}
\index{FLAME/C functions!\flaqrunbextns}
\purpose{
Perform a QR factorization ({\sc qr}):
\begin{eqnarray*}
A & \rightarrow & Q R
\end{eqnarray*}
where $ A $ is a general matrix, $ R $ is upper triangular (or upper
trapezoidal if $ m < n $), and $ Q $ is the product of $ k = \min(m,n) $
Householder reflectors:
\begin{eqnarray*}
Q & = & H(0) H(1) \cdots H(k-1)
\end{eqnarray*}
Each $ H(i) $ has the form
\begin{eqnarray*}
H(i) & = & I - \tau v v^T
\end{eqnarray*}
where $ \tau $ is a scalar and $ v $ is a vector of length $ m $.
If $ \nu_j $ is the $ j $th element of $ v $, we may describe $ v $ such that,
for a given $ H(i) $, the element $ \nu_i = 1 $ while elements
$ \nu_{0:i-1} $ are zero, with other entries holding non-zero values.
The operation overwrites the the upper triangle (or upper trapezoid) of $ A $
with $ R $.
However, the matrix $ Q $ is not stored explicitly.
Instead, the operation stores the $ \tau $ associated with $ H(i) $ to the
$ i $th element of vector $ t $, and also stores the non-unit, non-zero entries
$ \nu_{i+1:m-1} $ of Householder reflectors $ H_{0} $ through $ H_{k} $
column-wise below the diagonal of $ A $.
More specifically, entries $ \nu_{i+1:m-1} $ are stored to elements $ i+1:m-1 $
of the $ i $th column of matrix $ A $.
}
\caveats{
\flaqrblkext and \flaqrunbext are available only if external LAPACK
interfaces were enabled at configure-time.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ t $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The length of $ t $ must be $ \min(m,n) $ where $ A $ is $ m \by n $.
\end{checks}
\implnotes{
\flaqrblkext and \flaqrunbext perform their computation by calling external
implementations of the LAPACK routines \geqrf and \geqrtns, respectively.
The algorithmic variants employed by these routines, as well as the
blocksize used by \geqrfns, are implementation-dependent.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{t}{An \flaobj representing vector $ t $.}
\end{params}
\end{flaspec}

% --- FLA_LQ_blk_external() ----------------------------------------------------
% --- FLA_LQ_unb_external() ----------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_LQ_blk_external( FLA_Obj A, FLA_Obj t );
void FLA_LQ_unb_external( FLA_Obj A, FLA_Obj t );
\end{verbatim}
\index{FLAME/C functions!\flalqblkextns}
\index{FLAME/C functions!\flalqunbextns}
\purpose{
Perform an LQ factorization ({\sc lq}):
\begin{eqnarray*}
A & \rightarrow & L Q
\end{eqnarray*}
where $ A $ is a general matrix, $ L $ is a lower triangular (or lower
trapezoidal if $ m > n $), and $ Q $ is the product of $ k = \min(m,n) $
Householder reflectors:
\begin{eqnarray*}
Q & = & H(k-1) \cdots H(1) H(0)
\end{eqnarray*}
Each $ H(i) $ has the form
\begin{eqnarray*}
H(i) & = & I - \tau v v^T
\end{eqnarray*}
where $ \tau $ is a scalar and $ v $ is a vector of length $ n $.
If $ \nu_j $ is the $ j $th element of $ v $, we may describe $ v $ such that,
for a given $ H(i) $, the element $ \nu_i = 1 $ while elements
$ \nu_{0:i-1} $ are zero, with other entries holding non-zero values.
The operation overwrites the the lower triangle (or lower trapezoid) of $ A $
with $ L $.
However, the matrix $ Q $ is not stored explicitly.
Instead, the operation stores the $ \tau $ associated with $ H(i) $ to the
$ i $th element of vector $ t $, and also stores the non-unit, non-zero entries
$ \nu_{i+1:n-1} $ of Householder reflectors $ H_{0} $ through $ H_{k} $
row-wise above the diagonal of $ A $.
More specifically, entries $ \nu_{i+1:n-1} $ are stored to elements $ i+1:n-1 $
of the $ i $th row of matrix $ A $.
}
\caveats{
\flalqblkext and \flalqunbext are available only if external LAPACK
interfaces were enabled at configure-time.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $ and $ t $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The length of $ t $ must be $ \min(m,n) $ where $ A $ is $ m \by n $.
\end{checks}
\implnotes{
\flalqblkext and \flalqunbext perform their computation by calling external
implementations of the LAPACK routines \gelqf and \gelqtns, respectively.
The algorithmic variants employed by these routines, as well as the
blocksize used by \gelqfns, are implementation-dependent.
}
\begin{params}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{t}{An \flaobj representing vector $ t $.}
\end{params}
\end{flaspec}

% --- FLA_Hess_unb_external() --------------------------------------------------
% --- FLA_Hess_blk_external() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Hess_blk_external( FLA_Obj A, FLA_Obj t, int ilo, int ihi );
void FLA_Hess_unb_external( FLA_Obj A, FLA_Obj t, int ilo, int ihi );
\end{verbatim}
\index{FLAME/C functions!\flahessblkextns}
\index{FLAME/C functions!\flahessunbextns}
\purpose{
Perform a reduction to upper Hessenberg form ({\sc hess}) via Householder
transformations:
\begin{eqnarray*}
A & \rightarrow & Q R Q^H
\end{eqnarray*}
where $ Q $ is an orthogonal matrix (or, a unitary matrix if $ A $ is complex)
and $ R $ is an upper Hessenberg matrix (zeroes below the first subdiagonal).
Matrix $ Q $ is expressed as a product of $( i_{hi} - i_{lo} ) $
Householder reflectors:
\begin{eqnarray*}
Q & = & H({i_{lo}}) H({i_{lo}+1}) \cdots H({i_{hi}-1})
\end{eqnarray*}
Each $ H(i) $ has the form
\begin{eqnarray*}
H(i) & = & I - \tau v v^H
\end{eqnarray*}
where $ \tau $ is a real scalar and $ v $ is a real vector of length $ n $.
If $ \nu_j $ is the $ j $th element of $ v $, we may describe $ v $ such that,
for a given $ H(i) $, the element $ \nu_{i+1} = 1 $ while elements
$ \nu_{0:i} $ and $ \nu_{i_{hi}+1:n-1} $ are zero, with other entries holding
non-zero values.
The operation overwrites the the upper triangle and first subdiagonal of $ A $
with $ H $.
However, the matrix $ Q $ is not stored explicitly.
Instead, the operation stores the $ \tau $ associated with $ H(i) $ to the
$ i $th element of vector $ t $, and also stores the non-unit, non-zero entries
$ \nu_{i+2:i_{hi}} $ of Householder reflectors $ H_{i_{lo}} $ through
$ H_{i_{hi}-2} $ to the elements below the first subdiagonal of $ A $.
More specifically, entries $ \nu_{i+2:i_{hi}} $ are stored to elements
$ i+2:i_{hi} $ of the $ i $th column of matrix $ A $.
}
\implnotes{
\flahessblkext and \flahessunbext perform their computation by calling
external implementations of the LAPACK routines \gehrd and \gehdtns,
respectively.
The algorithmic variants employed by these routines, as well as the
blocksize used by \gehrdns, are implementation-dependent.
}
\moreinfo{
This function is similar to that of \flahessutns.
Please see the description for \flahessut for further details.
}
\end{flaspec}

% --- FLA_Tridiag_UT_blk_external() --------------------------------------------
% --- FLA_Tridiag_UT_unb_external() --------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Tridiag_blk_external( FLA_Uplo uplo, FLA_Obj A, FLA_Obj t );
void FLA_Tridiag_unb_external( FLA_Uplo uplo, FLA_Obj A, FLA_Obj t );
\end{verbatim}
\index{FLAME/C functions!\flatridiagblkextns}
\index{FLAME/C functions!\flatridiagunbextns}
\purpose{
Perform a reduction to tridiagonal form ({\sc tridiag}) via Householder
transformations:
\begin{eqnarray*}
A & \rightarrow & Q R Q^H
\end{eqnarray*}
where $ Q $ is an orthogonal matrix (or, a unitary matrix if $ A $ is complex)
and $ R $ is a tridiagonal matrix (zeroes below the first subdiagonal and above
the first superdiagonal).
}
\implnotes{
\flatridiagblkext and \flatridiagunbext perform their computation by calling
external implementations of the LAPACK routines \sytrdns/\hetrdns and
\sytdtns/\hetdtns, respectively.
The algorithmic variants employed by these routines, as well as the
blocksizes used by \sytrd and \hetrdns, are implementation-dependent.
}
\moreinfo{
This function is similar to that of \flatridiagutns.
Please see the description for \flatridiagut for further details.
}
\end{flaspec}

% --- FLA_Apply_Q_blk_external() -----------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Apply_Q_blk_external( FLA_Side side, FLA_Trans trans, FLA_Store storev,
                               FLA_Obj A, FLA_Obj t, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaapplyqblkextns}
\purpose{
Apply a matrix $ Q $ (or $ Q^T $ or $ Q^H $) to a general 
matrix $ B $ from either the left or the right:
\begin{center}
\begin{math}
\begin{array}{cclcccl}
B & := & Q B       & \hsp & B & := & B Q   \\[0.05in]
B & := & Q^T B     & \hsp & B & := & B Q^T \\[0.05in]
B & := & Q^H B     & \hsp & B & := & B Q^H
\end{array}
\end{math}
\end{center}
where $ Q $ is the orthogonal (or, if $ A $ is complex, unitary) matrix
implicitly defined by the Householder vectors stored in matrix $ A $ and the
$ \tau $ values stored in vector $ t $.
The \side argument indicates whether $ Q $ is applied to $ B $ from the left
or the right.
The \trans argument indicates whether $ Q $ or $ Q^T $ (or $ Q^H $) is applied
to $ B $.
The \storev argument indicates whether the Householder vectors which define
$ Q $ are stored column-wise (in the strictly lower triangle) or 
row-wise (in the strictly upper triangle) of $ A $.
}
\implnotes{
\flaapplyqblkext performs its computation by
calling an external implementation of the LAPACK routines
\ormqrns/\unmqrns/\ormlqns/\unmlqns.
The algorithmic variants employed by these routines, as well as the
blocksizes used by \ormqrns, \unmqrns, \ormlqns, and \unmlq are
implementation-dependent.
}
\caveats{
\flaapplyqblkext is available only if external LAPACK
interfaces were enabled at configure-time.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ t $, and $ B $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
If \side equals \flaleftns, then the number of rows in $ B $ and the order of
$ A $ must be equal; otherwise, if \side equals \flarightns, then the number
of columns in $ B $ and the order of $ A $ must be equal.
\itemvsp
\checkitem
If $ A $ is real, then \trans must be \flanotranspose or \flatransposens; 
otherwise if $ A $ is complex, then \trans must be \flanotranspose or
\flaconjtransposens.
\itemvsp
\checkitem
The length of $ t $ must be $ \min(m,n) $ where $ A $ is $ m \by n $.
\end{checks}
\begin{params}
\parameter{\flaside}{side}{Indicates whether $ Q $ (or $ Q^T $ or $ Q^H $) is multipled on the left or right side of $ B $.}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if $ Q $ were transposed (or conjugate-transposed).}
\parameter{\flastorev}{storev}{Indicates whether the vectors stored within $ A $ are stored column-wise or row-wise.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{t}{An \flaobj representing vector $ t $.}
\parameter{\flaobj}{B}{An \flaobj representing matrix $ B $.}
\end{params}
\end{flaspec}

% --- FLA_Sylv_blk_external() --------------------------------------------------
% --- FLA_Sylv_unb_external() --------------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Sylv_blk_external( FLA_Trans transa, FLA_Trans transb, FLA_Obj isgn,
                            FLA_Obj A, FLA_Obj B, FLA_Obj C, FLA_Obj scale );
void FLA_Sylv_unb_external( FLA_Trans transa, FLA_Trans transb, FLA_Obj isgn,
                            FLA_Obj A, FLA_Obj B, FLA_Obj C, FLA_Obj scale );
\end{verbatim}
\index{FLAME/C functions!\flasylvblkextns}
\index{FLAME/C functions!\flasylvunbextns}
\purpose{
Solve one of the following triangular Sylvester equations ({\sc sylv}):
\begin{center}
\begin{math}
\begin{array}{lclcc}
A   X & \pm & X B   & = & C \\
A   X & \pm & X B^T & = & C \\
A^T X & \pm & X B   & = & C \\
A^T X & \pm & X B^T & = & C \\
\end{array}
\end{math}
\end{center}
where $ A $ and $ B $ are real upper triangular matrices and $ C $ is a
real general matrix.
If $ A $, $ B $, and $ C $ are complex matrices, then the possible operations
are:
\begin{center}
\begin{math}
\begin{array}{lclcc}
A   X & \pm & X B   & = & C \\
A   X & \pm & X B^H & = & C \\
A^H X & \pm & X B   & = & C \\
A^H X & \pm & X B^H & = & C \\
\end{array}
\end{math}
\end{center}
where $ A $ and $ B $ are complex upper triangular matrices and $ C $ is a
complex general matrix.
The operation references and then overwrites matrix $ C $ with the solution
matrix $ X $.
The \isgn argument is a scalar integer object that indicates whether the
$ \pm $ sign between terms is a plus or a minus.
The \scale argument is not referenced and set to $ 1.0 $ upon completion.
}
\implnotes{
\flasylvblkext and \flasylvunbext perform their computation by calling an
external implementation of the LAPACK routine \trsylns.
The algorithmic variant employed by this routine is implementation-dependent.
}
\implnotes{
\flasylvblkext is simply a wrapper to \flasylvunbextns.
}
\caveats{
\flasylvblkext and \flasylvunbext are available only if external LAPACK
interfaces were enabled at configure-time.
}
\moreinfo{
This function is similar to that of \flasylvns.
Please see the description for \flasylv for further details.
}
\end{flaspec}

% --- FLA_Eig_gest_blk_external() ----------------------------------------------
% --- FLA_Eig_gest_unb_external() ----------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Eig_gest_blk_external( FLA_Inv inv, FLA_Uplo uplo, FLA_Obj A, FLA_Obj B );
void FLA_Eig_gest_unb_external( FLA_Inv inv, FLA_Uplo uplo, FLA_Obj A, FLA_Obj B );
\end{verbatim}
\index{FLAME/C functions!\flaeiggestblkextns}
\index{FLAME/C functions!\flaeiggestunbextns}
\purpose{
Perform one of the following operations to reduce a symmetric- or
Hermitian-definite eigenproblem to standard form ({\sc eiggest}):
\begin{eqnarray*}
A & := & L^H A L \\
A & := & U A U^H \\
A & := & L A L^{-H} \\
A & := & U^{-H} A U
\end{eqnarray*}
where $ A $, on input and output, is symmetric (or Hermitian) and
$ B $ contains either a lower ($ L $) or upper ($ U $) triangular Cholesky
factor.
The value of \inv determines whether the operation, as expressed above,
requires an inversion of $ L $ or $ U $.
The value of \uplo determines which triangle of $ A $ is read on input,
which triangle of the symmetric (or Hermitian)
right-hand side is stored, and also which Cholesky factor
exists in $ B $.
}
\implnotes{
\flaeiggestblkext and \flaeiggestunbext perform their computation by calling
external implementations of the LAPACK routines
\sygstns/\hegst and \sygstwns/\hegstwns, respectively.
The algorithmic variants employed by these routines, as well as the
blocksize used by \sygstns/\hegstns, are implementation-dependent.
}
\caveats{
\flaeiggestblkext and \flaeiggestunbext are available only if external LAPACK
interfaces were enabled at configure-time.
}
\moreinfo{
This function is similar to that of \flaeiggestns.
Please see the description for \flaeiggest for further details.
}
\end{flaspec}

% --- FLA_Hevd_external() ------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Hevd_external( FLA_Evd_type jobz, FLA_Uplo uplo, FLA_Obj A, FLA_Obj l );
\end{verbatim}
\index{FLAME/C functions!\flahevdextns}
\purpose{
Perform a Hermitian eigenvalue decomposition ({\sc hevd}):
\begin{eqnarray*}
A & \rightarrow & U \Lambda U^H
\end{eqnarray*}
where $ \Lambda $ is a diagonal matrix whose elements contain the eigenvalues
of $ A $, and the columns of $ U $ contain the eigenvectors of $ A $.
The \jobz argument determines whether only eigenvalues (\flaevdwithoutvectorsns)
or both eigenvalues and eigenvectors (\flaevdwithvectorsns) are computed.
The \uplo argument determines whether $ A $ is stored in the lower or upper
triangle.
Upon completion, the eigenvalues are stored to the vector $ l $ in ascending
order, and the eigenvectors $ U $, if requested, overwrite matrix $ A $ such
that vector element $ l_j $ contains the eigenvalue corresponding to the
eigenvector stored in the $j$th column of $ U $.
If eigenvectors are not requested, then the triangle specified by \uplo is
destroyed.
}
\rvalue{
\flasuccess if the operation is successful; otherwise, $ k $ is returned,
where $ k $ is the number of off-diagonal elements of the intermediate
tridiagonal matrix that failed to converge.
}
\implnotes{
\flahevdext performs its computation by
calling an external implementation of the LAPACK routines
\heevns/\syevns.
The algorithmic variants employed by these routines, as well as
any blocksizes used by subroutines of \heevns/\syevns, are
implementation-dependent.
}
\caveats{
\flahevdext is available only if external LAPACK
interfaces were enabled at configure-time.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point and must not be
\flaconstantns.
\itemvsp
\checkitem
The numerical datatype of $ l $ must be real and must not be
\flaconstantns.
\itemvsp
\checkitem
The precision of the datatype of $ l $ must be equal to that of $ A $.
\itemvsp
\checkitem
$ l $ must be a contiguously-stored vector of length $ n $,
where $ A $ is $ n \times n $.
\end{checks}
\begin{params}
\parameter{\flaevdtype}{jobz}{Indicates whether only eigenvalues or both eigenvalues and eigenvectors are computed.}
\parameter{\flauplo}{uplo}{Indicates whether the lower or upper triangle of $ A $ is read during the operation.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{l}{An \flaobj representing vector $ l $.}
\end{params}
\end{flaspec}

% --- FLA_Svd_external() -------------------------------------------------------

\begin{flaspec}
\begin{verbatim}
FLA_Error FLA_Svd_external( FLA_Svd_type jobu, FLA_Svd_type jobv, FLA_Obj A, FLA_Obj s,
                            FLA_Obj U, FLA_Obj V );
\end{verbatim}
\index{FLAME/C functions!\flasvdextns}
\purpose{
Perform a singular value decomposition ({\sc svd}):
\begin{eqnarray*}
A & \rightarrow & U \Sigma V^H
\end{eqnarray*}
where $ \Sigma $ is an $ m \times n $ diagonal matrix whose elements contain
the singular values of $ A $, $ U $ is an $ m \times m $ matrix whose columns
contain the left singular vectors of $ A $, and $ V $ is an $ n \times n $
matrix whose rows of $ V $ contain the right singular vectors of $ A $.
The \jobu and \jobv arguments determine if (and how many of) the left and
right singular vectors, respectively, are computed and where they are
stored.
The \jobu and \jobv arguments accept the following values:
\begin{itemize}
\item
\flasvdvectorsallns.
For \jobuns: compute all $ m $ columns of $ U $, storing the result in $ U $.
For \jobvns: compute all $ n $ columns of $ V $, storing the result in $ V $.
\item
\flasvdvectorsmincopyns.
For \jobuns: compute the first $ \min(m,n) $ columns of $ U $ and store them
in $ U $.
For \jobvns: compute the first $ \min(m,n) $ columns of $ V $ and store them
in $ V $.
\item
\flasvdvectorsminoverwritens.
For \jobuns: compute the first $ \min(m,n) $ columns of $ U $ and store them
in $ A $.
For \jobvns: compute the first $ \min(m,n) $ columns of $ V $ and store them
in $ A $.
Note that \jobu and \jobv cannot both be \flasvdvectorsminoverwritens.
\item
\flasvdvectorsnonens.
For \jobuns: no columns of $ U $ are computed.
For \jobvns: no columns of $ V $ are computed.
\end{itemize}
Upon completion, the $ \min(m,n) $ singular values of $ A $ are stored to
$ s $, sorted in descending order and singular vectors, if computed, are
stored to either $ A $ or $ U $ and $ V $, depending on the values of
\jobu and \jobvns.
If neither \jobu nor \jobv is \flasvdvectorsminoverwritens, then $ A $
is destroyed.
}
\rvalue{
\flasuccess if the operation is successful; otherwise, $ k $ is returned,
where $ k $ is the number of superdiagonal elements of the intermediate
bidiagonal matrix that failed to converge.
}
\notes{
If right singular vectors are requested (ie: \jobv is not \flasvdvectorsnonens)
then $ V^H $ is actually stored rather than $ V $.
}
\implnotes{
\flasvdext performs its computation by
calling an external implementation of the LAPACK routines
\gesvdns/\gesvdns.
The algorithmic variants employed by these routines, as well as
any blocksizes used by subroutines of \gesvdns/\gesvdns, are
implementation-dependent.
}
\caveats{
\flasvdext is available only if external LAPACK
interfaces were enabled at configure-time.
}
\begin{checks}
\checkitem
The numerical datatypes of $ A $, $ U $, and $ V $ must be identical and
floating-point, and must not be \flaconstantns.
\itemvsp
\checkitem
The numerical datatype of $ s $ must be real and must not be
\flaconstantns.
\itemvsp
\checkitem
The precision of the datatype of $ s $ must be equal to that of $ A $.
\itemvsp
\checkitem
$ e $ must be a contiguously-stored vector of length $ \min(m,n) $,
where $ A $ is $ m \times n $.
\itemvsp
\checkitem
$ U $ and $ V $ must be square.
\itemvsp
\checkitem
The order of $ U $ and the order of $ V $ must be equal to the the number of
rows in $ A $ and the number of columns in $ A $, respectively.
\end{checks}
\begin{params}
\parameter{\flasvdtype}{jobu}{Indicates whether the left singular vectors are computed, how many are computed, and where they are stored.}
\parameter{\flasvdtype}{jobv}{Indicates whether the right singular vectors are computed, how many are computed, and where they are stored.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\parameter{\flaobj}{s}{An \flaobj representing vector $ s $.}
\parameter{\flaobj}{U}{An \flaobj representing matrix $ U $.}
\parameter{\flaobj}{V}{An \flaobj representing matrix $ V $.}
\end{params}
\end{flaspec}










\subsection{LAPACK-related utility functions}


% --- FLA_Apply_pivots_unb_external() ------------------------------------------

\begin{flaspec}
\begin{verbatim}
void FLA_Apply_pivots_unb_external( FLA_Side side, FLA_Trans trans, FLA_Obj p, FLA_Obj A );
\end{verbatim}
\index{FLAME/C functions!\flaapplypivotsunbextns}
\purpose{
Apply a permutation matrix $ P $ (or $ P^T$) from either the left or the right
to a matrix $ A $.
The permutation matrix $ P $, which is not explicitly formed, is encoded by the
integer values stored in the pivot vector $ p $.
}
\notes{
The pivot vector $ p $ must contain pivot values that conform to \libflame
pivot indexing.
If the pivot vector was filled using an LAPACK routine, it must first be
converted to \libflame pivot indexing with \flashiftpivotsto before it may be
used with \flaapplypivotsunbextns.
Please see the description for \flalupiv in Section \ref{sec:lapack-front-ends}
for details on the differences between LAPACK-style pivot vectors and \libflame
pivot vectors.
}
\begin{checks}
\checkitem
The numerical datatype of $ A $ must be floating-point, and must not be
\flaconstantns.
\itemvsp
\checkitem
The numerical datatype of $ p $ must be integer, and must not be
\flaconstantns.
\end{checks}
\implnotes{
This function uses an external implementation of the LAPACK routine
\laswpns.
}
\caveats{
\flaapplypivotsunbext is only implemented for the case where \side is left and
\trans is \flanotransposens.
}
\caveats{
\flaapplypivotsunbext is available only if external LAPACK
interfaces were enabled at configure-time.
}
\begin{params}
\parameter{\flaside}{side}{Indicates whether the permutation matrix $ P $ is applied from the left or the right.}
\parameter{\flatrans}{trans}{Indicates whether the operation proceeds as if the permutation matrix $ P $ were transposed.}
\parameter{\flaobj}{p}{An \flaobj representing vector $ p $.}
\parameter{\flaobj}{A}{An \flaobj representing matrix $ A $.}
\end{params}
\end{flaspec}









\section{LAPACK compatibility ({\tt lapack2flame})}
\label{sec:lapack2flame}

As part of the \libflame package we provide an LAPACK compatibility
layer, which we call \lapacktflamens, that allows the user to take advantage of
some of the performance benefits of \libflame without rewriting their
code to use the native FLAME/C API.
More specifically, \lapacktflame consists of interfaces that map
LAPACK routine invocations to their corresponding \libflame implementations.
For example, linking your application to an \lapacktflamens-enabled
build of \libflame would cause any invocation of {\tt dpotrf()} to invoke
the Cholesky factorization implemented by \flacholns.
The amount of overhead incurred when interfacing to \libflame via this
compatibility layer is typically
small.\footnote{
There are, however, operations for which the overhead is noticeable even at
larger problem sizes.
This typically is due to \libflame needing to recompute intermediate data
products that LAPACK routines discard.
A noteworthy example is the routine family {\tt ?ormqr}/{\tt ?unmqr} and
{\tt ?ormlq}/{\tt ?unmlq}, which apply the orthogonal (or unitary) matrix
$ Q $ that was previously computed via a QR or LQ factorization.
The QR and LQ factorizations in LAPACK were designed to preserve only the vector
of the $ \tau $ values that form the individual Householder transformations.
By contrast, the corresponding QR and LQ factorizations in \libflame preserve
the $ b \by b $ triangular factors of the block Householder transformations
applied at each step of the blocked factorization algorithm, which are then
reused when applying $ Q $ or $ Q^H $.
But since the LAPACK interface does not allow the user to pass in the full
triangular factors, the \lapacktflame impelementation must re-compute the
factors on-the-fly before continuing with the application of $ Q $.
}
Much of this overhead stems from needing to initialize and finalize the
library within each LAPACK interface routine implementation.
If the user initializes \libflame {\em a priori}, the overhead
incurred within the LAPACK interface routine is usually much lower.
That said, even in under this ideal usage scenario, the overhead may still
be noticeable for very small matrices
(ie: those smaller than approximately $ 100 \by 100 $).


\subsection{Supported routines}

This section summarizes the LAPACK interfaces currently supported within
\lapacktflamens.
Table \ref{fig:lapack2flame} lists all LAPACK interfaces which map directly
to functionality implemented within \libflamens.

\input{figs/40-lapack2flame}

%However, many routines within LAPACK utilize other routines as subproblems
%toward their larger goal.
%Table \ref{fig:lapack2flame-indirect} summarizes the LAPACK interfaces
%which indirectly depend upon routines listed in \ref{fig:lapack2flame}.
%
%\input{figs/40-lapack2flame-indirect}
%
%These routines may exhibit improved performance by virtue of the fact that
%they utilize higher-performing implementations of their suboperations.
%However, the performance improvement may be markedly lower than that
%observed when invoking the routines in Table \ref{fig:lapack2flame}
%directly.
%
%Directions on how to link \lapacktflame to your application may be found
%in Section \ref{sec:linking}.







%\section{Algorithmic variants}
%\label{sec:algorithmic-variants}
%
%
%
%\subsection{Level-3 BLAS}
%\subsubsection{{\sc gemm}}
%\subsubsection{{\sc hemm}}
%\subsubsection{{\sc herk}}
%\subsubsection{{\sc her2k}}
%\subsubsection{{\sc symm}}
%\subsubsection{{\sc syrk}}
%\subsubsection{{\sc syr2k}}
%\subsubsection{{\sc trmm}}
%\subsubsection{{\sc trsm}}
%
%
%
%
%\subsection{LAPACK}
%\subsubsection{{\sc chol}}
%\subsubsection{{\sc trinv}}
%\subsubsection{{\sc ttmm}}
%\subsubsection{{\sc spdinv}}
%\subsubsection{{\sc hess}}
%\subsubsection{{\sc lunopiv}}
%\subsubsection{{\sc lupiv}}
%\subsubsection{{\sc qr}}
%\subsubsection{{\sc lq}}
%\subsubsection{{\sc qrut}}
%\subsubsection{{\sc lqut}}
%\subsubsection{{\sc sylv}}






