{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RebindableSyntax #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
module Crypto.Lol.RLWE.Discrete where
import Crypto.Lol
import Crypto.Lol.RLWE.Continuous as C (errorBound, tailGaussian)
import Control.Monad.Random
type Sample cm zq = (cm zq, cm zq)
type RLWECtx cm zq = (Cyclotomic (cm zq), Ring (cm zq), Reduce (cm (LiftOf zq)) (cm zq))
sample :: forall rnd v cm zq .
(RLWECtx cm zq, Random (cm zq), RoundedGaussianCyc (cm (LiftOf zq)),
MonadRandom rnd, ToRational v)
=> v -> cm zq -> rnd (Sample cm zq)
{-# INLINABLE sample #-}
sample svar s = let s' = adviseCRT s in do
a <- getRandom
e :: cm (LiftOf zq) <- roundedGaussian svar
return (a, a * s' + reduce e)
errorTerm :: (RLWECtx cm zq, LiftCyc (cm zq))
=> cm zq -> Sample cm zq -> LiftOf (cm zq)
{-# INLINABLE errorTerm #-}
errorTerm s = let s' = adviseCRT s
in \(a,b) -> liftDec $ b - a * s'
errorGSqNorm :: (RLWECtx cm zq, GSqNormCyc cm (LiftOf zq),
LiftCyc (cm zq), LiftOf (cm zq) ~ cm (LiftOf zq))
=> cm zq -> Sample cm zq -> LiftOf zq
{-# INLINABLE errorGSqNorm #-}
errorGSqNorm s = gSqNorm . errorTerm s
errorBound :: forall m v . (Fact m, RealRing v, Transcendental v)
=> v
-> v
-> Int64
errorBound =
let n = fromIntegral $ totientFact @m
ps = filter (/= 2) . fmap fst $ ppsFact @m
in \v eps -> let
bsq = C.errorBound @m v eps
csq = C.tailGaussian @m eps
fsq = (2 ^ length ps) * n * csq
in ceiling $ fsq + bsq + 2 * sqrt bsq * sqrt fsq