-- |-- Module: Math.NumberTheory.ArithmeticFunctions.Class-- Copyright: (c) 2016 Andrew Lelechenko-- Licence: MIT-- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>---- Generic type for arithmetic functions over arbitrary unique-- factorisation domains.--{-# LANGUAGE GADTs #-}moduleMath.NumberTheory.ArithmeticFunctions.Class(ArithmeticFunction (..),runFunction ,runFunctionOnFactors )whereimportControl.ApplicativeimportPreludehiding(Applicative(..))importMath.NumberTheory.Primes -- | A typical arithmetic function operates on the canonical factorisation of-- a number into prime's powers and consists of two rules. The first one-- determines the values of the function on the powers of primes. The second-- one determines how to combine these values into final result.---- In the following definition the first argument is the function on prime's-- powers, the monoid instance determines a rule of combination (typically-- 'Data.Semigroup.Product' or 'Data.Semigroup.Sum'), and the second argument is convenient for unwrapping-- (typically, 'Data.Semigroup.getProduct' or 'Data.Semigroup.getSum').dataArithmeticFunction n a whereArithmeticFunction ::Monoidm =>(Prime n ->Word->m )->(m ->a )->ArithmeticFunction n a -- | Convert to a function. The value on 0 is undefined.runFunction ::UniqueFactorisation n =>ArithmeticFunction n a ->n ->a runFunction :: forall n a. UniqueFactorisation n => ArithmeticFunction n a -> n -> a runFunction ArithmeticFunction n a f =ArithmeticFunction n a -> [(Prime n, Word)] -> a forall n a. ArithmeticFunction n a -> [(Prime n, Word)] -> a runFunctionOnFactors ArithmeticFunction n a f ([(Prime n, Word)] -> a) -> (n -> [(Prime n, Word)]) -> n -> a forall b c a. (b -> c) -> (a -> b) -> a -> c .n -> [(Prime n, Word)] forall a. UniqueFactorisation a => a -> [(Prime a, Word)] factorise -- | Convert to a function on prime factorisation.runFunctionOnFactors ::ArithmeticFunction n a ->[(Prime n ,Word)]->a runFunctionOnFactors :: forall n a. ArithmeticFunction n a -> [(Prime n, Word)] -> a runFunctionOnFactors (ArithmeticFunction Prime n -> Word -> m f m -> a g )=m -> a g (m -> a) -> ([(Prime n, Word)] -> m) -> [(Prime n, Word)] -> a forall b c a. (b -> c) -> (a -> b) -> a -> c .[m] -> m forall a. Monoid a => [a] -> a mconcat([m] -> m) -> ([(Prime n, Word)] -> [m]) -> [(Prime n, Word)] -> m forall b c a. (b -> c) -> (a -> b) -> a -> c .((Prime n, Word) -> m) -> [(Prime n, Word)] -> [m] forall a b. (a -> b) -> [a] -> [b] map((Prime n -> Word -> m) -> (Prime n, Word) -> m forall a b c. (a -> b -> c) -> (a, b) -> c uncurryPrime n -> Word -> m f )instanceFunctor(ArithmeticFunction n )wherefmap :: forall a b. (a -> b) -> ArithmeticFunction n a -> ArithmeticFunction n b fmapa -> b f (ArithmeticFunction Prime n -> Word -> m g m -> a h )=(Prime n -> Word -> m) -> (m -> b) -> ArithmeticFunction n b forall m n a. Monoid m => (Prime n -> Word -> m) -> (m -> a) -> ArithmeticFunction n a ArithmeticFunction Prime n -> Word -> m g (a -> b f (a -> b) -> (m -> a) -> m -> b forall b c a. (b -> c) -> (a -> b) -> a -> c .m -> a h )instanceApplicative(ArithmeticFunction n )wherepure :: forall a. a -> ArithmeticFunction n a purea x =(Prime n -> Word -> ()) -> (() -> a) -> ArithmeticFunction n a forall m n a. Monoid m => (Prime n -> Word -> m) -> (m -> a) -> ArithmeticFunction n a ArithmeticFunction (\Prime n _Word _->())(a -> () -> a forall a b. a -> b -> a consta x )(ArithmeticFunction Prime n -> Word -> m f1 m -> a -> b g1 )<*> :: forall a b. ArithmeticFunction n (a -> b) -> ArithmeticFunction n a -> ArithmeticFunction n b <*>(ArithmeticFunction Prime n -> Word -> m f2 m -> a g2 )=(Prime n -> Word -> (m, m)) -> ((m, m) -> b) -> ArithmeticFunction n b forall m n a. Monoid m => (Prime n -> Word -> m) -> (m -> a) -> ArithmeticFunction n a ArithmeticFunction (\Prime n p Word k ->(Prime n -> Word -> m f1 Prime n p Word k ,Prime n -> Word -> m f2 Prime n p Word k ))(\(m a1 ,m a2 )->m -> a -> b g1 m a1 (m -> a g2 m a2 ))instanceSemigroupa =>Semigroup(ArithmeticFunction n a )where<> :: ArithmeticFunction n a -> ArithmeticFunction n a -> ArithmeticFunction n a (<>)=(a -> a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b c. (a -> b -> c) -> ArithmeticFunction n a -> ArithmeticFunction n b -> ArithmeticFunction n c forall (f :: * -> *) a b c. Applicative f => (a -> b -> c) -> f a -> f b -> f c liftA2a -> a -> a forall a. Semigroup a => a -> a -> a (<>)instanceMonoida =>Monoid(ArithmeticFunction n a )wheremempty :: ArithmeticFunction n a mempty=a -> ArithmeticFunction n a forall a. a -> ArithmeticFunction n a forall (f :: * -> *) a. Applicative f => a -> f a purea forall a. Monoid a => a mempty-- | Factorisation is expensive, so it is better to avoid doing it twice.-- Write 'runFunction (f + g) n' instead of 'runFunction f n + runFunction g n'.instanceNuma =>Num(ArithmeticFunction n a )wherefromInteger :: Integer -> ArithmeticFunction n a fromInteger=a -> ArithmeticFunction n a forall a. a -> ArithmeticFunction n a forall (f :: * -> *) a. Applicative f => a -> f a pure(a -> ArithmeticFunction n a) -> (Integer -> a) -> Integer -> ArithmeticFunction n a forall b c a. (b -> c) -> (a -> b) -> a -> c .Integer -> a forall a. Num a => Integer -> a fromIntegernegate :: ArithmeticFunction n a -> ArithmeticFunction n a negate=(a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b. (a -> b) -> ArithmeticFunction n a -> ArithmeticFunction n b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapa -> a forall a. Num a => a -> a negatesignum :: ArithmeticFunction n a -> ArithmeticFunction n a signum =(a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b. (a -> b) -> ArithmeticFunction n a -> ArithmeticFunction n b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapa -> a forall a. Num a => a -> a signumabs :: ArithmeticFunction n a -> ArithmeticFunction n a abs =(a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b. (a -> b) -> ArithmeticFunction n a -> ArithmeticFunction n b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapa -> a forall a. Num a => a -> a abs+ :: ArithmeticFunction n a -> ArithmeticFunction n a -> ArithmeticFunction n a (+) =(a -> a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b c. (a -> b -> c) -> ArithmeticFunction n a -> ArithmeticFunction n b -> ArithmeticFunction n c forall (f :: * -> *) a b c. Applicative f => (a -> b -> c) -> f a -> f b -> f c liftA2a -> a -> a forall a. Num a => a -> a -> a (+)(-)=(a -> a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b c. (a -> b -> c) -> ArithmeticFunction n a -> ArithmeticFunction n b -> ArithmeticFunction n c forall (f :: * -> *) a b c. Applicative f => (a -> b -> c) -> f a -> f b -> f c liftA2(-)* :: ArithmeticFunction n a -> ArithmeticFunction n a -> ArithmeticFunction n a (*) =(a -> a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b c. (a -> b -> c) -> ArithmeticFunction n a -> ArithmeticFunction n b -> ArithmeticFunction n c forall (f :: * -> *) a b c. Applicative f => (a -> b -> c) -> f a -> f b -> f c liftA2a -> a -> a forall a. Num a => a -> a -> a (*)instanceFractionala =>Fractional(ArithmeticFunction n a )wherefromRational :: Rational -> ArithmeticFunction n a fromRational=a -> ArithmeticFunction n a forall a. a -> ArithmeticFunction n a forall (f :: * -> *) a. Applicative f => a -> f a pure(a -> ArithmeticFunction n a) -> (Rational -> a) -> Rational -> ArithmeticFunction n a forall b c a. (b -> c) -> (a -> b) -> a -> c .Rational -> a forall a. Fractional a => Rational -> a fromRationalrecip :: ArithmeticFunction n a -> ArithmeticFunction n a recip =(a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b. (a -> b) -> ArithmeticFunction n a -> ArithmeticFunction n b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapa -> a forall a. Fractional a => a -> a recip/ :: ArithmeticFunction n a -> ArithmeticFunction n a -> ArithmeticFunction n a (/) =(a -> a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b c. (a -> b -> c) -> ArithmeticFunction n a -> ArithmeticFunction n b -> ArithmeticFunction n c forall (f :: * -> *) a b c. Applicative f => (a -> b -> c) -> f a -> f b -> f c liftA2a -> a -> a forall a. Fractional a => a -> a -> a (/)instanceFloatinga =>Floating(ArithmeticFunction n a )wherepi :: ArithmeticFunction n a pi =a -> ArithmeticFunction n a forall a. a -> ArithmeticFunction n a forall (f :: * -> *) a. Applicative f => a -> f a purea forall a. Floating a => a piexp :: ArithmeticFunction n a -> ArithmeticFunction n a exp =(a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b. (a -> b) -> ArithmeticFunction n a -> ArithmeticFunction n b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapa -> a forall a. Floating a => a -> a explog :: ArithmeticFunction n a -> ArithmeticFunction n a log =(a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b. (a -> b) -> ArithmeticFunction n a -> ArithmeticFunction n b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapa -> a forall a. Floating a => a -> a logsin :: ArithmeticFunction n a -> ArithmeticFunction n a sin =(a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b. (a -> b) -> ArithmeticFunction n a -> ArithmeticFunction n b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapa -> a forall a. Floating a => a -> a sincos :: ArithmeticFunction n a -> ArithmeticFunction n a cos =(a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b. (a -> b) -> ArithmeticFunction n a -> ArithmeticFunction n b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapa -> a forall a. Floating a => a -> a cosasin :: ArithmeticFunction n a -> ArithmeticFunction n a asin =(a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b. (a -> b) -> ArithmeticFunction n a -> ArithmeticFunction n b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapa -> a forall a. Floating a => a -> a asinacos :: ArithmeticFunction n a -> ArithmeticFunction n a acos =(a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b. (a -> b) -> ArithmeticFunction n a -> ArithmeticFunction n b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapa -> a forall a. Floating a => a -> a acosatan :: ArithmeticFunction n a -> ArithmeticFunction n a atan =(a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b. (a -> b) -> ArithmeticFunction n a -> ArithmeticFunction n b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapa -> a forall a. Floating a => a -> a atansinh :: ArithmeticFunction n a -> ArithmeticFunction n a sinh =(a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b. (a -> b) -> ArithmeticFunction n a -> ArithmeticFunction n b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapa -> a forall a. Floating a => a -> a sinhcosh :: ArithmeticFunction n a -> ArithmeticFunction n a cosh =(a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b. (a -> b) -> ArithmeticFunction n a -> ArithmeticFunction n b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapa -> a forall a. Floating a => a -> a coshasinh :: ArithmeticFunction n a -> ArithmeticFunction n a asinh =(a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b. (a -> b) -> ArithmeticFunction n a -> ArithmeticFunction n b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapa -> a forall a. Floating a => a -> a asinhacosh :: ArithmeticFunction n a -> ArithmeticFunction n a acosh =(a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b. (a -> b) -> ArithmeticFunction n a -> ArithmeticFunction n b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapa -> a forall a. Floating a => a -> a acoshatanh :: ArithmeticFunction n a -> ArithmeticFunction n a atanh =(a -> a) -> ArithmeticFunction n a -> ArithmeticFunction n a forall a b. (a -> b) -> ArithmeticFunction n a -> ArithmeticFunction n b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapa -> a forall a. Floating a => a -> a atanh