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