home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 11 / FM Towns Free Software Collection 11.iso / t_os / lib / objcol2 / src / value.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-13  |  7.1 KB  |  417 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <math.h>
  4. #include <ctype.h>
  5.  
  6. #define    NOERR    0
  7. #define    ERR        1
  8. #define    FUNCMAX    20
  9. #define    PI        3.14159
  10.  
  11. /*----------     演算子情報構造体     ----------*/
  12. typedef struct
  13. {
  14.     char    name[8];
  15.     int        prior;
  16. } FUNC ;
  17.  
  18. /*----------     演算子設定      ----------*/
  19. static FUNC    func[FUNCMAX] = {
  20.                     { "(", 5 }, { "number", 4 }, { "^", 3 }, { "sqr", 3 },
  21.                     { "*", 2 }, { "/", 2 }, { "+", 1 }, { "-", 1 },
  22.                     { ")", 0 }, { "sin", 3 }, { "cos", 3 }, { "tan", 3 },
  23.                     { "arcsin", 3 }, { "arccos", 3 }, { "arctan", 3 },
  24.                     { "log", 3 }, { "ln", 3 }, { "exp", 3 }, { "mod", 3 },
  25.                     { "abs", 3 }
  26. };
  27.  
  28. int        calcvalue( const char *, double * );
  29. static int    CV_get_number( const char *, double *, int *, int );
  30. static int    CV_get_function( const char *, int *, int * );
  31. static int    topcmp( const char *, const char * );
  32. static void    tolowerstr( const char *, char * );
  33.  
  34. /*----------     main routine     ----------*/
  35. int        calcvalue( const char *q, double *v )
  36. {
  37.     int        mem_1[256],mem_2[256];
  38.     double    mem_3[256],mem_4[256],value;
  39.     int        code,a;
  40.     int        *st_1,*st_2;
  41.     double    *st_3,*st_4;
  42.     char    *p,buf[256];
  43.  
  44.     p = buf;
  45.     tolowerstr( q, p );
  46.     bzero( mem_2, 256 );
  47. /*-----------     逆ポーランド記法への変換     -----------*/
  48.  
  49.     st_1 = mem_1;
  50.     st_2 = mem_2;
  51.     st_3 = mem_3;
  52.     st_4 = mem_4;
  53.  
  54.     code = 0;
  55.  
  56.     while( *p )
  57.     {
  58.         while( *p == ' ' )
  59.             ++ p;
  60.  
  61.         if( CV_get_number( p, &value, &a, code ) )
  62.         {
  63.             if( CV_get_function( p, &code, &a ) )
  64.             {
  65.                 return ERR;
  66.             }
  67.         }
  68.         else
  69.         {
  70.             code = 1;
  71.         }
  72.  
  73.         p += a;
  74.         while( func[code].prior <= func[*st_2].prior && *st_2 != 0 && st_2 > mem_2 )
  75.         {
  76.             *st_1 = *st_2;
  77.             *st_3 = *st_4;
  78.             ++st_1;
  79.             ++st_3;
  80.             --st_2;
  81.             --st_4;
  82.         }
  83.  
  84.         if( code != 8 )
  85.         {
  86.             ++st_2;
  87.             ++st_4;
  88.             *st_2 = code;
  89.             *st_4 = value; 
  90.         }
  91.         else
  92.         {
  93.             if( *st_2 != 0 )
  94.                 return ERR;
  95.             --st_2;
  96.             --st_4;
  97.         }
  98.     }
  99.  
  100.     while( st_2 > mem_2 )
  101.     {
  102.         *st_1 = *st_2;
  103.         *st_3 = *st_4;
  104.         ++st_1;
  105.         ++st_3;
  106.         --st_2;
  107.         --st_4;
  108.     }
  109.  
  110.     *st_1 = 0xff;
  111. /*-----------     逆ポーランド記法の計算     ----------*/
  112.  
  113.     st_1 = mem_1;
  114.     st_3 = mem_3;
  115.     st_4 = mem_4;
  116.  
  117.     while( *st_1 != 0xff )
  118.     {
  119.         double    x,y,z,dmy;
  120.  
  121.         switch( *st_1 )
  122.         {
  123.             case 1:/*-----     数値     -----*/
  124.                 *st_4 = *st_3;
  125.                 ++st_4;
  126.                 break;
  127.  
  128.             case 2:/*-----     巾乗 (x ^ y)     -----*/
  129.                 y = *(st_4-1);
  130.                 x = *(st_4-2);
  131.                 st_4 -= 2;
  132.                 if( x < 0 && modf( y, &dmy ) != 0 )
  133.                     return ERR;
  134.                 z = pow( x, y );
  135.                 *st_4 = z;
  136.                 ++st_4;
  137.                 break;
  138.  
  139.             case 3:/*-----     平方根 (sqr x)[x>=0]     -----*/
  140.                 x = *(st_4-1);
  141.                 --st_4;
  142.                 if( x < 0 )
  143.                     return ERR;
  144.                 z = sqrt( x );
  145.                 *st_4 = z;
  146.                 ++st_4;
  147.                 break;
  148.  
  149.             case 4:/*-----     掛け算 (x * y)     -----*/
  150.                 y = *(st_4-1);
  151.                 x = *(st_4-2);
  152.                 st_4 -= 2;
  153.                 z = x * y;
  154.                 *st_4 = z;
  155.                 ++st_4;
  156.                 break;
  157.  
  158.             case 5:/*-----     割り算 (x / y)[y!=0]     -----*/
  159.                 y = *(st_4-1);
  160.                 x = *(st_4-2);
  161.                 st_4 -= 2;
  162.                 z = x / y;
  163.                 if( y == 0 )
  164.                     return ERR;
  165.                 *st_4 = z;
  166.                 ++st_4;
  167.                 break;
  168.  
  169.             case 6:/*-----     足し算 (x + y)     -----*/
  170.                 y = *(st_4-1);
  171.                 x = *(st_4-2);
  172.                 st_4 -= 2;
  173.                 z = x + y;
  174.                 *st_4 = z;
  175.                 ++st_4;
  176.                 break;
  177.  
  178.             case 7:/*-----     引き算 (x - y)     -----*/
  179.                 y = *(st_4-1);
  180.                 if( st_4-1 == mem_4 )
  181.                 {
  182.                     x = 0;
  183.                     --st_4;
  184.                 }
  185.                 else
  186.                 {
  187.                     x = *(st_4-2);
  188.                     st_4 -= 2;
  189.                 }
  190.                 z = x - y;
  191.                 *st_4 = z;
  192.                 ++st_4;
  193.                 break;
  194.  
  195.             case 9:/*-----     正弦 (sin x)     -----*/
  196.                 x = *(st_4-1);
  197.                 --st_4;
  198.                 z = sin( x );
  199.                 *st_4 = z;
  200.                 ++st_4;
  201.                 break;
  202.  
  203.             case 10:/*-----     余弦 (cos x)     -----*/
  204.                 x = *(st_4-1);
  205.                 --st_4;
  206.                 z = cos( x );
  207.                 *st_4 = z;
  208.                 ++st_4;
  209.                 break;
  210.  
  211.             case 11:/*-----     正接 (tan x)[x!=PI/2+2*n*PI]     -----*/
  212.                 x = *(st_4-1);
  213.                 --st_4;
  214.                 if( modf( fmod( x - PI/2, PI ), &dmy ) == 0 )
  215.                     return ERR;
  216.                 z = tan( x );
  217.                 *st_4 = z;
  218.                 ++st_4;
  219.                 break;
  220.  
  221.             case 12:/*-----     正弦の逆関数 (Arcsin x)[-1<=x<=1]     -----*/
  222.                 x = *(st_4-1);
  223.                 --st_4;
  224.                 if( x > 1 || x < -1 )
  225.                     return ERR;
  226.                 z = asin( x );
  227.                 *st_4 = z;
  228.                 ++st_4;
  229.                 break;
  230.  
  231.             case 13:/*-----     余弦の逆関数 (Arccos x)[-1<=x<=1]     -----*/
  232.                 x = *(st_4-1);
  233.                 --st_4;
  234.                 if( x > 1 || x < -1 )
  235.                     return ERR;
  236.                 z = acos( x );
  237.                 *st_4 = z;
  238.                 ++st_4;
  239.                 break;
  240.  
  241.             case 14:/*-----     正接の逆関数 (Arctan x)     -----*/
  242.                 x = *(st_4-1);
  243.                 --st_4;
  244.                 z = atan( x );
  245.                 *st_4 = z;
  246.                 ++st_4;
  247.                 break;
  248.  
  249.             case 15:/*-----     常用対数 (log x)[x>0]     -----*/
  250.                 x = *(st_4-1);
  251.                 --st_4;
  252.                 if( x <= 0 )
  253.                     return ERR;
  254.                 z = log10( x );
  255.                 *st_4 = z;
  256.                 ++st_4;
  257.                 break;
  258.  
  259.             case 16:/*-----     自然対数 (ln x)[x>0]     -----*/
  260.                 x = *(st_4-1);
  261.                 --st_4;
  262.                 if( x <= 0 )
  263.                     return ERR;
  264.                 z = log( x );
  265.                 *st_4 = z;
  266.                 ++st_4;
  267.                 break;
  268.  
  269.             case 17:/*-----     自然対数の巾乗 (exp x)     -----*/
  270.                 x = *(st_4-1);
  271.                 --st_4;
  272.                 z = exp( x );
  273.                 *st_4 = z;
  274.                 ++st_4;
  275.                 break;
  276.  
  277.             case 18:/*-----     剰余 (x mod y)[y!=0]     -----*/
  278.                 y = *(st_4-1);
  279.                 x = *(st_4-2);
  280.                 st_4 -= 2;
  281.                 if( y == 0 )
  282.                     return ERR;
  283.                 z = fmod( x, y );
  284.                 *st_4 = z;
  285.                 ++st_4;
  286.                 break;
  287.  
  288.             case 19:/*-----     絶対値 (abs x)     -----*/
  289.                 x = *(st_4-1);
  290.                 --st_4;
  291.                 z = fabs( x );
  292.                 *st_4 = z;
  293.                 ++st_4;
  294.                 break;
  295.         }
  296.         ++st_1;
  297.         ++st_3;
  298.     }
  299.  
  300.     *v = *(st_4-1);
  301.  
  302.     return NOERR;
  303. }
  304.  
  305. static int    CV_get_number( const char *p, double *value, int *a, int code )
  306. {
  307.     int        flg1,flg2,flg3;
  308.     double    tmp;    
  309.  
  310.     *value = 0;
  311.     *a = 0;
  312.     flg1 = 0;
  313.     flg2 = ERR;
  314.     flg3 = 0;
  315.  
  316.     if( *p == '-' && code != 1 )
  317.     {
  318.         ++ *a;
  319.         ++ p;
  320.         flg3 = 1;
  321.     }
  322.     
  323.     if( *p == '0' && *(p+1) == 'x' )
  324.     {
  325.         p += 2;
  326.         *a += 2;
  327.  
  328.         while( ( *p >= '0' && *p <= '9' ) || ( *p >= 'a' && *p <= 'f' ) )
  329.         {
  330.             *value *= 16;
  331.             if( *p >= '0' && *p <= '9' )
  332.                 *value += *p - '0';
  333.             else
  334.                 *value += *p - 'a' + 10;
  335.  
  336.             ++ p;
  337.             ++ *a;
  338.         }
  339.         flg2 = NOERR;
  340.     }
  341.     else
  342.     {
  343.         while( ( *p >= '0' && *p <= '9' ) || *p == '.' )
  344.         {
  345.             if( *p == '.' )
  346.             {
  347.                 if( flg1 != 0 )
  348.                     return ERR;
  349.                 flg1 = 1;
  350.                 ++ *a;
  351.                 ++p;
  352.                 continue;
  353.             }
  354.  
  355.             if( flg1 == 0 )
  356.             {
  357.                 *value *= 10;
  358.                 *value += *p - '0';
  359.             }
  360.             else
  361.             {
  362.                 tmp = *p - '0';
  363.                 tmp /= pow( 10, flg1 );
  364.                 *value += tmp;
  365.                 ++flg1;
  366.             }
  367.  
  368.             flg2 = NOERR;
  369.             ++ p;
  370.             ++ *a;
  371.         }
  372.     }
  373.  
  374.     if( flg3 == 1 )
  375.     *value = 0 - *value;
  376.  
  377.     return flg2;
  378. }
  379.  
  380. static int    CV_get_function( const char *p, int *code, int *a )
  381. {
  382.     int        i;
  383.  
  384.     i = 0;
  385.     while( i < FUNCMAX )
  386.     {
  387.         if( strncmp( p, func[i].name, strlen(func[i].name) ) == 0 /*topcmp( p, func[i].name )*/ )
  388.         {
  389.             *code = i;
  390.             *a = strlen( func[i].name );
  391.             return NOERR;
  392.         }
  393.         ++ i;
  394.     }
  395.     return ERR;
  396. }
  397.  
  398. static int    topcmp( const char *p, const char *q )
  399. {
  400.     while( *q )
  401.     {
  402.         if( *p != *q )
  403.             return 0;
  404.         ++p;
  405.         ++q;
  406.     }
  407.     return 1;
  408. }
  409.  
  410. static void    tolowerstr( const char *in, char *out )
  411. {
  412.     while( *in )
  413.         *out++ = tolower(*in++);
  414.     *out = 0;
  415.     return;
  416. }
  417.