Home | History | Annotate | Line # | Download | only in generated
      1      1.1  mrg /* Implementation of the BESSEL_JN and BESSEL_YN transformational
      2      1.1  mrg    function using a recurrence algorithm.
      3  1.1.1.3  mrg    Copyright (C) 2010-2022 Free Software Foundation, Inc.
      4      1.1  mrg    Contributed by Tobias Burnus <burnus (at) net-b.de>
      5      1.1  mrg 
      6      1.1  mrg This file is part of the GNU Fortran runtime library (libgfortran).
      7      1.1  mrg 
      8      1.1  mrg Libgfortran is free software; you can redistribute it and/or
      9      1.1  mrg modify it under the terms of the GNU General Public
     10      1.1  mrg License as published by the Free Software Foundation; either
     11      1.1  mrg version 3 of the License, or (at your option) any later version.
     12      1.1  mrg 
     13      1.1  mrg Libgfortran is distributed in the hope that it will be useful,
     14      1.1  mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     15      1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16      1.1  mrg GNU General Public License for more details.
     17      1.1  mrg 
     18      1.1  mrg Under Section 7 of GPL version 3, you are granted additional
     19      1.1  mrg permissions described in the GCC Runtime Library Exception, version
     20      1.1  mrg 3.1, as published by the Free Software Foundation.
     21      1.1  mrg 
     22      1.1  mrg You should have received a copy of the GNU General Public License and
     23      1.1  mrg a copy of the GCC Runtime Library Exception along with this program;
     24      1.1  mrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     25      1.1  mrg <http://www.gnu.org/licenses/>.  */
     26      1.1  mrg 
     27      1.1  mrg #include "libgfortran.h"
     28      1.1  mrg 
     29      1.1  mrg 
     30      1.1  mrg 
     31      1.1  mrg #define MATHFUNC(funcname) funcname
     32      1.1  mrg 
     33      1.1  mrg #if defined (HAVE_GFC_REAL_8)
     34      1.1  mrg 
     35      1.1  mrg 
     36      1.1  mrg 
     37      1.1  mrg #if defined (HAVE_JN)
     38      1.1  mrg extern void bessel_jn_r8 (gfc_array_r8 * const restrict ret, int n1,
     39      1.1  mrg 				     int n2, GFC_REAL_8 x);
     40      1.1  mrg export_proto(bessel_jn_r8);
     41      1.1  mrg 
     42      1.1  mrg void
     43      1.1  mrg bessel_jn_r8 (gfc_array_r8 * const restrict ret, int n1, int n2, GFC_REAL_8 x)
     44      1.1  mrg {
     45      1.1  mrg   int i;
     46      1.1  mrg   index_type stride;
     47      1.1  mrg 
     48      1.1  mrg   GFC_REAL_8 last1, last2, x2rev;
     49      1.1  mrg 
     50      1.1  mrg   stride = GFC_DESCRIPTOR_STRIDE(ret,0);
     51      1.1  mrg 
     52      1.1  mrg   if (ret->base_addr == NULL)
     53      1.1  mrg     {
     54      1.1  mrg       size_t size = n2 < n1 ? 0 : n2-n1+1;
     55      1.1  mrg       GFC_DIMENSION_SET(ret->dim[0], 0, size-1, 1);
     56      1.1  mrg       ret->base_addr = xmallocarray (size, sizeof (GFC_REAL_8));
     57      1.1  mrg       ret->offset = 0;
     58      1.1  mrg     }
     59      1.1  mrg 
     60      1.1  mrg   if (unlikely (n2 < n1))
     61      1.1  mrg     return;
     62      1.1  mrg 
     63      1.1  mrg   if (unlikely (compile_options.bounds_check)
     64      1.1  mrg       && GFC_DESCRIPTOR_EXTENT(ret,0) != (n2-n1+1))
     65      1.1  mrg     runtime_error("Incorrect extent in return value of BESSEL_JN "
     66      1.1  mrg 		  "(%ld vs. %ld)", (long int) n2-n1,
     67      1.1  mrg 		  (long int) GFC_DESCRIPTOR_EXTENT(ret,0));
     68      1.1  mrg 
     69      1.1  mrg   stride = GFC_DESCRIPTOR_STRIDE(ret,0);
     70      1.1  mrg 
     71      1.1  mrg   if (unlikely (x == 0))
     72      1.1  mrg     {
     73      1.1  mrg       ret->base_addr[0] = 1;
     74      1.1  mrg       for (i = 1; i <= n2-n1; i++)
     75      1.1  mrg         ret->base_addr[i*stride] = 0;
     76      1.1  mrg       return;
     77      1.1  mrg     }
     78      1.1  mrg 
     79      1.1  mrg   last1 = MATHFUNC(jn) (n2, x);
     80      1.1  mrg   ret->base_addr[(n2-n1)*stride] = last1;
     81      1.1  mrg 
     82      1.1  mrg   if (n1 == n2)
     83      1.1  mrg     return;
     84      1.1  mrg 
     85      1.1  mrg   last2 = MATHFUNC(jn) (n2 - 1, x);
     86      1.1  mrg   ret->base_addr[(n2-n1-1)*stride] = last2;
     87      1.1  mrg 
     88      1.1  mrg   if (n1 + 1 == n2)
     89      1.1  mrg     return;
     90      1.1  mrg 
     91      1.1  mrg   x2rev = GFC_REAL_8_LITERAL(2.)/x;
     92      1.1  mrg 
     93      1.1  mrg   for (i = n2-n1-2; i >= 0; i--)
     94      1.1  mrg     {
     95      1.1  mrg       ret->base_addr[i*stride] = x2rev * (i+1+n1) * last2 - last1;
     96      1.1  mrg       last1 = last2;
     97      1.1  mrg       last2 = ret->base_addr[i*stride];
     98      1.1  mrg     }
     99      1.1  mrg }
    100      1.1  mrg 
    101      1.1  mrg #endif
    102      1.1  mrg 
    103      1.1  mrg #if defined (HAVE_YN)
    104      1.1  mrg extern void bessel_yn_r8 (gfc_array_r8 * const restrict ret,
    105      1.1  mrg 				     int n1, int n2, GFC_REAL_8 x);
    106      1.1  mrg export_proto(bessel_yn_r8);
    107      1.1  mrg 
    108      1.1  mrg void
    109      1.1  mrg bessel_yn_r8 (gfc_array_r8 * const restrict ret, int n1, int n2,
    110      1.1  mrg 			 GFC_REAL_8 x)
    111      1.1  mrg {
    112      1.1  mrg   int i;
    113      1.1  mrg   index_type stride;
    114      1.1  mrg 
    115      1.1  mrg   GFC_REAL_8 last1, last2, x2rev;
    116      1.1  mrg 
    117      1.1  mrg   stride = GFC_DESCRIPTOR_STRIDE(ret,0);
    118      1.1  mrg 
    119      1.1  mrg   if (ret->base_addr == NULL)
    120      1.1  mrg     {
    121      1.1  mrg       size_t size = n2 < n1 ? 0 : n2-n1+1;
    122      1.1  mrg       GFC_DIMENSION_SET(ret->dim[0], 0, size-1, 1);
    123      1.1  mrg       ret->base_addr = xmallocarray (size, sizeof (GFC_REAL_8));
    124      1.1  mrg       ret->offset = 0;
    125      1.1  mrg     }
    126      1.1  mrg 
    127      1.1  mrg   if (unlikely (n2 < n1))
    128      1.1  mrg     return;
    129      1.1  mrg 
    130      1.1  mrg   if (unlikely (compile_options.bounds_check)
    131      1.1  mrg       && GFC_DESCRIPTOR_EXTENT(ret,0) != (n2-n1+1))
    132      1.1  mrg     runtime_error("Incorrect extent in return value of BESSEL_JN "
    133      1.1  mrg 		  "(%ld vs. %ld)", (long int) n2-n1,
    134      1.1  mrg 		  (long int) GFC_DESCRIPTOR_EXTENT(ret,0));
    135      1.1  mrg 
    136      1.1  mrg   stride = GFC_DESCRIPTOR_STRIDE(ret,0);
    137      1.1  mrg 
    138      1.1  mrg   if (unlikely (x == 0))
    139      1.1  mrg     {
    140      1.1  mrg       for (i = 0; i <= n2-n1; i++)
    141      1.1  mrg #if defined(GFC_REAL_8_INFINITY)
    142      1.1  mrg         ret->base_addr[i*stride] = -GFC_REAL_8_INFINITY;
    143      1.1  mrg #else
    144      1.1  mrg         ret->base_addr[i*stride] = -GFC_REAL_8_HUGE;
    145      1.1  mrg #endif
    146      1.1  mrg       return;
    147      1.1  mrg     }
    148      1.1  mrg 
    149      1.1  mrg   last1 = MATHFUNC(yn) (n1, x);
    150      1.1  mrg   ret->base_addr[0] = last1;
    151      1.1  mrg 
    152      1.1  mrg   if (n1 == n2)
    153      1.1  mrg     return;
    154      1.1  mrg 
    155      1.1  mrg   last2 = MATHFUNC(yn) (n1 + 1, x);
    156      1.1  mrg   ret->base_addr[1*stride] = last2;
    157      1.1  mrg 
    158      1.1  mrg   if (n1 + 1 == n2)
    159      1.1  mrg     return;
    160      1.1  mrg 
    161      1.1  mrg   x2rev = GFC_REAL_8_LITERAL(2.)/x;
    162      1.1  mrg 
    163      1.1  mrg   for (i = 2; i <= n2 - n1; i++)
    164      1.1  mrg     {
    165      1.1  mrg #if defined(GFC_REAL_8_INFINITY)
    166      1.1  mrg       if (unlikely (last2 == -GFC_REAL_8_INFINITY))
    167      1.1  mrg 	{
    168      1.1  mrg 	  ret->base_addr[i*stride] = -GFC_REAL_8_INFINITY;
    169      1.1  mrg 	}
    170      1.1  mrg       else
    171      1.1  mrg #endif
    172      1.1  mrg 	{
    173      1.1  mrg 	  ret->base_addr[i*stride] = x2rev * (i-1+n1) * last2 - last1;
    174      1.1  mrg 	  last1 = last2;
    175      1.1  mrg 	  last2 = ret->base_addr[i*stride];
    176      1.1  mrg 	}
    177      1.1  mrg     }
    178      1.1  mrg }
    179      1.1  mrg #endif
    180      1.1  mrg 
    181      1.1  mrg #endif
    182      1.1  mrg 
    183