Qucs-core  0.0.18
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cbesselj.cpp
Go to the documentation of this file.
1 /*
2  * cbesselj.cpp - Bessel function of first kind
3  *
4  * Copyright (C) 2007 Bastien Roucaries <roucaries.bastien@gmail.com>
5  *
6  * This is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This software is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this package; see the file COPYING. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  * $Id$
22  *
23  */
24 
60 //#if HAVE_CONFIG_H
61 //# include <config.h>
62 //#endif
63 //
64 //#include <cmath>
65 //#include <assert.h>
66 //#include <errno.h>
67 //#include <stdio.h>
68 //#include <stdlib.h>
69 //
70 //#include "real.h"
71 //#include "complex.h"
72 //#include "constants.h"
73 //#include "precision.h"
74 
75 #define SMALL_J0_BOUND 1e6
76 
78 #define SMALL_JN_BOUND 5.0
79 
81 #define BIG_JN_BOUND 25.0
82 
84 #define MAX_SMALL_ITERATION 2048
85 
86 
104 static nr_complex_t
106 {
107  nr_complex_t ak, Rk;
108  nr_complex_t R;
109  nr_complex_t R0;
110  unsigned int k;
111 
112  /* a_0 */
113  errno = 0;
114  ak = pow (0.5 * z, n);
115  /* underflow */
116  if (errno == ERANGE)
117  {
118  return n > 0 ? 0.0 : 1;
119  }
120 
121  ak = ak / (nr_double_t) qucs::factorial (n);
122 
123  /* R_0 */
124  R0 = ak * 1.0;
125  Rk = R0;
126  R = R0;
127 
128  for (k = 1; k < MAX_SMALL_ITERATION; k++)
129  {
130  ak = -(z * z) / (4.0 * k * (n + k));
131  Rk = ak * Rk;
132  if (fabs (real (Rk)) < fabs (real (R) * NR_EPSI) &&
133  fabs (imag (Rk)) < fabs (imag (R) * NR_EPSI))
134  return R;
135 
136  R += Rk;
137  }
138  /* impossible */
139  assert (k < MAX_SMALL_ITERATION);
140  abort ();
141 }
142 
143 
144 static nr_complex_t
146 {
147  nr_complex_t first, second;
148  nr_complex_t ak;
149 
150  unsigned int m;
151  unsigned int k;
152  nr_double_t t;
153  nr_double_t m1pna2;
154 
155  m = (2 * std::abs (z) + 0.25 * (n + std::abs (imag (z))));
156 
157  /* -1^(n/2) */
158  m1pna2 = (n / 2) % 2 == 0 ? 1.0 : -1.0;
159  first = (1.0 + m1pna2 * cos (z)) / (2.0 * m);
160 
161  second = 0.0;
162  for (k = 1; k <= m - 1; k++)
163  {
164  t = (k * M_PI) / (2 * m);
165  ak = cos (z * std::sin (t)) * std::cos (n * t);
166  second += ak;
167  }
168  return first + second / (nr_double_t) m;
169 }
170 
171 static nr_complex_t
173 {
174  nr_complex_t first, second;
175  nr_complex_t ak;
176 
177  unsigned int m;
178  unsigned int k;
179  nr_double_t t;
180  nr_double_t m1pn1a2;
181 
182  m = (2 * std::abs (z) + 0.25 * (n + std::abs (imag (z))));
183 
184  /* -1^(n/2) */
185  m1pn1a2 = ((n - 1) / 2) % 2 == 0 ? 1.0 : -1.0;
186  first = (m1pn1a2 * sin (z)) / (2.0 * m);
187 
188  second = 0.0;
189  for (k = 1; k <= m - 1; k++)
190  {
191  t = (k * M_PI) / (2 * m);
192  ak = std::sin (z * std::sin (t)) * std::sin (n * t);
193  second += ak;
194  }
195  return first + second / (nr_double_t) m;
196 }
197 
198 
199 static nr_complex_t
201 {
202  if (n % 2 == 0)
203  return cbesselj_mediumarg_odd (n, z);
204  else
205  return cbesselj_mediumarg_even (n, z);
206 }
207 
208 
209 
211 #define MAX_LARGE_ITERATION 430
212 
217 static nr_complex_t
219 {
220  nr_complex_t Pk, P0, P, Qk, Q0, Q_;
221  nr_complex_t tmp;
222  unsigned long num, denum;
223  nr_complex_t m1a8z2;
224  unsigned int k;
225  nr_double_t l, m;
226 
227  /* P0 & Q0 */
228  P0 = 1;
229  P = P0;
230  Pk = P0;
231 
232  Q0 = (4.0 * n * n - 1) / (8.0 * z);
233  Q_ = Q0;
234  Qk = Q0;
235 
236  m1a8z2 = (-1.0) / (8.0 * sqr (z));
237 
238  /* P */
239  for (k = 1;; k++)
240  {
241  /* Usually converge before overflow */
242  assert (k <= MAX_LARGE_ITERATION);
243 
244  num = (4 * sqr (n) - sqr (4 * k - 3)) * (4 * sqr (n) - (4 * k - 1));
245  denum = 2 * k * (2 * k - 1);
246  Pk = Pk * ((nr_double_t) num * m1a8z2) / ((nr_double_t) denum);
247 
248  if (real (Pk) < real (P0) * NR_EPSI &&
249  imag (Pk) < imag (P0) * NR_EPSI)
250  break;
251 
252  P += Pk;
253  }
254 
255  /* P */
256  for (k = 1;; k++)
257  {
258  /* Usually converge before overflow */
259  assert (k <= MAX_LARGE_ITERATION);
260 
261  num = (4 * sqr (n) - sqr (4 * k - 1)) * (4 * sqr (n) - (4 * k - 1));
262  denum = 2 * k * (2 * k - 1);
263  Qk = Qk * ((nr_double_t) num * m1a8z2) / ((nr_double_t) denum);
264 
265  if (real (Qk) < real (Q0) * NR_EPSI ||
266  imag (Qk) < imag (Q0) * NR_EPSI)
267  break;
268 
269  Q_ += Qk;
270  }
271 
272  /* l, m cf [5] eq (5) */
273  l = (n % 4 == 0) || (n % 4 == 3) ? 1.0 : -1.0;
274  m = (n % 4 == 0) || (n % 4 == 1) ? 1.0 : -1.0;
275 
276 
277  tmp = (l * P + m * Q_) * cos (z);
278  tmp += (m * P - l * Q_) * sin (z);
279  return tmp / sqrt (M_PI * z);
280 }
281 
286 cbesselj (unsigned int n, nr_complex_t z)
287 {
288  nr_double_t mul = 1.0;
289  nr_complex_t ret;
290 
291  /* J_n(-z)=(-1)^n J_n(z) */
292  /*
293  if(real(z) < 0.0)
294  {
295  z = -z;
296  mul = (n % 2) == 0 ? 1.0 : -1.0 ;
297  }
298  */
299  if (abs (z) < SMALL_JN_BOUND)
300  ret = cbesselj_smallarg (n, z);
301  else if (abs (z) > BIG_JN_BOUND)
302  ret = cbesselj_largearg (n, z);
303  else
304  ret = cbesselj_mediumarg (n, z);
305 
306  return mul * ret;
307 }
static nr_complex_t cbesselj_largearg(unsigned int n, nr_complex_t z)
besselj for large argument
Definition: cbesselj.cpp:218
std::complex< nr_double_t > nr_complex_t
Definition: complex.h:31
l
Definition: parse_vcd.y:213
matrix real(matrix a)
Real part matrix.
Definition: matrix.cpp:568
matrix abs(matrix a)
Computes magnitude of each matrix element.
Definition: matrix.cpp:531
static nr_complex_t cbesselj_smallarg(unsigned int n, nr_complex_t z)
Definition: cbesselj.cpp:105
static nr_complex_t cbesselj_mediumarg_odd(unsigned int n, nr_complex_t z)
Definition: cbesselj.cpp:145
nr_complex_t pow(const nr_complex_t z, const nr_double_t d)
Compute power function with real exponent.
Definition: complex.cpp:238
nr_complex_t cos(const nr_complex_t z)
Compute complex cosine.
Definition: complex.cpp:57
t
Definition: parse_vcd.y:290
n
Definition: parse_citi.y:147
#define MAX_LARGE_ITERATION
num of P(k) (n = 8) will overlow above this value
Definition: complex.cpp:212
#define SMALL_JN_BOUND
use ascending serie below this magnitude
Definition: complex.cpp:79
#define R(con)
nr_complex_t sqr(const nr_complex_t z)
Square of complex number.
Definition: complex.cpp:673
matrix imag(matrix a)
Imaginary part matrix.
Definition: matrix.cpp:581
nr_complex_t sqrt(const nr_complex_t z)
Compute principal value of square root.
Definition: complex.cpp:271
#define BIG_JN_BOUND
use assymptotic expression above this magnitude
Definition: complex.cpp:82
nr_complex_t sin(const nr_complex_t z)
Compute complex sine.
Definition: complex.cpp:66
nr_complex_t cbesselj(unsigned int n, nr_complex_t z)
Main entry point for besselj function.
Definition: cbesselj.cpp:286
static nr_complex_t cbesselj_mediumarg(unsigned int n, nr_complex_t z)
Definition: cbesselj.cpp:200
#define M_PI
Archimedes' constant ( )
Definition: consts.h:47
#define MAX_SMALL_ITERATION
Arbitrary value for iteration.
Definition: complex.cpp:85
unsigned int factorial(unsigned int n)
Compute factorial n ie $n!$.
Definition: real.cpp:444
static nr_complex_t cbesselj_mediumarg_even(unsigned int n, nr_complex_t z)
Definition: cbesselj.cpp:172