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  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 #if defined(POWER_IEEE128)
     32  1.1  mrg #define MATHFUNC(funcname) __ ## funcname ## ieee128
     33  1.1  mrg #else
     34  1.1  mrg #define MATHFUNC(funcname) funcname ## q
     35  1.1  mrg #endif
     36  1.1  mrg 
     37  1.1  mrg #if defined (HAVE_GFC_REAL_17)
     38  1.1  mrg 
     39  1.1  mrg 
     40  1.1  mrg 
     41  1.1  mrg #if 1 /* FIXME: figure this out later.  */
     42  1.1  mrg extern void bessel_jn_r17 (gfc_array_r17 * const restrict ret, int n1,
     43  1.1  mrg 				     int n2, GFC_REAL_17 x);
     44  1.1  mrg export_proto(bessel_jn_r17);
     45  1.1  mrg 
     46  1.1  mrg void
     47  1.1  mrg bessel_jn_r17 (gfc_array_r17 * const restrict ret, int n1, int n2, GFC_REAL_17 x)
     48  1.1  mrg {
     49  1.1  mrg   int i;
     50  1.1  mrg   index_type stride;
     51  1.1  mrg 
     52  1.1  mrg   GFC_REAL_17 last1, last2, x2rev;
     53  1.1  mrg 
     54  1.1  mrg   stride = GFC_DESCRIPTOR_STRIDE(ret,0);
     55  1.1  mrg 
     56  1.1  mrg   if (ret->base_addr == NULL)
     57  1.1  mrg     {
     58  1.1  mrg       size_t size = n2 < n1 ? 0 : n2-n1+1;
     59  1.1  mrg       GFC_DIMENSION_SET(ret->dim[0], 0, size-1, 1);
     60  1.1  mrg       ret->base_addr = xmallocarray (size, sizeof (GFC_REAL_17));
     61  1.1  mrg       ret->offset = 0;
     62  1.1  mrg     }
     63  1.1  mrg 
     64  1.1  mrg   if (unlikely (n2 < n1))
     65  1.1  mrg     return;
     66  1.1  mrg 
     67  1.1  mrg   if (unlikely (compile_options.bounds_check)
     68  1.1  mrg       && GFC_DESCRIPTOR_EXTENT(ret,0) != (n2-n1+1))
     69  1.1  mrg     runtime_error("Incorrect extent in return value of BESSEL_JN "
     70  1.1  mrg 		  "(%ld vs. %ld)", (long int) n2-n1,
     71  1.1  mrg 		  (long int) GFC_DESCRIPTOR_EXTENT(ret,0));
     72  1.1  mrg 
     73  1.1  mrg   stride = GFC_DESCRIPTOR_STRIDE(ret,0);
     74  1.1  mrg 
     75  1.1  mrg   if (unlikely (x == 0))
     76  1.1  mrg     {
     77  1.1  mrg       ret->base_addr[0] = 1;
     78  1.1  mrg       for (i = 1; i <= n2-n1; i++)
     79  1.1  mrg         ret->base_addr[i*stride] = 0;
     80  1.1  mrg       return;
     81  1.1  mrg     }
     82  1.1  mrg 
     83  1.1  mrg   last1 = MATHFUNC(jn) (n2, x);
     84  1.1  mrg   ret->base_addr[(n2-n1)*stride] = last1;
     85  1.1  mrg 
     86  1.1  mrg   if (n1 == n2)
     87  1.1  mrg     return;
     88  1.1  mrg 
     89  1.1  mrg   last2 = MATHFUNC(jn) (n2 - 1, x);
     90  1.1  mrg   ret->base_addr[(n2-n1-1)*stride] = last2;
     91  1.1  mrg 
     92  1.1  mrg   if (n1 + 1 == n2)
     93  1.1  mrg     return;
     94  1.1  mrg 
     95  1.1  mrg   x2rev = GFC_REAL_17_LITERAL(2.)/x;
     96  1.1  mrg 
     97  1.1  mrg   for (i = n2-n1-2; i >= 0; i--)
     98  1.1  mrg     {
     99  1.1  mrg       ret->base_addr[i*stride] = x2rev * (i+1+n1) * last2 - last1;
    100  1.1  mrg       last1 = last2;
    101  1.1  mrg       last2 = ret->base_addr[i*stride];
    102  1.1  mrg     }
    103  1.1  mrg }
    104  1.1  mrg 
    105  1.1  mrg #endif
    106  1.1  mrg 
    107  1.1  mrg #if 1 /* FIXME: figure this out later.  */
    108  1.1  mrg extern void bessel_yn_r17 (gfc_array_r17 * const restrict ret,
    109  1.1  mrg 				     int n1, int n2, GFC_REAL_17 x);
    110  1.1  mrg export_proto(bessel_yn_r17);
    111  1.1  mrg 
    112  1.1  mrg void
    113  1.1  mrg bessel_yn_r17 (gfc_array_r17 * const restrict ret, int n1, int n2,
    114  1.1  mrg 			 GFC_REAL_17 x)
    115  1.1  mrg {
    116  1.1  mrg   int i;
    117  1.1  mrg   index_type stride;
    118  1.1  mrg 
    119  1.1  mrg   GFC_REAL_17 last1, last2, x2rev;
    120  1.1  mrg 
    121  1.1  mrg   stride = GFC_DESCRIPTOR_STRIDE(ret,0);
    122  1.1  mrg 
    123  1.1  mrg   if (ret->base_addr == NULL)
    124  1.1  mrg     {
    125  1.1  mrg       size_t size = n2 < n1 ? 0 : n2-n1+1;
    126  1.1  mrg       GFC_DIMENSION_SET(ret->dim[0], 0, size-1, 1);
    127  1.1  mrg       ret->base_addr = xmallocarray (size, sizeof (GFC_REAL_17));
    128  1.1  mrg       ret->offset = 0;
    129  1.1  mrg     }
    130  1.1  mrg 
    131  1.1  mrg   if (unlikely (n2 < n1))
    132  1.1  mrg     return;
    133  1.1  mrg 
    134  1.1  mrg   if (unlikely (compile_options.bounds_check)
    135  1.1  mrg       && GFC_DESCRIPTOR_EXTENT(ret,0) != (n2-n1+1))
    136  1.1  mrg     runtime_error("Incorrect extent in return value of BESSEL_JN "
    137  1.1  mrg 		  "(%ld vs. %ld)", (long int) n2-n1,
    138  1.1  mrg 		  (long int) GFC_DESCRIPTOR_EXTENT(ret,0));
    139  1.1  mrg 
    140  1.1  mrg   stride = GFC_DESCRIPTOR_STRIDE(ret,0);
    141  1.1  mrg 
    142  1.1  mrg   if (unlikely (x == 0))
    143  1.1  mrg     {
    144  1.1  mrg       for (i = 0; i <= n2-n1; i++)
    145  1.1  mrg #if defined(GFC_REAL_17_INFINITY)
    146  1.1  mrg         ret->base_addr[i*stride] = -GFC_REAL_17_INFINITY;
    147  1.1  mrg #else
    148  1.1  mrg         ret->base_addr[i*stride] = -GFC_REAL_17_HUGE;
    149  1.1  mrg #endif
    150  1.1  mrg       return;
    151  1.1  mrg     }
    152  1.1  mrg 
    153  1.1  mrg   last1 = MATHFUNC(yn) (n1, x);
    154  1.1  mrg   ret->base_addr[0] = last1;
    155  1.1  mrg 
    156  1.1  mrg   if (n1 == n2)
    157  1.1  mrg     return;
    158  1.1  mrg 
    159  1.1  mrg   last2 = MATHFUNC(yn) (n1 + 1, x);
    160  1.1  mrg   ret->base_addr[1*stride] = last2;
    161  1.1  mrg 
    162  1.1  mrg   if (n1 + 1 == n2)
    163  1.1  mrg     return;
    164  1.1  mrg 
    165  1.1  mrg   x2rev = GFC_REAL_17_LITERAL(2.)/x;
    166  1.1  mrg 
    167  1.1  mrg   for (i = 2; i <= n2 - n1; i++)
    168  1.1  mrg     {
    169  1.1  mrg #if defined(GFC_REAL_17_INFINITY)
    170  1.1  mrg       if (unlikely (last2 == -GFC_REAL_17_INFINITY))
    171  1.1  mrg 	{
    172  1.1  mrg 	  ret->base_addr[i*stride] = -GFC_REAL_17_INFINITY;
    173  1.1  mrg 	}
    174  1.1  mrg       else
    175  1.1  mrg #endif
    176  1.1  mrg 	{
    177  1.1  mrg 	  ret->base_addr[i*stride] = x2rev * (i-1+n1) * last2 - last1;
    178  1.1  mrg 	  last1 = last2;
    179  1.1  mrg 	  last2 = ret->base_addr[i*stride];
    180  1.1  mrg 	}
    181  1.1  mrg     }
    182  1.1  mrg }
    183  1.1  mrg #endif
    184  1.1  mrg 
    185  1.1  mrg #endif
    186  1.1  mrg 
    187