module AERN2.MP.UseMPFR.Dyadic
(
Dyadic, HasDyadics
, CanBeDyadic, dyadic
, specDyadic, tDyadic
)
where
#ifdef DEBUG
import Debug.Trace (trace)
#define maybeTrace trace
#define maybeTraceIO putStrLn
#else
#define maybeTrace (\ (_ :: String) t -> t)
#define maybeTraceIO (\ (_ :: String) -> return ())
#endif
import MixedTypesNumPrelude
import qualified Prelude as P
import Control.CollectErrors
import Text.Printf
import Text.Regex.TDFA
import Data.Typeable
import Data.Convertible
import Test.Hspec
import Test.QuickCheck
import Data.Ratio (denominator, numerator)
import Math.NumberTheory.Logarithms (integerLog2)
import AERN2.Norm
import AERN2.MP.Precision
import AERN2.MP.Accuracy
import AERN2.MP.UseMPFR.Float
newtype Dyadic = Dyadic { dyadicMPFloat :: MPFloat }
deriving (P.Eq, P.Ord, CanRound, HasPrecision, HasNorm, Typeable)
instance Ring Dyadic
instance Ring (CN Dyadic)
instance OrderedRing Dyadic
instance OrderedRing (CN Dyadic)
instance OrderedCertainlyRing Dyadic
instance OrderedCertainlyRing (CN Dyadic)
instance HasAccuracy Dyadic where getAccuracy _ = Exact
instance Show Dyadic where
show (Dyadic x)
| e == 0 = printf "dyadic (%d)" n
| e > 0 = printf "dyadic (%d*0.5^%d)" n e
| otherwise = error "in show Dyadic"
where
xR = rational x
NormBits e = getNormLog (denominator xR)
n = numerator xR
instance Read Dyadic where
readsPrec _pr dyadicS =
tryInt $ tryWithExp []
where
tryInt tryNext =
case groups of
[nS] ->
case reads nS of
[(n,"")] -> [(dyadic (n :: Integer), afterS)]
_ -> tryNext
_ -> tryNext
where
(_,_,afterS,groups) =
dyadicS =~ "\\`dyadic \\(([-0-9]*)\\)"
:: (String, String, String, [String])
tryWithExp tryNext =
case groups of
[nS,eS] ->
case (reads nS, reads eS) of
([(n,"")],[(e,"")]) ->
[((n :: Integer)*(dyadic 0.5)^!(e :: Integer), afterS)]
_ -> tryNext
_ -> tryNext
where
(_,_,afterS,groups) =
dyadicS =~ "\\`dyadic \\(([-0-9]*)\\*0.5\\^([0-9]*)\\)"
:: (String, String, String, [String])
instance (SuitableForCE es) => CanEnsureCE es Dyadic
type HasDyadics t = ConvertibleExactly Dyadic t
instance ConvertibleExactly Dyadic Dyadic where
safeConvertExactly = Right
instance ConvertibleExactly Dyadic MPFloat where
safeConvertExactly = Right . dyadicMPFloat
instance ConvertibleExactly Dyadic Rational where
safeConvertExactly = safeConvertExactly . dyadicMPFloat
type CanBeDyadic t = ConvertibleExactly t Dyadic
dyadic :: (CanBeDyadic t) => t -> Dyadic
dyadic = convertExactly
instance ConvertibleExactly MPFloat Dyadic where
safeConvertExactly = Right . Dyadic
instance HasIntegerBounds Dyadic where
integerBounds d = (floor d, ceiling d)
instance ConvertibleExactly Integer Dyadic where
safeConvertExactly = fmap Dyadic . safeConvertExactly
instance ConvertibleExactly Int Dyadic where
safeConvertExactly = fmap Dyadic . safeConvertExactly
instance ConvertibleExactly Rational Dyadic where
safeConvertExactly q
| isDyadic = Right $ Dyadic (fromRationalUp (prec $ max 2 (dp + np + 1)) q)
| otherwise = convError "this number is not dyadic" q
where
isDyadic = d == 2^!dp
dp = integerLog2 d
d = denominator q
np = integerLog2 (max 1 $ abs $ numerator q)
instance Convertible Dyadic Double where
safeConvert = safeConvert . dyadicMPFloat
instance (ConvertibleExactly Dyadic t, Monoid es) => ConvertibleExactly Dyadic (CollectErrors es t) where
safeConvertExactly = fmap (\v -> CollectErrors (Just v) mempty) . safeConvertExactly
instance HasEqAsymmetric Dyadic Dyadic
instance HasEqAsymmetric Dyadic Integer where
equalTo = convertSecond equalTo
instance HasEqAsymmetric Integer Dyadic where
equalTo = convertFirst equalTo
instance HasEqAsymmetric Dyadic Int where
equalTo = convertSecond equalTo
instance HasEqAsymmetric Int Dyadic where
equalTo = convertFirst equalTo
instance HasEqAsymmetric Dyadic Rational where
equalTo = convertFirst equalTo
instance HasEqAsymmetric Rational Dyadic where
equalTo = convertSecond equalTo
instance
(HasEqAsymmetric Dyadic b
, CanEnsureCE es b
, CanEnsureCE es (EqCompareType Dyadic b)
, IsBool (EnsureCE es (EqCompareType Dyadic b))
, SuitableForCE es)
=>
HasEqAsymmetric Dyadic (CollectErrors es b)
where
type EqCompareType Dyadic (CollectErrors es b) =
EnsureCE es (EqCompareType Dyadic b)
equalTo = lift2TLCE equalTo
instance
(HasEqAsymmetric a Dyadic
, CanEnsureCE es a
, CanEnsureCE es (EqCompareType a Dyadic)
, IsBool (EnsureCE es (EqCompareType a Dyadic))
, SuitableForCE es)
=>
HasEqAsymmetric (CollectErrors es a) Dyadic
where
type EqCompareType (CollectErrors es a) Dyadic =
EnsureCE es (EqCompareType a Dyadic)
equalTo = lift2TCE equalTo
instance CanTestZero Dyadic
instance HasOrderAsymmetric Dyadic Dyadic
instance HasOrderAsymmetric Dyadic Integer where
lessThan = convertSecond lessThan
leq = convertSecond leq
instance HasOrderAsymmetric Integer Dyadic where
lessThan = convertFirst lessThan
leq = convertFirst leq
instance HasOrderAsymmetric Dyadic Int where
lessThan = convertSecond lessThan
leq = convertSecond leq
instance HasOrderAsymmetric Int Dyadic where
lessThan = convertFirst lessThan
leq = convertFirst leq
instance HasOrderAsymmetric Rational Dyadic where
lessThan = convertSecond lessThan
leq = convertSecond leq
instance HasOrderAsymmetric Dyadic Rational where
lessThan = convertFirst lessThan
leq = convertFirst leq
instance
(HasOrderAsymmetric Dyadic b
, CanEnsureCE es b
, CanEnsureCE es (OrderCompareType Dyadic b)
, IsBool (EnsureCE es (OrderCompareType Dyadic b))
, SuitableForCE es)
=>
HasOrderAsymmetric Dyadic (CollectErrors es b)
where
type OrderCompareType Dyadic (CollectErrors es b) =
EnsureCE es (OrderCompareType Dyadic b)
lessThan = lift2TLCE lessThan
leq = lift2TLCE leq
greaterThan = lift2TLCE greaterThan
geq = lift2TLCE geq
instance
(HasOrderAsymmetric a Dyadic
, CanEnsureCE es a
, CanEnsureCE es (OrderCompareType a Dyadic)
, IsBool (EnsureCE es (OrderCompareType a Dyadic))
, SuitableForCE es)
=>
HasOrderAsymmetric (CollectErrors es a) Dyadic
where
type OrderCompareType (CollectErrors es a) Dyadic =
EnsureCE es (OrderCompareType a Dyadic)
lessThan = lift2TCE lessThan
leq = lift2TCE leq
greaterThan = lift2TCE greaterThan
geq = lift2TCE geq
instance CanTestPosNeg Dyadic
instance CanTestInteger Dyadic where
certainlyNotInteger = certainlyNotInteger . rational
certainlyIntegerGetIt = certainlyIntegerGetIt . rational
instance CanNeg Dyadic where
negate = lift1 negate
instance CanAbs Dyadic where
abs = lift1 abs
lift1 :: (MPFloat -> MPFloat) -> (Dyadic -> Dyadic)
lift1 op (Dyadic x) = Dyadic (op x)
instance CanMinMaxAsymmetric Dyadic Dyadic
instance CanMinMaxAsymmetric Integer Dyadic where
type MinMaxType Integer Dyadic = Dyadic
min = convertFirst min
max = convertFirst max
instance CanMinMaxAsymmetric Dyadic Integer where
type MinMaxType Dyadic Integer = Dyadic
min = convertSecond min
max = convertSecond max
instance CanMinMaxAsymmetric Int Dyadic where
type MinMaxType Int Dyadic = Dyadic
min = convertFirst min
max = convertFirst max
instance CanMinMaxAsymmetric Dyadic Int where
type MinMaxType Dyadic Int = Dyadic
min = convertSecond min
max = convertSecond max
instance CanMinMaxAsymmetric Rational Dyadic where
type MinMaxType Rational Dyadic = Rational
min = convertSecond min
max = convertSecond max
instance CanMinMaxAsymmetric Dyadic Rational where
type MinMaxType Dyadic Rational = Rational
min = convertFirst min
max = convertFirst max
instance
(CanMinMaxAsymmetric Dyadic b
, CanEnsureCE es b
, CanEnsureCE es (MinMaxType Dyadic b)
, SuitableForCE es)
=>
CanMinMaxAsymmetric Dyadic (CollectErrors es b)
where
type MinMaxType Dyadic (CollectErrors es b) =
EnsureCE es (MinMaxType Dyadic b)
min = lift2TLCE min
max = lift2TLCE max
instance
(CanMinMaxAsymmetric a Dyadic
, CanEnsureCE es a
, CanEnsureCE es (MinMaxType a Dyadic)
, SuitableForCE es)
=>
CanMinMaxAsymmetric (CollectErrors es a) Dyadic
where
type MinMaxType (CollectErrors es a) Dyadic =
EnsureCE es (MinMaxType a Dyadic)
min = lift2TCE min
max = lift2TCE max
instance CanAddAsymmetric Dyadic Dyadic where
add = lift2 addDown addUp
instance CanAddAsymmetric Integer Dyadic where
type AddType Integer Dyadic = Dyadic
add = convertFirst add
instance CanAddAsymmetric Dyadic Integer where
type AddType Dyadic Integer = Dyadic
add = convertSecond add
instance CanAddAsymmetric Int Dyadic where
type AddType Int Dyadic = Dyadic
add = convertFirst add
instance CanAddAsymmetric Dyadic Int where
type AddType Dyadic Int = Dyadic
add = convertSecond add
instance CanAddAsymmetric Rational Dyadic where
type AddType Rational Dyadic = Rational
add = convertSecond add
instance CanAddAsymmetric Dyadic Rational where
type AddType Dyadic Rational = Rational
add = convertFirst add
instance
(CanAddAsymmetric Dyadic b
, CanEnsureCE es b
, CanEnsureCE es (AddType Dyadic b)
, SuitableForCE es)
=>
CanAddAsymmetric Dyadic (CollectErrors es b)
where
type AddType Dyadic (CollectErrors es b) =
EnsureCE es (AddType Dyadic b)
add = lift2TLCE add
instance
(CanAddAsymmetric a Dyadic
, CanEnsureCE es a
, CanEnsureCE es (AddType a Dyadic)
, SuitableForCE es)
=>
CanAddAsymmetric (CollectErrors es a) Dyadic
where
type AddType (CollectErrors es a) Dyadic =
EnsureCE es (AddType a Dyadic)
add = lift2TCE add
instance CanSub Dyadic Dyadic where
sub = lift2 subDown subUp
instance CanSub Integer Dyadic where
type SubType Integer Dyadic = Dyadic
sub = convertFirst sub
instance CanSub Dyadic Integer where
type SubType Dyadic Integer = Dyadic
sub = convertSecond sub
instance CanSub Int Dyadic where
type SubType Int Dyadic = Dyadic
sub = convertFirst sub
instance CanSub Dyadic Int where
type SubType Dyadic Int = Dyadic
sub = convertSecond sub
instance CanSub Rational Dyadic where
type SubType Rational Dyadic = Rational
sub = convertSecond sub
instance CanSub Dyadic Rational where
type SubType Dyadic Rational = Rational
sub = convertFirst sub
instance
(CanSub Dyadic b
, CanEnsureCE es b
, CanEnsureCE es (SubType Dyadic b)
, SuitableForCE es)
=>
CanSub Dyadic (CollectErrors es b)
where
type SubType Dyadic (CollectErrors es b) =
EnsureCE es (SubType Dyadic b)
sub = lift2TLCE sub
instance
(CanSub a Dyadic
, CanEnsureCE es a
, CanEnsureCE es (SubType a Dyadic)
, SuitableForCE es)
=>
CanSub (CollectErrors es a) Dyadic
where
type SubType (CollectErrors es a) Dyadic =
EnsureCE es (SubType a Dyadic)
sub = lift2TCE sub
instance CanMulAsymmetric Dyadic Dyadic where
mul = lift2 mulDown mulUp
instance CanMulAsymmetric Integer Dyadic where
type MulType Integer Dyadic = Dyadic
mul = convertFirst mul
instance CanMulAsymmetric Dyadic Integer where
type MulType Dyadic Integer = Dyadic
mul = convertSecond mul
instance CanMulAsymmetric Int Dyadic where
type MulType Int Dyadic = Dyadic
mul = convertFirst mul
instance CanMulAsymmetric Dyadic Int where
type MulType Dyadic Int = Dyadic
mul = convertSecond mul
instance CanMulAsymmetric Rational Dyadic where
type MulType Rational Dyadic = Rational
mul = convertSecond mul
instance CanMulAsymmetric Dyadic Rational where
type MulType Dyadic Rational = Rational
mul = convertFirst mul
instance
(CanMulAsymmetric Dyadic b
, CanEnsureCE es b
, CanEnsureCE es (MulType Dyadic b)
, SuitableForCE es)
=>
CanMulAsymmetric Dyadic (CollectErrors es b)
where
type MulType Dyadic (CollectErrors es b) =
EnsureCE es (MulType Dyadic b)
mul = lift2TLCE mul
instance
(CanMulAsymmetric a Dyadic
, CanEnsureCE es a
, CanEnsureCE es (MulType a Dyadic)
, SuitableForCE es)
=>
CanMulAsymmetric (CollectErrors es a) Dyadic
where
type MulType (CollectErrors es a) Dyadic =
EnsureCE es (MulType a Dyadic)
mul = lift2TCE mul
instance CanPow Dyadic Integer where
powNoCN = powUsingMul (dyadic 1)
pow = integerPowCN (powUsingMul (dyadic 1))
instance CanPow Dyadic Int where
powNoCN = powUsingMul (dyadic 1)
pow = integerPowCN (powUsingMul (dyadic 1))
instance
(CanDiv a Dyadic
, CanEnsureCE es a
, CanEnsureCE es (DivType a Dyadic)
, CanEnsureCE es (DivTypeNoCN a Dyadic)
, SuitableForCE es)
=>
CanDiv (CollectErrors es a) Dyadic
where
type DivType (CollectErrors es a) Dyadic =
EnsureCE es (DivType a Dyadic)
divide = lift2TCE divide
type DivTypeNoCN (CollectErrors es a) Dyadic =
EnsureCE es (DivTypeNoCN a Dyadic)
divideNoCN = lift2TCE divideNoCN
instance CanDiv Integer Dyadic where
type DivTypeNoCN Integer Dyadic = Rational
divideNoCN a b = divideNoCN a (rational b)
instance CanDiv Dyadic Integer where
type DivTypeNoCN Dyadic Integer = Rational
divideNoCN a b = divideNoCN (rational a) b
instance CanDiv Int Dyadic where
type DivTypeNoCN Int Dyadic = Rational
divideNoCN a b = divideNoCN a (rational b)
instance CanDiv Dyadic Int where
type DivTypeNoCN Dyadic Int = Rational
divideNoCN a b = divideNoCN (rational a) b
instance CanDiv Rational Dyadic where
type DivTypeNoCN Rational Dyadic = Rational
divideNoCN = convertSecond divideNoCN
instance CanDiv Dyadic Rational where
type DivTypeNoCN Dyadic Rational = Rational
divideNoCN = convertFirst divideNoCN
instance
(CanDiv Dyadic b
, CanEnsureCE es b
, CanEnsureCE es (DivType Dyadic b)
, CanEnsureCE es (DivTypeNoCN Dyadic b)
, SuitableForCE es)
=>
CanDiv Dyadic (CollectErrors es b)
where
type DivType Dyadic (CollectErrors es b) =
EnsureCE es (DivType Dyadic b)
divide = lift2TLCE divide
type DivTypeNoCN Dyadic (CollectErrors es b) =
EnsureCE es (DivTypeNoCN Dyadic b)
divideNoCN = lift2TLCE divideNoCN
instance
(CanPow Dyadic b
, CanEnsureCE es b
, CanEnsureCE es (PowTypeNoCN Dyadic b)
, CanEnsureCE es (PowType Dyadic b)
, SuitableForCE es)
=>
CanPow Dyadic (CollectErrors es b)
where
type PowTypeNoCN Dyadic (CollectErrors es b) =
EnsureCE es (PowTypeNoCN Dyadic b)
powNoCN = lift2TLCE powNoCN
type PowType Dyadic (CollectErrors es b) =
EnsureCE es (PowType Dyadic b)
pow = lift2TLCE pow
instance
(CanPow a Dyadic
, CanEnsureCE es a
, CanEnsureCE es (PowType a Dyadic)
, CanEnsureCE es (PowTypeNoCN a Dyadic)
, SuitableForCE es)
=>
CanPow (CollectErrors es a) Dyadic
where
type PowTypeNoCN (CollectErrors es a) Dyadic =
EnsureCE es (PowTypeNoCN a Dyadic)
powNoCN = lift2TCE powNoCN
type PowType (CollectErrors es a) Dyadic =
EnsureCE es (PowType a Dyadic)
pow = lift2TCE pow
lift2 ::
(MPFloat -> MPFloat -> MPFloat) ->
(MPFloat -> MPFloat -> MPFloat) ->
(Dyadic -> Dyadic -> Dyadic)
lift2 opDown opUp (Dyadic x0) (Dyadic y0) = Dyadic (opExact x0 y0)
where
opExact x y
| rUp == rDown = rUp
| otherwise =
maybeTrace (printf "Dyadic.lift2: rUp = %s; rDown = %s; p = %s" (show rUp) (show rDown) (show $ integer p)) $
opExact xH yH
where
rUp = opUp x y
rDown = opDown x y
xH = setPrecision pH x
yH = setPrecision pH y
pH = precisionTimes2 p
p = getPrecision rUp
instance Arbitrary Dyadic where
arbitrary =
do
c <- finiteMPFloat
return (Dyadic c)
where
finiteMPFloat =
do
x <- arbitrary
if isFinite x
then return x
else finiteMPFloat
tDyadic :: T Dyadic
tDyadic = T "Dyadic"
specDyadic :: Spec
specDyadic =
describe ("Dyadic") $ do
specConversion tInteger tDyadic dyadic round
specConversion tDyadic tRational rational dyadic
describe "order" $ do
specHasEqNotMixed tDyadic
specHasEq tInt tDyadic tRational
specCanTestZero tDyadic
specHasOrderNotMixed tDyadic
specHasOrder tInt tDyadic tRational
describe "min/max/abs" $ do
specCanNegNum tDyadic
specCanAbs tDyadic
specCanMinMaxNotMixed tDyadic
specCanMinMax tDyadic tInteger tDyadic
it "min Dyadic Rational (dyadic only)" $ do
property $ \ (x :: Dyadic) (y :: Dyadic) ->
x `min` y == x `min` (rational y)
it "max Dyadic Rational (dyadic only)" $ do
property $ \ (x :: Dyadic) (y :: Dyadic) ->
x `max` y == x `max` (rational y)
describe "ring" $ do
specCanAddNotMixed tDyadic
specCanAddSameType tDyadic
specCanAdd tInt tDyadic tInteger
specCanAdd tInteger tDyadic tInt
it "Dyadic + Rational (dyadic only)" $ do
property $ \ (x :: Dyadic) (y :: Dyadic) ->
x + y == x + (rational y)
specCanSubNotMixed tDyadic
specCanSub tDyadic tInteger
specCanSub tInteger tDyadic
specCanSub tDyadic tInt
specCanSub tInt tDyadic
it "Dyadic - Rational (dyadic only)" $ do
property $ \ (x :: Dyadic) (y :: Dyadic) ->
x y == x (rational y)
specCanMulNotMixed tDyadic
specCanMulSameType tDyadic
specCanMul tInt tDyadic tInteger
it "Dyadic * Rational (dyadic only)" $ do
property $ \ (x :: Dyadic) (y :: Dyadic) ->
x * y == x * (rational y)
specCanPow tDyadic tInteger
instance P.Num Dyadic where
fromInteger = convertExactly
negate = negate
(+) = (+)
(*) = (*)
abs = abs
signum d
| d < 0 = dyadic (1)
| d == 0 = dyadic 0
| otherwise = dyadic 1
instance P.Real Dyadic where
toRational = convertExactly