Le samedi 19 janvier 2008, Mengda Wu a écrit :
> Hi gsler,
>
>    Is there a way in GSL to calculate bessel functions with complex numbers
> as input? It seems only real numbers are supported.

Here the bessel file. #if 0 some code that I have not finished...
>
> Thanks,
> Mengda
> _______________________________________________
> Help-gsl mailing list
> [email protected]
> http://lists.gnu.org/mailman/listinfo/help-gsl



-- 

"ROUCARIES Bastien"
                                                   [EMAIL PROTECTED]
-------------------------------------------------------------------------------
DO NOT WRITE TO [EMAIL PROTECTED] OR BE BLACKLISTED
/* Compute bessel function of first kind
 * Copyright (C) 2006 Bastien ROUCARIES
 *
 * COPYRIGHT NOTICE (README  FIRST)
 * ********************************
 *
 * The copyright of this file is quite COMPLICATED:
 * THIS FILE is put by me bastien ROUCARIES under the 
 * LGPL licence 
 * BUT because I use bessel_I0 and bessel_I1 
 * from gsl this file becomes de facto GPL
 * 
 * I would prefere to use a pure LGPL license, but I lack time 
 * to rewrite all the GPL function. 
 * If you think GPL is too strong,
 * you MUST rewrite the following function and this file will
 * become LGPL:
 * 
 * 
 *
 * COPYRIGHT FOR THIS FILE ALONE
 * *****************************
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * COPYRIGHT FOR EXECUTE AND LINKING THIS FILE (DO SOMETHING USEFUL)
 * *****************************************************************
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

/* Please send comments to roucaries.bastien+mathsoft at gmail.com
 *
 * ABOUT SPAM and SPAM BOT
 * If you want to send me spam (you don't and by UE law forbid you to do so)
 * please send me a mail to my kill list address 
 * [EMAIL PROTECTED]
 * END SPAM and SPAM BOT section
 */

/*!\file cbesseljn.c
   \brief compute complex bessel J function
 
  References:

  [1]  Bessel function of the first kind with complex argument
       Yousif, Hashim A.; Melka, Richard
       Computer Physics Communications, vol. 106, Issue 3, pp.199-206
       11/1997, ELSEVIER, doi://10.1016/S0010-4655(97)00087-8
      
  [2]  Handbook of Mathematical Functions with
       Formulas, Graphs, and Mathematical Tables
       Milton Abramowitz and Irene A. Stegun
       public domain (work of US government)
       online http://www.math.sfu.ca/~cbm/aands/

  [3]  Mathematica Manual
       Bessel, Airy, Struve Functions> BesselJ[nu,z]
       > General characteristics> Symmetries and periodicities
       http://functions.wolfram.com/BesselAiryStruveFunctions/BesselJ/04/02/01/

  [4]  Mathematica Manual
       Bessel, Airy, Struve Functions> BesselJ[nu,z]
       Representations through equivalent functions 
       http://functions.wolfram.com/BesselAiryStruveFunctions/BesselJ/27/ShowAll.html

  [5]  Algorithms for the evaluation of Bessel functions 
       of complex argument and integer orders
       G. D. C. Kuiken
       Applied Mathematics Letters, Volume 2, Issue 4, 
       1989,  Pages 353-356
       doi://10.1016/0893-9659(89)90086-4

  [6]  The numerical computation of Bessel functions of the 
       first and second kind for integer orders and complex arguments
       du Toit, C.F.  
       Antennas and Propagation, IEEE Transactions on,
       Volume 38,  Issue 9
       Sep 1990 pages 1341-1349
       doi://10.1109/8.56985      

  [7]  "Bessel Function of the First Kind."
       Weisstein, Eric W. 
       From MathWorld--A Wolfram Web Resource. 
       online http://mathworld.wolfram.com/BesselFunctionoftheFirstKind.html

  [8]  Kahan summation algorithm
       Wikipedia
       http://en.wikipedia.org/wiki/Kahan_summation_algorithm
   
  [9]  Integer sequence A000142
       Factorial numbers: n! = 1*2*3*4*...*n
       http://www.research.att.com/~njas/sequences/table?a=142&fmt=4

  [10] N. M. Temme
       Numerical algorithms for uniform {Airy-type} asymptotic expansions
       Numerical Algorithms 
       Volume 15, Issue 2
       pages 207-225
       1997
       online http://citeseer.ist.psu.edu/temme97numerical.html
*/

/* we use special algorithm what do not like optimization */
//#pragma STDC FP_CONTRACT OFF
//#pragma STDC CX_LIMITED_RANGE OFF


#include <complex.h>
#include <math.h>
#include <float.h>
#include <fenv.h>
#include <limits.h>

#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

#include <stdbool.h>

#include "debug.h"
//#define NDEBUG


#define cprint(x) creal(x), cimag(x)
#define fmtc "%+4.4e%+4.4e*j"

#define forget(a) do {} while(0)  

// __asm__ __volatile__ ("" :"=m" (a) :"m" (a))



/*!\brief Force a compilation error if condition is true */
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))


#define max(x,y) x < y ? y : x
#define sqr(x) ((x) * (x))
#define norm(z) (sqr(creal(z))+sqr(cimag(z)))
#define SQR_DBL_EPSILON sqr(DBL_EPSILON)
//#define norm(z) (cabs(z))
//#define SQR_DBL_EPSILON (DBL_EPSILON)


#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))

#define SMALL_J0_BOUND 1e6

/*!\brief use ascending serie below this magnitude */
#define SMALL_JN_BOUND 5.0

/*!\brief use assymptotic expression above this magnitude */
#define BIG_JN_BOUND 25.0

/*!\brief Tolerance for assert bound checking */
#define TOL_JN_BOUND 1e-2

/*!\brief Arbitrary value for iteration*/
#define MAX_SMALL_ITERATION 1024

/*!\brief Max order for direct approximation */
#define MAX_DIRECT_ORDER 8


/*!\brief Kahan algorithm for summation 

   For better understanding see [8]
   \todo move to header
*/
static inline complex kahanaddcomplex(complex R, complex Rk, complex *correction)
{
  complex corrected_next_term;
  complex new_sum;

  corrected_next_term = Rk - *(correction);
  forget(corrected_next_term);

  new_sum = R + corrected_next_term;
  forget(new_sum);

  *correction = (new_sum - R) - corrected_next_term;
  forget(*correction);

  return new_sum;
}


/*\brief The first factorial (\f$n!\f$) 0 to MAXORDER */
static const unsigned long int factorialarray[] =  
  { 1, 1, 2, 6, 24, 120, 720, 5040, 40320 };

#ifdef KAHAN_SMALL_ARGUMENT
#define declaresmallcorrection(a) complex a = 0.0
#define addsmallRandRk(a, b, c) kahanaddcomplex((a),(b),(c))
#else
#define declaresmallcorrection(a) do {} while(0)
/*!\brief Return a + b (corrected by c if using Kahan correction) */
#define addsmallRandRk(a, b, c) ((a) + (b))
#endif


/*!\brief Implement bessel J function for small arguments
    according to [5]

    For small argument we use the following formulae:
    \f[
    J_n(z)=\sum_0^\infty R_k
    \f]
    Where:
    \f{align*}
    R_{-1}&=1 & R_k &= a_k R_{k-1} \\
    a_0&=\frac{\left(\frac{1}{2}z\right)^n}{n!} &
    a_{+k}&=\frac{-\frac{1}{4} z^2}{k(n+k)}
    \f}
    
    This formula is derivated of [2] eq 9.1.10 p 360:
    \f[
    J_n(z)=(\frac{1}{2}z)^n 
            \sum_{k=0}^\infty \frac{(-\frac{1}{4}z^2)^k}{k!\Gamma(n+k+1)}
    \f]
    \note Precision is evaluated to be more than 1e-13

    \param[in] n order
    \param[in] z input argument
    \note could implement kahan sum if KAHAN_SMALL_ARGUMENT=1
    \todo Check if Kahan summation improve precision
*/
static complex cbesseljn_smallarg (unsigned int n, complex z)
{
  complex ak, Rk;
  complex R;
  complex R0;
  unsigned short int k;
  /* for 4 * k * (n + k) */
  unsigned long diviser;

  /* For Kahan sum */
  declaresmallcorrection(correction);

  assert(cabs(z) < SMALL_JN_BOUND * ( 1 + TOL_JN_BOUND ));
  assert(creal(z) >= 0 && cimag(z) >= 0);
  assert(n <= MAX_DIRECT_ORDER);
 
  /* Do not overflow diviser = 4 * k * (k + n) */
  BUILD_BUG_ON(4 * MAX_SMALL_ITERATION * 
	       (MAX_DIRECT_ORDER + MAX_SMALL_ITERATION) >= ULONG_MAX );
  BUILD_BUG_ON(ARRAY_SIZE(factorialarray) != MAX_DIRECT_ORDER + 1);

  /* a_0 */
  errno = 0;
  ak = cpow (0.5 * z, n);

  /* underflow
     NB: errno and exception is propagated from cpow
   */
  if (errno == ERANGE)
    goto underflow;

  if (norm(ak) < sqr(DBL_MIN * factorialarray[n]))
  { 
    /* do the computation if we are 
       lucky we get a subnormal */
    ak = ak / factorialarray[n];
    goto fullunderflow;
  }
  ak = ak / factorialarray[n];

  /* R_0 */
  R0 = ak * 1.0;
  Rk = R0;
  R = R0;
  DEBUG ("a%-4i: " fmtc " R%-4i: " fmtc " R: " fmtc "\n",
	 0, cprint (ak), 0, cprint (Rk), cprint (R));

  for (k = 1; k < MAX_SMALL_ITERATION; k++)
    {
      assert (k < MAX_SMALL_ITERATION - 1);
      
      diviser = (4 * k * (n + k));
      ak = - sqr(z) / diviser;
      Rk = ak * Rk;

      DEBUG("a%-4i: " fmtc " R%-4i: " fmtc " R: " fmtc "\n",
	     k, cprint (ak), k, cprint (Rk), cprint (R));

      if (norm(Rk) < norm(R) * SQR_DBL_EPSILON/2)
	return R;

      /* R += Rk */
      R = addsmallRandRk(R, Rk, &correction);
    }

  /* not converged */
  errno = ERANGE;
  (void) feraiseexcept(FE_INVALID);
  return R;

 fullunderflow:
  DEBUG ("Underflow\n");
  errno = ERANGE;
  (void) feraiseexcept(FE_UNDERFLOW);
  return ak;

 underflow:
  DEBUG ("Underflow\n");
  return n > 0 ? 0.0 : 1;
}

#ifdef KAHAN_MEDIUM_ARGUMEMENT
#define addmediumsumandak(a, b, c) kahanaddcomplex((a),(b),(c))
#define declaremediumcorrection(a) complex a = 0.0
#else
/*!\brief Return a + b (corrected by c if using Kahan correction) */
#define addmediumsumandak(a, b, c) ((a) + (b))
#define declaremediumcorrection(a) do {} while(0)
#endif


/*!\brief Compute besselj for complex moderate argument 
          and integer even order using poisson expansion

	  According to [5] eq (7) for moderate argument and even order
	  \f[
	  J_n(z) = \frac{1+(-1)^\frac{n}{2}\cos z}{2m}
                   + \frac{1}{m} \sum_{k=1}^{m-1} \cos (z sin t) cos (nt)
	  \f]
	  Where \f$t\f$ is defined by:
	  \f[
	  t=\frac{k\pi}{2m}
	  \f]
	  And \f$m\f$ is an integer such as:
	  \f[
	  m \ge 2 * |z| + \frac{1}{4} (n + |\Im\text{m}\; z|)
	  \f]
	  In order to improve precision tranform 
	  \f$1+(-1)^\frac{n}{2}\cos z\f$ to:
	  \f[
	  \begin{cases}
	  2\cos^2\frac{z}{2} & \text{if } \frac{n}{2} \text{ even}  \\
	  2\sin^2\frac{z}{2} & \text{else}
	  \end{cases}
	  \f]
	  Therefore we could transform the evaluated expression
	  to:
	  \f[
	  \begin{cases}
	  \frac{1}{m}\left[ \cos^2\frac{z}{2} 
	      + \sum_{k=1}^{m-1} \cos (z sin t) cos (nt) \right] & 
                \text{if } \frac{n}{2} \text{ even} \\
	  \frac{1}{m}\left[ \sin^2\frac{z}{2} 
	      + \sum_{k=1}^{m-1} \cos (z sin t) cos (nt) \right] & 
                \text{else} 
	  \end{cases}
	  \f]

	  \note Precision is evaluated to be better than 1e-13
	  \note use even m for better precision
	  \note USe 1/2 instead of 1/4 before n (better precision)
*/
static complex cbesseljn_mediumarg_even (unsigned int n, complex z)
{
  complex sum;
  complex ak;

  unsigned int m;
  unsigned int k;
  double t;

  /* For Kahan sum */
  declaremediumcorrection(correction);

  assert(n % 2 == 0);
  BUILD_BUG_ON(2 * BIG_JN_BOUND 
	       + 0.5 * ( MAX_DIRECT_ORDER  + BIG_JN_BOUND) >= UINT_MAX);

  /* use conservative measurement (m even give better error) */
  m = ceil(2 * cabs (z) + 0.5 * (n + fabs (cimag (z))));
  m = m % 2 == 0 ? m  : m + 1;
  
  DEBUG("m=%li", (long) m);

  /* compute (1 + (-1)^n cos(z)) / 2 */
  if(n % 4 == 0)
    /* Use 2 cos^2 (z/2) = (1 + cos z) */
    sum = sqr(ccos(z/2));
  else
    /* use 2 sin^2 (z/2) = 1 - cos(z) */
    sum = sqr(csin(z/2));

  DEBUG("a%-3i=" fmtc " sum=" fmtc "\n", 0, cprint(sum), cprint(sum));
  for (k = 1; k <= m - 1; k++)
    {
      t = (k * M_PI_2) / m;
      ak = ccos (z * sin (t)) * cos (n * t);
      /* R += ak */
      sum = addmediumsumandak(sum, ak, &correction);

      DEBUG("a%-3i=" fmtc " sum=" fmtc "\n", k, cprint(ak), cprint(sum));
    }
  /* first+= second */
  return sum / m;
}

/*!\brief Compute besselj for complex moderate argument 
          and integer odd order using poisson expansion

	  According to [5] eq (7) for moderate argument and odd order
	  \f[
	  J_n(z) = \frac{(-1)^\frac{n-1}{2}\sin z}{2m}
                   + \frac{1}{m} \sum_{k=1}^{m-1} \sin (z sin t) sin (nt)
	  \f]
	  Where \f$t\f$ is defined by:
	  \f[
	  t=\frac{k\pi}{2m}
	  \f]
	  And \f$m\f$ is an integer such as:
	  \f[
	  m \ge 2 |z| + \frac{1}{4} (n + |\Im\text{m}\; z|)
	  \f]

	  \note Precision is evaluated to be better than 1e-13
	  \note use even m for better precision
	  \note USe 1/2 instead of 1/4 before n (better precision)
*/
static complex cbesseljn_mediumarg_odd (unsigned int n, complex z)
{
  complex sum;
  complex ak;

  unsigned int m;
  unsigned int k;
  double t;

  /* For Kahan sum */
  declaremediumcorrection(correction);

  assert(n % 2 == 1);
  BUILD_BUG_ON(2 * BIG_JN_BOUND 
	       + 0.5 * ( MAX_DIRECT_ORDER  + BIG_JN_BOUND) >= UINT_MAX);

  /* use conservative measurement (m even give better error) */
  m = ceil(2 * cabs (z) + 0.5 * (n + fabs (cimag (z))));
  m = m % 2 == 0 ? m  : m + 1;

  sum = csin (z) / (2); 
  /* -1^((n-1)/2) */
  sum = (n - 1) % 4 == 0 ? sum : - sum;

  DEBUG("a%-3i=" fmtc " sum=" fmtc "\n", 0, cprint(sum), cprint(sum));
  for (k = 1; k <= m - 1; k++)
    {
      t = (k * M_PI_2) / m;
      ak = csin (z * sin (t)) * sin (n * t);

      /* sum +=  ak*/
      sum = addmediumsumandak(sum, ak, &correction);

      DEBUG("a%-3i=" fmtc " sum=" fmtc "\n", 0, cprint(sum), cprint(sum));
    }

  return sum / m;
}

/*!\brief Compute besselj for complex moderate argument 
          and integer order using poisson expansion
*/
static complex cbesseljn_mediumarg (unsigned int n, complex z)
{
  assert(cabs(z) > SMALL_JN_BOUND * ( 1 - TOL_JN_BOUND ));
  assert(cabs(z) < BIG_JN_BOUND * ( 1 + TOL_JN_BOUND ));
  assert(creal(z) >= 0 && cimag(z) >= 0);
  assert(n <= MAX_DIRECT_ORDER);

  if (n % 2 == 0)
    return cbesseljn_mediumarg_even (n, z);
  else
    return cbesseljn_mediumarg_odd (n, z);
}


/*! \brief max iteration avoid overflow*/
#define MAX_LARGE_ITERATION 100

#ifdef KAHAN_LARGE_ARGUMEMENT
#define addlargesumandak(a, b, c) kahanaddcomplex((a),(b),(c))
#define declarelargecorrection(a) complex a = 0.0
#else
/*!\brief Return a + b (corrected by c if using Kahan correction) */
#define addlargesumandak(a, b, c) ((a) + (b))
#define declarelargecorrection(a) do {} while(0)
#endif


/*!\brief besselj for large argument 
  
    According to [6] eq (23), (25), (26) 
    based on [2] eq (9.2.5), (9.2.9), (9.2.10) p 364, 
    for \f$|z|\rightarrow\infty\f$ and
    \f$\operatorname{arg} z < \pi\f$:
    \f[
    J_n(v)=\sqrt{\frac{2}{\pi z}} \left[
              P_n cos \left(z - \frac{n\pi}{2} - \frac{\pi}{4}\right)
	     -Q_n sin \left(z - \frac{n\pi}{2} - \frac{\pi}{4}\right)
	     \right]
    \f]
    Where:
    \f{align*}
    P_n(z)&= 1 + \sum_{k=1}^\infty (-1)^k
                 \dfrac{
		   \prod_{r=1}^{2k}\displaylimits
		      \left[4n^2 - (2r - 1) \right]}
		      {(2k)!(8z)^{2k}} \\
    Q_n(z)&= \sum_{k=0}^\infty (-1)^k
                 \dfrac{
		      \prod\limits_{r=1}^{2k+1}
		      \left[4n^2 - (2r - 1) \right]}
		      {(2k+1)!(8z)^{2k+1}} \\
    \f}
    First for n integer we sould note that:
    \f{align*}
    \cos \left(z - \frac{n\pi}{2} - \frac{\pi}{4}\right)&=
    \frac{1}{\sqrt{2}}\cos \left(z - \frac{n\pi}{2}\right)
    + \frac{1}{\sqrt{2}}\sin \left(z - \frac{n\pi}{2}\right) \\
    \sin \left(z - \frac{n\pi}{2} - \frac{\pi}{4}\right)&=
    \frac{1}{\sqrt{2}}\sin \left(z - \frac{n\pi}{2}\right)
    - \frac{1}{\sqrt{2}}\cos \left(z - \frac{n\pi}{2}\right)
    \f}
    Let \f$l,m\f$ such as:
    \f{align*}
    l &= \begin{cases}
         +1 & \text{if } n\mod 4 \equiv 0,3 \\
	 -1 & \text{ else}
	 \end{cases}\\
    m &= \begin{cases}
         +1 & \text{if } n\mod 4 \equiv 0,1 \\
	 -1 & \text{ else}
	 \end{cases}
    \f}
    Therefore we find eq (5) of [5]:
    \f[
    \boxed{
    J_n(z)= \frac{1}{\sqrt{\pi z}} \left[
               (lP_n + mQ_n)  \cos z 
             + (mP_n - lQ_n)  \sin z
	     \right]
    }
    \f]
    Moreover we could rewrite \f$P_n\f$ using recursivity 
    (see also [5] p 354):
    \f{align*}
    P_n(z)&=\sum_{k=0}^\infty P'_k &
    P'_0&=1 &
    P'_k&=P'_{k-1} 
          \frac{\left[4n^2 + (4k - 3)^2\right]
                \left[4n^2 + (4k - 1)^2\right]}
	       {2k(2k-1)} \frac{1}{-64z^2}
    \f}
    And for \f$Q_n\f$ (see also [5] p 354)
    \f{align*}
    Q_n(z)&=\sum_{k=0}^\infty P'_k &
    Q'_0&=\frac{4n^2-1}{8z} &
    Q'_k&=Q'_{k-1} 
          \frac{\left[4n^2 + (4k - 1)^2\right]
                \left[4n^2 + (4k + 1)^2\right]}
	       {2k(2k+1)} \frac{1}{-64z^2}
    \f}
   
    \note assert \f$|z| > 2 z^2 \f$
    \note [5] as a typo, \f$8z^2\f$ should be read \f$(8z)^2\f$ 

    \note valid only if \f$\Re\text{e}\; z > 0 \f$ (asserted)
          see [6]
    \note Please note that the serie is not convergent
    \note According to remark on page 364 afer (9.2.10)
    of [6] the sum of remainder terms
    in \f$P\f$ and \f$Q\f$ after rank \f$k\f$ 
    is lesser than respectively \f$Pk\f$ and 
    \f$Qk\f$ if \f$k >\frac{1}{2}n - \frac{1}{4}\f$ for \f$P\f$
    and\f$k >\frac{1}{2}n - \frac{3}{4}\f$ for \f$Q\f$.
    \note According to eq (56) reference [7] this expansion is valid 
    for \f$|z| \gg |m^2 - \frac{1}{4}|\f$. We assert
    \f$|z| > 10 |m^2 - \frac{1}{4}|\f$
    
*/
static complex
cbesseljn_largearg (unsigned int n, complex z)
{
  complex Pk, Pkm1, P, Qk, Qkm1, Q;
  complex tmp;
  double denum;
  double num;
  complex m8z2;
  unsigned int k;
  double l, m;
  double mu;

  declarelargecorrection(correctionP);
  declarelargecorrection(correctionQ);

  // for debuging using remark of [6]
  double esterr;
  bool trust;

  assert(creal(z) >= 0);
  assert(cabs(z) >= BIG_JN_BOUND * ( 1 - TOL_JN_BOUND ));
  assert(norm(z) >= norm(sqr(n) - 1/4) || n <= 8);
  assert(creal(z) >= 0 && cimag(z) >= 0);
  /* overflow check */
  assert(4.0 * sqr((double) n) < UINT_MAX);

  mu = 4 * sqr(n);

  /* P0 & Q0 */
  Pk = 1;
  P = Pk;
  Pkm1 = Pk;
  
  Qk = (mu - 1.0) / (8.0 * z);
  Q = Qk;
  Qkm1 = Qk;
  m8z2 = (-64.0 * sqr (z));

  /* P */
  for (k = 1; k < MAX_LARGE_ITERATION; k++)
    {
      /* Usually converge before overflow */
      assert (k <= MAX_LARGE_ITERATION - 1);

      num = (mu - sqr (4 * k - 3)) * (mu - sqr(4 * k - 1));
      denum = 2 * k * (2 * k - 1);
      Pk = (Pk * num) / (denum * m8z2);

      DEBUG("num=%e denum=%e"
            " P=" fmtc " Pk=" fmtc "\n", 
	    num, denum , cprint(P), cprint(Pk));

      if (norm(Pk) > norm(Pkm1) || 
	   norm(Pk) < norm(P) * SQR_DBL_EPSILON)
	  break;
      Pkm1 = Pk;
      P = addlargesumandak(P, Pk, &correctionP);
    }

  trust = k - 1 > 0.5  * n - 0.25;

  /* Q */
  for (k = 1;k < MAX_LARGE_ITERATION; k++)
    {
      /* Usually converge before overflow */
      assert (k <= MAX_LARGE_ITERATION - 1);

      num = (mu - sqr (4 * k - 1)) * (mu - sqr(4 * k + 1));
      denum = 2 * k  * (2 * k + 1);
      Qk = (Qk * num) / (denum * m8z2);
      
      
      DEBUG("num=%e denum=%e"
            " Q=" fmtc " Qk=" fmtc "\n", 
	    num, denum , cprint(Q), cprint(Qk));

      if (norm(Qk) > norm(Qkm1) || 
	  norm(Qk) < norm(Q) * SQR_DBL_EPSILON)
	  break;
      
      Qkm1 = Qk;
      Q = addlargesumandak(Q, Qk, &correctionQ);
    }

  trust &= k - 1 > 0.5 * n - 0.75;

  /* l, m cf [5] eq (5) */
  l = (n % 4 == 0) || (n % 4 == 3) ? 1.0 : -1.0;
  m = (n % 4 == 0) || (n % 4 == 1) ? 1.0 : -1.0;

  esterr = (cabs(l * Pkm1* ccos(z)) 
	    + cabs(m * Qkm1 * ccos (z))
	    + cabs(m * Pkm1*csin(z))
	    + cabs(l * Qkm1 * csin(z))) / csqrt (M_PI * z);

  tmp = (l * P + m * Q) * ccos (z);
  tmp += (m * P - l * Q) * csin (z);

  tmp /= csqrt(M_PI *z);
  DEBUG("max error theoric %e (rel %e) trust it: %s\n",
	esterr, esterr / cabs(tmp),
	trust == true ? "true" : "false");

  return tmp;
}

#if 0
/*!\brief Compute \f$\zeta^{3}{2}\f$ for \f$|z| < 1\f$

  According to [10] (2.3) p3 and [2] (9.3.38) p368
  \f[
  \frac{3}{2} \zeta^\frac{3}{2} 
      = \ln \frac{1+\sqrt{1-z^2}}{z} - \sqrt{1-z^2}
  \f]
  Therefore:
  \f[
  \zeta^\frac{3}{2} 
  = \frac{2}{3} \left[ \ln \frac{1+\sqrt{1-z^2}}{z} - \sqrt{1-z^2}\right]
  \f]
*/
static complex zeta32lesser1(complex z)
{
  complex sqrt1mz2;
  complex ret;
  
  sqrt1mz2 = csqrt(1 - sqr(z));
  ret = clog(1 + sqrt1mz2) / z - sqrt1mz2;
  return 2/3 * ret;
}

/*!\brief Compute \f$\zeta^\frac{3}{2}\f$ for \f$|z| > 1\f$

  According to [10] (2.3) p3 and [2] (9.3.39) p368
  \f[
  \frac{3}{2} (-\zeta)^\frac{3}{2} 
      = \sqrt(z^2 - 1) - \arccos \frac{1}{z} 
  \f]
  Therefore:
  \f[
  (\zeta)^\frac{3}{2} 
      = \frac{2i}{3} \left[\sqrt(z^2 - 1) - \arccos \frac{1}{z}\right]
  \f]
*/
static complex zeta32greater1(complex z)
{
  complex ret;
 
  ret = csqrt(sqr(z) - 1) - cacos(1 / z);
  return 2/3 * I  * ret;
}

/*!\brief Compute \f$\zeta^\frac{3}{2}\f$ in large order computation 
  
  Compute \f$\zeta^\frac{3}{2}\f$ where \f$\zeta\f$ is used for computing
  asymptotic uniform expansion of bessel function as given by 
  (9.3.35) [2, p368] 
*/
static complex zeta32(complex z)
{
  assert(creal(z) > 0);

  return norm(z) < 1 ?  zeta32lesser1(z) : zeta32greater1(z);
}


/*!\brief Computed \f$lambda_s\f$ 
  
  \f$lambda_s\f$ is defined by equation (9.3.41) [2,p368]
  \f[
  \lambda_s=\frac{(2s+1)(2s+3)\dotsm(2s+2k+1)\dotsm(6s-1)}{s!(144)^s}
  \f]
  \note \f$\lambda_0=1$ see (9.3.40) [2,p368] comment
  \note Only 11 \f$lambda_s\f$ because we know only 11 \f$u_s\f$
*/
static double lambda_s[]=
{
  1,                       /*  0 */
  1.0416666666666667e-01,  /*  1 */
  8.3550347222222222e-02,  /*  2 */
  1.2822657455632716e-01,  /*  3 */
  2.9184902646414046e-01,  /*  4 */
  8.8162726744375765e-01,  /*  5 */
  3.3214082818627675e+00,  /*  6 */
  5.6983899350077708e+02,  /*  7 */
  2.9990744944402877e+03,  /*  8 */
  1.8029158476994044e+04,  /*  9 */
  1.2188462345384515e+05,  /* 10 */
  9.1528888635321219e+05   /* 11 */
};


/*!\brief Factorized form of \f$u_k\f$ polynom */
struct ukroot {
  double a_n;       /*!< First factor */
  complex roots[];  /*!< Root list */
};



/*!\brief \f$u_1\f$ roots and first coefficient 

   \f[
   u_1 = 1/8 t - 5/24 t^3
   \f]

*/
static struct ukroot u_1 =
{ 
    -0.20833333333333333333,  /* 5/24 */
    { 
      0,
      -0.77459666924148338e0,
      0.77459666924148338e0
    }
};

/*!\brief \f$u_2\f$ roots and first coefficient 

   \f[
   u_2 &= 9/128 t^2 - 77/192 t^4 + 385/1152 t^6 
   \f]
*/
static struct ukroot u_2 =
{ 
    0.33420138888888888889,  /* 385/1152 */
    {
      0,
      0,
      -0.9933755698285430168303331391995165308e0,
      -0.4617412449281712766841302930873661235e0,
      +0.4617412449281712766841302930873661235e0,
      +0.9933755698285430168303331391995165308e0,
    }
}; 


/*!\brief u_3 roots and first coefficient 

   \f[
   u_3 = -85085/82944t^9 + 17017/9216 t^7 
         + 4563/5120 t^5 + 75/1024} t^39/128 t^2 - 77/192 t^4 + 385/1152 t^6 
   \f]
*/
static struct ukroot u_3 = 
{ 
  -1.02581259645061728395, /* -85085/82944 */
  {
    0, 
    0, 
    0, 
    -0.138580249705429438745460173524421702e1 
        - I * 0.101220782843783380746980555686986861e1,
    -0.138580249705429438745460173524421702e1 
        + I * 0.101220782843783380746980555686986861e1,
    -0.907317707191653384781336166975996007e-1,
    +0.907317707191653384781336166975996007e-1,
    +0.138580249705429438745460173524421702e1 
        - I * 0.101220782843783380746980555686986861e1,
    0.138580249705429438745460173524421702e1 
        + I * 0.101220782843783380746980555686986861e1
  }
};

/*!\brief u_4 roots and first coefficient 

   \f[
   u_4 = 37182145/7962624 t^{12} - 7436429/663552 t^{10} + 
         144001/16384 t^8 - 96833/40960 t^6 + 3675/32768 t^4
   \f]
*/
static struct ukroot u_4 = 
{ 
  4.66958442342624742798,  /* 37182145/7962624 */
  {
    0,
    0,
    0,
    0,
    -0.100041841035515907398258771298995e1,
    -0.941110901446937114426276664565697e0,
    -0.6736186161701436742651354273089735e0,
    -0.24435882498737510668615735106017847e0,
    0.24435882498737510668615735106017847e0,
    0.6736186161701436742651354273089735e0,
    0.941110901446937114426276664565697e0,
    0.100041841035515907398258771298995e1,
  }
};

/*!\brief \f$u_5\f$ roots and first coefficient 

   \f[
    u_5 = -5391411025/191102976 t^{15} + 5391411025/63700992 t^{13} 
         - 108313205/1179648 t^{11} + 250881631/1179648 t^9 
	 - 67608983/9175040 t^7 + 59535/62144 t^5 
   \f]
*/
static struct ukroot u_5 = 
{ 
  -28.21207255820024487740,
  {
    0,
    0,
    0,
    0,
    0,
    -0.1670438449895470671100910542996629e1,
    -0.9270613773884269855139917426769127e0 
       + I * 0.8782105373619380223726485586305577e0,
    -0.9270613773884269855139917426769127e0 
       - I * 0.8782105373619380223726485586305577e0,
    -0.2052781979771350691712212640237954e0 
       - I * 0.1597200535972700029703224113919119e0,
    -0.2052781979771350691712212640237954e0 
       + I * 0.1597200535972700029703224113919119e0,
    0.2052781979771350691712212640237954e0 
       - I * 0.1597200535972700029703224113919119e0,
    +0.2052781979771350691712212640237954e0 
       + I * 0.1597200535972700029703224113919119e0,
    +0.9270613773884269855139917426769127e0 
       - I * 0.8782105373619380223726485586305577e0,
    +0.9270613773884269855139917426769127e0 
       + I * 0.8782105373619380223726485586305577e0,
    +0.1670438449895470671100910542996629e1
  }
};

/*!\brief \f$u_6\f$ roots and first coefficient 

   \f[
   u_6 =-6183948445675/27518828544 t^{18} + 415138648925/509607936 t^{16}
         -4775249765/4194304 t^{14} + 7176153985/9437184 t^{12} 
	 -75861726551/314572800 t^{10} + 440748681/4680064 t^8
	 -2837835/4194304 t^6
   \f]
*/
static struct ukroot u_6 = 
{
  -224.71699461288667273874,  /* -6183948445675/27518828544 */
  { 
    0,
    0,
    0,
    0,
    0,
    0,
    -0.124382324519963642353346130366904e1,
    -0.104686419493993367114570194049547e1 
        + I * 0.332780470809332051417451647998361e0,
    -0.104686419493993367114570194049547e1 
        - I * 0.332780470809332051417451647998361e0,
    -0.4886325386868278874127653855249475e0 
        - I * 0.4342768586722670861475045894935201e0
    -0.4886325386868278874127653855249475e0 
        + I * 0.4342768586722670861475045894935201e0
    -0.8554751362758030119554608462468941e-1,
    +0.8554751362758030119554608462468941e-1,
    +0.4886325386868278874127653855249475e0 
        + I * 0.4342768586722670861475045894935201e0,
    +0.4886325386868278874127653855249475e0 
        - I * 0.4342768586722670861475045894935201e0,
    +0.104686419493993367114570194049547e1 
        + I * 0.332780470809332051417451647998361e0,
    +0.104686419493993367114570194049547e1 
        - I * 0.332780470809332051417451647998361e0,
    0.124382324519963642353346130366904e1,
  }
};

/*!\brief \f$u_7\f$ roots and first coefficient 

   \f[
   u_7 = 1329548915820125/660451885056 t^{21} -  623575990562525/73383542784 t^{19} 
         + 117495020467825/8153726976 t^{17} - 11287669528993/905969664 t^{15}
	 + 4806755210517/838860800 t^{13} - 23169978705569/17616076800 t^{11}
	 + 28375388975/234881024 t^9 - 66891825/33554432 t^7
   \f]
*/
static struct ukroot u_7 = 
{
  2013.08974340710977661787,  /* 1329548915820125/660451885056  */
  { 
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    -0.998039537598447177441282460677148435648e0,
    -0.99724587573846447076295130893102873649e0,
    -0.94882272724636817247619094545e0,
    -0.837374760217824635777173307031e0,
    -0.6573774609597790399970190455416e0,
    -0.4196709133247513072532002482099e0,
    -0.144245206044656036277453505803109e0,
    +0.144245206044656036277453505803109e0,
    +0.4196709133247513072532002482099e0,
    +0.6573774609597790399970190455416e0,
    +0.837374760217824635777173307031e0,
    +0.94882272724636817247619094545e0,
    +0.99724587573846447076295130893102873649e0,
    +0.998039537598447177441282460677148435648e0,
  }
};

/*!\brief \f$u_8\f$ roots and first coefficient 

   \f[
   u_8 = - 2671063771882631125/126806761930752 t^{24} + 59582343274078625/587068342272 t^{22} 
         - 237670164192005545/1174136684544 t^{20} + 42077740772116621/195689447424 t^{18} 
	 - 1257093219318079/9663676416 t^{16} + 296916207863309/6710886400 t^{14} 
	 - 2904156520889/3758096384 t^{12}    + 146540630595/268435456 t^{10} 
	 -  14783093325/2147483648 t^8
   \f]
*/
static struct ukroot u_8 = 
{
  -21064.04840887960177721512,  /* -2671063771882631125/126806761930752  */
  { 
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    -0.12855209236173717865334911825102e1,
    -0.11487230378788506995018715201335e1 + I * 0.3055693429633894025779426362946e0,
    -0.11487230378788506995018715201335e1 - I * 0.3055693429633894025779426362946e0,
    -0.762452554807904557645736589045814e0 + I * 0.46398205611410723966390073095189e0,
    -0.762452554807904557645736589045814e0 - I * 0.46398205611410723966390073095189e0,
    -0.21817886085393558522734608580627e0 - I * 0.251708826111540961305085325918613e0,
    -0.21817886085393558522734608580627e0 + I * 0.251708826111540961305085325918613e0,
    -0.112598695910012723571769914377913e0,
    +0.112598695910012723571769914377913e0,
    +0.21817886085393558522734608580627e0 - I * 0.251708826111540961305085325918613e0,
    +0.21817886085393558522734608580627e0 + I * 0.251708826111540961305085325918613e0,
    +0.762452554807904557645736589045814e0 + I * 0.46398205611410723966390073095189e0,
    +0.762452554807904557645736589045814e0 - I * 0.46398205611410723966390073095189e0,
    +0.11487230378788506995018715201335e1 + I * 0.3055693429633894025779426362946e0,
    +0.11487230378788506995018715201335e1 - I * 0.3055693429633894025779426362946e0,
    +0.12855209236173717865334911825102e1
  }
};


/*!\brief \f$u_9\f$ roots and first coefficient 

   \f[
   u_9 =   6904699850316601458125/27390260577042432 t^{27} 
         - 461679745093525633675/338151365148672 t^{25}
	 + 29412227933816172445/9393093476352 t^{23}
	 - 37073088786771732695/9393093476352 t^{21}
	 + 6190356955971173843/2087354105856 t^{19}
	 - 519996976064854883/386547056640 t^{17}
	 + 3996930023590772587/11274289152000 t^{15}
	 - 1468251292588911/30064771072 t^{13}
	 + 517406211757245/188978561024 t^{11}
	 - 468131288625/7179869184 t^9
   \f]
*/
static struct ukroot u_9 = 
{
  252085.94970811930830602353,  /* 6904699850316601458125/27390260577042432  */
  { 
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    -0.1058716313630550998779067364599140564345e1,
    -0.1012744489055979013043786254838985367869e1 
        - I * 0.8079524305020719395243932495366809870049e-1,
    -0.1012744489055979013043786254838985367869e1 
        + I * 0.8079524305020719395243932495366809870049e-1,
    -0.867199766734964955853948753249e0 
        + I * 0.12151310340817222279307347891e0,
    -0.867199766734964955853948753249e0 
        - I * 0.12151310340817222279307347891e0,
    -0.600543999351638174178690057091e0 
        + I * 0.107411727631102758807388532378e0,
    -0.600543999351638174178690057091e0 
        - I * 0.107411727631102758807388532378e0,
    -0.216370068593315513557972526683829e0 
        + I * 0.68924788863076631695122509655846e-1,
    -0.216370068593315513557972526683829e0 
        - I * 0.68924788863076631695122509655846e-1,
    0.216370068593315513557972526683829e0 
        - I * 0.68924788863076631695122509655846e-1,
    0.216370068593315513557972526683829e0 
        + I * 0.68924788863076631695122509655846e-1,
    0.600543999351638174178690057091e0 
        + I * 0.107411727631102758807388532378e0,
    0.600543999351638174178690057091e0 
        - I * 0.107411727631102758807388532378e0,
    0.867199766734964955853948753249e0 
        - I * 0.12151310340817222279307347891e0,
    0.867199766734964955853948753249e0 
        + I * 0.12151310340817222279307347891e0,
    0.1012744489055979013043786254838985367869e1 
        - I * 0.8079524305020719395243932495366809870049e-1,
    0.1012744489055979013043786254838985367869e1 
        + I * 0.8079524305020719395243932495366809870049e-1,
    0.1058716313630550998779067364599140564345e1
  }
};


/*!\brief \f$u_{10}\f$ roots and first coefficient 

   \f[
   u_{10} = - 4464578923214714502823625/1314732507698036736 t^{30}
            + 1491741571661309972478475/73040694872113152 t^{28}
	    - 286485860646564818213975/5410421842378752 t^{26}
	    + 17416724745836133903185/225434243432448 t^{24}
	    - 2318810066751674077595/33397665693696 t^{22}
	    + 16487466760916641832507/417470821171200 t^{20}
	    - 45614196450845087013377/3246995275776000 t^{18}
	    + 12736018679229356269/4294967296000 t^{16}
	    - 49042918914307396335/148159191842816 t^{14}
	    + 22818897912239625/1511828488192 t^{12}
	    - 33424574007825/274877906944 t^{10}
    \f]
*/
static struct ukroot u_10 = 
{
  -3395807.81419312384897239204,
  {
    0, 
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    -0.10001090783214750809440416432541680599188e1,
    -0.9993294917832275718734757908005237189461e0,
    -0.9888500788629341914999395888452394835901557e0,
    -0.9524074579126822822167397126841777753775329e0,
    -0.882853338709630498587057483665940085863536107e0,
    -0.7792607086106625162758717324993474593597737525e0,
    -0.64368000020409505993637643841829812109365971659e0,
    -0.48077792088388172553910915777979533697628420406e0,
    -0.2971121517155323652483396314558797798412890267508e0,
    -0.1005022696406253921602443854248310446528817542823e0,
    +0.1005022696406253921602443854248310446528817542823e0,
    +0.2971121517155323652483396314558797798412890267508e0,
    0.48077792088388172553910915777979533697628420406e0,
    0.64368000020409505993637643841829812109365971659e0,
    0.7792607086106625162758717324993474593597737525e0,
    0.882853338709630498587057483665940085863536107e0,
    0.9524074579126822822167397126841777753775329e0,
    0.9888500788629341914999395888452394835901557e0,
    0.9993294917832275718734757908005237189461e0,
    0.10001090783214750809440416432541680599188e1
  }
}


/*!\brief \f$u_{11}\f$ roots and first coefficient 

   \f[
   u_{11} = + 1604407316678887857241980875/31553580184752881664 t^{33}
            - 392956135061308232223935125/1168651117953810432 t^{31}
	    + 1136426675054854043018733575/1168651117953810432 t^{29}
	    - 209347382482809784715977475/129850124217090048 t^{27}
	    + 4057208263006803008962871/2404631929946112 t^{25}
	    - 7721779642093423553411219/6679533138739200 t^{23}
	    + 24317219180863821793468459/46756731971174400 t^{21}
	    - 185223434015774166216919/1236950581248000 t^{19}
	    + 109880525895631410224729/4233119766937600 t^{17}
	    - 258444671539364377513/107752139522048 t^{15}
	    + 28529686078127770725/314460325543936 t^{13}
	    - 1327867167401775/2199023255552 t^{11}
    \f]
*/




/*!\brief Table of \f$u_k\f$ 

  The different u are defined by the following recurence relation:
  \f{align*}
  u_0 &= 1 \\
  u_{k+1} = \frac{1}{2} t^2 (1-t^2) u'_k + \frac{1}{8} \int_0^t (1-5t^2) u_k(t)\; dt	 
  \f}


  We do not use direct evaluation by monomial formula due to numerical ill behavior
 
  \note We compute roots using a arbitrary precision software

  \f}
*/
struct ukroot * ukroots[] = {
  /* u_0 (special case) */
  NULL,
  /* u_1 */
  &u_1,
  /* u_2 */
  &u_2,
  /* u_3 */
  &u_3,
  /* u_4 */
  &u_4,
  /* u_5 */
  &u_5,
  /* u_6 */
  &u_6,
  /* u_7 */
  &u_7,
  /* u_8 */
  &u_8,
  /* u_9 */
  &u_9,
  /* u_10 */
  &u_10
};





/*!\brief Bessel function for large order
   


 */
complex cbesseljn_largeorder(unsigned int n, complex z)
{


}

#endif

/*!\brief Main entry point for besselj function 

  Bessel function of first kind and integer order is 
  The Bessel functions of the first kind \f$J_n(z)\f$ are defined as the solutions 
  to the Bessel differential equation (for \f$n \in \mathbb{N}\f$)
  \f[
  x^2\frac{\text{d}^2y}{\text{d}x^2}+x\frac{\text{d}y}{\text{d}x}+(x^2-n^2)y=0 
  \f]
  which are nonsingular at the origin

  We use two properties of bessel function of first kind in order to compute in the first 
  quadrant:
  \f[
  J_{-v}(z) = (-1)^v J_v(z)
  \f]
  Therefore we could compute only whan \f$\Re\text{e}\; z > 0\f$, and apply the following formula:
  \f{align*}
  J_{v^*}(z^*) &= (J_v(z))^* & \Re\text{e}\; z &> 0
  \f}
*/
complex cbesseljn (unsigned int n, complex z)
{
  bool retopp = false;
  bool retconj = false;
  complex ret;

  if(isnan(creal(z)) || isnan(cimag(z)))
    return NAN + I*NAN;

  /* J_n(-z)=(-1)^n J_n(z) */
  if(creal(z) < 0.0) 
    return n % 2 ? cbesseljn (n, -z) : - cbesseljn (n, -z);

  assert(creal(z) >= 0.0);
  
  /* J_n(~z)=~(J_n(z)) */
  if(cimag(z) < 0.0) 
    return conj(cbesseljn(n, conj(z)));

  /* we are in first quadrant */
  assert(cimag(z) >= 0.0);

  /* large argument */
  if(norm(z) >= 10 * norm(sqr(n) - 1/4))
    return cbesseljn_largearg (n, z);

  if (norm (z) < norm(SMALL_JN_BOUND))
    return cbesseljn_smallarg (n, z);
  else if (norm (z) > norm(BIG_JN_BOUND))
    return cbesseljn_largearg (n, z);
  else
    return cbesseljn_mediumarg (n, z);
}


#ifdef CBESSELJ_TEST
#include "test_cbesseljn.c"
#endif /* CBESSELJ_TEST */
_______________________________________________
Help-gsl mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/help-gsl

Reply via email to