// Get multiple layers of a Benes permutation network. Returns in out[i][j] // the shift amount to move item j in the i'th layer. Also isID[i]=true if // the i'th layer is the identity (i.e., contains only 0 shift amounts). void ColPerm::getBenesShiftAmounts(Vec<Permut>& out, Vec<bool>& isID, const Vec<long>& benesLvls) const { // Go over the columns one by one. For each column extract the columns // permutation, prepare a Benes network for it, and then for every layer // compute the shift amounts for this columns. long n = getDim(dim); // the permutations are over [0,n-1] // Allocate space out.SetLength(benesLvls.length()); isID.SetLength(benesLvls.length()); for (long k=0; k<benesLvls.length(); k++) { out[k].SetLength(getSize()); isID[k] = true; } Vec<long> col; col.SetLength(n); for (long slice_index = 0; slice_index < numSlices(dim); slice_index++) { ConstCubeSlice<long> slice(*this, slice_index, dim); for (long col_index = 0; col_index < slice.numCols(); col_index++) { getHyperColumn(col, slice, col_index); GeneralBenesNetwork net(col); // build a Benes network for this column // Sanity checks: width of network == n, // and sum of benesLvls entries == # of levels assert(net.getSize()==n); {long sum=0; for (long k=0; k<benesLvls.length(); k++) sum+=benesLvls[k]; assert(net.getNumLevels()==sum); } // Compute the layers of the collapased network for this column for (long lvl=0,k=0; k<benesLvls.length(); lvl += benesLvls[k], k++) { // Returns in col the shift amounts for this layer in the network, // restricted to this column. Also returns true if the returned // permutation is the idendity, false otherwise. bool id = collapseBenesLevels(col, net, lvl, benesLvls[k]); isID[k] = isID[k] && id; CubeSlice<long> oslice(out[k], getSig()); CubeSlice<long> osubslice(oslice, slice_index, dim); setHyperColumn(col, osubslice, col_index); } // next collapsed layer } // next column } // next slice }
// powVec[d] = m_d = p_d^{e_d} // computes multiEvalPoints[d] as a vector of length phi(m_d) // containing base^{(m/m_d) j} for j in Z_{m_d}^* void computeMultiEvalPoints(Vec< Vec<zz_p> >& multiEvalPoints, const zz_p& base, long m, const Vec<long>& powVec, const Vec<long>& phiVec) { long k = powVec.length(); multiEvalPoints.SetLength(k); for (long d = 0; d < k; d++) { long m_d = powVec[d]; long phi_d = phiVec[d]; long count = 0; zz_p pow = conv<zz_p>(1); zz_p mult = power(base, m/m_d); multiEvalPoints[d].SetLength(phi_d); for (long j = 0; j < m_d; j++) { if (GCD(j, m_d) == 1) { multiEvalPoints[d][count] = pow; count++; } pow = pow * mult; } } }
void IndexCalc::GenerateBase(long quant){ Vec<ZZ> numbersTable; numbersTable.SetLength(quant); for(long i = 2; i < quant; ++i) numbersTable[i] = conv<ZZ>("0"); for (long i = 2; i*i < quant; ++i ) // przeszukuj liczby od 2 do sqrt(n), 0 i 1 nie s¹ liczbami pierwszymi { if (numbersTable[i] == conv<ZZ>("1")) // je¿eli dana liczba jest ju¿ wykreœlona continue; // to przejdŸ do kolejnej for (long j = 2*i ; j < quant; j += i){ // przejdŸ od liczby 2 * i do n przesuwaj¹c siê o i numbersTable[j] = conv<ZZ>("1"); // i ka¿d¹ z nich usuwaj ze zbioru } } cout << "Liczby pierwsze z przedzia³u od 2 do " << quant << ":" << endl; long j = 0; for (int i = 2; i < quant; i++) // przeszukaj liczby od 2 do n if (numbersTable[i] == conv<ZZ>("0")){ // jeœli liczba nie zosta³a usuniêta ze zbioru j++; primeNumbers.SetLength(j); primeNumbers[j-1] = i; } }
// Compute the cost for all (n choose 2) possible ways to collapse levels. // For j in [0..nlev-i) tab[i][j] is the cost of collapsing levels i..i+j. // I.e., how many different shift amounts would we need to implement for // a permutation-network-layer constructed by collapsing these levels. void buildBenesCostTable(long n, long k, bool good, Vec< Vec<long> >& tab) { long nlev = 2*k-1; tab.SetLength(nlev); for (long i = 0; i < nlev; i++) tab[i].SetLength(nlev-i); Vec<bool> aux_vec; aux_vec.SetLength(2*n-1); bool *aux = &aux_vec[n-1]; for (long i = 0; i < 2*n-1; i++) aux_vec[i] = false; for (long i = 0; i < nlev; i++) { list<long> x; x.push_front(0L); for (long j = 0; j < nlev-i; j++) { long shamt = GeneralBenesNetwork::shamt(n, k, i+j); // The shift amount for this level addOffset(x, shamt, n, aux); if (good) tab[i][j] = reducedCount(x, n, aux) - 1; else tab[i][j] = x.size() - 1; // FIXME: Alternative Impl: // Replace the 5 lines above by // addOffset(x, shamt, n, aux, good); // tab[i][j] = x.size() - 1; // Also initialize aux to false in every iteration } } }
void applyPermToVec(Vec<T>& out, const Vec<T>& in, const Permut& p1) { assert(&out != &in); // NOT an in-place procedure out.SetLength(p1.length()); for (long i=0; i<p1.length(); i++) out[i] = in.at(p1[i]); }
void factorize(Vec< Pair<long, long> > &factors, long N) { factors.SetLength(0); if (N < 2) return; PrimeSeq s; long n = N; while (n > 1) { if (ProbPrime(n)) { append(factors, cons(n, 1L)); return; } long p = s.next(); if ((n % p) == 0) { long e = 1; n = n/p; while ((n % p) == 0) { n = n/p; e++; } append(factors, cons(p, e)); } } }
// Returns a list of prime factors and their multiplicity, // N = \prod_i factors[i].first^{factors[i].second} void factorize(Vec< Pair<long, long> > &factors, long N) { factors.SetLength(0); if (N < 2) return; PrimeSeq s; long n = N; while (n > 1) { if (ProbPrime(n)) { // n itself is a prime, add (n,1) to the list append(factors, cons(n, 1L)); return; } long p = s.next(); if ((n % p) == 0) { // p divides n, find its multiplicity long e = 1; n = n/p; while ((n % p) == 0) { n = n/p; e++; } append(factors, cons(p, e)); // add (p,e) to the list } } }
void computePowVec(Vec<long>& powVec, const Vec< Pair<long, long> >& factors) { long k = factors.length(); powVec.SetLength(k); for (long i = 0; i < k; i++) powVec[i] = computePow(factors[i]); }
// factors[d] = (p_d, e_d) // computes powVec[d] = p_d^{e_d} void computePowVec(Vec<long>& powVec, const Vec< Pair<long, long> >& factors) { long k = factors.length(); powVec.SetLength(k); for (long d = 0; d < k; d++) powVec[d] = computePow(factors[d]); }
void FileList::AddFile(const char *name) { Vec<char> item; item.SetLength(strlen(name)+1); strcpy(item.elts(), name); data.append(item); }
// powVec[d] = p_d^{e_d}, m = \prod_d p_d^{e_d} // computes divVec[d] = m/p_d^{e_d} void computeDivVec(Vec<long>& divVec, long m, const Vec<long>& powVec) { long k = powVec.length(); divVec.SetLength(k); for (long d = 0; d < k; d++) divVec[d] = m/powVec[d]; }
void computeDivVec(Vec<long>& divVec, long m, const Vec<long>& powVec) { long k = powVec.length(); divVec.SetLength(k); for (long i = 0; i < k; i++) divVec[i] = m/powVec[i]; }
void FFTHelper::FFT(const zz_pX& f, Vec<zz_p>& v) const { tmp = f; BluesteinFFT(tmp, m, root, powers, powers_aux, Rb, Rb_aux, Ra); v.SetLength(phim); for (long i = 0, j = 0; i < m; i++) if (coprime[i]) v[j++] = coeff(tmp, i); }
// powVec[d] = p_d^{e_d} // cycVec[d] = Phi_{p_d^{e_d}}(X) mod p void computeCycVec(Vec<zz_pX>& cycVec, const Vec<long>& powVec) { long k = powVec.length(); cycVec.SetLength(k); for (long d = 0; d < k; d++) { ZZX PhimX = Cyclotomic(powVec[d]); cycVec[d] = conv<zz_pX>(PhimX); } }
void getHyperColumn(Vec<T>& v, const ConstCubeSlice<T>& s, long pos) { long m = s.getProd(1); long n = s.getDim(0); assert(pos >= 0 && pos < m); v.SetLength(n); for (long i = 0; i < n; i++) v[i] = s[pos + i*m]; }
// Get the "crude" cube dimensions corresponding to a vector of trees, // the ordered vector with one dimension per tree void GeneratorTrees::getCubeDims(Vec<long>& dims) const { dims.SetLength(trees.length()); // copy dims from the trees for (long i=0; i<trees.length(); i++) { const OneGeneratorTree& T = trees[i]; dims[T.getAuxKey()] = T.DataOfNode(T.rootIdx()).size; // getAuxKey() returns the generator number associated with this tree } }
// Compute one or more layers corresponding to one network of one leaf void PermNetwork::setLayers4Leaf(long lyrIdx, const ColPerm& p, const Vec<long>& benesLvls, long gIdx, const SubDimension& leafData, const Permut& map2cube) { #ifdef DEBUG_PRINTOUT std::cerr << "Layer "<<lyrIdx<<", column-permutation="<< p << endl; #endif // Compute the shift amounts for all the layers in this network Vec<bool> isID; Vec<Permut> shifts; if (benesLvls.length()==1) {// Special case for a "trivial" 1-layer network shifts.SetLength(1); isID.SetLength(1); isID[0] = !p.getShiftAmounts(shifts[0]); } else // The general case of a multi-layer Benes network p.getBenesShiftAmounts(shifts,isID,benesLvls); // Copy the shift amounts to the right place in the bigger network, // renaming the slots from a linear array to the hyper cube for (long i=0; i<benesLvls.length(); i++) { PermNetLayer& lyr = layers[lyrIdx+i]; lyr.genIdx = gIdx; lyr.isID = isID[i]; lyr.e = leafData.e; if (!lyr.isID) { #ifdef DEBUG_PRINTOUT std::cerr << "layer "<<lyrIdx+i<<": "<<shifts[i]<<endl; #endif if (leafData.good) // For good leaves, shift by -x is the same as size-x for (long k=0; k<shifts[i].length(); k++) if (shifts[i][k]<0) shifts[i][k] += leafData.size; applyPermToVec(lyr.shifts, shifts[i], map2cube); // do the renaming #ifdef DEBUG_PRINTOUT std::cerr << " : "<<lyr.shifts<<endl; #endif } // else std::cerr << "layer "<<lyrIdx+i<<"= identity\n"; } }
static void init_representatives(Vec<long>& representatives, long dim, const Vec<long>& mvec, const PAlgebra& zMStar) { assert(dim >= 0 && dim < mvec.length()); // special case if (dim >= LONG(zMStar.numOfGens())) { representatives.SetLength(1); representatives[0] = 1; return; } long m = mvec[dim]; long D = zMStar.OrderOf(dim); long g = InvMod(zMStar.ZmStarGen(dim) % m, m); representatives.SetLength(D); for (long i = 0; i < D; i++) representatives[i] = PowerMod(g, i, m); }
// Converts list<long> to Vec<long> static long listToVec(Vec<long>& vec, LongNodePtr ptr) { long len = length(ptr); vec.SetLength(len); long i = 0; for (LongNodePtr p = ptr; p != NULL; p = p->next) { vec[i] = p->count; i++; } return len; }
// divVec[d] = m/p_d^{e_d}, powVec[d] = p^{e_d} // computes invVec[d] = divVec[d]^{-1} mod powVec[d] void computeInvVec(Vec<long>& invVec, const Vec<long>& divVec, const Vec<long>& powVec) { long k = divVec.length(); invVec.SetLength(k); for (long d = 0; d < k; d++) { long t1 = divVec[d] % powVec[d]; long t2 = InvMod(t1, powVec[d]); invVec[d] = t2; } }
void computeInvVec(Vec<long>& invVec, const Vec<long>& divVec, const Vec<long>& powVec) { long k = divVec.length(); invVec.SetLength(k); for (long i = 0; i < k; i++) { long t1 = divVec[i] % powVec[i]; long t2 = InvMod(t1, powVec[i]); invVec[i] = t2; } }
// computes linearEvalPoints[i] = base^i, i in Z_m^* void computeLinearEvalPoints(Vec<zz_p>& linearEvalPoints, const zz_p& base, long m, long phim) { linearEvalPoints.SetLength(phim); zz_p pow = conv<zz_p>(1); for (long i = 0, j = 0; i < m; i++) { if (GCD(i, m) == 1) linearEvalPoints[j++] = pow; pow = pow * base; } }
static void init_representatives(Vec<long>& representatives, long dim, const Vec<long>& mvec, const PAlgebra& zMStar) { //OLD: assert(dim >= 0 && dim < mvec.length()); helib::assertInRange(dim, 0l, mvec.length(), "Invalid argument: dim must be between 0 and mvec.length()"); // special case if (dim >= LONG(zMStar.numOfGens())) { representatives.SetLength(1); representatives[0] = 1; return; } long m = mvec[dim]; long D = zMStar.OrderOf(dim); long g = InvMod(zMStar.ZmStarGen(dim) % m, m); representatives.SetLength(D); for (long i = 0; i < D; i++) representatives[i] = PowerMod(g, i, m); }
NTL_CLIENT // powVec[d] = p_d^{e_d}, m = \prod_d p_d^{e_d} // computes divVec[d] = m/p_d^{e_d} inline void computeDivVec(Vec<long>& divVec, long m, const Vec<long>& powVec) { long k = powVec.length(); divVec.SetLength(k); for (long d = 0; d < k; d++) divVec[d] = m/powVec[d]; }
// m = m_1 ... m_k, m_d = p_d^{e_d} // powVec[d] = m_d // invVec[d] = (m/m_d)^{-1} mod m_d // computes polyToCubeMap[i] and cubeToPolyMap[i] // where polyToCubeMap[i] is the index of (i_1, ..., i_k) // in the cube with CubeSignature longSig = (m_1, ..., m_k), // and (i_1, ..., i_k) is the unique tuple satistifying // i = i_1 (m/m_1) + ... + i_k (m/m_k) mod m // and // cubeToPolyMap is the inverse map. void computePowerToCubeMap(Vec<long>& polyToCubeMap, Vec<long>& cubeToPolyMap, long m, const Vec<long>& powVec, const Vec<long>& invVec, const CubeSignature& longSig) { long k = powVec.length(); polyToCubeMap.SetLength(m); cubeToPolyMap.SetLength(m); for (long i = 0; i < m; i++) { long j = 0; for (long d = 0; d < k; d++) { long i_d = MulMod((i % powVec[d]), invVec[d], powVec[d]); j += i_d * longSig.getProd(d+1); } polyToCubeMap[i] = j; cubeToPolyMap[j] = i; } }
int main() { Vec<ZZ> v; cin >> v; long n = v.length(); v.SetLength(2*n); long i; for (i = 0 ; i < n; i++) v[n+i] = v[n-1-i]; cout << v << "\n"; }
void vecRed(Vec<ZZ>& out, const Vec<ZZ>& in, long q, bool abs) { out.SetLength(in.length()); // allocate space if needed for (long i=0; i<in.length(); i++) { long c = in[i]%q; if (abs) { if (c<0) c+=q; } else if (q==2) { if (in[i]<0) c = -c; } else { if (c >= q/2) c -= q; else if (c < -(q/2)) c += q; } out[i] = c; } }
// Computes the inverse of the shortToLongMap, computed above. // "undefined" entries are initialzed to -1. void computeLongToShortMap(Vec<long>& longToShortMap, long m, const Vec<long>& shortToLongMap) { long n = shortToLongMap.length(); longToShortMap.SetLength(m); for (long i = 0; i < m; i++) longToShortMap[i] = -1; for (long j = 0; j < n; j++) { long i = shortToLongMap[j]; longToShortMap[i] = j; } }
// For each position in the data vector, compute how many slots it should be // shifted inside its small permutation. // Return value is zero if all the shift amounts are zero, nonzero otherwise. long ColPerm::getShiftAmounts(Vec<long>& out) const { long sz = getSize(); out.SetLength(sz); long nonZero = 0; for (long k = 0; k < sz; k++) { long i = getCoord(k, dim); long pi_i = at(k); if (i != pi_i) nonZero = 1; out.at(addCoord(k, dim, pi_i-i)) = i - pi_i; } return nonZero; }
// Get the "fine" cube dimensions corresponding to a vector of trees, // the ordered vector with one dimension per leaf in any of the trees. void GeneratorTrees::getCubeSubDims(Vec<long>& dims) const { // how many dimensions do we need long nDims = 0; for (long i=0; i<trees.length(); i++) nDims += trees[i].getNleaves(); dims.SetLength(nDims); // set the size // copy dims from the leaves in all the trees long idx = 0; for (long i=0; i<trees.length(); i++) { const OneGeneratorTree& T = trees[i]; for (long leaf=T.firstLeaf(); leaf>=0; leaf=T.nextLeaf(leaf)) dims[idx++] = T[leaf].getData().size; } }