packages feed

AERN-Real (empty) → 0.9.0

raw patch · 23 files changed

+4187/−0 lines, 23 filesdep +basedep +binarydep +containerssetup-changed

Dependencies added: base, binary, containers

Files

+ AERN-Real.cabal view
@@ -0,0 +1,81 @@+Name:           AERN-Real+Version:        0.9.0+Cabal-Version:  >= 1.2+Build-Type:     Simple+License:        BSD3+License-File:   LICENCE+Author:         Michal Konecny+Copyright:      (c) 2007-2008 Michal Konecny, Amin Farjudian, Jan Duracz +Maintainer:     Michal Konecny+Stability:      experimental+Category:       Data, Math+Synopsis:       datatypes and abstractions for approximating exact real numbers+Tested-with:    GHC ==6.8.2+Description:+    Datatypes and abstractions for approximating exact real numbers+    and a basic arithmetic over such approximations.  The design is+    inspired to some degree by Mueller's iRRAM and Lambov's RealLib+    (both are C++ libraries for exact real arithmetic).+    .+    Abstractions are provided via 4 type classes:+    .+    * ERRealBase: abstracts floating point numbers+    .+    * ERApprox: abstracts neighbourhoods of real numbers+    .+    * ERIntApprox: abstracts neighbourhoods of real numbers that are known to be intervals+    .+    * ERApproxElementary: abstracts real number approximations that support elementary operations+    .+    For ERRealBase we give several implementations.  The default is +    an arbitrary precision floating point type that uses Double+    for lower precisions and an Integer-based simulation for higher+    precisions.  Rational numbers can be used as one of the alternatives.+    Augustsson's Data.Number.BigFloat can be easily wrapped as an instance+    of ERRealBase except that it uses a different method to control precision.+    .+    ERIntApprox is implemented via outwards-rounded arbitrary precision interval arithmetic.  +    Any instance of ERRealBase can be used for the endpoints of the intervals.+    .+    ERApproxElementary is implemented generically for any implementation+    of ERIntApprox.  This way some of the most common elementary operations are provided, +    notably: sqrt, exp, log, sin, cos, atan.  These operations converge +    to an arbitrary precision and also work well over larger intervals without+    excessive wrapping.+    .+    There is also some support for generic Taylor series, interval Newton method+    and simple numerical integration.++Flag containers-in-base++Library+  hs-source-dirs:  src+  if flag(containers-in-base)+    Build-Depends:+      base < 3, binary >= 0.4+  else+    Build-Depends:+      base >= 3, containers, binary >= 0.4+  Exposed-modules:+    Data.Number.ER,+    Data.Number.ER.Real,+    Data.Number.ER.Real.DefaultRepr,+    Data.Number.ER.Real.Base.MachineDouble,+    Data.Number.ER.Real.Base.CombinedMachineAP,+    Data.Number.ER.Real.Base.Rational,+    Data.Number.ER.Real.Base.Float,+    Data.Number.ER.Real.Base,+    Data.Number.ER.Real.Arithmetic.Elementary,+    Data.Number.ER.Real.Arithmetic.Integration,+    Data.Number.ER.Real.Arithmetic.Taylor,+    Data.Number.ER.Real.Arithmetic.Newton,+    Data.Number.ER.Real.Approx.Sequence,+    Data.Number.ER.Real.Approx.Elementary,+    Data.Number.ER.Real.Approx.Interval,+    Data.Number.ER.Real.Approx,+    Data.Number.ER.PlusMinus,+    Data.Number.ER.BasicTypes,+    Data.Number.ER.Misc,+    Data.Number.ER.ExtendedInteger+  Extensions: DeriveDataTypeable, ForeignFunctionInterface, ScopedTypeVariables+  
+ LICENCE view
@@ -0,0 +1,30 @@+Copyright (c) 2007-2008 Michal Konecny, Amin Farjudian, Jan Duracz++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of his contributors+   may be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ Setup.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ src/Data/Number/ER.hs view
@@ -0,0 +1,25 @@+{-|+    Module      :  Data.Number.ER+    Description :  top level of the exactreals framework+    Copyright   :  (c) Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  non-portable (requires fenv.h)++    This namespace is the root for the AERN family of packages.+    AERN stands for Approximated Exact Real Numbers.+    All AERN packages build on the package AERN-Real.+    +    Module "Data.Number.ER.Real" contains an overview+    of the AERN-Real package.+    +-}+module Data.Number.ER +(+    module Data.Number.ER.Real+)+where++import Data.Number.ER.Real
+ src/Data/Number/ER/BasicTypes.hs view
@@ -0,0 +1,92 @@+{-|+    Module      :  Data.Number.ER.BasicTypes+    Description :  generic types for exact real number processing +    Copyright   :  (c) Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  portable++    generic types for exact real number processing+-}+module Data.Number.ER.BasicTypes +where++import qualified Data.Number.ER.ExtendedInteger as EI++import qualified Data.Map as Map++{-|+    Precision represents an upper bound on the measure of +    an approximation viewed as a set;+    not to be confused with the precision of +    an 'Data.Number.ER.Real.Base.Float.ERFloat' and similar.+     +    In an approximation comprising a number of+    instances of 'Data.Number.ER.Real.Base.ERRealBase',+    we will refer to the bit-precision of these base components+    as the 'Granularity' of the approximation.+-}+type Precision = EI.ExtendedInteger++{-|+  The bit size of the floating point numbers (or similar)+  used internally in real number and function approximations.+-}+type Granularity = Int++prec2gran :: Precision -> Granularity+prec2gran = fromInteger . toInteger++{-|+    This type synonym should be used for funciton parameter(s)+    that guide the convergence of the function's result to+    a perfect (exact) result.  +    +    The name should remind us +    that there is no universally valid relationship between+    this integer the quality (precision) of the result.    +    The only condition usually assumed is that in the limit+    when the effort index rises to infinity, the result +    should be exact.+-}+type EffortIndex = Integer++effIx2gran :: EffortIndex -> Granularity+effIx2gran  = fromInteger . toInteger++effIx2prec :: EffortIndex -> Precision+effIx2prec = fromInteger . toInteger++effIx2int :: EffortIndex -> Int+effIx2int = fromInteger . toInteger++int2effIx :: Int -> EffortIndex+int2effIx = fromInteger . toInteger++prec2effIx :: Precision -> EffortIndex+prec2effIx = fromInteger . toInteger++gran2effIx :: Granularity -> EffortIndex+gran2effIx = fromInteger . toInteger++{-| +    A variable identifier for axes in function domains, polynomials etc.+-}+type VarID = Int+defaultVar :: VarID+defaultVar = 0++{-|+    A many-dimensional point or interval.+-}+type Box ira = Map.Map VarID ira++{-| using 'defaultVar' -}+unaryDom :: ira -> Box ira+unaryDom r = Map.singleton defaultVar r++noinfoDom :: Box ira+noinfoDom = Map.empty+ 
+ src/Data/Number/ER/ExtendedInteger.hs view
@@ -0,0 +1,125 @@+{-|+    Module      :  Data.Number.ER.ExtendedInteger+    Description :  integer with infinities +    Copyright   :  (c) Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  portable+    +    An arbitrary sized integer type with additional +infinity and -infinity.+    +    To be imported qualified, usually with prefix EI. +-}+module Data.Number.ER.ExtendedInteger +(+    ExtendedInteger(..),+    isInfinite, binaryLog, take+)+where++import Prelude hiding (isInfinite, take)+import qualified Prelude++data ExtendedInteger+    = MinusInfinity | Finite Integer | PlusInfinity+    deriving (Eq)++isInfinite :: ExtendedInteger -> Bool+isInfinite MinusInfinity = True+isInfinite PlusInfinity = True+isInfinite _ = False++{-|+    the smallest integer i for which 2^i <=  abs n+-}+binaryLog :: ExtendedInteger -> ExtendedInteger+binaryLog PlusInfinity = PlusInfinity+binaryLog MinusInfinity = PlusInfinity+binaryLog (Finite n) +    | n < 0 = binaryLog (Finite (- n))+    | n == 0 = MinusInfinity+    | otherwise = -- (n > 0)+        -- how to do this fast?+        intBinaryLog n++intBinaryLog n +    | n > 1 = 1 + (intBinaryLog (n `div` 2))+    | n == 1 = 0++instance Show ExtendedInteger where+    show MinusInfinity = "-InfInt"+    show PlusInfinity = "+InfInt"+    show (Finite i) = show i++take :: ExtendedInteger -> [a] -> [a]+take MinusInfinity _ = error "takeEI called with MinusInfinity"+take PlusInfinity list = list+take (Finite n) list = Prelude.take (fromInteger n) list++instance Ord ExtendedInteger where+    compare MinusInfinity MinusInfinity = EQ+    compare MinusInfinity _ = LT+    compare _ MinusInfinity = GT+    compare PlusInfinity PlusInfinity = EQ+    compare PlusInfinity _ = GT+    compare _ PlusInfinity = LT+    compare (Finite i1) (Finite i2) =+        compare i1 i2++instance Num ExtendedInteger where+    fromInteger i = Finite i+    {- abs -}+    abs MinusInfinity = PlusInfinity+    abs PlusInfinity = PlusInfinity+    abs (Finite i) = Finite $ abs i+    {- signum -}+    signum ei+        | ei < 0 = -1+        | ei > 0 = 1+        | otherwise = 0+    {- negate -}+    negate (Finite i) = Finite (-i)+    negate MinusInfinity = PlusInfinity+    negate PlusInfinity = MinusInfinity+    {- addition -}+    PlusInfinity + MinusInfinity = +        error "cannot add PlusInfinity and MinusInfinity"+    MinusInfinity + PlusInfinity = +        error "cannot add PlusInfinity and MinusInfinity"+    PlusInfinity + ei = PlusInfinity+    ei + PlusInfinity = PlusInfinity+    MinusInfinity + ei = MinusInfinity+    ei + MinusInfinity = MinusInfinity+    (Finite i1) + (Finite i2) = Finite $ i1 + i2+    {- multiplication -}+    ei1 * ei2 | ei1 > ei2 = ei2 * ei1+    MinusInfinity * ei +        | ei < 0 = PlusInfinity+        | ei > 0 = MinusInfinity+        | otherwise = error "cannot multiply MinusInfinity and 0"+    ei * PlusInfinity+        | ei < 0 = MinusInfinity+        | ei > 0 = PlusInfinity+        | otherwise = error "cannot multiply PlusInfinity and 0"+    (Finite i1) * (Finite i2) = Finite $ i1 * i2++instance Enum ExtendedInteger where+    toEnum i = Finite $ toInteger i+    fromEnum (Finite i) = fromInteger i+    fromEnum _ = error "infinite integers cannot be enumerated"++instance Real ExtendedInteger where+    toRational (Finite i) = toRational i+    toRational _ = error "infinite integers cannot be converted to rational"+    +instance Integral ExtendedInteger where+    quotRem (Finite i) (Finite m) = +        (Finite a, Finite b)+        where+        (a,b) = quotRem i m+    quotRem _ _ = error "cannot make a quotient involving an infinite integer"+    toInteger (Finite i) = i+    toInteger _ = error "infinite integers cannot be converted to Integer"+        
+ src/Data/Number/ER/Misc.hs view
@@ -0,0 +1,268 @@+{-|+    Module      :  Data.Number.ER.Misc+    Description :  general purpose extras +    Copyright   :  (c) Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  portable+    +    Miscelaneous utilities (eg related to Ordering, pairs, booleans, strings)+-}+module Data.Number.ER.Misc where++import List+import System.IO.Unsafe++unsafePrint msg val =+    unsafePerformIO $+        do+        putStrLn $ "unsafe: " ++ msg+        return val++{-|+    Compose as when defining the lexicographical ordering.+-}+compareCompose :: Ordering -> Ordering -> Ordering+compareCompose EQ o = o+compareCompose o _ = o++{-|+    Compose as when defining the lexicographical ordering.+-}+compareComposeMany :: [Ordering] -> Ordering+compareComposeMany [] = EQ+compareComposeMany (EQ:os) = compareComposeMany os+compareComposeMany (o:_) = o++{-|+    The lexicographical ordering.+-}+compareLex :: (Ord a) => [a] -> [a] -> Ordering+compareLex [] _ = LT+compareLex _ [] = GT+compareLex (x:xs) (y:ys)+    | x == y = compareLex xs ys+    | otherwise = compare x y++mapFst :: (a1 -> a2) -> (a1,b) -> (a2,b)     +mapFst f (a,b) = (f a,b)+mapSnd :: (b1 -> b2) -> (a,b1) -> (a,b2)     +mapSnd f (a,b) = (a,f b)+mapPair :: (a1 -> a2, b1 -> b2) -> (a1,b1) -> (a2,b2)     +mapPair (f1, f2) (a,b) = (f1 a, f2 b)+mapPairHomog :: (a1 -> a2) -> (a1,a1) -> (a2,a2)     +mapPairHomog f = mapPair (f,f) ++unpair :: [(a,a)] -> [a]+unpair = (\(l1,l2) -> l1 ++ l2) . unzip++bool2maybe :: Bool -> Maybe ()+bool2maybe True = Just ()+bool2maybe False = Nothing++dropLast :: Int -> [a] -> [a]+dropLast n list = reverse $ drop n (reverse list)++{-|+    eg ++>    concatWith "," ["a","b"] = "a,b"++-}+concatWith :: +    String {-^ a connective -} -> +    [String] -> +    String+concatWith sep [] = ""+concatWith sep [str] = str+concatWith sep (str : strs) = str ++ sep ++ (concatWith sep strs)+    +{-|+    eg ++>    replicateSeveral [(2,"a"),(1,"b")] = "aab"++-}+replicateSeveral :: [(Int,a)] -> [a]+replicateSeveral [] = []+replicateSeveral ((n,e):rest) =+    replicate n e ++ (replicateSeveral rest)+    +{-|+    eg ++>    countDuplicates "aaba" = [(2,"a"),(1,"b"),(1,"a")]++-}+countDuplicates :: +    Eq a => +    [a] -> +    [(Int,a)]+countDuplicates list =+    map (\ g -> (length g, head g)) $ group list+    +{-|+    eg+    +>    allCombinations +>        [+>         (1,['a']), +>         (2,['b','c']), +>         (3,['d','e','f'])+>        ] =+>            [+>             [(1,'a'),(2,'b'),(3,'d')], +>             [(1,'a'),(2,'b'),(3,'e')],+>             [(1,'a'),(2,'b'),(3,'f')],+>             [(1,'a'),(2,'c'),(3,'d')], +>             [(1,'a'),(2,'c'),(3,'e')],+>             [(1,'a'),(2,'c'),(3,'f')]+>            ]+-}+allCombinations :: +    [(k,[v])] -> [[(k,v)]]+allCombinations [] = [[]]+allCombinations ((k, vals) : rest) =+    concat $ map (\ v -> map ((k,v):) restCombinations) vals+    where+    restCombinations = +        allCombinations rest++allPairsCombinations ::+    [(k,(v,v))] -> [[(k,v)]]+allPairsCombinations [] = [[]]+allPairsCombinations ((k, (v1,v2)) : rest) =+    (map ((k, v1) :) restCombinations)+    +++    (map ((k, v2) :) restCombinations)+    where+    restCombinations =+        allPairsCombinations rest+    +    +{-|+    eg+    +>    allPairsCombinationsEvenOdd +>        [+>         (1,('a0','a1'), +>         (2,('b0','b1'), +>         (3,('c0','c1')+>        ] =+>           ([+>             [(1,'a0'),(2,'b0'),(3,'c0')], +>             [(1,'a0'),(2,'b1'),(3,'c1')], +>             [(1,'a1'),(2,'b1'),(3,'c0')], +>             [(1,'a1'),(2,'b0'),(3,'c1')] +>            ]+>           ,[+>             [(1,'a0'),(2,'b0'),(3,'c1')], +>             [(1,'a0'),(2,'b1'),(3,'c0')], +>             [(1,'a1'),(2,'b0'),(3,'c0')], +>             [(1,'a1'),(2,'b1'),(3,'c1')] +>            ]+>           )+-}+allPairsCombinationsEvenOdd ::+    [(k,(v,v))] {-^ the first value is even, the second odd -} -> +    ([[(k,v)]], [[(k,v)]])+allPairsCombinationsEvenOdd [] = ([[]], [])+allPairsCombinationsEvenOdd ((k, (evenVal,oddVal)) : rest) =+    (+        (map ((k, evenVal) :) restCombinationsEven)+        +++        (map ((k, oddVal) :) restCombinationsOdd)+    ,+        (map ((k, evenVal) :) restCombinationsOdd)+        +++        (map ((k, oddVal) :) restCombinationsEven)+    )+    where+    (restCombinationsEven, restCombinationsOdd) =+        allPairsCombinationsEvenOdd rest+    +    +    +{- numeric -}    +    +intLog :: +    (Num n1, Num n2, Ord n1) => +    n1 {-^ base -} -> +    n1 {-^ x -} -> +    n2+intLog b n +    | n > 0 = p2+    where+    (p2, pe2) = findSlow (p1, pe1) (p1 + 1, pe1 * b)+    (p1, pe1) = findFast (1, b) (2, b*b)+    findFast (p, pe) (pp, ppe)+        | ppe < n = findFast (pp, ppe) (2 * pp, ppe * ppe)+        | otherwise = (p, pe)+    findSlow (p, pe) (pp, ppe)+        | ppe < n = findSlow (pp, ppe) (pp + 1, ppe * b)+        | otherwise = (pp, ppe)        ++{-|+    Directionally rounded versions of @+,*,sum,prod@.+-}+plusUp, plusDown, timesUp, timesDown :: +    (Num t) =>+    t -> t -> t+sumUp, sumDown, productDown, productUp :: +    (Num t) =>+    [t] -> t+plusUp = (+)+plusDown c1 c2 = - ((- c1) - c2)+sumUp = foldl plusUp 0+sumDown = foldl plusDown 0+timesUp = (*)+timesDown c1 c2 = - ((- c1) * c2)+productUp = foldl timesUp 1+productDown = foldl timesDown 1++{- parsing -}+readMaybe :: (Read a) => String -> Maybe a+readMaybe s =+    case reads s of+        [] -> Nothing+        (val,_) : _ -> Just val++    +{- sequences -}+listUpdate :: Int -> a -> [a] -> [a]+listUpdate i newx (x:xs) +    | i == 0 = newx : xs+    | i > 0 = x : (listUpdate (i - 1) newx xs) +++listHasMatch :: (a -> Bool) -> [a] -> Bool+listHasMatch f s =+    foldl (\b a -> b && (f a)) False s+    +--{-| types encoding natural numbers -}+--class TypeNumber n+--    where+--    getTNData :: n+--    getTNNumber :: n -> Int+--+--data TN_0 = TN_0+--tn_0 = TN_0+--data TN_SUCC tn_prev = TN_SUCC tn_prev+--+--type TN_ONE = TN_SUCC TN_0+--tn_1 = TN_SUCC TN_0+--+--instance (TypeNumber TN_0)+--    where+--    getTNData = TN_0+--    getTNNumber _ = 0+--    +--instance +--    (TypeNumber tn_prev) => +--    (TypeNumber (TN_SUCC tn_prev))+--    where+--    getTNData = TN_SUCC getTNData+--    getTNNumber (TN_SUCC p) = 1 + (getTNNumber p)+    
+ src/Data/Number/ER/PlusMinus.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE DeriveDataTypeable   #-}+{-|+    Module      :  Data.Number.ER.PlusMinus+    Description :  mini sign datatype+    Copyright   :  (c) Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  portable+    +    A mini enumeration to represent the sign of different numbers and approximations.+-}+module Data.Number.ER.PlusMinus where++import Data.Typeable+import Data.Generics.Basics+import Data.Binary+--import BinaryDerive++data PlusMinus = Minus | Plus+    deriving (Eq, Ord, Typeable, Data)++instance Show PlusMinus where+    show Plus = "+"+    show Minus = "-"++{- the following has been generated by BinaryDerive -}+instance Binary PlusMinus where+  put Minus = putWord8 0+  put Plus = putWord8 1+  get = do+    tag_ <- getWord8+    case tag_ of+      0 -> return Minus+      1 -> return Plus+      _ -> fail "no parse"+{- the above has been generated by BinaryDerive -}++signNeg Plus = Minus+signNeg Minus = Plus++signMult Plus s = s+signMult Minus s = signNeg s++signToNum Plus = 1+signToNum Minus = -1
+ src/Data/Number/ER/Real.hs view
@@ -0,0 +1,70 @@+{-|+    Module      :  Data.Number.ER.Real+    Description :  overview of AERN-Real+    Copyright   :  (c) Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  non-portable (requires fenv.h)++    Datatypes and abstractions for approximating exact real numbers+    and a basic arithmetic over such approximations.  The design is+    inspired to some degree by Mueller's iRRAM and Lambov's RealLib+    (both are C++ libraries for exact real arithmetic).+    +    Abstractions are provided via 4 type classes:+     +     * 'B.ERRealBase': abstracts floating point numbers+     +     * 'RA.ERApprox': abstracts neighbourhoods of real numbers+     +     * 'RA.ERIntApprox': abstracts neighbourhoods of real numbers that are known to be intervals++     * 'RAEL.ERApproxElementary': abstracts real number approximations that support elementary operations++    For ERRealBase we give several implementations.  The default is +    an arbitrary precision floating point type that uses Double+    for lower precisions and an Integer-based simulation for higher+    precisions.  Rational numbers can be used as one of the alternatives.+    Augustsson's Data.Number.BigFloat can be easily wrapped as an instance+    of ERRealBase except that it uses a different method to control precision.+    +    ERIntApprox is implemented via outwards-rounded arbitrary precision interval arithmetic.  +    Any instance of ERRealBase can be used for the endpoints of the intervals.+    +    ERApproxElementary is implemented generically for any implementation+    of ERIntApprox.  This way some of the most common elementary operations are provided, +    notably: sqrt, exp, log, sin, cos, atan.  These operations converge +    to an arbitrary precision and also work well over larger intervals without+    excessive wrapping.+    +    There is also some support for generic Taylor series, interval Newton method+    and simple numerical integration.+    +-}+module Data.Number.ER.Real +(+    B.ERRealBase,+    RA.ERApprox,+    RA.ERIntApprox,+    RAEL.ERApproxElementary,+    module Data.Number.ER.Real.DefaultRepr,+    module Data.Number.ER.Real.Approx.Sequence,+    module Data.Number.ER.Real.Arithmetic.Taylor,+    module Data.Number.ER.Real.Arithmetic.Newton,+    module Data.Number.ER.Real.Arithmetic.Integration,+    module Data.Number.ER.BasicTypes+)+where++import Data.Number.ER.Real.DefaultRepr+import Data.Number.ER.BasicTypes+import qualified Data.Number.ER.Real.Base as B+import qualified Data.Number.ER.Real.Approx as RA+import qualified Data.Number.ER.Real.Approx.Elementary as RAEL+import Data.Number.ER.Real.Approx.Sequence+import Data.Number.ER.Real.Arithmetic.Taylor+import Data.Number.ER.Real.Arithmetic.Newton+import Data.Number.ER.Real.Arithmetic.Integration+
+ src/Data/Number/ER/Real/Approx.hs view
@@ -0,0 +1,303 @@+{-|+    Module      :  Data.Number.ER.Real.Approx+    Description :  classes abstracting exact reals+    Copyright   :  (c) Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  portable++    Definitions of classes that describe what is+    required from arbitrary precision approximations+    of exact real numbers.+    +    We introduce two levels of abstraction for these+    approximations:+    +        * 'ERApprox' = +            a *set* of approximated numbers whose size is+            measured using some fixed measure+        +        * 'ERIntApprox' = +            an *interval* of real numbers with finitely+            representable endpoints +    +    To be imported qualified, usually with the synonym RA.+-}+module Data.Number.ER.Real.Approx+(+    ERApprox(..),+    ERIntApprox(..),+    bounds2ira,+    effIx2ra,+    splitIRA,+--    checkShrinking,+--    eqSingletons,+    exactMiddle,+    maxExtensionR2R+)+where++import Data.Number.ER.BasicTypes+import qualified Data.Number.ER.ExtendedInteger as EI++import Data.Typeable++{-|+   A type whose elements represent sets that can be used+   to approximate a single extended real number with arbitrary precision.+-}+class (Fractional ra, Ord ra) => ERApprox ra where+    getPrecision :: ra -> Precision +    {-^ +            Precision is a measure of the set size.+            +            The default interpretation:+            +            * If the diameter of the set is d, then the precision+            should be near floor(- log_2 d).+    -}+    getGranularity :: ra -> Granularity+    -- ^ the lower the granularity the bigger the rounding errors+    setGranularity :: Granularity -> ra -> ra+    -- ^ increase or safely decrease granularity+    setMinGranularity :: Granularity -> ra -> ra+    -- ^ ensure granularity is not below the first arg+    isEmpty :: ra -> Bool +    -- ^ true if this represents a computational error+    isBottom :: ra -> Bool +    -- ^ true if this holds no information+    isExact :: ra -> Bool +    -- ^ true if this is a singleton+    isDisjoint :: ra -> ra -> Bool+    isDisjoint a b = isEmpty $ a /\ b+    isBounded :: ra -> Bool +    -- ^ true if the approximation excludes infinity+    bottomApprox :: ra +    -- ^ the bottom element - any number+    emptyApprox :: ra +    -- ^ the top element - error+    refines :: ra -> ra -> Bool +    -- ^ first arg is a subset of the second arg+    (/\) :: ra -> ra -> ra +    -- ^ join; combining two approximations of the same number+    intersectMeasureImprovement ::+        EffortIndex -> ra -> ra -> (ra, ra)+    {-^ +            Like intersection but the second component:+            +             * measures improvement of the intersection relative to the first of the two approximations+             +             * is a positive number: 1 means no improvement, 2 means doubled precision, etc. +    -}+    equalReals :: ra -> ra -> Maybe Bool +    -- ^ nothing if overlapping and not singletons+    compareReals :: ra -> ra -> Maybe Ordering+    -- ^ nothing if overlapping and not singletons+    leqReals :: ra -> ra -> Maybe Bool+    -- ^ nothing if overlapping on interior or by a wrong endpoint+    equalApprox :: ra -> ra -> Bool+    -- ^ syntactic comparison+    compareApprox :: ra -> ra -> Ordering+    -- ^ syntactic linear ordering+    double2ra :: Double -> ra+    showApprox :: +        Int {-^ number of relevant decimals to show -} ->+        Bool {-^ should show granularity -} ->+        Bool {-^ should show internal representation details -} ->+        ra {-^ the approximation to show -} ->+        String+    +{-|+    Assuming the arguments are singletons, equality is decidable.+-}+eqSingletons :: (ERApprox ra) => ra -> ra -> Bool+eqSingletons s1 s2 =  +    case equalReals s1 s2 of +        Just b -> b+        _ -> False ++{-|+    Assuming the arguments are singletons, @<=@ is decidable.+-}+leqSingletons :: (ERApprox ra) => ra -> ra -> Bool+leqSingletons s1 s2 =  +    case compareReals s1 s2 of +        Just EQ -> True+        Just LT -> True+        _ -> False +        +{-|+    Assuming the arguments are singletons, @<@ is decidable.+-}+ltSingletons :: (ERApprox ra) => ra -> ra -> Bool+ltSingletons s1 s2 =  +    case compareReals s1 s2 of +        Just LT -> True+        _ -> False +        +{-|+    For a finite sequence of real approximations, determine+    whether it is a shrinking sequence.+-}    +checkShrinking ::+    (ERApprox ra) =>+    [ra] -> +    Maybe (ra, ra)+checkShrinking [] = Nothing+checkShrinking [_] = Nothing+checkShrinking (a : b : rest) +    | b `refines` a = checkShrinking (b : rest)+    | otherwise = Just (a,b)++        +{-|+   A type whose elements represent sets that can be used+   to approximate a recursive set of closed extended real number intervals +   with arbitrary precision.+-}+--class (ERApprox sra) => SetOfRealsApprox sra where+--    (\/) :: sra -> sra -> sra -- ^ union; either approximation could be correct++{-|+   A type whose elements represent real *intervals* that can be used+   to approximate a single extended real number with arbitrary precision.++   Sometimes, these types can be used to approximate +   a closed extended real number interval with arbitrary precision.+   Nevetheless, this is not guaranteed.+-}+class (ERApprox ira) => ERIntApprox ira +    where+    doubleBounds :: ira -> (Double, Double) +    floatBounds :: ira -> (Float, Float)+    integerBounds :: ira -> (EI.ExtendedInteger, EI.ExtendedInteger)+    bisectDomain :: +        Maybe ira {-^ point to split at -} -> +        ira {-^ interval to split -} -> +        (ira, ira) -- ^ left and right, overlapping on a singleton+    defaultBisectPt :: ira -> ira+    -- | returns thin approximations of endpoints, in natural order +    bounds :: ira -> (ira, ira)+    {-|+         meet, usually constructing interval from approximations of its endpoints+         +         This does not need to be the meet of the real intervals +         but it has to be a maximal element in the set of all+         ira elements that are below the two parameters.+    -}+    (\/) :: ira -> ira -> ira+    +bounds2ira ::+    (ERIntApprox ira) =>+    ira -> ira -> ira+bounds2ira = (\/)+    +{- old stuff that will probably never be resurrected:++--   It is intended that ra and ira are the same type.+--   We distinguish them so that we can conveniently+--   switch between two levels of abstraction when+--   working with values of this one type. +--+--   Given some ra or ira, the other type is determined uniquely.       +    +--    -- | coercion to more concrete view (allows a more intentional computation)+--    ra2ira :: ra -> ira+--    -- | coercion to more abstract view (guarantees certain extensionality and convergence properties)+--    ira2ra :: ira -> ra++--    -- | coercion+--    ira2sra :: ira -> sra    +--    sraCover :: sra -> ira+--    sraAllIntervals :: sra -> [ira] -- ^ disjoint, in natural order+-}++--+--bounds2ira :: +--    (ERIntApprox ira) => +--    ra -> +--    ra -> +--    ira+--bounds2ira leftRA rightRA =+--    (ra2ira leftRA) \/ (ra2ira rightRA)++effIx2ra :: +    (ERApprox ra) =>+    EffortIndex -> ra+effIx2ra = fromInteger . toInteger++{-|+    Split an interval to a sequence of intervals whose union is the+    original interval using a given sequence of cut points.+    The cut points are expected to be in increasing order and contained+    in the given interval.  Violations of this rule are tolerated.+-}+splitIRA ::+    (ERIntApprox ira) =>+    ira {-^ an interval to be split -} -> +    [ira] {-^ approximations of the cut points in increasing order -} -> +    [ira]+splitIRA interval splitPoints =+    doSplit [] end pointsRev+    where+    (start, end) = bounds interval+    pointsRev = reverse $ start : splitPoints+    doSplit previousSegments nextRight [] = previousSegments+    doSplit previousSegments nextRight (nextLeft : otherPoints) =+        doSplit (nextLeft \/ nextRight : previousSegments) nextLeft otherPoints++{-|+    * Return the endpoints of the interval as well as the exact midpoint.+    +    * To be able to do this, there may be a need to increase granularity.+    +    * All three singleton intervals are set to the same new granularity.+-}        +exactMiddle ::+    (ERIntApprox ira) =>+    ira ->+    (ira,ira,ira,Granularity)+exactMiddle dom =+    case isExact domM of+        True ->+            (domL, domM, domR, gran)+        False ->+            (domLhg, domMhg, domRhg, higherGran)+    where+    (domL, domR) = bounds dom+    gran = max (getGranularity domL) (getGranularity domR)+    domM = (domL + domR) / 2+    higherGran = gran + 1+    domLhg = setMinGranularity higherGran domL+    domRhg = setMinGranularity higherGran domR+    domMhg = (domLhg + domRhg) / 2+     +        +{-| +    This produces a function that computes the maximal extension of the+    given function.  A maximal extension function has the property:+    f(I) = { f(x) | x in I }.  Here we get this property only for the+    limit function for ix tending to infinity.+-}+maxExtensionR2R ::+    (ERIntApprox ira) =>+    (EffortIndex -> ira -> [ira]) +        {-^ returns a safe approximation of all extrema within the interval -} ->+    (EffortIndex -> ira -> ira) +        {-^ a function behaving well on sequences that intersect to a point -} ->+    (EffortIndex -> ira -> ira) +        {- ^ a function behaving well on sequences that intersect to a non-empty interval -}+maxExtensionR2R getExtremes f ix x+    | getPrecision x < effIx2prec ix =+        (f ix xL) \/ (f ix xR) \/ +        (foldl (\/) emptyApprox $ getExtremes ix x)+    -- x is thin enough (?), don't bother evaluating by endpoints and extrema:+    | otherwise =+        f ix x+    where+    (xL, xR) = bounds x+        +        +        
+ src/Data/Number/ER/Real/Approx/Elementary.hs view
@@ -0,0 +1,60 @@+{-|+    Module      :  Data.Number.ER.Real.Approx.Elementary+    Description :  abstraction of exact reals capable of elementary operations+    Copyright   :  (c) Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  portable+        +    To be imported qualified, usually with the synonym RAEL.+-}+module Data.Number.ER.Real.Approx.Elementary +(+    ERApproxElementary(..)+)+where++import Prelude hiding (exp, log, sin, cos)++import qualified Data.Number.ER.Real.Approx as RA +import Data.Number.ER.BasicTypes++import Data.Number.ER.Real.Arithmetic.Elementary++{-|+    A class defining various common real number operations+    in a approximation-aware fashion, ie introducing effort indices.+    +    All operations here have default implementations based on+    "Data.Number.ER.Real.Arithmetic.Elementary".+-}+class (RA.ERIntApprox ra) => (ERApproxElementary ra) +    where+    abs :: EffortIndex -> ra -> ra+    abs ix = Prelude.abs+    min :: EffortIndex -> ra -> ra -> ra+    min ix = Prelude.min+    max :: EffortIndex -> ra -> ra -> ra+    max ix = Prelude.max+    exp :: EffortIndex -> ra -> ra+    exp = erExp_IR+    log :: EffortIndex -> ra -> ra+    log = erLog_IR+    (**) :: EffortIndex -> ra -> ra -> ra+    (**) ix b e = exp ix $ e * (log ix b)+    pi :: EffortIndex -> ra+    pi = erPi_R+    sin :: EffortIndex -> ra -> ra+    sin = erSine_IR+    cos :: EffortIndex -> ra -> ra+    cos = erCosine_IR+    tan :: EffortIndex -> ra -> ra+    tan ix r = (sin ix r) / (cos ix r) +    atan :: EffortIndex -> ra -> ra+    atan = erATan_IR+    +    +    +    
+ src/Data/Number/ER/Real/Approx/Interval.hs view
@@ -0,0 +1,531 @@+{-# LANGUAGE DeriveDataTypeable   #-}+{-|+    Module      :  Data.Number.ER.Real.Approx.Interval+    Description :  safe interval arithmetic+    Copyright   :  (c) Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  portable++    This module defines an arbitrary precision interval type and+    most of its interval arithmetic operations.+-}+module Data.Number.ER.Real.Approx.Interval +(+    ERInterval(..),+    normaliseERInterval+)+where++import qualified Data.Number.ER.Real.Approx as RA+import qualified Data.Number.ER.Real.Approx.Elementary as RAEL+import qualified Data.Number.ER.Real.Base as B+import qualified Data.Number.ER.ExtendedInteger as EI++import Data.Number.ER.BasicTypes+import Data.Number.ER.Misc++import Data.Ratio++import Data.Typeable+import Data.Generics.Basics+import Data.Binary+--import BinaryDerive++{-|+    Type for arbitrary precision interval arithmetic.+-}+data ERInterval base =+    ERIntervalEmpty -- ^ usually represents computation error (top element in the interval domain)+    | ERIntervalAny  -- ^ represents no knowledge of result (bottom element in the interval domain) +    | ERInterval+    {+        erintv_left :: base,+        erintv_right :: base+    }+    deriving (Typeable, Data)+    +{- the following has been generated by BinaryDerive -}+instance (Binary a) => Binary (ERInterval a) where+  put ERIntervalEmpty = putWord8 0+  put ERIntervalAny = putWord8 1+  put (ERInterval a b) = putWord8 2 >> put a >> put b+  get = do+    tag_ <- getWord8+    case tag_ of+      0 -> return ERIntervalEmpty+      1 -> return ERIntervalAny+      2 -> get >>= \a -> get >>= \b -> return (ERInterval a b)+      _ -> fail "no parse"+{- the above has been generated by BinaryDerive -}+    +    +{-|+    convert to a normal form, ie:+    +    * no NaNs as endpoints+    +    * @l <= r@+    +    * no (-Infty, +Infty)+-}+normaliseERInterval :: +    (B.ERRealBase b) => +    ERInterval b -> ERInterval b+normaliseERInterval (ERInterval minusInfty plusInfty) +    | B.isPlusInfinity plusInfty && B.isPlusInfinity (- minusInfty) = +        ERIntervalAny+normaliseERInterval (ERInterval nan1 nan2) +    | B.isERNaN nan1 && B.isERNaN nan2 =+        ERIntervalAny+normaliseERInterval (ERInterval nan r) +    | B.isERNaN nan = +        ERInterval (- B.plusInfinity) r+normaliseERInterval (ERInterval l nan) +    | B.isERNaN nan = +        ERInterval l (B.plusInfinity)+normaliseERInterval (ERInterval l r)+    | l > r = ERIntervalEmpty+normaliseERInterval i = i++{-|+    erintvPrecision returns an approximation of the number of bits required+    to represent the mantissa of a normalised size of the interval:++  +  >  - log_2 ((r - l) / (1 + abs(r) + abs(l)))+    +    Notice that this is +Infty for singleton and empty intervals+    and -Infty for the whole real line.+-}    +erintvPrecision :: +    (B.ERRealBase b) => +    ERInterval b -> EI.ExtendedInteger+erintvPrecision (ERInterval l r) =+    - (B.getApproxBinaryLog $ (r - l)/(1 + abs(r) + abs(l)))+erintvPrecision ERIntervalEmpty = EI.PlusInfinity+erintvPrecision ERIntervalAny = EI.MinusInfinity++erintvGranularity :: +    (B.ERRealBase b) => +    ERInterval b -> Int+erintvGranularity ERIntervalAny = 0+erintvGranularity ERIntervalEmpty = 0+erintvGranularity (ERInterval l r) =+    min (B.getGranularity l) (B.getGranularity r)++{- syntactic comparisons -}++{-|+    a syntactic equality test+-}+erintvEqualApprox :: +    (B.ERRealBase b) => +    ERInterval b -> ERInterval b -> Bool+erintvEqualApprox (ERInterval l1 r1) (ERInterval l2 r2) =+    l1 == l2 && r1 == r2+erintvEqualApprox ERIntervalEmpty ERIntervalEmpty = True+erintvEqualApprox ERIntervalAny ERIntervalAny = True+erintvEqualApprox _ _ = False++{-|+    a syntactic linear order+-}+erintvCompareApprox :: +    (B.ERRealBase b) => +    ERInterval b -> ERInterval b -> Ordering+erintvCompareApprox ERIntervalEmpty ERIntervalEmpty = EQ+erintvCompareApprox ERIntervalEmpty _ = LT+erintvCompareApprox _ ERIntervalEmpty = GT+erintvCompareApprox ERIntervalAny ERIntervalAny = EQ+erintvCompareApprox ERIntervalAny _ = LT+erintvCompareApprox _ ERIntervalAny = GT+erintvCompareApprox (ERInterval l1 r1) (ERInterval l2 r2) =+    case compare l1 l2 of+        EQ -> compare r1 r2+        res -> res++{- semantic comparisons -}++{-|+    Compare for equality two intervals interpreted as approximations for+    2 single real numbers.  When equality or inequality cannot+    be established, return Nothing (ie bottom).+-}+erintvEqualReals ::+    (B.ERRealBase b) =>+    ERInterval b ->+    ERInterval b ->+    Maybe Bool+erintvEqualReals ERIntervalEmpty _ = Nothing+erintvEqualReals _ ERIntervalEmpty = Nothing+erintvEqualReals ERIntervalAny _ = Nothing+erintvEqualReals _ ERIntervalAny = Nothing+erintvEqualReals (ERInterval l1 r1) (ERInterval l2 r2)+    | l1 == r1 && l2 == r2 && l1 == l2 = Just True+    | r1 < l2 || l1 > r2 = Just False+    | otherwise = Nothing++{-|+    Compare in natural order two intervals interpreted as approximations for+    2 single real numbers.  When equality or inequality cannot+    be established, return Nothing (ie bottom).+-}+erintvCompareReals ::+    (B.ERRealBase b) =>+    ERInterval b ->+    ERInterval b ->+    Maybe Ordering+erintvCompareReals ERIntervalEmpty _ = Nothing+erintvCompareReals _ ERIntervalEmpty = Nothing+erintvCompareReals ERIntervalAny _ = Nothing+erintvCompareReals _ ERIntervalAny = Nothing+erintvCompareReals i1@(ERInterval l1 r1) i2@(ERInterval l2 r2)+    | r1 < l2 = Just LT+    | l1 > r2 = Just GT+    | l1 == r1 && l2 == r2 && l1 == l2 = Just EQ+    | otherwise = Nothing++{-|+    Compare in natural order two intervals interpreted as approximations for+    2 single real numbers.  When relaxed equality cannot+    be established nor disproved, return Nothing (ie bottom).+-}+erintvLeqReals ::+    (B.ERRealBase b) =>+    ERInterval b ->+    ERInterval b ->+    Maybe Bool+erintvLeqReals ERIntervalEmpty _ = Nothing+erintvLeqReals _ ERIntervalEmpty = Nothing+erintvLeqReals ERIntervalAny _ = Nothing+erintvLeqReals _ ERIntervalAny = Nothing+erintvLeqReals i1@(ERInterval l1 r1) i2@(ERInterval l2 r2)+    | r1 <= l2 = Just True+    | l1 > r2 = Just False+    | otherwise = Nothing+++{-|+    +    Default splitting:++    > [-Infty,+Infty] |-> [-Infty,0] [0,+Infty] +    +    > [-Infty,x] |-> [-Infty,2*x-1] [2*x-1, x] (x <= 0)+    +    > [-Infty,x] |-> [-Infty,0] [0, x] (x > 0)+    +    > [x,+Infty] |-> [x,2*x+1] [2*x+1,+Infty]  (x => 0)+    +    > [x,+Infty] |-> [x,0] [0,+Infty]  (x < 0)+    +    > [x,y] |-> [x, (x+y)/2] [(x+y)/2, y]+    +    > empty |-> empty empty+-}+erintvDefaultBisectPt ::+    (B.ERRealBase b) => +    Granularity -> +    (ERInterval b) ->+    (ERInterval b)+erintvDefaultBisectPt gran ERIntervalAny = 0+erintvDefaultBisectPt gran ERIntervalEmpty = ERIntervalEmpty+erintvDefaultBisectPt gran (ERInterval l r) =+    ERInterval m m+    where+    m+        | B.isPlusInfinity r =+            if l < 0 +                then 0+                else 2 * (B.setMinGranularity gran l) + 1+        | B.isPlusInfinity (-l) =+            if r > 0 +                then 0+                else 2 * (B.setMinGranularity gran r) - 1+        | otherwise =+             ((B.setMinGranularity gran l) + r)/2+    ++erintvBisect ::+    (B.ERRealBase b, RealFrac b) => +    Granularity -> +    (Maybe (ERInterval b)) ->+    (ERInterval b) ->+    (ERInterval b, ERInterval b)+erintvBisect gran maybePt i =+    (l RA.\/ m, m RA.\/ r)+    where+    (l,r) = RA.bounds i+    m =+        case maybePt of+            Just m -> m+            Nothing -> erintvDefaultBisectPt gran i ++instance (B.ERRealBase b) => Eq (ERInterval b) where+    i1 == i2 =+        case erintvEqualReals i1 i2 of+            Nothing -> +                error $+                     "ERInterval: Eq: comparing overlapping intervals:\n" +++                    show i1 ++ "\n" +++                    show i2+            Just b -> b++instance (B.ERRealBase b) => Ord (ERInterval b) where+    compare i1 i2 = +        case erintvCompareReals i1 i2 of+            Nothing -> +                error $ +                    "ERInterval: Ord: comparing overlapping intervals:\n" +++                    show i1 ++ "\n" +++                    show i2+            Just r -> r+    {- max:+       (Default implementation is wrong in this case:+        eg compare is not defined for overlapping intervals.)+    -}+    max i1@(ERInterval l1 r1) i2@(ERInterval l2 r2) =+        normaliseERInterval $ ERInterval (max l1 l2) (max r1 r2)+    max ERIntervalEmpty _ = ERIntervalEmpty+    max _ ERIntervalEmpty = ERIntervalEmpty+    max ERIntervalAny ERIntervalAny = ERIntervalAny+    max ERIntervalAny (ERInterval l r) = ERInterval l B.plusInfinity+    max (ERInterval l r) ERIntervalAny = ERInterval l B.plusInfinity+    {- min: -}+    min i1@(ERInterval l1 r1) i2@(ERInterval l2 r2) =+        normaliseERInterval $ ERInterval (min l1 l2) (min r1 r2)+    min ERIntervalEmpty _ = ERIntervalEmpty+    min _ ERIntervalEmpty = ERIntervalEmpty+    min ERIntervalAny ERIntervalAny = ERIntervalAny+    min ERIntervalAny (ERInterval l r) = ERInterval (- B.plusInfinity) r+    min (ERInterval l r) ERIntervalAny = ERInterval (- B.plusInfinity) r+        +instance (B.ERRealBase b) => Show (ERInterval b) +    where+    show = erintvShow 6 True False+    +erintvShow numDigits showGran showComponents interval =+    showERI interval+    where+    showERI ERIntervalEmpty = "[NONE]"+    showERI ERIntervalAny = "[ANY]"+    showERI (ERInterval l r) +        | l == r = "<" ++ showBase l ++ ">"+        | otherwise = +            "[" ++ showBase l ++ "," ++ showBase r ++ "]"+    showBase = B.showDiGrCmp numDigits showGran showComponents+        +instance (B.ERRealBase b) => Num (ERInterval b) where+    fromInteger n =+        normaliseERInterval $ ERInterval (fromInteger n) (fromInteger n)+    {- abs -}+    abs (ERInterval l r)+        | l < 0 && r > 0 = ERInterval 0 (max (-l) r)+        | r <= 0 = ERInterval (-r) (-l)+        | otherwise = ERInterval l r+    abs ERIntervalAny = ERInterval 0 B.plusInfinity+    abs ERIntervalEmpty = ERIntervalEmpty+    {- signum -}+    signum i@(ERInterval l r)+        | l < 0 && r > 0 = ERInterval (-1) 1 -- need many-valuedness via sequences of intervals+        | r < 0 = ERInterval (-1) (-1)+        | l > 0 = ERInterval 1 1+        | l == 0 && r == 0 = i+        | l == 0 = ERInterval 0 1+        | r == 0 = ERInterval (-1) 0+    signum ERIntervalAny = ERInterval (-1) 1+    signum ERIntervalEmpty = ERIntervalEmpty+    {- negate -}+    negate (ERInterval l r) = (ERInterval (-r) (-l))+    negate ERIntervalEmpty = ERIntervalEmpty+    negate ERIntervalAny = ERIntervalAny+    {- addition -}+    (ERInterval l1 r1) + (ERInterval l2 r2) =+        normaliseERInterval $+        ERInterval +            (-((-l1) + (-l2))) -- reverse the rounding mode+            (r1 + r2)+    ERIntervalAny + i2 = ERIntervalAny+    i1 + ERIntervalAny = ERIntervalAny+    ERIntervalEmpty + i2 = ERIntervalEmpty+    i1 + ERIntervalEmpty = ERIntervalEmpty+    {- multiplication -}+    (ERInterval l1 r1) * (ERInterval l2 r2)+        | haveNan = ERIntervalAny+        | otherwise =+            normaliseERInterval $+            ERInterval minProd maxProd+        where+        haveNan = or $ map B.isERNaN (prodsL ++ prodsR)+        minProd = foldl1 min prodsL+        maxProd = foldl1 max prodsR+        prodsL = [-((-l1) * l2), -((-l1) * r2), -((-r1) * l2), -((-r1) * r2)]+        prodsR = [l1 * l2, l1 * r2, r1 * l2, r1 * r2]+    ERIntervalAny * i2 = ERIntervalAny+    i1 * ERIntervalAny = ERIntervalAny+    ERIntervalEmpty * i2 = ERIntervalEmpty+    i1 * ERIntervalEmpty = ERIntervalEmpty++instance (B.ERRealBase b) => Fractional (ERInterval b) where+    fromRational rat =+        (fromInteger $ numerator rat)+        / (fromInteger $ denominator rat)+    {- division -}+    (ERInterval l1 r1) / (ERInterval l2 r2)+        | l2 < 0 && r2 > 0 = ERIntervalAny+        | haveNan = +--            unsafePrint "ERInterval: /: haveNan" $ +            ERIntervalAny+        | l2 == 0 && r2 > 0 && 1/l2 < 0 = -- minus 0+            (ERInterval l1 r1) / (ERInterval (-l2) r2) -- correct it to +0+        | r2 == 0 && l2 < 0 && 1/r2 > 0 = -- plus 0+            (ERInterval l1 r1) / (ERInterval l2 (-r2)) -- correct it to -0+        | otherwise =+            normaliseERInterval $+            ERInterval minDiv maxDiv+        where+        haveNan = or $ map B.isERNaN (divsL ++ divsR)+        minDiv = foldl1 min divsL+        maxDiv = foldl1 max divsR+        divsL = [-(l1 / (-l2)), -(l1 / (-r2)), -(r1 / (-l2)), -(r1 / (-r2))]+        divsR = [l1 / l2, l1 / r2, r1 / l2, r1 / r2]+    ERIntervalAny / i2 = ERIntervalAny+    i1 / ERIntervalAny = ERIntervalAny+    ERIntervalEmpty / i2 = ERIntervalEmpty+    i1 / ERIntervalEmpty = ERIntervalEmpty+            +instance (B.ERRealBase b, RealFrac b) => RA.ERApprox (ERInterval b) where+    getPrecision i = erintvPrecision i+    getGranularity i = erintvGranularity i+    {- setMinGranularity -}+    setMinGranularity gr (ERInterval l r) =+        normaliseERInterval $+        (ERInterval (- (B.setMinGranularity gr (-l))) (B.setMinGranularity gr r))+    setMinGranularity _ i = i+    {- setGranularity -}+    setGranularity gr (ERInterval l r) =+        normaliseERInterval $+        (ERInterval (- (B.setGranularity gr (-l))) (B.setGranularity gr r))+    setGranularity _ i = i+    {- isDisjoint -}+    isDisjoint i1 i2 = RA.isEmpty $ i1 RA./\ i2+    {- bottomApprox -}  +    bottomApprox = ERIntervalAny+    {- emptyApprox -}  +    emptyApprox = ERIntervalEmpty+    {- isEmpty -}+    isEmpty ERIntervalEmpty = True+    isEmpty _ = False+    {- isBottom -}+    isBottom ERIntervalAny = True+    isBottom (ERInterval l r) =+        B.isPlusInfinity r && B.isPlusInfinity (-l)+    isBottom _ = False+    {- isExact -}+    isExact ERIntervalEmpty = False+    isExact ERIntervalAny = False+    isExact (ERInterval l r) = l == r+    {- isBounded -}+    isBounded ERIntervalEmpty = True+    isBounded ERIntervalAny = False+    isBounded (ERInterval l r) = +        (- B.plusInfinity) < l && r < B.plusInfinity+    {- intersection -}+    ERIntervalEmpty /\ i = ERIntervalEmpty+    i /\ ERIntervalEmpty = ERIntervalEmpty+    ERIntervalAny /\ i = i+    i /\ ERIntervalAny = i+    (ERInterval l1 r1) /\ (ERInterval l2 r2) =+        normaliseERInterval $+        ERInterval (max l1 l2) (min r1 r2)+    {- intersectMeasureImprovement -}+    intersectMeasureImprovement _ ERIntervalEmpty i = (ERIntervalEmpty, 1)+    intersectMeasureImprovement _ i ERIntervalEmpty = (ERIntervalEmpty, 1)+    intersectMeasureImprovement _ ERIntervalAny i = (i, 1)+    intersectMeasureImprovement _ i ERIntervalAny = (i, 1)+    intersectMeasureImprovement ix i1 i2 =+        (isec, impr)+        where+        isec = i1 RA./\ i2+        impr +            | 0 `RA.refines` isecWidth && 0 `RA.refines` i1Width = 1 -- 0 -> 0 is no improvement+            | otherwise = i1Width / isecWidth +        i1Width = i1H - i1L+        isecWidth = isecH - isecL+        (isecL, isecH) = RA.bounds $ RA.setMinGranularity gran isec  +        (i1L, i1H) = RA.bounds $ RA.setMinGranularity gran i1+        gran = effIx2gran ix  +    {- refines -}+    refines _ ERIntervalAny = True+    refines ERIntervalEmpty _ = True+    refines ERIntervalAny _ = False+    refines _ ERIntervalEmpty = False+    refines (ERInterval l1 r1) (ERInterval l2 r2) =+        l2 <= l1 && r1 <= r2+    {- semantic comparisons -}+    equalReals = erintvEqualReals+    compareReals = erintvCompareReals+    leqReals = erintvLeqReals+    {- non-semantic comparisons -}+    equalApprox = erintvEqualApprox+    compareApprox = erintvCompareApprox+    {- conversion from Double -}+    double2ra d = +        ERInterval b b+        where+        b = B.fromDouble d+    {- formatting -}+    showApprox = erintvShow++instance (B.ERRealBase b, RealFrac b) => RA.ERIntApprox (ERInterval b)+    where+    doubleBounds ERIntervalAny = (- infinity, infinity)+        where+        infinity = 1/0+    doubleBounds ERIntervalEmpty = +        error "SuiteERInterval: iraDoubleBounds: empty interval"+    doubleBounds (ERInterval l r) =+        (B.toDouble l, B.toDouble r) +    floatBounds ERIntervalAny = (- infinity, infinity)+        where+        infinity = 1/0+    floatBounds ERIntervalEmpty = +        error "SuiteERInterval: iraFloatBounds: empty interval"+    floatBounds (ERInterval l r) =+        (B.toFloat l, B.toFloat r) +    integerBounds ERIntervalAny = (- infinity, infinity)+        where+        infinity = EI.PlusInfinity+    integerBounds ERIntervalEmpty = +        error "SuiteERInterval: iraIntegerBounds: empty interval"+    integerBounds (ERInterval l r) = +        (- (mkEI (- l)), mkEI r)+        where+        mkEI f +            | B.isPlusInfinity f = EI.PlusInfinity+            | B.isPlusInfinity (-f) = EI.MinusInfinity+            | otherwise = ceiling f+    defaultBisectPt dom = erintvDefaultBisectPt  (RA.getGranularity dom + 1) dom+    bisectDomain maybePt dom = +        erintvBisect (RA.getGranularity dom + 1) maybePt dom+    {- \/ -}+    ERIntervalEmpty \/ i = i+    i \/ ERIntervalEmpty = i+    ERIntervalAny \/ _ = ERIntervalAny+    _ \/ ERIntervalAny = ERIntervalAny+    (ERInterval l1 r1) \/ (ERInterval l2 r2) =+        normaliseERInterval $+        ERInterval (min l1 l2) (max r1 r2)+    {- RA.bounds -}+    bounds ERIntervalAny = +        (ERInterval (-B.plusInfinity) (-B.plusInfinity), +         ERInterval B.plusInfinity B.plusInfinity)+    bounds ERIntervalEmpty = (ERIntervalEmpty, ERIntervalEmpty)+    bounds (ERInterval l r) = +        (ERInterval l l, ERInterval r r)++instance (B.ERRealBase b, RealFrac b) => RAEL.ERApproxElementary (ERInterval b)+-- all operations here have appropriate default implementations
+ src/Data/Number/ER/Real/Approx/Sequence.hs view
@@ -0,0 +1,220 @@+{-|+    Module      :  Data.Number.ER.Real.Approx.Sequence+    Description :  exact reals via convergent sequences+    Copyright   :  (c) Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  portable++    Types and methods related to explicit +    convergent sequences of real number approximations.+-}+module Data.Number.ER.Real.Approx.Sequence +(+    ConvergRealSeq,+    makeFastConvergRealSeq,+    convertFuncRA2Seq,+    convertBinFuncRA2Seq,+    convergRealSeqElem,+    showConvergRealSeq,+    showConvergRealSeqAuto+)+where++import qualified Data.Number.ER.Real.Approx as RA+import Data.Number.ER.BasicTypes++import Data.Maybe+import Data.Ratio++{-|+  A converging sequence of real number approximations.+  +  * Every finite subsequence has a non-empty intersection.+  +  * The limit should be a singleton.+-}+data ConvergRealSeq ra =+    ConvergRealSeq (EffortIndex -> ra)++convergRealSeqElem :: (ConvergRealSeq ra) -> EffortIndex -> ra+convergRealSeqElem (ConvergRealSeq sq) ix = sq ix++{-| +    Using this operator, a unary funtion working over+    approximations can be converted to one that works+    over exact numbers represented through a sequence+    of approximations.+-}+convertFuncRA2Seq ::+    (EffortIndex -> ra -> ra) ->+    (ConvergRealSeq ra) ->+    (ConvergRealSeq ra)+convertFuncRA2Seq f (ConvergRealSeq argSeq) = +    ConvergRealSeq resultSeq+    where+    resultSeq ix =+        f ix (argSeq ix)+        +{-|+    The same as above, where f is binary+-}            +convertBinFuncRA2Seq :: +    (EffortIndex -> ra -> ra -> ra) -> +    (ConvergRealSeq ra) -> +    (ConvergRealSeq ra) -> +    (ConvergRealSeq ra)+    +convertBinFuncRA2Seq f (ConvergRealSeq arg1) (ConvergRealSeq arg2) = +    ConvergRealSeq resultSeq+    where+    resultSeq ix =+        f ix (arg1 ix) (arg2 ix)++{-|+    Turn an arbitrary convergent sequence into one with+    a guaranteed convergence rate - the precision (as defined+    by 'RA.ERApprox.RA.getPrecision') of x_ix is at least ix.+-}+makeFastConvergRealSeq :: +    (RA.ERApprox ra) => +    (ConvergRealSeq ra) -> +    (ConvergRealSeq ra)+makeFastConvergRealSeq (ConvergRealSeq argSeq) = +    ConvergRealSeq fastSeq+    where+    fastSeq ix =+        head $ catMaybes $ map (precisionOK . argSeq) indexSeries+        where+        indexSeries =+    --        take 5 $ -- upper bound on iteration - for testing+            binGeomSeries (max 1 ix)+        precisionOK ra+            | RA.getPrecision ra >= (effIx2prec ix) = Just ra+            | otherwise = Nothing++{-| +    binGeomSeries n is the geometric series+    [ n, 2n, 4n, 8n, ...]+-}    +binGeomSeries+    :: (Num a)+    => a+    -> [a]+binGeomSeries n =+    n : (binGeomSeries (2 * n))++instance (RA.ERApprox ra) => Show (ConvergRealSeq ra) +    where+    show = showConvergRealSeq 6 True True 10 -- cheating here, should throw an error+++{-|+    Show function for ConvergRealSeq's with full arguments.+-}    +showConvergRealSeq+    :: (RA.ERApprox ra)+    => Int+    -> Bool+    -> Bool+    -> Precision+    -> (ConvergRealSeq ra)+    -> String++showConvergRealSeq numDigits showGran showComponents prec r =+    RA.showApprox numDigits showGran showComponents $+         convergRealSeqElem (makeFastConvergRealSeq r) (prec2effIx prec)+++{-|+    Show function for ConvergRealSeq's with all parameters fixed+    except for number of digits+-}+showConvergRealSeqAuto +    :: (RA.ERApprox ra)+    => Int+    -> (ConvergRealSeq ra)+    -> String+showConvergRealSeqAuto numDigits argSeq =+    showConvergRealSeq numDigits True True prec argSeq+    where+    prec = effIx2prec $ ceiling $ (fromInteger $ toInteger numDigits) * 3.3219280948873626++++instance+    (RA.ERApprox ra)+    => Eq (ConvergRealSeq ra)+    where+    r1 == r2 = +        iterateRA_A raEq 2 [r1, r2]+        where+        raEq _ ([a1,a2]) = RA.equalReals a1 a2+                +instance+    (RA.ERApprox ra)+    => Ord (ConvergRealSeq ra)+    where+    compare r1 r2 = +        iterateRA_A eraComp 2 [r1, r2]+        where+        eraComp _ ([a1,a2]) = RA.compareReals a1 a2+            +pointwiseConvergRealSeq1 f (ConvergRealSeq sq) =+    ConvergRealSeq (f . sq)+pointwiseConvergRealSeq2 f (ConvergRealSeq sq1) (ConvergRealSeq sq2) =+    ConvergRealSeq (\ix -> f (sq1 ix) (sq2 ix))+            +instance +    (RA.ERApprox ra)+    => Num (ConvergRealSeq ra)+    where+    fromInteger n = ConvergRealSeq sq+        where+        sq ix =+            RA.setMinGranularity (effIx2gran ix) $ fromInteger n+    abs = pointwiseConvergRealSeq1 $ abs+    signum = pointwiseConvergRealSeq1 $ signum+    negate = pointwiseConvergRealSeq1 $ negate+    (+) = pointwiseConvergRealSeq2 $ (+)+    (*) = pointwiseConvergRealSeq2 $ (*)+    +instance+    (RA.ERApprox ra)+    => Fractional (ConvergRealSeq ra)+    where+    fromRational q = ConvergRealSeq sq+        where+        sq ix =+            (RA.setMinGranularity (effIx2gran ix) num) / denom+        num = fromInteger $ numerator q+        denom = fromInteger $ denominator q+    recip = pointwiseConvergRealSeq1 $ recip++{-|+    Take a converging sequence of partial functions F_i that operate on +    real approximations and turn it into a function F that operates on converging sequences. +    F looks for some members of the real approximation sequences +    and an i so that F_i is defined for the chosen approximations+    and returns its result.  +-}+iterateRA_A+    :: (EffortIndex -> [ra] -> Maybe a) +        -- ^ a sequence of partial functions based on approximations+    -> EffortIndex -- ^ a starting index to use when searching sequences+    -> ([ConvergRealSeq ra] -> a) +        -- ^ a total function based on sequences++iterateRA_A fn_RA startIx args =+    head $ catMaybes $ map ((uncurry fn_RA) . args_Prec) indexSeries+    where+    indexSeries =+--        take 5 $ -- upper bound on iteration - for testing+        binGeomSeries $ max 1 startIx+        -- [(max 1 startIx)..]+    args_Prec currentIndex =+        (currentIndex, map (\ arg -> convergRealSeqElem arg currentIndex) args)+       +    
+ src/Data/Number/ER/Real/Arithmetic/Elementary.hs view
@@ -0,0 +1,602 @@+{-|+    Module      :  Data.Number.ER.Real.Arithmetic.Elementary+    Description :  some elementary functions+    Copyright   :  (c) Michal Konecny, Amin Farjudian, Jan Duracz+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  portable++    Some important elementary functions for real approximations+    and their maximal extensions for interval approximations.+-}+module Data.Number.ER.Real.Arithmetic.Elementary+(   +    -- * specialised exponentiation+    erSqr_R,+    erSqr_IR,+    erPow_R,+    erPow_IR,+    erSqrt_R,+    erSqrt_IR,+    erRoot_R,+    erRoot_IR,+    -- * exponentiation and logarithm +    erExp_R,+    erExp_IR,+    erLog_R,+    erLog_IR,+    -- * trigonometrics+    erSine_R,+    erSine_IR,+    erCosine_R,+    erCosine_IR,+    erATan_R,+    erATan_IR,+    erPi_R+)+where++import qualified Data.Number.ER.Real.Approx as RA+import Data.Number.ER.BasicTypes++import Data.Number.ER.Real.Arithmetic.Taylor+-- import Data.Number.ER.Real.Arithmetic.Newton++import Data.Number.ER.Misc++{-+    sqr+-}++erSqr_IR ::+    (RA.ERIntApprox ira) =>+    EffortIndex -> +    ira -> ira+erSqr_IR = erSqr_R++erSqr_R ::+    (RA.ERIntApprox ira) =>+    EffortIndex -> +    ira -> ira+erSqr_R ix a+    | RA.isEmpty a =+        RA.emptyApprox+    | otherwise = +        max 0 $ a' * a'+    where+    a' = RA.setMinGranularity gran a+    gran = effIx2gran ix+    +{-+    integer exponentiation x ^ p+-}++erPow_IR ::+    (RA.ERIntApprox ira) =>+    EffortIndex -> +    Integer ->+    ira -> ira+erPow_IR = erPow_R++erPow_R ::+    (RA.ERIntApprox ira) =>+    EffortIndex ->+    Integer ->+    ira -> ira+erPow_R ix p a+    | RA.isEmpty a =+        RA.emptyApprox+    | p < 0 =+        1 / erPow_R ix (-p) a+    | p == 0 = +        1+    | even p =+        erPow_R ix (div p 2) (erSqr_R ix a')+    | otherwise =+        a' * (erPow_R ix (div (p - 1) 2) (erSqr_R ix a'))+    where+    a' = RA.setMinGranularity gran a+    gran = effIx2gran ix++{-+    sqrt+-}++erSqrt_R ::+    (RA.ERIntApprox ira) => +    EffortIndex -> ira -> ira+erSqrt_R = erSqrtNewton_R  +    +erSqrt_IR ::+    (RA.ERIntApprox ira) => +    EffortIndex -> ira -> ira+erSqrt_IR =+    RA.maxExtensionR2R +        sqrtExtrema+        (\ ix x -> erSqrt_R ix x)++sqrtExtrema ix x+    | 0 `RA.refines` x = [0]+    | otherwise = []+        +++erSqrtContFr_R ::+    (RA.ERIntApprox ira) => +    EffortIndex -> ira -> ira+erSqrtContFr_R ix a+    | aR == 0 = 0+    | aL == 1/0 = 1/0+    | aR < 0 = RA.emptyApprox+    | otherwise =+        contFrIter (ix + 3) $+            RA.setMinGranularity gran $ max 0 (0 RA.\/ a) +    where+    gran = effIx2gran ix+    (aL, aR) = RA.bounds a+    aM1 = a - 1+    +    contFrIter i x_i+        | i == 0 =+            x_i+        | otherwise =+            1 + (aM1 / (x_iPlus1 + 1))+        where+        x_iPlus1 = contFrIter (i - 1) x_i+            +erSqrtNewton_R ::+    (RA.ERIntApprox ira) => +    EffortIndex -> ira -> ira+erSqrtNewton_R ix a+    | RA.isEmpty a = RA.emptyApprox+    | aR == 0 = 0+    | aL == 1/0 = 1/0+    | aR < 0 = RA.emptyApprox+    | otherwise =        +        x_i RA.\/ (a/x_i)+    where+    gran = effIx2gran ix+    (aL, aR) = RA.bounds a+    aM1 = a - 1+    +    x_i = +        newtonIter ((ix `div` 100) + 5) $+                RA.setMinGranularity gran $ max 0 aR +    newtonIter i x_i+        | i == 0 = x_i+        | otherwise =+                snd $ RA.bounds $+                    (x_iMinus1 + a / (x_iMinus1)) / 2+        where+        x_iMinus1 = newtonIter (i - 1) x_i++{-+    pth root x ^ (1/p)+-}++erRoot_R ::+    (RA.ERIntApprox ira) => +    EffortIndex -> Integer -> ira -> ira+erRoot_R = erRootNewton_R    +    +erRoot_IR ::+    (RA.ERIntApprox ira) => +    EffortIndex -> Integer -> ira -> ira+erRoot_IR ix p =+    RA.maxExtensionR2R +        (rootExtrema p)+        (\ ix x -> erRoot_R ix p x) $+            ix++rootExtrema p ix x+    | 0 `RA.refines` x && even p = [0]+    | otherwise = []++erRootNewton_R ::+    (RA.ERIntApprox ira) => +    EffortIndex -> Integer -> ira -> ira+erRootNewton_R ix p a+    | RA.isEmpty a = RA.emptyApprox+    | aR == 0 = 0+    | aL == 1/0 = 1/0+    | aR < 0 && even p = RA.emptyApprox+    | aR < 0 = - erRootNewton_R ix p (-a)+    | p > 0 =+        x_i RA.\/ (a/x_i_pow_p_minus_1)+    | otherwise =   +        1 / (erRootNewton_R ix (-p) a) -- TODO: check extremes+    where+    gran = effIx2gran ix+    (aL, aR) = RA.bounds a+    aM1 = a - 1+    pIRA = fromInteger p+    pIRA_minus_1 = pIRA - 1+    +    (x_i, x_i_pow_p_minus_1) = +        newtonIter (ix + 5) $+                RA.setMinGranularity gran $ max 0 aR+ +    newtonIter i x_0+        | i == 0 = +            (x_0, x_0_pow_p_minus_1)+        | otherwise =+            (x_i, x_i_pow_p_minus_1)+            +        where+        (x_iMinus1, x_iMinus1_pow_p_minus_1) = +            newtonIter (i - 1) x_0+        x_i =+                snd $ RA.bounds $+                    (pIRA_minus_1 * x_iMinus1 + a / x_iMinus1_pow_p_minus_1) / pIRA+        x_i_pow_p_minus_1 =+                erPow_R ix (p - 1) x_i+        x_0_pow_p_minus_1 =+                erPow_R ix (p - 1) x_0++{-+    e^x and log+-}++erExp_R :: +    (RA.ERIntApprox ira) => +    EffortIndex -> ira -> ira+    +erExp_R = erExp_Tay_Opt_R++{- +    exp as derived from Taylor series is already a maximal extension+    because it does not suffer from the wrapping effect - all+    functions used are monotone - all Taylor coeffs are positive+-}+erExp_IR :: +    (RA.ERIntApprox ira) => +    EffortIndex -> ira -> ira+    +erExp_IR ix x+    | 0 `RA.refines` x || (-1/0) `RA.refines` x=+        RA.maxExtensionR2R+            (\ ix x -> [])+            (\ ix x -> erExp_R ix x)+            ix x+    | otherwise =+        erExp_R ix x+++{- Log using Newton -}++erLog_R :: +    (RA.ERIntApprox ira) => +    EffortIndex -> ira -> ira+    +erLog_R =+    logDivSeries_R +--    erLog_IR -- intervals are more efficient for log than singletons ++erLog_IR ::+    (RA.ERIntApprox ira) => +    EffortIndex -> ira -> ira+    +erLog_IR =+    RA.maxExtensionR2R+        logExtrema+        (\ ix x -> logDivSeries_R ix x)+        +logExtrema ix x+    | 0 `RA.refines` x = [-1/0]+    | otherwise = []+        +{-| log using a fast converging series, designed to be used with singletons -}+logDivSeries_R ::+    (RA.ERIntApprox ira) => EffortIndex -> ira -> ira +logDivSeries_R ix x +    | RA.isEmpty posx = RA.emptyApprox+    | posx `RA.refines` 0 = -1/0 +    | posx `RA.refines` (1/0) = 1/0+    | otherwise =+        case RA.compareReals posx 1 of+            Just LT ->+                - (logDivSeries_R ix (recip posx))+            _ ->+                nearLogx + 2 * t * (series ix (RA.setMinGranularity gran 1))+    where+    gran = effIx2gran ix+    posx = (RA.setMinGranularity gran x) RA./\ (0 RA.\/ (1/0))+    nearLogx =+        0.69314718055994530941 * (fromInteger $ intLog 2 $ xCeiling)+    remNearLogx =+        posx / (erExp_R ix nearLogx) -- should be very close to 1+    xCeiling = +        snd $ RA.integerBounds posx+    t = +        ((remNearLogx - 1) / (remNearLogx + 1)) -- the range of this expression is [-1,1] +            RA./\ ((-1) RA.\/ 1) -- correction of wrapping +    tsqare = abs $ t * t -- the range is [0,1]+    series termsCount currentDenominator +        | termsCount > 0 =+            (recip currentDenominator) + tsqare * (series (termsCount - 1) (currentDenominator + 2))+        | otherwise =+            (recip currentDenominator)+            * (1 RA.\/ (recip $ 1 - tsqare)) -- [1,1/(1-t^2)] is a valid error bound+        +--{- log using Newton -}+--    +--logNewton_RA+--    :: (RA.ERIntApprox ira)+--    => EffortIndex+--    -> ra -- must not be below 1+--    -> ra+--    +--logNewton_RA i x = +--    case compareReals posx 1 of+--        Just LT ->+--            - (logNewton_RA i (recip posx))+--        _ ->    +--            erNewton_FullArgs +--                ( \ i y -> (erExp_RA i y) - posx, erExp_RA) +--                (RA.setMinGranularity gran nearLogx) +--                (RA.setMinGranularity gran 1) +--                (fromInteger $ toInteger i)+--                i+--    where+--    gran = effIx2gran i+--    posx = +--        RA.setMinGranularity gran x /\ (ira2ra $ 0 RA.\/ (1/0))+--    nearLogx =                    +--        0.69314718055994530941 * (fromInteger $ intLog 2 $ xCeiling)+--    xCeiling +--        | RA.isEmpty posx = 1 -- choice of constant irrelevant+--        | otherwise =+--            snd $ RA.iraIntegerBounds $ ra2ira posx+++{-+    sin(x) and cos(x)+-}++erSine_R :: +    (RA.ERIntApprox ira) => +    EffortIndex -> ira -> ira++erSine_R ix x+    | (1/0) `RA.refines` x || (-1/0) `RA.refines` x = +        (-1) RA.\/ 1  +    | otherwise =+        erSine_Tay_Opt_R ix x++erCosine_R :: +    (RA.ERIntApprox ira) => +    EffortIndex -> ira -> ira+     +erCosine_R ix x+    | (1/0) `RA.refines` x || (-1/0) `RA.refines` x =   +        (-1) RA.\/ 1  +    | otherwise =+        erCosine_Tay_Opt_R ix x +++{- Sine using generic Taylor (see Taylor for an optimised version) -}++erSine_Tay_R :: +    (RA.ERIntApprox ira) =>+    EffortIndex -> ira -> ira++erSine_Tay_R ix x+    | (1/0) `RA.refines` x || (-1/0) `RA.refines` x = +        (-1) RA.\/ 1  +    | otherwise =+        erTaylor_R ix sine_coefSeq sine_error 0 x++sine_coefSeq :: +    (RA.ERIntApprox ira) => +    Int -> ira++sine_coefSeq n+  | n `mod` 4 == 0 = 0+  | n `mod` 4 == 1 = 1+  | n `mod` 4 == 2 = 0+  | n `mod` 4 == 3 = -1+  +sine_error n = (-1) RA.\/ 1  ++{- maximal extensions -}++erSine_IR ::+    (RA.ERIntApprox ira) =>+    EffortIndex -> ira -> ira +    +erSine_IR = +    RA.maxExtensionR2R sineExtremes erSine_R+    +erCosine_IR ::+    (RA.ERIntApprox ira) =>+    EffortIndex -> ira -> ira +    +erCosine_IR = +    RA.maxExtensionR2R cosineExtremes erCosine_R+        +sineExtremes ix x +    | RA.isBounded x =+        alternatingExtremes 1 (-1) ix scaledX+    | otherwise = [-1,1]+    where+    scaledX = (x / (erPi_R ix)) - 0.5+    +cosineExtremes ix x+    | RA.isBounded x =+        alternatingExtremes 1 (-1) ix scaledX+    | otherwise = [-1,1]+    where+    scaledX = (x / (erPi_R ix))+    +alternatingExtremes extr0 extr1 ix scaledX+    | extremesCount >= 2 = [extr0,extr1]  +    | extremesCount == 1 && even minExtremeN = [extr0]+    | extremesCount == 1 = [extr1]+    | otherwise = []+    where+    extremesCount = 1 + maxExtremeN - minExtremeN+    (xFloor, xCeiling) = RA.integerBounds scaledX+    minExtremeN = +        case RA.compareReals (fromInteger $ toInteger xFloor) scaledX of+            Just LT -> (xFloor + 1)+            _ -> xFloor+    maxExtremeN =+        case RA.compareReals scaledX (fromInteger $ toInteger xCeiling) of+            Just LT -> xCeiling - 1+            _ -> xCeiling+        ++{-+    tan(x), atan(x) and pi+-}++erATan_R :: +    (RA.ERIntApprox ira) => +    EffortIndex -> ira -> ira+    +erATan_R = atanEuler_R++erATan_IR ::+    (RA.ERIntApprox ira) =>+    EffortIndex -> ira -> ira +    +erATan_IR =+    RA.maxExtensionR2R atanExtremes erATan_R++atanExtremes ix x = []++{- atan using Euler's series: +    x / (1 + x^2) * (1 + t*2*1/(2*1 + 1)*(1 + t*2*2/(2*2 + 1)*(1 + ... (1 + t*2*n/(2*n+1)*(1 + ...)))))+    where+    t = x^2/(1 + x^2)+    +    where the tail  (1 + t*2*n/(2*n+1)*(1 + ...)) is inside the interval:+    [1 + (x^2*2n/(2n + 1)), 1 + x^2]+-}++atanEuler_R ::+    (RA.ERIntApprox ira) => +    EffortIndex -> ira -> ira++atanEuler_R ix x +    | RA.isEmpty x = RA.emptyApprox+    | otherwise =+        (x / xSquarePlus1) * (series ix (RA.setMinGranularity gran 2))+    where+    gran = effIx2gran ix+    series termsCount coeffBase +        | termsCount > 0 =+            1 + xSquareOverXSquarePlus1 * coeff * (series (termsCount - 1) (coeffBase + 2))+        | otherwise =+            1 + xSquare * (coeff RA.\/ 1)+        where+        coeff = coeffBase / (coeffBase + 1)+    xSquare = abs $ x * x+    xSquarePlus1 = xSquare + 1+    xSquareOverXSquarePlus1 = xSquare / xSquarePlus1+    +--{- atan using Newton -}+--+--atanNewton_RA :: +--    (RA.ERIntApprox ira) => +--    EffortIndex -> ra -> ra+--    +--atanNewton_RA i x = +--    erNewton_FullArgs +--        ( \ i y -> (erTan_RA i y) - x, erTanDeriv_RA) +--        (RA.setMinGranularity (effIx2gran i) (x))+--        (RA.setMinGranularity (effIx2gran i) 1) +--        (fromInteger $ toInteger i)+--        i++{- tan -}++erTan_R :: +    (RA.ERIntApprox ira) => +    EffortIndex -> ira -> ira+    +erTan_R ix x =+    (erSine_R ix x) / (erCosine_R ix x)++erTanDeriv_R ix x = +    recip $ abs $ cosx * cosx+    where+    cosx = erCosine_R ix x+++{- pi -}++{-|+    pi using Bellard's formula+    +    Convergence properties:+    +    * shrinking sequence+     +    * rate at least 2^(-i).+    +-}+erPi_R :: +    (RA.ERIntApprox ira) => +    EffortIndex -> ira+erPi_R = piBellard_R++-- | pi using atan +piAtan_R ::+    (RA.ERIntApprox ira) => +    EffortIndex -> ira+piAtan_R ix =+    (*) 4 $ atanEuler_R ix 1++{-|+    pi using Bellard's formula+    (see <http://en.wikipedia.org/wiki/Computing_π>)+    +    Convergence properties:+    +    * shrinking sequence+     +    * rate at least 2^(-i).+    +-}+piBellard_R ::+    (RA.ERIntApprox ira) => +    EffortIndex -> ira+piBellard_R ix =+    r1over64 * (sum $ reverse $ bellardTerms 0 (10 + (ix `div` 10)) (1,z,z))+    {- +      sum from the smallest to the largest +      (got this trick from Martin Escardo who said he got it from Andrej Bauer)+      +      the rounding error dominates the truncation error to such+      a degree that the truncation error can be safely left out+      +      each bellard term contributes 10 binary digits that the following terms+      do not influence+    -} +    where+    gran = max 0 (effIx2gran ix) + 10+    r1over64 = (RA.setMinGranularity gran 1) / 64+    r1over1024 = (RA.setMinGranularity gran 1) / 1024+    z = RA.setMinGranularity gran 0+    bellardTerms n nMax (mult, r4n, r10n)+        | n >= nMax = []+        | otherwise =+             termN : rest+        where+        rest = +            bellardTerms (n + 1) nMax (- mult * r1over1024, r4n + 4, r10n + 10)+        termN = +            mult * bellardSum+        bellardSum =+            -- sum from the smallest to the largest+            (recip $ r10n + 9)+            - (recip $ r4n + 3)+            - 4 * ((recip $ r10n + 7) + (recip $ r10n + 5))+            - (64 / (r10n + 3))+            - (32 / (r4n + 1))+            + (256 / (r10n + 1)) +    +    
+ src/Data/Number/ER/Real/Arithmetic/Integration.hs view
@@ -0,0 +1,141 @@+{-|+    Module      :  Data.Number.ER.Real.Arithmetic.Integration+    Description :  simple integration methods+    Copyright   :  (c) Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  portable++    Simple integration methods for Haskell functions operating +    on real number approximations.+-}+module Data.Number.ER.Real.Arithmetic.Integration+(+    integrateCont,+--    integrateDiff,+    integrateCont_R,+    integrateContAdapt_R+)+where++import qualified Data.Number.ER.Real.Approx as RA+import Data.Number.ER.BasicTypes+import Data.Number.ER.Real.Approx.Sequence+import Data.Number.ER.Real.Arithmetic.Elementary++testIntegr1 :: +    (RA.ERIntApprox ira) => +    (ConvergRealSeq ira)+testIntegr1 = integrateCont erExp_IR 0 1++integrateCont :: +    (RA.ERIntApprox ira) => +    (EffortIndex -> ira -> ira) ->+    (ConvergRealSeq ira) -> (ConvergRealSeq ira) -> (ConvergRealSeq ira)++integrateCont f = convertBinFuncRA2Seq $ integrateContAdapt_R f++integrateDiff :: +    (RA.ERIntApprox ira) => +    (EffortIndex -> ira -> ira, EffortIndex -> ira -> ira) ->+    (ConvergRealSeq ra) -> (ConvergRealSeq ra) -> (ConvergRealSeq ra)++integrateDiff f = convertBinFuncRA2Seq $ integrateDiffAdapt_RA f+++{-|+    naive integration, using a partition of 2 * prec equally sized intervals+-}+integrateCont_R ::+    (RA.ERIntApprox ira) => +    (EffortIndex -> ira -> ira) ->+    EffortIndex -> (ira) -> (ira) -> (ira)+integrateCont_R f ix a b =+    sum $ map rectArea rectangles+    where+    rectArea (width, height) = width * height+    rectangles = +        zip (repeat width) $ map (f ix) covering+    width = (b - a) / (fromInteger rectCount)+    rectCount = 2 * (fromInteger $ toInteger gran)+    gran = effIx2gran ix+    covering = getCoveringIntervals division+    getCoveringIntervals ( pt1 : pt2 : rest ) =+        ((pt1) RA.\/ (pt2)) : (getCoveringIntervals $ pt2 : rest)+    getCoveringIntervals _ = []+    division = map getEndPoint $ [0..rectCount]+    getEndPoint n =+        a + ((fromInteger n) * width)++{-|+    integration using divide and conquer adaptive partitioning+-}+integrateContAdapt_R ::+    (RA.ERIntApprox ira) => +    (EffortIndex -> ira -> ira) ->+    EffortIndex -> (ira) -> (ira) -> (ira)+integrateContAdapt_R f ix a b =+    sum rectangleAreas+    where+    rectangleAreas = +        getRs ix a b+    getRs subix l r+        | RA.getPrecision area >= prec = [area]+        | otherwise =+            (getRs nsubix l m) ++ (getRs nsubix m r)+        where+        prec = foldl1 min [effIx2prec ix, RA.getPrecision l, RA.getPrecision r]+        area = (r - l) * (f subix (l RA.\/ r))+        nsubix = subix + 1+        m = (l + r)/2+        ++{-|+    integration using divide and conquer adaptive partitioning+    making use of the derivative of the integrated function+-}+integrateDiffAdapt_RA ::+    (RA.ERIntApprox ira) => +    (EffortIndex -> ira -> ira, EffortIndex -> ira -> ira) ->+    EffortIndex -> (ra) -> (ra) -> (ra)+integrateDiffAdapt_RA f prec a b =+    error "TODO"+    +{-+    sum rectangleAreas+    where+    rectangleAreas = +        getRs prec a b+    getRs p l r+        | getPrecision area >= prec = [area]+        | otherwise =+            (getRs np l m) ++ (getRs np m r)+        where+        np = p + 1+        m = (l + r)/2+--        area = areaDiff+        area = areaRect /\ areaDiff+            -- merge the information given by the rectangle method+            -- with the information given by the derivative method+        areaRect = w * fVal -- same as in integrateContAdapt_R+        (fVal, fDeriv) = applyRdiffR f p (l \/ r)+        w = r - l+        areaDiff+            | isExact fDeriv = w * (fl + fr) / 2 -- derivative is constant and perfectly known+            | otherwise = areaLow \/ areaHigh+        fl = fst $ applyRdiffR f (2 * p) l+        fr = fst $ applyRdiffR f (2 * p) r+            -- interestingly, we have to request fl, fr with higher precision than+            -- we requested fDeriv so that the derivative would be of any use+            -- with these values - replace (2 * p) by p and it will not converge!+        -- area computed by a scary formula:+        areaLow = t + w * (fl * dHigh - fr * dLow) / dDiff+        areaHigh = - t - w * (fl * dLow - fr * dHigh) / dDiff -- swap dHigh and dLow+        t = (w^2 * dLow * dHigh + (fr - fl)^2)/(2 * dDiff)+        dDiff = dHigh - dLow+        (dLow, dHigh) = getBounds fDeriv+-}        +        +    
+ src/Data/Number/ER/Real/Arithmetic/Newton.hs view
@@ -0,0 +1,201 @@+{-| ++    Module      :  Data.Number.ER.Real.Arithmetic.Taylor+    Description :  interval Newton method+    Copyright   :  (c) Amin Farjudian, Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  alpha+    Portability :  portable++    Interval Newton's method for root finding. +       +    To be used for obtaining functions out of their inverse(s) over various +    intervals.+-}+module Data.Number.ER.Real.Arithmetic.Newton +(+    erNewton_FullArgs,+    erNewton_mdfd_FullArgs+)+where++import qualified Data.Number.ER.Real.Approx as RA+import Data.Number.ER.BasicTypes+import Data.Number.ER.Real.Arithmetic.Taylor++erNewton_FullArgs+	:: (RA.ERIntApprox ira)+	=> (EffortIndex -> ira -> ira, EffortIndex -> ira -> ira) -- ^ a function and its derivative+	-> ira -- ^ a starting point+	-> ira -- ^ a lower bound of the absolute value of the derivative over the working interval+	-> Int -- ^ number of iterations+	-> EffortIndex  -- ^ the initial index to use for argument function and its derivative+	-> ira -- ^ the result+	+erNewton_FullArgs (f ,df) startPt minDrv iterCnt i = +    erNewton_FullArgs_aux startPt startOtherPt iterCnt+	where +    erNewton_FullArgs_aux newtonPt otherPt iterCnt+        | (iterCnt <= 0 || RA.getPrecision result >= prec) =+            result +        | otherwise = +            erNewton_FullArgs_aux newNewtonPt newOtherPt (iterCnt - 1)+        where +        result = +            newtonPt RA.\/ otherPt+        prec = effIx2prec i +        newNewtonPt = +            midPoint $ RA.bounds $ +            (newtonPt - ( (f i newtonPt) / (( df i newtonPt)))) +               --  /\ (ira2ra ((ra2ira minDrv) \/ 100000000)))))+        newOtherPt = otherEndPoint newNewtonPt+    startOtherPt = otherEndPoint startPt+    otherEndPoint a =  a - ((f i a) / minDrv) --   /\ (0 \/ 10000000)++    +{-|+    This auxiliary function returns the average of two ra's+-}+midPoint+    :: (RA.ERIntApprox ira)+    => (ira ,ira)+    -> ira+midPoint (x1, x2) = (x1 + x2) / 2+        ++{-| Modified Newton Method+    Notes:+    +        1. It has a cubic convergence speed, as opposed to the original Newton's+            square convergence speed.+            +        2. It does not deal with multiple roots.+        +        3. Per iteration, it makes two queries on the derivative, so it best +            suits the cases where computation of the derivative is at most as+            expensive as the function itself.+-}+erNewton_mdfd_FullArgs+    :: (RA.ERIntApprox ira)+    => (EffortIndex -> ira -> ira, EffortIndex -> ira -> ira) -- ^ a function and its derivative+    -> ira -- ^ a starting point+    -> ira -- ^ The minimum of absolute value of derivative over the working interval+    -> Int -- ^ number of iterations+    -> EffortIndex  -- ^ It triggers the initial index to be called by the argument function and its derivative.+    -> ira -- ^ the result+    +erNewton_mdfd_FullArgs (f ,df) startPt minDrv iterCnt i = +    erNewton_FullArgs_aux startPt startOtherPt iterCnt+    where +    erNewton_FullArgs_aux newtonPt otherPt iterCnt+        | iterCnt <= 0 = newtonPt RA.\/ otherPt+        | otherwise = erNewton_FullArgs_aux newNewtonPt newOtherPt (iterCnt - 1)+        where+        valueAtNewOtherPt = f i newOtherPt+        derivAtNewtonPt   = df i newOtherPt+        unblurredDeriv = midPoint $ RA.bounds $ derivAtNewtonPt+        intermediaryPt = midPoint $ RA.bounds $ newtonPt - valueAtNewOtherPt / (2 * derivAtNewtonPt)+        derivAtIntermediaryPt = df i intermediaryPt+        newNewtonPt = +            midPoint $ RA.bounds $ +            (newtonPt - ( valueAtNewOtherPt / derivAtIntermediaryPt))+        newOtherPt = otherEndPoint newNewtonPt+    startOtherPt = otherEndPoint startPt+    otherEndPoint a = a - ((f i a) / minDrv)++erNewton_mdfd+    :: (RA.ERIntApprox ira)+    => (EffortIndex -> ira -> ira, EffortIndex -> ira -> ira) -- ^ a function and its derivative+    -> ira -- ^ a starting point+    -> ira -- ^ The minimum of absolute value of derivative over the working interval+    -> EffortIndex  -- ^ It triggers the initial index to be called by the argument function and its derivative.+    -> ira -- ^ the result+    +erNewton_mdfd (f ,df) startPt minDrv i = +    erNewton_mdfd_FullArgs (f, df) startPt minDrv (fromInteger $ toInteger $ i) i++--apNewton_mdfd+--    :: (RA.ERIntApprox ira)+--    => (EffortIndex -> ra -> ra, EffortIndex -> ra -> ra) -- ^ a function and its derivative+--    -> ra -- ^ a starting point+--    -> ra -- ^ The minimum of absolute value of derivative over the working interval+--    -> EffortIndex  -- ^ It triggers the initial index to be called by the argument function and its derivative. Moreover, the number of iterations are predefined by this argument.+--    -> ra -- ^ the result+--    +--apNewton_mdfd (f, df) startPt minDrv i =+--    erNewton_mdfd_FullArgs+--+			+--id_RA +--	:: (RA.ERIntApprox ira)+--	=> EffortIndex -> ira -> ira+--+--id_RA i x = x+--+--const_one_RA+--	:: (RA.ERIntApprox ira)+--	=> EffortIndex -> ira -> ira+--+--const_one_RA i x = (setMinGranularity (effIx2gran i) 1)+--	+--+--test_erNewton_FullArgs_01_RA +--	:: (RA.ERIntApprox ira)+--	=> EffortIndex -> ira -> ira+--+--test_erNewton_FullArgs_01_RA i x = erNewton_FullArgs_01 ( id_RA, const_one_RA) x 10 i+--+--test_erNewton_FullArgs_01+--	:: (RA.ERIntApprox ira)+--	=> (ConvergRealSeq ira) -> (ConvergRealSeq ira)+--	+--test_erNewton_FullArgs_01 = convertFuncRA2Seq test_erNewton_FullArgs_01_RA+--+--exp_Ra_minus_r_RA+--	:: (RA.ERIntApprox ira)+--	=> EffortIndex -> ira -> ira -> ira +--	+--exp_Ra_minus_r_RA i r x = (erExp_RA i x) - r+--+--exp_Ra_minus_r +--	:: (RA.ERIntApprox ira)+--	=> (ConvergRealSeq ira) -> (ConvergRealSeq ira) -> (ConvergRealSeq ira)+--+--exp_Ra_minus_r = convertBinFuncRA2Seq exp_Ra_minus_r_RA+--+--logNewton_RA_02+--    :: (RA.ERIntApprox ira)+--    => EffortIndex -> ira -> ira+--    +--logNewton_RA_02 i x = +--    erNewton_FullArgs_02+--        ( \ i y -> (erExp_RA i y) - x, erExp_RA) +--        (setMinGranularity (effIx2gran i) (2)) +--        (setMinGranularity (effIx2gran i) 1) +--        i   +--+--logNewton_02  +--    :: (RA.ERIntApprox ira)+--    => (ConvergRealSeq ira) -> (ConvergRealSeq ira)+--    +--logNewton_02 = convertFuncRA2Seq logNewton_RA_02+++--logNewton_mdfd_RA+--    :: (RA.ERIntApprox ira)+--    => EffortIndex -> ira -> ira+    +--logNewton_mdfd_RA i x = +--    erNewton_mdfd_FullArgs+--        ( \ i y -> (erExp_RA i y) - x, erExp_RA) +--        (setMinGranularity (effIx2gran i) (2)) +--        (setMinGranularity (effIx2gran i) 1) +--        i   ++--logNewton_mdfd+--    :: (RA.ERIntApprox ira)+--    => (ConvergRealSeq ira) -> (ConvergRealSeq ira)+--    +--logNewton_mdfd = convertFuncRA2Seq logNewton_mdfd_RA
+ src/Data/Number/ER/Real/Arithmetic/Taylor.hs view
@@ -0,0 +1,177 @@+{-|+    Module      :  Data.Number.ER.Real.Arithmetic.Taylor+    Description :  implementation of Taylor series+    Copyright   :  (c) Amin Farjudian, Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  portable++    Taylor series related functions.+-}+module Data.Number.ER.Real.Arithmetic.Taylor where++import qualified Data.Number.ER.Real.Approx as RA+import qualified Data.Number.ER.ExtendedInteger as EI+import Data.Number.ER.BasicTypes+++erTaylor_R+    :: (RA.ERIntApprox ira)+    => EffortIndex+    -> (Int -> ira) -- ^ coefficients of the Taylor series+    -> (Int -> ira) -- ^ function to estimate the n'th derivative between a and x+    -> ira -- ^ centre of the Taylor Expansion+    -> ira +    -> ira+erTaylor_R ix coefSeq derivBounds a x =+    erTaylor_R_FullArgs coefSeq derivBounds n a gran x+    where+    n = fromInteger ix+    gran = fromInteger $ toInteger $ ix++erTaylor_R_FullArgs+    :: (RA.ERIntApprox ira)+    => (Int -> ira)  -- ^ coefficients of the Taylor series+    -> (Int -> ira) -- ^ function to estimate the n'th derivative between a and x+    -> Int -- ^ use this many elements of the series (+ account for error appropriately)+    -> ira -- ^ centre of the Taylor Expansion+    -> Granularity -- ^ make all constants have this granularity, thus influencing rounding errors+    -> ira +    -> ira+erTaylor_R_FullArgs coefSeq derivBounds n a gran x = +    rec_apTaylor (RA.setMinGranularity gran 0) 0+    where+    rec_apTaylor i j+        | n > j = (coefSeq(j)) + +                        ((x - a)/(i+1)) * (rec_apTaylor (i+1) (j+1))+        | n == j = derivBounds n+        | otherwise = +            error "Data.Number.ER.Real.Arithmetic.Taylor.hs: erTaylor_RA_FullArgs: The index n cannot be negative"++{-|+    A Taylor series for exponentiation.    +-}+erExp_Tay_Opt_R+    :: (RA.ERIntApprox ira)+    => EffortIndex+    -> ira+    -> ira+erExp_Tay_Opt_R ix x +    | RA.isEmpty x = RA.emptyApprox+    | x `RA.refines` (-1/0) = 0 -- -infty is not handled well by the Taylor formula+    | otherwise = 1 + (te ix x (RA.setMinGranularity gran 1))+    where+    gran = effIx2gran ix+    te steps x i+        | steps > 0 =+            (x/i) * (1 + (te (steps - 1) x (i + 1)))+        | steps == 0 = +            errorBound+            where+            errorBound = +                (x/i) * ithDerivBound+            ithDerivBound +                | xCeiling == EI.MinusInfinity = -- certainly -infty:+                    0+                | xCeiling < 0 = -- certainly negative:+                    pow26xFloor RA.\/ 1+                | xFloor > 0 = -- certainly positive:+                    1 RA.\/ pow28xCeiling+                | otherwise = -- could contain 0:+                    pow26xFloor RA.\/ pow28xCeiling+                where+                (xFloor, xCeiling) = RA.integerBounds x+                pow26xFloor +                    | xFloor == EI.MinusInfinity =+                        0+                    | otherwise = +                        ((RA.setMinGranularity gran 26)/10) ^^ xFloor +                            -- lower estimate of e^x+                pow28xCeiling +                    | xCeiling == EI.PlusInfinity =+                        (1/0)+                    | otherwise = +                        ((RA.setMinGranularity gran 28)/10) ^^ xCeiling +                            -- upper estimate of e^x++{-+ The sine and cosine are implemented in almost exactly the same way +-}++{-|+    A Taylor series for sine.    +-}+erSine_Tay_Opt_R+    :: (RA.ERIntApprox ira)+    => EffortIndex+    -> ira+    -> ira+erSine_Tay_Opt_R ix x = taylor_seg ix x (RA.setMinGranularity gran 1)+	where+		gran = effIx2gran ix+		taylor_seg i x n -- 'i' for iterator+			| i > 0  = x - ((x*x)/((n+1)*(n+2))) * (taylor_seg (i-2) x (n+2))+			| otherwise = errorRegion+				where +					errorRegion = (-1) RA.\/ (1)+		+{-|+    A Taylor series for cosine.    +-}+erCosine_Tay_Opt_R +    :: (RA.ERIntApprox ira) +    => EffortIndex +    -> ira+    -> ira+erCosine_Tay_Opt_R ix x = taylor_seg ix x (RA.setMinGranularity gran 1)+	where+		gran = effIx2gran ix+		taylor_seg i x n -- 'i' for iterator+			| i > 0  = 1 - ((x*x)/(n*(n+1))) * (taylor_seg (i-2) x (n+2))+			| otherwise = errorRegion+				where +					errorRegion = (-1) RA.\/ (1)++   +				+{-| Natural Logarithm: The following is a code for obtaining natural+ 	logarithm using taylor series. Note that it only works for + 	x in [ 1, 2]. For other values, a scaling by factors of e^q is+ 	best to do, i.e. if x is not in [1,2], then find some ratioal number				+ 	q where exp(q) * x is in [1,2]. Then you have:+ 	log ( exp(q) * m)  = q + log(m)+-}++{-| Coefficients of the taylor series around a=1 -}+--logTayCoefs+--	:: (RA.ERIntApprox ira)+--	=>	Int -- up to how many terms of the Taylor series is desired+--	-> Int+--    -> ra+--	+--logTayCoefs n i +----	| i < 0 = error "ERTaylor.logTayCoefs: Negative n for the n-th term of Taylor series for logarithm"+--	| i == 0 = 0+--	| i == n = fromInteger $ toInteger $ amFact(n-1)	+--	| otherwise = fromInteger $ toInteger $ ((-1)^(i-1) * amFact(i-1))+--	where+--		amFact (m) = product [1..m]+		+--logTay_RA+--	:: (RA.ERIntApprox ira)+--	=> EffortIndex+--    -> ra+--    -> ra+--	+--logTay_RA i = erTaylor_RA_FullArgs (logTayCoefs $fromInteger $ toInteger $ i) +--                (100000) (setMinGranularity (effIx2gran i) 1) (effIx2gran i)+--	+--	+--logTay +--	:: (RA.ERIntApprox ira)	+--	=> (ConvergRealSeq ra)+--    -> (ConvergRealSeq ra)+--logTay = convertFuncRA2Seq logTay_RA	+					
+ src/Data/Number/ER/Real/Base.hs view
@@ -0,0 +1,58 @@+{-|+    Module      :  Data.Number.ER.Real.Base+    Description :  class abstracting floats+    Copyright   :  (c) Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  portable++    Abstraction over various fixed and floating point types as well+    as rational numbers.+    +    This module should be included qualified as is often given the local+    synonym B.+-}+module Data.Number.ER.Real.Base+(+    module Data.Number.ER.BasicTypes,+    ERRealBase(..)+)+where++import Data.Number.ER.BasicTypes+import qualified Data.Number.ER.ExtendedInteger as EI++import Data.Typeable++{-|+    This class is an abstraction of a subset of real numbers+    with upwards rounded operations. +-}+class (Fractional rb, Ord rb) => ERRealBase rb +    where+    defaultGranularity :: rb -> Granularity+    getApproxBinaryLog :: rb -> EI.ExtendedInteger+    getGranularity :: rb -> Granularity+    setMinGranularity :: Granularity -> rb -> rb+    setGranularity :: Granularity -> rb -> rb+    {-|+        if @a@ is rounded to @ao@ then @|a-ao| <= getBaseMaxRounding ao@+    -}+    getMaxRounding :: rb -> rb+    isERNaN :: rb -> Bool+    erNaN :: rb+    isPlusInfinity :: rb -> Bool+    plusInfinity :: rb+    minusInfinity :: rb+    minusInfinity = - plusInfinity+    fromDouble :: Double -> rb+    toDouble :: rb -> Double+    fromFloat :: Float -> rb+    toFloat :: rb -> Float+    showDiGrCmp :: +        Int {- ^ number of decimal digits to show -} ->+        Bool {-^ whether to show granularity -} ->+        Bool {-^ whether to show internal structure -} ->+        rb -> String
+ src/Data/Number/ER/Real/Base/CombinedMachineAP.hs view
@@ -0,0 +1,238 @@+{-# LANGUAGE DeriveDataTypeable   #-}+{-# LANGUAGE ScopedTypeVariables  #-}+{-|+    Module      :  Data.Number.ER.Real.Base.CombinedMachineAP+    Description :  auto-switching hardware-software floats +    Copyright   :  (c) Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  non-portable (requires fenv.h)++    Arbitrary precision floating point numbers that use+    machine double up to its precision.  When a higher+    granularity is required, it automatically switches +    to another floating point type.+-}+module Data.Number.ER.Real.Base.CombinedMachineAP +(+    ERMachineAP,+    doubleDigits+)+where++import qualified Data.Number.ER.Real.Base as B+import qualified Data.Number.ER.ExtendedInteger as EI+import Data.Number.ER.Real.Base.MachineDouble+import Data.Number.ER.Real.Base.Float+import Data.Number.ER.BasicTypes+import Data.Number.ER.Misc++import Data.Typeable+import Data.Generics.Basics+import Data.Binary+--import BinaryDerive++import Data.Ratio++data ERMachineAP b =+    ERMachineAPMachineDouble+    {+        machapfltDoubleGranularity :: Granularity+        {-^ this has to be between 1 and 'doubleDigits' -}+    ,+        machapfltDouble :: Double+    }+    |    +    ERMachineAPB+    {+        machapfltB :: b+    }+    deriving (Typeable, Data)++doubleDigits = floatDigits (0 :: Double)++{- the following has been generated by BinaryDerive -}     +instance (Binary b) => (Binary (ERMachineAP b)) where+  put (ERMachineAPMachineDouble a b) = putWord8 0 >> put a >> put b+  put (ERMachineAPB a) = putWord8 1 >> put a+  get = do+    tag_ <- getWord8+    case tag_ of+      0 -> get >>= \a -> get >>= \b -> return (ERMachineAPMachineDouble a b)+      1 -> get >>= \a -> return (ERMachineAPB a)+      _ -> fail "no parse"+{- the above has been generated by BinaryDerive -}+    +lift1ERMachineAP ::+    (Double -> Double) ->+    (b -> b) ->+    (ERMachineAP b -> ERMachineAP b)+lift1ERMachineAP fD fB (ERMachineAPMachineDouble g d) = +    ERMachineAPMachineDouble g (fD d) +lift1ERMachineAP fD fB (ERMachineAPB b) = +    ERMachineAPB (fB b) ++op1ERMachineAP ::+    (Double -> a) ->+    (b -> a) ->+    (ERMachineAP b -> a)+op1ERMachineAP fD fB (ERMachineAPMachineDouble g d) = +    fD d +op1ERMachineAP fD fB (ERMachineAPB b) = +    fB b ++lift2ERMachineAP ::+    (B.ERRealBase b) =>+    (Double -> Double -> Double) ->+    (b -> b -> b) ->+    (ERMachineAP b -> ERMachineAP b -> ERMachineAP b)+lift2ERMachineAP fD fB +        (ERMachineAPMachineDouble g1 d1) (ERMachineAPMachineDouble g2 d2) = +    ERMachineAPMachineDouble (max g1 g2) (fD d1 d2)+lift2ERMachineAP fD fB +        (ERMachineAPMachineDouble g1 d1) (ERMachineAPB b2) = +    ERMachineAPB $ fB (B.fromDouble d1) b2+lift2ERMachineAP fD fB +        (ERMachineAPB b1) (ERMachineAPMachineDouble g2 d2) = +    ERMachineAPB $ fB b1 (B.fromDouble d2)+lift2ERMachineAP fD fB +        (ERMachineAPB b1) (ERMachineAPB b2) = +    ERMachineAPB $ fB b1 b2+    +op2ERMachineAP ::+    (B.ERRealBase b) =>+    (Double -> Double -> a) ->+    (b -> b -> a) ->+    (ERMachineAP b -> ERMachineAP b -> a)+op2ERMachineAP fD fB +        (ERMachineAPMachineDouble g1 d1) (ERMachineAPMachineDouble g2 d2) = +    fD d1 d2+op2ERMachineAP fD fB +        (ERMachineAPMachineDouble g1 d1) (ERMachineAPB b2) = +    fB (B.fromDouble d1) b2+op2ERMachineAP fD fB +        (ERMachineAPB b1) (ERMachineAPMachineDouble g2 d2) = +    fB b1 (B.fromDouble d2)+op2ERMachineAP fD fB +        (ERMachineAPB b1) (ERMachineAPB b2) = +    fB b1 b2+    +instance (B.ERRealBase b) => Show (ERMachineAP b)+    where+    show = showERMachineAP 6 True True+    +showERMachineAP numDigits showGran showComponents =+    showEMA+    where+    maybeGran gr+        | showGran = "{g=" ++ show gr ++ "}"+        | otherwise = ""+    maybeComps+        | showComponents = "{Double}"+        | otherwise = ""+    showEMA (ERMachineAPMachineDouble gr d) = +        show d ++ (maybeGran gr) ++ maybeComps+    showEMA (ERMachineAPB b) = +        B.showDiGrCmp numDigits showGran showComponents b+++instance (B.ERRealBase b) => Eq (ERMachineAP b)+    where+    (==) = op2ERMachineAP (==) (==)+    +instance (B.ERRealBase b) => Ord (ERMachineAP b)+    where+    compare = op2ERMachineAP compare compare+    ++    +instance (B.ERRealBase b) => Num (ERMachineAP b)+    where+    fromInteger n +        | gran < doubleDigits = +            ERMachineAPMachineDouble gran $ fromInteger n+        | otherwise = +            ERMachineAPB b+        where+        gran = B.getGranularity b    +        b = fromInteger n+    abs = lift1ERMachineAP abs abs  +    signum = lift1ERMachineAP signum signum+    negate = lift1ERMachineAP negate negate+    (+) = lift2ERMachineAP (+) (+)+    (*) = lift2ERMachineAP (*) (*)+    +instance (B.ERRealBase b) => Fractional (ERMachineAP b)+    where+    fromRational rat =+        (fromInteger $ numerator rat) +        / (fromInteger $ denominator rat)+    recip = lift1ERMachineAP recip recip+    (/) = lift2ERMachineAP (/) (/)+        +instance (B.ERRealBase b, Real b) => Real (ERMachineAP b)+    where+    toRational = op1ERMachineAP toRational toRational+    +instance (B.ERRealBase b, RealFrac b) => RealFrac (ERMachineAP b)+    where+    properFraction (ERMachineAPMachineDouble g d) =+        (a, ERMachineAPMachineDouble g remainder)+        where+        (a,remainder) = properFraction d +    properFraction (ERMachineAPB b) =+        (a, ERMachineAPB remainder)+        where+        (a,remainder) = properFraction b +        +        +instance (B.ERRealBase b) => B.ERRealBase (ERMachineAP b)+    where+    defaultGranularity _ = (B.defaultGranularity (0 :: b))+    getApproxBinaryLog = +        op1ERMachineAP doubleBinaryLog B.getApproxBinaryLog+        where+        doubleBinaryLog d+            | d < 0 =+                error $ "ERMachineAP: getApproxBinaryLog: negative argument " ++ show d +            | d == 0 = EI.MinusInfinity +            | d >= 1 =+                fromInteger $ intLog 2 $ ceiling d+            | d < 1 =+                negate $ fromInteger $ intLog 2 $ ceiling $ recip d+    getGranularity (ERMachineAPB b) = B.getGranularity b+    getGranularity (ERMachineAPMachineDouble gr _) = gr+    setMinGranularity gran (ERMachineAPMachineDouble g d) +        | gran > doubleDigits =+            ERMachineAPB $ B.setMinGranularity gran $ B.fromDouble d+        | otherwise =+            ERMachineAPMachineDouble gran d+    setMinGranularity gran (ERMachineAPB b) = ERMachineAPB $ B.setMinGranularity gran b +    setGranularity gran (ERMachineAPMachineDouble g d) +        | gran > doubleDigits =+            ERMachineAPB $ B.setGranularity gran $ B.fromDouble d+        | otherwise =+            ERMachineAPMachineDouble gran d+    setGranularity gran (ERMachineAPB b)+        | gran <= doubleDigits =+            ERMachineAPMachineDouble gran $ B.toDouble b+        | otherwise = +            ERMachineAPB $ B.setGranularity gran b +    getMaxRounding _ = +        error "ERMachineAP: getMaxRounding not implemented yet"+    isERNaN = op1ERMachineAP isNaN B.isERNaN+    erNaN = B.fromDouble (0/0)+    isPlusInfinity = +        op1ERMachineAP (== 1/0) B.isPlusInfinity+    plusInfinity = B.fromDouble $ 1/0+    fromDouble d = +        ERMachineAPMachineDouble (B.defaultGranularity (0 :: b)) d+    toDouble = op1ERMachineAP id B.toDouble+    fromFloat f = +        ERMachineAPMachineDouble (B.defaultGranularity (0 :: b)) $+            fromRational $ toRational f+    toFloat = op1ERMachineAP (fromRational . toRational) B.toFloat +    showDiGrCmp = showERMachineAP+    
+ src/Data/Number/ER/Real/Base/Float.hs view
@@ -0,0 +1,508 @@+{-# LANGUAGE DeriveDataTypeable   #-}+{-|+    Module      :  Data.Number.ER.Real.Base+    Description :  arbitrary precision floating point numbers+    Copyright   :  (c) Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  portable++    This module defines an arbitrary precision floating point type and+    its operations.  It should be viewed more abstractly as an instance+    of 'B.ERRealBase' when used as interval endpoints.+-}+module Data.Number.ER.Real.Base.Float+(+    ERFloat+)+where++import qualified Data.Number.ER.ExtendedInteger as EI+import Data.Number.ER.PlusMinus+import Data.Number.ER.Misc+import Data.Number.ER.BasicTypes+import qualified Data.Number.ER.Real.Base as B++import Data.Ratio++import Data.Typeable+import Data.Generics.Basics+import Data.Binary+-- import BinaryDerive++--debugMsg = unsafePrint+debugMsg msg = id+++{-|+A floating point number with a given but arbitrary precision represented by its 'Granularity'.++    * base: 2.+    +    * granularity specifies the bit-size of both the significand and the exponent  ++    * special values: NaN, signed Infinity and signed Zero+    +    * no denormalised numbers+    +    * operations unify the granularity of their operands to the maximum 'Granularity'+     +    * Rounding is always towards +Infinity.  +      For field operations, the rounded result is as close as possible to the exact result.+-}+data ERFloat =+    ERFloatNaN -- any number / bottom+        { +            apfltGran :: Granularity -- >0+        }+    | ERFloatInfty +        { +            apfltGran :: Granularity, -- >0+            apfltSign :: PlusMinus +        }+    | ERFloatZero+        { +            apfltGran :: Granularity, -- >0+            apfltSign :: PlusMinus +        }+    | ERFloat+        {+            -- represents:+            -- sign * (1 + (mant/2^gran)) * (2 ^ exp)+            apfltGran :: Granularity, -- >0  granularity+            apfltSign :: PlusMinus,+            apfltMant :: Integer, -- 0 .. (2^gran - 1)+            apfltExp :: Integer -- -2^gran..2^gran+        }+    deriving (Typeable, Data)+    +zero = ERFloatZero 10 Plus+    +{- the following has been generated by BinaryDerive -}+instance Binary ERFloat where+  put (ERFloatNaN a) = putWord8 0 >> put a+  put (ERFloatInfty a b) = putWord8 1 >> put a >> put b+  put (ERFloatZero a b) = putWord8 2 >> put a >> put b+  put (ERFloat a b c d) = putWord8 3 >> put a >> put b >> put c >> put d+  get = do+    tag_ <- getWord8+    case tag_ of+      0 -> get >>= \a -> return (ERFloatNaN a)+      1 -> get >>= \a -> get >>= \b -> return (ERFloatInfty a b)+      2 -> get >>= \a -> get >>= \b -> return (ERFloatZero a b)+      3 -> get >>= \a -> get >>= \b -> get >>= \c -> get >>= \d -> return (ERFloat a b c d)+      _ -> fail "no parse"+{- the above has been generated by BinaryDerive -}+    +    +{-| normalisation++  * ensures that the components are within their regions+  +  * possibly turning the number into a zero or infinity+-}+normaliseERFloat :: ERFloat -> ERFloat+normaliseERFloat flt@(ERFloat gr s m e) +    | m < 0 = +        normaliseERFloat $ +        ERFloat gr s (2*m + grmax) (e - 1)+    | m >= grmax =+        normaliseERFloat $ +        ERFloat gr s ((m - grmax + (rndCorr s)) `div` 2) (e + 1)+    | e > grmax =+        case s of+            Plus -> ERFloatInfty gr Plus+            Minus -> minERFloat gr -- round upwards!+    | e < -grmax = +        case s of+            Plus -> ulpERFloat gr -- round upwards!+            Minus -> ERFloatZero gr Minus+    | otherwise = flt+    where+    grmax = 2^gr+normaliseERFloat flt = flt++ulpERFloat gr =+    ERFloat gr Plus 0 (-2^gr)++minERFloat gr =+    ERFloat gr Minus (grmax - 1) grmax+    where+    grmax = 2^gr++maxERFloat gr =+    ERFloat gr Plus (grmax - 1) grmax+    where+    grmax = 2^gr++rndCorr Plus = 1+rndCorr Minus = 0++increaseERFloatExp e flt@(ERFloat gr s m eOld) =+    ERFloat gr s mNew e+    where+    mNew = +        -grmax + ((m + grmax +  (rndCorr s) * (ediff - 1)) `div` ediff)+                           --  .^^^^^^^^^^^^^^^^^^^^^^^^^ round upwards+    grmax = 2^gr+    ediff = 2^(e - eOld) -- assuming e >= eOld+increaseERFloatExp _ flt = flt++decreaseERFloatExp e flt@(ERFloat gr s m eOld) =+    ERFloat gr s mNew e+    where+    mNew = +        -grmax + ediff * (m + grmax)+    grmax = 2^gr+    ediff = 2^(eOld - e) -- assuming e <= eOld+decreaseERFloatExp _ flt = flt+++apFloatExponent :: ERFloat -> EI.ExtendedInteger++apFloatExponent (ERFloatInfty _ _) = EI.PlusInfinity+apFloatExponent (ERFloatZero _ _) = EI.MinusInfinity+apFloatExponent (ERFloatNaN _) = EI.PlusInfinity -- includes infinity+apFloatExponent flt = EI.Finite $ apfltExp flt+        ++setERFloatGranularity ::+    Granularity -> ERFloat -> ERFloat+setERFloatGranularity gr flt@(ERFloat oldGr s m e) +    | gr > 0 =+        normaliseERFloat $ ERFloat gr s newM e+    | otherwise =+        flt+    where+    newM = +        (m * (2^gr) +          + ((rndCorr s)*(2^oldGr - 1))) -- round upwards!+        `div` (2^oldGr)+setERFloatGranularity gr f = f { apfltGran = gr } +        +setERFloatMinGranularity ::+    Granularity -> ERFloat -> ERFloat+setERFloatMinGranularity gr flt+    | gr > oldGr = +        setERFloatGranularity gr flt+    | otherwise = flt+    where+    oldGr = apfltGran flt+        +apfltGranularity = apfltGran++{-^ see the documentation of 'ERRealBase.getBaseMaxRounding' -}+apfltGetMaxRounding ::+    ERFloat -> ERFloat+apfltGetMaxRounding f@(ERFloatNaN _) = f+apfltGetMaxRounding f@(ERFloatInfty _ _) = f+apfltGetMaxRounding (ERFloatZero gr _) =+    ERFloat gr Plus 0 (-(2^gr))+apfltGetMaxRounding (ERFloat gr s m e) =+    ERFloat gr Plus 0 (max (e - (toInteger gr)) (-(2^gr)))++instance Show ERFloat where+    show = showERFloat 6 True False+    +    +showERFloat numDigits showGran showComponents flt =+    showERF flt+    where+    maybeGran gr+        | showGran = "{g=" ++ show gr ++ "}"+        | otherwise = ""+    showERF (ERFloatNaN gr) = "NaN" ++ (maybeGran gr)  +    showERF (ERFloatZero gr pm) = show pm ++ "0" ++ (maybeGran gr)+    showERF (ERFloatInfty gr pm) = show pm ++ "oo" ++ (maybeGran gr)+    showERF f@(ERFloat gr s m e) =+        decimal ++ (maybeGran gr) ++ maybeComps+        where+        maybeComps+            | showComponents = "{val="++ show (s,m,e) ++ "}"+            | otherwise = ""+        decimal = +            show s +            ++ show digit1 ++ "." ++ (concat $ map show $ take numDigits digits)+            ++ "E" ++ show dexp+        dexp = dexpBound - zerosCount+        digit1 : digits =+            drop zerosCount preDigits+        dexpBound -- upper bound of dexp: f/10^dexpBound < 1+            | e > 0 = intLog 10 (2^e)+            | e <= 0 = 2 - (intLog 10 (2^(-e)))+        (zerosCount, preDigits) =+            getDigits 0 $ (abs $ setERFloatGranularity numBinDigits f) / (ten ^^ dexpBound)+        ten = setERFloatGranularity numBinDigits 10+        numBinDigits = 4 * numDigits+        getDigits prevZeros ff +            | digit == 0 = (zerosCount, digit : digits)+            | otherwise = (prevZeros, digit : digits)+            where+            digit :: Integer+            digit = truncate ff+            (zerosCount, digits) =+                getDigits zerosNow ((ff - (fromInteger digit)) * ten)+            zerosNow+                | digit == 0 = prevZeros + 1+                | otherwise = 0+            ++{-+    Beware: cannot use List.elem with ERFloat because of+    the intensional nature of Eq (eg ERFloatNaN /= ERFloatNaN).+-}+instance Eq ERFloat where+    (ERFloatNaN _) == _ = +        False+        -- error "cannot compare NaN"+    _ == (ERFloatNaN _) = +        False+        -- error "cannot compare NaN"+    (ERFloatZero _ _) == (ERFloatZero _ _) = True+    (ERFloatInfty _ pm1) == (ERFloatInfty _ pm2) = (pm1 == pm2)+    f1@(ERFloat gr1 s1 m1 e1) == f2@(ERFloat gr2 s2 m2 e2) +        | gr1 < gr2 =+            (setERFloatGranularity gr2 f1) == f2+        | gr1 > gr2 =+            f1 == (setERFloatGranularity gr1 f2)+        | otherwise =+            s1 == s2 && m1 == m2 && e1 == e2+    _ == _ = False    ++isERFloatNaN (ERFloatNaN _) = True+isERFloatNaN _ = False++instance Ord ERFloat where+    {- compare NaN -}+    compare _ (ERFloatNaN _) = +        error "ERFloat: comparing NaN - aborting"+    compare (ERFloatNaN _) _ = +        error "ERFloat: comparing NaN - aborting"+    {- compare infty -}+    compare (ERFloatInfty gr1 pm1) (ERFloatInfty gr2 pm2) =+        compare pm1 pm2+    compare _ (ERFloatInfty _ Plus) = LT+    compare _ (ERFloatInfty _ Minus) = GT+    compare (ERFloatInfty _ Plus) _ = GT+    compare (ERFloatInfty _ Minus) _ = LT+    {- compare zero -}+    compare (ERFloatZero gr1 pm1) (ERFloatZero gr2 pm2) = EQ+    compare (ERFloatZero _ _) (ERFloat _ Plus _ _) = LT+    compare (ERFloatZero _ _) (ERFloat _ Minus _ _) = GT+    compare (ERFloat _ Minus _ _) (ERFloatZero _ _) = LT+    compare (ERFloat _ Plus _ _) (ERFloatZero _ _) = GT+    {- compare regular -}+    compare (ERFloat _ Minus _ _) (ERFloat _ Plus _ _) = LT+    compare (ERFloat _ Plus _ _) (ERFloat _ Minus _ _) = GT+    compare (ERFloat gr1 Plus m1 e1) (ERFloat gr2 _ m2 e2) +        | e1 < e2 = LT+        | e1 > e2 = GT+        | gr1 == gr2 = compare m1 m2+        | otherwise = compare ((2^gr2)*m1) ((2^gr1)*m2)+    compare f1@(ERFloat _ Minus _ _) f2@(ERFloat _ _ _ _) =+        compare (-f2) (-f1)+        +instance Num ERFloat where+    fromInteger n+        | n == 0 = ERFloatZero (B.defaultGranularity zero) Plus+        | n < 0 =+            normaliseERFloat $ ERFloat gr Minus m e+        | otherwise = +            normaliseERFloat $ ERFloat gr Plus m e+        where+        gr = fromInteger e+        e = max (toInteger (B.defaultGranularity zero)) $ (intLog 2 $ abs n) - 1+        m = (abs n) - 2^gr+    abs f@(ERFloatNaN _) = f+    abs f = f { apfltSign = Plus }+    signum f@(ERFloatNaN _) = f+    signum (ERFloatZero gr Plus) = setERFloatMinGranularity gr 1+    signum (ERFloatZero gr Minus) = setERFloatMinGranularity gr (-1)+    signum (ERFloatInfty gr Plus) = setERFloatMinGranularity gr 1+    signum (ERFloatInfty gr Minus) = setERFloatMinGranularity gr (-1)+    signum flt = +        case apfltSign flt of { Plus -> 1; Minus -> -1 }+    negate (ERFloat gr s m e) = ERFloat gr (signNeg s) m e+    negate (ERFloatZero gr s) = ERFloatZero gr (signNeg s)+    negate (ERFloatInfty gr s) = ERFloatInfty gr (signNeg s)+    negate f@(ERFloatNaN _) = f+    {- addition -}+    f1 + f2 -- ensure equal granularity:+        | gr1 > gr2 = f1 + (setERFloatGranularity gr1 f2)+        | gr1 < gr2 = (setERFloatGranularity gr2 f1) + f2 +        where+        gr1 = apfltGran f1+        gr2 = apfltGran f2+    f@(ERFloatNaN _) + _ = f+    _ + f@(ERFloatNaN _) = f+    (ERFloatZero _ _) + f = f+    f + (ERFloatZero _ _) = f+    (ERFloatInfty gr Plus) + (ERFloatInfty _ Minus) =+        debugMsg ("ERFloat: infty - infty -> NaN\n") $ +        ERFloatNaN gr+    (ERFloatInfty gr Minus) + (ERFloatInfty _ Plus) = +        debugMsg ("ERFloat: -infty + infty -> NaN\n") $ +        ERFloatNaN gr+    f@(ERFloatInfty gr s) + _ = f+    _ + f@(ERFloatInfty gr s) = f+    f1@(ERFloat gr s1 m1 e1) + f2@(ERFloat _ s2 m2 e2)+        -- equalise the exponents: +        | e1 < e2 = f1 + (decreaseERFloatExp e1 f2)+        | e1 > e2 = (decreaseERFloatExp e2 f1) + f2+        -- ensure positive comes before negative: +        | s1 == Minus && s2 == Plus = +            f2 + f1+        -- opposite signs:+        | s1 == Plus && s2 == Minus && m1 == m2 =+            ERFloatZero gr Plus+        | s1 == Plus && s2 == Minus && m1 > m2 =+            normaliseERFloat $+            ERFloat gr s1 (m1 - m2 - 2^gr) e1+        | s1 == Plus && s2 == Minus && m1 < m2 =+            normaliseERFloat $+            ERFloat gr s2 (m2 - m1 - 2^gr) e1+        -- equal signs:+        | otherwise =+            normaliseERFloat $+            ERFloat gr s1 (m1 + m2 + 2^gr) e1+    {- multiplication -}+    -- ensure equal granularity:+    f1 * f2+        | gr1 > gr2 = f1 * (setERFloatGranularity gr1 f2)+        | gr1 < gr2 = (setERFloatGranularity gr2 f1) * f2 +        where+        gr1 = apfltGran f1+        gr2 = apfltGran f2+    -- NaN:+    f@(ERFloatNaN _) * _ = f+    _ * f@(ERFloatNaN _) = f+    -- Infty+    (ERFloatInfty gr _) * (ERFloatZero _ _) = +        debugMsg ("ERFloat: infty * 0 -> NaN\n") $ +        ERFloatNaN gr+    (ERFloatZero gr _) * (ERFloatInfty _ _) = +        debugMsg ("ERFloat: 0 * infty -> NaN\n") $ +        ERFloatNaN gr+    f * (ERFloatInfty gr s) = ERFloatInfty gr $ signMult s (apfltSign f)+    (ERFloatInfty gr s) * f = ERFloatInfty gr $ signMult s (apfltSign f)+    -- Zero+    (ERFloatZero gr s) * f = ERFloatZero gr $ signMult s (apfltSign f)+    f * (ERFloatZero gr s) = ERFloatZero gr $ signMult s (apfltSign f)+    -- regular+    f1@(ERFloat gr s1 m1 e1) * f2@(ERFloat _ s2 m2 e2) =+        normaliseERFloat $+        ERFloat gr s mNew (e1 + e2)+        where+        s = signMult s1 s2+        mNew = +            m1 + m2 +            + ((m1 * m2 + (rndCorr s) * (2^gr - 1)) +               `div` 2^gr)+    +instance Fractional ERFloat where+    fromRational rat = +--        error "ERFloat: fromRational cannot be implemented reliably: use apfloatFromRational instead"+        (fromInteger $ numerator rat) +        / (fromInteger $ denominator rat)+    f1 / f2 +        | gr1 > gr2 = f1 / (setERFloatGranularity gr1 f2)+        | gr1 < gr2 = (setERFloatGranularity gr2 f1) / f2+        where+        gr1 = apfltGran f1+        gr2 = apfltGran f2+    f@(ERFloatNaN _) / _ = f+    f1 / f2 =+        case apfltSign f1 of+            Plus -> f1 * (recip f2)+            Minus -> (- f1) * (recip (- f2)) -- rounding upwards!+    recip f@(ERFloatNaN _) = f+    recip (ERFloatZero gr s) = ERFloatInfty gr s+    recip (ERFloatInfty gr s) = ERFloatZero gr s+    recip (ERFloat gr s m e) =+        normaliseERFloat $+        ERFloat gr s mNew (-e)+        where+        mNew = +            (- grmax * m +             + (rndCorr s) * (grmax + m -1)) -- rounding upwards!+            `div`+            (grmax + m)+        grmax = 2^gr+        +        +apfloatFromRational ::+    Granularity -> Rational -> ERFloat+apfloatFromRational gran rat = +    (setERFloatMinGranularity gran (fromInteger $ numerator rat)) +        / (fromInteger $ denominator rat)+        +     +        +instance Real ERFloat where+    toRational (ERFloat gr s m e) =+        case s of+            Plus -> r+            Minus -> -r+        where+        r = (eOn2R) * (1 + mR/(grOn2R))+        mR = toRational m+        eOn2R = toRational $ 2 ^^ e+        grOn2R = toRational $ 2 ^ gr+    toRational (ERFloatZero _ _) = 0+    toRational f = +        error $ "cannot covert " ++ show f ++ " to a rational" +    +instance RealFrac ERFloat where+    properFraction (ERFloatNaN _) = +        error "no integral part in ERFloatNaN"+    properFraction (ERFloatZero _ _) =+        (0, 0)+    properFraction (ERFloatInfty _ _) =+        error "no integral part in ERFloatInfty"+    properFraction f@(ERFloat gr s m e) +        | e < 0 = (0, f)+        | s == Plus =+            (n, frac)+        | s == Minus =+            (-n, frac)+        where+        n = fromInteger $ 2^e + (m*(2^e) `div` 2^gr)+        frac = f - (fromInteger $ toInteger n)+        +    +instance B.ERRealBase ERFloat+    where+    defaultGranularity _ = 10+    getApproxBinaryLog = apFloatExponent+    getGranularity = apfltGran+    setMinGranularity = setERFloatMinGranularity+    setGranularity = setERFloatGranularity+    getMaxRounding = apfltGetMaxRounding+    isERNaN (ERFloatNaN _) = True+    isERNaN _ = False+    erNaN = ERFloatNaN (B.defaultGranularity zero)+    isPlusInfinity (ERFloatInfty _ Plus) = True+    isPlusInfinity _ = False+    plusInfinity = ERFloatInfty (B.defaultGranularity zero) Plus    +    fromDouble d+        | isNaN d = ERFloatNaN (B.defaultGranularity zero)+        | otherwise = (fromRational . toRational) d+    toDouble (ERFloatInfty _ s) = signToNum s * (1/0)+    toDouble (ERFloatNaN _) = 0/0+    toDouble flt =+        (fromInteger $ numerator rat) / (fromInteger $ denominator rat)+        where+        rat = toRational flt+    fromFloat f+        | isNaN f = ERFloatNaN (B.defaultGranularity zero)+        | otherwise = (fromRational . toRational) f+    toFloat (ERFloatInfty _ s) = signToNum s * (1/0) +    toFloat (ERFloatNaN _) = 0/0+    toFloat flt =+        (fromInteger $ numerator rat) / (fromInteger $ denominator rat)+        where+        rat = toRational flt+    showDiGrCmp = showERFloat+    
+ src/Data/Number/ER/Real/Base/MachineDouble.hs view
@@ -0,0 +1,87 @@+{-# INCLUDE <fenv.h> #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-|+    Module      :  Data.Number.ER.Real.Base.MachineDouble+    Description :  enabling Double's as interval endpoints+    Copyright   :  (c) Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  non-portable (requires fenv.h)++    Make 'Double' an instance of 'B.ERRealBase' as much as possible.    +-}+module Data.Number.ER.Real.Base.MachineDouble +(+    initMachineDouble+)+where++import qualified Data.Number.ER.Real.Base as B+import qualified Data.Number.ER.ExtendedInteger as EI+import Data.Number.ER.Misc++import Foreign.C++{- +    The following section is taken from Oleg Kiselyov's email+    http://www.haskell.org/pipermail/haskell/2005-October/016574.html+-}++type FP_RND_T = CInt  -- fenv.h++eFE_TONEAREST = 0+eFE_DOWNWARD = 0x400+eFE_UPWARD   = 0x800+eFE_TOWARDZERO = 0xc00++foreign import ccall "fenv.h fegetround" fegetround +  :: IO FP_RND_T++foreign import ccall "fenv.h fesetround" fesetround+  :: FP_RND_T -> IO FP_RND_T+{- end of Oleg's code -}++{-|+    Set machine floating point unit to the upwards-directed rounding+    mode.  +    +    This procedure has to be executed before using 'Double' +    as a basis for interval and polynomial arithmetic defined in this package.+-}+initMachineDouble :: IO ()+initMachineDouble =+    do+    currentRndMode <- fegetround+    case currentRndMode == eFE_UPWARD of+        True -> +            putStrLn "initMachineDouble: already rounding upwards" +        False ->+            do+            fesetround eFE_UPWARD+            putStrLn "initMachineDouble: switched to upwards rounding" ++instance B.ERRealBase Double+    where+    defaultGranularity _ = 53+    getApproxBinaryLog f +        | f == 0 =+            EI.MinusInfinity+        | otherwise =+            intLog 2 (abs $ ceiling f)+    getGranularity _ = 53+    setMinGranularity _ = id+    setGranularity _ = id+    getMaxRounding _ = 0+    isERNaN f = isNaN f+    erNaN = 0/0+    isPlusInfinity f = isInfinite f && f > 0+    plusInfinity = 1/0+    fromDouble = fromRational . toRational+    toDouble = fromRational . toRational+    fromFloat = fromRational . toRational+    toFloat = fromRational . toRational+    showDiGrCmp _numDigits _showGran _showComponents f = show f+    +
+ src/Data/Number/ER/Real/Base/Rational.hs view
@@ -0,0 +1,242 @@+{-# LANGUAGE DeriveDataTypeable   #-}+{-|+    Module      :  Data.Number.ER.Real.Base.Rational+    Description :  rational numbers with infinities+    Copyright   :  (c) Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  portable++    Unlimited size rational numbers extended with signed infinities and NaN.+    +    These can serve as endpoints of 'Data.Number.ER.Real.Approx.Interval.ERInterval'.+    +    To be imported qualified, usually with prefix ERAT. +-}+module Data.Number.ER.Real.Base.Rational +(+    ExtendedRational(..)+)+where++import Prelude hiding (isNaN)++import qualified Data.Number.ER.Real.Base as B+import qualified Data.Number.ER.ExtendedInteger as EI+import Data.Number.ER.PlusMinus+import Data.Number.ER.Misc++import Data.Ratio+import Data.Typeable+import Data.Generics.Basics++import Data.Binary++data ExtendedRational =+    NaN+    | Infinity PlusMinus+    | Finite Rational+    deriving (Typeable, Data)++{- the following has been generated by BinaryDerive -}     +instance Binary ExtendedRational where+  put NaN = putWord8 0+  put (Infinity a) = putWord8 1 >> put a+  put (Finite a) = putWord8 2 >> put a+  get = do+    tag_ <- getWord8+    case tag_ of+      0 -> return NaN+      1 -> get >>= \a -> return (Infinity a)+      2 -> get >>= \a -> return (Finite a)+      _ -> fail "no parse"+{- the above has been generated by BinaryDerive -}++eratSign :: ExtendedRational -> PlusMinus+eratSign NaN = error "ExtendedRational: eratSign: NaN"+eratSign (Infinity s) = s+eratSign (Finite r)+    | r < 0 = Minus+    | otherwise = Plus++liftToERational1 ::+    (Rational -> Rational) ->+    (ExtendedRational -> ExtendedRational)+liftToERational1 f (Finite r) = +    Finite (f r)++liftToERational2 ::+    (Rational -> Rational -> Rational) ->+    (ExtendedRational -> ExtendedRational -> ExtendedRational)+liftToERational2 f (Finite r1) (Finite r2) = +    Finite (f r1 r2)+++instance Show ExtendedRational +    where+    show = showERational 6 True False+    +showERational numDigits _showGran showComponents =+    showER+    where+    showER NaN = "NaN"+    showER (Infinity pm) =+        show pm ++ "oo"+    showER (Finite r) | r == 0 =+        "0"+    showER (Finite r) =+        decimal +        ++ (if showComponents then components else "")+        where+        components = "{" ++  show r ++ "}"+        decimal = +            show pm+            ++ show digit1 ++ "." ++ (concat $ map show $ take numDigits digits)+            ++ "E" ++ show dexp+        pm | r < 0 = Minus+           | otherwise = Plus+        dexp = dexpBound - zerosCount+        digit1 : digits =+            drop zerosCount preDigits+        dexpBound = -- upper bound of dexp: f/10^dexpBound < 1+            2 + (intLog 10 num) - (intLog 10 dnm)+        num = numerator absr+        dnm = denominator absr+        absr = abs r+        (zerosCount, preDigits) =+            getDigits 0 $ absr / (10 ^^ dexpBound)+        getDigits prevZeros rr+            | digit == 0 = (zerosCount, digit : digits)+            | otherwise = (prevZeros, digit : digits)+            where+            digit :: Integer+            digit = truncate rr+            (zerosCount, digits) =+                getDigits zerosNow ((rr - (fromInteger digit)) * 10)+            zerosNow+                | digit == 0 = prevZeros + 1+                | otherwise = 0+        +instance Eq ExtendedRational where+    NaN == _ = +        False+        -- error "cannot compare NaN"+    _ == NaN = +        False+        -- error "cannot compare NaN"+    (Infinity pm1) == (Infinity pm2) = (pm1 == pm2)+    (Finite r1) == (Finite r2) = r1 == r2+    _ == _ = False++isNaN NaN = True+isNaN _ = False+        +instance Ord ExtendedRational where+    {- compare NaN -}+    compare _ NaN = +        error "comparing NaN - aborting"+    compare NaN _ = +        error "comparing NaN - aborting"+    {- compare infty -}+    compare (Infinity pm1) (Infinity pm2) =+        compare pm1 pm2+    compare _ (Infinity Plus) = LT+    compare _ (Infinity Minus) = GT+    compare (Infinity Plus) _ = GT+    compare (Infinity Minus) _ = LT+    {- compare regular -}+    compare (Finite r1) (Finite r2) = compare r1 r2++instance Num ExtendedRational where+    fromInteger n = Finite (fromInteger n)+    abs NaN = NaN+    abs (Infinity _) = Infinity Plus+    abs r = liftToERational1 abs r+    signum NaN = NaN+    signum (Infinity Plus) = 1+    signum (Infinity Minus) = -1+    signum r = liftToERational1 signum r+    negate NaN = NaN+    negate (Infinity s) = Infinity (signNeg s)+    negate (Finite r) = Finite (negate r)+    {- addition -}+    -- NaN+    NaN + _ = NaN+    _ + NaN = NaN+    -- Infty+    (Infinity Plus) + (Infinity Minus) = NaN+    (Infinity Minus) + (Infinity Plus) = NaN+    (Infinity s) + _ = Infinity s+    _ + (Infinity s) = Infinity s+    -- regular+    r1 + r2 = liftToERational2 (+) r1 r2+    {- multiplication -}+    -- NaN+    NaN * _ = NaN+    _ * NaN = NaN+    -- Infty+    (Infinity _) * (Finite r) | r == 0 = NaN+    (Finite r) * (Infinity _) | r == 0 = NaN+    r * (Infinity s) = Infinity $ signMult s (eratSign r)+    (Infinity s) * r = Infinity $ signMult s (eratSign r)+    -- regular+    r1 * r2 = liftToERational2 (*) r1 r2++instance Fractional ExtendedRational where+    fromRational rat = Finite rat+    recip NaN = NaN+    recip (Infinity s) = 0+    recip (Finite r) +        | r == 0 = Infinity Plus+        | otherwise = (Finite $ recip r)+        +instance Real ExtendedRational where+    toRational (Finite r) = r+    toRational r = error $ "cannot convert " ++  show r ++ " to Rational"+    +instance RealFrac ExtendedRational where+    properFraction (Finite r) = +        (a, Finite b)+        where+        (a,b) = properFraction r+    properFraction r = +        error $ "ExtendedRational: RealFrac: no integral part in " ++ show r+        +instance B.ERRealBase ExtendedRational+    where+    defaultGranularity _ = 10+    getApproxBinaryLog (Finite r)+        | r == 0 =+            EI.MinusInfinity+        | otherwise =+            (intLog 2 (abs $ numerator $ r)) +            -+            (intLog 2 (abs $ denominator $ r))+    getApproxBinaryLog (Infinity _) = EI.PlusInfinity+    getApproxBinaryLog (NaN) = error "RationalBase: getApproxBinaryLog: NaN"+    getGranularity _ = 0+    setMinGranularity _ = id+    setGranularity _ = id+    getMaxRounding _ = 0+    isERNaN = isNaN+    erNaN = NaN+    isPlusInfinity (Infinity Plus) = True+    isPlusInfinity _ = False+    plusInfinity = Infinity Plus+    fromDouble = fromRational . toRational+    toDouble (Infinity Plus) = 1/0 +    toDouble (Infinity Minus) = -1/0 +    toDouble (NaN) = 0/0+    toDouble (Finite r) = fromRational r+    fromFloat = fromRational . toRational+    toFloat (Infinity Plus) = 1/0 +    toFloat (Infinity Minus) = -1/0 +    toFloat (NaN) = 0/0+    toFloat (Finite r) = fromRational r+    showDiGrCmp = showERational++++        
+ src/Data/Number/ER/Real/DefaultRepr.hs view
@@ -0,0 +1,78 @@+{-|+    Module      :  Data.Number.ER.Real.DefaultRepr+    Description :  concise names for default real representations+    Copyright   :  (c) Michal Konecny+    License     :  LGPL++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  non-portable (requires fenv.h)++    This module supplies default instances for the real number classes+    defined in "Data.Number.ER.Real.Approx".+    +    These classes express loosely coupled abstraction layers.    +    To preserve the intended loose coupling, +    please use these definitions only in functions that do not import or export+    any real numbers or real functions.+-}+module Data.Number.ER.Real.DefaultRepr+(+    initMachineDouble,+    B, BM, BAP, BMAP, BR, +    RA, IRA+)+where++--import ++import Data.Number.ER.Real.Base.Float+import Data.Number.ER.Real.Base.Rational++import Data.Number.ER.Real.Approx.Interval++--import Data.Number.ER.Real.Base.BigFloatBase+import Data.Number.ER.Real.Base.MachineDouble+import Data.Number.ER.Real.Base.CombinedMachineAP++type BAP = ERFloat++{-| +        Limited granularity, but sometimes up to 100x faster+        than ERFloat!+        +        !!! to be safe, one has to run 'initMachineDouble'+-}+type BM = Double++{-|+        Use machine 'Double' while the granularity is up to its significant bit length+        and when the granularity grows beyond that, use 'ERFloat'.+        +        !!! to be safe, one has to run 'initMachineDouble'+-}+type BMAP = ERMachineAP BAP+ +--type BBF = BigFloat Prec50 -- seems incomplete on 25/Jun/2008 ++{-| very inefficient -}+type BR = ExtendedRational ++{-| +    the default base type+-}+--type B = BAP+--type B = BM+type B = BMAP+--type B = BR++{-| +    the default instance of 'Data.Number.ER.Real.Approx.ERApprox' +-}+type RA = ERInterval B++{-| +    the default instance of 'Data.Number.ER.Real.Approx.ERIntApprox' +-}+type IRA = ERInterval B+