# 
# Implementation of Hankel Functions in terms of BesselJ and BesselY
# 
# Author: Douglas B. Meade (meade@math.scarolina.edu)
# Date: 15 July 1993	(Revised: 27 July 1993)
# 
#-------------------------------------------------------------------------------
#
# These deinitions follow the structure of the definitins of the other
# Bessel functions. In particular, the definitions of BesselJ and BesselY
# for diff, evalf, expand, and simplify.
#
# There is very little content in these procedures. The basic idea is to
# provide a convenient interface; most operations are passed on to the
# corresponding BesselJ and BesselY procedures.
#
# One addition is the `evalc/BesselH` procedure.
#
# My basic philosophy is to simplify, expand, differentiate the Hankel
# function in terms of other Hankel functions. The evalc procedure is
# used to obtain expressions in terms of BesselJ and BesselY.
#
# NOTE: The `expand/BesselY` appears to be missing from the standard
#	distribution of Maple. I have written what seems to be the
#	appropriate implementation of `expand/BesselY`.
# 
#-------------------------------------------------------------------------------
#
# Future Enhancements:
#	Teach Maple about:
#		Wronskians of the different Bessel functions
#		recurrence relations for cross-products
#
# Any comments, corrections, improvements will be appreciated.
# 
#-------------------------------------------------------------------------------

#printf(	`Hankel function procedures:\n`);
#printf( `\n%20s %20s %20s\n%20s %20s %20s\n%20s\n \n`,
#	`BesselH`, `diff/BesselH`, `evalc/BesselH`, `evalf/BesselH`,
#	`expand/BesselH`, `simplify/BesselH`, `expand/BesselY` );
#printf( `Implemented by Douglas B. Meade, University of South Carolina (July #1993)\nPlease e-mail questions and comments to: meade@math.scarolina.edu\n`);

BesselH := proc(i,v,x)
  options remember, `Douglas B. Meade, 1993 (Based on BesselJ and BesselY)`;

  if not member(i,{1,2}) or not type([v,x],[algebraic,algebraic]) then
    ERROR(`invalid arguments`)
  fi;
  if type(v,integer) then
    if x = 0 then ERROR(`singularity encountered`)
    elif v < 0 then (-1)^v*BesselH(i,-v,x)
    elif type(x,float) then evalf('BesselH(i,v,x)')
    else 'BesselH(i,v,x)'
    fi
  elif type(v,numeric) and type(x,float) and 0 < x then evalf('BesselH(i,v,x)')
  elif type(2*v,integer) then BesselJ(v,x)+(-1)^(i+1)*BesselY(v,x)*I
  else 'BesselH(i,v,x)'
  fi
end:

`diff/BesselH` := proc(i,v,z,x)
  local k;
  options `Douglas B. Meade, 1993 (Based on BesselJ and BesselY)`;

  if diff(v,x)<>0 or diff(i,x)<>0 then RETURN('diff(BesselH(i,v,z),x)')
  elif
    type(v,`+`) and member(true,map(type,[op(v)],rational)) or type(v,rational)
  then
    if type(v,rational) then k := v
    else k := op(map(proc(x) if type(x,rational) then x fi end,[op(v)]))
    fi;
    if 1/2 < k then RETURN((BesselH(i,v-1,z)-v/z*BesselH(i,v,z))*diff(z,x)) fi
  fi;
  (-BesselH(i,v+1,z)+v/z*BesselH(i,v,z))*diff(z,x)
end:

`evalc/BesselH` := proc(i,v,x)
  options `Douglas B. Meade, 1993 (Based on BesselJ and BesselY)`;

  if evalc(Im(x)) <> 0 then
    RETURN( 'BesselH(i,v,x)' )
  fi;
  BesselJ(v,x)+(-1)^(i+1)*BesselY(v,x)*I
end:

`evalf/BesselH` := proc(i,v,x)
  local vf, xf;
  options `Douglas B. Meade, 1993 (Based on BesselJ and BesselY)`;

  vf := evalf(v);
  xf := evalf(x);
  if evalc(Im(xf)) <> 0 then
    RETURN( BesselH(i,vf,xf) )
  fi;
  evalf( BesselJ(vf,xf) )+(-1)^(i+1)*I* evalf( BesselY(vf,xf) )
end:

`expand/BesselH` := proc(i,pv,px)
  local v,x;
  options `Douglas B. Meade, 1993 (Based on BesselJ and BesselY)`;

  v := expand(pv);
  x := expand(px);
  if type(v,'integer') and v>1 then
    expand(2*(v-1)/x*BesselH(i,v-1,x)-BesselH(i,v-2,x))
  else
    BesselH(i,v,x)
  fi
end:

`simplify/BesselH` := proc(a)
  local k,i,v,x;
  options remember, `Douglas B. Meade, 1993 (Based on BesselJ and BesselY)`;

  if not has(a,BesselH) then
    a
  elif type(a,function) and op(0,a)=BesselH and nops(a)=3 then
    i := op(1,a);
    v := op(2,a);
    x := op(3,a);
    if type(v,`+`) and member(true,map(type,[op(v)],rational))
	or type(v,rational) then
      if type(v,rational) then
        k:=v
      else
        k:=op(map(proc(x) if type(x,rational) then x fi end,[op(v)]))
      fi;
      if abs(k)<100 then
        if k>1 then
          RETURN(procname(2*(v-1)/x*BesselH(i,v-1,x)-BesselH(i,v-2,x)))
        elif k<=-1 then
          RETURN(procname(2*(v+1)/x*BesselH(i,v+1,x)-BesselH(i,v+2,x)))
        fi
      fi
    fi;
    a
  elif type(a,{function,`*`,`^`,`+`}) then
    eval(map(`simplify/BesselH`,a))
  else
    a
  fi
end:

`expand/BesselY` := proc(pv,px)
  local v,x;
  options `Douglas B. Meade, 1993 (Based on BesselJ)`;

  v := expand(pv);
  x := expand(px);
  if type(v,'integer') and v>1 then
    expand(2*(v-1)/x*BesselY(v-1,x)-BesselY(v-2,x))
  else
    BesselY(v,x)
  fi
end:

`help/text/BesselH` := TEXT(
`FUNCTION: BesselH - The Bessel functions of the third kind`,
`		     (aka Hankel functions)`,
`   `,
`CALLING SEQUENCE: BesselH(i, v, x)`,
`   `,
`PARAMETERS:`,
`	    i - integer (must be 1 or 2),`,
`	    v - an algebraic expression or real number`,
`	    x - an algebraic expression or real number`,
`   `,
`SYNOPSIS:   `,
`- In the function call, BesselH(i,v,x), i denotes the ``kind' of`,
`  the Hankel function, v is the order, and x is the argument.`,
`     `,
`Hankel function procedures:					`,
`								`,
`                   H         diff/BesselH        evalc/BesselH	`,
`       evalf/BesselH       expand/BesselH     simplify/BesselH	`,
`      expand/BesselY						`,
` 								`,
`Implemented by Douglas B. Meade, University of South Carolina (July 1993) `,
`Please e-mail questions and comments to: meade@math.scarolina.edu `,
`								`,
`EXAMPLES:   `,
`								`,
`> BesselH(1,1,r);						`,
`                                BesselH(1, 1, r)		`,
`								`,
`> BesselH(1,1/2,r );						`,
`                            1/2             1/2		`,
`                           2    sin(r)   I 2    cos(r)		`,
`                           ----------- - -------------		`,
`                              1/2  1/2      1/2   1/2		`,
`                            Pi    r        r    Pi		`,
`								`,
`> evalf( BesselH( 1,1,2 ), 20 );				`,
`                 .57672480775687338720 - .10703243154093754689 I`,
`								`,
`> BesselH(1,1,x);						`,
`                                BesselH(1, 1, x)		`,
`								`,
`> evalc( " );							`,
`                         BesselJ(1, x) + I BesselY(1, x)	`,
`								`,
`REFERENCE:							`,
`Abramowitz & Stegun, Handbook of Mathematical Functions,	`,
`Chapter 9: Bessel Functions of Integer Order, Dover, 1972.	`,
`								`,
`SEE ALSO: BesselJ, BesselY,  ``diff/BesselH``, ``evalc/BesselH``, `,
`	   ``evalf/BesselH``, ``expand/BesselH``, ``simplify/BesselH`` `,
`   `,
`AUTHOR: Douglas B. Meade (e-mail: meade@math.scarolina.edu)`,
`	 Department of Mathematics, University of South Carolina`
):
`help/text/hankel` := ":
#save `hankel.m`;
#quit
