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