📄 simplify.c
字号:
result = gfc_constant_result (BT_INTEGER, e->ts.kind, &e->where); mpz_set_ui (result->value.integer, gfc_integer_kinds[i].bit_size); return result;}gfc_expr *gfc_simplify_btest (gfc_expr * e, gfc_expr * bit){ int b; if (e->expr_type != EXPR_CONSTANT || bit->expr_type != EXPR_CONSTANT) return NULL; if (gfc_extract_int (bit, &b) != NULL || b < 0) return gfc_logical_expr (0, &e->where); return gfc_logical_expr (mpz_tstbit (e->value.integer, b), &e->where);}gfc_expr *gfc_simplify_ceiling (gfc_expr * e, gfc_expr * k){ gfc_expr *ceil, *result; int kind; kind = get_kind (BT_INTEGER, k, "CEILING", gfc_default_integer_kind); if (kind == -1) return &gfc_bad_expr; if (e->expr_type != EXPR_CONSTANT) return NULL; result = gfc_constant_result (BT_INTEGER, kind, &e->where); ceil = gfc_copy_expr (e); mpfr_ceil (ceil->value.real, e->value.real); gfc_mpfr_to_mpz(result->value.integer, ceil->value.real); gfc_free_expr (ceil); return range_check (result, "CEILING");}gfc_expr *gfc_simplify_char (gfc_expr * e, gfc_expr * k){ gfc_expr *result; int c, kind; kind = get_kind (BT_CHARACTER, k, "CHAR", gfc_default_character_kind); if (kind == -1) return &gfc_bad_expr; if (e->expr_type != EXPR_CONSTANT) return NULL; if (gfc_extract_int (e, &c) != NULL || c < 0 || c > UCHAR_MAX) { gfc_error ("Bad character in CHAR function at %L", &e->where); return &gfc_bad_expr; } result = gfc_constant_result (BT_CHARACTER, kind, &e->where); result->value.character.length = 1; result->value.character.string = gfc_getmem (2); result->value.character.string[0] = c; result->value.character.string[1] = '\0'; /* For debugger */ return result;}/* Common subroutine for simplifying CMPLX and DCMPLX. */static gfc_expr *simplify_cmplx (const char *name, gfc_expr * x, gfc_expr * y, int kind){ gfc_expr *result; result = gfc_constant_result (BT_COMPLEX, kind, &x->where); mpfr_set_ui (result->value.complex.i, 0, GFC_RND_MODE); switch (x->ts.type) { case BT_INTEGER: mpfr_set_z (result->value.complex.r, x->value.integer, GFC_RND_MODE); break; case BT_REAL: mpfr_set (result->value.complex.r, x->value.real, GFC_RND_MODE); break; case BT_COMPLEX: mpfr_set (result->value.complex.r, x->value.complex.r, GFC_RND_MODE); mpfr_set (result->value.complex.i, x->value.complex.i, GFC_RND_MODE); break; default: gfc_internal_error ("gfc_simplify_dcmplx(): Bad type (x)"); } if (y != NULL) { switch (y->ts.type) { case BT_INTEGER: mpfr_set_z (result->value.complex.i, y->value.integer, GFC_RND_MODE); break; case BT_REAL: mpfr_set (result->value.complex.i, y->value.real, GFC_RND_MODE); break; default: gfc_internal_error ("gfc_simplify_dcmplx(): Bad type (y)"); } } return range_check (result, name);}gfc_expr *gfc_simplify_cmplx (gfc_expr * x, gfc_expr * y, gfc_expr * k){ int kind; if (x->expr_type != EXPR_CONSTANT || (y != NULL && y->expr_type != EXPR_CONSTANT)) return NULL; kind = get_kind (BT_REAL, k, "CMPLX", gfc_default_real_kind); if (kind == -1) return &gfc_bad_expr; return simplify_cmplx ("CMPLX", x, y, kind);}gfc_expr *gfc_simplify_complex (gfc_expr * x, gfc_expr * y){ int kind; if (x->expr_type != EXPR_CONSTANT || (y != NULL && y->expr_type != EXPR_CONSTANT)) return NULL; if (x->ts.type == BT_INTEGER) { if (y->ts.type == BT_INTEGER) kind = gfc_default_real_kind; else kind = y->ts.kind; } else { if (y->ts.type == BT_REAL) kind = (x->ts.kind > y->ts.kind) ? x->ts.kind : y->ts.kind; else kind = x->ts.kind; } return simplify_cmplx ("COMPLEX", x, y, kind);}gfc_expr *gfc_simplify_conjg (gfc_expr * e){ gfc_expr *result; if (e->expr_type != EXPR_CONSTANT) return NULL; result = gfc_copy_expr (e); mpfr_neg (result->value.complex.i, result->value.complex.i, GFC_RND_MODE); return range_check (result, "CONJG");}gfc_expr *gfc_simplify_cos (gfc_expr * x){ gfc_expr *result; mpfr_t xp, xq; if (x->expr_type != EXPR_CONSTANT) return NULL; result = gfc_constant_result (x->ts.type, x->ts.kind, &x->where); switch (x->ts.type) { case BT_REAL: mpfr_cos (result->value.real, x->value.real, GFC_RND_MODE); break; case BT_COMPLEX: gfc_set_model_kind (x->ts.kind); mpfr_init (xp); mpfr_init (xq); mpfr_cos (xp, x->value.complex.r, GFC_RND_MODE); mpfr_cosh (xq, x->value.complex.i, GFC_RND_MODE); mpfr_mul(result->value.complex.r, xp, xq, GFC_RND_MODE); mpfr_sin (xp, x->value.complex.r, GFC_RND_MODE); mpfr_sinh (xq, x->value.complex.i, GFC_RND_MODE); mpfr_mul (xp, xp, xq, GFC_RND_MODE); mpfr_neg (result->value.complex.i, xp, GFC_RND_MODE ); mpfr_clear (xp); mpfr_clear (xq); break; default: gfc_internal_error ("in gfc_simplify_cos(): Bad type"); } return range_check (result, "COS");}gfc_expr *gfc_simplify_cosh (gfc_expr * x){ gfc_expr *result; if (x->expr_type != EXPR_CONSTANT) return NULL; result = gfc_constant_result (x->ts.type, x->ts.kind, &x->where); mpfr_cosh (result->value.real, x->value.real, GFC_RND_MODE); return range_check (result, "COSH");}gfc_expr *gfc_simplify_dcmplx (gfc_expr * x, gfc_expr * y){ if (x->expr_type != EXPR_CONSTANT || (y != NULL && y->expr_type != EXPR_CONSTANT)) return NULL; return simplify_cmplx ("DCMPLX", x, y, gfc_default_double_kind);}gfc_expr *gfc_simplify_dble (gfc_expr * e){ gfc_expr *result; if (e->expr_type != EXPR_CONSTANT) return NULL; switch (e->ts.type) { case BT_INTEGER: result = gfc_int2real (e, gfc_default_double_kind); break; case BT_REAL: result = gfc_real2real (e, gfc_default_double_kind); break; case BT_COMPLEX: result = gfc_complex2real (e, gfc_default_double_kind); break; default: gfc_internal_error ("gfc_simplify_dble(): bad type at %L", &e->where); } return range_check (result, "DBLE");}gfc_expr *gfc_simplify_digits (gfc_expr * x){ int i, digits; i = gfc_validate_kind (x->ts.type, x->ts.kind, false); switch (x->ts.type) { case BT_INTEGER: digits = gfc_integer_kinds[i].digits; break; case BT_REAL: case BT_COMPLEX: digits = gfc_real_kinds[i].digits; break; default: gcc_unreachable (); } return gfc_int_expr (digits);}gfc_expr *gfc_simplify_dim (gfc_expr * x, gfc_expr * y){ gfc_expr *result; int kind; if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT) return NULL; kind = x->ts.kind > y->ts.kind ? x->ts.kind : y->ts.kind; result = gfc_constant_result (x->ts.type, kind, &x->where); switch (x->ts.type) { case BT_INTEGER: if (mpz_cmp (x->value.integer, y->value.integer) > 0) mpz_sub (result->value.integer, x->value.integer, y->value.integer); else mpz_set_ui (result->value.integer, 0); break; case BT_REAL: if (mpfr_cmp (x->value.real, y->value.real) > 0) mpfr_sub (result->value.real, x->value.real, y->value.real, GFC_RND_MODE); else mpfr_set_ui (result->value.real, 0, GFC_RND_MODE); break; default: gfc_internal_error ("gfc_simplify_dim(): Bad type"); } return range_check (result, "DIM");}gfc_expr *gfc_simplify_dprod (gfc_expr * x, gfc_expr * y){ gfc_expr *a1, *a2, *result; if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT) return NULL; result = gfc_constant_result (BT_REAL, gfc_default_double_kind, &x->where); a1 = gfc_real2real (x, gfc_default_double_kind); a2 = gfc_real2real (y, gfc_default_double_kind); mpfr_mul (result->value.real, a1->value.real, a2->value.real, GFC_RND_MODE); gfc_free_expr (a1); gfc_free_expr (a2); return range_check (result, "DPROD");}gfc_expr *gfc_simplify_epsilon (gfc_expr * e){ gfc_expr *result; int i; i = gfc_validate_kind (e->ts.type, e->ts.kind, false); result = gfc_constant_result (BT_REAL, e->ts.kind, &e->where); mpfr_set (result->value.real, gfc_real_kinds[i].epsilon, GFC_RND_MODE); return range_check (result, "EPSILON");}gfc_expr *gfc_simplify_exp (gfc_expr * x){ gfc_expr *result; mpfr_t xp, xq; if (x->expr_type != EXPR_CONSTANT) return NULL; result = gfc_constant_result (x->ts.type, x->ts.kind, &x->where); switch (x->ts.type) { case BT_REAL: mpfr_exp(result->value.real, x->value.real, GFC_RND_MODE); break; case BT_COMPLEX: gfc_set_model_kind (x->ts.kind); mpfr_init (xp); mpfr_init (xq); mpfr_exp (xq, x->value.complex.r, GFC_RND_MODE); mpfr_cos (xp, x->value.complex.i, GFC_RND_MODE); mpfr_mul (result->value.complex.r, xq, xp, GFC_RND_MODE); mpfr_sin (xp, x->value.complex.i, GFC_RND_MODE); mpfr_mul (result->value.complex.i, xq, xp, GFC_RND_MODE); mpfr_clear (xp); mpfr_clear (xq); break; default: gfc_internal_error ("in gfc_simplify_exp(): Bad type"); } return range_check (result, "EXP");}/* FIXME: MPFR should be able to do this better */gfc_expr *gfc_simplify_exponent (gfc_expr * x){ int i; mpfr_t tmp; gfc_expr *result; if (x->expr_type != EXPR_CONSTANT) return NULL; result = gfc_constant_result (BT_INTEGER, gfc_default_integer_kind, &x->where); gfc_set_model (x->value.real); if (mpfr_sgn (x->value.real) == 0) { mpz_set_ui (result->value.integer, 0); return result; } mpfr_init (tmp); mpfr_abs (tmp, x->value.real, GFC_RND_MODE); mpfr_log2 (tmp, tmp, GFC_RND_MODE); gfc_mpfr_to_mpz (result->value.integer, tmp); /* The model number for tiny(x) is b**(emin - 1) where b is the base and emin is the smallest exponent value. So, we need to add 1 if x is tiny(x). */ i = gfc_validate_kind (x->ts.type, x->ts.kind, false); if (mpfr_cmp (x->value.real, gfc_real_kinds[i].tiny) == 0) mpz_add_ui (result->value.integer,result->value.integer, 1); mpfr_clear (tmp); return range_check (result, "EXPONENT");}gfc_expr *gfc_simplify_float (gfc_expr * a){ gfc_expr *result; if (a->expr_type != EXPR_CONSTANT) return NULL; result = gfc_int2real (a, gfc_default_real_kind); return range_check (result, "FLOAT");}gfc_expr *gfc_simplify_floor (gfc_expr * e, gfc_expr * k){ gfc_expr *result; mpfr_t floor; int kind; kind = get_kind (BT_INTEGER, k, "FLOOR", gfc_default_integer_kind); if (kind == -1) gfc_internal_error ("gfc_simplify_floor(): Bad kind"); if (e->expr_type != EXPR_CONSTANT) return NULL; result = gfc_constant_result (BT_INTEGER, kind, &e->where); gfc_set_model_kind (kind); mpfr_init (floor); mpfr_floor (floor, e->value.real); gfc_mpfr_to_mpz (result->value.integer, floor); mpfr_clear (floor); return range_check (result, "FLOOR");}gfc_expr *gfc_simplify_fraction (gfc_expr * x){ gfc_expr *result; mpfr_t absv, exp, pow2; if (x->expr_type != EXPR_CONSTANT) return NULL; result = gfc_constant_result (BT_REAL, x->ts.kind, &x->where); gfc_set_model_kind (x->ts.kind); if (mpfr_sgn (x->value.real) == 0) { mpfr_set_ui (result->value.real, 0, GFC_RND_MODE); return result; } mpfr_init (exp); mpfr_init (absv); mpfr_init (pow2); mpfr_abs (absv, x->value.real, GFC_RND_MODE); mpfr_log2 (exp, absv, GFC_RND_MODE); mpfr_trunc (exp, exp); mpfr_add_ui (exp, exp, 1, GFC_RND_MODE); mpfr_ui_pow (pow2, 2, exp, GFC_RND_MODE); mpfr_div (result->value.real, absv, pow2, GFC_RND_MODE); mpfr_clear (exp); mpfr_clear (absv); mpfr_clear (pow2); return range_check (result, "FRACTION");}gfc_expr *gfc_simplify_huge (gfc_expr * e){ gfc_expr *result; int i; i = gfc_validate_kind (e->ts.type, e->ts.kind, false); result = gfc_constant_result (e->ts.type, e->ts.kind, &e->where); switch (e->ts.type) { case BT_INTEGER: mpz_set (result->value.integer, gfc_integer_kinds[i].huge); break; case BT_REAL: mpfr_set (result->value.real, gfc_real_kinds[i].huge, GFC_RND_MODE); break; default: gcc_unreachable (); } return result;}gfc_expr *gfc_simplify_iachar (gfc_expr * e){ gfc_expr *result; int index; if (e->expr_type != EXPR_CONSTANT) return NULL; if (e->value.character.length != 1) { gfc_error ("Argument of IACHAR at %L must be of length one", &e->where); return &gfc_bad_expr; } index = xascii_table[(int) e->value.character.string[0] & 0xFF]; result = gfc_int_expr (index); result->where = e->where; return range_check (result, "IACHAR");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -