{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RebindableSyntax #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
module Crypto.Lol.RLWE.Continuous where
import Crypto.Lol
import Control.Monad.Random
type Sample cm zq rrq = (cm zq, cm rrq)
type RLWECtx cm zq rrq =
(Cyclotomic (cm zq), Ring (cm zq), Additive (cm rrq),
Subgroup zq rrq, FunctorCyc cm zq rrq)
sample :: forall rnd v cm zq rrq .
(RLWECtx cm zq rrq, Random (cm zq), GaussianCyc (cm (LiftOf rrq)),
Reduce (cm (LiftOf rrq)) (cm rrq), MonadRandom rnd, ToRational v)
=> v -> cm zq -> rnd (Sample cm zq rrq)
{-# INLINABLE sample #-}
sample svar s = let s' = adviseCRT s in do
a <- getRandom
e :: cm (LiftOf rrq) <- tweakedGaussian svar
let as = fmapDec fromSubgroup (a * s')
return (a, as + reduce e)
errorTerm :: (RLWECtx cm zq rrq, LiftCyc (cm rrq))
=> cm zq -> Sample cm zq rrq -> LiftOf (cm rrq)
{-# INLINABLE errorTerm #-}
errorTerm s = let s' = adviseCRT s
in \(a,b) -> liftDec $ b - fmapDec fromSubgroup (a * s')
errorGSqNorm :: (RLWECtx cm zq rrq, GSqNormCyc cm (LiftOf rrq),
LiftCyc (cm rrq), LiftOf (cm rrq) ~ cm (LiftOf rrq))
=> cm zq -> Sample cm zq rrq -> LiftOf rrq
{-# INLINABLE errorGSqNorm #-}
errorGSqNorm = fmap gSqNorm . errorTerm
tailGaussian :: forall m v . (Fact m, Ord v, Transcendental v) => v -> v
tailGaussian eps =
let n = fromIntegral $ totientFact @m
stabilize x =
let x' = (1/2 + log (2 * pi * x)/2 - log eps/n)/pi
in if x'-x < 0.0001 then x' else stabilize x'
in stabilize $ 1/(2*pi)
errorBound :: forall m v . (Fact m, Ord v, Transcendental v)
=> v
-> v
-> v
errorBound v eps =
let n = fromIntegral $ totientFact @m
mhat = fromIntegral $ valueHatFact @m
csq = tailGaussian @m eps
in mhat * n * v * csq