{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PartialTypeSignatures #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RebindableSyntax #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-partial-type-signatures #-}
module Crypto.Lol.Tests.TensorTests
(
tensorCrtTests1, tensorCrtTests2, tensorTests1, tensorTests2
)
where
import Crypto.Lol
import Crypto.Lol.Cyclotomic.Tensor
import Crypto.Lol.Utils.ShowType
import Crypto.Lol.Utils.Tests (Gen, Test, nestGroup, testGroup,
testWithGen, testWithoutGen, (=~=))
import Control.Applicative
import Data.Maybe
tensorTests1 :: forall t m r . _ => Gen (t m r) -> Test
tensorTests1 tensorGen =
let ptmr = Proxy::Proxy '(t,m,r)
tests = ($ tensorGen) <$> [
testWithGen "fmap comparison" prop_fmap,
nestGroup "GInv.G == id" [
testWithGen "Pow basis" prop_ginv_pow,
testWithGen "Dec basis" prop_ginv_dec],
testWithGen "DecToPowToDec == id" prop_decToPowToDec,
testWithGen "G commutes with L on Dec basis" prop_g_dec,
testWithGen "Tw and Em ID on Pow/Dec for equal indices" prop_twEmID] in
testGroup (showType ptmr) tests
tensorCrtTests1 :: forall t m r . _ => Gen r -> Gen (t m r) -> Test
tensorCrtTests1 ringGen tensorGen =
let ptmr = Proxy::Proxy '(t,m,r)
tests = [
testWithGen "GInv.G == id on CRT basis" prop_ginv_crt tensorGen,
testWithGen "CRTInv.CRT == id" prop_crt_inv tensorGen,
testWithGen "G commutes with L on CRT basis" prop_g_crt tensorGen,
testWithGen "Tw and Em ID on CRT for equal indices" prop_twEmIDCRT tensorGen,
testWithGen "Scalar" (prop_scalar_crt ptmr) ringGen] in
testGroup (showType ptmr) tests
tensorTests2 :: forall t m m' r . _
=> Proxy '(t,m,m',r) -> Gen (t m r) -> Test
tensorTests2 _ tensorGen =
let ptmmr = Proxy::Proxy '(t,m,m',r)
randTests = ($ tensorGen) <$> [
nestGroup "Tw.Em == id" [
testWithGen "Pow basis" (prop_trem_pow ptmmr)
, testWithGen "Dec basis" (prop_trem_dec ptmmr)
],
testWithGen "Em commutes with L in Dec basis" (prop_embed_dec ptmmr),
testWithGen "Tw commutes with L in Dec basis" (prop_twace_dec ptmmr)]
deterministicTests = [
testGroup "Twace invariants" [
testWithoutGen "Invar1 Pow basis" (prop_twace_invar1_pow ptmmr),
testWithoutGen "Invar1 Dec basis" (prop_twace_invar1_dec ptmmr),
testWithoutGen "Invar2 Pow/Dec basis" (prop_twace_invar2_powdec ptmmr)]] in
testGroup (showType ptmmr) (randTests ++ deterministicTests)
tensorCrtTests2 :: forall t m m' r . _ => Proxy '(t,m,m',r) -> Gen (t m r) -> Test
tensorCrtTests2 _ tensorGen =
let ptmmr = Proxy::Proxy '(t,m,m',r)
randTests = ($ tensorGen) <$> [
testWithGen "Tw.Em == id in CRT basis" (prop_trem_crt ptmmr),
testWithGen "Em commutes with L in CRT basis" (prop_embed_crt ptmmr),
testWithGen "Tw commutes with L in CRT basis" (prop_twace_crt ptmmr)]
deterministicTests = [
testGroup "Twace invariants" [
testWithoutGen "Invar1 CRT basis" (prop_twace_invar1_crt ptmmr),
testWithoutGen "Invar2 CRT basis" (prop_twace_invar2_crt ptmmr)]] in
testGroup (showType ptmmr) (randTests ++ deterministicTests)
prop_fmap :: _ => t m r -> Bool
prop_fmap x = fmap id x =~= x
prop_ginv_pow :: _ => t m r -> Bool
prop_ginv_pow x = fromMaybe (error "could not divide by G in prop_ginv_pow") (
divGPow $ mulGPow x) =~= x
prop_ginv_dec :: _ => t m r -> Bool
prop_ginv_dec x = fromMaybe (error "could not divide by G in prop_ginv_dec") (
divGDec $ mulGDec x) =~= x
prop_ginv_crt :: _ => t m r -> Bool
prop_ginv_crt x = fromMaybe (error "no CRT in prop_ginv_crt") $ do
divGCRT' <- divGCRT
mulGCRT' <- mulGCRT
return $ divGCRT' (mulGCRT' x) =~= x
prop_g_dec :: _ => t m r -> Bool
prop_g_dec x = mulGDec x =~= powToDec (mulGPow $ decToPow x)
prop_g_crt :: _ => t m r -> Bool
prop_g_crt x = fromMaybe (error "no CRT in prop_g_crt") $ do
mulGCRT' <- mulGCRT
crt' <- crt
crtInv' <- crtInv
return $ mulGCRT' x =~= crt' (mulGPow $ crtInv' x)
prop_crt_inv :: _ => t m r -> Bool
prop_crt_inv x = fromMaybe (error "no CRT in prop_crt_inv") $ do
crt' <- crt
crtInv' <- crtInv
return $ crtInv' (crt' x) =~= x
prop_decToPowToDec :: _ => t m r -> Bool
prop_decToPowToDec x = powToDec (decToPow x) =~= x
prop_scalar_crt :: forall t m r . (TensorPowDec t r, Fact m, _) => Proxy '(t,m,r) -> r -> Bool
prop_scalar_crt _ x = fromMaybe (error "no CRT in prop_scalar_crt") $ do
scalarCRT' <- scalarCRT
crt' <- crt
return $ (scalarCRT' x :: t m r) =~= crt' (scalarPow x)
prop_trem_pow :: forall t m m' r . (m `Divides` m', _) => Proxy '(t,m,m',r) -> t m r -> Bool
prop_trem_pow _ x = twacePowDec (embedPow x :: t m' r) =~= x
prop_trem_dec :: forall t m m' r . (m `Divides` m', _) => Proxy '(t,m,m',r) -> t m r -> Bool
prop_trem_dec _ x = twacePowDec (embedDec x :: t m' r) =~= x
prop_trem_crt :: forall t m m' r . (m `Divides` m', _) => Proxy '(t,m,m',r) -> t m r -> Bool
prop_trem_crt _ x = maybe (error "no CRT in prop_trem_crt") (x=~=) (twaceCRT <*> (embedCRT <*> pure x :: Maybe (t m' r)))
prop_embed_dec :: forall t m m' r . (m `Divides` m', _) => Proxy '(t,m,m',r) -> t m r -> Bool
prop_embed_dec _ x = (embedDec x :: t m' r) =~=
powToDec (embedPow $ decToPow x)
prop_embed_crt :: forall t m m' r . (m `Divides` m', _) => Proxy '(t,m,m',r) -> t m r -> Bool
prop_embed_crt _ x = fromMaybe (error "no CRT in prop_embed_crt") $ do
crt' <- crt
crtInv' <- crtInv
embedCRT' <- embedCRT
return $ (embedCRT' x :: t m' r) =~= crt' (embedPow $ crtInv' x)
prop_twace_dec :: forall t m m' r . _ => Proxy '(t,m,m',r) -> t m r -> Bool
prop_twace_dec _ x = (twacePowDec x :: t m r) =~=
powToDec (twacePowDec $ decToPow x)
prop_twace_crt :: forall t m m' r . _ => Proxy '(t,m,m',r) -> t m r -> Bool
prop_twace_crt _ x = fromMaybe (error "no CRT in prop_trace_crt") $ do
twaceCRT' <- twaceCRT
crt' <- crt
crtInv' <- crtInv
return $ (twaceCRT' x :: t m r) =~= crt' (twacePowDec $ crtInv' x)
prop_twEmIDCRT :: forall t m r . _ => t m r -> Bool
prop_twEmIDCRT x = (fromMaybe (error "twemid_crt") twaceCRT x =~= x) &&
(fromMaybe (error "twemid_crt") embedCRT x =~= x)
prop_twEmID :: forall t m r . _ => t m r -> Bool
prop_twEmID x = (twacePowDec x =~= x) &&
(embedPow x =~= x)
prop_twace_invar1_pow :: forall t m m' r . _ => Proxy '(t,m,m',r) -> Bool
prop_twace_invar1_pow _ = fromMaybe (error "could not divide by G in prop_twace_invar1_pow") $ do
let mhat = valueHatFact @m
mhat' = valueHatFact @m'
totm = totientFact @m
totm' = totientFact @m'
output :: t m r <- divGPow $ scalarPow $ fromIntegral $ mhat * totm' `div` totm
input :: t m' r <- divGPow $ scalarPow $ fromIntegral mhat'
return $ twacePowDec input =~= output
prop_twace_invar1_dec :: forall t m m' r . _ => Proxy '(t,m,m',r) -> Bool
prop_twace_invar1_dec _ = fromMaybe (error "could not divide by G in prop_twace_invar1_dec") $ do
let mhat = valueHatFact @m
mhat' = valueHatFact @m'
totm = totientFact @m
totm' = totientFact @m'
output :: t m r <- divGDec $ powToDec $ scalarPow $ fromIntegral $ mhat * totm' `div` totm
input :: t m' r <- divGDec $ powToDec $ scalarPow $ fromIntegral mhat'
return $ twacePowDec input =~= output
prop_twace_invar1_crt :: forall t m m' r . _ => Proxy '(t,m,m',r) -> Bool
prop_twace_invar1_crt _ = fromMaybe (error "no CRT in prop_twace_invar1_crt") $ do
let mhat = valueHatFact @m
mhat' = valueHatFact @m'
totm = totientFact @m
totm' = totientFact @m'
scalarCRT1 <- scalarCRT
scalarCRT2 <- scalarCRT
divGCRT1 <- divGCRT
divGCRT2 <- divGCRT
twaceCRT' <- twaceCRT
let output :: t m r = divGCRT1 $ scalarCRT1 $ fromIntegral $ mhat * totm' `div` totm
input :: t m' r = divGCRT2 $ scalarCRT2 $ fromIntegral mhat'
return $ twaceCRT' input =~= output
prop_twace_invar2_powdec :: forall t m m' r . (TensorPowDec t r, m `Divides` m', _)
=> Proxy '(t,m,m',r) -> Bool
prop_twace_invar2_powdec _ =
let output = scalarPow one :: t m r
input = scalarPow one :: t m' r
in twacePowDec input =~= output
prop_twace_invar2_crt :: forall t m m' r . (TensorPowDec t r, m `Divides` m', _)
=> Proxy '(t,m,m',r) -> Bool
prop_twace_invar2_crt _ = fromMaybe (error "no CRT in prop_twace_invar2_crt") $ do
scalarCRT1 <- scalarCRT
scalarCRT2 <- scalarCRT
let input = scalarCRT1 one :: t m' r
output = scalarCRT2 one :: t m r
return $ twacePowDec input =~= output