{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE PartialTypeSignatures #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Crypto.Lol.Cyclotomic.Cyc
(
Cyc
, UnCyc(..)
) where
import qualified Algebra.Additive as Additive (C)
import qualified Algebra.Module as Module (C)
import qualified Algebra.Ring as Ring (C)
import qualified Algebra.ZeroTestable as ZeroTestable (C)
import Crypto.Lol.CRTrans
import Crypto.Lol.Cyclotomic.CycRep hiding (coeffsDec,
coeffsPow, crtSet,
powBasis)
import qualified Crypto.Lol.Cyclotomic.CycRep as R
import Crypto.Lol.Cyclotomic.Language hiding (Dec, Pow)
import qualified Crypto.Lol.Cyclotomic.Language as L
import Crypto.Lol.Cyclotomic.Tensor (TensorCRT, TensorCRTSet,
TensorGSqNorm,
TensorGaussian,
TensorPowDec)
import Crypto.Lol.Gadget
import Crypto.Lol.Prelude as LP
import Crypto.Lol.Reflects
import Crypto.Lol.Types (RRq, ZqBasic)
import Crypto.Lol.Types.FiniteField
import Crypto.Lol.Types.IFunctor
import Crypto.Lol.Types.Proto
import Control.Applicative hiding ((*>))
import Control.Arrow
import Control.DeepSeq
import Control.Monad.Random hiding (lift)
import Data.Constraint ((\\))
import Data.Foldable (Foldable)
import Data.Traversable
import Language.Haskell.TH
data CycG t m r where
Pow :: !(CycRep t P m r) -> CycG t m r
Dec :: !(CycRep t D m r) -> CycG t m r
CRT :: !(CycRepEC t m r) -> CycG t m r
Scalar :: !r -> CycG t m r
Sub :: (l `Divides` m) => !(CycG t l r) -> CycG t m r
data family Cyc (t :: Factored -> * -> *) (m :: Factored) r
type instance LiftOf (CycG t m r) = CycG t m (LiftOf r)
type instance LiftOf (Cyc t m r) = Cyc t m (LiftOf r)
newtype instance Cyc t m Double = CycDbl { unCycDbl :: CycG t m Double }
newtype instance Cyc t m Int64 = CycI64 { unCycI64 :: CycG t m Int64 }
newtype instance Cyc t m (ZqBasic q z) = CycZqB { unCycZqB :: CycG t m (ZqBasic q z) }
data instance Cyc t m (a,b) = CycPair !(Cyc t m a) !(Cyc t m b)
data instance Cyc t m Integer
= PowIgr !(CycRep t P m Integer)
| DecIgr !(CycRep t D m Integer)
data instance Cyc t m (RRq q r)
= PowRRq !(CycRep t P m (RRq q r))
| DecRRq !(CycRep t D m (RRq q r))
cycPC :: Either (CycRep t P m r) (CycRep t C m r) -> CycG t m r
cycPC = either Pow (CRT . Right)
{-# INLINABLE cycPC #-}
cycPE :: Either (CycRep t P m r) (CycRep t E m r) -> CycG t m r
cycPE = either Pow (CRT . Left)
{-# INLINABLE cycPE #-}
unCycGPow :: (Fact m, CRTElt t r) => CycG t m r -> CycRep t P m r
{-# INLINABLE unCycGPow #-}
unCycGPow c = let (Pow u) = toPow' c in u
unCycGDec :: (Fact m, CRTElt t r) => CycG t m r -> CycRep t D m r
{-# INLINABLE unCycGDec #-}
unCycGDec c = let (Dec u) = toDec' c in u
class UnCyc t r where
cycPow :: (Fact m) => CycRep t P m r -> Cyc t m r
cycDec :: (Fact m) => CycRep t D m r -> Cyc t m r
unCycPow :: (Fact m) => Cyc t m r -> CycRep t P m r
unCycDec :: (Fact m) => Cyc t m r -> CycRep t D m r
instance CRTElt t Double => UnCyc t Double where
cycPow = CycDbl . Pow
cycDec = CycDbl . Dec
unCycPow = unCycGPow . unCycDbl
unCycDec = unCycGDec . unCycDbl
instance CRTElt t Int64 => UnCyc t Int64 where
cycPow = CycI64 . Pow
cycDec = CycI64 . Dec
unCycPow = unCycGPow . unCycI64
unCycDec = unCycGDec . unCycI64
instance CRTElt t (ZqBasic q z) => UnCyc t (ZqBasic q z) where
cycPow = CycZqB . Pow
cycDec = CycZqB . Dec
unCycPow = unCycGPow . unCycZqB
unCycDec = unCycGDec . unCycZqB
instance TensorPowDec t (RRq q r) => UnCyc t (RRq q r) where
cycPow = PowRRq
cycDec = DecRRq
unCycPow (PowRRq v) = v
unCycPow (DecRRq v) = toPow v
unCycDec (DecRRq v) = v
unCycDec (PowRRq v) = toDec v
instance (UnCyc t a, UnCyc t b, IFunctor t, IFElt t a, IFElt t b, IFElt t (a,b))
=> UnCyc t (a,b) where
cycPow = uncurry CycPair . ((cycPow . fmapI fst) &&& (cycPow . fmapI snd))
cycDec = uncurry CycPair . ((cycDec . fmapI fst) &&& (cycDec . fmapI snd))
unCycPow (CycPair a b) = zipWithI (,) (unCycPow a) (unCycPow b)
unCycDec (CycPair a b) = zipWithI (,) (unCycDec a) (unCycDec b)
instance (Fact m, CRTElt t r, Foldable (t m))
=> FoldableCyc (CycG t m) r where
foldrCyc (Just L.Pow) f acc (Pow u) = foldr f acc u
foldrCyc (Just L.Dec) f acc (Dec u) = foldr f acc u
foldrCyc Nothing f acc (Pow u) = foldr f acc u
foldrCyc Nothing f acc (Dec u) = foldr f acc u
foldrCyc b@(Just L.Pow) f acc c = foldrCyc b f acc $ toPow' c
foldrCyc b@(Just L.Dec) f acc c = foldrCyc b f acc $ toDec' c
foldrCyc Nothing f acc c = foldrCyc Nothing f acc $ toPow' c
instance (FoldableCyc (CycG t m) Double) => FoldableCyc (Cyc t m) Double where
foldrCyc bas f acc = foldrCyc bas f acc . unCycDbl
instance (FoldableCyc (CycG t m) Int64) => FoldableCyc (Cyc t m) Int64 where
foldrCyc bas f acc = foldrCyc bas f acc . unCycI64
instance (FoldableCyc (CycG t m) (ZqBasic q z))
=> FoldableCyc (Cyc t m) (ZqBasic q z) where
foldrCyc bas f acc = foldrCyc bas f acc . unCycZqB
instance (Foldable (t m)) => FoldableCyc (Cyc t m) Integer where
foldrCyc (Just L.Pow) f acc (PowIgr u) = foldr f acc u
foldrCyc (Just L.Dec) f acc (DecIgr u) = foldr f acc u
foldrCyc Nothing f acc (PowIgr u) = foldr f acc u
foldrCyc Nothing f acc (DecIgr u) = foldr f acc u
foldrCyc _ _ _ _ =
error "Cyc.foldrCyc over Integer: mismatched bases, implementation TODO."
instance (Fact m, TensorPowDec t (RRq q r), Foldable (t m))
=> FoldableCyc (Cyc t m) (RRq q r) where
foldrCyc (Just L.Pow) f acc = foldr f acc . unCycPow
foldrCyc (Just L.Dec) f acc = foldr f acc . unCycDec
foldrCyc Nothing f acc = foldrCyc (Just L.Pow) f acc
instance (Fact m, CRTElt t a, IFunctor t, IFElt t a, IFElt t b)
=> FunctorCyc (CycG t m) a b where
fmapCyc (Just L.Pow) f = Pow . fmapI f . unCycGPow
fmapCyc (Just L.Dec) f = Dec . fmapI f . unCycGDec
fmapCyc Nothing f = fmapCyc (Just L.Pow) f
instance (Functor (t m)) => FunctorCyc (Cyc t m) Integer Integer where
fmapCyc (Just L.Pow) f (PowIgr u) = PowIgr $ fmap f u
fmapCyc (Just L.Dec) f (DecIgr u) = DecIgr $ fmap f u
fmapCyc Nothing f (PowIgr u) = PowIgr $ fmap f u
fmapCyc Nothing f (DecIgr u) = DecIgr $ fmap f u
fmapCyc _ _ _ =
error "Cyc.fmapCyc Integer->Integer: mismatched bases, implementation TODO"
instance (Fact m, ZeroTestable r, CRTElt t r,
forall m' . Fact m' => ZeroTestable.C (t m' r))
=> ZeroTestable.C (CycG t m r) where
isZero x = case x of
(Pow u) -> isZero u
(Dec u) -> isZero u
(CRT (Right u)) -> isZero u
c@(CRT _) -> isZero $ toPow' c
(Scalar c) -> isZero c
(Sub c) -> isZero c
deriving instance ZeroTestable (CycG t m Double) => ZeroTestable.C (Cyc t m Double)
deriving instance ZeroTestable (CycG t m Int64) => ZeroTestable.C (Cyc t m Int64)
deriving instance ZeroTestable (CycG t m (ZqBasic q z)) => ZeroTestable.C (Cyc t m (ZqBasic q z))
instance (ZeroTestable (Cyc t m a), ZeroTestable (Cyc t m b))
=> ZeroTestable.C (Cyc t m (a,b)) where
isZero (CycPair a b) = isZero a && isZero b
instance ZeroTestable (t m Integer) => ZeroTestable.C (Cyc t m Integer) where
isZero (PowIgr v) = isZero v
isZero (DecIgr v) = isZero v
instance ZeroTestable (t m (RRq q r)) => ZeroTestable.C (Cyc t m (RRq q r)) where
isZero (PowRRq c) = isZero c
isZero (DecRRq c) = isZero c
instance (Eq r, Fact m, CRTElt t r,
forall m' . Fact m' => Eq (t m' r)) => Eq (CycG t m r) where
{-# INLINABLE (==) #-}
(Scalar c1) == (Scalar c2) = c1 == c2
(Pow u1) == (Pow u2) = u1 == u2
(Dec u1) == (Dec u2) = u1 == u2
(CRT (Right u1)) == (CRT (Right u2)) = u1 == u2
(Sub (c1 :: CycG t l1 r)) == (Sub (c2 :: CycG t l2 r)) =
(embed' c1 :: CycG t (FLCM l1 l2) r) == embed' c2
\\ lcmDivides @l1 @l2
(Scalar c1) == (Pow u2) = scalarPow c1 == u2
(Pow u1) == (Scalar c2) = u1 == scalarPow c2
c1 == c2 = toPow' c1 == toPow' c2
deriving instance Eq (CycG t m Int64) => Eq (Cyc t m Int64)
deriving instance Eq (CycG t m (ZqBasic q z)) => Eq (Cyc t m (ZqBasic q z))
instance (Eq (Cyc t m a), Eq (Cyc t m b)) => Eq (Cyc t m (a,b)) where
(CycPair a b) == (CycPair a' b') = a == a' && b == b'
instance (Fact m, CRTElt t r, ZeroTestable r) => Additive.C (CycG t m r) where
{-# INLINABLE zero #-}
zero = Scalar zero
{-# INLINABLE (+) #-}
(Scalar c1) + c2 | isZero c1 = c2
c1 + (Scalar c2) | isZero c2 = c1
(Scalar c1) + (Scalar c2) = Scalar (c1+c2)
(Pow u1) + (Pow u2) = Pow $ u1 + u2
(Dec u1) + (Dec u2) = Dec $ u1 + u2
(CRT u1) + (CRT u2) = CRT $ u1 + u2
(Sub (c1 :: CycG t m1 r)) + (Sub (c2 :: CycG t m2 r)) =
Sub ((embed' c1 :: CycG t (FLCM m1 m2) r) + embed' c2)
\\ lcm2Divides @m1 @m2 @m
(Scalar c) + (Pow u) = Pow $ scalarPow c + u
(Scalar c) + (Dec u) = Pow $ scalarPow c + toPow u
(Scalar c) + (CRT u) = CRT $ scalarCRT c + u
(Scalar c1) + (Sub c2) = Sub $ Scalar c1 + c2
(Pow u) + (Scalar c) = Pow $ u + scalarPow c
(Dec u) + (Scalar c) = Pow $ toPow u + scalarPow c
(CRT u) + (Scalar c) = CRT $ u + scalarCRT c
(Sub c1) + (Scalar c2) = Sub $ c1 + Scalar c2
(Sub c1) + c2 = embed' c1 + c2
c1 + (Sub c2) = c1 + embed' c2
(Dec u1) + (Pow u2) = Pow $ toPow u1 + u2
(Pow u1) + (Dec u2) = Pow $ u1 + toPow u2
(CRT u1) + (Pow u2) = CRT $ u1 + toCRT u2
(CRT u1) + (Dec u2) = CRT $ u1 + toCRT u2
(Pow u1) + (CRT u2) = CRT $ toCRT u1 + u2
(Dec u1) + (CRT u2) = CRT $ toCRT u1 + u2
{-# INLINABLE negate #-}
negate (Pow u) = Pow $ negate u
negate (Dec u) = Dec $ negate u
negate (CRT u) = CRT $ negate u
negate (Scalar c) = Scalar (negate c)
negate (Sub c) = Sub $ negate c
deriving instance Additive (CycG t m Double) => Additive.C (Cyc t m Double)
deriving instance Additive (CycG t m Int64) => Additive.C (Cyc t m Int64)
deriving instance Additive (CycG t m (ZqBasic q z)) => Additive.C (Cyc t m (ZqBasic q z))
instance (Additive (Cyc t m a), Additive (Cyc t m b))
=> Additive.C (Cyc t m (a,b)) where
zero = CycPair zero zero
(CycPair a b) + (CycPair a' b') = CycPair (a+a') (b+b')
negate (CycPair a b) = CycPair (negate a) (negate b)
instance (Additive (RRq q r), TensorPowDec t (RRq q r), IFunctor t, Fact m)
=> Additive.C (Cyc t m (RRq q r)) where
zero = PowRRq zero
(PowRRq u1) + (PowRRq u2) = PowRRq $ u1 + u2
(DecRRq u1) + (DecRRq u2) = DecRRq $ u1 + u2
(PowRRq u1) + (DecRRq u2) = PowRRq $ u1 + toPow u2
(DecRRq u1) + (PowRRq u2) = PowRRq $ toPow u1 + u2
negate (PowRRq u) = PowRRq $ negate u
negate (DecRRq u) = DecRRq $ negate u
instance (Fact m, CRTElt t r, ZeroTestable r) => Ring.C (CycG t m r) where
{-# INLINABLE one #-}
one = Scalar one
{-# INLINABLE fromInteger #-}
fromInteger = Scalar . fromInteger
{-# INLINABLE (*) #-}
v1@(Scalar c1) * _ | isZero c1 = v1
_ * v2@(Scalar c2) | isZero c2 = v2
(CRT u1) * (CRT u2) = either (Pow . toPow) (CRT . Right) $ u1*u2
(Scalar c1) * (Scalar c2) = Scalar $ c1*c2
(Scalar c) * (Pow u) = Pow $ c *> u
(Scalar c) * (Dec u) = Dec $ c *> u
(Scalar c) * (CRT u) = CRT $ c *> u
(Scalar c1) * (Sub c2) = Sub $ Scalar c1 * c2
(Pow u) * (Scalar c) = Pow $ c *> u
(Dec u) * (Scalar c) = Dec $ c *> u
(CRT u) * (Scalar c) = CRT $ c *> u
(Sub c1) * (Scalar c2) = Sub $ c1 * Scalar c2
(Sub (c1 :: CycG t m1 r)) * (Sub (c2 :: CycG t m2 r)) =
Sub ((toCRT' $ Sub c1 :: CycG t (FLCM m1 m2) r) * toCRT' (Sub c2))
\\ lcm2Divides @m1 @m2 @m
c1 * c2 = toCRT' c1 * toCRT' c2
deriving instance Ring (CycG t m Double) => Ring.C (Cyc t m Double)
deriving instance Ring (CycG t m Int64) => Ring.C (Cyc t m Int64)
deriving instance Ring (CycG t m (ZqBasic q z)) => Ring.C (Cyc t m (ZqBasic q z))
instance (Ring (Cyc t m a), Ring (Cyc t m b)) => Ring.C (Cyc t m (a,b)) where
one = CycPair one one
fromInteger z = CycPair (fromInteger z) (fromInteger z)
(CycPair a b) * (CycPair a' b') = CycPair (a*a') (b*b')
instance (Fact m, CRTElt t r, ZeroTestable r) => Module.C r (CycG t m r) where
r *> (Scalar c) = Scalar $ r * c
r *> (Pow v) = Pow $ r *> v
r *> (Dec v) = Dec $ r *> v
r *> (Sub c) = Sub $ r *> c
r *> x = r *> toPow' x
deriving instance Module Int64 (CycG t m Int64) => Module.C Int64 (Cyc t m Int64)
deriving instance Module Double (CycG t m Double) => Module.C Double (Cyc t m Double)
deriving instance (Module (ZqBasic q z) (CycG t m (ZqBasic q z)),
Ring (ZqBasic q z))
=> Module.C (ZqBasic q z) (Cyc t m (ZqBasic q z))
instance (Module a (Cyc t m a), Module b (Cyc t m b))
=> Module.C (a,b) (Cyc t m (a,b)) where
(a,b) *> (CycPair ca cb) = CycPair (a *> ca) (b *> cb)
instance (GFCtx fp d, Fact m, CRTElt t fp, Module (GF fp d) (t m fp))
=> Module.C (GF fp d) (CycG t m fp) where
r *> (Pow v) = Pow $ r *> v
r *> x = r *> toPow' x
deriving instance (Ring (GF (ZqBasic q z) d),
Module (GF (ZqBasic q z) d) (CycG t m (ZqBasic q z)))
=> Module.C (GF (ZqBasic q z) d) (Cyc t m (ZqBasic q z))
instance (Fact m, CRTElt t r, ZeroTestable r, IntegralDomain r)
=> Cyclotomic (CycG t m r) where
{-# SPECIALIZE instance (Fact m, CRTElt t Int64) => Cyclotomic (CycG t m Int64) #-}
{-# SPECIALIZE instance (Fact m, CRTElt t Double) => Cyclotomic (CycG t m Double) #-}
{-# SPECIALIZE instance (Fact m, CRTElt t (ZqBasic q Int64), Reflects q Int64) => Cyclotomic (CycG t m (ZqBasic q Int64)) #-}
mulG (Pow u) = Pow $ R.mulGPow u
mulG (Dec u) = Dec $ R.mulGDec u
mulG (CRT (Left u)) = Pow $ R.mulGPow $ toPow u
mulG (CRT (Right u)) = CRT $ Right $ R.mulGCRTC u
mulG c@(Scalar _) = mulG $ toCRT' c
mulG (Sub c) = mulG $ embed' c
divG (Pow u) = Pow <$> R.divGPow u
divG (Dec u) = Dec <$> R.divGDec u
divG (CRT (Left u)) = Pow <$> R.divGPow (toPow u)
divG (CRT (Right u)) = Just $ (CRT . Right) $ R.divGCRTC u
divG c@(Scalar _) = divG $ toCRT' c
divG (Sub c) = divG $ embed' c
advisePow = toPow'
adviseDec = toDec'
adviseCRT = toCRT'
deriving instance Cyclotomic (CycG t m Double) => Cyclotomic (Cyc t m Double)
deriving instance Cyclotomic (CycG t m Int64) => Cyclotomic (Cyc t m Int64)
deriving instance Cyclotomic (CycG t m (ZqBasic q z)) => Cyclotomic (Cyc t m (ZqBasic q z))
instance (Cyclotomic (Cyc t m a), Cyclotomic (Cyc t m b))
=> Cyclotomic (Cyc t m (a,b)) where
{-# SPECIALIZE instance (Fact m, CRTElt t (ZqBasic q Int64), Reflects q Int64, Cyclotomic (Cyc t m b)) => Cyclotomic (Cyc t m (ZqBasic q Int64, b)) #-}
mulG (CycPair a b) = CycPair (mulG a) (mulG b)
divG (CycPair a b) = CycPair <$> divG a <*> divG b
advisePow (CycPair a b) = CycPair (advisePow a) (advisePow b)
adviseDec (CycPair a b) = CycPair (adviseDec a) (adviseDec b)
adviseCRT (CycPair a b) = CycPair (adviseCRT a) (adviseCRT b)
instance (Fact m, TensorGSqNorm t r, CRTElt t r)
=> GSqNormCyc (CycG t m) r where
gSqNorm (Dec c) = gSqNormDec c
gSqNorm c = gSqNorm $ toDec' c
instance (Fact m, TensorGSqNorm t Double, CRTElt t Double)
=> GSqNormCyc (Cyc t m) Double where
gSqNorm = gSqNorm . unCycDbl
instance (Fact m, TensorGSqNorm t Int64, CRTElt t Int64)
=> GSqNormCyc (Cyc t m) Int64 where
gSqNorm = gSqNorm . unCycI64
instance (Fact m, TensorGaussian t Double, FunctorCyc (Cyc t m) Double Int64)
=> RoundedGaussianCyc (Cyc t m Int64) where
roundedGaussian :: forall v rnd . (ToRational v, MonadRandom rnd)
=> v -> rnd (Cyc t m Int64)
{-# INLINABLE roundedGaussian #-}
roundedGaussian svar =
fmapCyc (Just L.Dec) (roundMult one) <$>
(L.tweakedGaussian svar :: rnd (Cyc t m Double))
instance (Lift' r, FunctorCyc (Cyc t m) r (LiftOf r)) => LiftCyc (Cyc t m r) where
{-# SPECIALIZE instance (Fact m, Reflects q Int64, UnCyc t (ZqBasic q Int64), UnCyc t Int64, IFunctor t, IFElt t (ZqBasic q Int64), IFElt t Int64) => LiftCyc (Cyc t m (ZqBasic q Int64)) #-}
{-# INLINABLE liftCyc #-}
liftCyc = flip fmapCyc lift
instance (Fact m, TensorGaussian t q) => GaussianCyc (CycG t m q) where
tweakedGaussian = fmap Dec . R.tweakedGaussian
instance (Fact m, TensorGaussian t Double) => GaussianCyc (Cyc t m Double) where
tweakedGaussian = fmap CycDbl . L.tweakedGaussian
instance (TensorGaussian t Double, IFElt t Double, IFunctor t, Fact m, Mod zp,
Lift zp (ModRep zp), CRTElt t zp, IFElt t (LiftOf zp))
=> CosetGaussianCyc (CycG t m zp) where
{-# INLINABLE cosetGaussian #-}
cosetGaussian v = (Dec <$>) . R.cosetGaussian v . unCycGDec
instance (CosetGaussianCyc (CycG t m (ZqBasic q Int64)))
=> CosetGaussianCyc (Cyc t m (ZqBasic q Int64)) where
cosetGaussian v = fmap CycI64 . L.cosetGaussian v . unCycZqB
instance (CRTElt t r, ZeroTestable r, IntegralDomain r)
=> ExtensionCyc (CycG t) r where
{-# SPECIALIZE instance (CRTElt t Int64) => ExtensionCyc (CycG t) Int64 #-}
{-# SPECIALIZE instance (CRTElt t Double) => ExtensionCyc (CycG t) Double #-}
{-# SPECIALIZE instance (CRTElt t (ZqBasic q Int64), Reflects q Int64) => ExtensionCyc (CycG t) (ZqBasic q Int64) #-}
embed :: forall m m' . (m `Divides` m') => CycG t m r -> CycG t m' r
embed (Scalar c) = Scalar c
embed (Sub (c :: CycG t l r)) = Sub c
\\ transDivides @l @m @m'
embed c = Sub c
twace :: forall m m' . (m `Divides` m') => CycG t m' r -> CycG t m r
twace (Pow u) = Pow $ twacePow u
twace (Dec u) = Dec $ twaceDec u
twace (CRT u) = either (cycPE . twaceCRTE) (cycPC . twaceCRTC) u
twace (Scalar u) = Scalar u
twace (Sub (c :: CycG t l r)) = Sub (twace c :: CycG t (FGCD l m) r)
\\ gcdDivides @l @m
powBasis :: forall m m' . (m `Divides` m') => Tagged m [CycG t m' r]
powBasis = tag $ Pow <$> R.powBasis @m
coeffsCyc L.Pow c' = Pow <$> R.coeffsPow (unCycGPow c')
coeffsCyc L.Dec c' = Dec <$> R.coeffsDec (unCycGDec c')
instance CRTElt t Double => ExtensionCyc (Cyc t) Double where
embed = CycDbl . embed . unCycDbl
twace = CycDbl . twace . unCycDbl
powBasis = (CycDbl <$>) <$> powBasis
coeffsCyc b = fmap CycDbl . coeffsCyc b . unCycDbl
instance CRTElt t Int64 => ExtensionCyc (Cyc t) Int64 where
embed = CycI64 . embed . unCycI64
twace = CycI64 . twace . unCycI64
powBasis = (CycI64 <$>) <$> powBasis
coeffsCyc b = fmap CycI64 . coeffsCyc b . unCycI64
instance (ExtensionCyc (CycG t) (ZqBasic q z))
=> ExtensionCyc (Cyc t) (ZqBasic q z) where
embed = CycZqB . embed . unCycZqB
twace = CycZqB . twace . unCycZqB
powBasis = (CycZqB <$>) <$> powBasis
coeffsCyc b = fmap CycZqB . coeffsCyc b . unCycZqB
instance (ExtensionCyc (Cyc t) a, ExtensionCyc (Cyc t) b)
=> ExtensionCyc (Cyc t) (a,b) where
{-# SPECIALIZE instance (ExtensionCyc (Cyc t) (ZqBasic q Int64), ExtensionCyc (Cyc t) b) => ExtensionCyc (Cyc t) (ZqBasic q Int64, b) #-}
embed (CycPair a b) = CycPair (embed a) (embed b)
twace (CycPair a b) = CycPair (twace a) (twace b)
powBasis = zipWith CycPair <$> powBasis <*> powBasis
coeffsCyc bas (CycPair a b) =
zipWith CycPair (coeffsCyc bas a) (coeffsCyc bas b)
instance (TensorPowDec t (RRq q r)) => ExtensionCyc (Cyc t) (RRq q r) where
embed (PowRRq u) = PowRRq $ embedPow u
embed (DecRRq u) = PowRRq $ embedPow $ toPow u
twace (PowRRq u) = PowRRq $ twacePow u
twace (DecRRq u) = DecRRq $ twaceDec u
powBasis :: forall m m' . (m `Divides` m') => Tagged m [Cyc t m' (RRq q r)]
powBasis = tag $ PowRRq <$> R.powBasis @m
coeffsCyc L.Pow (PowRRq c) = PowRRq <$> R.coeffsPow c
coeffsCyc L.Dec (DecRRq c) = DecRRq <$> R.coeffsDec c
coeffsCyc L.Pow (DecRRq c) = PowRRq <$> R.coeffsPow (toPow c)
coeffsCyc L.Dec (PowRRq c) = DecRRq <$> R.coeffsDec (toDec c)
embed' :: forall t r l m . (l `Divides` m, CRTElt t r)
=> CycG t l r -> CycG t m r
{-# INLINE embed' #-}
embed' (Pow u) = Pow $ embedPow u
embed' (Dec u) = Pow $ embedPow $ toPow u
embed' (CRT u) = either (cycPE . embedCRTE) (cycPC . embedCRTC) u
embed' (Scalar c) = Scalar c
embed' (Sub (c :: CycG t k r)) = embed' c \\ transDivides @k @l @m
instance (PPow pp, Prime (PrimePP pp), zpp ~ ZqBasic pp z, ToInteger z,
CRTElt t zpp, TensorCRTSet t (ZqBasic (PrimePP pp) z),
ExtensionCyc (CycG t) zpp)
=> CRTSetCyc (CycG t) (ZqBasic pp z) where
crtSet :: forall m m' . (m `Divides` m') => Tagged m [CycG t m' zpp]
crtSet = tag $ Pow <$> R.crtSet @m
{-# INLINABLE crtSet #-}
instance (CRTSetCyc (CycG t) (ZqBasic q z))
=> CRTSetCyc (Cyc t) (ZqBasic q z) where
crtSet = (CycZqB <$>) <$> crtSet
{-# INLINABLE crtSet #-}
instance (RescaleCyc (Cyc t m) a b, Fact m,
Additive (Cyc t m a), Additive (Cyc t m b))
=> Rescale (Cyc t m a) (Cyc t m b) where
rescale = rescaleCyc L.Pow
{-# INLINABLE rescale #-}
instance (Fact m, Rescale a b, CRTElt t a, TensorPowDec t b)
=> RescaleCyc (CycG t m) a b where
{-# SPECIALIZE instance (Fact m, Reflects q1 Int64, Reflects q2 Int64, CRTElt t (ZqBasic q1 Int64), TensorPowDec t (ZqBasic q2 Int64)) => RescaleCyc (CycG t m) (ZqBasic q1 Int64) (ZqBasic q2 Int64) #-}
rescaleCyc L.Pow (Scalar c) = Scalar $ rescale c
rescaleCyc L.Pow (Sub c) = Sub $ rescalePow c
rescaleCyc L.Pow c = Pow $ fmapI rescale $ unCycGPow c
rescaleCyc L.Dec c = Dec $ fmapI rescale $ unCycGDec c
{-# INLINABLE rescaleCyc #-}
instance {-# OVERLAPPING #-} RescaleCyc (CycG t m) a a where
rescaleCyc _ = id
{-# INLINABLE rescaleCyc #-}
instance (RescaleCyc (CycG t m) (ZqBasic q z) (ZqBasic p z))
=> RescaleCyc (Cyc t m) (ZqBasic q z) (ZqBasic p z) where
rescaleCyc b = CycZqB . rescaleCyc b . unCycZqB
{-# INLINABLE rescaleCyc #-}
instance (Fact m, Rescale (RRq q r) (RRq p r),
TensorPowDec t (RRq q r), TensorPowDec t (RRq p r))
=> RescaleCyc (Cyc t m) (RRq q r) (RRq p r) where
rescaleCyc L.Pow (PowRRq u) = PowRRq $ rescale u
rescaleCyc L.Pow (DecRRq u) = PowRRq $ rescale $ toPow u
rescaleCyc L.Dec (DecRRq u) = DecRRq $ rescale u
rescaleCyc L.Dec (PowRRq u) = DecRRq $ rescale $ toDec u
{-# INLINABLE rescaleCyc #-}
instance RescaleCyc (Cyc t m) (a,b) (a,b) where
rescaleCyc = const id
{-# INLINABLE rescaleCyc #-}
instance (Fact m, Reflects q z, Reduce z b, ZeroTestable z,
CRTElt t (ZqBasic q z), Module.C b (Cyc t m b))
=> RescaleCyc (Cyc t m) b (ZqBasic q z, b) where
rescaleCyc = let q :: z = value @q
in \_ b -> CycPair zero $ (reduce q :: b) *> b
{-# INLINABLE rescaleCyc #-}
instance (ToInteger z, Reflects q z, Reduce z b, Field b,
FunctorCyc (Cyc t m) (ZqBasic q z) z,
FunctorCyc (Cyc t m) z b,
Additive (Cyc t m b), Module b (Cyc t m b))
=> RescaleCyc (Cyc t m) (ZqBasic q z, b) b where
rescaleCyc bas (CycPair a b) =
let q :: z = value @q
x = liftCyc (Just bas) a
in recip (reduce q :: b) *> (b - reduceCyc x)
{-# INLINABLE rescaleCyc #-}
instance (RescaleCyc (Cyc t m) (b,c) c, RescaleCyc (Cyc t m) (a,(b,c)) (b,c))
=> RescaleCyc (Cyc t m) (a,(b,c)) c where
rescaleCyc bas a = rescaleCyc bas (rescaleCyc bas a :: Cyc t m (b,c))
{-# INLINABLE rescaleCyc #-}
instance (RescaleCyc (Cyc t m) (b,(c,d)) d,
RescaleCyc (Cyc t m) (a,(b,(c,d))) (b,(c,d)))
=> RescaleCyc (Cyc t m) (a,(b,(c,d))) d where
rescaleCyc bas a = rescaleCyc bas (rescaleCyc bas a :: Cyc t m (b,(c,d)))
{-# INLINABLE rescaleCyc #-}
instance (RescaleCyc (Cyc t m) (b,(c,(d,e))) e,
RescaleCyc (Cyc t m) (a,(b,(c,(d,e)))) (b,(c,(d,e))))
=> RescaleCyc (Cyc t m) (a,(b,(c,(d,e)))) e where
rescaleCyc bas a = rescaleCyc bas (rescaleCyc bas a :: Cyc t m (b,(c,(d,e))))
{-# INLINABLE rescaleCyc #-}
instance (Gadget gad (ZqBasic q z),
Fact m, CRTElt t (ZqBasic q z),
ZeroTestable (ZqBasic q z), IntegralDomain (ZqBasic q z))
=> Gadget gad (CycG t m (ZqBasic q z)) where
gadget = Scalar <$> gadget @gad
{-# INLINABLE gadget #-}
instance Gadget gad (CycG t m (ZqBasic q z))
=> Gadget gad (Cyc t m (ZqBasic q z)) where
gadget = CycZqB <$> gadget @gad
{-# INLINABLE gadget #-}
instance (Gadget gad (Cyc t m a), Gadget gad (Cyc t m b))
=> Gadget gad (Cyc t m (a,b)) where
gadget = (++) (flip CycPair zero <$> gadget @gad)
( CycPair zero <$> gadget @gad)
{-# INLINABLE gadget #-}
instance (Fact m, Reduce a b, CRTElt t a, TensorPowDec t b)
=> Reduce (CycG t m a) (CycG t m b) where
reduce (Pow u) = Pow $ reduce u
reduce (Dec u) = Dec $ reduce u
reduce (CRT u) = Pow $ reduce $ either toPow toPow u
reduce (Scalar c) = Scalar $ reduce c
reduce (Sub (c :: CycG t l a)) = Sub (reduce c :: CycG t l b)
{-# INLINABLE reduce #-}
instance (Reduce (CycG t m Int64) (CycG t m (ZqBasic q Int64)))
=> Reduce (Cyc t m Int64) (Cyc t m (ZqBasic q Int64)) where
reduce = CycZqB . reduce . unCycI64
{-# INLINABLE reduce #-}
instance (Reflects q Int64, Functor (t m))
=> Reduce (Cyc t m Integer) (Cyc t m (ZqBasic q Int64)) where
reduce (PowIgr u) = CycZqB $ Pow $ fmap reduce u
reduce (DecIgr u) = CycZqB $ Dec $ fmap reduce u
{-# INLINABLE reduce #-}
instance (Reflects q Double, FunctorCyc (Cyc t m) Double (RRq q Double))
=> Reduce (Cyc t m Double) (Cyc t m (RRq q Double)) where
reduce = fmapCyc Nothing reduce
{-# INLINABLE reduce #-}
instance (Reduce (Cyc t m z) (Cyc t m a), Reduce (Cyc t m z) (Cyc t m b))
=> Reduce (Cyc t m z) (Cyc t m (a,b)) where
reduce z = CycPair (reduce z) (reduce z)
{-# INLINABLE reduce #-}
instance (Decompose gad (ZqBasic q z), CRTElt t (ZqBasic q z), Fact m,
ZeroTestable (ZqBasic q z), IntegralDomain (ZqBasic q z),
CRTElt t z, ZeroTestable z)
=> Decompose gad (CycG t m (ZqBasic q z)) where
type DecompOf (CycG t m (ZqBasic q z)) = CycG t m z
decompose (Scalar c) = Scalar <$> decompose @gad c
decompose (Sub c) = Sub <$> decompose @gad c
decompose (Pow u) = getZipList $ Pow <$> traverse (ZipList . decompose @gad) u
decompose c = decompose @gad $ toPow' c
{-# INLINABLE decompose #-}
instance (Decompose gad (CycG t m (ZqBasic q Int64)),
Reduce (Cyc t m Int64) (Cyc t m (ZqBasic q Int64)))
=> Decompose gad (Cyc t m (ZqBasic q Int64)) where
type DecompOf (Cyc t m (ZqBasic q Int64)) = Cyc t m Int64
decompose (CycZqB c) = CycI64 <$> decompose @gad c
{-# INLINABLE decompose #-}
instance (Decompose gad (Cyc t m a), Decompose gad (Cyc t m b),
DecompOf (Cyc t m a) ~ DecompOf (Cyc t m b),
Reduce (DecompOf (Cyc t m a)) (Cyc t m (a, b)))
=> Decompose gad (Cyc t m (a,b)) where
type DecompOf (Cyc t m (a,b)) = DecompOf (Cyc t m a)
decompose (CycPair a b) = (++) (decompose @gad a) (decompose @gad b)
{-# INLINABLE decompose #-}
instance (Correct gad (ZqBasic q z), CRTElt t (ZqBasic q z), Fact m,
ZeroTestable (ZqBasic q z), IntegralDomain (ZqBasic q z),
Traversable (CycRep t D m))
=> Correct gad (CycG t m (ZqBasic q z)) where
correct bs = Dec *** (Dec <$>) $
second sequence $ fmap fst &&& fmap snd $ correct @gad <$>
sequenceA (unCycGDec <$> bs)
{-# INLINABLE correct #-}
instance Correct gad (CycG t m (ZqBasic q Int64))
=> Correct gad (Cyc t m (ZqBasic q Int64)) where
correct = (CycZqB *** fmap CycI64) . correct @gad . fmap unCycZqB
{-# INLINABLE correct #-}
toPow', toDec', toCRT' :: (Fact m, CRTElt t r) => CycG t m r -> CycG t m r
{-# INLINABLE toPow' #-}
{-# INLINABLE toDec' #-}
{-# INLINABLE toCRT' #-}
toPow' c@(Pow _) = c
toPow' (Dec u) = Pow $ toPow u
toPow' (CRT u) = Pow $ either toPow toPow u
toPow' (Scalar c) = Pow $ scalarPow c
toPow' (Sub c) = toPow' $ embed' c
toDec' (Pow u) = Dec $ toDec u
toDec' c@(Dec _) = c
toDec' (CRT u) = Dec $ either toDec toDec u
toDec' (Scalar c) = Dec $ toDec $ scalarPow c
toDec' (Sub c) = toDec' $ embed' c
toCRT' (Pow u) = CRT $ toCRT u
toCRT' (Dec u) = CRT $ toCRT u
toCRT' c@(CRT _) = c
toCRT' (Scalar c) = CRT $ scalarCRT c
toCRT' (Sub c) = toCRT' $ embed' $ toCRT' c
instance (Random (t m r), Fact m, TensorCRT t Maybe r)
=> Random (CycG t m r) where
random g = let (u,g') = random g
in (either Pow (CRT . Right) u, g')
{-# INLINABLE random #-}
randomR _ = error "randomR non-sensical for CycG"
deriving instance Random (CycG t m Double) => Random (Cyc t m Double)
deriving instance Random (CycG t m Int64) => Random (Cyc t m Int64)
deriving instance Random (CycG t m (ZqBasic q z)) => Random (Cyc t m (ZqBasic q z))
instance (Random (Cyc t m a), Random (Cyc t m b)) => Random (Cyc t m (a,b)) where
{-# SPECIALIZE instance (Fact m, Random (t m (ZqBasic q Int64)), TensorCRT t Maybe (ZqBasic q Int64), Random (Cyc t m b)) => Random (Cyc t m (ZqBasic q Int64, b)) #-}
random g = let (a,g') = random g
(b,g'') = random g'
in (CycPair a b, g'')
randomR _ = error "randomR non-sensical for Cyc"
{-# INLINABLE random #-}
instance (Random (t m Integer), Fact m) => Random (Cyc t m Integer) where
random g = let (u,g') = random g in (PowIgr u, g')
randomR = error "randomR nonsensical for Cyc over Integer"
{-# INLINABLE random #-}
instance (Random (t m (RRq q r)))
=> Random (Cyc t m (RRq q r)) where
random g = let (u,g') = random g in (PowRRq u, g')
randomR = error "randomR nonsensical for Cyc over (RRq q r)"
{-# INLINABLE random #-}
instance (Show r, Fact m, r' ~ CRTExt r,
forall m' . Fact m' => (Show (t m' r), Show (t m' r')))
=> Show (CycG t m r) where
show (Pow x) = "Cyc.Pow " ++ show x
show (Dec x) = "Cyc.Dec " ++ show x
show (CRT (Left x)) = "Cyc.CRT " ++ show x
show (CRT (Right x)) = "Cyc.CRT " ++ show x
show (Scalar x) = "Cyc.Scalar " ++ show x
show (Sub x) = "Cyc.Sub " ++ show x
deriving instance Show (CycG t m Double) => Show (Cyc t m Double)
deriving instance Show (CycG t m Int64) => Show (Cyc t m Int64)
deriving instance Show (CycG t m (ZqBasic q z)) => Show (Cyc t m (ZqBasic q z))
deriving instance (Show (Cyc t m a), Show (Cyc t m b))
=> Show (Cyc t m (a,b))
deriving instance (Show (t m Integer)) => Show (Cyc t m Integer)
deriving instance (Show (t m (RRq q r))) => Show (Cyc t m (RRq q r))
instance (NFData r, Fact m, r' ~ CRTExt r,
forall m' . Fact m' => (NFData (t m' r), NFData (t m' r')))
=> NFData (CycG t m r) where
rnf (Pow u) = rnf u
rnf (Dec u) = rnf u
rnf (CRT u) = rnf u
rnf (Scalar u) = rnf u
rnf (Sub c) = rnf c
deriving instance NFData (CycG t m Double) => NFData (Cyc t m Double)
deriving instance NFData (CycG t m Int64) => NFData (Cyc t m Int64)
deriving instance NFData (CycG t m (ZqBasic q z)) => NFData (Cyc t m (ZqBasic q z))
instance (NFData (Cyc t m a), NFData (Cyc t m b)) => NFData (Cyc t m (a,b)) where
rnf (CycPair a b) = rnf a `seq` rnf b
instance (Fact m, forall m' . Fact m' => NFData (t m' Integer))
=> NFData (Cyc t m Integer) where
rnf (PowIgr u) = rnf u
rnf (DecIgr u) = rnf u
instance (Fact m, forall m' . Fact m' => NFData (t m' (RRq q r)))
=> NFData (Cyc t m (RRq q r)) where
rnf (PowRRq u) = rnf u
rnf (DecRRq u) = rnf u
instance (Fact m, CRTElt t r, Protoable (CycRep t D m r))
=> Protoable (CycG t m r) where
type ProtoType (CycG t m r) = ProtoType (CycRep t D m r)
toProto (Dec uc) = toProto uc
toProto x = toProto $ toDec' x
fromProto x = Dec <$> fromProto x
instance (Fact m, CRTElt t Double, Protoable (CycG t m Double))
=> Protoable (Cyc t m Double) where
type ProtoType (Cyc t m Double) = ProtoType (CycG t m Double)
toProto = toProto . unCycDbl
fromProto x = CycDbl <$> fromProto x
instance (Fact m, CRTElt t Int64, Protoable (CycG t m Int64))
=> Protoable (Cyc t m Int64) where
type ProtoType (Cyc t m Int64) = ProtoType (CycG t m Int64)
toProto = toProto . unCycI64
fromProto x = CycI64 <$> fromProto x
instance (Fact m, CRTElt t Double, Protoable (CycG t m (ZqBasic q z)))
=> Protoable (Cyc t m (ZqBasic q z)) where
type ProtoType (Cyc t m (ZqBasic q z)) = ProtoType (CycG t m (ZqBasic q z))
toProto = toProto . unCycZqB
fromProto x = CycZqB <$> fromProto x
instance (Fact m, CRTElt t Double, TensorPowDec t (RRq q Double),
Protoable (CycRep t D m (RRq q Double)))
=> Protoable (Cyc t m (RRq q Double)) where
type ProtoType (Cyc t m (RRq q Double)) = ProtoType (CycG t m (RRq q Double))
toProto (PowRRq x) = toProto $ toDec x
toProto (DecRRq x) = toProto x
fromProto x = DecRRq <$> fromProto x
let types = [ [t| Int64 |]
, [t| Double |]
, [t| ZqBasic $(varT (mkName "q")) $(varT (mkName "z")) |]
, [t| RRq $(varT (mkName "q")) $(varT (mkName "r")) |]
, [t| ( $(varT (mkName "a")) , $(varT (mkName "b"))) |]
]
mkIFunctorCyc y z =
[d|
instance (Fact m, UnCyc t $y, UnCyc t $z,
IFunctor t, IFElt t $y, IFElt t $z)
=> FunctorCyc (Cyc t m) $y $z where
fmapCyc (Just L.Pow) f = cycPow . fmapI f . unCycPow
fmapCyc (Just L.Dec) f = cycDec . fmapI f . unCycDec
fmapCyc Nothing f = fmapCyc (Just L.Pow) f
|]
mkFunctorCyc y =
[d|
instance (Fact m, Functor (t m), UnCyc t $y)
=> FunctorCyc (Cyc t m) $y Integer where
fmapCyc (Just L.Pow) f = PowIgr . fmap f . unCycPow
fmapCyc (Just L.Dec) f = DecIgr . fmap f . unCycDec
fmapCyc Nothing f = fmapCyc (Just L.Pow) f
|]
in fmap concat $ sequence $
(mkIFunctorCyc <$> types <*> types) ++ (mkFunctorCyc <$> types)