/**************************************************************************
	行/列求和函数。按下面的要求编辑此文件：
	1. 将你的学号、姓名，以注释的方式写到下面；
	2. 实现不同版本的行列求和函数；
	3. 编辑rc_fun_rec rc_fun_tab数组，将你的最好的答案
		（最好的行和列求和、最好的列求和）作为数组的前两项
***************************************************************************/
   
/*
	学号：202302723005
	姓名：程景愉
*/


#include  <stdio.h>
#include  <stdlib.h>
#include  "rowcol.h"
#include  <math.h>

/* 参考的列求和函数实现 */
/* 计算矩阵中的每一列的和。请注意对于行和列求和来说，调用参数是
	一样的，只是第2个参数不会用到而已
*/
/*
void c_sum(matrix_t M, vector_t rowsum, vector_t colsum)
{
    int i,j;
    for (j = 0; j < N; j++) {
	colsum[j] = 0;
	for (i = 0; i < N; i++)
	    colsum[j] += M[i][j];
    }
}
*/
void c_sum(matrix_t M, vector_t rowsum, vector_t colsum) {
  int i, j;
  for (j = 0; j < N; j += 4) {
    int sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0;
    for (i = 0; i < N; i++) {
      sum0 += M[i][j];
      sum1 += M[i][j + 1];
      sum2 += M[i][j + 2];
      sum3 += M[i][j + 3];
    }
    colsum[j] = sum0;
    colsum[j + 1] = sum1;
    colsum[j + 2] = sum2;
    colsum[j + 3] = sum3;
  }
}


/* 参考的列和行求和函数实现 */
/* 计算矩阵中的每一行、每一列的和。 */
/*
void rc_sum(matrix_t M, vector_t rowsum, vector_t colsum)
{
    int i,j;
    for (i = 0; i < N; i++) {
	rowsum[i] = colsum[i] = 0;
	for (j = 0; j < N; j++) {
	    rowsum[i] += M[i][j];
	    colsum[i] += M[j][i];
	}
    }
}
*/
void rc_sum(matrix_t M, vector_t rowsum, vector_t colsum) {
  int i, j;
  // 初始化colsum
  for (i = 0; i < N; i++) {
    colsum[i] = 0;
  }

  // 分块处理，提高缓存利用率
  for (i = 0; i < N; i += 4) {
    int row_sum0 = 0, row_sum1 = 0, row_sum2 = 0, row_sum3 = 0;
    for (j = 0; j < N; j++) {
      // 计算行和
      row_sum0 += M[i][j];
      row_sum1 += M[i + 1][j];
      row_sum2 += M[i + 2][j];
      row_sum3 += M[i + 3][j];

      // 同时更新列和
      colsum[j] += M[i][j] + M[i + 1][j] + M[i + 2][j] + M[i + 3][j];
    }
    rowsum[i] = row_sum0;
    rowsum[i + 1] = row_sum1;
    rowsum[i + 2] = row_sum2;
    rowsum[i + 3] = row_sum3;
  }
}



/* 
	这个表格包含多个数组元素，每一组元素（函数名字, COL/ROWCOL, "描述字符串"）
	COL表示该函数仅仅计算每一列的和
	ROWCOL表示该函数计算每一行、每一列的和
	将你认为最好的两个实现，放在最前面。
	比如：
	{my_c_sum1, "超级垃圾列求和实现"},
	{my_rc_sum2, "好一点的行列求和实现"},
*/

rc_fun_rec rc_fun_tab[] = 
{

  /* 第一项，应当是你写的最好列求和的函数实现 */
    {c_sum, COL, "Best column sum"},
  /* 第二项，应当是你写的最好行列求和的函数实现 */
    {rc_sum, ROWCOL, "Best row and column sum"},

    {c_sum, COL, "Column sum, reference implementation"},

    {rc_sum, ROWCOL, "Row and column sum, reference implementation"},

 /* 下面的代码不能修改或者删除！！表明数组列表结束 */
    {NULL,ROWCOL,NULL}
};
