aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorTobias Burnus <burnus@gcc.gnu.org>2010-08-21 12:12:53 +0200
committerTobias Burnus <burnus@gcc.gnu.org>2010-08-21 12:12:53 +0200
commit47b996944dcb50a831c1332b8ea667ff6f95fa95 (patch)
treef963b78e966a67d516f6105c26a4b775d5c2dcfd /gcc
parent508e475706c3560a86b08446e1bb764773b93ed9 (diff)
downloadgcc-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')
-rw-r--r--gcc/fortran/ChangeLog22
-rw-r--r--gcc/fortran/gfortran.h2
-rw-r--r--gcc/fortran/intrinsic.c31
-rw-r--r--gcc/fortran/intrinsic.h1
-rw-r--r--gcc/fortran/iresolve.c43
-rw-r--r--gcc/fortran/simplify.c19
-rw-r--r--gcc/fortran/symbol.c1
-rw-r--r--gcc/fortran/trans-expr.c2
-rw-r--r--gcc/fortran/trans-intrinsic.c7
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gfortran.dg/bessel_6.f9045
-rw-r--r--gcc/testsuite/gfortran.dg/bessel_7.f9050
12 files changed, 219 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;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 423729b..1bdada5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+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.
+
2010-08-20 Jan Hubicka <jh@suse.cz>
PR c++/45307
diff --git a/gcc/testsuite/gfortran.dg/bessel_6.f90 b/gcc/testsuite/gfortran.dg/bessel_6.f90
new file mode 100644
index 0000000..1834d67
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bessel_6.f90
@@ -0,0 +1,45 @@
+! { dg-do run }
+!
+! PR fortran/36158
+! PR fortran/33197
+!
+! Run-time tests for transformations BESSEL_JN
+!
+implicit none
+real,parameter :: values(*) = [0.0, 0.5, 1.0, 0.9, 1.8,2.0,3.0,4.0,4.25,8.0,34.53, 475.78]
+real,parameter :: myeps(size(values)) = epsilon(0.0) &
+ * [2, 7, 5, 6, 9, 12, 12, 7, 7, 8, 75, 6 ]
+! The following is sufficient for me - the values above are a bit
+! more tolerant
+! * [0, 5, 3, 4, 6, 7, 7, 5, 5, 6, 66, 4 ]
+integer,parameter :: mymax(size(values)) = &
+ [100, 17, 23, 21, 27, 28, 32, 35, 36, 41, 49, 50 ]
+integer, parameter :: Nmax = 100
+real :: rec(0:Nmax), lib(0:Nmax)
+integer :: i
+
+do i = 1, ubound(values,dim=1)
+ call compare(mymax(i), values(i), myeps(i))
+end do
+
+contains
+
+subroutine compare(mymax, X, myeps)
+
+integer :: i, nit, mymax
+real X, myeps, myeps2
+
+rec(0:mymax) = BESSEL_JN(0, mymax, X)
+lib(0:mymax) = [ (BESSEL_JN(i, X), i=0,mymax) ]
+
+!print *, 'YN for X = ', X, ' -- Epsilon = ',epsilon(x)
+do i = 0, mymax
+! print '(i2,2e17.9,e12.2,f18.10,2l3)', i, rec(i), lib(i), &
+! rec(i)-lib(i), ((rec(i)-lib(i))/rec(i))/epsilon(x), &
+! rec(i) == lib(i) .or. abs((rec(i)-lib(i))/rec(i)) < myeps
+if (.not. (rec(i) == lib(i) .or. abs((rec(i)-lib(i))/rec(i)) < myeps)) &
+ call abort()
+end do
+
+end
+end
diff --git a/gcc/testsuite/gfortran.dg/bessel_7.f90 b/gcc/testsuite/gfortran.dg/bessel_7.f90
new file mode 100644
index 0000000..87b206c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bessel_7.f90
@@ -0,0 +1,50 @@
+! { dg-do run }
+!
+! PR fortran/36158
+! PR fortran/33197
+!
+! Run-time tests for transformations BESSEL_YN
+!
+implicit none
+real,parameter :: values(*) = [0.0, 0.5, 1.0, 0.9, 1.8,2.0,3.0,4.0,4.25,8.0,34.53, 475.78]
+real,parameter :: myeps(size(values)) = epsilon(0.0) &
+ * [2, 2, 2, 5, 5, 2, 12, 2, 4, 3, 30, 130 ]
+! The following is sufficient for me - the values above are a bit
+! more tolerant
+! * [0, 0, 0, 3, 3, 0, 9, 0, 2, 1, 22, 130 ]
+integer,parameter :: nit(size(values)) = &
+ [100, 100, 100, 100, 100, 100, 10, 100, 100, 100, 10, 25 ]
+integer, parameter :: Nmax = 100
+real :: rec(0:Nmax), lib(0:Nmax)
+integer :: i
+
+do i = 1, ubound(values,dim=1)
+ call compare(values(i), myeps(i), nit(i), 3*epsilon(0.0))
+end do
+
+contains
+
+subroutine compare(X, myeps, nit, myeps2)
+
+integer :: i, nit
+real X, myeps, myeps2
+
+rec = BESSEL_YN(0, Nmax, X)
+lib = [ (BESSEL_YN(i, X), i=0,Nmax) ]
+
+!print *, 'YN for X = ', X, ' -- Epsilon = ',epsilon(x)
+do i = 0, Nmax
+! print '(i2,2e17.9,e12.2,f14.10,2l3)', i, rec(i), lib(i), &
+! rec(i)-lib(i), ((rec(i)-lib(i))/rec(i))/epsilon(x), &
+! i > nit .or. rec(i) == lib(i) &
+! .or. abs((rec(i)-lib(i))/rec(i)) < myeps2, &
+! rec(i) == lib(i) .or. abs((rec(i)-lib(i))/rec(i)) < myeps
+if (.not. (i > nit .or. rec(i) == lib(i) &
+ .or. abs((rec(i)-lib(i))/rec(i)) < myeps2)) &
+ call abort ()
+if (.not. (rec(i) == lib(i) .or. abs((rec(i)-lib(i))/rec(i)) < myeps)) &
+ call abort ()
+end do
+
+end
+end