#include "../include/lass.h"

/**
 *
 * 	@file ddss_dtiled_laswp.c
 *
 * 	@brief LASs-DDSs ddss_dtiled_laswp routines.
 *
 * 	LASs-DDSs is a software package provided by:
 * 	Barcelona Supercomputing Center - Centro Nacional de Supercomputacion
 *
 * 	@author Davor Davidovic
 * 	@date 2019-04-16
 * 	@reviewer 
 * 	@modified 
 *
 **/

/**
 *  
 *	@ingroup DDSs
 *   
 *  ddss_dtiled_laswp:
 *	Performs the rows interchanges obtained from the dgetrf routine on the 
 *  panel stored in tiled layout.
 *
**/

/**
 * 
 * 	@param[in]
 *	M		int.	
 *	        M specifies the number of rows of the flat matrix.
 * 
 * 	@param[in]
 *	N		int.	
 *	        N specifies the number of columns of the flat matrix.
 *	
 * 	@param[in, out]
 *	A		double *.	
 *	        A is a pointer to the flat matrix.
 *
 * 	@param[in]
 *	LDA		int.
 *  		LDA specifies the number of columns ( row-major order ) of matrix A.
 *
 * 	@param[in]
 *	MT		int.	
 *	        MT specifies the number of rows of the matrix TILE_A.
 *			
 * 	@param[in]
 *	NT		int.
 *  		NT specifies the number of columns of the matrix TILE_A.
 *
 * 	@param[in]
 *	TILE_A	double *.
 *  		TILE_A is a pointer to the tile matrix.
 *
 **/ 

/**
 *
 *	@sa ddss_dscatter_tile
 *	@sa ddss_tile_size
 *
 **/ 
/* Converts from tiled to flat format.
 * Matrix A can be a submatrix, but TILE_A should ALWAYS be the pointer the 
 * start of the original array. The position (start tile) in TILE_A is defined
 * value starti and startj, which correspond to the start tile indices
 * by rows and columns, respectively) */

// Be careful, the indices in ipiv came from lapack routines and are 
// 1-order indexing!
void ddss_dtiled_laswp( int N, int mi, int ni, int MT, int NT, 
		double (*TILE_A)[NT][TILE_SIZE * TILE_SIZE],  
		int K1, int K2, int *ipiv, int incx )
{

	// Local variables
	int m_tile_idx;		// Index of the tile where ipiv(i) rows is
	int m_tile_i;		// Position of the row ipiv(i) inside tile pni
	int lda = TILE_SIZE;
	double temp;
	
	// Iterate over K1:K2-1 indices of the permutation vector
	for ( int i = K1; i < K2; i += incx )
	{
		// If rows interchanged
		if(ipiv[i]-1 != i){
			
			// Find the tile index and the position witin the tile of the row 
			// ipiv(i)
			m_tile_idx = (ipiv[i]-1) / TILE_SIZE;
			m_tile_i =  ipiv[i]-1 - m_tile_idx * TILE_SIZE;
			m_tile_idx += mi;

			// Interchange row i from tile[mi][ni] with the row pi_ni from 
			// tile[mi][pni]
			for ( int j = 0; j < N; j++ ){
				temp = TILE_A[mi][ni][i*lda+j];
				TILE_A[mi][ni][i*lda+j] = 
					TILE_A[m_tile_idx][ni][m_tile_i*lda+j];
				TILE_A[m_tile_idx][ni][m_tile_i*lda+j] = temp;
			}
		}
	}
}
