content: {-# LANGUAGE MultiParamTypeClasses #-}
  module Numeric.Log 
    ( Log(..)
    ) where
  
  import Data.Function (on)
  import Numeric.Algebra
  
  import Prelude hiding ((*),(^),(/),recip,negate,subtract)
  
  newtype Log r = Log { runLog :: r } 
  
  instance Multiplicative r => Additive (Log r) where
    Log a + Log b = Log (a * b)
    sumWith1 f = Log . productWith1 (runLog . f)
    sinnum1p n (Log m) = Log (pow1p m n)
  
  instance Unital r => LeftModule Natural (Log r) where
    n .* Log m = Log (pow m n)
  
  instance Unital r => RightModule Natural (Log r) where
    Log m *. n = Log (pow m n)
  
  instance Unital r => Monoidal (Log r) where
    zero = Log one
    sinnum n (Log m) = Log (pow m n)
    sumWith f = Log . productWith (runLog . f)
  
  instance Division r => LeftModule Integer (Log r) where
    n .* Log m = Log (m ^ n)
  
  instance Division r => RightModule Integer (Log r) where
    Log m *. n = Log (m ^ n)
  
  instance Division r => Group (Log r) where
    Log a - Log b = Log (a / b)
    negate (Log a) = Log (recip a)
    subtract (Log a) (Log b) = Log (a \\ b)
    times n (Log m) = Log (m ^ n)
  
  instance Commutative r => Abelian (Log r)
  
  instance Band r => Idempotent (Log r)
  
  instance Factorable r => Partitionable (Log r) where
    partitionWith f = factorWith (f `on` Log) . runLog
  