📄 simplify.c
字号:
int k = gfc_validate_kind (BT_REAL, x->ts.kind, 0); if (direction > 0) mpfr_add (result->value.real, x->value.real, gfc_real_kinds[k].subnormal, GFC_RND_MODE); else mpfr_sub (result->value.real, x->value.real, gfc_real_kinds[k].subnormal, GFC_RND_MODE); } else { if (sgn < 0) { direction = -direction; mpfr_neg (result->value.real, result->value.real, GFC_RND_MODE); } if (direction > 0) mpfr_add_one_ulp (result->value.real, GFC_RND_MODE); else { /* In this case the exponent can shrink, which makes us skip over one number because we subtract one ulp with the larger exponent. Thus we need to compensate for this. */ mpfr_init_set (tmp, result->value.real, GFC_RND_MODE); mpfr_sub_one_ulp (result->value.real, GFC_RND_MODE); mpfr_add_one_ulp (result->value.real, GFC_RND_MODE); /* If we're back to where we started, the spacing is one ulp, and we get the correct result by subtracting. */ if (mpfr_cmp (tmp, result->value.real) == 0) mpfr_sub_one_ulp (result->value.real, GFC_RND_MODE); mpfr_clear (tmp); } if (sgn < 0) mpfr_neg (result->value.real, result->value.real, GFC_RND_MODE); } return range_check (result, "NEAREST");}static gfc_expr *simplify_nint (const char *name, gfc_expr * e, gfc_expr * k){ gfc_expr *itrunc, *result; int kind; kind = get_kind (BT_INTEGER, k, name, 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); itrunc = gfc_copy_expr (e); mpfr_round(itrunc->value.real, e->value.real); gfc_mpfr_to_mpz (result->value.integer, itrunc->value.real); gfc_free_expr (itrunc); return range_check (result, name);}gfc_expr *gfc_simplify_nint (gfc_expr * e, gfc_expr * k){ return simplify_nint ("NINT", e, k);}gfc_expr *gfc_simplify_idnint (gfc_expr * e){ return simplify_nint ("IDNINT", e, NULL);}gfc_expr *gfc_simplify_not (gfc_expr * e){ gfc_expr *result; int i; if (e->expr_type != EXPR_CONSTANT) return NULL; result = gfc_constant_result (e->ts.type, e->ts.kind, &e->where); mpz_com (result->value.integer, e->value.integer); /* Because of how GMP handles numbers, the result must be ANDed with the max_int mask. For radices <> 2, this will require change. */ i = gfc_validate_kind (BT_INTEGER, e->ts.kind, false); mpz_and (result->value.integer, result->value.integer, gfc_integer_kinds[i].max_int); twos_complement (result->value.integer, gfc_integer_kinds[i].bit_size); return range_check (result, "NOT");}gfc_expr *gfc_simplify_null (gfc_expr * mold){ gfc_expr *result; if (mold == NULL) { result = gfc_get_expr (); result->ts.type = BT_UNKNOWN; } else result = gfc_copy_expr (mold); result->expr_type = EXPR_NULL; return result;}gfc_expr *gfc_simplify_or (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; if (x->ts.type == BT_INTEGER) { result = gfc_constant_result (BT_INTEGER, kind, &x->where); mpz_ior (result->value.integer, x->value.integer, y->value.integer); } else /* BT_LOGICAL */ { result = gfc_constant_result (BT_LOGICAL, kind, &x->where); result->value.logical = x->value.logical || y->value.logical; } return range_check (result, "OR");}gfc_expr *gfc_simplify_precision (gfc_expr * e){ gfc_expr *result; int i; i = gfc_validate_kind (e->ts.type, e->ts.kind, false); result = gfc_int_expr (gfc_real_kinds[i].precision); result->where = e->where; return result;}gfc_expr *gfc_simplify_radix (gfc_expr * e){ gfc_expr *result; int i; i = gfc_validate_kind (e->ts.type, e->ts.kind, false); switch (e->ts.type) { case BT_INTEGER: i = gfc_integer_kinds[i].radix; break; case BT_REAL: i = gfc_real_kinds[i].radix; break; default: gcc_unreachable (); } result = gfc_int_expr (i); result->where = e->where; return result;}gfc_expr *gfc_simplify_range (gfc_expr * e){ gfc_expr *result; int i; long j; i = gfc_validate_kind (e->ts.type, e->ts.kind, false); switch (e->ts.type) { case BT_INTEGER: j = gfc_integer_kinds[i].range; break; case BT_REAL: case BT_COMPLEX: j = gfc_real_kinds[i].range; break; default: gcc_unreachable (); } result = gfc_int_expr (j); result->where = e->where; return result;}gfc_expr *gfc_simplify_real (gfc_expr * e, gfc_expr * k){ gfc_expr *result; int kind; if (e->ts.type == BT_COMPLEX) kind = get_kind (BT_REAL, k, "REAL", e->ts.kind); else kind = get_kind (BT_REAL, k, "REAL", gfc_default_real_kind); if (kind == -1) return &gfc_bad_expr; if (e->expr_type != EXPR_CONSTANT) return NULL; switch (e->ts.type) { case BT_INTEGER: result = gfc_int2real (e, kind); break; case BT_REAL: result = gfc_real2real (e, kind); break; case BT_COMPLEX: result = gfc_complex2real (e, kind); break; default: gfc_internal_error ("bad type in REAL"); /* Not reached */ } return range_check (result, "REAL");}gfc_expr *gfc_simplify_realpart (gfc_expr * e){ gfc_expr *result; if (e->expr_type != EXPR_CONSTANT) return NULL; result = gfc_constant_result (BT_REAL, e->ts.kind, &e->where); mpfr_set (result->value.real, e->value.complex.r, GFC_RND_MODE); return range_check (result, "REALPART");}gfc_expr *gfc_simplify_repeat (gfc_expr * e, gfc_expr * n){ gfc_expr *result; int i, j, len, ncopies, nlen; if (e->expr_type != EXPR_CONSTANT || n->expr_type != EXPR_CONSTANT) return NULL; if (n != NULL && (gfc_extract_int (n, &ncopies) != NULL || ncopies < 0)) { gfc_error ("Invalid second argument of REPEAT at %L", &n->where); return &gfc_bad_expr; } len = e->value.character.length; nlen = ncopies * len; result = gfc_constant_result (BT_CHARACTER, e->ts.kind, &e->where); if (ncopies == 0) { result->value.character.string = gfc_getmem (1); result->value.character.length = 0; result->value.character.string[0] = '\0'; return result; } result->value.character.length = nlen; result->value.character.string = gfc_getmem (nlen + 1); for (i = 0; i < ncopies; i++) for (j = 0; j < len; j++) result->value.character.string[j + i * len] = e->value.character.string[j]; result->value.character.string[nlen] = '\0'; /* For debugger */ return result;}/* This one is a bear, but mainly has to do with shuffling elements. */gfc_expr *gfc_simplify_reshape (gfc_expr * source, gfc_expr * shape_exp, gfc_expr * pad, gfc_expr * order_exp){ int order[GFC_MAX_DIMENSIONS], shape[GFC_MAX_DIMENSIONS]; int i, rank, npad, x[GFC_MAX_DIMENSIONS]; gfc_constructor *head, *tail; mpz_t index, size; unsigned long j; size_t nsource; gfc_expr *e; /* Unpack the shape array. */ if (source->expr_type != EXPR_ARRAY || !gfc_is_constant_expr (source)) return NULL; if (shape_exp->expr_type != EXPR_ARRAY || !gfc_is_constant_expr (shape_exp)) return NULL; if (pad != NULL && (pad->expr_type != EXPR_ARRAY || !gfc_is_constant_expr (pad))) return NULL; if (order_exp != NULL && (order_exp->expr_type != EXPR_ARRAY || !gfc_is_constant_expr (order_exp))) return NULL; mpz_init (index); rank = 0; head = tail = NULL; for (;;) { e = gfc_get_array_element (shape_exp, rank); if (e == NULL) break; if (gfc_extract_int (e, &shape[rank]) != NULL) { gfc_error ("Integer too large in shape specification at %L", &e->where); gfc_free_expr (e); goto bad_reshape; } gfc_free_expr (e); if (rank >= GFC_MAX_DIMENSIONS) { gfc_error ("Too many dimensions in shape specification for RESHAPE " "at %L", &e->where); goto bad_reshape; } if (shape[rank] < 0) { gfc_error ("Shape specification at %L cannot be negative", &e->where); goto bad_reshape; } rank++; } if (rank == 0) { gfc_error ("Shape specification at %L cannot be the null array", &shape_exp->where); goto bad_reshape; } /* Now unpack the order array if present. */ if (order_exp == NULL) { for (i = 0; i < rank; i++) order[i] = i; } else { for (i = 0; i < rank; i++) x[i] = 0; for (i = 0; i < rank; i++) { e = gfc_get_array_element (order_exp, i); if (e == NULL) { gfc_error ("ORDER parameter of RESHAPE at %L is not the same size " "as SHAPE parameter", &order_exp->where); goto bad_reshape; } if (gfc_extract_int (e, &order[i]) != NULL) { gfc_error ("Error in ORDER parameter of RESHAPE at %L", &e->where); gfc_free_expr (e); goto bad_reshape; } gfc_free_expr (e); if (order[i] < 1 || order[i] > rank) { gfc_error ("ORDER parameter of RESHAPE at %L is out of range", &e->where); goto bad_reshape; } order[i]--; if (x[order[i]]) { gfc_error ("Invalid permutation in ORDER parameter at %L", &e->where); goto bad_reshape; } x[order[i]] = 1; } } /* Count the elements in the source and padding arrays. */ npad = 0; if (pad != NULL) { gfc_array_size (pad, &size); npad = mpz_get_ui (size); mpz_clear (size); } gfc_array_size (source, &size); nsource = mpz_get_ui (size); mpz_clear (size); /* If it weren't for that pesky permutation we could just loop through the source and round out any shortage with pad elements. But no, someone just had to have the compiler do something the user should be doing. */ for (i = 0; i < rank; i++) x[i] = 0; for (;;) { /* Figure out which element to extract. */ mpz_set_ui (index, 0); for (i = rank - 1; i >= 0; i--) { mpz_add_ui (index, index, x[order[i]]); if (i != 0) mpz_mul_ui (index, index, shape[order[i - 1]]); } if (mpz_cmp_ui (index, INT_MAX) > 0) gfc_internal_error ("Reshaped array too large at %L", &e->where); j = mpz_get_ui (index); if (j < nsource) e = gfc_get_array_element (source, j); else { j = j - nsource; if (npad == 0) { gfc_error ("PAD parameter required for short SOURCE parameter at %L", &source->where); goto bad_reshape; } j = j % npad; e = gfc_get_array_element (pad, j); } if (head == NULL) head = tail = gfc_get_constructor (); else { tail->next = gfc_get_constructor (); tail = tail->next; } if (e == NULL) goto bad_reshape; tail->where = e->where; tail->expr = e; /* Calculate the next element. */ i = 0;inc: if (++x[i] < shape[i]) continue; x[i++] = 0; if (i < rank) goto inc; break; } mpz_clear (index); e = gfc_get_expr (); e->where = source->where; e->expr_type = EXPR_ARRAY; e->value.constructor = head; e->shape = gfc_get_shape (rank); for (i = 0; i < rank; i++) mpz_init_set_ui (e->shape[i], shape[i]); e->ts = source->ts; e->rank = rank; return e;bad_reshape: gfc_free_constructor (head); mpz_clear (index); return &gfc_bad_expr;}gfc_expr *gfc_simplify_rrspacing (gfc_expr * x){ gfc_expr *result; mpfr_t absv, log2, exp, frac, pow2; int i, p; if (x->expr_type != EXPR_CONSTANT) return NULL; i = gfc_validate_kind (x->ts.type, x->ts.kind, false); result = gfc_constant_result (BT_REAL, x->ts.kind, &x->where); p = gfc_real_kinds[i].digits; gfc_set_model_kind (x->ts.kind); if (mpfr_sgn (x->value.real) == 0) { mpfr_ui_div (result->value.real, 1, gfc_real_kinds[i].tiny, GFC_RND_MODE); return result; } mpfr_init (log2); mpfr_init (absv); mpfr_init (frac); mpfr_init (pow2); mpfr_abs (absv, x->value.real, GFC_RND_MODE); mpfr_log2 (log2, absv, GFC_RND_MODE); mpfr_trunc (log2, log2); mpfr_add_ui (exp, log2, 1, GFC_RND_MODE); mpfr_ui_pow (pow2, 2, exp, GFC_RND_MODE); mpfr_div (frac, absv, pow2, GFC_RND_MODE); mpfr_mul_2exp (result->value.real, frac, (u
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -