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