/**
 * Author: Shiuh-Sheng Yu
 *         Department of Information Management
 *         National ChiNan University
 * Subject: 矩陣相加與相乘
 * Toolkit: gcc
 */
#include <stdio.h>
// 以巨集定義矩陣元素和動態分配空間的對應關係
// 所謂巨集指的是經由preprocess(前置處理器)取代原始檔內的字串
#define M(x,i,j) *(x->data+i*x->col+j)

// 定義MATRIX為 struct matrix *
// 也就是說MATRIX之型態為 pointer to struct matrix
// 至於struct則是C語言讓使用者 "自訂型態" 的關鍵字
typedef struct matrix {
    int row, col;
    double* data;
} *MATRIX;

/**
 * 由檔案讀入一個矩陣
 */
MATRIX readMatrix(FILE* f) {
    int x, y, i, j;
    char keyword[256];
    MATRIX m;
    /* read in keyword "matrix" */
    fscanf(f, "%s", keyword);
    if (strcmp(keyword,"matrix")!=0) {
        printf("keyword error: %s",keyword);
        return NULL;
    }
    // 動態分配一塊struct matrix大小的空間
    m = (MATRIX) malloc(sizeof(struct matrix));
    /* read in matrix dimension to x y */
    fscanf(f,"%d", &x);
    fscanf(f,"%d", &y);
    m->row = x;
    m->col = y;
    m->data = (double*)malloc(x*y*sizeof(double));
    /* read in x*y double and store them to m->data */
    for (i=0; i<x; i++) {
        for (j=0; j<y; j++) {
            fscanf(f,"%lf", m->data+i*y+j);
        }
    }
    return m;
}

/**
 * 印出矩陣的內容 
 */
void printMatrix(MATRIX x) {
    int i, j;
    for (i=0; i<x->row; i++) {
        for (j=0; j<x->col; j++) {
            printf("%lf ", M(x,i,j));
        }
        printf("\n");
    }
}

/**
 * 矩陣相加
 * 傳回一新矩陣為x,y之和
 */
MATRIX addMatrix(MATRIX x, MATRIX y) {
    int i, j;
    MATRIX m;
    // 檢查兩矩陣的大小是否能相加
    if ((x->row != y->row) || (x->col != y->col)) {
        printf("Matrix dimension mismatch.\n");
        return NULL;
    }
    // 產生新矩陣所需的記憶體空間
    m = (MATRIX) malloc(sizeof(struct matrix));
    m->row = x->row;
    m->col = x->col;
    // 產生存放資料所需的空間
    m->data = (double*)malloc(m->row*m->col*sizeof(double));
    // 進行矩陣的加法運算
    for (i=0; i<m->row; i++) {
        for (j=0; j<m->col; j++) {
            M(m,i,j) = M(x,i,j) + M(y,i,j);
        }
    }
    return m;
}

MATRIX multiplyMatrix(MATRIX x, MATRIX y) {
    /* fill your code */
}

/**
 * 將動態分配矩陣的空間還給系統
 */
void freeMatrix(MATRIX x) {
    free(x->data);
    free(x);
}

int main() {
    char buf[100];
    MATRIX a, b, c;
    // 持續讀入運算符號
    // stdin定義於stdio.h, 代表standard input. 在沒有透過作業系統重新指定
    // 的情形下, 一般為鍵盤
    for (;fscanf(stdin,"%s",buf)!=EOF;) {
        if (buf[0] == '+') {
            if ((a = readMatrix(stdin)) == NULL) {
                break; // 有錯誤則跳離開最接近的迴圈或switch敘述(此處為for迴圈)
            }
            printMatrix(a);
            if ((b = readMatrix(stdin)) == NULL) {
                break;
            }
            printf("+\n");
            printMatrix(b);
            printf("=\n");
            if ((c = addMatrix(a, b)) == NULL) {
                break;
            }
            printMatrix(c);
            printf("\n");
            freeMatrix(a); // 釋放動態分配的矩陣空間
            freeMatrix(b);
            freeMatrix(c);
        } else if (buf[0]=='*') {
            /* fill your code */
        } else {
            printf("Operator error\n");
            break;
        }
    }
}