Home | History | Annotate | Line # | Download | only in m4
      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.4  mrg    Copyright (C) 2010-2024 Free Software Foundation, Inc.
      4      1.1  mrg    Contributed by Tobias Burnus <burnus (a] 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 include(iparm.m4)dnl
     30      1.1  mrg include(`mtype.m4')dnl
     31      1.1  mrg 
     32      1.1  mrg mathfunc_macro
     33      1.1  mrg 
     34      1.1  mrg `#if defined (HAVE_'rtype_name`)
     35      1.1  mrg 
     36      1.1  mrg 
     37      1.1  mrg 
     38      1.1  mrg #if 'hasmathfunc(jn)`
     39      1.1  mrg extern void bessel_jn_r'rtype_kind` ('rtype` * const restrict ret, int n1,
     40      1.1  mrg 				     int n2, 'rtype_name` x);
     41      1.1  mrg export_proto(bessel_jn_r'rtype_kind`);
     42      1.1  mrg 
     43      1.1  mrg void
     44      1.1  mrg bessel_jn_r'rtype_kind` ('rtype` * const restrict ret, int n1, int n2, 'rtype_name` x)
     45      1.1  mrg {
     46      1.1  mrg   int i;
     47      1.1  mrg   index_type stride;
     48      1.1  mrg 
     49      1.1  mrg   'rtype_name` last1, last2, x2rev;
     50      1.1  mrg 
     51      1.1  mrg   stride = GFC_DESCRIPTOR_STRIDE(ret,0);
     52      1.1  mrg 
     53      1.1  mrg   if (ret->base_addr == NULL)
     54      1.1  mrg     {
     55      1.1  mrg       size_t size = n2 < n1 ? 0 : n2-n1+1; 
     56      1.1  mrg       GFC_DIMENSION_SET(ret->dim[0], 0, size-1, 1);
     57      1.1  mrg       ret->base_addr = xmallocarray (size, sizeof ('rtype_name`));
     58      1.1  mrg       ret->offset = 0;
     59      1.1  mrg     }
     60      1.1  mrg 
     61      1.1  mrg   if (unlikely (n2 < n1))
     62      1.1  mrg     return;
     63      1.1  mrg 
     64      1.1  mrg   if (unlikely (compile_options.bounds_check)
     65      1.1  mrg       && GFC_DESCRIPTOR_EXTENT(ret,0) != (n2-n1+1))
     66      1.1  mrg     runtime_error("Incorrect extent in return value of BESSEL_JN "
     67      1.1  mrg 		  "(%ld vs. %ld)", (long int) n2-n1,
     68      1.1  mrg 		  (long int) GFC_DESCRIPTOR_EXTENT(ret,0));
     69      1.1  mrg 
     70      1.1  mrg   stride = GFC_DESCRIPTOR_STRIDE(ret,0);
     71      1.1  mrg 
     72      1.1  mrg   if (unlikely (x == 0))
     73      1.1  mrg     {
     74      1.1  mrg       ret->base_addr[0] = 1;
     75      1.1  mrg       for (i = 1; i <= n2-n1; i++)
     76      1.1  mrg         ret->base_addr[i*stride] = 0;
     77      1.1  mrg       return;
     78      1.1  mrg     }
     79      1.1  mrg 
     80      1.1  mrg   last1 = MATHFUNC(jn) (n2, x);
     81      1.1  mrg   ret->base_addr[(n2-n1)*stride] = last1;
     82      1.1  mrg 
     83      1.1  mrg   if (n1 == n2)
     84      1.1  mrg     return;
     85      1.1  mrg 
     86      1.1  mrg   last2 = MATHFUNC(jn) (n2 - 1, x);
     87      1.1  mrg   ret->base_addr[(n2-n1-1)*stride] = last2;
     88      1.1  mrg 
     89      1.1  mrg   if (n1 + 1 == n2)
     90      1.1  mrg     return;
     91      1.1  mrg 
     92      1.1  mrg   x2rev = GFC_REAL_'rtype_kind`_LITERAL(2.)/x;
     93      1.1  mrg 
     94      1.1  mrg   for (i = n2-n1-2; i >= 0; i--)
     95      1.1  mrg     {
     96      1.1  mrg       ret->base_addr[i*stride] = x2rev * (i+1+n1) * last2 - last1;
     97      1.1  mrg       last1 = last2;
     98      1.1  mrg       last2 = ret->base_addr[i*stride];
     99      1.1  mrg     }
    100      1.1  mrg }
    101      1.1  mrg 
    102      1.1  mrg #endif
    103      1.1  mrg 
    104      1.1  mrg #if 'hasmathfunc(yn)`
    105      1.1  mrg extern void bessel_yn_r'rtype_kind` ('rtype` * const restrict ret,
    106      1.1  mrg 				     int n1, int n2, 'rtype_name` x);
    107      1.1  mrg export_proto(bessel_yn_r'rtype_kind`);
    108      1.1  mrg 
    109      1.1  mrg void
    110      1.1  mrg bessel_yn_r'rtype_kind` ('rtype` * const restrict ret, int n1, int n2,
    111      1.1  mrg 			 'rtype_name` x)
    112      1.1  mrg {
    113      1.1  mrg   int i;
    114      1.1  mrg   index_type stride;
    115      1.1  mrg 
    116      1.1  mrg   'rtype_name` last1, last2, x2rev;
    117      1.1  mrg 
    118      1.1  mrg   stride = GFC_DESCRIPTOR_STRIDE(ret,0);
    119      1.1  mrg 
    120      1.1  mrg   if (ret->base_addr == NULL)
    121      1.1  mrg     {
    122      1.1  mrg       size_t size = n2 < n1 ? 0 : n2-n1+1; 
    123      1.1  mrg       GFC_DIMENSION_SET(ret->dim[0], 0, size-1, 1);
    124      1.1  mrg       ret->base_addr = xmallocarray (size, sizeof ('rtype_name`));
    125      1.1  mrg       ret->offset = 0;
    126      1.1  mrg     }
    127      1.1  mrg 
    128      1.1  mrg   if (unlikely (n2 < n1))
    129      1.1  mrg     return;
    130      1.1  mrg 
    131      1.1  mrg   if (unlikely (compile_options.bounds_check)
    132      1.1  mrg       && GFC_DESCRIPTOR_EXTENT(ret,0) != (n2-n1+1))
    133      1.1  mrg     runtime_error("Incorrect extent in return value of BESSEL_JN "
    134      1.1  mrg 		  "(%ld vs. %ld)", (long int) n2-n1,
    135      1.1  mrg 		  (long int) GFC_DESCRIPTOR_EXTENT(ret,0));
    136      1.1  mrg 
    137      1.1  mrg   stride = GFC_DESCRIPTOR_STRIDE(ret,0);
    138      1.1  mrg 
    139      1.1  mrg   if (unlikely (x == 0))
    140      1.1  mrg     {
    141      1.1  mrg       for (i = 0; i <= n2-n1; i++)
    142      1.1  mrg #if defined('rtype_name`_INFINITY)
    143      1.1  mrg         ret->base_addr[i*stride] = -'rtype_name`_INFINITY;
    144      1.1  mrg #else
    145      1.1  mrg         ret->base_addr[i*stride] = -'rtype_name`_HUGE;
    146      1.1  mrg #endif
    147      1.1  mrg       return;
    148      1.1  mrg     }
    149      1.1  mrg 
    150      1.1  mrg   last1 = MATHFUNC(yn) (n1, x);
    151      1.1  mrg   ret->base_addr[0] = last1;
    152      1.1  mrg 
    153      1.1  mrg   if (n1 == n2)
    154      1.1  mrg     return;
    155      1.1  mrg 
    156      1.1  mrg   last2 = MATHFUNC(yn) (n1 + 1, x);
    157      1.1  mrg   ret->base_addr[1*stride] = last2;
    158      1.1  mrg 
    159      1.1  mrg   if (n1 + 1 == n2)
    160      1.1  mrg     return;
    161      1.1  mrg 
    162      1.1  mrg   x2rev = GFC_REAL_'rtype_kind`_LITERAL(2.)/x;
    163      1.1  mrg 
    164      1.1  mrg   for (i = 2; i <= n2 - n1; i++)
    165      1.1  mrg     {
    166      1.1  mrg #if defined('rtype_name`_INFINITY)
    167      1.1  mrg       if (unlikely (last2 == -'rtype_name`_INFINITY))
    168      1.1  mrg 	{
    169      1.1  mrg 	  ret->base_addr[i*stride] = -'rtype_name`_INFINITY;
    170      1.1  mrg 	}
    171      1.1  mrg       else
    172      1.1  mrg #endif
    173      1.1  mrg 	{
    174      1.1  mrg 	  ret->base_addr[i*stride] = x2rev * (i-1+n1) * last2 - last1;
    175      1.1  mrg 	  last1 = last2;
    176      1.1  mrg 	  last2 = ret->base_addr[i*stride];
    177      1.1  mrg 	}
    178      1.1  mrg     }
    179      1.1  mrg }
    180      1.1  mrg #endif
    181      1.1  mrg 
    182      1.1  mrg #endif'
    183      1.1  mrg 
    184