{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
module Crypto.Lol.Gadget
( Gadget(..), Decompose(..), Correct(..)
, decomposeList, decomposeMatrix
, TrivGad, BaseBGad
) where
import Crypto.Lol.Prelude
import MathObj.Matrix hiding (one, zero, zipWith)
import Control.Applicative
import Control.Arrow
data TrivGad
data BaseBGad b
class Ring u => Gadget gad u where
gadget :: [u]
encode :: u -> [u]
encode s = (* s) <$> gadget @gad
class (Gadget gad u, Reduce (DecompOf u) u) => Decompose gad u where
type DecompOf u
decompose :: u -> [DecompOf u]
decomposeList :: forall gad u . Decompose gad u => [u] -> [DecompOf u]
decomposeList = concatMap (decompose @gad)
decomposeMatrix :: forall gad u . (Decompose gad u)
=> Matrix u -> Matrix (DecompOf u)
decomposeMatrix =
let l = length $ gadget @gad @u
in \m -> fromColumns (l * numRows m) (numColumns m) $
decomposeList @gad <$> columns m
class Gadget gad u => Correct gad u where
correct :: [u] -> (u, [LiftOf u])
instance (Gadget gad a, Gadget gad b) => Gadget gad (a,b) where
gadget = (++) ((,zero) <$> gadget @gad @a) ((zero,) <$> gadget @gad @b)
instance (Decompose gad a, Decompose gad b, DecompOf a ~ DecompOf b)
=> Decompose gad (a,b) where
type DecompOf (a,b) = DecompOf a
decompose (a,b) = (++) (decompose @gad a) (decompose @gad b)
instance (Correct gad a, Correct gad b,
Mod a, Mod b, Field a, Field b, Lift' a, Lift' b,
ToInteger (LiftOf a), ToInteger (LiftOf b))
=> Correct gad (a,b) where
correct =
let ka = length $ gadget @gad @a
qaval = toInteger $ modulus @a
qbval = toInteger $ modulus @b
qamod = fromIntegral qaval
qbmod = fromIntegral qbval
qainv = recip qamod
qbinv = recip qbmod
in \tv ->
let (wa,wb) = splitAt ka tv
(va,xb) = unzip $
(\(a,b) -> let x = toInteger $ lift b
in (qbinv * (a - fromIntegral x), x)) <$> wa
(vb,xa) = unzip $
(\(a,b) -> let x = toInteger $ lift a
in (qainv * (b - fromIntegral x), x)) <$> wb
(sa,ea) = (qbmod *) ***
zipWith (\x e -> x + qbval * toInteger e) xb $
correct @gad va
(sb,eb) = (qamod *) ***
zipWith (\x e -> x + qaval * toInteger e) xa $
correct @gad vb
in ((sa,sb), ea ++ eb)