{-# LANGUAGE RebindableSyntax #-}
module Number.ResidueClass.Func where

import qualified Number.ResidueClass as Res

import qualified Algebra.PrincipalIdealDomain as PID
import qualified Algebra.IntegralDomain   as Integral
import qualified Algebra.Field            as Field
import qualified Algebra.Ring             as Ring
import qualified Algebra.Additive         as Additive
import qualified Algebra.EqualityDecision as EqDec

import Algebra.EqualityDecision ((==?), )

import qualified MathObj.Wrapper.Haskell98 as W98

import NumericPrelude.Base
import NumericPrelude.Numeric hiding (zero, one, )

import qualified Prelude        as P
import qualified NumericPrelude.Numeric as NP

{- |
Here a residue class is a representative
and the modulus is an argument.
You cannot show a value of type 'T',
you can only show it with respect to a concrete modulus.
Values cannot be compared,
because the comparison result depends on the modulus.
-}
newtype T a = Cons (a -> a)

concrete :: a -> T a -> a
concrete :: a -> T a -> a
concrete a
m (Cons a -> a
r) = a -> a
r a
m

fromRepresentative :: (Integral.C a) => a -> T a
fromRepresentative :: a -> T a
fromRepresentative = (a -> a) -> T a
forall a. (a -> a) -> T a
Cons ((a -> a) -> T a) -> (a -> a -> a) -> a -> T a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a -> a
forall a. C a => a -> a -> a
mod

lift0 :: (a -> a) -> T a
lift0 :: (a -> a) -> T a
lift0 = (a -> a) -> T a
forall a. (a -> a) -> T a
Cons

lift1 :: (a -> a -> a) -> T a -> T a
lift1 :: (a -> a -> a) -> T a -> T a
lift1 a -> a -> a
f (Cons a -> a
x) = (a -> a) -> T a
forall a. (a -> a) -> T a
Cons ((a -> a) -> T a) -> (a -> a) -> T a
forall a b. (a -> b) -> a -> b
$ \a
m -> a -> a -> a
f a
m (a -> a
x a
m)

lift2 :: (a -> a -> a -> a) -> T a -> T a -> T a
lift2 :: (a -> a -> a -> a) -> T a -> T a -> T a
lift2 a -> a -> a -> a
f (Cons a -> a
x) (Cons a -> a
y) = (a -> a) -> T a
forall a. (a -> a) -> T a
Cons ((a -> a) -> T a) -> (a -> a) -> T a
forall a b. (a -> b) -> a -> b
$ \a
m -> a -> a -> a -> a
f a
m (a -> a
x a
m) (a -> a
y a
m)


zero :: (Additive.C a) => T a
zero :: T a
zero = (a -> a) -> T a
forall a. (a -> a) -> T a
Cons ((a -> a) -> T a) -> (a -> a) -> T a
forall a b. (a -> b) -> a -> b
$ a -> a -> a
forall a b. a -> b -> a
const a
forall a. C a => a
Additive.zero

one :: (Ring.C a) => T a
one :: T a
one  = (a -> a) -> T a
forall a. (a -> a) -> T a
Cons ((a -> a) -> T a) -> (a -> a) -> T a
forall a b. (a -> b) -> a -> b
$ a -> a -> a
forall a b. a -> b -> a
const a
forall a. C a => a
NP.one

fromInteger :: (Integral.C a) => Integer -> T a
fromInteger :: Integer -> T a
fromInteger = a -> T a
forall a. C a => a -> T a
fromRepresentative (a -> T a) -> (Integer -> a) -> Integer -> T a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> a
forall a. C a => Integer -> a
NP.fromInteger

equal :: Eq a => a -> T a -> T a -> Bool
equal :: a -> T a -> T a -> Bool
equal a
m (Cons a -> a
x) (Cons a -> a
y)  =  a -> a
x a
m a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a -> a
y a
m


instance  (EqDec.C a) => EqDec.C (T a)  where
    ==? :: T a -> T a -> T a -> T a -> T a
(==?) (Cons a -> a
x) (Cons a -> a
y) (Cons a -> a
eq) (Cons a -> a
noteq) =
       (a -> a) -> T a
forall a. (a -> a) -> T a
Cons (\a
m -> (a -> a
x a
m a -> a -> a -> a -> a
forall a. C a => a -> a -> a -> a -> a
==? a -> a
y a
m) (a -> a
eq a
m) (a -> a
noteq a
m))

instance  (Integral.C a) => Additive.C (T a)  where
    zero :: T a
zero                =  T a
forall a. C a => T a
zero
    + :: T a -> T a -> T a
(+)                 =  (a -> a -> a -> a) -> T a -> T a -> T a
forall a. (a -> a -> a -> a) -> T a -> T a -> T a
lift2 a -> a -> a -> a
forall a. C a => a -> a -> a -> a
Res.add
    (-)                 =  (a -> a -> a -> a) -> T a -> T a -> T a
forall a. (a -> a -> a -> a) -> T a -> T a -> T a
lift2 a -> a -> a -> a
forall a. C a => a -> a -> a -> a
Res.sub
    negate :: T a -> T a
negate              =  (a -> a -> a) -> T a -> T a
forall a. (a -> a -> a) -> T a -> T a
lift1 a -> a -> a
forall a. C a => a -> a -> a
Res.neg

instance  (Integral.C a) => Ring.C (T a)  where
    one :: T a
one                 =  T a
forall a. C a => T a
one
    * :: T a -> T a -> T a
(*)                 =  (a -> a -> a -> a) -> T a -> T a -> T a
forall a. (a -> a -> a -> a) -> T a -> T a -> T a
lift2 a -> a -> a -> a
forall a. C a => a -> a -> a -> a
Res.mul
    fromInteger :: Integer -> T a
fromInteger         =  Integer -> T a
forall a. C a => Integer -> T a
Number.ResidueClass.Func.fromInteger

instance  (PID.C a) => Field.C (T a)  where
    / :: T a -> T a -> T a
(/)                 =  (a -> a -> a -> a) -> T a -> T a -> T a
forall a. (a -> a -> a -> a) -> T a -> T a -> T a
lift2 a -> a -> a -> a
forall a. C a => a -> a -> a -> a
Res.divide
    recip :: T a -> T a
recip               =  (T a
forall a. C a => a
NP.one T a -> T a -> T a
forall a. C a => a -> a -> a
/)
    fromRational' :: Rational -> T a
fromRational'       =  [Char] -> Rational -> T a
forall a. HasCallStack => [Char] -> a
error [Char]
"no conversion from rational to residue class"


{-
NumericPrelude.fromInteger seems to be not available at GHCi's prompt sometimes.
But Prelude.fromInteger requires Prelude.Num instance.
-}

{-# INLINE notImplemented #-}
notImplemented :: String -> a
notImplemented :: [Char] -> a
notImplemented [Char]
name =
   [Char] -> a
forall a. HasCallStack => [Char] -> a
error ([Char] -> a) -> [Char] -> a
forall a b. (a -> b) -> a -> b
$ [Char]
"ResidueClass.Func: method " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
name [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" cannot be implemented"


lift98_1 :: (W98.T a -> W98.T a -> W98.T a) -> T a -> T a
lift98_1 :: (T a -> T a -> T a) -> T a -> T a
lift98_1 T a -> T a -> T a
f (Cons a -> a
x) =
   (a -> a) -> T a
forall a. (a -> a) -> T a
Cons ((a -> a) -> T a) -> (a -> a) -> T a
forall a b. (a -> b) -> a -> b
$ \a
m -> T a -> a
forall a. T a -> a
W98.decons (T a -> a) -> T a -> a
forall a b. (a -> b) -> a -> b
$ T a -> T a -> T a
f (a -> T a
forall a. a -> T a
W98.Cons a
m) (a -> T a
forall a. a -> T a
W98.Cons (a -> T a) -> a -> T a
forall a b. (a -> b) -> a -> b
$ a -> a
x a
m)

lift98_2 :: (W98.T a -> W98.T a -> W98.T a -> W98.T a) -> T a -> T a -> T a
lift98_2 :: (T a -> T a -> T a -> T a) -> T a -> T a -> T a
lift98_2 T a -> T a -> T a -> T a
f (Cons a -> a
x) (Cons a -> a
y) =
   (a -> a) -> T a
forall a. (a -> a) -> T a
Cons ((a -> a) -> T a) -> (a -> a) -> T a
forall a b. (a -> b) -> a -> b
$ \a
m -> T a -> a
forall a. T a -> a
W98.decons (T a -> a) -> T a -> a
forall a b. (a -> b) -> a -> b
$ T a -> T a -> T a -> T a
f (a -> T a
forall a. a -> T a
W98.Cons a
m) (a -> T a
forall a. a -> T a
W98.Cons (a -> T a) -> a -> T a
forall a b. (a -> b) -> a -> b
$ a -> a
x a
m) (a -> T a
forall a. a -> T a
W98.Cons (a -> T a) -> a -> T a
forall a b. (a -> b) -> a -> b
$ a -> a
y a
m)


-- legacy instances for use of numeric literals in GHCi
instance (P.Integral a) => P.Num (T a) where
   fromInteger :: Integer -> T a
fromInteger = (a -> a) -> T a
forall a. (a -> a) -> T a
Cons ((a -> a) -> T a) -> (Integer -> a -> a) -> Integer -> T a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a -> a
forall a. Integral a => a -> a -> a
P.mod (a -> a -> a) -> (Integer -> a) -> Integer -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> a
forall a. Num a => Integer -> a
P.fromInteger
   negate :: T a -> T a
negate = (T a -> T a -> T a) -> T a -> T a
forall a. (T a -> T a -> T a) -> T a -> T a
lift98_1 T a -> T a -> T a
forall a. C a => a -> a -> a
Res.neg
   + :: T a -> T a -> T a
(+)    = (T a -> T a -> T a -> T a) -> T a -> T a -> T a
forall a. (T a -> T a -> T a -> T a) -> T a -> T a -> T a
lift98_2 T a -> T a -> T a -> T a
forall a. C a => a -> a -> a -> a
Res.add
   * :: T a -> T a -> T a
(*)    = (T a -> T a -> T a -> T a) -> T a -> T a -> T a
forall a. (T a -> T a -> T a -> T a) -> T a -> T a -> T a
lift98_2 T a -> T a -> T a -> T a
forall a. C a => a -> a -> a -> a
Res.mul
   abs :: T a -> T a
abs    = [Char] -> T a -> T a
forall a. [Char] -> a
notImplemented [Char]
"abs"
   signum :: T a -> T a
signum = [Char] -> T a -> T a
forall a. [Char] -> a
notImplemented [Char]
"signum"

instance Eq (T a) where
   == :: T a -> T a -> Bool
(==) = [Char] -> T a -> T a -> Bool
forall a. [Char] -> a
notImplemented [Char]
"(==)"

instance Show (T a) where
   show :: T a -> [Char]
show = [Char] -> T a -> [Char]
forall a. [Char] -> a
notImplemented [Char]
"show"