home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * "Irit" - the 3d polygonal solid modeller. *
- * *
- * Written by: Gershon Elber Ver 0.2, Mar. 1990 *
- ******************************************************************************
- * Module to handle overloaded operators for the input parser module. *
- * Note this module should be accessed by Input Parser only (InptPrsr.c). *
- *****************************************************************************/
-
- #ifdef __MSDOS__
- #include <alloc.h>
- #endif /* __MSDOS__ */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <math.h>
- #include <string.h>
- #include "program.h"
- #include "objects.h"
- #include "allocatg.h"
- #include "booleang.h"
- #include "inptprsg.h"
- #include "inptprsl.h"
- #include "overload.h"
- #include "geomat3d.h"
-
- /* The following table help to decide if the operand are legal for the given */
- /* operator. 5 entries for PLUS, MINUS, MULT, DIV, POWER. Each entry is a */
- /* square matrix of number of object types by number of object types: */
- /* GEOMETRIC_EXPR NUMERIC_EXPR VECTOR_EXPR MATRIX_EXPR (num. from 1 to 4). */
-
- static ByteType OverLoadDiadicTable[5][4][4] =
- /* GEOMETRIC_EXPR NUMERIC_EXPR VECTOR_EXPR MATRIX_EXPR */
- { { { GEOMETRIC_EXPR, 0, 0, 0 }, /* PLUS */
- { 0, NUMERIC_EXPR, 0, 0 },
- { 0, 0, VECTOR_EXPR, 0 },
- { 0, 0, 0, MATRIX_EXPR } },
-
- { { GEOMETRIC_EXPR, 0, 0, 0 }, /* MINUS */
- { 0, NUMERIC_EXPR, 0, 0 },
- { 0, 0, VECTOR_EXPR, 0 },
- { 0, 0, 0, MATRIX_EXPR } },
-
- { { GEOMETRIC_EXPR, 0, 0, GEOMETRIC_EXPR }, /*MULT */
- { 0, NUMERIC_EXPR, VECTOR_EXPR, MATRIX_EXPR },
- { 0, VECTOR_EXPR, NUMERIC_EXPR, VECTOR_EXPR },
- { GEOMETRIC_EXPR, MATRIX_EXPR, VECTOR_EXPR, MATRIX_EXPR } },
-
- { { 0, 0, 0, 0 }, /* DIV */
- { 0, NUMERIC_EXPR, 0, 0 },
- { 0, 0, 0, 0 },
- { 0, 0, 0, 0 } },
-
- { { 0, 0, 0, 0 }, /* POWER */
- { 0, NUMERIC_EXPR, 0, MATRIX_EXPR },
- { 0, 0, 0, 0 },
- { 0, MATRIX_EXPR, 0, 0 } }
- };
-
- /* The following table help to decide if the operand are legal for the given */
- /* operator. 1 entry for UNARMINUS. Each entry is a linear vector of length */
- /* of number of object types: */
- /* GEOMETRIC_EXPR NUMERIC_EXPR VECTOR_EXPR MATRIX_EXPR (num. from 1 to 4). */
-
- static ByteType OverLoadMonadicTable[1][NUM_OF_OBJECT_TYPES] =
- /* GEOMETRIC_EXPR NUMERIC_EXPR VECTOR_EXPR MATRIX_EXPR */
- { GEOMETRIC_EXPR, NUMERIC_EXPR, VECTOR_EXPR, MATRIX_EXPR };
- /* UNARMINUS */
-
- /*****************************************************************************
- * Routine to perform type checking on the overloaded operators. Returns *
- * TRUE if legal, and set Result to returned object type. *
- *****************************************************************************/
- int OverLoadTypeCheck(int Operator, int Right, int Left, int *Result)
- {
- if (!(Right == NUMERIC_OBJ ||
- Right == VECTOR_OBJ ||
- Right == MATRIX_OBJ ||
- Right == GEOMETRIC_OBJ) &&
- (Left == NUMERIC_OBJ ||
- Left == VECTOR_OBJ ||
- Left == MATRIX_OBJ ||
- Left == GEOMETRIC_OBJ)) return FALSE;
-
- switch(Operator) {
- case PLUS:
- case MINUS:
- case MULT:
- case DIV:
- case POWER:
- *Result = OverLoadDiadicTable[Operator - OPERATORS_OFFSET]
- [Right - 1][Left - 1];
- return *Result != 0;
-
- case UNARMINUS:
- *Result = OverLoadMonadicTable[0][Right - 1];
- return *Result != 0;
- default:
- FatalError("OverLoadTypeCheck: undefined operator\n");
- }
- return FALSE; /* Makes warning silent. */
- }
-
- /*****************************************************************************
- * Routine to evaluate an monadic or diadic expression. It is assumed the *
- * two operands are valid for the given expression - a test which can be made *
- * using OverLoadTypeCheck routine (see above). returned pointer to node with *
- * the result, NULL in case of error (should not happen actually). *
- * Root holds the simple sub-expression (Root has the operator). PObj holds *
- * all the currently defined objects available in the system. IError & CError *
- * will be set to relevant error if was one. *
- *****************************************************************************/
- struct ParseTree *OverLoadEvalOper(ParseTree *Root, ParseTree *TempR,
- ParseTree *TempL, int *IError, char *CError)
- {
- int i;
- RealType R;
- struct ParseTree *Temp;
- struct ParseTree *RetVal = Root;
-
- switch(Root->NodeKind) { /* Dies if undefined operator. */
- case PLUS:
- case MINUS:
- case MULT:
- case DIV:
- case POWER:
- if (TempR == NULL || TempL == NULL) return NULL; /* Error! */
- break;
-
- case UNARMINUS:
- if (TempR == NULL) return NULL; /* Error! */
- break;
-
- default:
- FatalError("OverLoadEvalOper: Undefined operator\n");
- }
-
- if (Root -> NodeKind != UNARMINUS &&
- TempR -> ObjType > TempL -> ObjType) { /* Make TempL be bigger! */
- Temp = TempR;
- TempR = TempL;
- TempL = Temp;
- }
-
- switch(Root->NodeKind) {
- case PLUS:
- if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
- Root->ObjType = NUMERIC_OBJ;
- Root->U.R = TempL->U.R + TempR->U.R;
- }
- else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
- Root->ObjType = VECTOR_OBJ;
- Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
- PT_ADD(Root->U.PObj->U.Vec,
- TempL->U.PObj->U.Vec, TempR->U.PObj->U.Vec);
- }
- else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
- Root->ObjType = MATRIX_OBJ;
- Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
- MatAddTwo4by4(Root->U.PObj->U.Mat,
- TempL->U.PObj->U.Mat, TempR->U.PObj->U.Mat);
- }
- else if (IS_GEOM_NODE(TempR) && IS_GEOM_NODE(TempL)) {
- Root->ObjType = GEOMETRIC_OBJ;
- Root->U.PObj = BooleanOR(TempL -> U.PObj, TempR -> U.PObj);
- if (Root->U.PObj == NULL) {
- IPGlblEvalError = IE_ERR_BooleanErr;
- UpdateCharError("Operator ", PLUS);
- RetVal = NULL;
- }
- }
- else RetVal = NULL;
- break;
- case MINUS:
- if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
- Root->ObjType = NUMERIC_OBJ;
- Root->U.R = TempL->U.R - TempR->U.R;
- }
- else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
- Root->ObjType = VECTOR_OBJ;
- Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
- PT_SUB(Root->U.PObj->U.Vec,
- TempL->U.PObj->U.Vec, TempR->U.PObj->U.Vec);
- }
- else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
- Root->ObjType = MATRIX_OBJ;
- Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
- MatSubTwo4by4(Root->U.PObj->U.Mat,
- TempL->U.PObj->U.Mat, TempR->U.PObj->U.Mat);
- }
- else if (IS_GEOM_NODE(TempR) && IS_GEOM_NODE(TempL)) {
- Root->ObjType = GEOMETRIC_OBJ;
- Root->U.PObj = BooleanSUB(TempL -> U.PObj, TempR -> U.PObj);
- if (Root->U.PObj == NULL) {
- IPGlblEvalError = IE_ERR_BooleanErr;
- UpdateCharError("Operator ", MINUS);
- RetVal = NULL;
- }
- }
- else RetVal = NULL;
- break;
- case MULT:
- if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
- Root->ObjType = NUMERIC_OBJ;
- Root->U.R = TempL->U.R * TempR->U.R;
- }
- else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
- Root->ObjType = NUMERIC_OBJ;
- Root->U.R = DOT_PROD(TempL->U.PObj->U.Vec,
- TempR->U.PObj->U.Vec);
- }
- else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
- Root->ObjType = MATRIX_OBJ;
- Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
- MatMultTwo4by4(Root->U.PObj->U.Mat,
- TempL->U.PObj->U.Mat, TempR->U.PObj->U.Mat);
- }
- else if (IS_NUM_NODE(TempR) && IS_VEC_NODE(TempL)) {
- Root->ObjType = VECTOR_OBJ;
- Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
- PT_COPY(Root->U.PObj->U.Vec, TempL->U.PObj->U.Vec);
- PT_SCALE(Root->U.PObj->U.Vec, TempR->U.R);
- }
- else if (IS_NUM_NODE(TempR) && IS_MAT_NODE(TempL)) {
- Root->ObjType = MATRIX_OBJ;
- Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
- MatScale4by4(Root->U.PObj->U.Mat,
- TempL->U.PObj->U.Mat, &TempR->U.R);
- }
- else if (IS_GEOM_NODE(TempR) && IS_MAT_NODE(TempL)) {
- Root->ObjType = GEOMETRIC_OBJ;
- Root->U.PObj = CopyObject(NULL, TempR->U.PObj, FALSE);
- TransformObject(Root->U.PObj, TempL->U.PObj->U.Mat);
- }
- else if (IS_VEC_NODE(TempR) && IS_MAT_NODE(TempL)) {
- Root->ObjType = VECTOR_OBJ;
- Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
- MatMultVecby4by4(Root->U.PObj->U.Vec,
- TempR->U.PObj->U.Vec, TempL->U.PObj->U.Mat);
- }
- else if (IS_GEOM_NODE(TempR) && IS_GEOM_NODE(TempL)) {
- Root->ObjType = GEOMETRIC_OBJ;
- Root->U.PObj = BooleanAND(TempL -> U.PObj, TempR -> U.PObj);
- if (Root->U.PObj == NULL) {
- IPGlblEvalError = IE_ERR_BooleanErr;
- UpdateCharError("Operator ", MULT);
- RetVal = NULL;
- }
- }
- else RetVal = NULL;
- break;
- case DIV:
- if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) { /* Numeric div. */
- Root->ObjType = NUMERIC_OBJ;
- if (Root->Right->U.R != 0.0) {
- Root->U.R = TempL->U.R / TempR->U.R;
- }
- else {
- *IError = IE_ERR_DivByZero;
- strcpy(CError, "/");
- RetVal = NULL;
- }
- }
- else RetVal = NULL;
- break;
- case POWER:
- if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {/* Numeric power. */
- Root->ObjType = NUMERIC_OBJ;
- Root->U.R = pow(TempL->U.R, TempR->U.R);
- }
- else if (IS_NUM_NODE(TempR) && IS_MAT_NODE(TempL)) {
- i = (int) TempR->U.R; /* Power MUST be integer in this case. */
- if (!APX_EQ(i, TempR->U.R) || i < -1) {
- *IError = IE_ERR_MatPower;
- strcpy(CError, "^");
- RetVal = NULL;
- }
- Root->ObjType = MATRIX_OBJ;
- Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
- if (i == -1) { /* Generate the inverse matrix: */
- if (!MatInverseMatrix(TempL->U.PObj->U.Mat,
- Root->U.PObj->U.Mat)) {
- *IError = IE_ERR_MatPower;
- strcpy(CError, "^");
- RetVal = NULL;
- }
- }
- else { /* I must be positive integer. */
- MatGenUnitMat(Root->U.PObj->U.Mat);
- while (i--) MatMultTwo4by4(Root->U.PObj->U.Mat,
- Root->U.PObj->U.Mat,
- TempL->U.PObj->U.Mat);
- }
- }
- else RetVal = NULL;
- break;
- case UNARMINUS:
- if (IS_NUM_NODE(TempR)) {
- Root->ObjType = NUMERIC_OBJ;
- Root->U.R = -TempR->U.R;
- }
- else if (IS_VEC_NODE(TempR)) {
- Root->ObjType = VECTOR_OBJ;
- Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
- PT_COPY(Root->U.PObj->U.Vec, TempR->U.PObj->U.Vec);
- PT_SCALE(Root->U.PObj->U.Vec, -1.0);
- }
- else if (IS_MAT_NODE(TempR)) {
- Root->ObjType = MATRIX_OBJ;
- Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
- R = -1.0;
- MatScale4by4(Root->U.PObj->U.Mat, TempR->U.PObj->U.Mat, &R);
- }
- else if (IS_GEOM_NODE(TempR)) {
- Root->ObjType = GEOMETRIC_OBJ;
- Root->U.PObj = BooleanNEG(TempR -> U.PObj);
- }
- else RetVal = NULL;
- break;
- }
- if (RetVal == NULL && *IError == 0) { /* Put general error message: */
- *IError = IE_ERR_TypeMismatch;
- switch (Root->NodeKind) {
- case PLUS:
- strcpy(CError, "Operator +");
- break;
- case MINUS:
- strcpy(CError, "Operator -");
- break;
- case MULT:
- strcpy(CError, "Operator *");
- break;
- case DIV:
- strcpy(CError, "Operator /");
- break;
- case POWER:
- strcpy(CError, "Operator ^");
- break;
- case UNARMINUS:
- strcpy(CError, "Operator (unary) -");
- break;
- }
- }
-
- return RetVal;
- }
-