bessel.m4 revision 1.1 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-2019 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