packages feed

lol-0.0.1.0: src/Crypto/Lol/Cyclotomic/Tensor/RepaTensor/Gauss.hs

{-# LANGUAGE ConstraintKinds, FlexibleContexts, NoImplicitPrelude,
             RebindableSyntax, ScopedTypeVariables #-}

-- | (Continuous) Gaussian sampling for Repa arrays

module Crypto.Lol.Cyclotomic.Tensor.RepaTensor.Gauss
( tGaussianDec' ) where

import Crypto.Lol.Cyclotomic.Tensor.RepaTensor.RTCommon
import Crypto.Lol.GaussRandom
import Crypto.Lol.LatticePrelude

import Control.Monad.Random

-- | A function tagged by the cyclotomic index which,
-- given a (scaled) variance, outputs a Gaussian-distributed
-- vector in the decoding basis
tGaussianDec' :: forall m v r rnd .
                 (Fact m, OrdFloat r, Random r, Unbox r, Elt r,
                  ToRational v, MonadRandom rnd)
                 => v -> rnd (Arr m r)
tGaussianDec' =
  let pm = Proxy::Proxy m
      m = proxy valueFact pm
      n = proxy totientFact pm
      rad = proxy radicalFact pm
  in \v -> do             -- rnd monad
    x <- realGaussians (v * fromIntegral (m `div` rad)) n
    let arr = Arr $ fromUnboxed (Z:.n) x
    return $ fD arr

-- | The fully tensored D transformation
fD :: (Fact m, Transcendental r, Unbox r, Elt r) => Arr m r -> Arr m r
fD = eval $ fTensor $ ppTensor pD

-- | The D transformation for a prime
pD :: forall p r . (NatC p, Transcendental r, Unbox r, Elt r)
      => Tagged p (Trans r)
pD = let pval = proxy valueNatC (Proxy::Proxy p)
     in tag $
        if pval==2
        then Id 1
        else trans (pval-1) $ mulMat $ force $
                            fromFunction (Z :. pval-1 :. pval-1)
                            (\(Z:.i:.j) ->
                              -- mtx is sqrt(2)*[ cos(2pi*i*(j+1)/p) | sin(same) ]
                              -- (signs of columns doesn't matter for our purposes.)
                              let theta = 2 * pi * fromIntegral (i*(j+1)) /
                                          fromIntegral pval
                              in sqrt 2 * if j < pval `div` 2
                                          then cos theta else sin theta)