packages feed

aern2-mp-0.2.9.0: src/AERN2/MP/Float/Type.hs

{-# OPTIONS_GHC -Wno-orphans #-}
{-# LANGUAGE StandaloneDeriving #-}
{-|
    Module      :  AERN2.MP.Float.Type
    Description :  Arbitrary precision floating point numbers (via cdar)
    Copyright   :  (c) Michal Konecny
    License     :  BSD3

    Maintainer  :  mikkonecny@gmail.com
    Stability   :  experimental
    Portability :  portable

    Arbitrary precision floating-point numbers, re-using CDAR Approx type.
-}
module AERN2.MP.Float.Type
  (
   -- * MPFloat numbers and their basic operations
   MPFloat(..)
   , lift1, lift2, lift2R
   , getErrorStepSizeLog
   , setPrecisionCEDU
   , p2cdarPrec
   , getBoundsCEDU
   )
where

import MixedTypesNumPrelude
import qualified Prelude as P

-- import Data.Bits (unsafeShiftL)
import Data.Typeable

import AERN2.Norm
import AERN2.MP.Precision
import AERN2.MP.Float.Auxi

import qualified Data.CDAR as MPLow
import Control.DeepSeq (NFData)
import GHC.Generics (Generic)

{-| Multiple-precision floating-point type based on CDAR.Approx with 0 radius. -}
newtype MPFloat = MPFloat { unMPFloat :: MPLow.Approx }
  deriving (Generic)

lift1 :: (MPLow.Approx -> MPLow.Approx) -> MPFloat -> MPFloat
lift1 f (MPFloat a) = MPFloat (f a)

lift2 :: 
  (MPLow.Approx -> MPLow.Approx -> MPLow.Approx) -> 
  (MPFloat -> MPFloat -> MPFloat)
lift2 f (MPFloat a1) (MPFloat a2) = MPFloat (f a1 a2)

lift2R :: 
  (MPLow.Approx -> MPLow.Approx -> t) -> 
  (MPFloat -> MPFloat -> t)
lift2R f (MPFloat a1) (MPFloat a2) = f a1 a2

instance Show MPFloat where
  show x = MPLow.showA $ unMPFloat x

deriving instance (Typeable MPFloat)
instance NFData MPFloat

p2cdarPrec :: Precision -> MPLow.Precision
p2cdarPrec = P.fromInteger . integer

getBoundsCEDU :: MPFloat -> BoundsCEDU MPFloat
getBoundsCEDU (MPFloat (MPLow.Approx mb m e s)) = 
  BoundsCEDU 
    (MPFloat $ MPLow.Approx mb m 0 s) (MPFloat $ MPLow.approxMB eb_mb e 0 s)
    (MPFloat $ MPLow.Approx mb (m-e) 0 s) (MPFloat $ MPLow.Approx mb (m+e) 0 s)
getBoundsCEDU (MPFloat MPLow.Bottom) =
  BoundsCEDU
    (MPFloat MPLow.Bottom) (MPFloat MPLow.Bottom) 
    (MPFloat MPLow.Bottom) (MPFloat MPLow.Bottom)

{-| The bit-size bound for the error bound in CEDU -}
eb_prec :: Precision
eb_prec = prec 63

{-| The bit-size bound for the error bound in CEDU -}
eb_mb :: Int
eb_mb = int $ integer eb_prec

instance HasPrecision MPFloat where
  getPrecision (MPFloat (MPLow.Approx mb _ _ _)) = prec (P.toInteger $ mb)
  getPrecision (MPFloat MPLow.Bottom) = error "illegal MPFloat (Bottom)"
  
instance CanSetPrecision MPFloat where
  setPrecision p = ceduCentre . setPrecisionCEDU p

setPrecisionCEDU :: Precision -> MPFloat -> BoundsCEDU MPFloat
setPrecisionCEDU pp = 
  getBoundsCEDU . lift1 MPLow.enforceMB . lift1 (MPLow.setMB (p2cdarPrec pp))

instance HasNorm MPFloat where
  getNormLog (MPFloat (MPLow.Approx _ m _ s)) = (getNormLog m) + (integer s)
  getNormLog (MPFloat MPLow.Bottom) = error "getNormLog undefined for Bottom"

{-|
  Returns @s@ such that @2^s@ is the distance to the nearest other number with the same precision.
  Returns Nothing for Bottom.
-}
getErrorStepSizeLog :: MPLow.Approx -> Maybe Int
getErrorStepSizeLog (MPLow.Approx _ _ _ s) = Just $ s
getErrorStepSizeLog _ = Nothing -- represents +Infinity