/*
    C/C++の宿題片付けます 161代目
    http://t...content-available-to-author-only...h.net/test/read.cgi/tech/1354070278/
        386 名前：デフォルトの名無しさん [aa]： 2012/12/17(月) 18:24:30.48
        二つの２×３型行列を
        A＝1.1　-2.2　0.9
          -0.2　 2.7 0.3
        B= 1.8 0.5 1.3
        -0.4 0.6 -0.3
        と定義する。

        387 名前：デフォルトの名無しさん [ｓｄ]： 2012/12/17(月) 18:26:36.33
        これらの二つの行列の宣言、初期化し、C≡A+B　C≡A-Bを算出して
        ２×３型の表形式で出力するプログラムを作成せよ。ただし、行列CとDは固定長
        配列とし、関数内の演算を行うこと

        上記の問題と同じように行列A、Bを用いて、積C≡ABｔ　を算出し、２×２型の表
        形式で出力せよ。ただし、Bの転置行列、Btはプログラム中に直接記述するのでは
        なく、Bより作成すること。また、Cはnew演算子によりメモリを確保し、関数内で
        演算を行うこと。
 */
#include <stdio.h>

#define MM (2)
#define NN (3)

/* M×N列 表示 */
void m_print_MN(double mx[MM][NN])
{
    int i, j;
    for (i = 0; i < MM; i++) {
        printf("  | ");
        for (j = 0; j < NN; j++) {
            printf("%f ", mx[i][j]);
        }
        printf("|\n");
    }
}

/* pointer行列 表示 */
void m_print_ptr(double **mx, int m, int n)
{
    int i, j;
    for (i = 0; i < m; i++) {
        printf("  | ");
        for (j = 0; j < n; j++) {
            printf("%f ", mx[i][j]);
        }
        printf("|\n");
    }
}

/* 行列確保(new) */
double **m_alloc(int m, int n)
{
    int i;
    double **pma;
    pma = new double *[m];
    pma[0] = new double[m * n];
    for (i = 1; i < m; i++) {
        pma[i] = pma[0] + n * i;
    }
    return pma;
}

/* 行列解放(delete) */
void m_free(double **pma)
{
    delete[]pma[0];
    delete[]pma;
}

/* 加算 */
double **m_add(double s1[MM][NN], double s2[MM][NN])
{
    int i, j;
    double **dst;
    dst = m_alloc(MM, NN);
    for (i = 0; i < MM; i++) {
        for (j = 0; j < NN; j++) {
            dst[i][j] = s1[i][j] + s2[i][j];
        }
    }
    return dst;
}

/* 減算 */
double **m_sub(double s1[MM][NN], double s2[MM][NN])
{
    int i, j;
    double **dst;
    dst = m_alloc(MM, NN);
    for (i = 0; i < MM; i++) {
        for (j = 0; j < NN; j++) {
            dst[i][j] = s1[i][j] - s2[i][j];
        }
    }
    return dst;
}

/* 転置乗算 */
double **m_mul_Bt(double ma[MM][NN], double mb[MM][NN])
{
    int i, j, k;
    double **bt = m_alloc(NN, MM);
    double **dst = m_alloc(MM, MM);
    // Bt
    printf("Bt =\n");
    for (i = 0; i < MM; i++) {
        for (j = 0; j < NN; j++) {
            bt[j][i] = mb[i][j];
        }
    }
    m_print_ptr(bt, NN, MM);
    // mul
    for (i = 0; i < MM; i++) {
        for (j = 0; j < MM; j++) {
            dst[i][j] = 0.0;
            for (k = 0; k < NN; k++) {
                dst[i][j] += ma[i][k] * bt[k][j];
            }
        }
    }
    // end
    m_free(bt);
    return dst;
}

/* */
int main()
{
    int i;

    double mA[MM][NN] = {
        {1.1, -2.2, 0.9},
        {-0.2, 2.7, 0.3}
    };
    double mB[MM][NN] = {
        {1.8, 0.5, 1.3},
        {-0.4, 0.6, -0.3}
    };
    double **mAB_add, **mAB_sub;
    double **mABt_mul;

    // A, B
    printf("A =\n");
    m_print_MN(mA);
    printf("B =\n");
    m_print_MN(mB);
    // A + B
    mAB_add = m_add(mA, mB);
    printf("A + B =\n");
    m_print_ptr(mAB_add, MM, NN);
    // A - B
    mAB_sub = m_sub(mA, mB);
    printf("A - B =\n");
    m_print_ptr(mAB_sub, MM, NN);
    // A × Bt
    mABt_mul = m_mul_Bt(mA, mB);
    printf("A × Bt =\n");
    m_print_ptr(mABt_mul, MM, MM);

    // end
    m_free(mABt_mul);
    m_free(mAB_sub);
    m_free(mAB_add);
    return 0;
}
