4 | isInf : (FromDouble a, Eq a, Fractional a) => a -> Bool
8 | negInf : (Neg a, Fractional a) => a
11 | %foreign "C:c_log1p,log-domain"
12 | c_log1p : Double -> Double
14 | %foreign "C:c_expm1,log-domain"
15 | c_expm1 : Double -> Double
17 | log1pexp : Double -> Double
18 | log1pexp a = c_log1p (exp a)
20 | log1mexp : Double -> Double
21 | log1mexp a = c_log1p (negate (exp a))
25 | record Log (a : Type) where
30 | Show (Log Double) where
31 | show (Exp a) = show (exp a)
35 | map f (Exp a) = Exp (f a)
38 | Num (Log Double) where
39 | fromInteger = Exp . log . fromInteger
40 | Exp a * Exp b = Exp (a + b)
42 | if a == b && isInf a && isInf b then Exp a else
43 | if a >= b then Exp (a + log1pexp (b - a)) else
44 | Exp (b + log1pexp (a - b))
47 | Abs (Log Double) where
51 | Neg (Log Double) where
52 | negate (Exp a) = if isInf a && a < 0 then Exp negInf else Exp (0/0)
53 | Exp a - Exp b = if isInf a && isInf b && a < 0 && b < 0 then Exp negInf else Exp (a + log1mexp (b - a))
56 | Fractional (Log Double) where
57 | Exp a / Exp b = Exp (a - b)
62 | Eq a => Eq (Log a) where
63 | Exp a == Exp b = a == b
66 | Ord a => Ord (Log a) where
67 | Exp a < Exp b = a < b
71 | interface ToLogDomain a where
72 | toLogDomain : a -> Log Double
75 | ToLogDomain Double where
76 | toLogDomain = Exp . log
79 | ToLogDomain Nat where
80 | toLogDomain = Exp . log . cast
83 | ToLogDomain Int where
84 | toLogDomain = Exp . log . cast
87 | ToLogDomain Integer where
88 | toLogDomain = Exp . log . cast
92 | fromLogDomain : Log Double -> Double
93 | fromLogDomain = exp . ln
96 | data Acc a = MkAcc Int64 a | None
99 | sum : (Foldable f) => f (Log Double) -> Log Double
100 | sum xs = Exp $
case foldl step1 None xs of
104 | else a + c_log1p (foldl (step2 a) 0 xs + cast nm1)
106 | step1 : Acc Double -> Log Double -> Acc Double
107 | step1 None (Exp x) = MkAcc 0 x
108 | step1 (MkAcc n y) (Exp x) = MkAcc (n + 1) (max x y)
109 | step2 : Double -> Double -> Log Double -> Double
110 | step2 a r (Exp x) = r + c_expm1 (x - a)