📄 arith.c
字号:
static arithgfc_arith_le (gfc_expr * op1, gfc_expr * op2, gfc_expr ** resultp){ gfc_expr *result; result = gfc_constant_result (BT_LOGICAL, gfc_default_logical_kind, &op1->where); result->value.logical = (gfc_compare_expr (op1, op2) <= 0); *resultp = result; return ARITH_OK;}static arithreduce_unary (arith (*eval) (gfc_expr *, gfc_expr **), gfc_expr * op, gfc_expr ** result){ gfc_constructor *c, *head; gfc_expr *r; arith rc; if (op->expr_type == EXPR_CONSTANT) return eval (op, result); rc = ARITH_OK; head = gfc_copy_constructor (op->value.constructor); for (c = head; c; c = c->next) { rc = eval (c->expr, &r); if (rc != ARITH_OK) break; gfc_replace_expr (c->expr, r); } if (rc != ARITH_OK) gfc_free_constructor (head); else { r = gfc_get_expr (); r->expr_type = EXPR_ARRAY; r->value.constructor = head; r->shape = gfc_copy_shape (op->shape, op->rank); r->ts = head->expr->ts; r->where = op->where; r->rank = op->rank; *result = r; } return rc;}static arithreduce_binary_ac (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **), gfc_expr * op1, gfc_expr * op2, gfc_expr ** result){ gfc_constructor *c, *head; gfc_expr *r; arith rc; head = gfc_copy_constructor (op1->value.constructor); rc = ARITH_OK; for (c = head; c; c = c->next) { rc = eval (c->expr, op2, &r); if (rc != ARITH_OK) break; gfc_replace_expr (c->expr, r); } if (rc != ARITH_OK) gfc_free_constructor (head); else { r = gfc_get_expr (); r->expr_type = EXPR_ARRAY; r->value.constructor = head; r->shape = gfc_copy_shape (op1->shape, op1->rank); r->ts = head->expr->ts; r->where = op1->where; r->rank = op1->rank; *result = r; } return rc;}static arithreduce_binary_ca (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **), gfc_expr * op1, gfc_expr * op2, gfc_expr ** result){ gfc_constructor *c, *head; gfc_expr *r; arith rc; head = gfc_copy_constructor (op2->value.constructor); rc = ARITH_OK; for (c = head; c; c = c->next) { rc = eval (op1, c->expr, &r); if (rc != ARITH_OK) break; gfc_replace_expr (c->expr, r); } if (rc != ARITH_OK) gfc_free_constructor (head); else { r = gfc_get_expr (); r->expr_type = EXPR_ARRAY; r->value.constructor = head; r->shape = gfc_copy_shape (op2->shape, op2->rank); r->ts = head->expr->ts; r->where = op2->where; r->rank = op2->rank; *result = r; } return rc;}static arithreduce_binary_aa (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **), gfc_expr * op1, gfc_expr * op2, gfc_expr ** result){ gfc_constructor *c, *d, *head; gfc_expr *r; arith rc; head = gfc_copy_constructor (op1->value.constructor); rc = ARITH_OK; d = op2->value.constructor; if (gfc_check_conformance ("Elemental binary operation", op1, op2) != SUCCESS) rc = ARITH_INCOMMENSURATE; else { for (c = head; c; c = c->next, d = d->next) { if (d == NULL) { rc = ARITH_INCOMMENSURATE; break; } rc = eval (c->expr, d->expr, &r); if (rc != ARITH_OK) break; gfc_replace_expr (c->expr, r); } if (d != NULL) rc = ARITH_INCOMMENSURATE; } if (rc != ARITH_OK) gfc_free_constructor (head); else { r = gfc_get_expr (); r->expr_type = EXPR_ARRAY; r->value.constructor = head; r->shape = gfc_copy_shape (op1->shape, op1->rank); r->ts = head->expr->ts; r->where = op1->where; r->rank = op1->rank; *result = r; } return rc;}static arithreduce_binary (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **), gfc_expr * op1, gfc_expr * op2, gfc_expr ** result){ if (op1->expr_type == EXPR_CONSTANT && op2->expr_type == EXPR_CONSTANT) return eval (op1, op2, result); if (op1->expr_type == EXPR_CONSTANT && op2->expr_type == EXPR_ARRAY) return reduce_binary_ca (eval, op1, op2, result); if (op1->expr_type == EXPR_ARRAY && op2->expr_type == EXPR_CONSTANT) return reduce_binary_ac (eval, op1, op2, result); return reduce_binary_aa (eval, op1, op2, result);}typedef union{ arith (*f2)(gfc_expr *, gfc_expr **); arith (*f3)(gfc_expr *, gfc_expr *, gfc_expr **);}eval_f;/* High level arithmetic subroutines. These subroutines go into eval_intrinsic(), which can do one of several things to its operands. If the operands are incompatible with the intrinsic operation, we return a node pointing to the operands and hope that an operator interface is found during resolution. If the operands are compatible and are constants, then we try doing the arithmetic. We also handle the cases where either or both operands are array constructors. */static gfc_expr *eval_intrinsic (gfc_intrinsic_op operator, eval_f eval, gfc_expr * op1, gfc_expr * op2){ gfc_expr temp, *result; int unary; arith rc; gfc_clear_ts (&temp.ts); switch (operator) { case INTRINSIC_NOT: /* Logical unary */ if (op1->ts.type != BT_LOGICAL) goto runtime; temp.ts.type = BT_LOGICAL; temp.ts.kind = gfc_default_logical_kind; unary = 1; break; /* Logical binary operators */ case INTRINSIC_OR: case INTRINSIC_AND: case INTRINSIC_NEQV: case INTRINSIC_EQV: if (op1->ts.type != BT_LOGICAL || op2->ts.type != BT_LOGICAL) goto runtime; temp.ts.type = BT_LOGICAL; temp.ts.kind = gfc_default_logical_kind; unary = 0; break; case INTRINSIC_UPLUS: case INTRINSIC_UMINUS: /* Numeric unary */ if (!gfc_numeric_ts (&op1->ts)) goto runtime; temp.ts = op1->ts; unary = 1; break; case INTRINSIC_PARENTHESES: temp.ts = op1->ts; unary = 1; break; case INTRINSIC_GE: case INTRINSIC_LT: /* Additional restrictions */ case INTRINSIC_LE: /* for ordering relations. */ case INTRINSIC_GT: if (op1->ts.type == BT_COMPLEX || op2->ts.type == BT_COMPLEX) { temp.ts.type = BT_LOGICAL; temp.ts.kind = gfc_default_logical_kind; goto runtime; } /* else fall through */ case INTRINSIC_EQ: case INTRINSIC_NE: if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER) { unary = 0; temp.ts.type = BT_LOGICAL; temp.ts.kind = gfc_default_logical_kind; break; } /* else fall through */ case INTRINSIC_PLUS: case INTRINSIC_MINUS: case INTRINSIC_TIMES: case INTRINSIC_DIVIDE: case INTRINSIC_POWER: /* Numeric binary */ if (!gfc_numeric_ts (&op1->ts) || !gfc_numeric_ts (&op2->ts)) goto runtime; /* Insert any necessary type conversions to make the operands compatible. */ temp.expr_type = EXPR_OP; gfc_clear_ts (&temp.ts); temp.value.op.operator = operator; temp.value.op.op1 = op1; temp.value.op.op2 = op2; gfc_type_convert_binary (&temp); if (operator == INTRINSIC_EQ || operator == INTRINSIC_NE || operator == INTRINSIC_GE || operator == INTRINSIC_GT || operator == INTRINSIC_LE || operator == INTRINSIC_LT) { temp.ts.type = BT_LOGICAL; temp.ts.kind = gfc_default_logical_kind; } unary = 0; break; case INTRINSIC_CONCAT: /* Character binary */ if (op1->ts.type != BT_CHARACTER || op2->ts.type != BT_CHARACTER) goto runtime; temp.ts.type = BT_CHARACTER; temp.ts.kind = gfc_default_character_kind; unary = 0; break; case INTRINSIC_USER: goto runtime; default: gfc_internal_error ("eval_intrinsic(): Bad operator"); } /* Try to combine the operators. */ if (operator == INTRINSIC_POWER && op2->ts.type != BT_INTEGER) goto runtime; if (op1->from_H || (op1->expr_type != EXPR_CONSTANT && (op1->expr_type != EXPR_ARRAY || !gfc_is_constant_expr (op1) || !gfc_expanded_ac (op1)))) goto runtime; if (op2 != NULL && (op2->from_H || (op2->expr_type != EXPR_CONSTANT && (op2->expr_type != EXPR_ARRAY || !gfc_is_constant_expr (op2) || !gfc_expanded_ac (op2))))) goto runtime; if (unary) rc = reduce_unary (eval.f2, op1, &result); else rc = reduce_binary (eval.f3, op1, op2, &result); if (rc != ARITH_OK) { /* Something went wrong */ gfc_error (gfc_arith_error (rc), &op1->where); return NULL; } gfc_free_expr (op1); gfc_free_expr (op2); return result;runtime: /* Create a run-time expression */ result = gfc_get_expr (); result->ts = temp.ts; result->expr_type = EXPR_OP; result->value.op.operator = operator; result->value.op.op1 = op1; result->value.op.op2 = op2; result->where = op1->where; return result;}/* Modify type of expression for zero size array. */static gfc_expr *eval_type_intrinsic0 (gfc_intrinsic_op operator, gfc_expr *op){ if (op == NULL) gfc_internal_error ("eval_type_intrinsic0(): op NULL"); switch (operator) { case INTRINSIC_GE: case INTRINSIC_LT: case INTRINSIC_LE: case INTRINSIC_GT: case INTRINSIC_EQ: case INTRINSIC_NE: op->ts.type = BT_LOGICAL; op->ts.kind = gfc_default_logical_kind; break; default: break; } return op;}/* Return nonzero if the expression is a zero size array. */static intgfc_zero_size_array (gfc_expr * e){ if (e->expr_type != EXPR_ARRAY) return 0; return e->value.constructor == NULL;}/* Reduce a binary expression where at least one of the operands involves a zero-length array. Returns NULL if neither of the operands is a zero-length array. */static gfc_expr *reduce_binary0 (gfc_expr * op1, gfc_expr * op2){ if (gfc_zero_size_array (op1)) { gfc_free_expr (op2); return op1; } if (gfc_zero_size_array (op2)) { gfc_free_expr (op1); return op2; } return NULL;}static gfc_expr *eval_intrinsic_f2 (gfc_intrinsic_op operator, arith (*eval) (gfc_expr *, gfc_expr **), gfc_expr * op1, gfc_expr * op2){ gfc_expr *result; eval_f f; if (op2 == NULL) { if (gfc_zero_size_array (op1)) return eval_type_intrinsic0 (operator, op1); } else { result = reduce_binary0 (op1, op2); if (result != NULL) return eval_type_intrinsic0 (operator, result); } f.f2 = eval; return eval_intrinsic (operator, f, op1, op2);}static gfc_expr *eval_intrinsic_f3 (gfc_intrinsic_op operator, arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **), gfc_expr * op1, gfc_expr * op2){ gfc_expr *result; eval_f f; result = reduce_binary0 (op1, op2); if (result != NULL) return eval_type_intrinsic0(operator, result); f.f3 = eval; return eval_intrinsic (operator, f, op1, op2);}gfc_expr *gfc_uplus (gfc_expr * op){ return eval_intrinsic_f2 (INTRINSIC_UPLUS, gfc_arith_uplus, op, NULL);}gfc_expr *gfc_uminus (gfc_expr * op){ return eval_intrinsic_f2 (INTRINSIC_UMINUS, gfc_arith_uminus, op, NULL);}gfc_expr *gfc_add (gfc_expr * op1, gfc_expr * op2){ return eval_intrinsic_f3 (INTRINSIC_PLUS, gfc_arith_plus, op1, op2);}gfc_expr *gfc_subtract (gfc_expr * op1, gfc_expr * op2){ return eval_intrinsic_f3 (INTRINSIC_MINUS, gfc_arith_minus, op1, op2);}gfc_expr *gfc_multiply (gfc_expr * op1, gfc_expr * op2){ return eval_intrinsic_f3 (INTRINSIC_TIMES, gfc_arith_times, op1, op2);}gfc_expr *gfc_divide (gfc_expr * op1, gfc_expr * op2){ return eval_intrinsic_f3 (INTRINSIC_DIVIDE, gfc_arith_divide, op1, op2);}gfc_expr *gfc_power (gfc_expr * op1, gfc_expr * op2){ return eval_intrinsic_f3 (INTRINSIC_POWER, gfc_arith_power, op1, op2);}gfc_expr *gfc_concat (gfc_expr * op1, gfc_expr * op2){ return eval_intrinsic_f3 (INTRINSIC_CONCAT, gfc_arith_concat, op1, op2);}gfc_expr *gfc_and (gfc_expr * op1, gfc_expr * op2){ return eval_intrinsic_f3 (INTRINSIC_AND, gfc_arith_and, op1, op2);}gfc_expr *gfc_or (gfc_expr * op1, gfc_expr * op2){ return eval_intrinsic_f3 (INTRINSIC_OR, gfc_arith_or, op1, op2);}gfc_expr *gfc_not (gfc_expr * op1){ return eval_intrinsic_f2 (INTRINSIC_NOT, gfc_arith_not, op1, NULL);}gfc_expr *gfc_eqv (gfc_expr * op1, gfc_expr * op2){ return eval_intrinsic_f3 (INTRINSIC_EQV, gfc_arith_eqv, op1, op2);}gfc_expr *gfc_neqv (gfc_expr * op1, gfc_expr * op2){ return eval_intrinsic_f3 (INTRINSIC_NEQV, gfc_arith_neqv, op1, op2);}gfc_expr *gfc_eq (gfc_expr * op1, gfc_expr * op2){ return eval_intrinsic_f3 (INTRINSIC_EQ, gfc_arith_eq, op1, op2);}gfc_expr *gfc_ne (gfc_expr * op1, gfc_expr * op2){ return eval_intrinsic_f3 (INTRINSIC_NE, gfc_arith_ne, op1, op2);}gfc_expr *gfc_gt (gfc_expr * op1, gfc_expr * op2){ return eval_intrinsic_f3 (INTRINSIC_GT, gfc_arith_gt, op1, op2);}gfc_expr *gfc_ge (gfc_expr * op1, gfc_expr * op2){ return eval_intrinsic_f3 (INTRINSIC_GE, gfc_arith_ge, op1, op2);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -