📄 simplify.c
字号:
mpz_clrbit (result->value.integer, i + delta); else mpz_setbit (result->value.integer, i + delta); } for (i = ashift; i < isize; i++) { if (bits[i] == 0) mpz_clrbit (result->value.integer, i + shift); else mpz_setbit (result->value.integer, i + shift); } } twos_complement (result->value.integer, isize); gfc_free (bits); return result;}gfc_expr *gfc_simplify_kind (gfc_expr * e){ if (e->ts.type == BT_DERIVED) { gfc_error ("Argument of KIND at %L is a DERIVED type", &e->where); return &gfc_bad_expr; } return gfc_int_expr (e->ts.kind);}static gfc_expr *simplify_bound (gfc_expr * array, gfc_expr * dim, int upper){ gfc_ref *ref; gfc_array_spec *as; gfc_expr *e; int d; if (array->expr_type != EXPR_VARIABLE) return NULL; if (dim == NULL) /* TODO: Simplify constant multi-dimensional bounds. */ return NULL; if (dim->expr_type != EXPR_CONSTANT) return NULL; /* Follow any component references. */ as = array->symtree->n.sym->as; for (ref = array->ref; ref; ref = ref->next) { switch (ref->type) { case REF_ARRAY: switch (ref->u.ar.type) { case AR_ELEMENT: as = NULL; continue; case AR_FULL: /* We're done because 'as' has already been set in the previous iteration. */ goto done; case AR_SECTION: case AR_UNKNOWN: return NULL; } gcc_unreachable (); case REF_COMPONENT: as = ref->u.c.component->as; continue; case REF_SUBSTRING: continue; } } gcc_unreachable (); done: if (as->type == AS_DEFERRED || as->type == AS_ASSUMED_SHAPE) return NULL; d = mpz_get_si (dim->value.integer); if (d < 1 || d > as->rank || (d == as->rank && as->type == AS_ASSUMED_SIZE && upper)) { gfc_error ("DIM argument at %L is out of bounds", &dim->where); return &gfc_bad_expr; } e = upper ? as->upper[d-1] : as->lower[d-1]; if (e->expr_type != EXPR_CONSTANT) return NULL; return gfc_copy_expr (e);}gfc_expr *gfc_simplify_lbound (gfc_expr * array, gfc_expr * dim){ return simplify_bound (array, dim, 0);}gfc_expr *gfc_simplify_len (gfc_expr * e){ gfc_expr *result; if (e->expr_type != EXPR_CONSTANT) return NULL; result = gfc_constant_result (BT_INTEGER, gfc_default_integer_kind, &e->where); mpz_set_si (result->value.integer, e->value.character.length); return range_check (result, "LEN");}gfc_expr *gfc_simplify_len_trim (gfc_expr * e){ gfc_expr *result; int count, len, lentrim, i; if (e->expr_type != EXPR_CONSTANT) return NULL; result = gfc_constant_result (BT_INTEGER, gfc_default_integer_kind, &e->where); len = e->value.character.length; for (count = 0, i = 1; i <= len; i++) if (e->value.character.string[len - i] == ' ') count++; else break; lentrim = len - count; mpz_set_si (result->value.integer, lentrim); return range_check (result, "LEN_TRIM");}gfc_expr *gfc_simplify_lge (gfc_expr * a, gfc_expr * b){ if (a->expr_type != EXPR_CONSTANT || b->expr_type != EXPR_CONSTANT) return NULL; return gfc_logical_expr (gfc_compare_string (a, b, xascii_table) >= 0, &a->where);}gfc_expr *gfc_simplify_lgt (gfc_expr * a, gfc_expr * b){ if (a->expr_type != EXPR_CONSTANT || b->expr_type != EXPR_CONSTANT) return NULL; return gfc_logical_expr (gfc_compare_string (a, b, xascii_table) > 0, &a->where);}gfc_expr *gfc_simplify_lle (gfc_expr * a, gfc_expr * b){ if (a->expr_type != EXPR_CONSTANT || b->expr_type != EXPR_CONSTANT) return NULL; return gfc_logical_expr (gfc_compare_string (a, b, xascii_table) <= 0, &a->where);}gfc_expr *gfc_simplify_llt (gfc_expr * a, gfc_expr * b){ if (a->expr_type != EXPR_CONSTANT || b->expr_type != EXPR_CONSTANT) return NULL; return gfc_logical_expr (gfc_compare_string (a, b, xascii_table) < 0, &a->where);}gfc_expr *gfc_simplify_log (gfc_expr * x){ gfc_expr *result; mpfr_t xr, xi; if (x->expr_type != EXPR_CONSTANT) return NULL; result = gfc_constant_result (x->ts.type, x->ts.kind, &x->where); gfc_set_model_kind (x->ts.kind); switch (x->ts.type) { case BT_REAL: if (mpfr_sgn (x->value.real) <= 0) { gfc_error ("Argument of LOG at %L cannot be less than or equal to zero", &x->where); gfc_free_expr (result); return &gfc_bad_expr; } mpfr_log(result->value.real, x->value.real, GFC_RND_MODE); break; case BT_COMPLEX: if ((mpfr_sgn (x->value.complex.r) == 0) && (mpfr_sgn (x->value.complex.i) == 0)) { gfc_error ("Complex argument of LOG at %L cannot be zero", &x->where); gfc_free_expr (result); return &gfc_bad_expr; } mpfr_init (xr); mpfr_init (xi); arctangent2 (x->value.complex.i, x->value.complex.r, result->value.complex.i); mpfr_mul (xr, x->value.complex.r, x->value.complex.r, GFC_RND_MODE); mpfr_mul (xi, x->value.complex.i, x->value.complex.i, GFC_RND_MODE); mpfr_add (xr, xr, xi, GFC_RND_MODE); mpfr_sqrt (xr, xr, GFC_RND_MODE); mpfr_log (result->value.complex.r, xr, GFC_RND_MODE); mpfr_clear (xr); mpfr_clear (xi); break; default: gfc_internal_error ("gfc_simplify_log: bad type"); } return range_check (result, "LOG");}gfc_expr *gfc_simplify_log10 (gfc_expr * x){ gfc_expr *result; if (x->expr_type != EXPR_CONSTANT) return NULL; gfc_set_model_kind (x->ts.kind); if (mpfr_sgn (x->value.real) <= 0) { gfc_error ("Argument of LOG10 at %L cannot be less than or equal to zero", &x->where); return &gfc_bad_expr; } result = gfc_constant_result (x->ts.type, x->ts.kind, &x->where); mpfr_log10 (result->value.real, x->value.real, GFC_RND_MODE); return range_check (result, "LOG10");}gfc_expr *gfc_simplify_logical (gfc_expr * e, gfc_expr * k){ gfc_expr *result; int kind; kind = get_kind (BT_LOGICAL, k, "LOGICAL", gfc_default_logical_kind); if (kind < 0) return &gfc_bad_expr; if (e->expr_type != EXPR_CONSTANT) return NULL; result = gfc_constant_result (BT_LOGICAL, kind, &e->where); result->value.logical = e->value.logical; return result;}/* This function is special since MAX() can take any number of arguments. The simplified expression is a rewritten version of the argument list containing at most one constant element. Other constant elements are deleted. Because the argument list has already been checked, this function always succeeds. sign is 1 for MAX(), -1 for MIN(). */static gfc_expr *simplify_min_max (gfc_expr * expr, int sign){ gfc_actual_arglist *arg, *last, *extremum; gfc_intrinsic_sym * specific; last = NULL; extremum = NULL; specific = expr->value.function.isym; arg = expr->value.function.actual; for (; arg; last = arg, arg = arg->next) { if (arg->expr->expr_type != EXPR_CONSTANT) continue; if (extremum == NULL) { extremum = arg; continue; } switch (arg->expr->ts.type) { case BT_INTEGER: if (mpz_cmp (arg->expr->value.integer, extremum->expr->value.integer) * sign > 0) mpz_set (extremum->expr->value.integer, arg->expr->value.integer); break; case BT_REAL: if (mpfr_cmp (arg->expr->value.real, extremum->expr->value.real) * sign > 0) mpfr_set (extremum->expr->value.real, arg->expr->value.real, GFC_RND_MODE); break; default: gfc_internal_error ("gfc_simplify_max(): Bad type in arglist"); } /* Delete the extra constant argument. */ if (last == NULL) expr->value.function.actual = arg->next; else last->next = arg->next; arg->next = NULL; gfc_free_actual_arglist (arg); arg = last; } /* If there is one value left, replace the function call with the expression. */ if (expr->value.function.actual->next != NULL) return NULL; /* Convert to the correct type and kind. */ if (expr->ts.type != BT_UNKNOWN) return gfc_convert_constant (expr->value.function.actual->expr, expr->ts.type, expr->ts.kind); if (specific->ts.type != BT_UNKNOWN) return gfc_convert_constant (expr->value.function.actual->expr, specific->ts.type, specific->ts.kind); return gfc_copy_expr (expr->value.function.actual->expr);}gfc_expr *gfc_simplify_min (gfc_expr * e){ return simplify_min_max (e, -1);}gfc_expr *gfc_simplify_max (gfc_expr * e){ return simplify_min_max (e, 1);}gfc_expr *gfc_simplify_maxexponent (gfc_expr * x){ gfc_expr *result; int i; i = gfc_validate_kind (BT_REAL, x->ts.kind, false); result = gfc_int_expr (gfc_real_kinds[i].max_exponent); result->where = x->where; return result;}gfc_expr *gfc_simplify_minexponent (gfc_expr * x){ gfc_expr *result; int i; i = gfc_validate_kind (BT_REAL, x->ts.kind, false); result = gfc_int_expr (gfc_real_kinds[i].min_exponent); result->where = x->where; return result;}gfc_expr *gfc_simplify_mod (gfc_expr * a, gfc_expr * p){ gfc_expr *result; mpfr_t quot, iquot, term; int kind; if (a->expr_type != EXPR_CONSTANT || p->expr_type != EXPR_CONSTANT) return NULL; kind = a->ts.kind > p->ts.kind ? a->ts.kind : p->ts.kind; result = gfc_constant_result (a->ts.type, kind, &a->where); switch (a->ts.type) { case BT_INTEGER: if (mpz_cmp_ui (p->value.integer, 0) == 0) { /* Result is processor-dependent. */ gfc_error ("Second argument MOD at %L is zero", &a->where); gfc_free_expr (result); return &gfc_bad_expr; } mpz_tdiv_r (result->value.integer, a->value.integer, p->value.integer); break; case BT_REAL: if (mpfr_cmp_ui (p->value.real, 0) == 0) { /* Result is processor-dependent. */ gfc_error ("Second argument of MOD at %L is zero", &p->where); gfc_free_expr (result); return &gfc_bad_expr; } gfc_set_model_kind (kind); mpfr_init (quot); mpfr_init (iquot); mpfr_init (term); mpfr_div (quot, a->value.real, p->value.real, GFC_RND_MODE); mpfr_trunc (iquot, quot); mpfr_mul (term, iquot, p->value.real, GFC_RND_MODE); mpfr_sub (result->value.real, a->value.real, term, GFC_RND_MODE); mpfr_clear (quot); mpfr_clear (iquot); mpfr_clear (term); break; default: gfc_internal_error ("gfc_simplify_mod(): Bad arguments"); } return range_check (result, "MOD");}gfc_expr *gfc_simplify_modulo (gfc_expr * a, gfc_expr * p){ gfc_expr *result; mpfr_t quot, iquot, term; int kind; if (a->expr_type != EXPR_CONSTANT || p->expr_type != EXPR_CONSTANT) return NULL; kind = a->ts.kind > p->ts.kind ? a->ts.kind : p->ts.kind; result = gfc_constant_result (a->ts.type, kind, &a->where); switch (a->ts.type) { case BT_INTEGER: if (mpz_cmp_ui (p->value.integer, 0) == 0) { /* Result is processor-dependent. This processor just opts to not handle it at all. */ gfc_error ("Second argument of MODULO at %L is zero", &a->where); gfc_free_expr (result); return &gfc_bad_expr; } mpz_fdiv_r (result->value.integer, a->value.integer, p->value.integer); break; case BT_REAL: if (mpfr_cmp_ui (p->value.real, 0) == 0) { /* Result is processor-dependent. */ gfc_error ("Second argument of MODULO at %L is zero", &p->where); gfc_free_expr (result); return &gfc_bad_expr; } gfc_set_model_kind (kind); mpfr_init (quot); mpfr_init (iquot); mpfr_init (term); mpfr_div (quot, a->value.real, p->value.real, GFC_RND_MODE); mpfr_floor (iquot, quot); mpfr_mul (term, iquot, p->value.real, GFC_RND_MODE); mpfr_sub (result->value.real, a->value.real, term, GFC_RND_MODE); mpfr_clear (quot); mpfr_clear (iquot); mpfr_clear (term); break; default: gfc_internal_error ("gfc_simplify_modulo(): Bad arguments"); } return range_check (result, "MODULO");}/* Exists for the sole purpose of consistency with other intrinsics. */gfc_expr *gfc_simplify_mvbits (gfc_expr * f ATTRIBUTE_UNUSED, gfc_expr * fp ATTRIBUTE_UNUSED, gfc_expr * l ATTRIBUTE_UNUSED, gfc_expr * to ATTRIBUTE_UNUSED, gfc_expr * tp ATTRIBUTE_UNUSED){ return NULL;}gfc_expr *gfc_simplify_nearest (gfc_expr * x, gfc_expr * s){ gfc_expr *result; mpfr_t tmp; int direction, sgn; if (x->expr_type != EXPR_CONSTANT || s->expr_type != EXPR_CONSTANT) return NULL; gfc_set_model_kind (x->ts.kind); result = gfc_copy_expr (x); direction = mpfr_sgn (s->value.real); if (direction == 0) { gfc_error ("Second argument of NEAREST at %L may not be zero", &s->where); gfc_free (result); return &gfc_bad_expr; } /* TODO: Use mpfr_nextabove and mpfr_nextbelow once we move to a newer version of mpfr. */ sgn = mpfr_sgn (x->value.real); if (sgn == 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -