/* -*- coding: utf-8 -*- */
/**
\ingroup algebra anespec geopot gshhs matriz mmcc snx
@{
\file posmatvec.c
\brief Definición de funciones para realizar cálculos de posiciones de
       elementos en matrices almacenadas en formato vector.
\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.
*/
/******************************************************************************/
/******************************************************************************/
#include"libgeoc/posmatvec.h"
/******************************************************************************/
/******************************************************************************/
int EsAlmMatVecCMO(void)
{
    //determinamos la salida dependiendo del tipo de almacenamiento
#if defined(ROW_MAJOR_ORDER_MATVEC)
    //el almacenamiento no es column major order
    return 0;
#elif defined(COLUMN_MAJOR_ORDER_MATVEC)
    //el almacenamiento es column major order
    return 1;
#else
    #error *****No se ha definido el tipo de almacenamiento matricial
#endif
}
/******************************************************************************/
/******************************************************************************/
void TipoAlmMatVec(char tipo[])
{
    //determinamos la cadena de código dependiendo del tipo de almacenamiento
#if defined(ROW_MAJOR_ORDER_MATVEC)
    //asignamos la cadena correspondiente al tipo row major order
    strcpy(tipo,GEOC_MATR_COD_ALM_RMO);
#elif defined(COLUMN_MAJOR_ORDER_MATVEC)
    //asignamos la cadena correspondiente al tipo column major order
    strcpy(tipo,GEOC_MATR_COD_ALM_CMO);
#else
    #error *****No se ha definido el tipo de almacenamiento matricial
#endif
    ////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////
    //salimos de la función
    return;
}
/******************************************************************************/
/******************************************************************************/
size_t Lmfc(const size_t filMem,
            const size_t colMem)
{
    //distinguimos según el tipo de almacenamiento
#if defined(ROW_MAJOR_ORDER_MATVEC)
    //almacenamiento row major order
    return GEOC_LMFC_RMO(filMem,colMem);
#elif defined(COLUMN_MAJOR_ORDER_MATVEC)
    //almacenamiento column major order
    return GEOC_LMFC_CMO(filMem,colMem);
#else
    #error *****No se ha definido el tipo de almacenamiento matricial
#endif
}
/******************************************************************************/
/******************************************************************************/
size_t IncElemFil(const size_t filMem)
{
    //distinguimos según el tipo de almacenamiento
#if defined(ROW_MAJOR_ORDER_MATVEC)
    //almacenamiento row major order
    //0*filMem para que el compilador no dé warning por variable no usada
    return 1+0*filMem;
#elif defined(COLUMN_MAJOR_ORDER_MATVEC)
    //almacenamiento column major order
    return filMem;
#else
    #error *****No se ha definido el tipo de almacenamiento matricial
#endif
}
/******************************************************************************/
/******************************************************************************/
size_t IncElemCol(const size_t colMem)
{
    //distinguimos según el tipo de almacenamiento
#if defined(ROW_MAJOR_ORDER_MATVEC)
    //almacenamiento row major order
    return colMem;
#elif defined(COLUMN_MAJOR_ORDER_MATVEC)
    //almacenamiento column major order
    //0*colMem para que el compilador no dé warning por variable no usada
    return 1+0*colMem;
#else
    #error *****No se ha definido el tipo de almacenamiento matricial
#endif
}
/******************************************************************************/
/******************************************************************************/
size_t PosMatVec(const size_t filMem,
                 const size_t colMem,
                 const size_t fil,
                 const size_t col)
{
    //calculamos la posición en el vector dependiendo del tipo de almacenamiento
#if defined(ROW_MAJOR_ORDER_MATVEC)
    //almacenamiento row major order
    return GEOC_POSMATVEC_RMO(filMem,colMem,fil,col);
#elif defined(COLUMN_MAJOR_ORDER_MATVEC)
    //almacenamiento column major order
    return GEOC_POSMATVEC_CMO(filMem,colMem,fil,col);
#else
    #error *****No se ha definido el tipo de almacenamiento matricial
#endif
}
/******************************************************************************/
/******************************************************************************/
void PosVecMat(const size_t filMem,
               const size_t colMem,
               const size_t posVec,
               size_t* fil,
               size_t* col)

{
    //calculamos la posición en la matriz dependiendo del tipo de almacenamiento
#if defined(ROW_MAJOR_ORDER_MATVEC)
    //calculamos la fila
    //la division se realiza entre elementos del mismo tipo, por lo que el
    //resultado tambien lo es (el redondeo de la division se hace por
    //truncamiento)
    //se añade el factor 0*filMem para que el compilador no emita un warning por
    //variable no usada
    *fil = posVec/colMem+0*filMem;
    //calculamos la columna
    *col = posVec%colMem;
#elif defined(COLUMN_MAJOR_ORDER_MATVEC)
    //calculamos la fila
    *fil = posVec%filMem;
    //calculamos la columna
    //la division se realiza entre elementos del mismo tipo, por lo que el
    //resultado tambien lo es (el redondeo de la division se hace por
    //truncamiento)
    //se añade el factor 0*colMem para que el compilador no emita un warning por
    //variable no usada
    *col = posVec/filMem+0*colMem;
#else
    #error *****No se ha definido el tipo de almacenamiento matricial
#endif
    ////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////
    //salimos de la función
    return;
}
/******************************************************************************/
/******************************************************************************/
size_t PosMatGenBanVec(const size_t diagInf,
                       const size_t diagSup,
                       const size_t fil,
                       const size_t col)
{
    //filas de la matriz empaquetada si el almacenamiento es COLUMN MAJOR ORDER
    //y columnas si es ROW MAJOR ORDER
    size_t lda=diagSup+diagInf+1;
    //calculamos la posición en el vector dependiendo del tipo de almacenamiento
#if defined(ROW_MAJOR_ORDER_MATVEC)
    //columna en la matriz empaquetada donde se encuentra el elemento de trabajo
    size_t colAux=diagInf-fil+col;
    //calculamos la posición en el vector
    return fil*lda+colAux;
#elif defined(COLUMN_MAJOR_ORDER_MATVEC)
    //fila en la matriz empaquetada donde se encuentra el elemento de trabajo
    size_t filAux=diagSup+fil-col;
    //calculamos la posición en el vector
    return col*lda+filAux;
#else
    #error *****No se ha definido el tipo de almacenamiento matricial
#endif
}
/******************************************************************************/
/******************************************************************************/
size_t PosMatTriEmVec(const size_t dim,
                      const enum GEOC_MATR_ID_TRI supInf,
                      const size_t fil,
                      const size_t col)
{
    //calculamos la posición en el vector dependiendo del tipo de almacenamiento
#if defined(ROW_MAJOR_ORDER_MATVEC)
    //distinguimos entre matriz triangular superior e inferior
    if(supInf==GeocMatTriSup)
    {
        //calculamos la posición
        return GEOC_POSMATVEC_TRIEM_SUP_RMO(dim,fil,col);
    }
    else
    {
        //calculamos la posición
        return GEOC_POSMATVEC_TRIEM_INF_RMO(dim,fil,col);
    }
#elif defined(COLUMN_MAJOR_ORDER_MATVEC)
    //distinguimos entre matriz triangular superior e inferior
    if(supInf==GeocMatTriSup)
    {
        //calculamos la posición
        return GEOC_POSMATVEC_TRIEM_SUP_CMO(dim,fil,col);
    }
    else
    {
        //calculamos la posición
        return GEOC_POSMATVEC_TRIEM_INF_CMO(dim,fil,col);
    }
#else
    #error *****No se ha definido el tipo de almacenamiento matricial
#endif
}
/******************************************************************************/
/******************************************************************************/
size_t PosMatTriBanVec(const size_t diag,
                       const enum GEOC_MATR_ID_TRI supInf,
                       const size_t fil,
                       const size_t col)
{
    //diagonales de la matriz de trabajo
    size_t diagInf=0,diagSup=0;
    ////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////
    //calculamos las diagonales de la matriz de trabajo
    if(supInf==GeocMatTriSup)
    {
        diagSup = diag;
    }
    else if(supInf==GeocMatTriInf)
    {
        diagInf = diag;
    }
    ////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////
    //calculamos la posicion
    return PosMatGenBanVec(diagInf,diagSup,fil,col);
}
/******************************************************************************/
/******************************************************************************/
size_t PosMatSimEmVec(const size_t dim,
                      const enum GEOC_MATR_ID_TRI supInf,
                      const size_t fil,
                      const size_t col)
{
    //calculamos y salimos de la función
    return PosMatTriEmVec(dim,supInf,fil,col);
}
/******************************************************************************/
/******************************************************************************/
size_t PosMatSimBanVec(const size_t diag,
                       const enum GEOC_MATR_ID_TRI supInf,
                       const size_t fil,
                       const size_t col)
{
    //calculamos y salimos de la función
    return PosMatTriBanVec(diag,supInf,fil,col);
}
/******************************************************************************/
/******************************************************************************/
/** @} */
/******************************************************************************/
/******************************************************************************/
/* 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; */
