Patchwork [Fortran] PR 36158 - Run-time implementation of BESSEL_JN/YN

login
register
mail settings
Submitter Tobias Burnus
Date Aug. 20, 2010, 11:18 p.m.
Message ID <4C6F0D40.4060100@net-b.de>
Download mbox | patch
Permalink /patch/62329/
State New
Headers show

Comments

Tobias Burnus - Aug. 20, 2010, 11:18 p.m.
The attached patch implements the run-time version of BESSEL_JN/YN. At 
the same time it allows to mark arguments of intrinsic functions as 
(call by) VALUE. In order to get this working, I had to modify the 
trans-intrinsics.c to use the interface - and I had to fix the fall out 
ICEs.

Build and regtested on x86-64-linux.
OK for the trunk?

Tobias

PS: I wouldn't be too surprised if there are some ICEs lurking due to 
the intrinsics formal args change; on the other hand, together with PR 
43665 it might help with generating faster programs by telling the ME 
that a function does not clobber the arguments - the INTENT(IN) 
attribute is currently not used passed on to the ME.

PPS: When reviewing the patch, you can ignore the generated files (cf. 
changelog). I included them for convenience (mine but also for those 
which want to test the patch without building GCC in maintainer mode 
with the correct autoconf). I hope that's OK.
Daniel Kraft - Aug. 21, 2010, 9:48 a.m.
Hi Tobias,

Tobias Burnus wrote:
>  The attached patch implements the run-time version of BESSEL_JN/YN. At 
> the same time it allows to mark arguments of intrinsic functions as 
> (call by) VALUE. In order to get this working, I had to modify the 
> trans-intrinsics.c to use the interface - and I had to fix the fall out 
> ICEs.
> 
> Build and regtested on x86-64-linux.
> OK for the trunk?

Ok, considering the following points:

@@ -883,6 +922,10 @@ gfc_resolve_extends_type_of (gfc_expr *f

    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"));
  }

Has this something to do with your patch?  I don't really see what.

+          mpfr_set_inf (e->value.real, -1);
+	  gfc_constructor_append_expr (&result->value.constructor, e,

This looks like white-space tab vs spaces mismatch.

In the .m4 file:
+      GFC_DIMENSION_SET(ret->dim[0], 0,  size-1, 1);

One space too much before size-1.

+  if (unlikely (x == 0.0'Q`))
+    {
+      ret->data[0] = 1.0;
+      for (i = 1; i <= n2-n1; i++)
+        ret->data[i*stride] = 0.0'Q`;
+      return;
+    }

Maybe another 'Q` suffix for 1.0?

Thanks for the patch!  Yours,
Daniel
Tobias Burnus - Aug. 21, 2010, 10:28 a.m.
Am 21.08.2010 11:48, schrieb Daniel Kraft:
> Tobias Burnus wrote:
>>  The attached patch implements the run-time version of BESSEL_JN/YN. 
>> At the same time it allows to mark arguments of intrinsic functions 
>> as (call by) VALUE. In order to get this working, I had to modify the 
>> trans-intrinsics.c to use the interface - and I had to fix the fall 
>> out ICEs.
>>
>> Build and regtested on x86-64-linux.
>> OK for the trunk?
>
> Ok, considering the following points:
>
> +
> +  f->value.function.isym->formal->ts = a->ts;
> +  f->value.function.isym->formal->next->ts = mo->ts;
> +
>
> Has this something to do with your patch?  I don't really see what.

That's a fall out of adding support for the value attribute - or more 
explicitly: the consequence of adding gfc_copy_formal_args_intr in 
trans-intrinsic.c; that change caused an ICE (segfault) for many test 
cases and intrinsics such as RESHAPE, which I fixed by checking for 
fsym->as == NULL in gfc_conv_procedure_call (which should lead to the 
same cause as before fsym==NULL matched). Well, the other ICE was then 
for extends_type_of due to the BT_UNKNOWN. I fixed this by the snippet 
above.

Thanks for the review! I have incorporated all the suggested changes.

Committed as Rev. 163440.

Tobias
H.J. Lu - Aug. 21, 2010, 2:17 p.m.
On Sat, Aug 21, 2010 at 3:28 AM, Tobias Burnus <burnus@net-b.de> wrote:
>  Am 21.08.2010 11:48, schrieb Daniel Kraft:
>>
>> Tobias Burnus wrote:
>>>
>>>  The attached patch implements the run-time version of BESSEL_JN/YN. At
>>> the same time it allows to mark arguments of intrinsic functions as (call
>>> by) VALUE. In order to get this working, I had to modify the
>>> trans-intrinsics.c to use the interface - and I had to fix the fall out
>>> ICEs.
>>>
>>> Build and regtested on x86-64-linux.
>>> OK for the trunk?
>>
>> Ok, considering the following points:
>>
>> +
>> +  f->value.function.isym->formal->ts = a->ts;
>> +  f->value.function.isym->formal->next->ts = mo->ts;
>> +
>>
>> Has this something to do with your patch?  I don't really see what.
>
> That's a fall out of adding support for the value attribute - or more
> explicitly: the consequence of adding gfc_copy_formal_args_intr in
> trans-intrinsic.c; that change caused an ICE (segfault) for many test cases
> and intrinsics such as RESHAPE, which I fixed by checking for fsym->as ==
> NULL in gfc_conv_procedure_call (which should lead to the same cause as
> before fsym==NULL matched). Well, the other ICE was then for extends_type_of
> due to the BT_UNKNOWN. I fixed this by the snippet above.
>
> Thanks for the review! I have incorporated all the suggested changes.
>
> Committed as Rev. 163440.
>

Tests failed on Linux/ia32:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45367

Patch

2010-08-19  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-19  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-19  Tobias Burnus  <burnus@net-b.de>

        PR fortran/36158
        PR fortran/33197
	* gfortran.dg/bessel_6.f90: New.
	* gfortran.dg/bessel_7.f90: New.

Index: gcc/fortran/intrinsic.c
===================================================================
--- gcc/fortran/intrinsic.c	(Revision 163419)
+++ gcc/fortran/intrinsic.c	(Arbeitskopie)
@@ -330,6 +330,7 @@  add_sym (const char *name, gfc_isym_id i
 	  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);
 
Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c	(Revision 163419)
+++ gcc/fortran/trans-expr.c	(Arbeitskopie)
@@ -3015,7 +3015,7 @@  gfc_conv_procedure_call (gfc_se * se, gf
 	      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
Index: gcc/fortran/symbol.c
===================================================================
--- gcc/fortran/symbol.c	(Revision 163419)
+++ gcc/fortran/symbol.c	(Arbeitskopie)
@@ -4108,6 +4108,7 @@  gfc_copy_formal_args_intr (gfc_symbol *d
       /* 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;
Index: gcc/fortran/intrinsic.h
===================================================================
--- gcc/fortran/intrinsic.h	(Revision 163419)
+++ gcc/fortran/intrinsic.h	(Arbeitskopie)
@@ -380,6 +380,7 @@  void gfc_resolve_atan (gfc_expr *, gfc_e
 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 *);
Index: gcc/fortran/gfortran.h
===================================================================
--- gcc/fortran/gfortran.h	(Revision 163419)
+++ gcc/fortran/gfortran.h	(Arbeitskopie)
@@ -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;
 
Index: gcc/fortran/iresolve.c
===================================================================
--- gcc/fortran/iresolve.c	(Revision 163419)
+++ gcc/fortran/iresolve.c	(Arbeitskopie)
@@ -416,6 +416,45 @@  gfc_resolve_besn (gfc_expr *f, gfc_expr
 
 
 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
 
   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"));
 }
Index: gcc/fortran/trans-intrinsic.c
===================================================================
--- gcc/fortran/trans-intrinsic.c	(Revision 163419)
+++ gcc/fortran/trans-intrinsic.c	(Arbeitskopie)
@@ -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
     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
     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 * exp
     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 * exp
     case GFC_ISYM_SHAPE:
     case GFC_ISYM_SPREAD:
     case GFC_ISYM_TRANSPOSE:
+    case GFC_ISYM_YN2:
       /* Ignore absent optional parameters.  */
       return 1;
 
Index: gcc/fortran/simplify.c
===================================================================
--- gcc/fortran/simplify.c	(Revision 163419)
+++ gcc/fortran/simplify.c	(Arbeitskopie)
@@ -1210,11 +1210,7 @@  gfc_simplify_bessel_n2 (gfc_expr *order1
 
   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);
@@ -1334,6 +1330,17 @@  gfc_simplify_bessel_n2 (gfc_expr *order1
   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);
Index: libgfortran/m4/bessel.m4
===================================================================
--- libgfortran/m4/bessel.m4	(Revision 0)
+++ libgfortran/m4/bessel.m4	(Revision 0)
@@ -0,0 +1,185 @@ 
+`/* Implementation of the BESSEL_JN and BESSEL_YN transformational
+   function using a recurrence algorithm.
+   Copyright 2010 Free Software Foundation, Inc.
+   Contributed by Tobias Burnus <burnus@net-b.de>
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <assert.h>'
+
+include(iparm.m4)dnl
+include(`mtype.m4')dnl
+
+`#if defined (HAVE_'rtype_name`)
+
+
+
+#if defined (HAVE_JN'Q`)
+extern void bessel_jn_r'rtype_kind` ('rtype` * const restrict ret, int n1,
+				     int n2, 'rtype_name` x);
+export_proto(bessel_jn_r'rtype_kind`);
+
+void
+bessel_jn_r'rtype_kind` ('rtype` * const restrict ret, int n1, int n2, 'rtype_name` x)
+{
+  int i;
+  index_type stride;
+
+  'rtype_name` last1, last2, x2rev;
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (ret->data == NULL)
+    {
+      size_t size = n2 < n1 ? 0 : n2-n1+1; 
+      GFC_DIMENSION_SET(ret->dim[0], 0,  size-1, 1);
+      ret->data = internal_malloc_size (sizeof ('rtype_name`) * size);
+      ret->offset = 0;
+    }
+
+  if (unlikely (n2 < n1))
+    return;
+
+  if (unlikely (compile_options.bounds_check)
+      && GFC_DESCRIPTOR_EXTENT(ret,0) != (n2-n1+1))
+    runtime_error("Incorrect extent in return value of BESSEL_JN "
+		  "(%ld vs. %ld)", (long int) n2-n1,
+		  GFC_DESCRIPTOR_EXTENT(ret,0));
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (unlikely (x == 0.0'Q`))
+    {
+      ret->data[0] = 1.0;
+      for (i = 1; i <= n2-n1; i++)
+        ret->data[i*stride] = 0.0'Q`;
+      return;
+    }
+
+  ret->data = ret->data;
+  last1 = jn'q` (n2, x);
+  ret->data[(n2-n1)*stride] = last1;
+
+  if (n1 == n2)
+    return;
+
+  last2 = jn'q` (n2 - 1, x);
+  ret->data[(n2-n1-1)*stride] = last2;
+
+  if (n1 + 1 == n2)
+    return;
+
+  x2rev = 2.0'Q`/x;
+
+  for (i = n2-n1-2; i >= 0; i--)
+    {
+      ret->data[i*stride] = x2rev * (i+1+n1) * last2 - last1;
+      last1 = last2;
+      last2 = ret->data[i*stride];
+    }
+}
+
+#endif
+
+#if defined (HAVE_YN'Q`)
+extern void bessel_yn_r'rtype_kind` ('rtype` * const restrict ret,
+				     int n1, int n2, 'rtype_name` x);
+export_proto(bessel_yn_r'rtype_kind`);
+
+void
+bessel_yn_r'rtype_kind` ('rtype` * const restrict ret, int n1, int n2,
+			 'rtype_name` x)
+{
+  int i;
+  index_type stride;
+
+  'rtype_name` last1, last2, x2rev;
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (ret->data == NULL)
+    {
+      size_t size = n2 < n1 ? 0 : n2-n1+1; 
+      GFC_DIMENSION_SET(ret->dim[0], 0,  size-1, 1);
+      ret->data = internal_malloc_size (sizeof ('rtype_name`) * size);
+      ret->offset = 0;
+    }
+
+  if (unlikely (n2 < n1))
+    return;
+
+  if (unlikely (compile_options.bounds_check)
+      && GFC_DESCRIPTOR_EXTENT(ret,0) != (n2-n1+1))
+    runtime_error("Incorrect extent in return value of BESSEL_JN "
+		  "(%ld vs. %ld)", (long int) n2-n1,
+		  GFC_DESCRIPTOR_EXTENT(ret,0));
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (unlikely (x == 0.0'Q`))
+    {
+      for (i = 0; i <= n2-n1; i++)
+#if defined('rtype_name`_INFINITY)
+        ret->data[i*stride] = -'rtype_name`_INFINITY;
+#else
+        ret->data[i*stride] = -'rtype_name`_HUGE;
+#endif
+      return;
+    }
+
+  ret->data = ret->data;
+  last1 = yn'q` (n1, x);
+  ret->data[0] = last1;
+
+  if (n1 == n2)
+    return;
+
+  last2 = yn'q` (n1 + 1, x);
+  ret->data[1*stride] = last2;
+
+  if (n1 + 1 == n2)
+    return;
+
+  x2rev = 2.0'Q`/x;
+
+  for (i = 2; i <= n1+n2; i++)
+    {
+#if defined('rtype_name`_INFINITY)
+      if (unlikely (last2 == -'rtype_name`_INFINITY))
+	{
+	  ret->data[i*stride] = -'rtype_name`_INFINITY;
+	}
+      else
+#endif
+	{
+	  ret->data[i*stride] = x2rev * (i-1+n1) * last2 - last1;
+	  last1 = last2;
+	  last2 = ret->data[i*stride];
+	}
+    }
+}
+#endif
+
+#endif'
+
Index: libgfortran/Makefile.in
===================================================================
--- libgfortran/Makefile.in	(Revision 163393)
+++ libgfortran/Makefile.in	(Arbeitskopie)
@@ -143,40 +143,41 @@  am__objects_11 = product_i1.lo product_i
 am__objects_12 = sum_i1.lo sum_i2.lo sum_i4.lo sum_i8.lo sum_i16.lo \
 	sum_r4.lo sum_r8.lo sum_r10.lo sum_r16.lo sum_c4.lo sum_c8.lo \
 	sum_c10.lo sum_c16.lo
-am__objects_13 = matmul_i1.lo matmul_i2.lo matmul_i4.lo matmul_i8.lo \
+am__objects_13 = bessel_r4.lo bessel_r8.lo bessel_r10.lo bessel_r16.lo
+am__objects_14 = matmul_i1.lo matmul_i2.lo matmul_i4.lo matmul_i8.lo \
 	matmul_i16.lo matmul_r4.lo matmul_r8.lo matmul_r10.lo \
 	matmul_r16.lo matmul_c4.lo matmul_c8.lo matmul_c10.lo \
 	matmul_c16.lo
-am__objects_14 = matmul_l4.lo matmul_l8.lo matmul_l16.lo
-am__objects_15 = transpose_i4.lo transpose_i8.lo transpose_i16.lo \
+am__objects_15 = matmul_l4.lo matmul_l8.lo matmul_l16.lo
+am__objects_16 = transpose_i4.lo transpose_i8.lo transpose_i16.lo \
 	transpose_r4.lo transpose_r8.lo transpose_r10.lo \
 	transpose_r16.lo transpose_c4.lo transpose_c8.lo \
 	transpose_c10.lo transpose_c16.lo
-am__objects_16 = shape_i4.lo shape_i8.lo shape_i16.lo
-am__objects_17 = eoshift1_4.lo eoshift1_8.lo eoshift1_16.lo
-am__objects_18 = eoshift3_4.lo eoshift3_8.lo eoshift3_16.lo
-am__objects_19 = cshift1_4.lo cshift1_8.lo cshift1_16.lo
-am__objects_20 = reshape_i4.lo reshape_i8.lo reshape_i16.lo \
+am__objects_17 = shape_i4.lo shape_i8.lo shape_i16.lo
+am__objects_18 = eoshift1_4.lo eoshift1_8.lo eoshift1_16.lo
+am__objects_19 = eoshift3_4.lo eoshift3_8.lo eoshift3_16.lo
+am__objects_20 = cshift1_4.lo cshift1_8.lo cshift1_16.lo
+am__objects_21 = reshape_i4.lo reshape_i8.lo reshape_i16.lo \
 	reshape_r4.lo reshape_r8.lo reshape_r10.lo reshape_r16.lo \
 	reshape_c4.lo reshape_c8.lo reshape_c10.lo reshape_c16.lo
-am__objects_21 = in_pack_i1.lo in_pack_i2.lo in_pack_i4.lo \
+am__objects_22 = in_pack_i1.lo in_pack_i2.lo in_pack_i4.lo \
 	in_pack_i8.lo in_pack_i16.lo in_pack_r4.lo in_pack_r8.lo \
 	in_pack_r10.lo in_pack_r16.lo in_pack_c4.lo in_pack_c8.lo \
 	in_pack_c10.lo in_pack_c16.lo
-am__objects_22 = in_unpack_i1.lo in_unpack_i2.lo in_unpack_i4.lo \
+am__objects_23 = in_unpack_i1.lo in_unpack_i2.lo in_unpack_i4.lo \
 	in_unpack_i8.lo in_unpack_i16.lo in_unpack_r4.lo \
 	in_unpack_r8.lo in_unpack_r10.lo in_unpack_r16.lo \
 	in_unpack_c4.lo in_unpack_c8.lo in_unpack_c10.lo \
 	in_unpack_c16.lo
-am__objects_23 = exponent_r4.lo exponent_r8.lo exponent_r10.lo \
+am__objects_24 = exponent_r4.lo exponent_r8.lo exponent_r10.lo \
 	exponent_r16.lo
-am__objects_24 = fraction_r4.lo fraction_r8.lo fraction_r10.lo \
+am__objects_25 = fraction_r4.lo fraction_r8.lo fraction_r10.lo \
 	fraction_r16.lo
-am__objects_25 = nearest_r4.lo nearest_r8.lo nearest_r10.lo \
+am__objects_26 = nearest_r4.lo nearest_r8.lo nearest_r10.lo \
 	nearest_r16.lo
-am__objects_26 = set_exponent_r4.lo set_exponent_r8.lo \
+am__objects_27 = set_exponent_r4.lo set_exponent_r8.lo \
 	set_exponent_r10.lo set_exponent_r16.lo
-am__objects_27 = pow_i4_i4.lo pow_i8_i4.lo pow_i16_i4.lo pow_c4_i4.lo \
+am__objects_28 = pow_i4_i4.lo pow_i8_i4.lo pow_i16_i4.lo pow_c4_i4.lo \
 	pow_c8_i4.lo pow_c10_i4.lo pow_c16_i4.lo pow_i4_i8.lo \
 	pow_i8_i8.lo pow_i16_i8.lo pow_r4_i8.lo pow_r8_i8.lo \
 	pow_r10_i8.lo pow_r16_i8.lo pow_c4_i8.lo pow_c8_i8.lo \
@@ -184,26 +185,26 @@  am__objects_27 = pow_i4_i4.lo pow_i8_i4.
 	pow_i16_i16.lo pow_r4_i16.lo pow_r8_i16.lo pow_r10_i16.lo \
 	pow_r16_i16.lo pow_c4_i16.lo pow_c8_i16.lo pow_c10_i16.lo \
 	pow_c16_i16.lo
-am__objects_28 = rrspacing_r4.lo rrspacing_r8.lo rrspacing_r10.lo \
+am__objects_29 = rrspacing_r4.lo rrspacing_r8.lo rrspacing_r10.lo \
 	rrspacing_r16.lo
-am__objects_29 = spacing_r4.lo spacing_r8.lo spacing_r10.lo \
+am__objects_30 = spacing_r4.lo spacing_r8.lo spacing_r10.lo \
 	spacing_r16.lo
-am__objects_30 = pack_i1.lo pack_i2.lo pack_i4.lo pack_i8.lo \
+am__objects_31 = pack_i1.lo pack_i2.lo pack_i4.lo pack_i8.lo \
 	pack_i16.lo pack_r4.lo pack_r8.lo pack_r10.lo pack_r16.lo \
 	pack_c4.lo pack_c8.lo pack_c10.lo pack_c16.lo
-am__objects_31 = unpack_i1.lo unpack_i2.lo unpack_i4.lo unpack_i8.lo \
+am__objects_32 = unpack_i1.lo unpack_i2.lo unpack_i4.lo unpack_i8.lo \
 	unpack_i16.lo unpack_r4.lo unpack_r8.lo unpack_r10.lo \
 	unpack_r16.lo unpack_c4.lo unpack_c8.lo unpack_c10.lo \
 	unpack_c16.lo
-am__objects_32 = spread_i1.lo spread_i2.lo spread_i4.lo spread_i8.lo \
+am__objects_33 = spread_i1.lo spread_i2.lo spread_i4.lo spread_i8.lo \
 	spread_i16.lo spread_r4.lo spread_r8.lo spread_r10.lo \
 	spread_r16.lo spread_c4.lo spread_c8.lo spread_c10.lo \
 	spread_c16.lo
-am__objects_33 = cshift0_i1.lo cshift0_i2.lo cshift0_i4.lo \
+am__objects_34 = cshift0_i1.lo cshift0_i2.lo cshift0_i4.lo \
 	cshift0_i8.lo cshift0_i16.lo cshift0_r4.lo cshift0_r8.lo \
 	cshift0_r10.lo cshift0_r16.lo cshift0_c4.lo cshift0_c8.lo \
 	cshift0_c10.lo cshift0_c16.lo
-am__objects_34 = $(am__objects_2) $(am__objects_3) $(am__objects_4) \
+am__objects_35 = $(am__objects_2) $(am__objects_3) $(am__objects_4) \
 	$(am__objects_5) $(am__objects_6) $(am__objects_7) \
 	$(am__objects_8) $(am__objects_9) $(am__objects_10) \
 	$(am__objects_11) $(am__objects_12) $(am__objects_13) \
@@ -213,11 +214,11 @@  am__objects_34 = $(am__objects_2) $(am__
 	$(am__objects_23) $(am__objects_24) $(am__objects_25) \
 	$(am__objects_26) $(am__objects_27) $(am__objects_28) \
 	$(am__objects_29) $(am__objects_30) $(am__objects_31) \
-	$(am__objects_32) $(am__objects_33)
-am__objects_35 = close.lo file_pos.lo format.lo inquire.lo \
+	$(am__objects_32) $(am__objects_33) $(am__objects_34)
+am__objects_36 = close.lo file_pos.lo format.lo inquire.lo \
 	intrinsics.lo list_read.lo lock.lo open.lo read.lo \
 	size_from_kind.lo transfer.lo unit.lo unix.lo write.lo fbuf.lo
-am__objects_36 = associated.lo abort.lo access.lo args.lo \
+am__objects_37 = associated.lo abort.lo access.lo args.lo \
 	bit_intrinsics.lo c99_functions.lo chdir.lo chmod.lo clock.lo \
 	cpu_time.lo cshift0.lo ctime.lo date_and_time.lo dtime.lo \
 	env.lo eoshift0.lo eoshift2.lo erfc_scaled.lo etime.lo exit.lo \
@@ -232,8 +233,8 @@  am__objects_36 = associated.lo abort.lo
 	system_clock.lo time.lo transpose_generic.lo umask.lo \
 	unlink.lo unpack_generic.lo in_pack_generic.lo \
 	in_unpack_generic.lo
-am__objects_37 =
-am__objects_38 = _abs_c4.lo _abs_c8.lo _abs_c10.lo _abs_c16.lo \
+am__objects_38 =
+am__objects_39 = _abs_c4.lo _abs_c8.lo _abs_c10.lo _abs_c16.lo \
 	_abs_i4.lo _abs_i8.lo _abs_i16.lo _abs_r4.lo _abs_r8.lo \
 	_abs_r10.lo _abs_r16.lo _aimag_c4.lo _aimag_c8.lo \
 	_aimag_c10.lo _aimag_c16.lo _exp_r4.lo _exp_r8.lo _exp_r10.lo \
@@ -257,18 +258,18 @@  am__objects_38 = _abs_c4.lo _abs_c8.lo _
 	_conjg_c4.lo _conjg_c8.lo _conjg_c10.lo _conjg_c16.lo \
 	_aint_r4.lo _aint_r8.lo _aint_r10.lo _aint_r16.lo _anint_r4.lo \
 	_anint_r8.lo _anint_r10.lo _anint_r16.lo
-am__objects_39 = _sign_i4.lo _sign_i8.lo _sign_i16.lo _sign_r4.lo \
+am__objects_40 = _sign_i4.lo _sign_i8.lo _sign_i16.lo _sign_r4.lo \
 	_sign_r8.lo _sign_r10.lo _sign_r16.lo _dim_i4.lo _dim_i8.lo \
 	_dim_i16.lo _dim_r4.lo _dim_r8.lo _dim_r10.lo _dim_r16.lo \
 	_atan2_r4.lo _atan2_r8.lo _atan2_r10.lo _atan2_r16.lo \
 	_mod_i4.lo _mod_i8.lo _mod_i16.lo _mod_r4.lo _mod_r8.lo \
 	_mod_r10.lo _mod_r16.lo
-am__objects_40 = misc_specifics.lo
-am__objects_41 = $(am__objects_38) $(am__objects_39) $(am__objects_40) \
+am__objects_41 = misc_specifics.lo
+am__objects_42 = $(am__objects_39) $(am__objects_40) $(am__objects_41) \
 	dprod_r8.lo f2c_specifics.lo
-am__objects_42 = $(am__objects_1) $(am__objects_34) $(am__objects_35) \
-	$(am__objects_36) $(am__objects_37) $(am__objects_41)
-@onestep_FALSE@am_libgfortran_la_OBJECTS = $(am__objects_42)
+am__objects_43 = $(am__objects_1) $(am__objects_35) $(am__objects_36) \
+	$(am__objects_37) $(am__objects_38) $(am__objects_42)
+@onestep_FALSE@am_libgfortran_la_OBJECTS = $(am__objects_43)
 @onestep_TRUE@am_libgfortran_la_OBJECTS = libgfortran_c.lo
 libgfortran_la_OBJECTS = $(am_libgfortran_la_OBJECTS)
 libgfortranbegin_la_LIBADD =
@@ -590,6 +591,12 @@  $(srcdir)/generated/any_l4.c \
 $(srcdir)/generated/any_l8.c \
 $(srcdir)/generated/any_l16.c
 
+i_bessel_c = \
+$(srcdir)/generated/bessel_r4.c \
+$(srcdir)/generated/bessel_r8.c \
+$(srcdir)/generated/bessel_r10.c \
+$(srcdir)/generated/bessel_r16.c
+
 i_count_c = \
 $(srcdir)/generated/count_1_l.c \
 $(srcdir)/generated/count_2_l.c \
@@ -997,11 +1004,11 @@  m4_files = m4/iparm.m4 m4/ifunction.m4 m
     m4/transpose.m4 m4/eoshift1.m4 m4/eoshift3.m4 m4/exponent.m4 \
     m4/fraction.m4 m4/nearest.m4 m4/set_exponent.m4 m4/pow.m4 \
     m4/misc_specifics.m4 m4/rrspacing.m4 m4/spacing.m4 m4/pack.m4 \
-    m4/unpack.m4 m4/spread.m4
+    m4/unpack.m4 m4/spread.m4 m4/bessel.m4
 
 gfor_built_src = $(i_all_c) $(i_any_c) $(i_count_c) $(i_maxloc0_c) \
     $(i_maxloc1_c) $(i_maxval_c) $(i_minloc0_c) $(i_minloc1_c) $(i_minval_c) \
-    $(i_product_c) $(i_sum_c) \
+    $(i_product_c) $(i_sum_c) $(i_bessel_c) \
     $(i_matmul_c) $(i_matmull_c) $(i_transpose_c) $(i_shape_c) $(i_eoshift1_c) \
     $(i_eoshift3_c) $(i_cshift1_c) $(i_reshape_c) $(in_pack_c) $(in_unpack_c) \
     $(i_exponent_c) $(i_fraction_c) $(i_nearest_c) $(i_set_exponent_c) \
@@ -1328,6 +1335,10 @@  distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/args.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/associated.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backtrace.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bessel_r10.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bessel_r16.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bessel_r4.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bessel_r8.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bit_intrinsics.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bounds.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/c99_functions.Plo@am__quote@
@@ -3456,6 +3467,34 @@  sum_c16.lo: $(srcdir)/generated/sum_c16.
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sum_c16.lo `test -f '$(srcdir)/generated/sum_c16.c' || echo '$(srcdir)/'`$(srcdir)/generated/sum_c16.c
 
+bessel_r4.lo: $(srcdir)/generated/bessel_r4.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bessel_r4.lo -MD -MP -MF $(DEPDIR)/bessel_r4.Tpo -c -o bessel_r4.lo `test -f '$(srcdir)/generated/bessel_r4.c' || echo '$(srcdir)/'`$(srcdir)/generated/bessel_r4.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/bessel_r4.Tpo $(DEPDIR)/bessel_r4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$(srcdir)/generated/bessel_r4.c' object='bessel_r4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bessel_r4.lo `test -f '$(srcdir)/generated/bessel_r4.c' || echo '$(srcdir)/'`$(srcdir)/generated/bessel_r4.c
+
+bessel_r8.lo: $(srcdir)/generated/bessel_r8.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bessel_r8.lo -MD -MP -MF $(DEPDIR)/bessel_r8.Tpo -c -o bessel_r8.lo `test -f '$(srcdir)/generated/bessel_r8.c' || echo '$(srcdir)/'`$(srcdir)/generated/bessel_r8.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/bessel_r8.Tpo $(DEPDIR)/bessel_r8.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$(srcdir)/generated/bessel_r8.c' object='bessel_r8.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bessel_r8.lo `test -f '$(srcdir)/generated/bessel_r8.c' || echo '$(srcdir)/'`$(srcdir)/generated/bessel_r8.c
+
+bessel_r10.lo: $(srcdir)/generated/bessel_r10.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bessel_r10.lo -MD -MP -MF $(DEPDIR)/bessel_r10.Tpo -c -o bessel_r10.lo `test -f '$(srcdir)/generated/bessel_r10.c' || echo '$(srcdir)/'`$(srcdir)/generated/bessel_r10.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/bessel_r10.Tpo $(DEPDIR)/bessel_r10.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$(srcdir)/generated/bessel_r10.c' object='bessel_r10.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bessel_r10.lo `test -f '$(srcdir)/generated/bessel_r10.c' || echo '$(srcdir)/'`$(srcdir)/generated/bessel_r10.c
+
+bessel_r16.lo: $(srcdir)/generated/bessel_r16.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bessel_r16.lo -MD -MP -MF $(DEPDIR)/bessel_r16.Tpo -c -o bessel_r16.lo `test -f '$(srcdir)/generated/bessel_r16.c' || echo '$(srcdir)/'`$(srcdir)/generated/bessel_r16.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/bessel_r16.Tpo $(DEPDIR)/bessel_r16.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$(srcdir)/generated/bessel_r16.c' object='bessel_r16.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bessel_r16.lo `test -f '$(srcdir)/generated/bessel_r16.c' || echo '$(srcdir)/'`$(srcdir)/generated/bessel_r16.c
+
 matmul_i1.lo: $(srcdir)/generated/matmul_i1.c
 @am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT matmul_i1.lo -MD -MP -MF $(DEPDIR)/matmul_i1.Tpo -c -o matmul_i1.lo `test -f '$(srcdir)/generated/matmul_i1.c' || echo '$(srcdir)/'`$(srcdir)/generated/matmul_i1.c
 @am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/matmul_i1.Tpo $(DEPDIR)/matmul_i1.Plo
@@ -5525,6 +5564,9 @@  fpu-target.h: $(srcdir)/$(FPU_HOST_HEADE
 @MAINTAINER_MODE_TRUE@$(i_all_c): m4/all.m4 $(I_M4_DEPS2)
 @MAINTAINER_MODE_TRUE@	$(M4) -Dfile=$@ -I$(srcdir)/m4 all.m4 > $@
 
+@MAINTAINER_MODE_TRUE@$(i_bessel_c): m4/bessel.m4 $(I_M4_DEPS)
+@MAINTAINER_MODE_TRUE@	$(M4) -Dfile=$@ -I$(srcdir)/m4 bessel.m4 > $@
+
 @MAINTAINER_MODE_TRUE@$(i_any_c): m4/any.m4 $(I_M4_DEPS2)
 @MAINTAINER_MODE_TRUE@	$(M4) -Dfile=$@ -I$(srcdir)/m4 any.m4 > $@
 
Index: libgfortran/gfortran.map
===================================================================
--- libgfortran/gfortran.map	(Revision 163393)
+++ libgfortran/gfortran.map	(Arbeitskopie)
@@ -1107,6 +1107,14 @@  GFORTRAN_1.4 {
   global:
     _gfortran_error_stop_numeric;
     _gfortran_selected_real_kind2008;
+    _gfortran_bessel_jn_r4;
+    _gfortran_bessel_jn_r8;
+    _gfortran_bessel_jn_r10;
+    _gfortran_bessel_jn_r16;
+    _gfortran_bessel_yn_r4;
+    _gfortran_bessel_yn_r8;
+    _gfortran_bessel_yn_r10;
+    _gfortran_bessel_yn_r16;
 } GFORTRAN_1.3; 
 
 F2C_1.0 {
Index: libgfortran/generated/bessel_r4.c
===================================================================
--- libgfortran/generated/bessel_r4.c	(Revision 0)
+++ libgfortran/generated/bessel_r4.c	(Revision 0)
@@ -0,0 +1,183 @@ 
+/* Implementation of the BESSEL_JN and BESSEL_YN transformational
+   function using a recurrence algorithm.
+   Copyright 2010 Free Software Foundation, Inc.
+   Contributed by Tobias Burnus <burnus@net-b.de>
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <assert.h>
+
+
+#if defined (HAVE_GFC_REAL_4)
+
+
+
+#if defined (HAVE_JNF)
+extern void bessel_jn_r4 (gfc_array_r4 * const restrict ret, int n1,
+				     int n2, GFC_REAL_4 x);
+export_proto(bessel_jn_r4);
+
+void
+bessel_jn_r4 (gfc_array_r4 * const restrict ret, int n1, int n2, GFC_REAL_4 x)
+{
+  int i;
+  index_type stride;
+
+  GFC_REAL_4 last1, last2, x2rev;
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (ret->data == NULL)
+    {
+      size_t size = n2 < n1 ? 0 : n2-n1+1; 
+      GFC_DIMENSION_SET(ret->dim[0], 0,  size-1, 1);
+      ret->data = internal_malloc_size (sizeof (GFC_REAL_4) * size);
+      ret->offset = 0;
+    }
+
+  if (unlikely (n2 < n1))
+    return;
+
+  if (unlikely (compile_options.bounds_check)
+      && GFC_DESCRIPTOR_EXTENT(ret,0) != (n2-n1+1))
+    runtime_error("Incorrect extent in return value of BESSEL_JN "
+		  "(%ld vs. %ld)", (long int) n2-n1,
+		  GFC_DESCRIPTOR_EXTENT(ret,0));
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (unlikely (x == 0.0F))
+    {
+      ret->data[0] = 1.0;
+      for (i = 1; i <= n2-n1; i++)
+        ret->data[i*stride] = 0.0F;
+      return;
+    }
+
+  ret->data = ret->data;
+  last1 = jnf (n2, x);
+  ret->data[(n2-n1)*stride] = last1;
+
+  if (n1 == n2)
+    return;
+
+  last2 = jnf (n2 - 1, x);
+  ret->data[(n2-n1-1)*stride] = last2;
+
+  if (n1 + 1 == n2)
+    return;
+
+  x2rev = 2.0F/x;
+
+  for (i = n2-n1-2; i >= 0; i--)
+    {
+      ret->data[i*stride] = x2rev * (i+1+n1) * last2 - last1;
+      last1 = last2;
+      last2 = ret->data[i*stride];
+    }
+}
+
+#endif
+
+#if defined (HAVE_YNF)
+extern void bessel_yn_r4 (gfc_array_r4 * const restrict ret,
+				     int n1, int n2, GFC_REAL_4 x);
+export_proto(bessel_yn_r4);
+
+void
+bessel_yn_r4 (gfc_array_r4 * const restrict ret, int n1, int n2,
+			 GFC_REAL_4 x)
+{
+  int i;
+  index_type stride;
+
+  GFC_REAL_4 last1, last2, x2rev;
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (ret->data == NULL)
+    {
+      size_t size = n2 < n1 ? 0 : n2-n1+1; 
+      GFC_DIMENSION_SET(ret->dim[0], 0,  size-1, 1);
+      ret->data = internal_malloc_size (sizeof (GFC_REAL_4) * size);
+      ret->offset = 0;
+    }
+
+  if (unlikely (n2 < n1))
+    return;
+
+  if (unlikely (compile_options.bounds_check)
+      && GFC_DESCRIPTOR_EXTENT(ret,0) != (n2-n1+1))
+    runtime_error("Incorrect extent in return value of BESSEL_JN "
+		  "(%ld vs. %ld)", (long int) n2-n1,
+		  GFC_DESCRIPTOR_EXTENT(ret,0));
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (unlikely (x == 0.0F))
+    {
+      for (i = 0; i <= n2-n1; i++)
+#if defined(GFC_REAL_4_INFINITY)
+        ret->data[i*stride] = -GFC_REAL_4_INFINITY;
+#else
+        ret->data[i*stride] = -GFC_REAL_4_HUGE;
+#endif
+      return;
+    }
+
+  ret->data = ret->data;
+  last1 = ynf (n1, x);
+  ret->data[0] = last1;
+
+  if (n1 == n2)
+    return;
+
+  last2 = ynf (n1 + 1, x);
+  ret->data[1*stride] = last2;
+
+  if (n1 + 1 == n2)
+    return;
+
+  x2rev = 2.0F/x;
+
+  for (i = 2; i <= n1+n2; i++)
+    {
+#if defined(GFC_REAL_4_INFINITY)
+      if (unlikely (last2 == -GFC_REAL_4_INFINITY))
+	{
+	  ret->data[i*stride] = -GFC_REAL_4_INFINITY;
+	}
+      else
+#endif
+	{
+	  ret->data[i*stride] = x2rev * (i-1+n1) * last2 - last1;
+	  last1 = last2;
+	  last2 = ret->data[i*stride];
+	}
+    }
+}
+#endif
+
+#endif
+
Index: libgfortran/generated/bessel_r16.c
===================================================================
--- libgfortran/generated/bessel_r16.c	(Revision 0)
+++ libgfortran/generated/bessel_r16.c	(Revision 0)
@@ -0,0 +1,183 @@ 
+/* Implementation of the BESSEL_JN and BESSEL_YN transformational
+   function using a recurrence algorithm.
+   Copyright 2010 Free Software Foundation, Inc.
+   Contributed by Tobias Burnus <burnus@net-b.de>
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <assert.h>
+
+
+#if defined (HAVE_GFC_REAL_16)
+
+
+
+#if defined (HAVE_JNL)
+extern void bessel_jn_r16 (gfc_array_r16 * const restrict ret, int n1,
+				     int n2, GFC_REAL_16 x);
+export_proto(bessel_jn_r16);
+
+void
+bessel_jn_r16 (gfc_array_r16 * const restrict ret, int n1, int n2, GFC_REAL_16 x)
+{
+  int i;
+  index_type stride;
+
+  GFC_REAL_16 last1, last2, x2rev;
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (ret->data == NULL)
+    {
+      size_t size = n2 < n1 ? 0 : n2-n1+1; 
+      GFC_DIMENSION_SET(ret->dim[0], 0,  size-1, 1);
+      ret->data = internal_malloc_size (sizeof (GFC_REAL_16) * size);
+      ret->offset = 0;
+    }
+
+  if (unlikely (n2 < n1))
+    return;
+
+  if (unlikely (compile_options.bounds_check)
+      && GFC_DESCRIPTOR_EXTENT(ret,0) != (n2-n1+1))
+    runtime_error("Incorrect extent in return value of BESSEL_JN "
+		  "(%ld vs. %ld)", (long int) n2-n1,
+		  GFC_DESCRIPTOR_EXTENT(ret,0));
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (unlikely (x == 0.0L))
+    {
+      ret->data[0] = 1.0;
+      for (i = 1; i <= n2-n1; i++)
+        ret->data[i*stride] = 0.0L;
+      return;
+    }
+
+  ret->data = ret->data;
+  last1 = jnl (n2, x);
+  ret->data[(n2-n1)*stride] = last1;
+
+  if (n1 == n2)
+    return;
+
+  last2 = jnl (n2 - 1, x);
+  ret->data[(n2-n1-1)*stride] = last2;
+
+  if (n1 + 1 == n2)
+    return;
+
+  x2rev = 2.0L/x;
+
+  for (i = n2-n1-2; i >= 0; i--)
+    {
+      ret->data[i*stride] = x2rev * (i+1+n1) * last2 - last1;
+      last1 = last2;
+      last2 = ret->data[i*stride];
+    }
+}
+
+#endif
+
+#if defined (HAVE_YNL)
+extern void bessel_yn_r16 (gfc_array_r16 * const restrict ret,
+				     int n1, int n2, GFC_REAL_16 x);
+export_proto(bessel_yn_r16);
+
+void
+bessel_yn_r16 (gfc_array_r16 * const restrict ret, int n1, int n2,
+			 GFC_REAL_16 x)
+{
+  int i;
+  index_type stride;
+
+  GFC_REAL_16 last1, last2, x2rev;
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (ret->data == NULL)
+    {
+      size_t size = n2 < n1 ? 0 : n2-n1+1; 
+      GFC_DIMENSION_SET(ret->dim[0], 0,  size-1, 1);
+      ret->data = internal_malloc_size (sizeof (GFC_REAL_16) * size);
+      ret->offset = 0;
+    }
+
+  if (unlikely (n2 < n1))
+    return;
+
+  if (unlikely (compile_options.bounds_check)
+      && GFC_DESCRIPTOR_EXTENT(ret,0) != (n2-n1+1))
+    runtime_error("Incorrect extent in return value of BESSEL_JN "
+		  "(%ld vs. %ld)", (long int) n2-n1,
+		  GFC_DESCRIPTOR_EXTENT(ret,0));
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (unlikely (x == 0.0L))
+    {
+      for (i = 0; i <= n2-n1; i++)
+#if defined(GFC_REAL_16_INFINITY)
+        ret->data[i*stride] = -GFC_REAL_16_INFINITY;
+#else
+        ret->data[i*stride] = -GFC_REAL_16_HUGE;
+#endif
+      return;
+    }
+
+  ret->data = ret->data;
+  last1 = ynl (n1, x);
+  ret->data[0] = last1;
+
+  if (n1 == n2)
+    return;
+
+  last2 = ynl (n1 + 1, x);
+  ret->data[1*stride] = last2;
+
+  if (n1 + 1 == n2)
+    return;
+
+  x2rev = 2.0L/x;
+
+  for (i = 2; i <= n1+n2; i++)
+    {
+#if defined(GFC_REAL_16_INFINITY)
+      if (unlikely (last2 == -GFC_REAL_16_INFINITY))
+	{
+	  ret->data[i*stride] = -GFC_REAL_16_INFINITY;
+	}
+      else
+#endif
+	{
+	  ret->data[i*stride] = x2rev * (i-1+n1) * last2 - last1;
+	  last1 = last2;
+	  last2 = ret->data[i*stride];
+	}
+    }
+}
+#endif
+
+#endif
+
Index: libgfortran/generated/bessel_r8.c
===================================================================
--- libgfortran/generated/bessel_r8.c	(Revision 0)
+++ libgfortran/generated/bessel_r8.c	(Revision 0)
@@ -0,0 +1,183 @@ 
+/* Implementation of the BESSEL_JN and BESSEL_YN transformational
+   function using a recurrence algorithm.
+   Copyright 2010 Free Software Foundation, Inc.
+   Contributed by Tobias Burnus <burnus@net-b.de>
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <assert.h>
+
+
+#if defined (HAVE_GFC_REAL_8)
+
+
+
+#if defined (HAVE_JN)
+extern void bessel_jn_r8 (gfc_array_r8 * const restrict ret, int n1,
+				     int n2, GFC_REAL_8 x);
+export_proto(bessel_jn_r8);
+
+void
+bessel_jn_r8 (gfc_array_r8 * const restrict ret, int n1, int n2, GFC_REAL_8 x)
+{
+  int i;
+  index_type stride;
+
+  GFC_REAL_8 last1, last2, x2rev;
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (ret->data == NULL)
+    {
+      size_t size = n2 < n1 ? 0 : n2-n1+1; 
+      GFC_DIMENSION_SET(ret->dim[0], 0,  size-1, 1);
+      ret->data = internal_malloc_size (sizeof (GFC_REAL_8) * size);
+      ret->offset = 0;
+    }
+
+  if (unlikely (n2 < n1))
+    return;
+
+  if (unlikely (compile_options.bounds_check)
+      && GFC_DESCRIPTOR_EXTENT(ret,0) != (n2-n1+1))
+    runtime_error("Incorrect extent in return value of BESSEL_JN "
+		  "(%ld vs. %ld)", (long int) n2-n1,
+		  GFC_DESCRIPTOR_EXTENT(ret,0));
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (unlikely (x == 0.0))
+    {
+      ret->data[0] = 1.0;
+      for (i = 1; i <= n2-n1; i++)
+        ret->data[i*stride] = 0.0;
+      return;
+    }
+
+  ret->data = ret->data;
+  last1 = jn (n2, x);
+  ret->data[(n2-n1)*stride] = last1;
+
+  if (n1 == n2)
+    return;
+
+  last2 = jn (n2 - 1, x);
+  ret->data[(n2-n1-1)*stride] = last2;
+
+  if (n1 + 1 == n2)
+    return;
+
+  x2rev = 2.0/x;
+
+  for (i = n2-n1-2; i >= 0; i--)
+    {
+      ret->data[i*stride] = x2rev * (i+1+n1) * last2 - last1;
+      last1 = last2;
+      last2 = ret->data[i*stride];
+    }
+}
+
+#endif
+
+#if defined (HAVE_YN)
+extern void bessel_yn_r8 (gfc_array_r8 * const restrict ret,
+				     int n1, int n2, GFC_REAL_8 x);
+export_proto(bessel_yn_r8);
+
+void
+bessel_yn_r8 (gfc_array_r8 * const restrict ret, int n1, int n2,
+			 GFC_REAL_8 x)
+{
+  int i;
+  index_type stride;
+
+  GFC_REAL_8 last1, last2, x2rev;
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (ret->data == NULL)
+    {
+      size_t size = n2 < n1 ? 0 : n2-n1+1; 
+      GFC_DIMENSION_SET(ret->dim[0], 0,  size-1, 1);
+      ret->data = internal_malloc_size (sizeof (GFC_REAL_8) * size);
+      ret->offset = 0;
+    }
+
+  if (unlikely (n2 < n1))
+    return;
+
+  if (unlikely (compile_options.bounds_check)
+      && GFC_DESCRIPTOR_EXTENT(ret,0) != (n2-n1+1))
+    runtime_error("Incorrect extent in return value of BESSEL_JN "
+		  "(%ld vs. %ld)", (long int) n2-n1,
+		  GFC_DESCRIPTOR_EXTENT(ret,0));
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (unlikely (x == 0.0))
+    {
+      for (i = 0; i <= n2-n1; i++)
+#if defined(GFC_REAL_8_INFINITY)
+        ret->data[i*stride] = -GFC_REAL_8_INFINITY;
+#else
+        ret->data[i*stride] = -GFC_REAL_8_HUGE;
+#endif
+      return;
+    }
+
+  ret->data = ret->data;
+  last1 = yn (n1, x);
+  ret->data[0] = last1;
+
+  if (n1 == n2)
+    return;
+
+  last2 = yn (n1 + 1, x);
+  ret->data[1*stride] = last2;
+
+  if (n1 + 1 == n2)
+    return;
+
+  x2rev = 2.0/x;
+
+  for (i = 2; i <= n1+n2; i++)
+    {
+#if defined(GFC_REAL_8_INFINITY)
+      if (unlikely (last2 == -GFC_REAL_8_INFINITY))
+	{
+	  ret->data[i*stride] = -GFC_REAL_8_INFINITY;
+	}
+      else
+#endif
+	{
+	  ret->data[i*stride] = x2rev * (i-1+n1) * last2 - last1;
+	  last1 = last2;
+	  last2 = ret->data[i*stride];
+	}
+    }
+}
+#endif
+
+#endif
+
Index: libgfortran/generated/bessel_r10.c
===================================================================
--- libgfortran/generated/bessel_r10.c	(Revision 0)
+++ libgfortran/generated/bessel_r10.c	(Revision 0)
@@ -0,0 +1,183 @@ 
+/* Implementation of the BESSEL_JN and BESSEL_YN transformational
+   function using a recurrence algorithm.
+   Copyright 2010 Free Software Foundation, Inc.
+   Contributed by Tobias Burnus <burnus@net-b.de>
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <assert.h>
+
+
+#if defined (HAVE_GFC_REAL_10)
+
+
+
+#if defined (HAVE_JNL)
+extern void bessel_jn_r10 (gfc_array_r10 * const restrict ret, int n1,
+				     int n2, GFC_REAL_10 x);
+export_proto(bessel_jn_r10);
+
+void
+bessel_jn_r10 (gfc_array_r10 * const restrict ret, int n1, int n2, GFC_REAL_10 x)
+{
+  int i;
+  index_type stride;
+
+  GFC_REAL_10 last1, last2, x2rev;
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (ret->data == NULL)
+    {
+      size_t size = n2 < n1 ? 0 : n2-n1+1; 
+      GFC_DIMENSION_SET(ret->dim[0], 0,  size-1, 1);
+      ret->data = internal_malloc_size (sizeof (GFC_REAL_10) * size);
+      ret->offset = 0;
+    }
+
+  if (unlikely (n2 < n1))
+    return;
+
+  if (unlikely (compile_options.bounds_check)
+      && GFC_DESCRIPTOR_EXTENT(ret,0) != (n2-n1+1))
+    runtime_error("Incorrect extent in return value of BESSEL_JN "
+		  "(%ld vs. %ld)", (long int) n2-n1,
+		  GFC_DESCRIPTOR_EXTENT(ret,0));
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (unlikely (x == 0.0L))
+    {
+      ret->data[0] = 1.0;
+      for (i = 1; i <= n2-n1; i++)
+        ret->data[i*stride] = 0.0L;
+      return;
+    }
+
+  ret->data = ret->data;
+  last1 = jnl (n2, x);
+  ret->data[(n2-n1)*stride] = last1;
+
+  if (n1 == n2)
+    return;
+
+  last2 = jnl (n2 - 1, x);
+  ret->data[(n2-n1-1)*stride] = last2;
+
+  if (n1 + 1 == n2)
+    return;
+
+  x2rev = 2.0L/x;
+
+  for (i = n2-n1-2; i >= 0; i--)
+    {
+      ret->data[i*stride] = x2rev * (i+1+n1) * last2 - last1;
+      last1 = last2;
+      last2 = ret->data[i*stride];
+    }
+}
+
+#endif
+
+#if defined (HAVE_YNL)
+extern void bessel_yn_r10 (gfc_array_r10 * const restrict ret,
+				     int n1, int n2, GFC_REAL_10 x);
+export_proto(bessel_yn_r10);
+
+void
+bessel_yn_r10 (gfc_array_r10 * const restrict ret, int n1, int n2,
+			 GFC_REAL_10 x)
+{
+  int i;
+  index_type stride;
+
+  GFC_REAL_10 last1, last2, x2rev;
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (ret->data == NULL)
+    {
+      size_t size = n2 < n1 ? 0 : n2-n1+1; 
+      GFC_DIMENSION_SET(ret->dim[0], 0,  size-1, 1);
+      ret->data = internal_malloc_size (sizeof (GFC_REAL_10) * size);
+      ret->offset = 0;
+    }
+
+  if (unlikely (n2 < n1))
+    return;
+
+  if (unlikely (compile_options.bounds_check)
+      && GFC_DESCRIPTOR_EXTENT(ret,0) != (n2-n1+1))
+    runtime_error("Incorrect extent in return value of BESSEL_JN "
+		  "(%ld vs. %ld)", (long int) n2-n1,
+		  GFC_DESCRIPTOR_EXTENT(ret,0));
+
+  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
+
+  if (unlikely (x == 0.0L))
+    {
+      for (i = 0; i <= n2-n1; i++)
+#if defined(GFC_REAL_10_INFINITY)
+        ret->data[i*stride] = -GFC_REAL_10_INFINITY;
+#else
+        ret->data[i*stride] = -GFC_REAL_10_HUGE;
+#endif
+      return;
+    }
+
+  ret->data = ret->data;
+  last1 = ynl (n1, x);
+  ret->data[0] = last1;
+
+  if (n1 == n2)
+    return;
+
+  last2 = ynl (n1 + 1, x);
+  ret->data[1*stride] = last2;
+
+  if (n1 + 1 == n2)
+    return;
+
+  x2rev = 2.0L/x;
+
+  for (i = 2; i <= n1+n2; i++)
+    {
+#if defined(GFC_REAL_10_INFINITY)
+      if (unlikely (last2 == -GFC_REAL_10_INFINITY))
+	{
+	  ret->data[i*stride] = -GFC_REAL_10_INFINITY;
+	}
+      else
+#endif
+	{
+	  ret->data[i*stride] = x2rev * (i-1+n1) * last2 - last1;
+	  last1 = last2;
+	  last2 = ret->data[i*stride];
+	}
+    }
+}
+#endif
+
+#endif
+
Index: libgfortran/Makefile.am
===================================================================
--- libgfortran/Makefile.am	(Revision 163393)
+++ libgfortran/Makefile.am	(Arbeitskopie)
@@ -175,6 +175,12 @@  $(srcdir)/generated/any_l4.c \
 $(srcdir)/generated/any_l8.c \
 $(srcdir)/generated/any_l16.c
 
+i_bessel_c= \
+$(srcdir)/generated/bessel_r4.c \
+$(srcdir)/generated/bessel_r8.c \
+$(srcdir)/generated/bessel_r10.c \
+$(srcdir)/generated/bessel_r16.c
+
 i_count_c= \
 $(srcdir)/generated/count_1_l.c \
 $(srcdir)/generated/count_2_l.c \
@@ -583,11 +589,11 @@  m4_files= m4/iparm.m4 m4/ifunction.m4 m4
     m4/transpose.m4 m4/eoshift1.m4 m4/eoshift3.m4 m4/exponent.m4 \
     m4/fraction.m4 m4/nearest.m4 m4/set_exponent.m4 m4/pow.m4 \
     m4/misc_specifics.m4 m4/rrspacing.m4 m4/spacing.m4 m4/pack.m4 \
-    m4/unpack.m4 m4/spread.m4
+    m4/unpack.m4 m4/spread.m4 m4/bessel.m4
 
 gfor_built_src= $(i_all_c) $(i_any_c) $(i_count_c) $(i_maxloc0_c) \
     $(i_maxloc1_c) $(i_maxval_c) $(i_minloc0_c) $(i_minloc1_c) $(i_minval_c) \
-    $(i_product_c) $(i_sum_c) \
+    $(i_product_c) $(i_sum_c) $(i_bessel_c) \
     $(i_matmul_c) $(i_matmull_c) $(i_transpose_c) $(i_shape_c) $(i_eoshift1_c) \
     $(i_eoshift3_c) $(i_cshift1_c) $(i_reshape_c) $(in_pack_c) $(in_unpack_c) \
     $(i_exponent_c) $(i_fraction_c) $(i_nearest_c) $(i_set_exponent_c) \
@@ -821,6 +827,9 @@  if MAINTAINER_MODE
 $(i_all_c): m4/all.m4 $(I_M4_DEPS2)
 	$(M4) -Dfile=$@ -I$(srcdir)/m4 all.m4 > $@
 
+$(i_bessel_c): m4/bessel.m4 $(I_M4_DEPS)
+	$(M4) -Dfile=$@ -I$(srcdir)/m4 bessel.m4 > $@
+
 $(i_any_c): m4/any.m4 $(I_M4_DEPS2)
 	$(M4) -Dfile=$@ -I$(srcdir)/m4 any.m4 > $@
 
Index: gcc/testsuite/gfortran.dg/bessel_6.f90
===================================================================
--- gcc/testsuite/gfortran.dg/bessel_6.f90	(Revision 0)
+++ gcc/testsuite/gfortran.dg/bessel_6.f90	(Revision 0)
@@ -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
Index: gcc/testsuite/gfortran.dg/bessel_7.f90
===================================================================
--- gcc/testsuite/gfortran.dg/bessel_7.f90	(Revision 0)
+++ gcc/testsuite/gfortran.dg/bessel_7.f90	(Revision 0)
@@ -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