module Data.Number.Flint.Acb.ComplexField ( CF(..) , RF'(..) , Special (..) , realPart , imagPart -- * Polar form , mkPolar , cis , polar , magnitude , phase -- * Conjugate , conjugate ) where import GHC.TypeLits import Data.Proxy import Data.Ratio import System.IO.Unsafe import Control.Monad import Foreign.C.String import Foreign.C.Types import Foreign.ForeignPtr import Foreign.Ptr ( Ptr, FunPtr, castPtr ) import Foreign.Storable import Foreign.Marshal ( free ) import Foreign.Marshal.Array ( advancePtr ) import Data.Number.Flint.Fmpz import Data.Number.Flint.Fmpz.Instances import Data.Number.Flint.Arb import Data.Number.Flint.Arb.RealField import Data.Number.Flint.Arb.Types import Data.Number.Flint.Acb import Data.Number.Flint.Acb.Acf import Data.Number.Flint.Acb.Types import Data.Number.Flint.Acb.Hypgeom import Data.Number.Flint.Acb.Modular import Data.Number.Flint.Acb.Elliptic import Data.Number.Flint.Support.D.Interval newtype CF (n :: Nat) = CF Acb realPart :: forall n. KnownNat n => (CF n) -> (RF n) realPart (CF z) = unsafePerformIO $ do res <- newArb withArb res $ \res -> do withAcb z $ \z -> do acb_get_real res z return $ RF res imagPart :: forall n. KnownNat n => (CF n) -> (RF n) imagPart (CF z) = unsafePerformIO $ do res <- newArb withArb res $ \res -> do withAcb z $ \z -> do acb_get_imag res z return $ RF res mkPolar :: forall n. KnownNat n => (RF n) -> (RF n) -> (CF n) mkPolar (RF r) (RF theta) = unsafePerformIO $ do let prec = fromInteger $ natVal (Proxy :: Proxy n) res <- newAcb withAcb res $ \res -> do withArb r $ \r -> do withArb theta $ \theta -> do withNewArb $ \x -> do withNewArb $ \y -> do arb_sin_cos y x theta prec arb_mul x x r prec arb_mul y y r prec acb_set_arb_arb res x y return $ CF res cis :: forall n. KnownNat n => (RF n) -> (CF n) cis (RF theta) = unsafePerformIO $ do let prec = fromInteger $ natVal (Proxy :: Proxy n) res <- newAcb withAcb res $ \res -> do withArb theta $ \theta -> do withNewArb $ \x -> do withNewArb $ \y -> do arb_sin_cos y x theta prec acb_set_arb_arb res x y return $ CF res polar :: forall n. KnownNat n => (CF n) -> (RF n, RF n) polar z = (magnitude z, phase z) magnitude :: forall n. KnownNat n => (CF n) -> (RF n) magnitude (CF z) = unsafePerformIO $ do let prec = fromInteger $ natVal (Proxy :: Proxy n) res <- newArb withArb res $ \res -> do withAcb z $ \z -> do acb_abs res z prec return $ RF res phase :: forall n. KnownNat n => (CF n) -> (RF n) phase (CF z) = unsafePerformIO $ do let prec = fromInteger $ natVal (Proxy :: Proxy n) res <- newArb withArb res $ \res -> do withAcb z $ \z -> do acb_arg res z prec return $ RF res conjugate :: forall n. KnownNat n => (CF n) -> (CF n) conjugate (CF z) = unsafePerformIO $ do res <- newAcb withAcb res $ \res -> do withAcb z $ \z -> do acb_conj res z return $ CF res instance forall n. KnownNat n => Eq (CF n) where {-# INLINE (==) #-} (==) = liftCmp acb_eq {-# INLINE (/=) #-} (/=) = liftCmp acb_ne instance forall n. KnownNat n => Ord (CF n) where compare = undefined instance forall n. KnownNat n => Num (CF n) where {-# INLINE (+) #-} (+) = lift2 acb_add {-# INLINE (-) #-} (-) = lift2 acb_sub {-# INLINE (*) #-} (*) = lift2 acb_mul {-# INLINE negate #-} negate = lift1 acb_neg abs = undefined {-# INLINE fromInteger #-} fromInteger x = unsafePerformIO $ do result <- newAcb let prec = fromInteger $ natVal (Proxy :: Proxy n) withAcb result $ \result -> do acb_set_ui result (fromIntegral x) return (CF result) signum = undefined instance forall n. KnownNat n => Fractional (CF n) where {-# INLINE (/) #-} (/) = lift2 acb_div fromRational x = p / q where p = fromIntegral (numerator x) :: CF n q = fromIntegral (denominator x) :: CF n instance forall n. KnownNat n => Real (CF n) where toRational = undefined instance forall n. KnownNat n => RealFrac (CF n) where properFraction = undefined instance forall n. KnownNat n => Floating (CF n) where pi = liftConstant arb_const_pi exp = liftF1 acb_exp log = liftF1 acb_log sqrt = liftF1 acb_sqrt sin = liftF1 acb_sin cos = liftF1 acb_cos tan = liftF1 acb_tan asin = liftF1 acb_asin acos = liftF1 acb_acos atan = liftF1 acb_atan sinh = liftF1 acb_sinh cosh = liftF1 acb_cosh tanh = liftF1 acb_tanh asinh = liftF1 acb_asinh acosh = liftF1 acb_acosh atanh = liftF1 acb_atanh instance forall n. KnownNat n => Show (CF n) where show (CF x) = unsafePerformIO $ do let prec = fromInteger $ natVal (Proxy :: Proxy n) digits = floor (fromIntegral prec * logBase 10 2) (_, cstr) <- withAcb x $ \p -> acb_get_strn p (fromIntegral digits) arb_str_no_radius str <- peekCString cstr return str ------------------------------------------------------------------------ instance forall n. KnownNat n => Special (CF n) where gamma = liftF1 acb_gamma digamma = liftF1 acb_digamma lgamma = liftF1 acb_hypgeom_lgamma zeta = liftF1 acb_zeta erf = liftF1 acb_hypgeom_erf airy (CF x) = unsafePerformIO $ do let prec = fromInteger $ natVal (Proxy :: Proxy n) ai <- newAcb ai' <- newAcb bi <- newAcb bi' <- newAcb withAcb x $ \x -> withAcb ai $ \ai -> withAcb ai' $ \ai' -> withAcb bi $ \bi -> withAcb bi' $ \bi' -> acb_hypgeom_airy ai ai' bi bi' x prec return $ (CF ai, CF ai', CF bi, CF bi') airyZeros = undefined besselJ = lift2 acb_hypgeom_bessel_j besselY = lift2 acb_hypgeom_bessel_y besselI = lift2 acb_hypgeom_bessel_i besselK = lift2 acb_hypgeom_bessel_k modj = liftF1 acb_modular_j modjq = undefined modeta = liftF1 acb_modular_eta modetaq = undefined modlambda = liftF1 acb_modular_lambda modlambdaq = undefined ellipp = lift2 acb_elliptic_p ellipzeta = lift2 acb_elliptic_zeta ellipsigma = lift2 acb_elliptic_sigma barnesg = liftF1 acb_barnes_g agm = lift2 acb_agm fresnels = undefined fresnelc = undefined instance forall n. KnownNat n => RF' (CF n) where euler = liftConstant arb_const_euler glaisher = liftConstant arb_const_glaisher catalan = liftConstant arb_const_catalan khinchin = liftConstant arb_const_khinchin polylog = lift2 acb_polylog midPoint = lift1 acb_get_mid -- lifting ------------------------------------------------------------- type Binary = Ptr CAcb -> Ptr CAcb -> Ptr CAcb -> CLong -> IO () type Cmp = Ptr CAcb -> Ptr CAcb -> IO CInt type Function = Ptr CAcb -> Ptr CAcb -> IO () lift2 :: forall n. KnownNat n => Binary -> CF n -> CF n -> CF n lift2 f (CF a) (CF b) = unsafePerformIO $ do let prec = fromInteger $ natVal (Proxy :: Proxy n) c <- newAcb withAcb a $ \a -> withAcb b $ \b -> withAcb c $ \c -> f c a b (CLong prec) return (CF c) lift1 :: forall n. KnownNat n => Function -> CF n -> CF n lift1 f (CF x) = unsafePerformIO $ do y <- newAcb withAcb x $ \x -> withAcb y $ \y -> f y x return (CF y) lift0 f x = CF $ unsafePerformIO $ fst <$> withNewAcb (`f` x) liftF1 :: forall n. KnownNat n => (Ptr CAcb -> Ptr CAcb -> CLong -> IO ()) -> CF n -> CF n liftF1 f (CF x) = unsafePerformIO $ do let prec = fromInteger $ natVal (Proxy :: Proxy n) y <- newAcb withAcb x $ \x -> withAcb y $ \y -> f y x (CLong prec) return (CF y) liftCmp :: forall n. KnownNat n => Cmp -> CF n -> CF n -> Bool liftCmp f (CF x) (CF y) = unsafePerformIO $ do (_, (_, cmp)) <- withAcb x $ \x -> withAcb y $ \y -> f x y return (cmp == 1) liftProp :: forall n. KnownNat n => (Ptr CAcb -> IO CInt) -> CF n -> Bool liftProp f (CF x) = unsafePerformIO $ do (_, prop) <- withAcb x $ \x -> f x return (prop == 1) liftConstant :: forall n. KnownNat n => (Ptr CArb -> CLong -> IO ()) -> CF n liftConstant f = CF $ fst $ snd $ unsafePerformIO $ do let prec = fromInteger $ natVal (Proxy :: Proxy n) tmp <- newArb withArb tmp $ \tmp -> do f tmp prec withNewAcb (`acb_set_arb` tmp)