{-|
Module      : Crypto.Lol.RLWE.RLWR
Description : Functions and types for working with ring-LWR samples.
Copyright   : (c) Eric Crockett, 2011-2017
                  Chris Peikert, 2011-2018
License     : GPL-3
Maintainer  : ecrockett0@gmail.com
Stability   : experimental
Portability : POSIX

Functions and types for working with ring-LWR samples.
-}

{-# LANGUAGE ConstraintKinds       #-}
{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE NoImplicitPrelude     #-}

module Crypto.Lol.RLWE.RLWR where

import Crypto.Lol

import Control.Monad.Random

-- | An RLWR sample \( (a,b) \in R_q \times R_p\).
type Sample cm zq zp = (cm zq, cm zp)

-- | Common constraints for working with RLWR.
type RLWRCtx cm zq zp =
  (Cyclotomic (cm zq), Random (cm zq), Ring (cm zq), RescaleCyc cm zq zp)

-- | An RLWR sample with the given secret.
sample :: (RLWRCtx cm zq zp, MonadRandom rnd)
          => cm zq -> rnd (Sample cm zq zp)
sample s = let s' = adviseCRT s in do
  a <- getRandom
  return (a, roundedProd s' a)

-- | The \(b\) component of an RLWR sample for secret \(s\) and given \(a\),
-- produced by rounding \(a\cdot s\) in the decoding basis.
roundedProd :: (RLWRCtx cm zq zp) => cm zq -> cm zq -> cm zp
{-# INLINABLE roundedProd #-}
roundedProd s = let s' = adviseCRT s in \a -> rescaleCyc Dec $ a * s'