module Crypto.Lol.RLWE.Discrete where
import Crypto.Lol.Cyclotomic.Cyc
import Crypto.Lol.Prelude
import Crypto.Lol.RLWE.Continuous as C (errorBound)
import Control.Applicative
import Control.Monad.Random
type Sample t m zq = (Cyc t m zq, Cyc t m zq)
type RLWECtx t m zq =
(Fact m, Ring zq, Lift' zq, ToInteger (LiftOf zq),
CElt t zq, CElt t (LiftOf zq))
sample :: forall rnd v t m zq .
(RLWECtx t m zq, Random zq, MonadRandom rnd, ToRational v)
=> v -> Cyc t m zq -> rnd (Sample t m zq)
sample svar s = let s' = adviseCRT s in do
a <- getRandom
e :: Cyc t m (LiftOf zq) <- errorRounded svar
return (a, a * s' + reduce e)
errorTerm :: (RLWECtx t m zq)
=> Cyc t m zq -> Sample t m zq -> Cyc t m (LiftOf zq)
errorTerm s = let s' = adviseCRT s
in \(a,b) -> liftDec $ b a * s'
errorGSqNorm :: (RLWECtx t m zq, Ring (LiftOf zq))
=> Cyc t m zq -> Sample t m zq -> LiftOf zq
errorGSqNorm s = gSqNorm . errorTerm s
errorBound :: (RealRing v, Transcendental v, Fact m)
=> v
-> v
-> Tagged m Int64
errorBound v eps = do
n <- fromIntegral <$> totientFact
cont <- C.errorBound v eps
ps <- filter (/= 2) . fmap fst <$> ppsFact
let stabilize x =
let x' = (1/2 + log(2 * pi * x)/2 log eps)/pi
in if x'x < 0.0001 then x' else stabilize x'
return $ ceiling $ (2 ^ length ps) * n * stabilize (1/(2*pi)) + cont