一个高效的稀疏矩阵转换算法,COO格式转换为DIA格式

COO格式的矩阵存储格式为:

VAL:存储矩阵的值,VAL[x]表示索引为x的值

INDX:存储行的索引值,例如INDX[x]表示索引为x的值其在矩阵中的行号

JNDX:存储列的索引值,例如JNDX[x]表示索引为x的值其在矩阵中的列号

DIA格式的矩阵存储格式为:

VAL:存储矩阵的值,VAL[x]表示索引为x的值,其中,不足lda长度的对角线需要补零,上三角补后面,下三角补在最前面

INDX:存储对角线的偏移值,例如INDX[x]表示索引为x的对角线其在矩阵中的相对中心对角线的偏移值,大于零位于上三角部分,等于零即中心对角线(最长的那根),小于零位于下三角部分

VAL[行号,列号]<=>VAL[对角线偏移,线内索引]:

上三角:行号=线内索引号,列号=对角线偏移+线内索引

下三角:行号=-对角线偏移+线内索引,列号=线内索引

函数参数含义

m:矩阵总行数

n:矩阵总列数

VAL:COO格式的矩阵非零元元素的值

n_VAL:矩阵的非零元个数

INDX:矩阵行索引

JDNX:矩阵列索引

LDA:对角线长度

NDIAG:对角线数量

代码如下:

void dpre_usconv_coo2dia  (int m,int n,double* VAL,int n_VAL,int* INDX,int* JNDX,int* LDA,int* NDIAG)
{
  *NDIAG=0;
  *LDA=m<n?m:n;
  int num_rows,num_cols,num_nonzeros;
  int i,ii,jj,offset,map_index,complete_ndiags,VAL_DIA_size;
  const int unmarked = -1;
  num_rows = m;
  num_cols = n;
  num_nonzeros = n_VAL;
  complete_ndiags = 0;
  int* diag_map = (int*)malloc(sizeof(int)*(num_rows+num_cols));     //mark the diags
  int* diag_offset = (int*)malloc(sizeof(int)*(num_cols+num_rows));
  memset(diag_map,unmarked,sizeof(int)*(num_rows+num_cols));
  memset(diag_offset,unmarked,sizeof(int)*(num_rows+num_cols));

  for(i=0;i<num_nonzeros;i++){
    ii = INDX[i];
    jj = JNDX[i];
    map_index = num_rows-ii+jj;            //used to find the same diag
    if(diag_map[map_index] == unmarked){        
      diag_map[map_index] = complete_ndiags;
      diag_offset[map_index] = jj - ii;             //get index of diags
      complete_ndiags++;                 //number of diags
    }
  }
  *NDIAG = complete_ndiags;
  VAL_DIA_size=(*NDIAG)*(*LDA);
  int* IDIAG=(int*)malloc(sizeof(int)*(complete_ndiags));
  double* VAL_DIA=(double*)malloc(sizeof(double)*VAL_DIA_size);
  memset(IDIAG,0,sizeof(int)*(complete_ndiags));
  memset(VAL_DIA,0,sizeof(double)*VAL_DIA_size);
  for(i=0;i<num_rows + num_cols;i++){
    if(diag_map[i] != unmarked){
      IDIAG[diag_map[i]] = diag_offset[i];     //offset of diags
    }
  }

  // for(i=0;i<complete_ndiags;i++){
  //   printf("%d\t",IDIAG[i]);
  // }

  for(i=0;i<num_nonzeros;i++){    //get values of every diag
    ii = INDX[i];
    jj = JNDX[i];
    map_index = num_rows-ii+jj;
    int diag = diag_map[map_index];
    if((*LDA)-(num_rows-ii)>0){
      offset=(*LDA)-(num_rows-ii);
    }else{
      offset=0;
    }
    VAL_DIA[diag*(*LDA)+offset] = VAL[i];
  }

  // for(i=0;i<VAL_DIA_size;i++){
  //   printf("%lf\t",VAL_DIA[i]);
  // }
  free(diag_map);
  free(diag_offset);
  //把结果的值拷贝到VAL,INDX中
  //其中VAL_DIA中存放斜线中的值
  //INDX中存放斜线号与斜线的偏移值
  VAL=VAL_DIA;
  INDX=IDIAG;
  free(IDIAG);
  free(VAL_DIA);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以参考以下代码: ``` #include <stdio.h> #include <stdlib.h> #define MAXSIZE 100 // 最大非零元个数 typedef struct{ int i, j; // 非零元素的行和列下标 int e; // 非零元素的值 }Triple; typedef struct{ Triple data[MAXSIZE + 1]; // 存储三元组的顺序表,data[0]不使用 int mu, nu, tu; // 矩阵的行数,列数和非零元素的个数 }TSMatrix; int getpos(int i, int j, TSMatrix M) // 查找(i,j)在三元组数组中的位置 { for(int k = 1; k <= M.tu; k++) if(M.data[k].i == i && M.data[k].j == j) return k; return 0; } void getsparse(TSMatrix *M) // 读入稀疏矩阵 { printf("请输入矩阵的行数、列数和非零元素个数:\n"); scanf("%d %d %d", &M->mu, &M->nu, &M->tu); printf("请输入所有非零元素的行、列、值:\n"); for(int k = 1; k <= M->tu; k++) scanf("%d %d %d", &M->data[k].i, &M->data[k].j, &M->data[k].e); } void transposetuple(TSMatrix M, TSMatrix *T) // 稀疏矩阵转置 { T->mu = M.nu; T->nu = M.mu; T->tu = M.tu; if(T->tu){ int q = 1; for(int col = 1; col <= M.nu; col++) // 对每一列进行转置 for(int p = 1; p <= M.tu; p++) // 扫描M中所有元素 if(M.data[p].j == col){ // 将列号为col的元素插入到T中 T->data[q].i = M.data[p].j; T->data[q].j = M.data[p].i; T->data[q].e = M.data[p].e; q++; } } } void printsparse(TSMatrix M) // 输出三元组矩阵 { printf("该矩阵的三元组表示:\n"); for(int i = 1; i <= M.tu; i++){ printf("(%d,%d,%d)", M.data[i].i, M.data[i].j, M.data[i].e); if(i % 5 == 0) printf("\n"); } printf("\n"); } void printtuple(TSMatrix M) // 输出三元组矩阵的行列式 { printf("该稀疏矩阵的三元组顺序表存储:\n"); printf(" i j e\n"); for(int i = 1; i <= M.tu; i++){ printf("%5d%5d%5d\n", M.data[i].i, M.data[i].j, M.data[i].e); } } int main() { TSMatrix M, T; getsparse(&M); printtuple(M); // 打印三元组矩阵 transposetuple(M, &T); printsparse(T); // 打印转置后的三元组矩阵 return 0; } ``` 以上代码通过定义三元组结构体和稀疏矩阵结构体,实现了将稀疏矩阵转换为三元组顺序表存储的功能。在转置时,对每一列扫描M中所有元素,将列号为col的元素插入到T中,最后得到转置后的三元组矩阵。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值