xref: /netbsd-src/external/gpl3/gcc.old/dist/libgfortran/m4/bessel.m4 (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1627f7eb2Smrg`/* Implementation of the BESSEL_JN and BESSEL_YN transformational
2627f7eb2Smrg   function using a recurrence algorithm.
3*4c3eb207Smrg   Copyright (C) 2010-2020 Free Software Foundation, Inc.
4627f7eb2Smrg   Contributed by Tobias Burnus <burnus@net-b.de>
5627f7eb2Smrg
6627f7eb2SmrgThis file is part of the GNU Fortran runtime library (libgfortran).
7627f7eb2Smrg
8627f7eb2SmrgLibgfortran is free software; you can redistribute it and/or
9627f7eb2Smrgmodify it under the terms of the GNU General Public
10627f7eb2SmrgLicense as published by the Free Software Foundation; either
11627f7eb2Smrgversion 3 of the License, or (at your option) any later version.
12627f7eb2Smrg
13627f7eb2SmrgLibgfortran is distributed in the hope that it will be useful,
14627f7eb2Smrgbut WITHOUT ANY WARRANTY; without even the implied warranty of
15627f7eb2SmrgMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16627f7eb2SmrgGNU General Public License for more details.
17627f7eb2Smrg
18627f7eb2SmrgUnder Section 7 of GPL version 3, you are granted additional
19627f7eb2Smrgpermissions described in the GCC Runtime Library Exception, version
20627f7eb2Smrg3.1, as published by the Free Software Foundation.
21627f7eb2Smrg
22627f7eb2SmrgYou should have received a copy of the GNU General Public License and
23627f7eb2Smrga copy of the GCC Runtime Library Exception along with this program;
24627f7eb2Smrgsee the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25627f7eb2Smrg<http://www.gnu.org/licenses/>.  */
26627f7eb2Smrg
27627f7eb2Smrg#include "libgfortran.h"'
28627f7eb2Smrg
29627f7eb2Smrginclude(iparm.m4)dnl
30627f7eb2Smrginclude(`mtype.m4')dnl
31627f7eb2Smrg
32627f7eb2Smrgmathfunc_macro
33627f7eb2Smrg
34627f7eb2Smrg`#if defined (HAVE_'rtype_name`)
35627f7eb2Smrg
36627f7eb2Smrg
37627f7eb2Smrg
38627f7eb2Smrg#if 'hasmathfunc(jn)`
39627f7eb2Smrgextern void bessel_jn_r'rtype_kind` ('rtype` * const restrict ret, int n1,
40627f7eb2Smrg				     int n2, 'rtype_name` x);
41627f7eb2Smrgexport_proto(bessel_jn_r'rtype_kind`);
42627f7eb2Smrg
43627f7eb2Smrgvoid
44627f7eb2Smrgbessel_jn_r'rtype_kind` ('rtype` * const restrict ret, int n1, int n2, 'rtype_name` x)
45627f7eb2Smrg{
46627f7eb2Smrg  int i;
47627f7eb2Smrg  index_type stride;
48627f7eb2Smrg
49627f7eb2Smrg  'rtype_name` last1, last2, x2rev;
50627f7eb2Smrg
51627f7eb2Smrg  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
52627f7eb2Smrg
53627f7eb2Smrg  if (ret->base_addr == NULL)
54627f7eb2Smrg    {
55627f7eb2Smrg      size_t size = n2 < n1 ? 0 : n2-n1+1;
56627f7eb2Smrg      GFC_DIMENSION_SET(ret->dim[0], 0, size-1, 1);
57627f7eb2Smrg      ret->base_addr = xmallocarray (size, sizeof ('rtype_name`));
58627f7eb2Smrg      ret->offset = 0;
59627f7eb2Smrg    }
60627f7eb2Smrg
61627f7eb2Smrg  if (unlikely (n2 < n1))
62627f7eb2Smrg    return;
63627f7eb2Smrg
64627f7eb2Smrg  if (unlikely (compile_options.bounds_check)
65627f7eb2Smrg      && GFC_DESCRIPTOR_EXTENT(ret,0) != (n2-n1+1))
66627f7eb2Smrg    runtime_error("Incorrect extent in return value of BESSEL_JN "
67627f7eb2Smrg		  "(%ld vs. %ld)", (long int) n2-n1,
68627f7eb2Smrg		  (long int) GFC_DESCRIPTOR_EXTENT(ret,0));
69627f7eb2Smrg
70627f7eb2Smrg  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
71627f7eb2Smrg
72627f7eb2Smrg  if (unlikely (x == 0))
73627f7eb2Smrg    {
74627f7eb2Smrg      ret->base_addr[0] = 1;
75627f7eb2Smrg      for (i = 1; i <= n2-n1; i++)
76627f7eb2Smrg        ret->base_addr[i*stride] = 0;
77627f7eb2Smrg      return;
78627f7eb2Smrg    }
79627f7eb2Smrg
80627f7eb2Smrg  last1 = MATHFUNC(jn) (n2, x);
81627f7eb2Smrg  ret->base_addr[(n2-n1)*stride] = last1;
82627f7eb2Smrg
83627f7eb2Smrg  if (n1 == n2)
84627f7eb2Smrg    return;
85627f7eb2Smrg
86627f7eb2Smrg  last2 = MATHFUNC(jn) (n2 - 1, x);
87627f7eb2Smrg  ret->base_addr[(n2-n1-1)*stride] = last2;
88627f7eb2Smrg
89627f7eb2Smrg  if (n1 + 1 == n2)
90627f7eb2Smrg    return;
91627f7eb2Smrg
92627f7eb2Smrg  x2rev = GFC_REAL_'rtype_kind`_LITERAL(2.)/x;
93627f7eb2Smrg
94627f7eb2Smrg  for (i = n2-n1-2; i >= 0; i--)
95627f7eb2Smrg    {
96627f7eb2Smrg      ret->base_addr[i*stride] = x2rev * (i+1+n1) * last2 - last1;
97627f7eb2Smrg      last1 = last2;
98627f7eb2Smrg      last2 = ret->base_addr[i*stride];
99627f7eb2Smrg    }
100627f7eb2Smrg}
101627f7eb2Smrg
102627f7eb2Smrg#endif
103627f7eb2Smrg
104627f7eb2Smrg#if 'hasmathfunc(yn)`
105627f7eb2Smrgextern void bessel_yn_r'rtype_kind` ('rtype` * const restrict ret,
106627f7eb2Smrg				     int n1, int n2, 'rtype_name` x);
107627f7eb2Smrgexport_proto(bessel_yn_r'rtype_kind`);
108627f7eb2Smrg
109627f7eb2Smrgvoid
110627f7eb2Smrgbessel_yn_r'rtype_kind` ('rtype` * const restrict ret, int n1, int n2,
111627f7eb2Smrg			 'rtype_name` x)
112627f7eb2Smrg{
113627f7eb2Smrg  int i;
114627f7eb2Smrg  index_type stride;
115627f7eb2Smrg
116627f7eb2Smrg  'rtype_name` last1, last2, x2rev;
117627f7eb2Smrg
118627f7eb2Smrg  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
119627f7eb2Smrg
120627f7eb2Smrg  if (ret->base_addr == NULL)
121627f7eb2Smrg    {
122627f7eb2Smrg      size_t size = n2 < n1 ? 0 : n2-n1+1;
123627f7eb2Smrg      GFC_DIMENSION_SET(ret->dim[0], 0, size-1, 1);
124627f7eb2Smrg      ret->base_addr = xmallocarray (size, sizeof ('rtype_name`));
125627f7eb2Smrg      ret->offset = 0;
126627f7eb2Smrg    }
127627f7eb2Smrg
128627f7eb2Smrg  if (unlikely (n2 < n1))
129627f7eb2Smrg    return;
130627f7eb2Smrg
131627f7eb2Smrg  if (unlikely (compile_options.bounds_check)
132627f7eb2Smrg      && GFC_DESCRIPTOR_EXTENT(ret,0) != (n2-n1+1))
133627f7eb2Smrg    runtime_error("Incorrect extent in return value of BESSEL_JN "
134627f7eb2Smrg		  "(%ld vs. %ld)", (long int) n2-n1,
135627f7eb2Smrg		  (long int) GFC_DESCRIPTOR_EXTENT(ret,0));
136627f7eb2Smrg
137627f7eb2Smrg  stride = GFC_DESCRIPTOR_STRIDE(ret,0);
138627f7eb2Smrg
139627f7eb2Smrg  if (unlikely (x == 0))
140627f7eb2Smrg    {
141627f7eb2Smrg      for (i = 0; i <= n2-n1; i++)
142627f7eb2Smrg#if defined('rtype_name`_INFINITY)
143627f7eb2Smrg        ret->base_addr[i*stride] = -'rtype_name`_INFINITY;
144627f7eb2Smrg#else
145627f7eb2Smrg        ret->base_addr[i*stride] = -'rtype_name`_HUGE;
146627f7eb2Smrg#endif
147627f7eb2Smrg      return;
148627f7eb2Smrg    }
149627f7eb2Smrg
150627f7eb2Smrg  last1 = MATHFUNC(yn) (n1, x);
151627f7eb2Smrg  ret->base_addr[0] = last1;
152627f7eb2Smrg
153627f7eb2Smrg  if (n1 == n2)
154627f7eb2Smrg    return;
155627f7eb2Smrg
156627f7eb2Smrg  last2 = MATHFUNC(yn) (n1 + 1, x);
157627f7eb2Smrg  ret->base_addr[1*stride] = last2;
158627f7eb2Smrg
159627f7eb2Smrg  if (n1 + 1 == n2)
160627f7eb2Smrg    return;
161627f7eb2Smrg
162627f7eb2Smrg  x2rev = GFC_REAL_'rtype_kind`_LITERAL(2.)/x;
163627f7eb2Smrg
164627f7eb2Smrg  for (i = 2; i <= n2 - n1; i++)
165627f7eb2Smrg    {
166627f7eb2Smrg#if defined('rtype_name`_INFINITY)
167627f7eb2Smrg      if (unlikely (last2 == -'rtype_name`_INFINITY))
168627f7eb2Smrg	{
169627f7eb2Smrg	  ret->base_addr[i*stride] = -'rtype_name`_INFINITY;
170627f7eb2Smrg	}
171627f7eb2Smrg      else
172627f7eb2Smrg#endif
173627f7eb2Smrg	{
174627f7eb2Smrg	  ret->base_addr[i*stride] = x2rev * (i-1+n1) * last2 - last1;
175627f7eb2Smrg	  last1 = last2;
176627f7eb2Smrg	  last2 = ret->base_addr[i*stride];
177627f7eb2Smrg	}
178627f7eb2Smrg    }
179627f7eb2Smrg}
180627f7eb2Smrg#endif
181627f7eb2Smrg
182627f7eb2Smrg#endif'
183627f7eb2Smrg
184