module Math.AngerWeber
  ( AngerWeberResult(..), angerWeber )
  where
import Data.Complex          ( realPart, imagPart, Complex(..) )
import Math.BesselJ          ( besselJ, BesselResult(..) )
import Math.AngerJ           ( angerJ, AngerResult(..))


-- | Data type to store the result of a computation of the Anger-Weber function.

-- It is based on a computation of the Bessel J-function and a computation of 

-- the Anger J-function. 

-- The fields are @_result@ for the value, @_besselResult@ for the result of 

-- the computation of the Bessel J-function, and @_angerResult@ for the result 

-- of the computation of the Anger J-function.

data AngerWeberResult = AngerWeberResult {
    AngerWeberResult -> Complex Double
_result       :: Complex Double
  , AngerWeberResult -> BesselResult
_besselResult :: BesselResult
  , AngerWeberResult -> AngerResult
_angerResult  :: AngerResult
} deriving Int -> AngerWeberResult -> ShowS
[AngerWeberResult] -> ShowS
AngerWeberResult -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AngerWeberResult] -> ShowS
$cshowList :: [AngerWeberResult] -> ShowS
show :: AngerWeberResult -> String
$cshow :: AngerWeberResult -> String
showsPrec :: Int -> AngerWeberResult -> ShowS
$cshowsPrec :: Int -> AngerWeberResult -> ShowS
Show


isInteger :: Complex Double -> Bool
isInteger :: Complex Double -> Bool
isInteger Complex Double
z = Double
y forall a. Eq a => a -> a -> Bool
== Double
0 Bool -> Bool -> Bool
&& Double
x forall a. Eq a => a -> a -> Bool
== forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a b. (RealFrac a, Integral b) => a -> b
floor Double
x :: Int)
  where
    x :: Double
x = forall a. Complex a -> a
realPart Complex Double
z
    y :: Double
y = forall a. Complex a -> a
imagPart Complex Double
z


aResult :: AngerResult -> Complex Double
aResult :: AngerResult -> Complex Double
aResult (AngerResult Complex Double
r  (Double, Double)
_  (Int, Int)
_) = Complex Double
r

bResult :: BesselResult -> Complex Double
bResult :: BesselResult -> Complex Double
bResult (BesselResult Complex Double
r (Double, Double)
_ (Int, Int)
_) = Complex Double
r


-- | Anger-Weber function. 

angerWeber :: Complex Double       -- ^ order, non-integer complex number with real part larger than -0.5

           -> Complex Double       -- ^ the variable, a complex number

           -> Double               -- ^ target relative accuracy for the integrals, e.g. 1e-5

           -> Int                  -- ^ number of subdivisions for the integrals, e.g. 5000

           -> IO AngerWeberResult  -- ^ result

angerWeber :: Complex Double
-> Complex Double -> Double -> Int -> IO AngerWeberResult
angerWeber Complex Double
nu Complex Double
z Double
err Int
subdiv 
  | Complex Double -> Bool
isInteger Complex Double
nu = forall a. HasCallStack => String -> a
error String
"The order `nu` cannot be an integer."
  | forall a. Complex a -> a
realPart Complex Double
nu forall a. Ord a => a -> a -> Bool
<= -Double
0.5 = forall a. HasCallStack => String -> a
error String
"The real part of the order `nu` must be larger than -0.5."
  | Bool
otherwise = do
      BesselResult
bessel <- Complex Double
-> Complex Double -> Double -> Int -> IO BesselResult
besselJ Complex Double
nu Complex Double
z Double
err Int
subdiv
      AngerResult
anger <- Complex Double -> Complex Double -> Double -> Int -> IO AngerResult
angerJ Complex Double
nu Complex Double
z Double
err Int
subdiv
      let bresult :: Complex Double
bresult = BesselResult -> Complex Double
bResult BesselResult
bessel
          aresult :: Complex Double
aresult = AngerResult -> Complex Double
aResult AngerResult
anger 
          result :: Complex Double
result = (Complex Double
aresult forall a. Num a => a -> a -> a
- Complex Double
bresult) forall a. Fractional a => a -> a -> a
/ forall a. Floating a => a -> a
sin(forall a. Floating a => a
piforall a. Num a => a -> a -> a
*Complex Double
nu)
      forall (m :: * -> *) a. Monad m => a -> m a
return (Complex Double -> BesselResult -> AngerResult -> AngerWeberResult
AngerWeberResult Complex Double
result BesselResult
bessel AngerResult
anger)