/* -*- coding: utf-8 -*- */
/**
\ingroup algebra anespec geopot gshhs matriz mmcc snx
@{
\file posmatvec.h
\brief Declaración de funciones para realizar cálculos de posiciones de
       elementos en matrices almacenadas en formato vector.

En el momento de la compilación de las funciones de cálculo de posición ha de
seleccionarse el tipo de almacenamiento matricial. Para realizar la selección es
necesario definir la variable \em ROW_MAJOR_ORDER_MATVEC si se quiere
almacenamiento de tipo ROW MAJOR ORDER o \em COLUMN_MAJOR_ORDER_MATVEC si se
quiere almacenamiento de tipo COLUMN MAJOR ORDER. En \p gcc, las variables para
el preprocesador se pasan como \em -DXXX, donde \em XXX es la variable a
introducir.

Una matriz puede ser almacenada en formato vector de dos formas distintas: ROW
MAJOR ORDER y COLUMN MAJOR ORDER. En la primera, la matriz es almacenada por
filas, mientras que en la segunda lo es por columnas. Por ejemplo, la matriz
\code
m = [1 2 3 4
     5 6 7 8]
\endcode
será almacenada en ROW MAJOR ORDER como
\code
m = [1 2 3 4 5 6 7 8]
\endcode
y en COLUMN MAJOR ORDER como
\code
m = [1 5 2 6 3 7 4 8]
\endcode
\author José Luis García Pallero, jgpallero@gmail.com
\date 14 de enero de 2009
\section Licencia Licencia
Copyright (c) 2009-2013, José Luis García Pallero. All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

- Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
  list of conditions and the following disclaimer in the documentation and/or
  other materials provided with the distribution.
- Neither the name of the copyright holders nor the names of its contributors
  may be used to endorse or promote products derived from this software without
  specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/******************************************************************************/
/******************************************************************************/
#ifndef _POSMATVEC_H_
#define _POSMATVEC_H_
/******************************************************************************/
/******************************************************************************/
#include<stdlib.h>
#include<string.h>
/******************************************************************************/
/******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************/
/******************************************************************************/
/**
\def GEOC_LON_CAD_COD_ALM
\brief Longitud máxima de una cadena para almacenar el código identificador de
       tipo de almacenamiento matricial.
\date 25 de septiembre de 2009: Creación de la constante.
*/
#define GEOC_LON_CAD_COD_ALM 25
/******************************************************************************/
/******************************************************************************/
/**
\def GEOC_MATR_COD_ALM_RMO
\brief Código identificador de almacenamiento como ROW MAJOR ORDER.
\date 14 de enero de 2009: Creación de la constante.
*/
#define GEOC_MATR_COD_ALM_RMO "ROW-MAJOR-ORDER"
/******************************************************************************/
/******************************************************************************/
/**
\def GEOC_MATR_COD_ALM_CMO
\brief Código identificador de almacenamiento como COLUMN MAJOR ORDER.
\date 14 de enero de 2009: Creación de la constante.
*/
#define GEOC_MATR_COD_ALM_CMO "COLUMN-MAJOR-ORDER"
/******************************************************************************/
/******************************************************************************/
/**
\def GEOC_INICIO_VEC
\brief Macro para seleccionar el índice correspondiente al primer elemento de un
       vector dependiendo del valor de las posiciones de separación entre sus
       elementos. El índice buscado será diferente de 0 cuando el valor de
       posiciones de separación sea menor que 0.
\param[in] n Número de elementos del vector. Ha de ser una variable de tipo
           \p size_t.
\param[in] inc Posiciones de separación entre los elementos del vector.
\return Índice del primer elemento del vector.
\note Esta macro ha sido copiada (sólo se le ha cambiado el nombre) del fichero
      \em cblas.h del código fuente de la biblioteca \p gsl \p v.1.12, que se
      distribuye bajo licencia GPL v.3 o posterior.
\date 19 de noviembre de 2009: Creación de la macro.
*/
#define GEOC_INICIO_VEC(n,inc) ((inc) >= 0 ? 0 : ((n)-1)*(size_t)(-(inc)))
/******************************************************************************/
/******************************************************************************/
/**
\def GEOC_LMFC_RMO
\brief Devuelve las columnas almacenadas en memoria de una matriz.
\param[in] filMem Filas de la matriz almacenada en memoria.
\param[in] colMem Columnas de la matriz almacenada en memoria.
\return Número de columnas almacenadas en memoria.
\date 25 de noviembre de 2009: Creación de la macro.
*/
//se añade 0*filMem para que el compilador no dé warning por variable no usada
#define GEOC_LMFC_RMO(filMem,colMem) ((colMem)+0*(filMem))
/******************************************************************************/
/******************************************************************************/
/**
\def GEOC_LMFC_CMO
\brief Devuelve las filas almacenadas en memoria de una matriz.
\param[in] filMem Filas de la matriz almacenada en memoria.
\param[in] colMem Columnas de la matriz almacenada en memoria.
\return Número de filas almacenadas en memoria.
\date 25 de noviembre de 2009: Creación de la macro.
*/
//se añade 0*colMem para que el compilador no dé warning por variable no usada
#define GEOC_LMFC_CMO(filMem,colMem) ((filMem)+0*(colMem))
/******************************************************************************/
/******************************************************************************/
/**
\def GEOC_POSMATVEC_RMO
\brief Calcula la posición de un elemento de una matriz almacenada en ROW MAJOR
       ORDER en el vector que la contiene.
\param[in] filMem Filas reales (almacenadas en memoria) de la matriz.
\param[in] colMem Columnas reales (almacenadas en memoria) de la matriz.
\param[in] fil Fila del elemento de trabajo.
\param[in] col Columna del elemento de trabajo.
\return Posición del elemento de trabajo en el vector que almacena la matriz.
\note Esta macro no comprueba si la posición del elemento de trabajo concuerda
      con las dimensiones de la matriz.
\date 25 de noviembre de 2009: Creación de la macro.
\date 13 de abril de 2010: Cambio de las dimensiones de la matriz por las
      realmente almacenadas en memoria.
*/
//se añade 0*filMem para que el compilador no dé warning por variable no usada
#define GEOC_POSMATVEC_RMO(filMem,colMem,fil,col) \
((fil)*(colMem)+(col)+0*(filMem))
/******************************************************************************/
/******************************************************************************/
/**
\def GEOC_POSMATVEC_CMO
\brief Calcula la posición de un elemento de una matriz almacenada en COLUMN
       MAJOR ORDER en el vector que la contiene.
\param[in] filMem Filas reales (almacenadas en memoria) de la matriz.
\param[in] colMem Columnas reales (almacenadas en memoria) de la matriz.
\param[in] fil Fila del elemento de trabajo.
\param[in] col Columna del elemento de trabajo.
\return Posición del elemento de trabajo en el vector que almacena la matriz.
\note Esta macro no comprueba si la posición del elemento de trabajo concuerda
      con las dimensiones de la matriz.
\date 25 de noviembre de 2009: Creación de la macro.
\date 13 de abril de 2010: Cambio de las dimensiones de la matriz por las
      realmente almacenadas en memoria.
*/
//se añade 0*colMem para que el compilador no dé warning por variable no usada
#define GEOC_POSMATVEC_CMO(filMem,colMem,fil,col) \
((col)*(filMem)+(fil)+0*(colMem))
/******************************************************************************/
/******************************************************************************/
/**
\def GEOC_POSMATVEC_TRIEM_INF_RMO
\brief Calcula la posición de un elemento de una matriz triangular inferior
       empaquetada en ROW MAJOR ORDER en el vector en el que está almacenada.
\param[in] dim Dimensiones de la matriz (filas==columnas).
\param[in] fil Fila del elemento de trabajo.
\param[in] col Columna del elemento de trabajo.
\return Posición del elemento de trabajo en el vector que almacena la matriz.
\note Esta macro no comprueba si la posición del elemento de trabajo concuerda
      con las dimensiones de la matriz.
\date 29 de enero de 2011: Creación de la macro.
*/
//se añade 0*dim para que el compilador no dé warning por variable no usada
#define GEOC_POSMATVEC_TRIEM_INF_RMO(dim,fil,col) \
((col)+(fil)*((fil)+1)/2+0*(dim))
/******************************************************************************/
/******************************************************************************/
/**
\def GEOC_POSMATVEC_TRIEM_SUP_RMO
\brief Calcula la posición de un elemento de una matriz triangular superior
       empaquetada en ROW MAJOR ORDER en el vector en el que está almacenada.
\param[in] dim Dimensiones de la matriz (filas==columnas).
\param[in] fil Fila del elemento de trabajo.
\param[in] col Columna del elemento de trabajo.
\return Posición del elemento de trabajo en el vector que almacena la matriz.
\note Esta macro no comprueba si la posición del elemento de trabajo concuerda
      con las dimensiones de la matriz.
\date 29 de enero de 2011: Creación de la macro.
*/
#define GEOC_POSMATVEC_TRIEM_SUP_RMO(dim,fil,col) \
((col)-(fil)+(fil)*(2*(dim)-(fil)+1)/2)
/******************************************************************************/
/******************************************************************************/
/**
\def GEOC_POSMATVEC_TRIEM_INF_CMO
\brief Calcula la posición de un elemento de una matriz triangular inferior
       empaquetada en COLUMN MAJOR ORDER en el vector en el que está almacenada.
\param[in] dim Dimensiones de la matriz (filas==columnas).
\param[in] fil Fila del elemento de trabajo.
\param[in] col Columna del elemento de trabajo.
\return Posición del elemento de trabajo en el vector que almacena la matriz.
\note Esta macro no comprueba si la posición del elemento de trabajo concuerda
      con las dimensiones de la matriz.
\date 29 de enero de 2011: Creación de la macro.
*/
#define GEOC_POSMATVEC_TRIEM_INF_CMO(dim,fil,col) \
((fil)-(col)+(col)*(2*(dim)-(col)+1)/2)
/******************************************************************************/
/******************************************************************************/
/**
\def GEOC_POSMATVEC_TRIEM_SUP_CMO
\brief Calcula la posición de un elemento de una matriz triangular superior
       empaquetada en COLUMN MAJOR ORDER en el vector en el que está almacenada.
\param[in] dim Dimensiones de la matriz (filas==columnas).
\param[in] fil Fila del elemento de trabajo.
\param[in] col Columna del elemento de trabajo.
\return Posición del elemento de trabajo en el vector que almacena la matriz.
\note Esta macro no comprueba si la posición del elemento de trabajo concuerda
      con las dimensiones de la matriz.
\date 29 de enero de 2011: Creación de la macro.
*/
//se añade 0*dim para que el compilador no dé warning por variable no usada
#define GEOC_POSMATVEC_TRIEM_SUP_CMO(dim,fil,col) \
((fil)+(col)*((col)+1)/2+0*(dim))
/******************************************************************************/
/******************************************************************************/
/** \enum GEOC_MATR_ID_TRI
\brief Indicador de parte de triangular de matriz.
\date 26 de julio de 2009: Creación del tipo.
*/
enum GEOC_MATR_ID_TRI
{
    /** \brief Indicador de parte triangular superior. */
    GeocMatTriSup=121,
    /** \brief Indicador de parte triangular inferior. */
    GeocMatTriInf=122
};
/******************************************************************************/
/******************************************************************************/
/** \enum GEOC_MATR_ID_DIAG
\brief Indicador del contenido de la diagonal de una matriz triangular.
\date 26 de septiembre de 2009: Creación del tipo.
*/
enum GEOC_MATR_ID_DIAG
{
    /** \brief Indicador de diagonal con algún elemento distinto de 1. */
    GeocMatDiagNoUnos=131,
    /** \brief Indicador de diagonal cuyos elementos son 1. */
    GeocMatDiagUnos=132
};
/******************************************************************************/
/******************************************************************************/
/**
\brief Comprueba si el tipo de almacenamiento utilizado es COLUMN-MAJOR-ORDER.
\return Dos posibilidades:
        - 0: El tipo de almacenamiento es ROW-MAJOR-ORDER.
        - Distinto de 0: El tipo de almacenamiento es COLUMN-MAJOR-ORDER.
\note El tipo de almacenamiento se selecciona en el momento de la compilación
      mediante la definición de una de las siguientes variables:
      \em ROW_MAJOR_ORDER_MATVEC (para un almacenamiento de tipo
      ROW MAJOR ORDER) o \em COLUMN_MAJOR_ORDER_MATVEC (para un almacenamiento
      de tipo COLUMN MAJOR ORDER). En \p gcc, las variables para el
      preprocesador se pasan como \em -DXXX, donde \em XXX es la variable a
      introducir.
\date 29 de julio de 2013: Creación de la función.
*/
int EsAlmMatVecCMO(void);
/******************************************************************************/
/******************************************************************************/
/**
\brief Devuelve el código de almacenamiento utilizado.
\param[out] tipo Cadena de texto identificadora del tipo de almacenamiento. Una
            de las almacenadas en #GEOC_MATR_COD_ALM_RMO o
            #GEOC_MATR_COD_ALM_CMO.
\note El tipo de almacenamiento se selecciona en el momento de la compilación
      mediante la definición de una de las siguientes variables:
      \em ROW_MAJOR_ORDER_MATVEC (para un almacenamiento de tipo
      ROW MAJOR ORDER) o \em COLUMN_MAJOR_ORDER_MATVEC (para un almacenamiento
      de tipo COLUMN MAJOR ORDER). En \p gcc, las variables para el
      preprocesador se pasan como \em -DXXX, donde \em XXX es la variable a
      introducir.
\date 14 de enero de 2009: Creación de la función.
*/
void TipoAlmMatVec(char tipo[]);
/******************************************************************************/
/******************************************************************************/
/**
\brief Devuelve la longitud de las filas o columnas almacenadas en memoria de
       una matriz, según el tipo de almacenamiento utilizado.
\param[in] filMem Filas de la matriz almacenada en memoria.
\param[in] colMem Columnas de la matriz almacenada en memoria.
\return Filas o columnas almacenadas en memoria. Si el tipo de almacenamiento es
        \em ROW_MAJOR_ORDER_MATVEC se devuelve \em colMem, mientras que si es
        \em COLUMN_MAJOR_ORDER_MATVEC se devuelve \em filMem.
\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
\date 19 de noviembre de 2009: Creación de la función.
\date 25 de noviembre de 2009: Cálculos internos mediante macros.
\date 30 de enero de 2011: Añado el identificador \p const a los argumentos de
      entrada.
*/
size_t Lmfc(const size_t filMem,
            const size_t colMem);
/******************************************************************************/
/******************************************************************************/
/**
\brief Devuelve las posiciones entre cada elemento de una fila de una matriz
       densa.
\param[in] filMem Filas de la matriz realmente almacenadas en memoria.
\return Posiciones entre cada elemento de las filas de la matriz.
\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
\date 30 de enero de 2011: Creación de la función.
*/
size_t IncElemFil(const size_t filMem);
/******************************************************************************/
/******************************************************************************/
/**
\brief Devuelve las posiciones entre cada elemento de una columna de una matriz
       densa.
\param[in] colMem Columnas de la matriz realmente almacenadas en memoria.
\return Posiciones entre cada elemento de las columnas de la matriz.
\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
\date 30 de enero de 2011: Creación de la función.
*/
size_t IncElemCol(const size_t colMem);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula la posición de un elemento de una matriz en el vector en el que
       está almacenada.
\param[in] filMem Filas reales (almacenadas en memoria) de la matriz.
\param[in] colMem Columnas reales (almacenadas en memoria) de la matriz.
\param[in] fil Fila del elemento de trabajo.
\param[in] col Columna del elemento de trabajo.
\return Posición del elemento de trabajo en el vector que almacena la matriz.
\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
\note Esta función no comprueba si la posición del elemento de trabajo concuerda
      con las dimensiones de la matriz.
\date 14 de enero de 2009: Creación de la función.
\date 25 de noviembre de 2009: Cálculos internos mediante macros.
\date 13 de abril de 2010: Cambio de las dimensiones de la matriz por las
      realmente almacenadas en memoria.
*/
size_t PosMatVec(const size_t filMem,
                 const size_t colMem,
                 const size_t fil,
                 const size_t col);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula la posición en una matriz a partir de la posición en el vector en
       que está almacenada.
\param[in] filMem Filas reales (almacenadas en memoria) de la matriz.
\param[in] colMem Columnas reales (almacenadas en memoria) de la matriz.
\param[in] posVec Posición en el vector.
\param[out] fil Columna del elemento de trabajo.
\param[out] col Columna del elemento de trabajo.
\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
\note Esta función no comprueba si la posición del elemento de trabajo concuerda
      con las dimensiones de la matriz.
\date 14 de enero de 2009: Creación de la función.
\date 13 de abril de 2010: Cambio de las dimensiones de la matriz por las
      realmente almacenadas en memoria.
*/
void PosVecMat(const size_t filMem,
               const size_t colMem,
               const size_t posVec,
               size_t* fil,
               size_t* col);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula la posición de un elemento de una matriz general banda en el
       vector en el que está almacenada.
\param[in] diagInf Número de subdiagonales de la matriz.
\param[in] diagSup Número de superdiagonales de la matriz.
\param[in] fil Fila del elemento de trabajo.
\param[in] col Columna del elemento de trabajo.
\return Posición del elemento de trabajo en el vector que almacena la matriz.
\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
\note Esta función no comprueba si la posición del elemento de trabajo concuerda
      con las dimensiones y la parte que contiene datos de la matriz.
\date 21 de agosto de 2009: Creación de la función.
*/
size_t PosMatGenBanVec(const size_t diagInf,
                       const size_t diagSup,
                       const size_t fil,
                       const size_t col);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula la posición de un elemento de una matriz triangular empaquetada
       en el vector en el que está almacenada.
\param[in] dim Dimensiones de la matriz (filas==columnas).
\param[in] supInf Identificador de matriz triangular superior o inferior. Ha de
           ser un elemento perteneciente al tipo enumerado #GEOC_MATR_ID_TRI.
\param[in] fil Fila del elemento de trabajo.
\param[in] col Columna del elemento de trabajo.
\return Posición del elemento de trabajo en el vector que almacena la matriz.
\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
\note Esta función no comprueba si el argumento \em supInf es correcto.
\note Esta función no comprueba si la posición del elemento de trabajo concuerda
      con las dimensiones y la parte triangular de la matriz.
\date 26 de julio de 2009: Creación de la función.
*/
size_t PosMatTriEmVec(const size_t dim,
                      const enum GEOC_MATR_ID_TRI supInf,
                      const size_t fil,
                      const size_t col);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula la posición de un elemento de una matriz triangular banda en el
       vector en el que está almacenada.
\param[in] diag Número de superdiagonales o subdiagonales de la matriz.
\param[in] supInf Identificador de matriz triangular superior o inferior. Ha de
           ser un elemento perteneciente al tipo enumerado #GEOC_MATR_ID_TRI.
\param[in] fil Fila del elemento de trabajo.
\param[in] col Columna del elemento de trabajo.
\return Posición del elemento de trabajo en el vector que almacena la matriz.
\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
\note Esta función no comprueba si el argumento \em supInf es correcto.
\note Esta función no comprueba si la posición del elemento de trabajo concuerda
      con las dimensiones y la parte que contiene datos de la matriz.
\date 27 de septiembre de 2009: Creación de la función.
*/
size_t PosMatTriBanVec(const size_t diag,
                       const enum GEOC_MATR_ID_TRI supInf,
                       const size_t fil,
                       const size_t col);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula la posición de un elemento de una matriz simétrica empaquetada en
       el vector en el que está almacenada.
\param[in] dim Dimensiones de la matriz (filas==columnas).
\param[in] supInf Identificador de la parte de matriz simétrica almacenada:
           superior o inferior. Ha de ser un elemento perteneciente al tipo
           enumerado #GEOC_MATR_ID_TRI.
\param[in] fil Fila del elemento de trabajo.
\param[in] col Columna del elemento de trabajo.
\return Posición del elemento de trabajo en el vector que almacena la matriz.
\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
\note Esta función no comprueba si el argumento \em supInf es correcto.
\note Esta función no comprueba si la posición del elemento de trabajo concuerda
      con las dimensiones y la parte triangular de la matriz.
\date 30 de enero de 2010: Creación de la función.
*/
size_t PosMatSimEmVec(const size_t dim,
                      const enum GEOC_MATR_ID_TRI supInf,
                      const size_t fil,
                      const size_t col);
/******************************************************************************/
/******************************************************************************/
/**
\brief Calcula la posición de un elemento de una matriz simétrica banda en el
       vector en el que está almacenada.
\param[in] diag Número de superdiagonales o subdiagonales de la matriz.
\param[in] supInf Identificador de la parte de matriz simétrica almacenada:
           superior o inferior. Ha de ser un elemento perteneciente al tipo
           enumerado #GEOC_MATR_ID_TRI.
\param[in] fil Fila del elemento de trabajo.
\param[in] col Columna del elemento de trabajo.
\return Posición del elemento de trabajo en el vector que almacena la matriz.
\note Esta función comprueba internamente el tipo de almacenamiento utilizado.
\note Esta función no comprueba si el argumento \em supInf es correcto.
\note Esta función no comprueba si la posición del elemento de trabajo concuerda
      con las dimensiones y la parte que contiene datos de la matriz.
\date 27 de septiembre de 2009: Creación de la función.
*/
size_t PosMatSimBanVec(const size_t diag,
                       const enum GEOC_MATR_ID_TRI supInf,
                       const size_t fil,
                       const size_t col);
/******************************************************************************/
/******************************************************************************/
#ifdef __cplusplus
}
#endif
/******************************************************************************/
/******************************************************************************/
#endif
/******************************************************************************/
/******************************************************************************/
/** @} */
/******************************************************************************/
/******************************************************************************/
/* kate: encoding utf-8; end-of-line unix; syntax c; indent-mode cstyle; */
/* kate: replace-tabs on; space-indent on; tab-indents off; indent-width 4; */
/* kate: line-numbers on; folding-markers on; remove-trailing-space on; */
/* kate: backspace-indents on; show-tabs on; */
/* kate: word-wrap-column 80; word-wrap-marker-color #D2D2D2; word-wrap off; */
