diff options
author | Tobias Burnus <burnus@gcc.gnu.org> | 2010-08-21 12:12:53 +0200 |
---|---|---|
committer | Tobias Burnus <burnus@gcc.gnu.org> | 2010-08-21 12:12:53 +0200 |
commit | 47b996944dcb50a831c1332b8ea667ff6f95fa95 (patch) | |
tree | f963b78e966a67d516f6105c26a4b775d5c2dcfd /gcc/fortran | |
parent | 508e475706c3560a86b08446e1bb764773b93ed9 (diff) | |
download | gcc-47b996944dcb50a831c1332b8ea667ff6f95fa95.zip gcc-47b996944dcb50a831c1332b8ea667ff6f95fa95.tar.gz gcc-47b996944dcb50a831c1332b8ea667ff6f95fa95.tar.bz2 |
re PR fortran/36158 (Transformational function BESSEL_YN(n1,n2,x) and BESSEL_JN missing)
2010-08-21 Tobias Burnus <burnus@net-b.de>
PR fortran/36158
PR fortran/33197
* intrinsic.c (add_sym): Init value attribute.
(set_attr_value): New function.
(add_functions) Use it and add JN/YN resolvers.
* symbol.c (gfc_copy_formal_args_intr): Copy value attr.
* intrinsic.h (gfc_resolve_bessel_n2): New prototype.
* gfortran.h (gfc_intrinsic_arg): Add value attribute.
* iresolve.c (gfc_resolve_bessel_n2): New function.
* trans-intrinsic.c (gfc_get_symbol_for_expr): Create
formal arg list.
(gfc_conv_intrinsic_function,gfc_is_intrinsic_libcall):
Add GFC_ISYM_JN2/GFC_ISYM_YN2 as case value.
* simplify.c (): For YN set to -INF if previous values
was -INF.
* trans-expr.c (gfc_conv_procedure_call): Don't crash
if sym->as is NULL.
* iresolve.c (gfc_resolve_extends_type_of): Set the
type of the dummy argument to the one of the actual.
2010-08-21 Tobias Burnus <burnus@net-b.de>
PR fortran/36158
PR fortran/33197
* m4/bessel.m4: Implement bessel_jn and bessel_yn.
* gfortran.map: Add the generated bessel_jn_r{4,8,10,16}
and bessel_yn_r{4,8,10,16}.
* Makefile.am: Add bessel.m4.
* Makefile.in: Regenerated.
* generated/bessel_r4.c: Generated.
* generated/bessel_r16.c: Generated.
* generated/bessel_r8.c: Generated.
* generated/bessel_r10.c: Generated.
2010-08-21 Tobias Burnus <burnus@net-b.de>
PR fortran/36158
PR fortran/33197
* gfortran.dg/bessel_6.f90: New.
* gfortran.dg/bessel_7.f90: New.
From-SVN: r163440
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/ChangeLog | 22 | ||||
-rw-r--r-- | gcc/fortran/gfortran.h | 2 | ||||
-rw-r--r-- | gcc/fortran/intrinsic.c | 31 | ||||
-rw-r--r-- | gcc/fortran/intrinsic.h | 1 | ||||
-rw-r--r-- | gcc/fortran/iresolve.c | 43 | ||||
-rw-r--r-- | gcc/fortran/simplify.c | 19 | ||||
-rw-r--r-- | gcc/fortran/symbol.c | 1 | ||||
-rw-r--r-- | gcc/fortran/trans-expr.c | 2 | ||||
-rw-r--r-- | gcc/fortran/trans-intrinsic.c | 7 |
9 files changed, 117 insertions, 11 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 943a5f2..111004d 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,25 @@ +2010-08-21 Tobias Burnus <burnus@net-b.de> + + PR fortran/36158 + PR fortran/33197 + * intrinsic.c (add_sym): Init value attribute. + (set_attr_value): New function. + (add_functions) Use it and add JN/YN resolvers. + * symbol.c (gfc_copy_formal_args_intr): Copy value attr. + * intrinsic.h (gfc_resolve_bessel_n2): New prototype. + * gfortran.h (gfc_intrinsic_arg): Add value attribute. + * iresolve.c (gfc_resolve_bessel_n2): New function. + * trans-intrinsic.c (gfc_get_symbol_for_expr): Create + formal arg list. + (gfc_conv_intrinsic_function,gfc_is_intrinsic_libcall): + Add GFC_ISYM_JN2/GFC_ISYM_YN2 as case value. + * simplify.c (): For YN set to -INF if previous values + was -INF. + * trans-expr.c (gfc_conv_procedure_call): Don't crash + if sym->as is NULL. + * iresolve.c (gfc_resolve_extends_type_of): Set the + type of the dummy argument to the one of the actual. + 2010-08-20 Joseph Myers <joseph@codesourcery.com> * lang.opt (MD, MMD): Use NoDriverArg instead of NoArgDriver. diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 5ca2488..9fb46d5 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -1540,7 +1540,7 @@ typedef struct gfc_intrinsic_arg char name[GFC_MAX_SYMBOL_LEN + 1]; gfc_typespec ts; - int optional; + unsigned optional:1, value:1; ENUM_BITFIELD (sym_intent) intent:2; gfc_actual_arglist *actual; diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c index 3751167..9087106 100644 --- a/gcc/fortran/intrinsic.c +++ b/gcc/fortran/intrinsic.c @@ -330,6 +330,7 @@ add_sym (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt type next_arg->ts.type = type; next_arg->ts.kind = kind; next_arg->optional = optional; + next_arg->value = 0; next_arg->intent = intent; } } @@ -1065,6 +1066,30 @@ make_noreturn (void) next_sym[-1].noreturn = 1; } +/* Set the attr.value of the current procedure. */ + +static void +set_attr_value (int n, ...) +{ + gfc_intrinsic_arg *arg; + va_list argp; + int i; + + if (sizing != SZ_NOTHING) + return; + + va_start (argp, n); + arg = next_sym[-1].formal; + + for (i = 0; i < n; i++) + { + gcc_assert (arg != NULL); + arg->value = va_arg (argp, int); + arg = arg->next; + } + va_end (argp); +} + /* Add intrinsic functions. */ @@ -1318,9 +1343,10 @@ add_functions (void) n, BT_INTEGER, di, REQUIRED, x, BT_REAL, dd, REQUIRED); add_sym_3 ("bessel_jn", GFC_ISYM_JN2, CLASS_TRANSFORMATIONAL, ACTUAL_NO, BT_REAL, dr, GFC_STD_F2008, - gfc_check_bessel_n2, gfc_simplify_bessel_jn2, NULL, + gfc_check_bessel_n2, gfc_simplify_bessel_jn2, gfc_resolve_bessel_n2, "n1", BT_INTEGER, di, REQUIRED,"n2", BT_INTEGER, di, REQUIRED, x, BT_REAL, dr, REQUIRED); + set_attr_value (3, true, true, true); make_generic ("bessel_jn", GFC_ISYM_JN, GFC_STD_F2008); @@ -1359,9 +1385,10 @@ add_functions (void) n, BT_INTEGER, di, REQUIRED, x, BT_REAL, dd, REQUIRED); add_sym_3 ("bessel_yn", GFC_ISYM_YN2, CLASS_TRANSFORMATIONAL, ACTUAL_NO, BT_REAL, dr, GFC_STD_F2008, - gfc_check_bessel_n2, gfc_simplify_bessel_yn2, NULL, + gfc_check_bessel_n2, gfc_simplify_bessel_yn2, gfc_resolve_bessel_n2, "n1", BT_INTEGER, di, REQUIRED,"n2", BT_INTEGER, di, REQUIRED, x, BT_REAL, dr, REQUIRED); + set_attr_value (3, true, true, true); make_generic ("bessel_yn", GFC_ISYM_YN, GFC_STD_F2008); diff --git a/gcc/fortran/intrinsic.h b/gcc/fortran/intrinsic.h index 7780ebc..5de0116 100644 --- a/gcc/fortran/intrinsic.h +++ b/gcc/fortran/intrinsic.h @@ -380,6 +380,7 @@ void gfc_resolve_atan (gfc_expr *, gfc_expr *); void gfc_resolve_atanh (gfc_expr *, gfc_expr *); void gfc_resolve_atan2 (gfc_expr *, gfc_expr *, gfc_expr *); void gfc_resolve_besn (gfc_expr *, gfc_expr *, gfc_expr *); +void gfc_resolve_bessel_n2 (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *a); void gfc_resolve_btest (gfc_expr *, gfc_expr *, gfc_expr *); void gfc_resolve_ceiling (gfc_expr *, gfc_expr *, gfc_expr *); void gfc_resolve_char (gfc_expr *, gfc_expr *, gfc_expr *); diff --git a/gcc/fortran/iresolve.c b/gcc/fortran/iresolve.c index 9bf767d..6565187 100644 --- a/gcc/fortran/iresolve.c +++ b/gcc/fortran/iresolve.c @@ -416,6 +416,45 @@ gfc_resolve_besn (gfc_expr *f, gfc_expr *n, gfc_expr *x) void +gfc_resolve_bessel_n2 (gfc_expr *f, gfc_expr *n1, gfc_expr *n2, gfc_expr *x) +{ + gfc_typespec ts; + gfc_clear_ts (&ts); + + f->ts = x->ts; + f->rank = 1; + if (n1->expr_type == EXPR_CONSTANT && n2->expr_type == EXPR_CONSTANT) + { + f->shape = gfc_get_shape (1); + mpz_init (f->shape[0]); + mpz_sub (f->shape[0], n2->value.integer, n1->value.integer); + mpz_add_ui (f->shape[0], f->shape[0], 1); + } + + if (n1->ts.kind != gfc_c_int_kind) + { + ts.type = BT_INTEGER; + ts.kind = gfc_c_int_kind; + gfc_convert_type (n1, &ts, 2); + } + + if (n2->ts.kind != gfc_c_int_kind) + { + ts.type = BT_INTEGER; + ts.kind = gfc_c_int_kind; + gfc_convert_type (n2, &ts, 2); + } + + if (f->value.function.isym->id == GFC_ISYM_JN2) + f->value.function.name = gfc_get_string (PREFIX ("bessel_jn_r%d"), + f->ts.kind); + else + f->value.function.name = gfc_get_string (PREFIX ("bessel_yn_r%d"), + f->ts.kind); +} + + +void gfc_resolve_btest (gfc_expr *f, gfc_expr *i, gfc_expr *pos) { f->ts.type = BT_LOGICAL; @@ -883,6 +922,10 @@ gfc_resolve_extends_type_of (gfc_expr *f, gfc_expr *a, gfc_expr *mo) f->ts.type = BT_LOGICAL; f->ts.kind = 4; + + f->value.function.isym->formal->ts = a->ts; + f->value.function.isym->formal->next->ts = mo->ts; + /* Call library function. */ f->value.function.name = gfc_get_string (PREFIX ("is_extension_of")); } diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c index 6c30707..4cb29fb 100644 --- a/gcc/fortran/simplify.c +++ b/gcc/fortran/simplify.c @@ -1210,11 +1210,7 @@ gfc_simplify_bessel_n2 (gfc_expr *order1, gfc_expr *order2, gfc_expr *x, if (x->expr_type != EXPR_CONSTANT || order1->expr_type != EXPR_CONSTANT || order2->expr_type != EXPR_CONSTANT) - { - gfc_error ("Sorry, non-constant transformational Bessel function at %L" - " not yet supported", &order2->where); - return &gfc_bad_expr; - } + return NULL; n1 = mpz_get_si (order1->value.integer); n2 = mpz_get_si (order2->value.integer); @@ -1253,7 +1249,7 @@ gfc_simplify_bessel_n2 (gfc_expr *order1, gfc_expr *order2, gfc_expr *x, if (jn) mpfr_set_ui (e->value.real, 0.0, GFC_RND_MODE); else - mpfr_set_inf (e->value.real, -1); + mpfr_set_inf (e->value.real, -1); gfc_constructor_append_expr (&result->value.constructor, e, &x->where); } @@ -1334,6 +1330,17 @@ gfc_simplify_bessel_n2 (gfc_expr *order1, gfc_expr *order2, gfc_expr *x, for (i = 2; i <= n2-n1; i++) { e = gfc_get_constant_expr (x->ts.type, x->ts.kind, &x->where); + + /* Special case: For YN, if the previous N gave -INF, set + also N+1 to -INF. */ + if (!jn && !gfc_option.flag_range_check && mpfr_inf_p (last2)) + { + mpfr_set_inf (e->value.real, -1); + gfc_constructor_append_expr (&result->value.constructor, e, + &x->where); + continue; + } + mpfr_mul_si (e->value.real, x2rev, jn ? (n2-i+1) : (n1+i-1), GFC_RND_MODE); mpfr_mul (e->value.real, e->value.real, last2, GFC_RND_MODE); diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c index 4d3db86..b4fc82c 100644 --- a/gcc/fortran/symbol.c +++ b/gcc/fortran/symbol.c @@ -4108,6 +4108,7 @@ gfc_copy_formal_args_intr (gfc_symbol *dest, gfc_intrinsic_sym *src) /* May need to copy more info for the symbol. */ formal_arg->sym->ts = curr_arg->ts; formal_arg->sym->attr.optional = curr_arg->optional; + formal_arg->sym->attr.value = curr_arg->value; formal_arg->sym->attr.intent = curr_arg->intent; formal_arg->sym->attr.flavor = FL_VARIABLE; formal_arg->sym->attr.dummy = 1; diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 63e6746..f7badd7 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -3015,7 +3015,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, bool f; f = (fsym != NULL) && !(fsym->attr.pointer || fsym->attr.allocatable) - && fsym->as->type != AS_ASSUMED_SHAPE; + && fsym->as && fsym->as->type != AS_ASSUMED_SHAPE; if (comp) f = f || !comp->attr.always_explicit; else diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index aa0db63..373770f 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -1562,7 +1562,8 @@ gfc_get_symbol_for_expr (gfc_expr * expr) sym->as->rank = expr->rank; } - /* TODO: proper argument lists for external intrinsics. */ + gfc_copy_formal_args_intr (sym, expr->value.function.isym); + return sym; } @@ -5389,6 +5390,7 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) case GFC_ISYM_IERRNO: case GFC_ISYM_IRAND: case GFC_ISYM_ISATTY: + case GFC_ISYM_JN2: case GFC_ISYM_LINK: case GFC_ISYM_LSTAT: case GFC_ISYM_MALLOC: @@ -5407,6 +5409,7 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) case GFC_ISYM_TIME8: case GFC_ISYM_UMASK: case GFC_ISYM_UNLINK: + case GFC_ISYM_YN2: gfc_conv_intrinsic_funcall (se, expr); break; @@ -5499,6 +5502,7 @@ gfc_is_intrinsic_libcall (gfc_expr * expr) case GFC_ISYM_ALL: case GFC_ISYM_ANY: case GFC_ISYM_COUNT: + case GFC_ISYM_JN2: case GFC_ISYM_MATMUL: case GFC_ISYM_MAXLOC: case GFC_ISYM_MAXVAL: @@ -5509,6 +5513,7 @@ gfc_is_intrinsic_libcall (gfc_expr * expr) case GFC_ISYM_SHAPE: case GFC_ISYM_SPREAD: case GFC_ISYM_TRANSPOSE: + case GFC_ISYM_YN2: /* Ignore absent optional parameters. */ return 1; |