/* 1992.10.3 守屋一成(morip)作 */
/* 1993.6.27 一部変更 */
/* 1994.2.13 複素数に拡張、ユーザ定数が使用可能 */
/* 1995.2.12 行列化、対話モード導入 */
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#define UCN 100
#define CNL 10

#define PI 3.1415926535897932384626433832795028841971693
#define IMAG cmplx(0.0,1.0)
#define NEGA cmplx(-1.0,0.0)

struct cmplx {
  double re;
  double im;
};
struct mat {
  struct cmplx **mat;
  int row;
  int column;
};
struct con {
  char name[CNL];
  struct mat val;
};

int ssp;
int matcalerr;
struct con cnst[UCN];

struct mat analyze(char[]);
struct mat makemat(char[]);
struct mat takevalue(char[], int *);
struct mat biterm(char[], struct mat, int *, int);
int *form(struct mat *, int, int);
double deg(double);
double rad(double);
double arg(struct cmplx);
double cabs(struct cmplx);
struct cmplx casin(struct cmplx);
struct cmplx cmplx(double, double);
struct cmplx cadd(struct cmplx, struct cmplx);
struct cmplx cmulti(struct cmplx, struct cmplx);
struct cmplx cdivid(struct cmplx, struct cmplx);
struct cmplx cmod(struct cmplx, struct cmplx);
struct cmplx cacos(struct cmplx);
struct cmplx catan(struct cmplx);
struct cmplx ccos(struct cmplx);
struct cmplx ccosh(struct cmplx);
struct cmplx cexp(struct cmplx);
struct cmplx clog(struct cmplx);
struct cmplx csin(struct cmplx);
struct cmplx csinh(struct cmplx);
struct cmplx csqrt(struct cmplx);
struct cmplx ctan(struct cmplx);
struct cmplx ctanh(struct cmplx);
struct cmplx cpow(struct cmplx, struct cmplx);
struct cmplx cfloor(struct cmplx);
struct mat madd(struct mat, struct mat);
struct mat mmulti(struct mat, struct mat);
struct mat mmod(struct mat, struct mat);
struct mat det(struct mat);
struct mat inv(struct mat);
struct mat umat(int);
struct mat trans(struct mat x);
struct mat mabs(struct mat x);
struct mat macos(struct mat);
struct mat masin(struct mat);
struct mat matan(struct mat);
struct mat mcos(struct mat);
struct mat mcosh(struct mat);
struct mat mexp(struct mat);
struct mat mlog(struct mat);
struct mat msin(struct mat);
struct mat msinh(struct mat);
struct mat msqrt(struct mat);
struct mat mtan(struct mat);
struct mat mtanh(struct mat);
struct mat mpow(struct mat, struct mat);
struct mat mceil(struct mat);
struct mat mfloor(struct mat);
struct mat mpai(struct mat, struct mat, char[]);
struct mat msigma(struct mat, struct mat, char[]);
struct mat msinc(struct mat);
struct mat mpulse(struct mat);
struct mat mtriangle(struct mat);
struct mat mroot(struct mat, struct mat);
struct mat mreal(struct mat x);
struct mat mimag(struct mat x);
struct mat mconj(struct mat x);
struct mat marg(struct mat x);
struct mat mrad(struct mat x);
struct mat mdeg(struct mat x);
double sinc(double);
double pulse(double);
double triangle(double);
int next(char[], int, char, char);
int level(char);
unsigned prtcpy(char[], int, int);
unsigned spacefilter(char[]);
void ansprnt(char[]);
void mprintf(struct mat ansr);

double deg(double x)
{
  double y;
  
  y = 180.0 * x / PI;
  
  return y;
}

double rad(double x)
{
  double y;
  
  y = PI * x / 180.0;
  
  return y;
}

struct mat mdeg(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j].re = 180.0 * x.mat[i][j].re / PI;
      y.mat[i][j].im = 0.0;
    }
  }
  
  return y;
}

struct mat mrad(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j].re = PI * x.mat[i][j].re / 180.0;
      y.mat[i][j].im = 0.0;
    }
  }
  
  return y;
}

struct cmplx cmplx(double x1, double x2)
{
  struct cmplx y;
  
  y.re = x1;
  y.im = x2;
  
  return y;
}

double arg(struct cmplx x)
{
  double y;
  
  if (x.re == 0.0) {
    y = PI / 2.0;
    if (x.im < 0.0) {
      y = -y;
    }
  }
  else {
    y = atan(x.im / x.re);
    if (x.re < 0.0) {
      if (x.im >= 0.0) {
        y = y + PI;
      }
      else {
        y = y - PI;
      }
    }
  }
  
  return y;
}

struct cmplx cadd(struct cmplx x1, struct cmplx x2)
{
  struct cmplx y;
  
  y.re = x1.re + x2.re;
  y.im = x1.im + x2.im;
  
  return y;
}

struct mat madd(struct mat x1, struct mat x2)
{
  int i, j;
  struct mat y;
  
  if (x1.row == x2.row && x1.column == x2.column) {
    if (form(&y, x1.row, x1.column) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    for (i = 0; i <= y.row - 1; i++) {
      for (j = 0; j <= y.column - 1; j++) {
        y.mat[i][j] = cadd(x1.mat[i][j], x2.mat[i][j]);
      }
    }
  }
  else if (x1.row == 1 && x1.column == 1 && cabs(x1.mat[0][0]) == 0.0) {
    if (form(&y, x2.row, x2.column) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    for (i = 0; i <= y.row - 1; i++) {
      for (j = 0; j <= y.column - 1; j++) {
        y.mat[i][j] = x2.mat[i][j];
      }
    }
  }
  else if (x2.row == 1 && x2.column == 1 && cabs(x2.mat[0][0]) == 0.0) {
    if (form(&y, x1.row, x1.column) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    for (i = 0; i <= y.row - 1; i++) {
      for (j = 0; j <= y.column - 1; j++) {
        y.mat[i][j] = x1.mat[i][j];
      }
    }
  }
  else {
    matcalerr = 1;
    if (form(&y, 1, 1) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    y.mat[0][0] = cmplx(0.0, 0.0);
  }
  
  return y;
}

struct cmplx cmulti(struct cmplx x1, struct cmplx x2)
{
  struct cmplx y;
  
  y.re = x1.re * x2.re - x1.im * x2.im;
  y.im = x1.re * x2.im + x1.im * x2.re;
  
  return y;
}

struct mat mmulti(struct mat x1, struct mat x2)
{
  int i, j, k;
  struct mat y;
  
  if (x1.column == x2.row) {
    if (form(&y, x1.row, x2.column) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    for (i=0; i <= y.row - 1; i++) {
      for ( j=0; j <= y.column - 1; j++) {
        y.mat[i][j] = cmulti(x1.mat[i][0], x2.mat[0][j]);
        for (k = 1; k <= x1.column - 1; k++) {
          y.mat[i][j] = cadd(y.mat[i][j], cmulti(x1.mat[i][k], x2.mat[k][j]));
        }
      }
    }
  }
  else if (x1.row == 1 && x1.column == 1) {
    if (form(&y, x2.row, x2.column) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    for (i = 0; i <= y.row - 1; i++) {
      for (j = 0; j <= y.column - 1; j++) {
        y.mat[i][j] = cmulti(x1.mat[0][0], x2.mat[i][j]);
      }
    }
  }
  else if (x2.row == 1 && x2.column == 1) {
    if (form(&y, x1.row, x1.column) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    for (i = 0; i <= y.row - 1; i++) {
      for (j = 0; j <= y.column - 1; j++) {
        y.mat[i][j] = cmulti(x2.mat[0][0], x1.mat[i][j]);
      }
    }
  }
  else {
    matcalerr = 1;
    if (form(&y, 1, 1) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    y.mat[0][0] = cmplx(0.0, 0.0);
  }
  
  return y;
}

struct cmplx cdivid(struct cmplx x1, struct cmplx x2)
{
  struct cmplx y;
  
  y.im = cabs(x2) * cabs(x2);
  
  if (y.im != 0.0) {
    y.re = (x1.re * x2.re + x1.im * x2.im) / y.im;
    y.im = (x1.im * x2.re - x1.re * x2.im) / y.im;
  }
  else {
    matcalerr = 100;
    y.re = 1.0e300;
    y.im = 1.0e300;
  }
  
  return y;
}

struct mat mmod(struct mat x1, struct mat x2)
{
  int i, j;
  struct mat y;
  
  
  if (x1.row == x2.row && x1.column == x2.column && x1.row == x1.column) {
    char c[3];
    
    strcpy(c,"-1");
    y=madd(x1, mmulti(makemat(c), mmulti(mfloor(mmulti(x1, inv(x2))), x2)));
  }
  else if (x1.row == 1 && x1.column == 1) {
    if (form(&y, x2.row, x2.column) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    for (i = 0; i <= x2.row - 1; i++) {
      for (j = 0; j <= x2.column - 1; j++) {
        y.mat[i][j] = cadd(x1.mat[0][0], cmulti(NEGA, cmulti(cfloor(cdivid(x1.mat[0][0], x2.mat[i][j])), x2.mat[i][j])));
      }
    }
  }
  else if (x2.row == 1 && x2.column == 1) {
    if (form(&y, x1.row, x1.column) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    for (i = 0; i <= x1.row - 1; i++) {
      for (j = 0; j <= x1.column - 1; j++) {
        y.mat[i][j] = cadd(x1.mat[i][j], cmulti(NEGA, cmulti(cfloor(cdivid(x1.mat[i][j], x2.mat[0][0])), x2.mat[0][0])));
      }
    }
    
  }
  else {
    matcalerr = 1;
    if (form(&y, 1, 1) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    y.mat[0][0] = cmplx(0.0, 0.0);
  }
  
  return y;
}

struct cmplx cmod(struct cmplx x1, struct cmplx x2)
{
  struct cmplx y;
  
  y.re = fmod(x1.re, x2.re);
  y.im = fmod(x1.im, x2.im);
  
  return y;
}

struct mat det(struct mat x)
{
  int i, j, k, in, sg;
  struct cmplx ct;
  struct mat tmp, y;
  
  sg = 1;
  if (form(&tmp, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  for (i = 0; i <= x.row - 1; i++) {
    for (j = 0; j <= x.column - 1; j++) {
      tmp.mat[i][j] = x.mat[i][j];
    }
  }
  
  if (x.row == x.column) {
    if (form(&y, 1, 1) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    if (tmp.row == 1) {
      y.mat[0][0] = tmp.mat[0][0];
    }
    else if (tmp.row == 2) {
      y.mat[0][0] = cadd(cmulti(tmp.mat[0][0], tmp.mat[1][1]), cmulti(NEGA, cmulti(tmp.mat[0][1], tmp.mat[1][0])));
    }
    else {
      for (i = 0; i <= tmp.row - 2; i++) {
        in = i;
        for (j = i + 1; j <= tmp.row - 1; j++) {
          if (cabs(tmp.mat[in][i]) < cabs(tmp.mat[j][i])) {
            in = j;
          }
        }
        if (in != i) {
          for (j = i; j <= tmp.row - 1; j++) {
            ct = tmp.mat[in][j];
            tmp.mat[in][j] = tmp.mat[i][j];
            tmp.mat[i][j] = ct;
          }
          sg = -1 * sg;
        }
        for (j = i + 1; j <= tmp.row - 1; j++) {
          ct = cdivid(tmp.mat[j][i], tmp.mat[i][i]);
          for (k = i + 1; k <= tmp.row - 1; k++) {
            tmp.mat[j][k] = cadd(tmp.mat[j][k], cmulti(NEGA, cmulti(ct, tmp.mat[i][k])));
          }
        }
      }
      y.mat[0][0] = tmp.mat[0][0];
      for (i = 1; i <= tmp.row - 1; i++) {
        y.mat[0][0] = cmulti(cmplx(sg, 0.0), cmulti(y.mat[0][0], tmp.mat[i][i]));
      }
    }
  }
  else {
    matcalerr = 2;
    if (form(&y, 1, 1) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    y.mat[0][0] = cmplx(0.0, 0.0);
  }
  
  free(tmp.mat);
  
  return y;
}

struct mat inv(struct mat x)
{
  int i, j, k, in, sg;
  struct cmplx ct;
  struct mat tmp, y;
  
  sg = 1;
  if (form(&tmp, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  for (i = 0; i <= x.row - 1; i++) {
    for (j = 0; j <= x.column - 1; j++) {
      tmp.mat[i][j] = x.mat[i][j];
    }
  }
  
  if (x.row == x.column) {
    if (form(&y, x.row, x.column) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    y = umat(y.row);
    
    if (x.row == 1) {
      y.mat[0][0] = cdivid(cmplx(1.0, 0.0), x.mat[0][0]);
    }
    else if (x.row == 2) {
      tmp = det(x);
      y.mat[0][0] = cdivid(x.mat[1][1], tmp.mat[0][0]);
      y.mat[1][1] = cdivid(x.mat[0][0], tmp.mat[0][0]);
      y.mat[0][1] = cmulti(NEGA, cdivid(x.mat[0][1], tmp.mat[0][0]));
      y.mat[1][0] = cmulti(NEGA, cdivid(x.mat[1][0], tmp.mat[0][0]));
    }
    else {
      for (i = 0; i <= x.row - 1; i++) {
        /*
        in = i;
        for (j = i + 1; j <= x.row - 1; j++) {
          if (cabs(tmp.mat[in][i]) < cabs(tmp.mat[j][i])) {
            in = j;
          }
        }
        if (in != i) {
          for (j = 0; j <= tmp.row - 1; j++) {
            ct = tmp.mat[in][j];
            tmp.mat[in][j] = tmp.mat[i][j];
            tmp.mat[i][j] = ct;
          }
          sg = -1 * sg;
        }
        */
        for (k = i + 1; k <= tmp.row - 1; k++) {
          tmp.mat[i][k] = cdivid(tmp.mat[i][k], tmp.mat[i][i]);
        }
        for (k = 0; k <= y.row - 1; k++) {
          y.mat[i][k] = cdivid(y.mat[i][k], tmp.mat[i][i]);
        }
        for (j = 0; j <= tmp.row - 1; j++) {
          if (j != i){
            for (k = i + 1; k <= tmp.row - 1; k++) {
              tmp.mat[j][k] = cadd(tmp.mat[j][k], cmulti(NEGA, cmulti(tmp.mat[j][i], tmp.mat[i][k])));
            }
            for (k = 0; k <= y.row - 1; k++) {
              y.mat[j][k] = cadd(y.mat[j][k], cmulti(NEGA, cmulti(tmp.mat[j][i], y.mat[i][k])));
            }
          }
        }
      }
    }
  }
  else {
    matcalerr = 2;
    if (form(&y, 1, 1) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    y.mat[0][0] = cmplx(0.0, 0.0);
  }
  
  free(tmp.mat);
  
  return y;
}

struct mat umat(int n)
{
  int i, j;
  struct mat y;
  
  if (form(&y, n, n) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= n - 1; i++) {
    for (j = 0; j <= n - 1; j++) {
      y.mat[i][j] = cmplx(0.0, 0.0);
    }
  }
  for (i = 0; i <= n - 1; i++) {
    y.mat[i][i] = cmplx(1.0, 0.0);
  }
  
  return y;
}

struct mat trans(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.column, x.row) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row - 1; i++) {
    for (j = 0; j <= x.column - 1; j++) {
      y.mat[j][i] = x.mat[i][j];
    }
  }
  
  return y;
}

double cabs(struct cmplx x)
{
  double y;
  
  y = sqrt(x.re * x.re + x.im * x.im);
  
  return y;
}

struct mat mabs(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j].re = cabs(x.mat[i][j]);
      y.mat[i][j].im = 0.0;
    }
  }
  
  return y;
}

struct mat macos(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j] = cacos(x.mat[i][j]);
    }
  }
  
  return y;
}

struct cmplx cacos(struct cmplx x)
{
  struct cmplx y;
  
  y = cadd(cpow(x, cmplx(2.0, 0.0)), NEGA);
  y = cadd(x, csqrt(y));
  y = cdivid(clog(y), IMAG);
  
  return y;
}

struct mat masin(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j] = casin(x.mat[i][j]);
    }
  }
  
  return y;
}

struct cmplx casin(struct cmplx x)
{
  struct cmplx y;
  
  y = cadd(cpow(x, cmplx(2.0, 0.0)), NEGA);
  y = cadd(cmulti(IMAG, x), csqrt(cmulti(NEGA, y)));
  y = cdivid(clog(y), IMAG);
  
  return y;
}

struct mat matan(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j] = catan(x.mat[i][j]);
    }
  }
  
  return y;
}

struct cmplx catan(struct cmplx x)
{
  struct cmplx y;
  
  y = cdivid(cadd(IMAG, cmulti(NEGA, x)), cadd(IMAG, x));
  y = cdivid(clog(y), cmulti(cmplx(2.0, 0.0), IMAG));
  
  return y;
}

struct mat mcos(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j] = ccos(x.mat[i][j]);
    }
  }
  
  return y;
}

struct cmplx ccos(struct cmplx x)
{
  struct cmplx y;
  
  y = cadd(cexp(cmulti(IMAG, x)), cexp(cmulti(cmulti(NEGA, IMAG), x)));
  y = cdivid(y, cmplx(2.0, 0.0));
  
  return y;
}

struct mat mcosh(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j] = ccosh(x.mat[i][j]);
    }
  }
  
  return y;
}

struct cmplx ccosh(struct cmplx x)
{
  struct cmplx y;
  
  y = cadd(cexp(x), cexp(cmulti(NEGA, x)));
  y = cdivid(y, cmplx(2.0, 0.0));
  
  return y;
}

struct mat mexp(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j] = cexp(x.mat[i][j]);
    }
  }
  
  return y;
}

struct cmplx cexp(struct cmplx x)
{
  struct cmplx y;
  
  y.re = exp(x.re) * cos(x.im);
  y.im = exp(x.re) * sin(x.im);
  
  return y;
}

struct mat mlog(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j] = clog(x.mat[i][j]);
    }
  }
  
  return y;
}

struct cmplx clog(struct cmplx x)
{
  double a;
  struct cmplx y;
  
  a = cabs(x);
  if (a != 0.0) {
    y.re = log(a);
    y.im = arg(x);
  }
  else {
    matcalerr = 101;
    
    y = cmplx(0.0, 0.0);
  }
  
  return y;
}

struct mat msin(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j] = csin(x.mat[i][j]);
    }
  }
  
  return y;
}

struct cmplx csin(struct cmplx x)
{
  struct cmplx y;
  
  y = cmulti(NEGA, cexp(cmulti(cmulti(NEGA, IMAG), x)));
  y = cadd(cexp(cmulti(IMAG, x)), y);
  y = cdivid(y, cmplx(0.0, 2.0));
  
  return y;
}

struct mat msinh(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j] = csinh(x.mat[i][j]);
    }
  }
  
  return y;
}

struct cmplx csinh(struct cmplx x)
{
  struct cmplx y;
  
  y = cadd(cexp(x), cmulti(NEGA, cexp(cmulti(NEGA, x))));
  y = cdivid(y, cmplx(2.0, 0.0));
  
  return y;
}

struct mat msqrt(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j] = csqrt(x.mat[i][j]);
    }
  }
  
  return y;
}

struct cmplx csqrt(struct cmplx x)
{
  struct cmplx y;
  
  y = cpow(x, cmplx(0.5, 0.0));
  
  return y;
}

struct mat mroot(struct mat x1, struct mat x2)
{
  int i;
  double b, n;
  struct cmplx tmp, a;
  struct mat y;
  
  if (x1.row == 1 && x1.column && x2.row == 1 && x2.column) {
    if (cabs(x1.mat[0][0]) != 0.0) {
      n = floor(x2.mat[0][0].re + 0.5);
      a = cpow(x1.mat[0][0], cmplx(1.0 / n, 0.0));
      b = arg(x1.mat[0][0]) / n;
      
      tmp.re = cos(2.0 * PI / n);
      tmp.im = sin(2.0 * PI / n);
      
      if (form(&y, 1, (int)n) == NULL) {
        puts("No more memories.\n");
        exit(1);
      }
      
      for (i = 1; i <= n; i++) {
        y.mat[0][i-1] = cmulti(a, cpow(tmp, cmplx((double)i, 0.0)));
      }
    }
    else {
      matcalerr = 104;
      if (form(&y, 1, 1) == NULL) {
        puts("No more memories.\n");
        exit(1);
      }
      y.mat[0][0] = cmplx(0.0, 0.0);
    }
  }
  else {
    matcalerr = 18;
    if (form(&y, 1, 1) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    y.mat[0][0] = cmplx(0.0, 0.0);
  }
  
  return y;
}

struct mat mtan(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j] = ctan(x.mat[i][j]);
    }
  }
  
  return y;
}

struct cmplx ctan(struct cmplx x)
{
  struct cmplx y;
  
  y = cdivid(csin(x), ccos(x));
  
  return y;
}

struct mat mtanh(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j] = ctanh(x.mat[i][j]);
    }
  }
  
  return y;
}

struct cmplx ctanh(struct cmplx x)
{
  struct cmplx y;
  
  y = cdivid(csinh(x), ccosh(x));
  
  return y;
}

struct mat mpow(struct mat x1, struct mat x2)
{
  int i, j;
  struct mat y;
  
  if ((x1.row == x2.row && x1.column == x2.column) || (x1.row == 1 && x1.column == 1) || (x2.row == 1 && x2.column == 1)) {
    y = mexp(mmulti(x2, mlog(x1)));
  }
  else {
    matcalerr = 1;
    if (form(&y, 1, 1) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    y.mat[0][0] = cmplx(0.0, 0.0);
  }
  
  return y;
}

struct cmplx cpow(struct cmplx x1,struct cmplx x2)
{
  struct cmplx y;
  
  if (cabs(x1) == 0.0) {
    matcalerr = 102;
    y = cmplx(0.0, 0.0);
  }
  else {
    y = cexp(cmulti(x2, clog(x1)));
  }
  
  return y;
}
struct mat mceil(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j].re = ceil(x.mat[i][j].re);
      y.mat[i][j].im = ceil(x.mat[i][j].im);
    }
  }
  
  return y;
}

struct cmplx cfloor(struct cmplx x)
{
  struct cmplx y;
  
  y.re = floor(x.re);
  y.im = floor(x.im);
  
  return y;
}

struct mat mfloor(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j] = cfloor(x.mat[i][j]);
    }
  }
  
  return y;
}

unsigned spacefilter(char expression[])  /* スペースを取除く */
{
  int i, j;
  char c, ext[256];
  
  i = 0;
  j = 0;
  
  c = expression[j];
  while (c != '\0') {
    while (c==' ') {
      j++;
      c = expression[j];
    }
    ext[i] = c;
    i++;
    j++;
    c = expression[j];
  }
  
  ext[i] = '\0';
  return (unsigned)ext;
}

unsigned prtcpy(char expression[], int start, int end)  /* startからendまでの文字列を取り出す */
{
  char extract[256];
  int k;
  
  for (k = 0; k <= end - start; k++) {
    extract[k] = expression[k + start];
  }
  extract[k] = '\0';
  return (unsigned)extract;
}

int next(char expression[], int i, char brs, char bre)  /* 括弧に対応する括弧の位置を検出する */
{
  int l;
  char c;
  
  l = strlen(expression) - 1;
  c = expression[i];
  while (c != bre && i <= l) {
    i++;
    if (c == brs) {
      i = next(expression, i, brs, bre);
      i++;
    }
    c = expression[i];
  }
  if (i > l) {
    matcalerr = 19;
  }
  
  return i;
}

struct mat mpai(struct mat s, struct mat e, char expression[]) /* Π（総積） */
{
  int i, j, k, l, len, start, end;
  char c, argument, extract[256], number[10];
  struct mat ansr;
  
  if (s.row == 1 && s.column == 1 && e.row == 1 && e.column == 1) {
    start = (int)floor(s.mat[0][0].re + 0.5);
    end = (int)floor(e.mat[0][0].re + 0.5);
    
    if (start > end) {
      /*
      printf("Error! Start value larger than end value");
      */
      matcalerr = 3;
      if (form(&ansr, 1, 1) == NULL) {
        puts("No more memories.\n");
        exit(1);
      }
      ansr.mat[0][0] = cmplx(0.0, 0.0);
    }
    else {
      ssp++;   /* ネスティングの回数 */
      argument = (char)('A' + ssp - 1);
      strcpy(extract, expression);
      strcpy(number, "1");
      ansr = makemat(number);
      for (i = start; i <= end; i++) {
        sprintf (number, "%d", i);
        k = 0;
        len = strlen(extract);
        if (len == 0) {
          matcalerr = 4;
          if (form(&ansr, 1, 1) == NULL) {
            puts("No more memories.\n");
            exit(1);
          }
          ansr.mat[0][0] = cmplx(0.0, 0.0);
        }
        else {
          for (j = 0; j <= len - 1; j++) {
            c = extract[j];
            if (c == argument) {
              if (j >= 1) {
                if (islower(extract[j-1]) == 0) {
                  if (j <= len - 1) {
                    if (islower(extract[j-1]) == 0) {
                      l = k;
                      c = number[k-l];
                      while (c != '\0') {
                        expression[k] = c;
                        k++;
                        c = number[k-l];
                      }
                    }
                    else {
                      expression[k] = c;
                      k++;
                    }
                  }
                  else {
                    l = k;
                    c = number[k-l];
                    while (c != '\0') {
                      expression[k] = c;
                      k++;
                      c = number[k-l];
                    }
                  }
                }
                else {
                  expression[k] = c;
                  k++;
                }
              }
              else if (j <= len-1) {
                if (islower(extract[j-1]) == 0) {
                  l = k;
                  c = number[k-l];
                  while (c != '\0') {
                    expression[k] = c;
                    k++;
                    c=number[k-l];
                  }
                }
              }
              else {
                expression[k] = c;
                k++;
              }
            }
            else {
              expression[k] = c;
              k++;
            }
          }
          expression[k] = '\0';
          ansr = mmulti(ansr, analyze(expression));
       }
      }
      ssp--;
    }
  }
  else {
    matcalerr = 18;
    if (form(&ansr, 1, 1) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    ansr.mat[0][0] = cmplx(0.0, 0.0);
  }
  
  return ansr;
}

struct mat msigma(struct mat s, struct mat e, char expression[]) /* Σ（総和） */
{
  int i, j, k, l, len, start, end;
  char c, argument, extract[256], number[10];
  struct mat ansr;
  
  if (s.row == 1 && s.column == 1 && e.row == 1 && e.column == 1) {
    start = (int)floor(s.mat[0][0].re + 0.5);
    end = (int)floor(e.mat[0][0].re + 0.5);
    
    if (start > end) {
      /*
      printf("Error! Start value larger than end value");
      */
      matcalerr = 3;
      if (form(&ansr, 1, 1) == NULL) {
        puts("No more memories.\n");
        exit(1);
      }
      ansr.mat[0][0] = cmplx(0.0, 0.0);
    }
    else {
      ssp++;   /* ネスティングの回数 */
      argument = (char)('A' + ssp - 1);
      strcpy(extract, expression);
      strcpy(number, "0");
      ansr = makemat(number);
      for (i = start; i <= end; i++) {
        sprintf (number, "%d", i);
        k = 0;
        len = strlen(extract);
        if (len == 0) {
          matcalerr = 4;
          if (form(&ansr, 1, 1) == NULL) {
            puts("No more memories.\n");
            exit(1);
          }
          ansr.mat[0][0] = cmplx(0.0, 0.0);
        }
        else {
          for (j = 0; j <= len - 1; j++) {
            c = extract[j];
            if (c == argument) {
              if (j >= 1) {
                if (islower(extract[j-1]) == 0) {
                  if (j <= len - 1) {
                    if (islower(extract[j-1]) == 0) {
                      l = k;
                      c = number[k-l];
                      while (c != '\0') {
                        expression[k] = c;
                        k++;
                        c = number[k-l];
                      }
                    }
                    else {
                      expression[k] = c;
                      k++;
                    }
                  }
                  else {
                    l = k;
                    c = number[k-l];
                    while (c != '\0') {
                      expression[k] = c;
                      k++;
                      c = number[k-l];
                    }
                  }
                }
                else {
                  expression[k] = c;
                  k++;
                }
              }
              else if (j <= len-1) {
                if (islower(extract[j-1]) == 0) {
                  l = k;
                  c = number[k-l];
                  while (c != '\0') {
                    expression[k] = c;
                    k++;
                    c=number[k-l];
                  }
                }
              }
              else {
                expression[k] = c;
                k++;
              }
            }
            else {
              expression[k] = c;
              k++;
            }
          }
          expression[k] = '\0';
          ansr = madd(ansr, analyze(expression));
       }
      }
      ssp--;
    }
  }
  else {
    matcalerr = 18;
    if (form(&ansr, 1, 1) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    ansr.mat[0][0] = cmplx(0.0, 0.0);
  }
  
  return ansr;
}

struct mat msinc(struct mat x) /* ｓｉｎｃ関数 */
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j].re = sinc(x.mat[i][j].re);
      y.mat[i][j].im = sinc(x.mat[i][j].im);
    }
  }
  
  return y;
}

double sinc(double x) /* ｓｉｎｃ関数 */
{
  double a;
  
  if (x == 0.0) {
    a = 1.0;
  }
  else {
    a = sin(PI * x) / (PI * x);
  }
  
  return a;
}

struct mat mpulse(struct mat x) /* 単パルス関数 */
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j].re = pulse(x.mat[i][j].re);
      y.mat[i][j].im = pulse(x.mat[i][j].im);
    }
  }
  
  return y;
}

double pulse(double x) /* 単パルス関数 */
{
  double a;
  
  if (x >= -0.5 && x <= 0.5) {
    a = 1.0;
  }
  else {
    a = 0.0;
  }
  
  return a;
}

struct mat mtriangle(struct mat x) /* 三角波関数 */
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j].re = triangle(x.mat[i][j].re);
      y.mat[i][j].im = triangle(x.mat[i][j].im);
    }
  }
  
  return y;
}

struct mat mreal(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j].re = x.mat[i][j].re;
      y.mat[i][j].im = 0.0;
    }
  }
  
  return y;
}

struct mat mimag(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j].re = x.mat[i][j].im;
      y.mat[i][j].im = 0.0;
    }
  }
  
  return y;
}

struct mat mconj(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j].re = x.mat[i][j].re;
      y.mat[i][j].im = -x.mat[i][j].im;
    }
  }
  
  return y;
}

struct mat marg(struct mat x)
{
  int i, j;
  struct mat y;
  
  if (form(&y, x.row, x.column) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  
  for (i = 0; i <= x.row-1; i++) {
    for (j = 0; j <= x.column-1; j++) {
      y.mat[i][j].re = arg(x.mat[i][j]);
      y.mat[i][j].im = 0.0;
    }
  }
  
  return y;
}

double triangle(double x) /* 三角波関数 */
{
  double a, p, s;
  
  s = 1.0;
  a = 0.0;
  p = PI / 2.0;
  
  if (x < 0.0) {
    s = -1.0;
    x = -x;
  }
  x = x - 2.0 * PI * floor(x / (2.0 * PI));
  if (x >= 0.0 && x <= p) {
    a = x / p;
  }
  else if (x > p && x <= PI + p) {
    a = -x / p + 2.0;
  }
  else if (x > PI + p && x <= 2.0 * PI) {
    a = x / p - 4.0;
  }
  a = a * s;
  
  return a;
}

int *form(struct mat *ansr,int row,int column)
{
  int i, *er;
  
  (*ansr).mat = (struct cmplx **)malloc(row * sizeof(struct cmplx *));
  er = (int*)(*ansr).mat;
  for (i = 0; i < row; i++) {
    (*ansr).mat[i] = (struct cmplx *)malloc(column * sizeof(struct cmplx));
    er = (int*)(*ansr).mat[i];
  }
  (*ansr).row = row;
  (*ansr).column = column;
  
  return er;
}

struct mat takevalue(char expression[], int *point) /* 値を取ってくる */
{
  int i, j, k, l, m, len;
  char c, func[10], extract[256];
  struct mat ansr, tmp;
  char *fnc[] = {
    "abs",
    "acos",
    "asin",
    "atan",
    "ceil",
    "cos",
    "cosh",
    "exp",
    "floor",
    "log",
    "log2",
    "log10",
    "sin",
    "sinh",
    "sqrt",
    "tan",
    "tanh",
    "pai",
    "sigma",
    "sinc",
    "pulse",
    "pow",
    "triangle",
    "re",
    "im",
    "conj",
    "arg",
    "rad",
    "deg",
    "root",
    "mod",
    "det",
    "inv",
    "umat",
    "trans"
  };
  
  i = 0;
  c = expression[i];
  if (c == '-' || c == '+'){          /* 単項演算子のとき */
    if (form(&tmp, 1, 1) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    tmp.mat[0][0].re = 1.0;
    tmp.mat[0][0].im = 0.0;
    if (c == '-') {
      tmp.mat[0][0].re = -1.0;
      tmp.mat[0][0].im = 0.0;
    }
    i++;
    *point = *point + 1;
    len = strlen(expression);
    strcpy(extract, (char *)prtcpy(expression, i, len));
    ansr = mmulti(tmp, takevalue(extract, point));
    
    free(tmp.mat);
  }
  else if (c == '(') {          /* ”(”のとき */
    i++;
    j = next(expression, i, '(', ')') - 1;
    strcpy(extract, (char *)prtcpy(expression, i, j));
    ansr = analyze(extract);
    *point = *point + j + 2;
  }
  else if (c == '[') {          /* ”[”のとき */
    i++;
    j = next(expression, i, '[', ']') - 1;
    strcpy(extract, (char *)prtcpy(expression, i, j));
    ansr = makemat(extract);
    *point = *point + j + 2;
  }
  else if (isdigit(c) != 0 || c == '.') {    /* 数字のとき */
    if (form(&ansr, 1, 1) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    j = 0;
    extract[j] = c;
    j++;
    c = expression[j];
    while (isdigit(c) != 0 || c == '.' || c == 'd' || c == 'D' || c == 'e' || c == 'E') {
      extract[j] = c;
      j++;
      if (c == 'd' || c == 'D' || c == 'e' || c == 'E') {
        c = expression[j];
        if (isdigit(c) != 0 || c == '+' || c == '-') {
          extract[j] = c;
          j++;
        }
        else {
          matcalerr = 5;
          if (form(&ansr, 1, 1) == NULL) {
            puts("No more memories.\n");
            exit(1);
          }
          ansr.mat[0][0] = cmplx(0.0, 0.0);
          
          return ansr;
        }
      }
      c = expression[j];
    }
    extract[j] = '\0';
    ansr.mat[0][0].re = atof(extract);
    ansr.mat[0][0].im = 0.0;
    *point = *point + j;
  }
  else if (isalpha(c) != 0) {  /* アルファベットのとき */
    j = 0;
    func[j] = c;
    j++;
    c = expression[j];
    while (isalnum(c) != 0) {
      func[j] = c;
      j++;
      if (j > 9) {
        matcalerr = 7;
        if (form(&ansr, 1, 1) == NULL) {
          puts("No more memories.\n");
          exit(1);
        }
        ansr.mat[0][0] = cmplx(0.0, 0.0);
      }
      c = expression[j];
    }
    func[j] = '\0';
    i = j;
    if (c != '(') {   /* 定数 */
      *point = *point + j;
      if (strcmp(func, "pi") == 0) {
        if (form(&ansr, 1, 1) == NULL) {
          puts("No more memories.\n");
          exit(1);
        }
        ansr.mat[0][0] = cmplx(PI, 0.0);
      }
      else if (strcmp(func, "e") == 0) {
        if (form(&ansr, 1, 1) == NULL) {
          puts("No more memories.\n");
          exit(1);
        }
        ansr.mat[0][0].re = 2.7182818284590452353602874713526624977572;
        ansr.mat[0][0].im = 0.0;
      }
      else if (strcmp(func, "i") == 0) {
        if (form(&ansr, 1, 1) == NULL) {
          puts("No more memories.\n");
          exit(1);
        }
        ansr.mat[0][0].re = 0.0;
        ansr.mat[0][0].im = 1.0;
      }
      else {
        k = 0;
        while (strcmp(func, cnst[k].name) != 0) {
          if (strlen(cnst[k].name) == 0) {
            matcalerr = 7;
            if (form(&ansr, 1, 1) == NULL) {
              puts("No more memories.\n");
              exit(1);
            }
            ansr.mat[0][0] = cmplx(0.0, 0.0);
            return ansr;
          }
          k++;
        }
        if (form(&ansr, cnst[k].val.row, cnst[k].val.column) == NULL) {
          puts("No more memories.\n");
          exit(1);
        }
        for (l = 0; l <= cnst[k].val.row - 1; l++) {
          for (m = 0; m <= cnst[k].val.column - 1; m++) {
            ansr.mat[l][m] = cnst[k].val.mat[l][m];
          }
        }
      }
    }
    else {  /* 関数 */
      i++;
      j = next(expression, i, '(', ')') - 1;
      strcpy(extract, (char *)prtcpy(expression, i, j));
      if (strcmp(func, fnc[17]) != 0 && strcmp(func, fnc[18]) != 0 && strcmp(func, fnc[21]) != 0 && strcmp(func, fnc[29]) != 0 && strcmp(func, fnc[30]) != 0) {
        ansr = analyze(extract);
      }
      else {   /* Π、Σ、ｐｏｗ、ｍｏｄのとき */
        strcpy(expression, extract);
        len = strlen(expression);
        k = 0;
        l = 0;
        c = expression[k];
        while (c != ',' && l <= len) {
          if (c == '(') {          /* ”(”のとき */
            int m, n;
            
            n = next(expression, l + 1, '(', ')');
            extract[l] = c;
            for (m = l + 1; m <= n; m++) {
              c = expression[m];
              extract[m] = c;
            }
            l = n + 1;
          }
          else if (c == '[') {          /* ”[”のとき */
            int m, n;
            
            n = next(expression, l + 1, '[', ']');
            extract[l] = c;
            for (m = l + 1; m <= n; m++) {
              c = expression[m];
              extract[m] = c;
            }
            l = n + 1;
          }
          else {
            extract[l] = c;
            l++;
          }
          
          c = expression[l];
        }
        extract[l] = '\0';
        if (l > len) {
          char num[2];
          
          strcpy(num, "0");
          matcalerr = 8;
          
          return makemat(num);
        }
        ansr = analyze(extract);
        k = l + 1;
        l = 0;
        c = expression[k];
        while (c != ',' && k + l <= len) {
          if (c == '(') {
            int m, n;
            
            n = next(expression, k + l + 1, '(', ')');
            extract[l] = c;
            for (m = l + 1; m <= n; m++) {
              c = expression[k + m];
              extract[m] = c;
            }
            l = n + 1;
          }
          else if (c == '[') {
            int m, n;
            
            n = next(expression, k + l + 1, '[', ']');
            extract[l] = c;
            for (m = l + 1; m <= n; m++) {
              c = expression[k + m];
              extract[m] = c;
            }
            l = n + 1;
          }
          else {
            extract[l] = c;
            l++;
          }
          
          c = expression[k + l];
        }
        extract[l] = '\0';
        k = k + l + 1;
        if (strcmp(func, fnc[17]) == 0 || strcmp(func, fnc[18]) == 0) {
          if (k > len) {
            char num[2];
            
            strcpy(num, "0");
            matcalerr = 8;
            
            return makemat(num);
          }
          tmp = analyze(extract);
          
          for (l = k; l <= len; l++) {
            extract[l - k] = expression[l];
          }
          extract[len - k + 1] = '\0';
        }
        else {
          tmp = analyze(extract);
        }
      }
      *point = *point + j + 2;
      
      if (strcmp(func, fnc[0]) == 0) {
        ansr = mabs(ansr);
      }
      else if (strcmp(func, fnc[1]) == 0) {
        ansr = macos(ansr);
      }
      else if (strcmp(func, fnc[2]) == 0) {
        ansr = masin(ansr);
      }
      else if (strcmp(func, fnc[3]) == 0) {
        ansr = matan(ansr);
      }
      else if (strcmp(func, fnc[4]) == 0) {
        ansr = mceil(ansr);
      }
      else if (strcmp(func, fnc[5]) == 0) {
        ansr = mcos(ansr);
      }
      else if (strcmp(func, fnc[6]) == 0) {
        ansr = mcosh(ansr);
      }
      else if (strcmp(func, fnc[7]) == 0) {
        ansr = mexp(ansr);
      }
      else if (strcmp(func, fnc[8]) == 0) {
        ansr = mfloor(ansr);
      }
      else if (strcmp(func, fnc[9]) == 0) {
        ansr = mlog(ansr);
      }
      else if(strcmp(func, fnc[10]) == 0) {
        char cn[2];
        
        strcpy(cn, "2");
        ansr = mmulti(mlog(ansr), inv(mlog(makemat(cn))));
      }
      else if (strcmp(func, fnc[11]) == 0) {
        char cn[3];
        
        strcpy(cn, "10");
        ansr = mmulti(mlog(ansr), inv(mlog(makemat(cn))));
      }
      else if (strcmp(func, fnc[12]) == 0) {
        ansr = msin(ansr);
      }
      else if (strcmp(func, fnc[13]) == 0) {
        ansr = msinh(ansr);
      }
      else if (strcmp(func, fnc[14]) == 0) {
        ansr = msqrt(ansr);
      }
      else if (strcmp(func, fnc[15]) == 0) {
        ansr = mtan(ansr);
      }
      else if (strcmp(func, fnc[16]) == 0) {
        ansr = mtanh(ansr);
      }
      else if (strcmp(func, fnc[17]) == 0) {
        ansr = mpai(ansr, tmp, extract);
      }
      else if (strcmp(func, fnc[18]) == 0) {
        ansr = msigma(ansr, tmp, extract);
      }
      else if (strcmp(func, fnc[19]) == 0) {
        ansr = msinc(ansr);
      }
      else if (strcmp(func, fnc[20]) == 0) {
        ansr = mpulse(ansr);
      }
      else if (strcmp(func, fnc[21]) == 0) {
        ansr = mpow(ansr, tmp);
        /*
        free(tmp.mat);
        */
      }
      else if (strcmp(func, fnc[22]) == 0) {
        ansr = mtriangle(ansr);
      }
      else if (strcmp(func, fnc[23]) == 0) {
        ansr = mreal(ansr);
      }
      else if (strcmp(func, fnc[24]) == 0) {
        ansr = mimag(ansr);
      }
      else if (strcmp(func, fnc[25]) == 0) {
        ansr = mconj(ansr);
      }
      else if (strcmp(func, fnc[26]) == 0) {
        ansr = marg(ansr);
      }
      else if (strcmp(func, fnc[27]) == 0) {
        ansr = mrad(ansr);
      }
      else if (strcmp(func, fnc[28]) == 0) {
        ansr = mdeg(ansr);
      }
      else if (strcmp(func, fnc[29]) == 0) {
        ansr = mroot(ansr, tmp);
      }
      else if (strcmp(func, fnc[30]) == 0) {
        ansr = mmod(ansr, tmp);
        /*
        free(tmp.mat);
        */
      }
      else if (strcmp(func, fnc[31]) == 0) {
        ansr = det(ansr);
      }
      else if (strcmp(func, fnc[32]) == 0) {
        ansr = inv(ansr);
      }
      else if (strcmp(func, fnc[33]) == 0) {
        ansr = umat((int)ansr.mat[0][0].re);
      }
      else if (strcmp(func, fnc[34]) == 0) {
        ansr = trans(ansr);
      }
      else {
        matcalerr = 6;
        if (form(&ansr, 1, 1) == NULL) {
          puts("No more memories.\n");
          exit(1);
        }
        ansr.mat[0][0] = cmplx(0.0, 0.0);
      }
    }
  }
  else {
    matcalerr = 9;
    if (form(&ansr, 1, 1) == NULL) {
      puts("No more memories.\n");
      exit(1);
    }
    ansr.mat[0][0] = cmplx(0.0, 0.0);
  }
  
  return ansr;
}

int level(char operater) /* 二項演算子の優先順位 */
{
  int i, l;
  char level[6] = {'^', '*', '/', '%', '+', '-'};
  
  l = 0;
  for (i = 0; i <= 5; i++) {
    if (operater == level[i]) {
      if (i == 0) {
        l = 0;
      }
      else if (i == 1 || i == 2 || i == 3) {
        l = 1;
      }
      else if (i == 4 || i == 5) {
        l = 2;
      }
      break;
    }
  }
  
  return l;
}
struct mat biterm(char expression[], struct mat ansr, int *point, int lev)   /* 二項演算 */
{
  int i, j, k, len, lv;
  double s;
  char c, extract[256];
  struct mat tmp, tmpb, tmpd;
  
  s = 1.0;
  i = 0;
  len = strlen(expression);
  c =expression[i];
  lv = level(c);
  if (lv < lev) {
    lv = lev;
  }
  i++;
  k = *point;
  *point = *point + 1;
  strcpy(extract, (char *)prtcpy(expression, i, len));
  strcpy(expression, extract);
  j = *point;
  switch(c) {
    case '^':
      tmpb = takevalue(expression, point);
      i = i + *point - j - 1;
      if (i + 1 <= len - 1) {
        c = expression[i];
        if (lv > level(c)) {
          tmpd = mpow(ansr, tmpb);
          strcpy(extract, (char *)prtcpy(expression, i, len));
          *point = k + i + 1;
          tmpd = biterm(extract, tmpb, point, lv);
        }
        else {
          tmpd = mpow(ansr, tmpb);
        }
      }
      else {
        tmpd = mpow(ansr, tmpb);
      }
      break;
    case '*':
      tmpb = takevalue(expression, point);
      i = i + *point - j - 1;
      if (i + 1 <= len - 1) {
        c = expression[i];
        if (lv > level(c)) {
          if (c == '^') {
            strcpy(extract, (char *)prtcpy(expression, i, len));
            *point = k + i + 1;
            tmpb = biterm(extract, tmpb, point, lv);
            tmpd = mmulti(ansr, tmpb);
          }
          
          else {
            tmpd = mmulti(ansr, tmpb);
            strcpy(extract, (char *)prtcpy(expression, i, len));
            *point = k + i + 1;
            tmpd = biterm(extract, tmpd, point, lv);
          }
        }
        else {
          tmpd = mmulti(ansr, tmpb);
        }
      }
      else {
        tmpd = mmulti(ansr, tmpb);
      }
      break;
    case '/':
      tmpb = takevalue(expression, point);
      i = i + *point - j - 1;
      if (i + 1 <= len - 1) {
        c = expression[i];
        if (lv > level(c)) {
          if (c == '^') {
            strcpy(extract, (char *)prtcpy(expression, i, len));
            *point = k + i + 1;
            tmpb = biterm(extract, tmpb, point, lv);
            tmp = det(tmpb);
            if (tmp.mat[0][0].re == 0.0) {
              matcalerr = 100;
              if (form(&tmpd,1,1) == NULL) {
                puts("No more memories.\n");
                exit(1);
              }
              tmpd.mat[0][0].re = 1.0e300;
              tmpd.mat[0][0].im = 1.0e300;
            }
            else {
              tmpd = mmulti(ansr, inv(tmpb));
            }
          }
          else {
            tmp = det(tmpb);
            if (tmp.mat[0][0].re == 0.0) {
              matcalerr = 100;
              if (form(&tmpd, 1, 1) == NULL) {
                printf("No more memories.\n");
                exit(1);
              }
              tmpd.mat[0][0].re = 1.0e300;
              tmpd.mat[0][0].im = 1.0e300;
            }
            else {
              tmpd = mmulti(ansr, inv(tmpb));
            }
            strcpy(extract, (char *)prtcpy(expression, i, len));
            *point = k + i + 1;
            tmpd = biterm(extract, tmpd, point, lv);
          }
        }
        else {
          tmp = det(tmpb);
          if (tmp.mat[0][0].re == 0.0) {
            matcalerr = 100;
            if(form(&tmpd, 1, 1) == NULL) {
              printf("No more memories.\n");
              exit(1);
            }
            tmpd.mat[0][0].re = 1.0e300;
            tmpd.mat[0][0].im = 1.0e300;
          }
          else {
            tmpd = mmulti(ansr, inv(tmpb));
          }
        }
      }
      else {
        tmp = det(tmpb);
        if (tmp.mat[0][0].re == 0.0) {
          matcalerr = 100;
          tmpd.row = 1;
          tmpd.column = 1;
          if(form(&tmpd, 1, 1) == NULL) {
            printf("No more memories.\n");
            exit(1);
          }
          tmpd.mat[0][0].re = 1.0e300;
          tmpd.mat[0][0].im = 1.0e300;
        }
        else {
          tmpd = mmulti(ansr, inv(tmpb));
        }
      }
      break;
    case '%':
      tmpb = takevalue(expression, point);
      i = i + *point - j - 1;
      if (i + 1 <= len - 1) {
        c = expression[i];
        if (lv > level(c)) {
          if (c == '^') {
            strcpy(extract, (char *)prtcpy(expression, i, len));
            *point = k + i + 1;
            tmpb = biterm(extract, tmpb, point, lv);
            tmpd = mmod(ansr, tmpb);
          }
          else {
            tmpb = mmod(ansr, tmpb);
            strcpy(extract, (char *)prtcpy(expression, i, len));
            *point = k + i + 1;
            tmpd = biterm(extract, tmpb, point, lv);
          }
        }
        else {
          tmpd = mmod(ansr, tmpb);
        }
      }
      else {
      printf("ansr");
      mprintf(ansr);
      printf("tmpb");
      mprintf(tmpb);
        tmpd = mmod(ansr, tmpb);
      }
      break;
    case '-':
      s=-1.0;
    case '+':
      tmpb = takevalue(expression, point);
      i = i + *point - j - 1;
      if (i + 1 <= len - 1) {
        c = expression[i];
        if (lv > level(c)) {
          strcpy(extract, (char *)prtcpy(expression, i, len));
          *point = k + i + 1;
          tmpb = biterm(extract, tmpb, point, lv);
        }
      }
      
      if (form(&tmp, 1, 1) == NULL) {
        puts("No more memories.\n");
        exit(1);
      }
      tmp.mat[0][0].re = s;
      tmp.mat[0][0].im = 0.0;
      tmpd = madd(ansr, mmulti(tmp, tmpb));
      break;
    default:
      matcalerr = 10;
      if (form(&tmpd, 1, 1) == NULL) {
        puts("No more memories.\n");
        exit(1);
      }
      tmpd.mat[0][0] = cmplx(0.0, 0.0);
  }
  
  ansr = tmpd;
  /*
  free(tmp.mat);
  free(tmpb.mat);
  */
  
  return ansr;
}

struct mat makemat(char expression[]) /*  */
{
  int i, j, k, l, len, ki, plr, plc, row, column, maxco, maxc, maxr, tmpr, tmpc, last;
  char extract[256], c;
  struct mat ansr, tmp[100];
  
  strcat(expression, ";");
  len = strlen(expression);
  i = 0;
  plr = 0;
  plc = 0;
  last = 0;
  tmpr = 0;
  tmpc = 1;
  maxco = 0;
  maxc = 0;
  maxr = 0;
  row = 1;
  column = 1;
  while (i <= len) {
    ki = tmpc*(row - 1) + (column - 1);
    c = expression[i];
    if (c == ';') {
      strcpy(extract, (char *)prtcpy(expression, last, i - 1));
      if (ki > 1000000) {
        matcalerr = 11;
        if (form(&ansr, 1, 1) == NULL) {
          puts("No more memories.\n");
          exit(1);
        }
        ansr.mat[0][0] = cmplx(0.0, 0.0);
        
        return ansr;
      }
      tmp[ki] = analyze(extract);
      maxc += tmp[ki].column;
      maxr += tmp[ki].row;
      if (tmpr != 0) {
        if(tmpr != tmp[ki].row) {
          matcalerr = 12;
          if (form(&ansr, 1, 1) == NULL) {
            puts("No more memories.\n");
            exit(1);
          }
          ansr.mat[0][0] = cmplx(0.0, 0.0);
          
          return ansr;
        }
      }
      if (row != 1) {
        if (tmpc != column) {
          matcalerr = 13;
          if (form(&ansr, 1, 1) == NULL) {
            puts("No more memories.\n");
            exit(1);
          }
          ansr.mat[0][0] = cmplx(0.0, 0.0);
          
          return ansr;
        }
        if (maxco != maxc) {
          matcalerr = 14;
          if (form(&ansr, 1, 1) == NULL) {
            puts("No more memories.\n");
            exit(1);
          }
          ansr.mat[0][0] = cmplx(0.0, 0.0);
          
          return ansr;
        }
      }
      row++;
      tmpr = 0;
      tmpc = column;
      maxco = maxc;
      maxc = 0;
      column = 1;
      last = i + 1;
    }
    else if (c == ',') {
      strcpy(extract, (char *)prtcpy(expression, last, i - 1));
      if (ki > 1000000) {
        matcalerr = 11;
        if (form(&ansr, 1, 1) == NULL) {
          puts("No more memories.\n");
          exit(1);
        }
        ansr.mat[0][0] = cmplx(0.0, 0.0);
        
        return ansr;
      }
      tmp[ki] = analyze(extract);
      if (tmpr != 0) {
        if (tmpr != tmp[ki].row) {
          matcalerr = 12;
          if (form(&ansr, 1, 1) == NULL) {
            puts("No more memories.\n");
            exit(1);
          }
          ansr.mat[0][0] = cmplx(0.0, 0.0);
          
          return ansr;
        }
      }
      tmpr = tmp[ki].row;
      maxc += tmp[ki].column;
      column++;
      last = i + 1;
    }
    else if (c == '(') {
      j = next(expression, i + 1, '(', ')');
      i = j;
    }
    else if (c == '[') {
      j = next(expression, i+1, '[', ']');
      i = j;
    }
    i++;
  }
  
  if (form(&ansr, maxr, maxco) == NULL) {
    puts("No more memories.\n");
    exit(1);
  }
  for (i = 0; i <= row - 2; i++) {
    for (j = 0; j <= tmpc - 1; j++) {
      if (ki >= tmpc * i + j) {
        for (k = 0; k <= tmp[tmpc*i+j].row - 1; k++) {
          for (l = 0; l <= tmp[tmpc*i+j].column - 1; l++) {
            if (i + k + plr <= maxr && j + l + plc <= maxco) {
              ansr.mat[i+k+plr][j+l+plc].re = tmp[tmpc*i+j].mat[k][l].re;
              ansr.mat[i+k+plr][j+l+plc].im = tmp[tmpc*i+j].mat[k][l].im;
            }
            else {
              matcalerr = 15;
              if (form(&ansr, 1, 1) == NULL) {
                puts("No more memories.\n");
                exit(1);
              }
              ansr.mat[0][0] = cmplx(0.0, 0.0);
              
              return ansr;
            }
          }
        }
      }
      else {
        matcalerr = 15;
        if (form(&ansr, 1, 1) == NULL) {
          puts("No more memories.\n");
          exit(1);
        }
        ansr.mat[0][0] = cmplx(0.0, 0.0);
        
        return ansr;
      }
      plc += tmp[tmpc*i+j].column - 1;
    }
    plr += tmp[tmpc*i+j-1].row - 1;
    plc = 0;
  }
  for (plc = 0; plc <= tmpc * (row - 2) + (tmpc - 1); plc++) {
    free(tmp[plc].mat);
  }
  
  return ansr;
}

struct mat analyze(char expression[]) /* メイン部分 */
{
  int len, point; /* point：与えられた数式での位置 */
  char extract[256];
  struct mat ansr;
  
  strcpy(expression, (char *)spacefilter(expression));
  len = strlen(expression);
  point = 1;
  ansr = takevalue(expression,&point);
  while (point <= len) {
    strcpy(extract, (char *)prtcpy(expression, point - 1, len));
    ansr = biterm(extract,ansr,&point,0);
  }
  
  return ansr;
}

void ansprnt(char expres[])
{
  static int curcon = -1;
  int i, j, len, st;
  char c, expression[256], conname[CNL];
  struct mat ansr;
  
  matcalerr = 0;
  j = 0;
  len = strlen(expres);
  c = expres[j];
  while (isalnum(c) != 0) {
    j++;
    c = expres[j];
    if (j >= len) break;
  }
  if (c == '=') {
    j = 0;
    while (expres[j] != '=') {
      if (j > CNL - 1) {
        matcalerr = 17;
      }
      conname[j] = expres[j];
      j++;
    }
    conname[j] = '\0';
    
    if (strcmp(conname, "e") == 0 || strcmp(conname, "pi") == 0 || strcmp(conname, "i") == 0) {
      matcalerr = 20;
    }
    else {
      i = 0;
      while (i <= curcon &&  strcmp(cnst[i].name, conname) != 0) {
        i++;
      }
      
      if (i > UCN - 1) {
        matcalerr = 16;
      }
      else {
        j++;
        st = j;
        while (j <= len) {
          expression[j-st] = expres[j];
          j++;
        }
        ansr = analyze(expression);
        if (matcalerr == 0) {
          strcpy(cnst[i].name, conname);
          cnst[i].val = ansr;
          if (i == curcon + 1) {
            curcon++;
          }
        }
      }
    }
    
    if (matcalerr != 0) {
      printf("\nError occurred in calculating.:%d\n",matcalerr);
    }
  }
  else {
    strcpy(expression, expres);
    
    ansr = analyze(expres);
    
    if (matcalerr != 0) {
      printf("\nError occurred in calculating.:%d\n",matcalerr);
    }
    
    printf("\n%s=\n", expression);
    mprintf(ansr);
  }
}

void mprintf(struct mat ansr)
{
  int i, j;
  
  for (i = 0; i < ansr.row; i++) {
    for (j = 0; j < ansr.column; j++) {
      if (fabs(ansr.mat[i][j].re) > 1.0e4 || fabs(ansr.mat[i][j].re) < 1.0e-4) {
        printf("  %12.4e", ansr.mat[i][j].re);
      }
      else {
        printf("  %12.4f",ansr.mat[i][j].re);
      }
      
      if (ansr.mat[i][j].im > 0.0) {
        if (ansr.mat[i][j].im > 1.0e4 || ansr.mat[i][j].im < 1.0e-4) {
          printf(" +%11.4ei", ansr.mat[i][j].im);
        }
        else {
          printf(" +%11.4fi", ansr.mat[i][j].im);
        }
      }
      else if (ansr.mat[i][j].im < 0.0) {
        if (-ansr.mat[i][j].im > 1.0e4 || -ansr.mat[i][j].im < 1.0e-4) {
          printf(" -%11.4ei", -ansr.mat[i][j].im);
        }
        else {
          printf(" -%11.4fi", -ansr.mat[i][j].im);
        }
      }
    }
    printf("\n");
  }
}

void main(int argc, char *argv[])
{
  int i;
  char expression[256];
  
  for(i = 0; i <= UCN - 1; i++) {
    cnst[i].name[0] = '\0';
  }
  
  if (argc == 1) {
    printf("\n>> ");
    scanf("%s", expression);
    while (strcmp(expression, "quit") != 0) {
      strcpy(expression, (char *)spacefilter(expression));
      ansprnt(expression);
      printf("\n>> ");
      scanf("%s", expression);
    }
  }
  else {
    for (i = 1; i <= argc - 1; i++) {
      ansprnt(argv[i]);
    }
  }
}
