Commit 47b99694 by Tobias Burnus

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
parent 508e4757
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.
......
......@@ -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;
......
......@@ -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);
......
......@@ -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 *);
......
......@@ -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"));
}
......
......@@ -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);
......
......@@ -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;
......
......@@ -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
......
......@@ -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;
......
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
......
! { 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
! { 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
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 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libfortran/45108
......@@ -33,8 +47,8 @@
2010-08-01 Janne Blomqvist <jb@gcc.gnu.org>
* io/unix.c (file_exists): Use access(2) instead of stat(2) to
test file existence.
* io/unix.c (file_exists): Use access(2) instead of stat(2) to
test file existence.
(fallback_access): Move up in file, implement F_OK.
2010-07-31 David Edelsohn <edelsohn@gnu.org>
......
......@@ -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/iforeach.m4 m4/all.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 > $@
......
/* 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.0L;
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
/* 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.0L;
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
/* 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.0F;
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
/* 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
......@@ -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 {
......
`/* 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'Q`;
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'
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment