PDA

Visualizza la versione completa : [c] matrice trasposta unico blocco


mariella_88
04-06-2014, 14:52
Salve,
per ottenere migliori prestazioni nel codice, ho deciso di salvare una matrice in un unico blocco di memoria allocandola con calloc(M*N,sizeof(float)) (M righe, N colonne). A questo punto devo calcolare la trasposta ma, non capisco perchè mi escono risultati sbagliati. Per il generico [i][j] ho usato: T[i*(m+1)+j]=X[j*(n+1)]. Vi posto il codice per maggiore chiarezza:


MATRIX trasposta(float* X, int m,int n) {
MATRIX trasp=alloc_matrix(n,m);
int i,j;

for (i = 0; i < n; i++) {

for (j = 0; j < m; j++) {

trasp[i*(n+1)+j]=X[j*(m+1)+i];
}

}
return trasp;

}

la stampa a video:

for(i=0;i<n;i++){
for(j=0;j<m;j++){
printf("T[%d][%d]=%ff ", i,j,T[i*(m+1)+j]);
}
printf("\n");
}
Dimenticavo MATRIX è stato precedentemente definito:
# define MATRIX float*

Scara95
04-06-2014, 14:59
//X N righe, M colonne
int n, m;
for(n = 0; n < N; n++) {
for(m = 0; m < M; m++) {
trasp[m*N+n] = X[n*M+m]
}
}


In generale l'indice lineare è dato da riga*N_COLONNE+colonna

mariella_88
04-06-2014, 15:27
Utilizzando gli indici come hai detto tu ottengo questo risultato:
el[0][0]=3.000000f el[0][1]=4.000000f el[0][2]=5.000000f el[0][3]=6.000000f
el[1][0]=2.000000f el[1][1]=3.000000f el[1][2]=4.000000f el[1][3]=5.000000f
el[2][0]=1.000000f el[2][1]=2.000000f el[2][2]=3.000000f el[2][3]=4.000000f
el[3][0]=7.000000f el[3][1]=8.000000f el[3][2]=9.000000f el[3][3]=0.000000f
el[4][0]=3.000000f el[4][1]=4.000000f el[4][2]=5.000000f el[4][3]=6.000000f
T[0][0]=3.000000f T[0][1]=3.000000f T[0][2]=3.000000f T[0][3]=4.000000f T[0][4]=4.000000f
T[1][0]=5.000000f T[1][1]=0.000000f T[1][2]=7.000000f T[1][3]=0.000000f T[1][4]=1.000000f
T[2][0]=2.000000f T[2][1]=2.000000f T[2][2]=9.000000f T[2][3]=0.000000f T[2][4]=0.000000f

Scara95
04-06-2014, 15:33
Utilizzando gli indici come hai detto tu ottengo questo risultato:
el[0][0]=3.000000f el[0][1]=4.000000f el[0][2]=5.000000f el[0][3]=6.000000f
el[1][0]=2.000000f el[1][1]=3.000000f el[1][2]=4.000000f el[1][3]=5.000000f
el[2][0]=1.000000f el[2][1]=2.000000f el[2][2]=3.000000f el[2][3]=4.000000f
el[3][0]=7.000000f el[3][1]=8.000000f el[3][2]=9.000000f el[3][3]=0.000000f
el[4][0]=3.000000f el[4][1]=4.000000f el[4][2]=5.000000f el[4][3]=6.000000f
T[0][0]=3.000000f T[0][1]=3.000000f T[0][2]=3.000000f T[0][3]=4.000000f T[0][4]=4.000000f
T[1][0]=5.000000f T[1][1]=0.000000f T[1][2]=7.000000f T[1][3]=0.000000f T[1][4]=1.000000f
T[2][0]=2.000000f T[2][1]=2.000000f T[2][2]=9.000000f T[2][3]=0.000000f T[2][4]=0.000000f
Hai cambiato la stampa? In
for(m = 0; m < M; m++) {
for(n = 0; n < N; n++) {
printf("T[%d][%d]=%f ", m, n, T[m*N+n]);
}
printf("\n");
}

mariella_88
04-06-2014, 16:00
Hai cambiato la stampa? In
for(m = 0; m < M; m++) {
for(n = 0; n < N; n++) {
printf("T[%d][%d]=%f ", m, n, T[m*N+n]);
}
printf("\n");
}

Non va lo stesso.. Io non riesco a capire.. Eppure la soluzione è questa.. Potrebbe esserci qualche problema sul compilatore o cose del genere?!

mariella_88
04-06-2014, 16:10
Se lo provo in ambiente window funziona, se lo provo sulla macchina virtuale oon linux mi da questi risultati strani..

Scara95
04-06-2014, 16:16
Posta tutto il codice..

mariella_88
04-06-2014, 18:09
Allora ho provato due versioni entrambe su Ubuntu, la prima calcola tutto nel main e funziona perfettamente:

#include <stdio.h>

# define VECTOR float*
#define MATRIX float*

int main() {
MATRIX Xy;
MATRIX Trasp;
int i,j;
int m=2,n=3;
Xy=calloc(m*(n+1),sizeof(float));;
Trasp=calloc(m*(n+1),sizeof(float));;
for (i = 0; i < m; i++) {

for (j = 0; j < n+1; j++) {

printf("el[%d][%d]= ", i,j);
fflush(stdout);
scanf("\%ff",&Xy[i*(n+1)+j]);
}
printf("\n");
}

for (i = 0; i < m; i++) {

for (j = 0; j < n+1; j++) {

printf("el[%d][%d]=%ff ", i,j,Xy[i*(n+1)+j]);

}
printf("\n");
}

for (i = 0; i < n+1; i++) {

for (j = 0; j < m; j++) {

Trasp[i*(m)+j]=Xy[j*(n+1)+i];

}
printf("\n");
}

for (i = 0; i < n+1; i++) {

for (j = 0; j < m; j++) {

printf("el[%d][%d]=%ff ", i,j,Trasp[i*(m)+j]);

}
printf("\n");
}



return 0;
}

con output corretto:

el[0][0]=4.000000f el[0][1]=5.000000f el[0][2]=6.000000f el[0][3]=7.000000f
el[1][0]=2.000000f el[1][1]=3.000000f el[1][2]=4.000000f el[1][3]=5.000000f



el[0][0]=4.000000f el[0][1]=7.000000f
el[1][0]=4.000000f el[1][1]=5.000000f
el[2][0]=2.000000f el[2][1]=5.000000f
el[3][0]=6.000000f el[3][1]=3.000000f

invece se utilizzo un metodo esterno, come segue:

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <xmmintrin.h>



#define MATRIX float*
#define VECTOR float*
//float inversa(int n, MATRIX c, MATRIX inversa);
void trasposta(MATRIX Xy,MATRIX T,int n, int m);

void* get_block(int size, int elements) {
return _mm_malloc(elements * size, 16);
}

void free_block(void* p) {
_mm_free(p);
}

MATRIX alloc_matrix(int rows, int cols) {
return (MATRIX) get_block(sizeof(float),rows*cols);
}

void dealloc_matrix(MATRIX mat) {
free_block(mat);
}

float frand() {
float r = (float) rand();
return r / RAND_MAX;
}


MATRIX random_input(int m, int n) {
int i, j;
MATRIX A = alloc_matrix(m,n+1);
float x, y, e;
float* beta = calloc(n,sizeof(float));

for (i = 0; i < n; i++)
beta[i] = frand();
e = frand()*0.2;

for (i = 0; i < m; i++) {
y = 0;
for (j = 0; j < n; j++) {
if (j < n-1)
x = frand();
else
x = 1.0;
A[i*(n+1)+j] = x;
y += x*beta[j];
}
A[i*(n+1)+n] = y*(1+frand()*e-e/2);
}

free(beta);
return A;
}

void trasposta(MATRIX Xy,MATRIX T,int n, int m)
{
int i,j;
for (i = 0; i < m; i++) {

for (j = 0; j < n; j++) {

T[i*(m)+j]=Xy[j*(n)+i];


}
printf("\n");
}
}

int main() {
MATRIX Xy;
MATRIX Trasp;
int i,j;
int m=2,n=3;
Xy=calloc(m*(n+1),sizeof(float));;
Trasp=calloc(m*(n+1),sizeof(float));
for (i = 0; i < m; i++) {

for (j = 0; j < n+1; j++) {

printf("el[%d][%d]= ", i,j);
fflush(stdout);
scanf("\%ff",&Xy[i*(n+1)+j]);
}
printf("\n");
}

for (i = 0; i < m; i++) {

for (j = 0; j < n+1; j++) {

printf("el[%d][%d]=%ff ", i,j,Xy[i*(n+1)+j]);

}
printf("\n");
}

trasposta(Xy,Trasp,m,n+1);


for (i = 0; i < n+1; i++) {

for (j = 0; j < m; j++) {

printf("el[%d][%d]=%ff ", i,j,Trasp[i*(m)+j]);

}
printf("\n");
}



return 0;
}

come risultato esce qualcosa di sballato del tipo:
el[0][0]=1.000000f el[0][1]=2.000000f el[0][2]=3.000000f el[0][3]=4.000000f
el[1][0]=5.000000f el[1][1]=6.000000f el[1][2]=7.000000f el[1][3]=8.000000f




el[0][0]=1.000000f el[0][1]=3.000000f
el[1][0]=0.000000f el[1][1]=0.000000f
el[2][0]=2.000000f el[2][1]=4.000000f
el[3][0]=0.000000f el[3][1]=0.000000f

Che cosa sbaglio?!?!
PS: vi prego di ignorare i primi metodi come alloc_matrix o random_input sono dei metodi di supporto che mi servono piu avanti

Scara95
04-06-2014, 18:55
void trasposta(MATRIX Xy,MATRIX T,int n, int m)
{
int i,j;
for (i = 0; i < m; i++) {

for (j = 0; j < n; j++) {

T[i*(m)+j]=Xy[j*(n)+i];


}
printf("\n");
}
}
Hai invertito n e m oppure i e j. Insomma confronta quel codice col ciclo sopra.

Loading