lol-cpp-0.2.0.0: Crypto/Lol/Cyclotomic/Tensor/CPP/tensor.h
/*
Module : tensor.h
Description : Templates for the tensor DSL.
Copyright : (c) Eric Crockett, 2011-2017
Chris Peikert, 2011-2017
License : GPL-3
Maintainer : ecrockett0@email.com
Stability : experimental
Portability : POSIX
A miniature DSL for converting (some) prime-index operators into arbitrary-index
operators via the tensorial decomposition for cyclotomic rings. In particular,
this DSL applies when the prime-power operator is just the tensor (with identity)
of the prime-index operator.
*/
#ifndef TENSOR_CPP_
#define TENSOR_CPP_
#include "types.h"
#include "common.h"
#ifdef __cplusplus
// templated function pointer for prime-index transformations
template <typename ring>
using primeFunc = void (*) (ring*, hDim_t, hDim_t, hDim_t);
// templated function pointer for prime-index CRT-style transformations, which
// also have pointers to roots of unity
template <typename ringy, typename ringru>
using primeCRTFunc = void (*) (ringy*, hDim_t, hDim_t, PrimeExponent, ringru*);
// Turns a prime-index transformation A_p which satisfies into
// A_{p^e} = I_{p^(e-1)} \otimes A_p into an arbitrary-index transformation.
// This mimics the tensor DSL in Haskell by turning A_m into
// A_{pp1} \otimes A_{pp2} \otimes ... \otimes A_{ppk}, where the prime-power
// factorization of m is pp1*pp2*...*ppk. It then applies turns each prime-power
// component into a tensor of prime-index transformations.
template <typename ring> void
tensorFuserPrime(ring* y, primeFunc<ring> f, hDim_t totm,
PrimeExponent* peArr, hShort_t sizeOfPE, hInt_t q)
{
// The first matrix to be applied (starting on the right) is
// (I_totient(pp2..ppk) \otimes A_pp1 \otimes I_1).
// From there, we shift pp2 to the right tensor, then pp3, etc.
hDim_t lts = totm;
hDim_t rts = 1;
hShort_t i;
for (i = 0; i < sizeOfPE; ++i) {
PrimeExponent pe = peArr[i];
// compute p^(e-1)
hDim_t ipow_pe = ipow(pe.prime, (pe.exponent-1));
// totient(ppi)
hDim_t dim = (pe.prime-1) * ipow_pe;
// remove the totient for this operator from the left
lts /= dim;
// apply the matrix
// (I_totient((ppi+1)..ppk) \otimes A_ppi \otimes I_(pp1..(ppi-1)))
// for a prime power
// since A_ppi (where ppi = p^e) is I_{p^(e-1)} \otimes A_p,
// add an additional p^(e-1) factor to lts and use the function
// pointer to call the *prime*-index transform.
(*f) (y, lts*ipow_pe, rts, pe.prime);
// Add the prime power for the transform we just applied to the right tensor.
rts *= dim;
}
}
template <typename ringy, typename ringru> void tensorFuserCRT(ringy* y, primeCRTFunc<ringy,ringru> f, hDim_t totm, PrimeExponent* peArr, hShort_t sizeOfPE, ringru** ru, hInt_t q)
{
hDim_t lts = totm;
hDim_t rts = 1;
hShort_t i;
for (i = 0; i < sizeOfPE; ++i) {
PrimeExponent pe = peArr[i];
hDim_t ipow_pe = ipow(pe.prime, (pe.exponent-1));
hDim_t dim = (pe.prime-1) * ipow_pe; // the totient of pe
lts /= dim;
(*f) (y, lts, rts, pe, ru[i]);
rts *= dim;
}
}
#endif /* __cplusplus */
#endif /* TENSOR_CPP_ */