数値計算レポートNo,5
(出題日:2001年6月29日)

G99P105-9 永山陽平

提出日:2001年8月2日

1  問題

数値計算用言語(インタプリタ)を作れ。仕様としてはMATLAB(Octave or Scilab)の 仕様の中からできるだけ実装せよ。

(1)データ:実数(double)、複素数、行列(実数、複素数)が扱えること。 (2)制御命令(for文、if文、while文など)があること。 (3)ユーザが定義できる関数がある。 (4)コマンドラインからだけでなく、ファイルに書かれたプログラムも読める。 (5)オブジェクトが定義でき、演算子多重定義ができる。 (6)絵が書ける。

2  プログラム


#include <stdlib.h>
#include "u.math.h"
#include "MEM.h"
#include "DBG.h"
#include "calc.h"
#include "bignum.c"

main () {
   /*行列演算の変数宣言*/
          static rec_mat x,y,z;
          static c_recmat a,b,c;
          int row,col,colm1,row1,colm2,row2,i,s,fg;
          scaler mdeterm,determ();
          string *str;
          complex ccef,c_math();


          /*複素数演算の変数宣言*/
          complex c_assign(),c_math(),c_exp((), c_pow(),
          c_log10(), c_sin(), c_log(), c_cos(),
          c_tan(),
          double x, y, z;   /*指定通りのdouble型*/
          scaler c_mag(), c_arg(), cls();


    /*行列の固有値問題の変数宣言*/
    int n;
    static rec_mat a, x;



          /*実行列、複素行列main*/
          void
            mat_product(),mat_get(),mat_print();
          while(1) {
              cls();
              printf("Input of a Real Matrix \n");
              printf("Input of a Complex Matrix \n");
              printf("a product of Real Matrix \n");
              prinft("a product of Complex Matrix \n");
              printf("an add of Real Matrix \n");
              printf("an add of Complex Matrix \n");

              scanf("%d,&s");
              if(s>=99) exit();

              switch(s) {
              case1: cls();
                     mat_get(x,&row1,&colm1,"matrix A input ");
                     cls();
                     mat_get(y,&row2,&colm2,"matrix B input ");
                     row=row1;
                     col=colm1; fg=3;
                     break;

              case2: mat_product(x,y,row1,colm1,colm2,z);
                     col=colm2;
                     str="mat_product";
                     fg=0;
                     break;
              case3: mat_product(x, y, row1, colm1, colm2, z);
                     col=colm2; str="mat_product";fg=0;
                     break;
              case4: c_mat_product(a, b, row1,colm1, colm2, c);
                     row=row1; col=colm1; str="c_mat_product"; fg=1;
              case5: mat_add(x, y, row1, colm1, z);
                     str="mat_add"; fg=0;
                     break;
              case6: c_mat_add(a, b, row1, colm1, c);
                     str="mat_add"; fg=1;

              }
              switch(fg) {
              case 0: cls();
                    mat_print(x,row1.colm1,"Input matrix X");
                    mat_print(y,row2,colm2,"Input matrix Y");
                    mat_print(z,row,col,str)
                    break;
              case 1:           cls();
                    mat_print(x,row,col,"matrix X");
                    printf("determinant = %lf\n" , mdeterm);
                    break;
              }
          }


       /*複素演算main*/
          x=c_assign(1.0, 2.0);
          y=c_assign(2.0, 4.0);
          c_print("c_x= ",x);
          c_print("c_y= ",y);
          c_print("c_plus=", c_math(x,plus,y));
          c_print("c_minus=", c_math(x,minus,y));
          c_print("c_multiply=", c_math(x,multiply,y));
          c_print("c_devide=",c_math(x,divide,y));
          c_print("c_exp=",c_exp(x));
          c_print("c.mag and arg=",c_assign(c_mag(x),c_arg(x)));
          printf("type any key:"); ci(); cls();
          x=c_assign(.5,.1);
          c_print("c_x=",x);
          c_print("c_inv=",c_inv(x));
          c_print("c_pow=",c_pow(x,2.0));
          c_print("c_sin=",c_sin(x));
          c_print("c_cos=",c_cos(x));
          c_print("c_tan=",c_tan(x));
          c_print("c_log10=",c_log10(x));
          c_print("c_log=",c_log(x));
          printf("type any key:"); ci();



 /*固有値問題演算main*/
 while(1) {
  switch(menu()) {
  case 1:mat_get(a,&n);break;
  case 2:mat_print(a,n);break;
  case 3:xqr(a,x,n);print_eig_vec(a,x,n);break;
  case 4:exit(0);
 }


        /*bisonでの四則演算main*/
 #if CONSOLEAP
 #define ANSFORM "\nanswer is %f\n"
 #define ANSFORMX "\nanswer is %X\n"

 char Buf[ 128 ];
 gets( Buf );
 lexpos = Buf;
 yyparse();
 puts( OutBuf );

}


  /***************-<<実数行列、複素数行列演算>>-****************/
void mat_print(ma,row,col,matname)rec_mat ma;int row,col;
string *matname; {
         int i, j, ii;
         printf("実行列 &s\n" ,matname);
         for (i=1; i <= col; i++) {
                     for (j=0; j <= col; j++)
                     printf("%7.2lf", ma[i][j]);
                     printf("\n");
         }
         printf("-------- end %s --------\n",matname);
}

void mat_print(mat, m, n, matname)c_recmat mat; int m,n;
string *matname; {
 int i, j, ii;
 printf("複素行列 %s\n", matname);
 for (i=1; i<=m; i++) {
  for (j=1; j<=n; j++)
     printf("[%7.2lf  %7.2lf] ",
         mat[i][j].re,mat[i][j].im);
         printf("\n");
 }
 printf("------end %s --------\n" ,matname);


       /*実行列の入力*/
void mat_get(a,m,n,matname)rec_mat a;int *m,*n;string *matname;{
         int i, j;
         printf("----------%s --------\n",matname);
         printf("行数を入力(<%d)",MAXR);scanf("%d",m);
         printf("列数を入力(<%d)",MAXC);scanf("%d",n);
         for (i=1; i < *m+1; i++)
                  for (j=1; j<*n+1; j++) {
                            printf("MATRIX[%2d][%2d]= ",i,j);
                            scanf("%lf",&a[i][j]);
         }
}


      /*複素行列の入力*/
void c_mat_get(mat, m, n, matname)c_recmat mat;int *m, *n;
string *matname; {
 int i, j;
 printf("----%s----\n",matname);
 printf("行数を入力(<%d)",MAXR); scanf("%d", m);
 printf("列数を入力(<%d)",MAXC); scanf("%d" ,n);
 for(i=1; i<=l; i++)
    for(j=1; j<=n; j++) {
     t=0.0;
     for(k=1; k<=m; k++)
     t+=ma[i][k]*mb{k][j];
     mz[i][j]=t;
    }
}

        /*実行列の積の演算*/
void mat_product(ma,mb,l,m,n,mz)rec_mat ma,mb,mz;int l,m,n; {
        int i, j, k; scaler t;
        printf("product of matrix A[%d][%d] and B[%d][%d]",l,m,m,n);
        for (i=1; i<=l; i++)
                  for (j=1; j<=n; j++){
                             t=0.0;
                             for (k=1; k <= m; k++)
                             t+=ma[i][k]*mb[k][j];
                             mz[i][j]=t;
        }
}

         /*複素行列の積の演算*/
void c_mat_product(maata, matb, l, m, n, matz) c_recmat mata, matb, maatz;
int l, m, n; {
 int i, j, k; complex t;
 for (i=1; i<=l+1; i++)
    for(j=1; j<n+1; j++) {
     t.re=t.im=0.0;
     for(k=1; k<m+1; k++)
     t=c_math(t,plus, c_math(mata[i][k], multiply matb[k][j]));
     matz[i][j]=t;
    }
}

           /*実行列の和の演算*/
void mat_add(ma, mb, nrow, ncol, mz)rec_mat ma, mb, mz; int nrow, ncol; {
 int i, j;
 for(i=1; i<=ncol; i++)
    for(j=1; j<=ncol+1; j++)
       matz[i][j]=c_math(mata[i][j], plus, matb[i][j]);
}

          /*複素行列の和の演算*/
void c_mat_add(mata, matb, nrow, ncol, matz)
   c_recmat mata, matbm matz; int nroq, ncol; {
   int i, j;
   for(i=1; i<=nrow; i++)
      for(j=1; j<ncol+1; j++) {
     matz[j][i].re=mata[i][j].re;
     matz[j][i].im=mata[i][j].im;
   }
}


/***************-<<複素数演算>>-*******************/
c_print(prompt,x)char *prompt; complex x;{
 printf("%s\t(%lf,%lf)\n", prompt,x.re, x.im);
}

      /*スカラー入力*/
complex c_assign(x,y)scaler x, y;{
 complex p;
 p.re=x; p.im=y;
 return(p);
}

        /*複素数の四則演算のswitch文による切り替え*/
complex c_math(c1,op,c2)complex c1, c2; opt op;{
 scaler p;
 complex t;
 switch(op) {
  case plus:      t.re=c1.re+c2.re;
                  t.im=c1.im+c2.im;
                  break;
  case minus:     t.re=c1.re-c2.re;
                  t.im=c1.im-c2.im;
                  break;
     case multiply:  t.re=c1.re*c2.re - c1.im*c2.im;
                     t.im=c1.re*c2.im + c1.im*c2.re;
                     break;
     case divide:    p=sqr(c2.re)+sqr(c2.im);
                     t.re=(c1.re*c2.re + c1.im*c2.im) / p;
                     t.im=(c1.im*c2.re - c1.re*c2.im) / p;
                     break;
     default:        t.re=c1.re;
                     t.im=c1.im;
                     break;
   }
   return(t);
}

/***以下三角関数等の関数定義***/

complex congugate(x)complex x;{
 complex t;
 t.re=x.re;
 t.im=-x.im;
 return(t);
}

scaler c_mag(x)complex x;{
 complex t, c_math();
 t=c_math(x,multiply,conjugate(x));
 return(sqrt(t.re));
}
scaler c_arg(x)complex x;{return(atan2(x.re, x.im));}

        /*指数定義*/
complex c_exp(x)complex x;{
 complex t;
 t.re=exp(x.re)*cos(x.im);
 t.im=exp(x.re)*sin(x.im);
 return(t);
}

complex c_pow(x,y)complex x;scaler y;{
 scaler z_abs, z_arg;
 complex ca, cb;
 z_abs=pow(c_mag(x),y);
 a_arg=y*c_arg(x);
 ca=c_assign(z_abs, o.o);
 cb=c_exp(0.0,z_arg);
 retrun(c_math(ca,multiply,cb));
}
       /*対数定義*/
complex c_log(x)complex x; {
 scaler tmp;
 complex ctmp;
 tmp=log((x.re*x.re+x.im*x.im)/2.0);
 ctmp=c_assign(tmp,c_arg(x));
}

complex c_log10(x)complex x;{
 scaler t,tt;
 t=c_assign(log10(EX), 0.0);
 tt=c_math(t,multiply,c_log(x));
 return(tt);
}

         /*sin関数定義*/
complex c_sin(x)complex x;{
 scaler yp,ym;
 complex t;
 yp=exp(x.im); ym=1.0/yp;
 t=c_assign(sin(x.re)*(yp+ym)/2.0,
     cos(x.re)*(yp-ym)/2.0;
 return(t);
}
     /*cos関数定義*/
complex c_cos(x)complex x;{
 scaler yp, ym;
 complex t;
 yp=exp(x.im);ym=1.0/yp;
 t=c_assign(cos(x.re)*(yp+ym)/2.0,
     sin(x.re)*(yp-ym)/2.0;
 return(t);
}

        /*tan関数定義*/
complex c_tan(x){retrun(c_math(c_sin(x),divide,c_cos(x)));}





/***********-<<QR法による行列の固有値問題>>-*************/
int menu() {
 int s;
 cls();
 printf("固有値と固有ベクトル\n");
 do {
  printf("Choose 1〜4.\n");
  scanf("%d", &s);
 }
 while((s<1)||(s>3)&&(s!4));
 return s;
}

mat_print(a,n) rec_mat a; int n; {
 int i, j;
 for(i=0; i<=n; i++) {
  for(j=1; j<=n; j++)
  printf("%7.4lf", a[i][j]);
  printf("\n");
 }
 printf("Type any key:"); ci();
}

       /*求める固有値行列の行数、列数の入力*/
mat_get(a,m,n,matname) rec_mat a; int *m, *n; string *matname; {
  int i,j;
  printf("行数は?");scanf("%d",m);
  printf("列数は?");scanf("%d",n);
  for(i=1; i<+m+1; i++)
   for(j=1; j<*n+1; j++) {
    printf("Please input a[%2d][%2d]=",i,j);
    scanf("%lf", &a[i][j]);
   }
}

put_vec(e,n) s_vector e; int n; {
 int i;
 for(i=1; i<=n; i++)
  printf("eigen[%2d]=%e\n", i, e[i]);
}

print_eig_vec(a,b,n)rec_mat a, b; int n; {
 int i, j;
 for(i=1; i<=n; i++)
 printf("%lf", a[i][i]);
 printf("\n\n Eigen Vector \n");
 for(i=1; i<=n; i++) {
  for(j=1; j<=n; j++)
  printf("%lf ", b[i][j]);
   printf("\n");
 }
 ci();
}
             /*固有値の解法*/
gvens(a,r,n) rec_mat a,r; int n; {
 int i, j, k, p, q;
 scaler sinx, cosx, tanx,rip, aip, api, app, aqq;
 unit(r,n);
 for(p=2; p<n; p++)
  for(q=p+1; q<=n; q++) {
   sinx=tanx*cosx;
   cosx=1.0/sqrt(1.0+sqr(tanx));
   tanx=-a[q][p-1]/a[p][p-1];

   for(i=1; i<=n; i++) {
    rip=r[i][p]*cosx-r[i][q]*sinx;
    r[i][q]=r[i][p]*sinx-r[i][q]*cosx;
    r[i][p]=rip;
    if((i!=p)&&(i!q)) {
     aip=a[i][p]*cosx-a[i][q]*sinx;
     a[i][q]=a[i][p]*sinx+a[i][q]*cosx;
    }
  }
  for(i=1; i<=n; i++)
   if((i!=p)&&(i!=q)) {
    api=a[p][i]*cosx-a[q][i]*sinx;
    a[q][i]=a[p][i]*sinx+a[q][i]*cosx;
  }
  app=a[p][p]*sqr(cosx)-2.0*a[p][q]*sinx*cosx+a[q][q]*sqr(sinx);
  aqq=a[p][p]*sqr(sinx)*2.0*a[p][q]*sinx*cosx+a[q][q]*sqr(cosx);
  a[p][q]=a[p][q]*(sqr(cosx)-sqr(sinx))+(a[p][p]-a[q][q])*sinx*cosx;
  a[q][p]=a[q][p]*(sqr(cosx)-sqr(sinx))+(a[p][p]-a[q][q])*sinx*cosx;
  a[p][p]=app;
  a[q][q]=aqq;
  a[q][p-1]=0.0;
 }
}

unit(a,n) rec_mat a; int n; {
  int i, j;
  for(i=1; i<=n; i++) {
   a[i][i]=1.0;
   for(j=i+1; j<=n; j++) a[i][j]=a[j][i]=0.0;
  }
}

              /*固有ベクトルの解法*/
qr(a,r,n) rec_mat a, r; int n; {
 int i, j, k, m, cnt;
 scaler d1, d2, rmdal, rmda2, rmdak, sinx, cosx, tanx, aij,qji, pji, tmp,
eps;
 static rec_mat q, p, z;
 eps=1.0E-20;
 unit(q,n);
 for(m=n; m>=2; m--)

  cnt=0;
  do {
   d1=a[m][n]+a[m-1][m-1];
   d2=sqr(d1)-4.0*(a[m-1][m-1]*a[m][m]-a[m][m-1]*a[m][m-1]*a[m-1][m]);
   d2=sqrt(d2);
   rmda1=(d1+d2)/2.0;
   rmda2=(d1-d2)/2.0;
   rmdak=(fabs(rmda1-a[m][m])<fabs(rmda2-a[m][m]))?rmdal:rmda2;

   unit(p,n);
   for(i=1; i<=m; i++)a[i][i]-=rmdak;
   for(i=1; i<m; i++) {
     sinx=cosx*tanx;
    cosx=1.0/sqrt(1.0+sqr(tanx));
    tanx=a[i+1][i].a[i][i];
    for(j=1; j<=n; j++) {
      aij=a[i][j]*cosx+a[j+1][j]*sinx;
     a[i+1][j]-=a[i][j]*sinx+q[j][i+1]*cosx;
     q[j][i]=qji;
     pji=p[j][i]*cosx+p[j][i+1]*sinx;
     p[j][i+1]-=p[j][i]*sinx+p[j][i+1]*cosx;
     p[j][i]=pji;
    }
   }
   for(i=1; i<=n; i++)
    for(j=1; g<=n; j++) z[i][j]=a[i][j];
   for(i=1; i<=n; i++)
    for(j=1; j<=n; j++) {
     tmp=0.0;
     for(k=1; k<=n; k++)tmp+=z[i][k]*p[k][j];     a[i][j]=tmp;
   }
   for(i=1; i<=m; i++) a[i][i]+=rmdak;
   cnt++;
  }
  while(fabs(a[m][m-1])>eps);
 }
 for(i=1; i<=n; i++)
  for(j=1; j<=n; j++) {
   for(k=1; k<=n; k++)tmp+=r[i][k]*q[k][j];
           z[i][j]=tmp;
  }
  for(i=1; i<=n; i++)
   for(j=1; j<=n; j++)r[i][j]=z[i][j];
}

xqr(a,x,n)rec_mat a, x; int n;{
  gvens(a,x,n);
  qe(a,x,n);
}



/****************-<<bisonによる四則演算>>-******************/
#define YYSTYPE double
#define CONSOLEAP 0 /* if console AP then set not zero */

#ifdef DEBUG
#define DebOut( s ) printf( "<%s>", s )
#else
#define DebOut( s )
#endif

char OutBuf[ 64 ]; /* result output buffer */
YYSTYPE result;
%}

%token EOL
%token NUMBER
%token LP RP
%left ADDOP SUBOP
%left MULOP DIVOP
%right MINUS
%start s

%%

s  : expr EOL
   {
    result = $1;
    dspresult();
    YYACCEPT;
   }
  ;
expr : expr ADDOP expr
   { $$ = $1 + $3; }
  | expr SUBOP expr
   { $$ = $1 - $3; }
  | expr MULOP expr
   { $$ = $1 * $3; }
  | expr DIVOP expr
   {
    if( $3 == 0.0 ) {
     sprintf( OutBuf, "divieded by zero");
     YYACCEPT;
    } else {
     $$ = $1 / $3;
    }
   }
  | SUBOP expr %prec MINUS
   { $$ = -$2; }
  | LP expr RP
   { $$ = $2; }
  | NUMBER
   { $$ = $1; }
  ;
%%

     /*yylex の現在の位置*/
static const char* lexpos = NULL;

#if CONSOLEAP
#define ANSFORM "\nanswer is %f\n"
#define ANSFORMX "\nanswer is %X\n"
char Buf[ 128 ];

/* コンソールアプリケーションの場合のメインルーチン */
#else

#define ANSFORM "%18.16g"
#define ANSFORMX "%X"
char *calculate( const char *buf )
{
 lexpos = buf;
 yyparse();
 return( OutBuf );
}
#endif


void dspresult( void )
{
 if( DspMode == 0 ) { /* if decimal */
  sprintf( OutBuf, ANSFORM, result );
 } else {
  sprintf( OutBuf, ANSFORMX, (int)result );
 }
}


int isnum( char c )
{
 return( c >= '0' && c <= '9' ? 1 : 0 );
}

char toupperalph( char c )
{
 return( c >= 'a' && c <= 'z' ? c - ( 'a' - 'A' ) : c );
}

int ishex( char c )
{
 return( isnum( c ) || ( c >= 'A' && c <= 'F' ) );
}

int hex( char c )
{
 return( c <= '9' ? c - '0' : c - 'A' + 10 );
}


        /***字句解析***/
static int yylex()
{
 char c;

 c = *lexpos;
 while( c == ' ' ) { /* 空白読み飛ばし */
  c = *++lexpos;
 }
 lexpos++;
 switch( c ) {
 case '\0':
  DebOut( "EOL" );
  return( EOL );
  break;
 case '+':
  DebOut( "ADDOP" );
  return( ADDOP );
  break;
 case '-':
  DebOut( "SUBOP" );
  return( SUBOP );
  break;
 case '*':
  DebOut( "MULOP" );
  return( MULOP );
  break;
 case '/':
  DebOut( "DIVOP" );
  return( DIVOP );
  break;
 case '(':
  DebOut( "LP" );
  return( LP );
  break;
 case ')':
  DebOut( "RP" );
  return( RP );
  break;
 default:
  if( isnum( c ) || c == '.' ) {
   lexpos--;
   if( c == '0' && *(lexpos + 1) != '.' ) { /* if hex */
    yylval = 0;
    while( ishex( c = toupperalph( *++lexpos ) ) ) {
     yylval = yylval * 16 + hex( c );
    }
   } else {
    int state;
    double point = 0.1;

    if( c == '.' ) {
     state = 1;
     yylval = 0.0;
    } else {
     state = 2;
     yylval = c - '0';
    }
    while( state ) {
     c = *++lexpos;
     switch( state ) {
     case 2:
      if( isnum( c ) ) {
       yylval = 10.0 * yylval + ( c - '0' );
      }
      else if( c == '.' ) {
       state--;
      } else {
       state = 0;
      }
      break;
     case 1:
      if( isnum( c ) ) {
       yylval += point * ( c - '0' );
       point /= 10.0;
      } else {
       state = 0;
      }
      break;
     }
    }
   }
#ifdef DEBUG
   printf( "<NUMBER:%f>", yylval );
#endif
   return( NUMBER );
  } else {
   return( c );
  }
  break;
 }
}


int yyerror( char *msg )
{
 sprintf( OutBuf,"%s", msg );
 return( 0 );
}




/**************-<<制御文の制定>>-***************/
/*calc.y*/
#define YYDEBUG 1
%}
%union {
    char  *identifier;
    ParameterList *parameter_list;
    Expression  *expression;
}
%token <expression> INT_LITERAL
%token <expression> DOUBLE_LITERAL
%token <identifier> IDENTIFIER
%token DEFINE IF ELSE WHILE LP RP LC RC SEMICOLON COMMA ASSIGN
 EQ NE GT GE LT LE ADD SUB MUL DIV MOD
%type   <parameter_list> parameter_list
%type   <expression> expression expression_list
        equality_expression relational_expression
 additive_expression multiplicative_expression
 unary_expression postfix_expression primary_expression
 if_expression while_expression
%%
translation_unit
 : definition_or_expression
 | translation_unit definition_or_expression
 ;
definition_or_expression
 : function_definition
 | expression SEMICOLON
 {
     clc_eval_expression($1);
 }
 | error
 {
     yyclearin;
     clc_reopen_current_storage();
 }
 ;
function_definition
 : DEFINE IDENTIFIER LP parameter_list RP LC expression_list RC
 {
     clc_function_define($2, $4, $7);
 }
 | DEFINE IDENTIFIER LP RP LC expression_list RC
 {
     clc_function_define($2, NULL, $6);
 }
 ;
parameter_list
 : IDENTIFIER
 {
     $$ = clc_create_parameter($1);
 }
 | parameter_list COMMA IDENTIFIER
 {
     $$ = clc_chain_parameter($1, $3);
 }
 ;
expression_list
 : expression
        {
     $$ = clc_create_expression_list($1);
 }
 | expression_list COMMA expression
 {
     $$ = clc_chain_expression_list($1, $3);
 }
 ;
expression
 : equality_expression
 | IDENTIFIER ASSIGN equality_expression
 {
     $$ = clc_create_assign_expression($1, $3);
 }
 ;
equality_expression
 : relational_expression
 | equality_expression EQ relational_expression
 {
     $$ = clc_create_binary_expression(EQ_EXPRESSION, $1, $3);
 }
 | equality_expression NE relational_expression
 {
     $$ = clc_create_binary_expression(NE_EXPRESSION, $1, $3);
 }
 ;
relational_expression
 : additive_expression
 | relational_expression GT additive_expression
 {
     $$ = clc_create_binary_expression(GT_EXPRESSION, $1, $3);
 }
 | relational_expression GE additive_expression
 {
     $$ = clc_create_binary_expression(GE_EXPRESSION, $1, $3);
 }
 | relational_expression LT additive_expression
 {
     $$ = clc_create_binary_expression(LT_EXPRESSION, $1, $3);
 }
 | relational_expression LE additive_expression
 {
     $$ = clc_create_binary_expression(LE_EXPRESSION, $1, $3);
 }
 ;
additive_expression
 : multiplicative_expression
 | additive_expression ADD multiplicative_expression
 {
     $$ = clc_create_binary_expression(ADD_EXPRESSION, $1, $3);
 }
 | additive_expression SUB multiplicative_expression
 {
     $$ = clc_create_binary_expression(SUB_EXPRESSION, $1, $3);
 }
 ;
multiplicative_expression
 : unary_expression
 | multiplicative_expression MUL unary_expression
 {
     $$ = clc_create_binary_expression(MUL_EXPRESSION, $1, $3);
 }
 | multiplicative_expression DIV unary_expression
 {
     $$ = clc_create_binary_expression(DIV_EXPRESSION, $1, $3);
 }
 | multiplicative_expression MOD unary_expression
 {
     $$ = clc_create_binary_expression(MOD_EXPRESSION, $1, $3);
 }
 ;
unary_expression
 : postfix_expression
 | SUB unary_expression
 {
     $$ = clc_create_minus_expression($2);
 }
 ;
postfix_expression
 : primary_expression
 ;
primary_expression
 : IDENTIFIER LP expression_list RP
 {
     $$ = clc_create_function_call_expression($1, $3);
 }
 | IDENTIFIER LP RP
 {
     $$ = clc_create_function_call_expression($1, NULL);
 }
 | if_expression
 | while_expression
 | LP expression RP
 {
     $$ = $2;
 }
 | IDENTIFIER
 {
     $$ = clc_create_identifier_expression($1);
 }
 | INT_LITERAL
 | DOUBLE_LITERAL
 ;
if_expression           /*if文宣言*/
 : IF expression LC expression_list RC
 {
     $$ = clc_create_if_expression($2, $4, NULL);
 }
 | IF expression LC expression_list RC ELSE LC expression_list RC
 {
     $$ = clc_create_if_expression($2, $4, $8);
 }
 ;
while_expression       /*while文宣言*/
 : WHILE expression LC expression_list RC
 {
     $$ = clc_create_while_expression($2, $4);
 }
 ;
%%

/****create.c****/

void
clc_function_define(char *identifier, ParameterList *parameter_list,
      Expression *expression_list)
{
    FunctionDefinition *f;

    if (clc_search_function(identifier)) {
 clc_compile_error(FUNCTION_MULTIPLE_DEFINE_ERR, "(%s)\n", identifier);
 clc_reopen_current_storage();
 return;
    }
    f = clc_malloc(sizeof(FunctionDefinition));
    f->name = identifier;
    f->parameter = parameter_list;
    f->expression_list = expression_list;
    f->storage = clc_current_interpreter->current_storage;
    clc_current_interpreter->current_storage = MEM_open_storage(0);

    f->next = clc_current_interpreter->function_list;
    clc_current_interpreter->function_list = f;
}

ParameterList*
clc_create_parameter(char *identifier)
{
    ParameterList *p;

    p = clc_malloc(sizeof(ParameterList));
    p->name = identifier;
    p->next = NULL;

    return p;
}

ParameterList *
chain_parameter(ParameterList *list, ParameterList *add)
{
    ParameterList *pos;

    for (pos = list; pos->next; pos = pos->next)
 ;
    pos->next = add;

    return list;
}

ParameterList*
clc_chain_parameter(ParameterList *list,  char *identifier)
{
    ParameterList *add;

    add = clc_create_parameter(identifier);

    return chain_parameter(list, add);
}

Expression *
clc_alloc_expression(ExpressionType type)
{
    Expression *exp;

    exp = clc_malloc(sizeof(Expression));
    exp->type = type;

    return exp;
}

Expression *
clc_create_expression_list(Expression *expression)
{
    Expression *exp;

    exp = clc_alloc_expression(EXPRESSION_LIST_EXPRESSION);
    exp->u.expression_list.expression = expression;
    exp->u.expression_list.next = NULL;

    return exp;
}

Expression *
clc_chain_expression_list(Expression *list, Expression *add)
{
    Expression *exp;
    Expression *pos;

    exp = clc_alloc_expression(EXPRESSION_LIST_EXPRESSION);
    exp->u.expression_list.expression = add;
    exp->u.expression_list.next = NULL;

    for (pos = list; pos->u.expression_list.next;
  pos = pos->u.expression_list.next)
 ;
    pos->u.expression_list.next = exp;

    return list;
}

Expression *
clc_create_assign_expression(char *variable,
        Expression *operand)
{
    Expression *exp;

    exp = clc_alloc_expression(ASSIGN_EXPRESSION);
    exp->u.assign_expression.variable = variable;
    exp->u.assign_expression.operand = operand;

    return exp;
}

static Expression
convert_value_to_expression(Value *v)
{
    Expression expr;

    if (v->type == INT_VALUE) {
 expr.type = INT_EXPRESSION;
 expr.u.int_value = v->u.int_value;
    } else {
 DBG_assert(v->type == DOUBLE_VALUE, ("v->type..%d\n", v->type));
 expr.type = DOUBLE_EXPRESSION;
 expr.u.double_value = v->u.double_value;
    }
    return expr;
}

Expression *
clc_create_binary_expression(ExpressionType operator,
        Expression *left,
        Expression *right)
{
    if ((left->type == INT_EXPRESSION
  || left->type == DOUBLE_EXPRESSION)
 && (right->type == INT_EXPRESSION
     || right->type == DOUBLE_EXPRESSION)) {
 Value v;
 v = clc_eval_binary_expression(NULL, operator, left, right);
 /* Overwriting left hand expression. */
 *left = convert_value_to_expression(&v);

 return left;
    } else {
 Expression *exp;
 exp = clc_alloc_expression(operator);
 exp->u.binary_expression.left = left;
 exp->u.binary_expression.right = right;
 return exp;
    }
}

Expression *
clc_create_minus_expression(Expression *operand)
{
    if (operand->type == INT_EXPRESSION
 || operand->type == DOUBLE_EXPRESSION) {
 Value v;
 v = clc_eval_minus_expression(NULL, operand);
 /* Notice! Overwriting operand expression. */
 *operand = convert_value_to_expression(&v);
 return operand;
    } else {
 Expression *exp;
 exp = clc_alloc_expression(MINUS_EXPRESSION);
 exp->u.minus_expression = operand;
 return exp;
    }
}

Expression *
clc_create_identifier_expression(char *identifier)
{
    Expression *exp;

    exp = clc_alloc_expression(IDENTIFIER_EXPRESSION);
    exp->u.identifier = identifier;

    return exp;
}

Expression *
clc_create_if_expression(Expression *condition,
    Expression *then_expression,
    Expression *else_expression)
{
    Expression *exp;

    exp = clc_alloc_expression(IF_EXPRESSION);
    exp->u.if_expression.condition = condition;
    exp->u.if_expression.then_expression = then_expression;
    exp->u.if_expression.else_expression = else_expression;

    return exp;
}

Expression *
clc_create_while_expression(Expression *condition,
       Expression *expression)
{
    Expression *exp;

    exp = clc_alloc_expression(WHILE_EXPRESSION);
    exp->u.while_expression.condition = condition;
    exp->u.while_expression.expression_list = expression;

    return exp;
}

Expression *
clc_create_function_call_expression(char *func_name,
        Expression *argument)
{
    Expression *exp;

    exp = clc_alloc_expression(FUNCTION_CALL_EXPRESSION);
    exp->u.function_call_expression.identifier = func_name;
    exp->u.function_call_expression.argument = argument;

    return exp;
}





3  感想

これまでの課題でさすがに一番重く、一番きついものだった。 四則演算プログラムはすぐにできた。その他にかなり要した。でも複素数のプログラ ム辺りは、以前の課題とマッチする部分もあり、それを参照したりしたので、その辺 は楽だった。今回初めて書くところが重かった。いろいろ機能を貼り付けないといけ なくて、「あれも、これも」と考えなければならないのが嫌になってきた。でも中途 半端で提出するのもどこか癪に障るので、絵とかさすがにできていないものの、要求 されたことがそれなりに満たされるまでは書いた。四則演算、複素演算、実行列演 算、複素行列演算、行列の固有値、固有ベクトル問題、三角関数や対数、for文、 while文といったものが定義してある。とりわけ行列の演算はほぼ何でもできるよう になっていると思う。行列は自分なりに力を入れて書いた部分である。絵とかどう やって実現したらいいのか、ちょっと手法が考え付かなかったので、そこだけはノー タッチである。当初、提出期限が7月31日までということで、それに合わせて書い ていたのであるが、先生の恩赦?により期限が延びたものの、僕はちょっと個人的な 都合で、もうこれ以上課題をやっていられなくなったので(伸ばしてもらったのにそ の恩恵をこうむることなく)、もう少し考えてみたい部分はあったのですが、これで 提出ということにさせて頂きます。 数値計算の課題は数が多かっただけでなく、その質も毎回高く、非常に苦しいもの だった。4月頃は本当に先行き不安であったが、でも何とかかんとかやってこれたと 思う。振り返ってみればあっという間だった気がする。この数値計算に限らず、何時 の間にか僕も3年でもう学生生活もそうは長くなくなってしまった。残り充実させる ように勉学共々励んでいきたいと思った。


File translated from TEX by TTH, version 2.80.
On 16 Aug 2001, 21:41.