home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / IRIT / IRITS.ZIP / OVERLOAD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-05  |  11.4 KB  |  347 lines

  1. /*****************************************************************************
  2. *   "Irit" - the 3d polygonal solid modeller.                     *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.2, Mar. 1990   *
  5. ******************************************************************************
  6. *   Module to handle overloaded operators for the input parser module.         *
  7. * Note this module should be accessed by Input Parser only (InptPrsr.c).     *
  8. *****************************************************************************/
  9.  
  10. #ifdef __MSDOS__
  11. #include <alloc.h>
  12. #endif /* __MSDOS__ */
  13.  
  14. #include <stdio.h>
  15. #include <ctype.h>
  16. #include <math.h>
  17. #include <string.h>
  18. #include "program.h"
  19. #include "objects.h"
  20. #include "allocatg.h"
  21. #include "booleang.h"
  22. #include "inptprsg.h"
  23. #include "inptprsl.h"
  24. #include "overload.h"
  25. #include "geomat3d.h"
  26.  
  27. /* The following table help to decide if the operand are legal for the given */
  28. /* operator. 5 entries for PLUS, MINUS, MULT, DIV, POWER. Each entry is a    */
  29. /* square matrix of number of object types by number of object types:         */
  30. /* GEOMETRIC_EXPR NUMERIC_EXPR VECTOR_EXPR MATRIX_EXPR (num. from 1 to 4).   */
  31.  
  32. static ByteType OverLoadDiadicTable[5][4][4] =
  33. /*    GEOMETRIC_EXPR    NUMERIC_EXPR    VECTOR_EXPR    MATRIX_EXPR    */
  34. { { {    GEOMETRIC_EXPR,    0,        0,        0 },    /* PLUS */
  35.     {    0,        NUMERIC_EXPR,    0,        0 },
  36.     {    0,        0,        VECTOR_EXPR,    0 },
  37.     {    0,        0,        0,        MATRIX_EXPR } },
  38.  
  39.   { {    GEOMETRIC_EXPR,    0,        0,        0 },    /* MINUS */
  40.     {    0,        NUMERIC_EXPR,    0,        0 },
  41.     {    0,        0,        VECTOR_EXPR,    0 },
  42.     {    0,        0,        0,        MATRIX_EXPR } },
  43.  
  44.   { {    GEOMETRIC_EXPR,    0,        0,        GEOMETRIC_EXPR }, /*MULT */
  45.     {    0,        NUMERIC_EXPR,    VECTOR_EXPR,    MATRIX_EXPR },
  46.     {    0,        VECTOR_EXPR,    NUMERIC_EXPR,    VECTOR_EXPR },
  47.     {    GEOMETRIC_EXPR,    MATRIX_EXPR,    VECTOR_EXPR,    MATRIX_EXPR } },
  48.  
  49.   { {    0,        0,        0,        0 },    /* DIV */
  50.     {    0,        NUMERIC_EXPR,    0,        0 },
  51.     {    0,        0,        0,        0 },
  52.     {    0,        0,        0,        0 } },
  53.  
  54.   { {    0,        0,        0,        0 },    /* POWER */
  55.     {    0,        NUMERIC_EXPR,    0,        MATRIX_EXPR },
  56.     {    0,        0,        0,        0 },
  57.     {    0,        MATRIX_EXPR,    0,        0 } }
  58. };
  59.  
  60. /* The following table help to decide if the operand are legal for the given */
  61. /* operator. 1 entry for UNARMINUS. Each entry is a linear vector of length  */
  62. /* of number of object types:                             */
  63. /* GEOMETRIC_EXPR NUMERIC_EXPR VECTOR_EXPR MATRIX_EXPR (num. from 1 to 4).   */
  64.  
  65. static ByteType OverLoadMonadicTable[1][NUM_OF_OBJECT_TYPES] =
  66. /*    GEOMETRIC_EXPR    NUMERIC_EXPR    VECTOR_EXPR    MATRIX_EXPR    */
  67. {    GEOMETRIC_EXPR,    NUMERIC_EXPR,    VECTOR_EXPR,    MATRIX_EXPR    };
  68.                                 /* UNARMINUS */
  69.  
  70. /*****************************************************************************
  71. *   Routine to perform type checking on the overloaded operators. Returns    *
  72. * TRUE if legal, and set Result to returned object type.             *
  73. *****************************************************************************/
  74. int OverLoadTypeCheck(int Operator, int Right, int Left, int *Result)
  75. {
  76.     if (!(Right == NUMERIC_OBJ ||
  77.       Right == VECTOR_OBJ ||
  78.       Right == MATRIX_OBJ ||
  79.       Right == GEOMETRIC_OBJ) &&
  80.      (Left  == NUMERIC_OBJ ||
  81.       Left  == VECTOR_OBJ ||
  82.       Left  == MATRIX_OBJ ||
  83.       Left  == GEOMETRIC_OBJ)) return FALSE;
  84.  
  85.     switch(Operator) {
  86.     case PLUS:
  87.     case MINUS:
  88.     case MULT:
  89.     case DIV:
  90.     case POWER:
  91.         *Result = OverLoadDiadicTable[Operator - OPERATORS_OFFSET]
  92.                             [Right - 1][Left - 1];
  93.         return *Result != 0;
  94.  
  95.     case UNARMINUS:
  96.         *Result = OverLoadMonadicTable[0][Right - 1];
  97.         return *Result != 0;
  98.     default:
  99.         FatalError("OverLoadTypeCheck: undefined operator\n");
  100.     }
  101.     return FALSE;                    /* Makes warning silent. */
  102. }
  103.  
  104. /*****************************************************************************
  105. *   Routine to evaluate    an monadic or diadic expression. It is assumed the   *
  106. * two operands are valid for the given expression - a test which can be made *
  107. * using OverLoadTypeCheck routine (see above). returned pointer to node with *
  108. * the result, NULL in case of error (should not happen actually).         *
  109. * Root holds the simple sub-expression (Root has the operator). PObj holds   *
  110. * all the currently defined objects available in the system. IError & CError *
  111. * will be set to relevant error if was one.                     *
  112. *****************************************************************************/
  113. struct ParseTree *OverLoadEvalOper(ParseTree *Root, ParseTree *TempR,
  114.                 ParseTree *TempL, int *IError, char *CError)
  115. {
  116.     int i;
  117.     RealType R;
  118.     struct ParseTree *Temp;
  119.     struct ParseTree *RetVal = Root;
  120.  
  121.     switch(Root->NodeKind) {              /* Dies if undefined operator. */
  122.     case PLUS:
  123.     case MINUS:
  124.     case MULT:
  125.     case DIV:
  126.     case POWER:
  127.         if (TempR == NULL || TempL == NULL) return NULL;       /* Error! */
  128.         break;
  129.  
  130.     case UNARMINUS:
  131.         if (TempR == NULL) return NULL;               /* Error! */
  132.         break;
  133.  
  134.     default:
  135.         FatalError("OverLoadEvalOper: Undefined operator\n");
  136.     }
  137.  
  138.     if (Root -> NodeKind != UNARMINUS &&
  139.     TempR -> ObjType > TempL -> ObjType) {        /* Make TempL be bigger! */
  140.     Temp = TempR;
  141.     TempR = TempL;
  142.     TempL = Temp;
  143.     }
  144.  
  145.     switch(Root->NodeKind) {
  146.     case PLUS:
  147.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
  148.         Root->ObjType = NUMERIC_OBJ;
  149.         Root->U.R = TempL->U.R + TempR->U.R;
  150.         }
  151.         else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
  152.         Root->ObjType = VECTOR_OBJ;
  153.         Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
  154.         PT_ADD(Root->U.PObj->U.Vec,
  155.             TempL->U.PObj->U.Vec, TempR->U.PObj->U.Vec);
  156.         }
  157.         else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
  158.         Root->ObjType = MATRIX_OBJ;
  159.         Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
  160.                 MatAddTwo4by4(Root->U.PObj->U.Mat,
  161.             TempL->U.PObj->U.Mat, TempR->U.PObj->U.Mat);
  162.         }
  163.         else if (IS_GEOM_NODE(TempR) && IS_GEOM_NODE(TempL)) {
  164.         Root->ObjType = GEOMETRIC_OBJ;
  165.         Root->U.PObj = BooleanOR(TempL -> U.PObj, TempR -> U.PObj);
  166.         if (Root->U.PObj == NULL) {
  167.             IPGlblEvalError = IE_ERR_BooleanErr;
  168.             UpdateCharError("Operator ", PLUS);
  169.             RetVal = NULL;
  170.         }
  171.         }
  172.         else RetVal = NULL;
  173.         break;
  174.     case MINUS:
  175.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
  176.         Root->ObjType = NUMERIC_OBJ;
  177.         Root->U.R = TempL->U.R - TempR->U.R;
  178.         }
  179.         else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
  180.         Root->ObjType = VECTOR_OBJ;
  181.         Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
  182.         PT_SUB(Root->U.PObj->U.Vec,
  183.             TempL->U.PObj->U.Vec, TempR->U.PObj->U.Vec);
  184.         }
  185.         else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
  186.         Root->ObjType = MATRIX_OBJ;
  187.         Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
  188.                 MatSubTwo4by4(Root->U.PObj->U.Mat,
  189.             TempL->U.PObj->U.Mat, TempR->U.PObj->U.Mat);
  190.         }
  191.         else if (IS_GEOM_NODE(TempR) && IS_GEOM_NODE(TempL)) {
  192.         Root->ObjType = GEOMETRIC_OBJ;
  193.         Root->U.PObj = BooleanSUB(TempL -> U.PObj, TempR -> U.PObj);
  194.         if (Root->U.PObj == NULL) {
  195.             IPGlblEvalError = IE_ERR_BooleanErr;
  196.             UpdateCharError("Operator ", MINUS);
  197.             RetVal = NULL;
  198.         }
  199.         }
  200.         else RetVal = NULL;
  201.         break;
  202.     case MULT:
  203.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
  204.         Root->ObjType = NUMERIC_OBJ;
  205.         Root->U.R = TempL->U.R * TempR->U.R;
  206.         }
  207.         else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
  208.         Root->ObjType = NUMERIC_OBJ;
  209.         Root->U.R = DOT_PROD(TempL->U.PObj->U.Vec,
  210.                      TempR->U.PObj->U.Vec);
  211.         }
  212.         else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
  213.         Root->ObjType = MATRIX_OBJ;
  214.         Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
  215.                 MatMultTwo4by4(Root->U.PObj->U.Mat,
  216.             TempL->U.PObj->U.Mat, TempR->U.PObj->U.Mat);
  217.         }
  218.         else if (IS_NUM_NODE(TempR) && IS_VEC_NODE(TempL)) {
  219.         Root->ObjType = VECTOR_OBJ;
  220.         Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
  221.         PT_COPY(Root->U.PObj->U.Vec, TempL->U.PObj->U.Vec);
  222.         PT_SCALE(Root->U.PObj->U.Vec, TempR->U.R);
  223.         }
  224.         else if (IS_NUM_NODE(TempR) && IS_MAT_NODE(TempL)) {
  225.         Root->ObjType = MATRIX_OBJ;
  226.         Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
  227.         MatScale4by4(Root->U.PObj->U.Mat,
  228.                     TempL->U.PObj->U.Mat, &TempR->U.R);
  229.         }
  230.         else if (IS_GEOM_NODE(TempR) && IS_MAT_NODE(TempL)) {
  231.         Root->ObjType = GEOMETRIC_OBJ;
  232.         Root->U.PObj = CopyObject(NULL, TempR->U.PObj, FALSE);
  233.         TransformObject(Root->U.PObj, TempL->U.PObj->U.Mat);
  234.         }
  235.         else if (IS_VEC_NODE(TempR) && IS_MAT_NODE(TempL)) {
  236.         Root->ObjType = VECTOR_OBJ;
  237.         Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
  238.         MatMultVecby4by4(Root->U.PObj->U.Vec,
  239.                  TempR->U.PObj->U.Vec, TempL->U.PObj->U.Mat);
  240.         }
  241.         else if (IS_GEOM_NODE(TempR) && IS_GEOM_NODE(TempL)) {
  242.         Root->ObjType = GEOMETRIC_OBJ;
  243.         Root->U.PObj = BooleanAND(TempL -> U.PObj, TempR -> U.PObj);
  244.         if (Root->U.PObj == NULL) {
  245.             IPGlblEvalError = IE_ERR_BooleanErr;
  246.             UpdateCharError("Operator ", MULT);
  247.             RetVal = NULL;
  248.         }
  249.         }
  250.         else RetVal = NULL;
  251.         break;
  252.     case DIV:
  253.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {  /* Numeric div. */
  254.         Root->ObjType = NUMERIC_OBJ;
  255.         if (Root->Right->U.R != 0.0) {
  256.             Root->U.R = TempL->U.R / TempR->U.R;
  257.         }
  258.         else {
  259.             *IError = IE_ERR_DivByZero;
  260.             strcpy(CError, "/");
  261.             RetVal = NULL;
  262.         }
  263.         }
  264.         else RetVal = NULL;
  265.         break;
  266.     case POWER:
  267.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {/* Numeric power. */
  268.         Root->ObjType = NUMERIC_OBJ;
  269.         Root->U.R = pow(TempL->U.R, TempR->U.R);
  270.         }
  271.         else if (IS_NUM_NODE(TempR) && IS_MAT_NODE(TempL)) {
  272.         i = (int) TempR->U.R; /* Power MUST be integer in this case. */
  273.         if (!APX_EQ(i, TempR->U.R) || i < -1) {
  274.             *IError = IE_ERR_MatPower;
  275.             strcpy(CError, "^");
  276.             RetVal = NULL;
  277.         }
  278.         Root->ObjType = MATRIX_OBJ;
  279.         Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
  280.         if (i == -1) {             /* Generate the inverse matrix: */
  281.             if (!MatInverseMatrix(TempL->U.PObj->U.Mat,
  282.                       Root->U.PObj->U.Mat)) {
  283.             *IError = IE_ERR_MatPower;
  284.             strcpy(CError, "^");
  285.             RetVal = NULL;
  286.             }
  287.         }
  288.         else {                  /* I must be positive integer. */
  289.             MatGenUnitMat(Root->U.PObj->U.Mat);
  290.             while (i--) MatMultTwo4by4(Root->U.PObj->U.Mat,
  291.                            Root->U.PObj->U.Mat,
  292.                            TempL->U.PObj->U.Mat);
  293.         }
  294.         }
  295.         else RetVal = NULL;
  296.         break;
  297.     case UNARMINUS:
  298.         if (IS_NUM_NODE(TempR)) {
  299.         Root->ObjType = NUMERIC_OBJ;
  300.         Root->U.R = -TempR->U.R;
  301.         }
  302.         else if (IS_VEC_NODE(TempR)) {
  303.         Root->ObjType = VECTOR_OBJ;
  304.         Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
  305.         PT_COPY(Root->U.PObj->U.Vec, TempR->U.PObj->U.Vec);
  306.         PT_SCALE(Root->U.PObj->U.Vec, -1.0);
  307.         }
  308.         else if (IS_MAT_NODE(TempR)) {
  309.         Root->ObjType = MATRIX_OBJ;
  310.         Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
  311.         R = -1.0;
  312.         MatScale4by4(Root->U.PObj->U.Mat, TempR->U.PObj->U.Mat, &R);
  313.         }
  314.         else if (IS_GEOM_NODE(TempR)) {
  315.         Root->ObjType = GEOMETRIC_OBJ;
  316.         Root->U.PObj = BooleanNEG(TempR -> U.PObj);
  317.         }
  318.         else RetVal = NULL;
  319.         break;
  320.     }
  321.     if (RetVal == NULL && *IError == 0) {      /* Put general error message: */
  322.     *IError = IE_ERR_TypeMismatch;
  323.     switch (Root->NodeKind) {
  324.         case PLUS:
  325.         strcpy(CError, "Operator +");
  326.         break;
  327.         case MINUS:
  328.         strcpy(CError, "Operator -");
  329.         break;
  330.         case MULT:
  331.         strcpy(CError, "Operator *");
  332.         break;
  333.         case DIV:
  334.         strcpy(CError, "Operator /");
  335.         break;
  336.         case POWER:
  337.         strcpy(CError, "Operator ^");
  338.         break;
  339.         case UNARMINUS:
  340.         strcpy(CError, "Operator (unary) -");
  341.         break;
  342.     }
  343.     }
  344.  
  345.     return RetVal;
  346. }
  347.