Example #1
0
void CombinedProfile::printDrift(const CombinedProfile& other,
                                 llvm::raw_ostream& stream) const
{

    // build union of non-zero histograms
    IndexSet I;

    for(unsigned i = 0, E = size(); i < E; ++i)
        if( (_histograms[i] != NULL) && _histograms[i]->nonZero() )
            I.insert(i);

    for(unsigned i = 0, E = other.size(); i < E; ++i)
        if( (other._histograms[i] != NULL) && other._histograms[i]->nonZero() )
            I.insert(i);

    if(I.size() == 0)
        errs() << "Warning: no histograms\n";

    // Compute and print drift
    stream << "#" << getNameStr() << "Index\t0-out\t0-in\n";
    for(IndexSet::iterator i = I.begin(), E = I.end(); i != E; ++i)
    {
        // check for 0-overlap (100% drift) cases
        if( (*i > size()) || (*i > other.size())
                || (_histograms[*i] == NULL) || (other._histograms[*i] == NULL)
                || !_histograms[*i]->nonZero() || !other._histograms[*i]->nonZero() )
        {
            errs() << "Warning: histogram " << *i << " only exists in one profile!\n";
            stream << *i << "\t1.0\t1.0\n";
            continue;
        }

        CPHistogram* h1 = _histograms[*i];
        CPHistogram* h2 = other._histograms[*i];

        if( h1->isPoint() && h2->isPoint() && (h1->min() != h2->min()))
        {
            errs() << "Warning: histogram " << *i << " has different point values\n";
            stream << *i << "\t1.0\t1.0\n";
            continue;
        }

        // finally, no exceptional situations!
        stream << *i << "\t" << 1-h1->overlap(*h2, false) << "\t"
               << 1-h1->overlap(*h2, true) << "\n";

    }
}
Example #2
0
 void Thread::removeOperator(const Operator* op)
 {
     typedef std::set< std::vector<Input>::iterator > IndexSet;
     
     if (op == 0)
         throw WrongArgument("Operator must not be null.");
     
     m_thread->removeOperator(op);
     
     IndexSet toBeErased;
     
     for(std::vector<Input>::iterator iter1 = m_inputSequence.begin();
         iter1 != m_inputSequence.end();
         ++iter1)
     {
         if((*iter1).op() == op)
             toBeErased.insert(iter1);
     }
     
     for(IndexSet::reverse_iterator iter2 = toBeErased.rbegin();
         iter2 != toBeErased.rend();
         ++iter2)
     {
         m_inputSequence.erase(*iter2);
     }
 }
void
readIndexSetFromFile(IndexSet<Index2D> &Lambda, string filename)
{
    std::ifstream infile (filename.c_str());
    if (infile.is_open()) {
        cerr << "   Indexset file is open." << endl;
    }
    else {
        cerr << "   Indexset file " << filename.c_str()  << " is not open." << endl;
    }

	int t1,t2;
    int j1,j2;
    long k1,k2;
    T coeff;

    while(!infile.eof()) {

    	infile >> t1 >> j1 >> k1 >> t2 >> j2 >> k2 >> coeff;

        if (t1 == 1 && t2 == 1) {
            Index1D index_x(j1,k1,XWavelet);
            Index1D index_y(j2,k2,XWavelet);
            Lambda.insert(Index2D(index_x,index_y));
        }
        else if (t1 == 1 && t2 == 0) {
            Index1D index_x(j1,k1,XWavelet);
            Index1D index_y(j2,k2,XBSpline);
            Lambda.insert(Index2D(index_x,index_y));
        }
        else if (t1 == 0 && t2 == 1) {
            Index1D index_x(j1,k1,XBSpline);
            Index1D index_y(j2,k2,XWavelet);
            Lambda.insert(Index2D(index_x,index_y));
        }
        else if (t1 == 0 && t2 == 0) {
            Index1D index_x(j1,k1,XBSpline);
            Index1D index_y(j2,k2,XBSpline);
            Lambda.insert(Index2D(index_x,index_y));
        }
        else {
            std::cerr << "Could not read file." << std::endl;
            exit(1); return;
        }
    }
}
Example #4
0
// Find the IndexSet such that modDown to that set of primes makes the
// additive term due to rounding into the dominant noise term 
void Ctxt::findBaseSet(IndexSet& s) const
{
  if (getNoiseVar()<=0.0) { // an empty ciphertext
    s = context.ctxtPrimes;
    return;
  }

  assert(verifyPrimeSet());
  bool halfSize = context.containsSmallPrime();
  double curNoise = log(getNoiseVar())/2;
  double firstNoise = context.logOfPrime(0);
  double noiseThreshold = log(modSwitchAddedNoiseVar())*0.55;
  // FIXME: The above should have been 0.5. Making it a bit more means
  // that we will mod-switch a little less frequently, whether this is
  // a good thing needs to be tested.

  // remove special primes, if they are included in this->primeSet
  s = getPrimeSet();
  if (!s.disjointFrom(context.specialPrimes)) { 
    // scale down noise
    curNoise -= context.logOfProduct(context.specialPrimes);
    s.remove(context.specialPrimes);
  }

  /* We compare below to noiseThreshold+1 rather than to noiseThreshold
   * to make sure that if you mod-switch down to c.findBaseSet() and
   * then immediately call c.findBaseSet() again, it will not tell you
   * to mod-switch further down. Note that mod-switching adds close to
   * noiseThreshold to the scaled noise, so if the scaled noise was
   * equal to noiseThreshold then after mod-switchign you would have
   * roughly twice as much noise. Since we're mesuring the log, it means
   * that you may have as much as noiseThreshold+log(2), which we round
   * up to noiseThreshold+1 in the test below.
   */
  if (curNoise<=noiseThreshold+1) return; // no need to mod down

  // if the first prime in half size, begin by removing it
  if (halfSize && s.contains(0)) {
    curNoise -= firstNoise;
    s.remove(0);
  }

  // while noise is larger than threshold, scale down by the next prime
  while (curNoise>noiseThreshold && !empty(s)) {
    curNoise -= context.logOfPrime(s.last());
    s.remove(s.last());
  }

  // Add 1st prime if s is empty or if this does not increase noise too much
  if (empty(s) || (!s.contains(0) && curNoise+firstNoise<=noiseThreshold)) {
    s.insert(0);
    curNoise += firstNoise;
  }

  if (curNoise>noiseThreshold && log_of_ratio()>-0.5)
    cerr << "Ctxt::findBaseSet warning: already at lowest level\n";
}
Example #5
0
void readContextBinary(istream& str, FHEcontext& context)
{
  assert(readEyeCatcher(str, BINIO_EYE_CONTEXT_BEGIN)==0);

  // Get the standard deviation
  context.stdev = read_raw_xdouble(str);

  long sizeOfS = read_raw_int(str);

  IndexSet s;
  for(long tmp, i=0; i<sizeOfS; i++){
    tmp = read_raw_int(str);
    s.insert(tmp);
  }

  context.moduli.clear();
  context.specialPrimes.clear();
  context.ctxtPrimes.clear();

  long nPrimes = read_raw_int(str);

  for (long p,i=0; i<nPrimes; i++) {
    p = read_raw_int(str);

    context.moduli.push_back(Cmodulus(context.zMStar,p,0));

    if (s.contains(i))
      context.specialPrimes.insert(i); // special prime
    else
      context.ctxtPrimes.insert(i);    // ciphertext prime
  }
  
  long nDigits = read_raw_int(str);

  context.digits.resize(nDigits);
  for(long i=0; i<(long)context.digits.size(); i++){
    sizeOfS = read_raw_int(str);

    for(long tmp, n=0; n<sizeOfS; n++){
      tmp = read_raw_int(str);
      context.digits[i].insert(tmp);
    }
  }

  // Read in the partition of m into co-prime factors (if bootstrappable)
  Vec<long> mv;
  read_ntl_vec_long(str, mv);

  long t = read_raw_int(str);
  bool consFlag = read_raw_int(str);  

  if (mv.length()>0) {
    context.makeBootstrappable(mv, t, consFlag);
  }

  assert(readEyeCatcher(str, BINIO_EYE_CONTEXT_END)==0);
}
Example #6
0
IndexSet<Index1D>
LambdaForEigenvalues(int jmin, int jmax, const Basis1D &basis, T radius, bool with_BSplines)
{
    const BSpline<T,Primal,R,CDF> phi = basis.mra.phi;
    const Wavelet<T,Primal,R,CDF> psi = basis.psi;
    IndexSet<Index1D> Lambda;
    int k_left, k_right;
    if (with_BSplines) {
        for (int j=jmin; j<=jmax; ++j) {
            k_left = std::floor(-pow2i<T>(j)*radius-psi.support(0,0).l2);
            k_right = std::ceil(pow2i<T>(j)*radius-psi.support(0,0).l1);
            for (int k=k_left; k<=k_right; ++k) {
                Lambda.insert(Index1D(j,k,XWavelet));
            }
        }

        k_left  = int(std::floor(-pow2i<T>(jmin)*radius-phi.support(0,0).l2));
        k_right = int(std::ceil(  pow2i<T>(jmin)*radius-phi.support(0,0).l1));
        for (int k=k_left; k<=k_right; ++k) {
            Lambda.insert(Index1D(jmin,k,XBSpline));
        }
    }
    else {
        for (int j=jmin; j<=jmax; ++j) {
                int k_left, k_right;
                if (j>=-6) {
                    k_left = std::floor(-pow2i<T>(j)*radius-psi.support(0,0).l2);
                    k_right = std::ceil(pow2i<T>(j)*radius-psi.support(0,0).l1);
                    if (k_left>=0) cout << "j=" << j << ", k_left=" << k_left << endl;
                    if (k_right<=0) cout << "j=" << j << ", k_right=" << k_right << endl;
                }
                else {
                    k_left = -psi.d-psi.d_;
                    k_right = psi.d+psi.d_;
                }
                for (int k=k_left; k<=k_right; ++k) {
                    Lambda.insert(Index1D(j,k,XWavelet));
                }
            }
    }
    return Lambda;
}
Example #7
0
//------------------------------add_liveout------------------------------------
// Add a live-out value to a given blocks live-out set.  If it is new, then
// also add it to the delta set and stick the block on the worklist.
void PhaseLive::add_liveout( Block *p, uint r, VectorSet &first_pass ) {
  IndexSet *live = &_live[p->_pre_order-1];
  if( live->insert(r) ) {       // If actually inserted...
    // We extended the live-out set.  See if the value is generated locally.
    // If it is not, then we must extend the live-in set.
    if( !_defs[p->_pre_order-1].member( r ) ) {
      if( !_deltas[p->_pre_order-1] && // Not on worklist?
          first_pass.test(p->_pre_order) )
        _worklist->push(p);     // Actually go on worklist if already 1st pass
      getset(p)->insert(r);  
    }
  }
}
Example #8
0
//------------------------------Union------------------------------------------
// Union edges of B into A
void PhaseIFG::Union( uint a, uint b ) {
  assert( _is_square, "only on square" );
  IndexSet *A = &_adjs[a];
  IndexSetIterator b_elements(&_adjs[b]);
  uint datum;
  while ((datum = b_elements.next()) != 0) {
    if(A->insert(datum)) {
      _adjs[datum].insert(a);
      lrgs(a).invalid_degree();
      lrgs(datum).invalid_degree();
    }
  }
}
Example #9
0
File: Ctxt.cpp Project: 2080/HElib
// Find the IndexSet such that modDown to that set of primes makes the
// additive term due to rounding into the dominant noise term 
void Ctxt::findBaseSet(IndexSet& s) const
{
  if (getNoiseVar()<=0.0) { // an empty ciphertext
    s = context.ctxtPrimes;
    return;
  }

  assert(verifyPrimeSet());
  bool halfSize = context.containsSmallPrime();
  double addedNoise = log(modSwitchAddedNoiseVar())/2;
  double curNoise = log(getNoiseVar())/2;
  double firstNoise = context.logOfPrime(0);

  // remove special primes, if they are included in this->primeSet
  s = getPrimeSet();
  if (!s.disjointFrom(context.specialPrimes)) { 
    // scale down noise
    curNoise -= context.logOfProduct(context.specialPrimes);
    s.remove(context.specialPrimes);
  }

  if (curNoise<=2*addedNoise) return; // no need to mod down

  // if the first prime in half size, begin by removing it
  if (halfSize && s.contains(0)) {
    curNoise -= firstNoise;
    s.remove(0);
  }

  // while noise is larger than added term, scale down by the next prime
  while (curNoise>addedNoise && card(s)>1) {
    curNoise -= context.logOfPrime(s.last());
    s.remove(s.last());
  }

  if (halfSize) {
    // If noise is still too big, drop last big prime and insert half-size prime
    if (curNoise>addedNoise) {
      curNoise = firstNoise;
      s = IndexSet(0);
    } 
    // Otherwise check if you can add back the half-size prime
    else if (curNoise+firstNoise <= addedNoise) {
      curNoise += firstNoise;
      s.insert(0);
    }
  }

  if (curNoise>addedNoise && log_of_ratio()>-0.5)
    cerr << "Ctxt::findBaseSet warning: already at lowest level\n";
}
Example #10
0
//------------------------------add_liveout------------------------------------
// Add a vector of live-out values to a given blocks live-out set.
void PhaseLive::add_liveout( Block *p, IndexSet *lo, VectorSet &first_pass ) {
  IndexSet *live = &_live[p->_pre_order-1];
  IndexSet *defs = &_defs[p->_pre_order-1];
  IndexSet *on_worklist = _deltas[p->_pre_order-1];
  IndexSet *delta = on_worklist ? on_worklist : getfreeset();

  IndexSetIterator elements(lo);
  uint r;
  while ((r = elements.next()) != 0) {
    if( live->insert(r) &&      // If actually inserted...
        !defs->member( r ) )    // and not defined locally
      delta->insert(r);         // Then add to live-in set
  }

  if( delta->count() ) {                // If actually added things
    _deltas[p->_pre_order-1] = delta; // Flag as on worklist now
    if( !on_worklist &&         // Not on worklist?
        first_pass.test(p->_pre_order) )
      _worklist->push(p);       // Actually go on worklist if already 1st pass
  } else {                      // Nothing there; just free it
    delta->set_next(_free_IndexSet);
    _free_IndexSet = delta;     // Drop onto free list
  }
}
Example #11
0
bool Octree::intersectHit( IndexSet& tris )
{
	if(this->children.size() > 0)
		return false;

	for(StdVector<BaseTriangle*>::iterator it = triangleData.begin(); it != triangleData.end(); it++)
	{
		BaseTriangle * face = *it;

		tris.insert( face->index );
	}

	root()->selectedChildren.push_back(this);

	return true;
}
int main (int argc, char *argv[]) {
    if (argc != 5 && argc != 6) {
        cout << "usage " << argv[0] << " d d_ max_its example [jmin]" << endl; exit(1);
    }
    T c = 1.;
    T contraction = 0.125;
    T threshTol = 0.1, cgTol = 0.1*threshTol, resTol=1e-4;

    int d=atoi(argv[1]), d_=atoi(argv[2]);
    int NumOfIterations=atoi(argv[3]);
    int example=atoi(argv[4]);
    int jmin=0;
    int rhs_order=10;
    if (argc==5) {
        if (d==2 && d_==2) {
            if (example==1)      jmin=-2;
            else if (example==2) jmin=-4;
            else if (example==3) jmin=-1;
            else if (example==4) jmin=0;
            else if (example==5) jmin=0;
            else if (example==6) jmin=-1;       //better convergence behaviour
        }
        else if (d==3 && d_==3) {
            if (example==1)      jmin=-2;
            else if (example==2) jmin=-4;
            else if (example==3) jmin=-1;
            else if (example==4) jmin=0;
            else if (example==5) jmin=-1;
            else if (example==6) jmin=-1;       //better convergence behaviour
        }
        else if (d==3 && d_==5) {
            if (example==1)      jmin=-2;
            else if (example==2) jmin=-4;
            else if (example==3) jmin=-1;
            else if (example==4) jmin=0;
            else if (example==5) jmin=-1;
            else if (example==6) jmin=-1;       //better convergence behaviour
        }
        //jmin = estimateMinimalLevel(example, c, d,d_);
    }
    else {
        jmin=atoi(argv[5]);
    }
    if (example==6) rhs_order=20;

    cout << "Initializing S-ADWAV, jmin = " << jmin << endl;

    Basis1D basis(d,d_,jmin);
    HelmholtzBilinearForm1D Bil(basis,c);
    Preconditioner1D P(basis);
    Compression1D Compr(basis);
    //MA A(Bil,P,Compr,0,2*8192,2*8192);
    MA A(Bil,P,Compr);
    RefSols_PDE_Realline1D<T> refsol;
    refsol.setExample(example, 1., 0, c);
    Function<T> rhs(refsol.rhs,refsol.sing_pts);
    RhsIntegral1D rhsintegral1d(basis, rhs, refsol.deltas, 25);
    Rhs F(rhsintegral1d,P);

    IndexSet<Index1D> InitialLambda;
    InitialLambda.insert(Index1D(jmin,1,XBSpline));

    S_Adwav s_adwav(basis, A, F, contraction, threshTol, cgTol, resTol, NumOfIterations, 2, 1e-2);
    cout << "... finished." << endl;

    Timer time;
    time.start();
    s_adwav.solve_cg(InitialLambda, refsol.H1norm());
    time.stop();
    cout << "S-ADWAV required " << time.elapsed() << " seconds real time" << endl;

    RhsIntegral1D rhsintegral1d_postproc(basis,rhs, refsol.deltas,60);
    Rhs F_postproc(rhsintegral1d_postproc,P);
    cout << "Postprocessing started." << endl;
    stringstream filename;
    filename << "s-adwav-realline-helmholtz1d-conv_" << example << "_" << d << "_" << d_
             << "_" << jmin << ".dat";
    assert(c==1);
    postprocessing_H1<T,Index1D, S_Adwav, MA, Rhs>(s_adwav, A, F_postproc, refsol.H1norm(),
                                                   filename.str().c_str());
    cout << "Postprocessing finished." << endl;

    stringstream plot_filename;
    plot_filename << "s-adwav-realline-helmholtz1d-plot_" << example << "_" << d << "_" << d_
                  << "_" << jmin << ".dat";
    cout << "Plot of solution started." << endl;
    plot<T, Basis1D, Preconditioner1D>(basis, s_adwav.solutions[NumOfIterations-1], P, refsol.u, refsol.d_u, -10., 10.,
         pow2i<T>(-5), plot_filename.str().c_str());
    cout << "Plot of solution finished." << endl;
    return 0;
}
Example #13
0
// union
IndexSet operator|(const IndexSet& s, const IndexSet& t) {
  IndexSet r = s;
  r.insert(t);
  return r;
}
//-----------------------------------------------------------------------------
void
RegularCutRefinement::compute_markers(std::vector<int>& refinement_markers,
                                      IndexSet& marked_edges,
                                      const Mesh& mesh,
                                      const MeshFunction<bool>& cell_markers)
{
  // Topological dimension
  const std::size_t D = mesh.topology().dim();

  // Create edge markers and initialize to false
  const std::size_t edges_per_cell = D + 1;
  std::vector<std::vector<bool> > edge_markers(mesh.num_cells());
  for (std::size_t i = 0; i < mesh.num_cells(); i++)
  {
    edge_markers[i].resize(edges_per_cell);
    for (std::size_t j = 0; j < edges_per_cell; j++)
      edge_markers[i][j] = false;
  }

  // Create index sets for marked cells
  IndexSet cells(mesh.num_cells());
  IndexSet marked_cells(mesh.num_cells());

  // Get bisection data
  const std::vector<std::size_t>* bisection_twins = NULL;
  if (mesh.data().exists("bisection_twins", D))
    bisection_twins = &(mesh.data().array("bisection_twins", D));

  // Iterate until no more cells are marked
  cells.fill();
  while (!cells.empty())
  {
    // Iterate over all cells in list
    for (std::size_t _i = 0; _i < cells.size(); _i++)
    {
      // Get cell index and create cell
      const std::size_t cell_index = cells[_i];
      const Cell cell(mesh, cell_index);

      // Count the number of marked edges
      const std::size_t num_marked = count_markers(edge_markers[cell_index]);

      // Check whether cell has a bisection twin
      std::size_t bisection_twin = cell_index;
      bool is_bisected = false;
      if (bisection_twins)
      {
        bisection_twin = (*bisection_twins)[cell_index];
        is_bisected = bisection_twin != cell_index;
      }

      // Get bisection edge
      std::size_t common_edge = 0;
      std::size_t bisection_edge = 0;
      if (is_bisected)
      {
        common_edge = find_common_edges(cell, mesh, bisection_twin).first;
        bisection_edge = find_bisection_edges(cell, mesh, bisection_twin).first;
      }

      // Decide if cell should be refined
      bool refine = false;
      refine = refine || cell_markers[cell_index];
      if (is_bisected)
        refine = refine || num_marked > 0;
      else
      {
        refine = refine || num_marked > 1;
        refine = refine || too_thin(cell, edge_markers[cell_index]);
      }

      // Skip cell if it should not be marked
      if (!refine)
        continue;

      // Iterate over edges
      for (EdgeIterator edge(cell); !edge.end(); ++edge)
      {
        // Skip edge if it is a bisected edge of a bisected cell
        if (is_bisected && edge.pos() == bisection_edge)
          continue;

        // Mark edge in current cell
        if (!edge_markers[cell_index][edge.pos()])
        {
          edge_markers[cell_index][edge.pos()] = true;
          marked_cells.insert(cell_index);
        }

        // Insert edge into set of marked edges but only if the edge
        // is not the common edge of a bisected cell in which case it
        // will later be removed and no new vertex be inserted...
        if (!is_bisected || edge.pos() != common_edge)
          marked_edges.insert(edge->index());

        // Iterate over cells sharing edge
        for (CellIterator neighbor(*edge); !neighbor.end(); ++neighbor)
        {
          // Get local edge number of edge relative to neighbor
          const std::size_t local_index = neighbor->index(*edge);

          // Mark edge for refinement
          if (!edge_markers[neighbor->index()][local_index])
          {
            edge_markers[neighbor->index()][local_index] = true;
            marked_cells.insert(neighbor->index());
          }
        }
      }
    }

    // Copy marked cells
    cells = marked_cells;
    marked_cells.clear();
  }

  // Extract which cells to refine and indices which edges to bisect
  refinement_markers.resize(mesh.num_cells());
  for (std::size_t i = 0; i < edge_markers.size(); i++)
  {
    // Count the number of marked edges
    const std::size_t num_marked = count_markers(edge_markers[i]);

    // Check if cell has been bisected before
    const bool is_bisected = bisection_twins && (*bisection_twins)[i] != i;

    // No refinement
    if (num_marked == 0)
      refinement_markers[i] = no_refinement;

    // Mark for bisection
    else if (num_marked == 1 && !is_bisected)
      refinement_markers[i] = extract_edge(edge_markers[i]);

    // Mark for regular refinement
    else if (num_marked == edges_per_cell && !is_bisected)
      refinement_markers[i] = regular_refinement;

    // Mark for bisection backtracking
    else if (num_marked == 2 && is_bisected)
      refinement_markers[i] = backtrack_bisection;

    // Mark for bisection backtracking and refinement
    else if (num_marked == edges_per_cell && is_bisected)
      refinement_markers[i] = backtrack_bisection_refine;

    // Sanity check
    else
      dolfin_error("RegularCutRefinement.cpp",
                   "compute marked edges",
                   "Unexpected number of edges marked");
  }
}
Example #15
0
void
TopologyGraph::createBoundary(unsigned graphNum, TopologyGraph::IndexVector& output) const
{
    // nothing to do - bail
    if (_verts.empty() || graphNum+1 > _maxGraphID)
        return;

    // graph ID is one more than the graph number passed in:
    unsigned graphID = graphNum + 1u;

    // Find the starting point (vertex with minimum Y) for this graph ID.
    // By the nature of disconnected graphs, that start point is all we need
    // to ensure we are walking a single connected mesh.
    Index vstart = _verts.end();
    for (VertexSet::const_iterator vert = _verts.begin(); vert != _verts.end(); ++vert)
    {
        if (vert->_graphID == graphID) 
        {
            if (vstart == _verts.end() || vert->y() < vstart->y())
            {
                vstart = vert;
            }
        }
    }

    // couldn't find a start point - bail (should never happen)
    if (vstart == _verts.end())
        return;

    // starting with the minimum-Y vertex (which is guaranteed to be in the boundary)
    // traverse the outside of the point set. Do this by sorting all the edges by
    // their angle relative to the vector from the previous point. The "leftest" turn
    // represents the edge connecting the current point to the next boundary point.
    // Thusly we walk the boundary counterclockwise until we return to the start point.
    Index vptr = vstart;
    Index vptr_prev = _verts.end();

    IndexSet visited;

    while( true )
    {
        // store this vertex in the result set:
        output.push_back( vptr );

        // pull up the next 2D vertex (XY plane):
        osg::Vec2d vert ( vptr->x(), vptr->y() );

        // construct the "base" vector that points from the previous 
        // point to the current point; or to +X in the initial case
        osg::Vec2d base;
        if ( vptr_prev == _verts.end() )
        {
            base.set(1, 0);
        }
        else
        {
            base = vert - osg::Vec2d( vptr_prev->x(), vptr_prev->y() );
            base.normalize();
        }
            
        // pull up the edge set for this vertex:
        EdgeMap::const_iterator ei = _edgeMap.find(vptr);
        if (ei == _edgeMap.end())
            continue; // should be impossible

        const IndexSet& edges = ei->second;

        // find the edge with the minimum delta angle to the base vector
        double bestScore = -DBL_MAX;
        Index  bestEdge  = _verts.end();
        
        //OE_NOTICE << "VERTEX (" << 
        //    vptr->x() << ", " << vptr->y() << ", "
        //    << ") has " << edges.size() << " edges..."
        //    << std::endl;

        unsigned possibleEdges = 0u;

        for( IndexSet::iterator e = edges.begin(); e != edges.end(); ++e )
        {
            // don't go back from whence we just came
            if ( *e == vptr_prev )
                continue;

            // never return to a vert we've already visited
            if ( visited.find(*e) != visited.end() )
                continue;

            ++possibleEdges;

            // calculate the angle between the base vector and the current edge:
            osg::Vec2d edgeVert( (*e)->x(), (*e)->y() );
            osg::Vec2d edge = edgeVert - vert;
            edge.normalize();

            double cross = base.x()*edge.y() - base.y()*edge.x();
            double dot   = base * edge;

            double score;
            if (cross <= 0.0)
                score = 1.0-dot; // [0..2]
            else
                score = dot-1.0; // [-2..0]

            //OE_NOTICE << "   check: " << (*e)->x() << ", " << (*e)->y() << std::endl;
            //OE_NOTICE << "   base = " << base.x() << ", " << base.y() << std::endl;
            //OE_NOTICE << "   edge = " << edge.x() << ", " << edge.y() << std::endl;
            //OE_NOTICE << "   crs = " << cross << ", dot = " << dot << ", score = " << score << std::endl;
            
            if (score > bestScore)
            {
                bestScore = score;
                bestEdge = *e;
            }
        }

        if ( bestEdge == _verts.end() )
        {
            // this should never happen
            // but sometimes does anyway
            OE_WARN << LC << getName() << " - Illegal state - reached a dead end during boundary detection. Vertex (" 
                << vptr->x() << ", " << vptr->y() << ") has " << possibleEdges << " possible edges.\n"
                << std::endl;
            break;
        }

        // store the previous:
        vptr_prev = vptr;

        // follow the chosen edge around the outside of the geometry:
        //OE_DEBUG << "   BEST SCORE = " << bestScore << std::endl;
        vptr = bestEdge;

        // record this vert so we don't visit it again.
        visited.insert( vptr );

        // once we make it all the way around, we're done:
        if ( vptr == vstart )
            break;
    }
}
Example #16
0
//------------------------------build_ifg_virtual------------------------------
// Actually build the interference graph.  Uses virtual registers only, no
// physical register masks.  This allows me to be very aggressive when
// coalescing copies.  Some of this aggressiveness will have to be undone
// later, but I'd rather get all the copies I can now (since unremoved copies
// at this point can end up in bad places).  Copies I re-insert later I have
// more opportunity to insert them in low-frequency locations.
void PhaseChaitin::build_ifg_virtual( ) {

  // For all blocks (in any order) do...
  for( uint i=0; i<_cfg._num_blocks; i++ ) {
    Block *b = _cfg._blocks[i];
    IndexSet *liveout = _live->live(b);

    // The IFG is built by a single reverse pass over each basic block.
    // Starting with the known live-out set, we remove things that get
    // defined and add things that become live (essentially executing one
    // pass of a standard LIVE analysis). Just before a Node defines a value
    // (and removes it from the live-ness set) that value is certainly live.
    // The defined value interferes with everything currently live.  The
    // value is then removed from the live-ness set and it's inputs are
    // added to the live-ness set.
    for( uint j = b->end_idx() + 1; j > 1; j-- ) {
      Node *n = b->_nodes[j-1];

      // Get value being defined
      uint r = n2lidx(n);

      // Some special values do not allocate
      if( r ) {

        // Remove from live-out set
        liveout->remove(r);

        // Copies do not define a new value and so do not interfere.
        // Remove the copies source from the liveout set before interfering.
        uint idx = n->is_Copy();
        if( idx ) liveout->remove( n2lidx(n->in(idx)) );

        // Interfere with everything live
        interfere_with_live( r, liveout );
      }

      // Make all inputs live
      if( !n->is_Phi() ) {      // Phi function uses come from prior block
        for( uint k = 1; k < n->req(); k++ )
          liveout->insert( n2lidx(n->in(k)) );
      }

      // 2-address instructions always have the defined value live
      // on entry to the instruction, even though it is being defined
      // by the instruction.  We pretend a virtual copy sits just prior
      // to the instruction and kills the src-def'd register.
      // In other words, for 2-address instructions the defined value
      // interferes with all inputs.
      uint idx;
      if( n->is_Mach() && (idx = n->as_Mach()->two_adr()) ) {
        const MachNode *mach = n->as_Mach();
        // Sometimes my 2-address ADDs are commuted in a bad way.
        // We generally want the USE-DEF register to refer to the
        // loop-varying quantity, to avoid a copy.
        uint op = mach->ideal_Opcode();
        // Check that mach->num_opnds() == 3 to ensure instruction is
        // not subsuming constants, effectively excludes addI_cin_imm
        // Can NOT swap for instructions like addI_cin_imm since it
        // is adding zero to yhi + carry and the second ideal-input
        // points to the result of adding low-halves.
        // Checking req() and num_opnds() does NOT distinguish addI_cout from addI_cout_imm
        if( (op == Op_AddI && mach->req() == 3 && mach->num_opnds() == 3) &&
            n->in(1)->bottom_type()->base() == Type::Int &&
            // See if the ADD is involved in a tight data loop the wrong way
            n->in(2)->is_Phi() &&
            n->in(2)->in(2) == n ) {
          Node *tmp = n->in(1);
          n->set_req( 1, n->in(2) );
          n->set_req( 2, tmp );
        }
        // Defined value interferes with all inputs
        uint lidx = n2lidx(n->in(idx));
        for( uint k = 1; k < n->req(); k++ ) {
          uint kidx = n2lidx(n->in(k));
          if( kidx != lidx )
            _ifg->add_edge( r, kidx );
        }
      }
    } // End of forall instructions in block
  } // End of forall blocks
}
Example #17
0
void buildModChain(FHEcontext &context, long nLevels, long nDgts)
{
#ifdef NO_HALF_SIZE_PRIME
    long nPrimes = nLevels;
#else
    long nPrimes = (nLevels+1)/2;
    // The first prime should be of half the size. The code below tries to find
    // a prime q0 of this size where q0-1 is divisible by 2^k * m for some k>1.
    // Then if the plaintext space is a power of two it tries to choose the
    // second prime q1 so that q0*q1 = 1 mod ptxtSpace. All the other primes are
    // chosen so that qi-1 is divisible by 2^k * m for as large k as possible.
    long twoM;
    if (ALT_CRT)
        twoM = 2;
    else
        twoM = 2 * context.zMStar.getM();

    long bound = (1L << (context.bitsPerLevel-1));
    while (twoM < bound/(2*context.bitsPerLevel))
        twoM *= 2; // divisible by 2^k * m  for a larger k

    bound = bound - (bound % twoM) +1; // = 1 mod 2m
    long q0 = context.AddPrime(bound, twoM, false, !ALT_CRT);
    // add next prime to chain

    assert(q0 != 0);
    nPrimes--;
#endif

    // Choose the next primes as large as possible
    if (nPrimes>0) AddPrimesByNumber(context, nPrimes);

    // calculate the size of the digits

    if (nDgts > nPrimes) nDgts = nPrimes; // sanity checks
    if (nDgts <= 0) nDgts = 1;
    context.digits.resize(nDgts); // allocate space

    IndexSet s1;
    double sizeSoFar = 0.0;
    double maxDigitSize = 0.0;
    if (nDgts>1) { // we break ciphetext into a few digits when key-switching
        double dsize = context.logOfProduct(context.ctxtPrimes)/nDgts; // estimate
        double target = dsize-(context.bitsPerLevel/3.0);
        long idx = context.ctxtPrimes.first();
        for (long i=0; i<nDgts-1; i++) { // compute next digit
            IndexSet s;
            while (idx <= context.ctxtPrimes.last() && (empty(s)||sizeSoFar<target)) {
                s.insert(idx);
                sizeSoFar += log((double)context.ithPrime(idx));
                idx = context.ctxtPrimes.next(idx);
            }
            assert (!empty(s));
            context.digits[i] = s;
            s1.insert(s);
            double thisDigitSize = context.logOfProduct(s);
            if (maxDigitSize < thisDigitSize) maxDigitSize = thisDigitSize;
            target += dsize;
        }
        IndexSet s = context.ctxtPrimes / s1; // all the remaining primes
        if (!empty(s)) {
            context.digits[nDgts-1] = s;
            double thisDigitSize = context.logOfProduct(s);
            if (maxDigitSize < thisDigitSize) maxDigitSize = thisDigitSize;
        }
        else { // If last digit is empty, remove it
            nDgts--;
            context.digits.resize(nDgts);
        }
    }
    else {
        maxDigitSize = context.logOfProduct(context.ctxtPrimes);
        context.digits[0] = context.ctxtPrimes;
    }

    // Add primes to the chain for the P factor of key-switching
    long p2r = (context.rcData.alMod)? context.rcData.alMod->getPPowR()
               : context.alMod.getPPowR();
    double sizeOfSpecialPrimes
        = maxDigitSize + log(nDgts/32.0)/2 + log(context.stdev *2)
          + log((double)p2r);

    AddPrimesBySize(context, sizeOfSpecialPrimes, true);
}
Example #18
0
void PhaseLive::compute(uint maxlrg) {
  _maxlrg   = maxlrg;
  _worklist = new (_arena) Block_List();

  // Init the sparse live arrays.  This data is live on exit from here!
  // The _live info is the live-out info.
  _live = (IndexSet*)_arena->Amalloc(sizeof(IndexSet)*_cfg._num_blocks);
  uint i;
  for( i=0; i<_cfg._num_blocks; i++ ) {
    _live[i].initialize(_maxlrg);
  }

  // Init the sparse arrays for delta-sets.  
  ResourceMark rm;              // Nuke temp storage on exit

  // Does the memory used by _defs and _deltas get reclaimed?  Does it matter?  TT

  // Array of values defined locally in blocks
  _defs = NEW_RESOURCE_ARRAY(IndexSet,_cfg._num_blocks);
  for( i=0; i<_cfg._num_blocks; i++ ) {
    _defs[i].initialize(_maxlrg);
  }

  // Array of delta-set pointers, indexed by block pre_order-1.
  _deltas = NEW_RESOURCE_ARRAY(IndexSet*,_cfg._num_blocks);
  memset( _deltas, 0, sizeof(IndexSet*)* _cfg._num_blocks);

  _free_IndexSet = NULL;

  // Blocks having done pass-1
  VectorSet first_pass(Thread::current()->resource_area());

  // Outer loop: must compute local live-in sets and push into predecessors.
  uint iters = _cfg._num_blocks;        // stat counters
  for( uint j=_cfg._num_blocks; j>0; j-- ) {
    Block *b = _cfg._blocks[j-1];

    // Compute the local live-in set.  Start with any new live-out bits.
    IndexSet *use = getset( b );
    IndexSet *def = &_defs[b->_pre_order-1];
    uint i;
    for( i=b->_nodes.size(); i>1; i-- ) {
      Node *n = b->_nodes[i-1];
      if( n->is_Phi() ) break;
      // BoxNodes keep their input alive as long as their uses.  If we
      // see a BoxNode then make its input live to the Root block.
      // Because we are solving LIVEness, the input now becomes live
      // over the whole procedure, interferencing with everything else
      // and getting a private unshared stack slot.  YeeeHaw!
      MachNode *mach = n->is_Mach();
      if( mach && mach->ideal_Opcode() == Op_Box ) 
        getset(_cfg._broot)->insert( _names[n->in(1)->_idx] );

      uint r = _names[n->_idx];
      def->insert( r );
      use->remove( r );
      uint cnt = n->req();
      for( uint k=1; k<cnt; k++ ) {
        Node *nk = n->in(k);
        uint nkidx = nk->_idx;
        if( _cfg._bbs[nkidx] != b )
          use->insert( _names[nkidx] );
      }
    }
    // Remove anything defined by Phis and the block start instruction
    for( uint k=i; k>0; k-- ) {
      uint r = _names[b->_nodes[k-1]->_idx];
      def->insert( r );
      use->remove( r );
    }

    // Push these live-in things to predecessors
    for( uint l=1; l<b->num_preds(); l++ ) {
      Block *p = _cfg._bbs[b->pred(l)->_idx];
      add_liveout( p, use, first_pass );

      // PhiNode uses go in the live-out set of prior blocks.
      for( uint k=i; k>0; k-- ) 
        add_liveout( p, _names[b->_nodes[k-1]->in(l)->_idx], first_pass );
    }
    freeset( b );
    first_pass.set(b->_pre_order);
    
    // Inner loop: blocks that picked up new live-out values to be propagated
    while( _worklist->size() ) {
        // !!!!!
// #ifdef ASSERT
      iters++;
// #endif
      Block *b = _worklist->pop();
      IndexSet *delta = getset(b);
      assert( delta->count(), "missing delta set" );

      // Add new-live-in to predecessors live-out sets
      for( uint l=1; l<b->num_preds(); l++ ) 
        add_liveout( _cfg._bbs[b->pred(l)->_idx], delta, first_pass );

      freeset(b);
    } // End of while-worklist-not-empty

  } // End of for-all-blocks-outer-loop

  // We explicitly clear all of the IndexSets which we are about to release.
  // This allows us to recycle their internal memory into IndexSet's free list.

  for( i=0; i<_cfg._num_blocks; i++ ) {
    _defs[i].clear();
    if (_deltas[i]) {
      // Is this always true?
      _deltas[i]->clear();
    }
  }
  IndexSet *free = _free_IndexSet;
  while (free != NULL) {
    IndexSet *temp = free;
    free = free->next();
    temp->clear();
  }

}
Example #19
0
int main(int argc, char *argv[]) 
{
  if (argc<2) {
    cout << "\nUsage: " << argv[0] << " L [c=2 w=64 k=80 d=1]" << endl;
    cout << "  L is the number of levels\n";
    cout << "  optional c is number of columns in the key-switching matrices (default=2)\n";
    cout << "  optional w is Hamming weight of the secret key (default=64)\n";
    cout << "  optional k is the security parameter (default=80)\n";
    cout << "  optional d specifies GF(2^d) arithmetic (default=1, must be <=16)\n";
    //    cout << "  k is the security parameter\n";
    //    cout << "  m determines the ring mod Phi_m(X)" << endl;
    cout << endl;
    exit(0);
  }
  cout.unsetf(ios::floatfield);
  cout.precision(4);

  long L = atoi(argv[1]);
  long c = 2;
  long w = 64;
  long k = 80;
  long d = 1;
  if (argc>2) c = atoi(argv[2]);
  if (argc>3) w = atoi(argv[3]);
  if (argc>4) k = atoi(argv[4]);
  if (argc>5) d = atoi(argv[5]);

  if (d>16) Error("d cannot be larger than 16\n");

  cout << "\nTesting FHE with parameters L="<<L
       << ", c="<<c<<", w="<<w<<", k="<<k<<", d="<<d<< endl;

  // get a lower-bound on the parameter N=phi(m):
  // 1. Empirically, we use ~20-bit small primes in the modulus chain (the main
  //    constraints is that 2m must divide p-1 for every prime p). The first
  //    prime is larger, a 40-bit prime. (If this is a 32-bit machine then we
  //    use two 20-bit primes instead.)
  // 2. With L levels, the largest modulus for "fresh ciphertexts" has size
  //          q0 ~ p0 * p^{L} ~ 2^{40+20L}
  // 3. We break each ciphertext into upto c digits, do each digit is as large
  //    as    D=2^{(40+20L)/c}
  // 4. The added noise variance term from the key-switching operation is
  //    c*N*sigma^2*D^2, and this must be mod-switched down to w*N (so it is
  //    on part with the added noise from modulus-switching). Hence the ratio
  //    P that we use for mod-switching must satisfy c*N*sigma^2*D^2/P^2<w*N,
  //    or    P > sqrt(c/w) * sigma * 2^{(40+20L)/c}
  // 5. With this extra P factor, the key-switching matrices are defined
  //    relative to a modulus of size
  //          Q0 = q0*P ~ sqrt{c/w} sigma 2^{(40+20L)(1+1/c)}
  // 6. To get k-bit security we need N>log(Q0/sigma)(k+110)/7.2, i.e. roughly
  //          N > (40+20L)(1+1/c)(k+110) / 7.2

  long ptxtSpace = 2;
  double cc = 1.0+(1.0/(double)c);
  long N = (long) ceil((pSize*L+p0Size)*cc*(k+110)/7.2);
  cout << "  bounding phi(m) > " << N << endl;

#if 0  // A small m for debugging purposes
  long m = 15;
#else
  // pre-computed values of [phi(m),m,d]
  long ms[][4] = {
    //phi(m)  m  ord(2) c_m*1000
    { 1176,  1247, 28,  3736},
    { 1936,  2047, 11,  3870},
    { 2880,  3133, 24,  3254},
    { 4096,  4369, 16,  3422},
    { 5292,  5461, 14,  4160},
    { 5760,  8435, 24,  8935},
    { 8190,  8191, 13,  1273},
    {10584, 16383, 14,  8358},
    {10752, 11441, 48,  3607},
    {12000, 13981, 20,  2467},
    {11520, 15665, 24, 14916},
    {14112, 18415, 28, 11278},
    {15004, 15709, 22,  3867},
    {15360, 20485, 24, 12767},
 // {16384, 21845, 16, 12798},
    {17208 ,21931, 24, 18387},
    {18000, 18631, 25,  4208},
    {18816, 24295, 28, 16360},
    {19200, 21607, 40, 35633},
    {21168, 27305, 28, 15407},
    {23040, 23377, 48,  5292},
    {24576, 24929, 48,  5612},
    {27000, 32767, 15, 20021},
    {31104, 31609, 71,  5149},
    {42336, 42799, 21,  5952},
    {46080, 53261, 24, 33409},
    {49140, 57337, 39,  2608},
    {51840, 59527, 72, 21128},
    {61680, 61681, 40,  1273},
    {65536, 65537, 32,  1273},
    {75264, 82603, 56, 36484},
    {84672, 92837, 56, 38520}
  };

#if 0

  for (long i = 0; i < 25; i++) {
    long m = ms[i][1];
    PAlgebra alg(m);
    alg.printout();
    cout << "\n";
    // compute phi(m) directly
    long phim = 0;
    for (long j = 0; j < m; j++)
      if (GCD(j, m) == 1) phim++;

    if (phim != alg.phiM()) cout << "ERROR\n";
  }

  exit(0);


#endif



  // find the first m satisfying phi(m)>=N and d | ord(2) in Z_m^*
  long m = 0;
  for (unsigned i=0; i<sizeof(ms)/sizeof(long[3]); i++) 
    if (ms[i][0]>=N && (ms[i][2] % d) == 0) {
      m = ms[i][1];
      c_m = 0.001 * (double) ms[i][3];
      break;
    }
  if (m==0) Error("Cannot support this L,d combination");
#endif
  //  m = 257;
  FHEcontext context(m);
#if 0
  context.stdev = to_xdouble(0.5); // very low error
#endif
  activeContext = &context; // Mark this as the "current" context

  context.zMstar.printout();
  cout << endl;


  // Set the modulus chain

#if 1
  // The first 1-2 primes of total p0size bits
  #if (NTL_SP_NBITS > p0Size)
    AddPrimesByNumber(context, 1, 1UL<<p0Size); // add a single prime
  #else
    AddPrimesByNumber(context, 2, 1UL<<(p0Size/2)); // add two primes
  #endif
#endif

  // The next L primes, as small as possible
  AddPrimesByNumber(context, L);

  ZZ productOfCtxtPrimes = context.productOfPrimes(context.ctxtPrimes);
  double productSize = context.logOfProduct(context.ctxtPrimes);

  // might as well test that the answer is roughly correct
  cout << "  context.logOfProduct(...)-log(context.productOfPrimes(...)) = "
       << productSize-log(productOfCtxtPrimes) << endl;

  // calculate the size of the digits

  context.digits.resize(c);
  IndexSet s1;
#if 0
  for (long i=0; i<c-1; i++) context.digits[i] = IndexSet(i,i);
  context.digits[c-1] = context.ctxtPrimes / IndexSet(0,c-2);
  AddPrimesByNumber(context, 2, 1, true);
#else
  double sizeSoFar = 0.0;
  double maxDigitSize = 0.0;
  if (c>1) {   // break ciphetext into a few digits
    double dsize = productSize/c;  // initial estimate
    double target = dsize-(pSize/3.0);
    long idx = context.ctxtPrimes.first();
    for (long i=0; i<c-1; i++) { // compute next digit
      IndexSet s;
      while (idx <= context.ctxtPrimes.last() && sizeSoFar < target) {
        s.insert(idx);
	sizeSoFar += log((double)context.ithPrime(idx));
	idx = context.ctxtPrimes.next(idx);
      }
      context.digits[i] = s;
      s1.insert(s);
      double thisDigitSize = context.logOfProduct(s);
      if (maxDigitSize < thisDigitSize) maxDigitSize = thisDigitSize;
      cout << "  digit #"<<i+1<< " " <<s << ": size " << thisDigitSize << endl;
      target += dsize;
    }
    IndexSet s = context.ctxtPrimes / s1; // all the remaining primes
    context.digits[c-1] = s;
    double thisDigitSize = context.logOfProduct(s);
    if (maxDigitSize < thisDigitSize) maxDigitSize = thisDigitSize;
    cout << "  digit #"<<c<< " " <<s << ": size " << thisDigitSize << endl;
  }
  else { 
    maxDigitSize = context.logOfProduct(context.ctxtPrimes);
    context.digits[0] = context.ctxtPrimes;
  }

  // Add primes to the chain for the P factor of key-switching
  double sizeOfSpecialPrimes 
    = maxDigitSize + log(c/(double)w)/2 + log(context.stdev *2);

  AddPrimesBySize(context, sizeOfSpecialPrimes, true);
#endif

  cout << "* ctxtPrimes: " << context.ctxtPrimes 
       << ", log(q0)=" << context.logOfProduct(context.ctxtPrimes) << endl;
  cout << "* specialPrimes: " << context.specialPrimes
       << ", log(P)=" << context.logOfProduct(context.specialPrimes) << endl;

  for (long i=0; i<context.numPrimes(); i++) {
    cout << "  modulus #" << i << " " << context.ithPrime(i) << endl;
  }
  cout << endl;

  setTimersOn();
  const ZZX& PhimX = context.zMstar.PhimX(); // The polynomial Phi_m(X)
  long phim = context.zMstar.phiM();         // The integer phi(m)
  FHESecKey secretKey(context);
  const FHEPubKey& publicKey = secretKey;

#if 0 // Debug mode: use sk=1,2
  DoubleCRT newSk(to_ZZX(2), context);
  long id1 = secretKey.ImportSecKey(newSk, 64, ptxtSpace);
  newSk -= 1;
  long id2 = secretKey.ImportSecKey(newSk, 64, ptxtSpace);
#else
  long id1 = secretKey.GenSecKey(w,ptxtSpace); // A Hamming-weight-w secret key
  long id2 = secretKey.GenSecKey(w,ptxtSpace); // A second Hamming-weight-w secret key
#endif

  ZZX zero = to_ZZX(0);
//  Ctxt zeroCtxt(publicKey);

  /******************************************************************/
  /**                      TESTS BEGIN HERE                       ***/
  /******************************************************************/


  cout << "ptxtSpace = " << ptxtSpace << endl;

  GF2X G;          // G is the AES polynomial, G(X)= X^8 +X^4 +X^3 +X +1
  SetCoeff(G,8); SetCoeff(G,4); SetCoeff(G,3); SetCoeff(G,1); SetCoeff(G,0);
  GF2X X;
  SetX(X);
  
#if 1
  // code for rotations...

  {
    GF2X::HexOutput = 1;
    
    const PAlgebra& al = context.zMstar;
    const PAlgebraModTwo& al2 = context.modTwo;

    long ngens = al.numOfGens();
    long nslots = al.NSlots();
    DoubleCRT tmp(context);

    vector< vector< DoubleCRT > > maskTable;

    maskTable.resize(ngens);
    for (long i = 0; i < ngens; i++) {
      if (i==0 && al.SameOrd(i)) continue;
      long ord = al.OrderOf(i);
      maskTable[i].resize(ord+1, tmp);
      for (long j = 0; j <= ord; j++) {
        // initialize the mask that is 1 whenever
        // the ith coordinate is at least j

        vector<GF2X> maps, alphas, betas;

        al2.mapToSlots(maps, G); // Change G to X to get bits in the slots
        alphas.resize(nslots);

        for (long k = 0; k < nslots; k++) 
          if (coordinate(al, i, k) >= j)
               alphas[k] = 1;
          else alphas[k] = 0;

       GF2X ptxt;
       al2.embedInSlots(ptxt, alphas, maps);

       // Sanity-check, make sure that encode/decode works as expected
       al2.decodePlaintext(betas, ptxt, G, maps);
       for (long k = 0; k < nslots; k++) {
	 if (alphas[k] != betas[k]) {
	   cout << " Mask computation failed, i="<<i<<", j="<<j<<"\n";
	   return 0;
	 }
       }
       maskTable[i][j] = to_ZZX(ptxt);
      }
    }

  vector<GF2X> maps;
  al2.mapToSlots(maps, G);

  vector<GF2X> alphas(nslots);
  for (long i=0; i < nslots; i++) 
    random(alphas[i], 8); // random degree-7 polynomial mod 2

  for (long amt = 0; amt < 20; amt++) {

    cout << ".";

     GF2X ptxt;
     al2.embedInSlots(ptxt, alphas, maps);

     DoubleCRT pp(context);
     pp = to_ZZX(ptxt);

     rotate(pp, amt, maskTable);

     GF2X ptxt1 = to_GF2X(to_ZZX(pp));

     vector<GF2X> betas;
     al2.decodePlaintext(betas, ptxt1, G, maps);

     for (long i = 0; i < nslots; i++) {
       if (alphas[i] != betas[(i+amt)%nslots]) {
	 cout << " amt="<<amt<<" oops\n";
          return 0;
       }
     }
   }

   cout << "\n";

#if 0
  long ord0 = al.OrderOf(0);

  for (long i = 0; i < nslots; i++) {
    cout << alphas[i] << " ";
    if ((i+1) % (nslots/ord0) == 0) cout << "\n";
  }
 
  cout << "\n\n";
  cout << betas.size() << "\n";

  for (long i = 0; i < nslots; i++) {
    cout << betas[i] << " ";
    if ((i+1) % (nslots/ord0) == 0) cout << "\n";
  }
#endif


  return 0;
  

  }


#endif

  // an initial sanity check on noise estimates,
  // comparing the estimated variance to the actual average
  cout << "pk:"; checkCiphertext(publicKey.pubEncrKey, zero, secretKey);

  ZZX ptxt[6]; // first four are plaintext, last two are constants
  std::vector<Ctxt> ctxt(4, Ctxt(publicKey));

  // Initialize the plaintext and constants to random 0-1 polynomials
  for (size_t j=0; j<6; j++) {
    ptxt[j].rep.SetLength(phim);
    for (long i = 0; i < phim; i++)
      ptxt[j].rep[i] = RandomBnd(ptxtSpace);
    ptxt[j].normalize();

    if (j<4) { 
      publicKey.Encrypt(ctxt[j], ptxt[j], ptxtSpace);
      cout << "c"<<j<<":"; checkCiphertext(ctxt[j], ptxt[j], secretKey);
    }
  }

  // perform upto 2L levels of computation, each level computing:
  //    1. c0 += c1
  //    2. c1 *= c2            // L1' = max(L1,L2)+1
  //    3. c1.reLinearlize
  //    4. c2 *= p4
  //    5. c2.automorph(k)     // k is the first generator of Zm^* /(2)
  //    6. c2.reLinearlize
  //    7. c3 += p5
  //    8. c3 *= c0            // L3' = max(L3,L0,L1)+1
  //    9. c2 *= c3            // L2' = max(L2,L0+1,L1+1,L3+1)+1
  //   10. c0 *= c0            // L0' = max(L0,L1)+1
  //   11. c0.reLinearlize
  //   12. c2.reLinearlize
  //   13. c3.reLinearlize
  //
  // The levels of the four ciphertexts behave as follows:
  // 0, 0, 0, 0  =>  1, 1, 2, 1  =>  2, 3, 3, 2
  //             =>  4, 4, 5, 4  =>  5, 6, 6, 5
  //             =>  7, 7, 8, 7  =>  8,,9, 9, 10  => [...]
  //
  // We perform the same operations on the plaintext, and after each operation
  // we check that decryption still works, and print the curretn modulus and
  // noise estimate. We stop when we get the first decryption error, or when
  // we reach 2L levels (which really should not happen).

  zz_pContext zzpc;
  zz_p::init(ptxtSpace);
  zzpc.save();
  const zz_pXModulus F = to_zz_pX(PhimX);
  long g = context.zMstar.ZmStarGen(0); // the first generator in Zm*
  zz_pX x2g(g, 1);
  zz_pX p2;

  // generate a key-switching matrix from s(X^g) to s(X)
  secretKey.GenKeySWmatrix(/*powerOfS= */  1,
			   /*powerOfX= */  g,
			   0, 0,
			   /*ptxtSpace=*/  ptxtSpace);

  // generate a key-switching matrix from s^2 to s
  secretKey.GenKeySWmatrix(/*powerOfS= */  2,
			   /*powerOfX= */  1,
			   0, 0,
			   /*ptxtSpace=*/  ptxtSpace);

  // generate a key-switching matrix from s^3 to s
  secretKey.GenKeySWmatrix(/*powerOfS= */  3,
			   /*powerOfX= */  1,
			   0, 0,
			   /*ptxtSpace=*/  ptxtSpace);

  for (long lvl=0; lvl<2*L; lvl++) {
    cout << "=======================================================\n";
    ctxt[0] += ctxt[1];
    ptxt[0] += ptxt[1];
    PolyRed(ptxt[0], ptxtSpace, true);
    cout << "c0+=c1:  "; checkCiphertext(ctxt[0], ptxt[0], secretKey);

    ctxt[1].multiplyBy(ctxt[2]);
    ptxt[1] = (ptxt[1] * ptxt[2]) % PhimX;
    PolyRed(ptxt[1], ptxtSpace, true);
    cout << "c1*=c2:  "; checkCiphertext(ctxt[1], ptxt[1], secretKey);

    ctxt[2].multByConstant(ptxt[4]);
    ptxt[2] = (ptxt[2] * ptxt[4]) % PhimX;
    PolyRed(ptxt[2], ptxtSpace, true);
    cout <<  "c2*=p4:  "; checkCiphertext(ctxt[2], ptxt[2], secretKey);

    ctxt[2] >>= g;
    zzpc.restore();
    p2 = to_zz_pX(ptxt[2]);
    CompMod(p2, p2, x2g, F);
    ptxt[2] = to_ZZX(p2);
    cout << "c2>>="<<g<<":"; checkCiphertext(ctxt[2], ptxt[2], secretKey);

    ctxt[2].reLinearize();
    cout << "c2.relin:"; checkCiphertext(ctxt[2], ptxt[2], secretKey);

    ctxt[3].addConstant(ptxt[5]);
    ptxt[3] += ptxt[5];
    PolyRed(ptxt[3], ptxtSpace, true);
    cout << "c3+=p5:  "; checkCiphertext(ctxt[3], ptxt[3], secretKey);

    ctxt[3].multiplyBy(ctxt[0]);
    ptxt[3] = (ptxt[3] * ptxt[0]) % PhimX;
    PolyRed(ptxt[3], ptxtSpace, true);
    cout << "c3*=c0:  ";    checkCiphertext(ctxt[3], ptxt[3], secretKey);

    ctxt[0].square();
    ptxt[0] = (ptxt[0] * ptxt[0]) % PhimX;
    PolyRed(ptxt[0], ptxtSpace, true);
    cout << "c0*=c0:  ";    checkCiphertext(ctxt[0], ptxt[0], secretKey);

    ctxt[2].multiplyBy(ctxt[3]);
    ptxt[2] = (ptxt[2] * ptxt[3]) % PhimX;
    PolyRed(ptxt[2], ptxtSpace, true);
    cout << "c2*=c3:  ";    checkCiphertext(ctxt[2], ptxt[2], secretKey);
  }
  /******************************************************************/
  /**                       TESTS END HERE                        ***/
  /******************************************************************/
  cout << endl;
  return 0;
}
Example #20
0
//------------------------------insert_copies----------------------------------
void PhaseAggressiveCoalesce::insert_copies( Matcher &matcher ) {
  // We do LRGs compressing and fix a liveout data only here since the other
  // place in Split() is guarded by the assert which we never hit.
  _phc.compress_uf_map_for_nodes();
  // Fix block's liveout data for compressed live ranges.
  for(uint lrg = 1; lrg < _phc._maxlrg; lrg++ ) {
    uint compressed_lrg = _phc.Find(lrg);
    if( lrg != compressed_lrg ) {
      for( uint bidx = 0; bidx < _phc._cfg._num_blocks; bidx++ ) {
        IndexSet *liveout = _phc._live->live(_phc._cfg._blocks[bidx]);
        if( liveout->member(lrg) ) {
          liveout->remove(lrg);
          liveout->insert(compressed_lrg);
        }
      }
    }
  }

  // All new nodes added are actual copies to replace virtual copies.
  // Nodes with index less than '_unique' are original, non-virtual Nodes.
  _unique = C->unique();

  for( uint i=0; i<_phc._cfg._num_blocks; i++ ) {
    Block *b = _phc._cfg._blocks[i];
    uint cnt = b->num_preds();  // Number of inputs to the Phi

    for( uint l = 1; l<b->_nodes.size(); l++ ) {
      Node *n = b->_nodes[l];

      // Do not use removed-copies, use copied value instead
      uint ncnt = n->req();
      for( uint k = 1; k<ncnt; k++ ) {
        Node *copy = n->in(k);
        uint cidx = copy->is_Copy();
        if( cidx ) {
          Node *def = copy->in(cidx);
          if( _phc.Find(copy) == _phc.Find(def) )
            n->set_req(k,def);
        }
      }

      // Remove any explicit copies that get coalesced.
      uint cidx = n->is_Copy();
      if( cidx ) {
        Node *def = n->in(cidx);
        if( _phc.Find(n) == _phc.Find(def) ) {
          n->replace_by(def);
          n->set_req(cidx,NULL);
          b->_nodes.remove(l);
          l--;
          continue;
        }
      }

      if( n->is_Phi() ) {
        // Get the chosen name for the Phi
        uint phi_name = _phc.Find( n );
        // Ignore the pre-allocated specials
        if( !phi_name ) continue;
        // Check for mismatch inputs to Phi
        for( uint j = 1; j<cnt; j++ ) {
          Node *m = n->in(j);
          uint src_name = _phc.Find(m);
          if( src_name != phi_name ) {
            Block *pred = _phc._cfg._bbs[b->pred(j)->_idx];
            Node *copy;
            assert(!m->is_Con() || m->is_Mach(), "all Con must be Mach");
            // Rematerialize constants instead of copying them
            if( m->is_Mach() && m->as_Mach()->is_Con() &&
                m->as_Mach()->rematerialize() ) {
              copy = m->clone();
              // Insert the copy in the predecessor basic block
              pred->add_inst(copy);
              // Copy any flags as well
              _phc.clone_projs( pred, pred->end_idx(), m, copy, _phc._maxlrg );
            } else {
              const RegMask *rm = C->matcher()->idealreg2spillmask[m->ideal_reg()];
              copy = new (C) MachSpillCopyNode(m,*rm,*rm);
              // Find a good place to insert.  Kinda tricky, use a subroutine
              insert_copy_with_overlap(pred,copy,phi_name,src_name);
            }
            // Insert the copy in the use-def chain
            n->set_req( j, copy );
            _phc._cfg._bbs.map( copy->_idx, pred );
            // Extend ("register allocate") the names array for the copy.
            _phc._names.extend( copy->_idx, phi_name );
          } // End of if Phi names do not match
        } // End of for all inputs to Phi
      } else { // End of if Phi

        // Now check for 2-address instructions
        uint idx;
        if( n->is_Mach() && (idx=n->as_Mach()->two_adr()) ) {
          // Get the chosen name for the Node
          uint name = _phc.Find( n );
          assert( name, "no 2-address specials" );
          // Check for name mis-match on the 2-address input
          Node *m = n->in(idx);
          if( _phc.Find(m) != name ) {
            Node *copy;
            assert(!m->is_Con() || m->is_Mach(), "all Con must be Mach");
            // At this point it is unsafe to extend live ranges (6550579).
            // Rematerialize only constants as we do for Phi above.
            if( m->is_Mach() && m->as_Mach()->is_Con() &&
                m->as_Mach()->rematerialize() ) {
              copy = m->clone();
              // Insert the copy in the basic block, just before us
              b->_nodes.insert( l++, copy );
              if( _phc.clone_projs( b, l, m, copy, _phc._maxlrg ) )
                l++;
            } else {
              const RegMask *rm = C->matcher()->idealreg2spillmask[m->ideal_reg()];
              copy = new (C) MachSpillCopyNode( m, *rm, *rm );
              // Insert the copy in the basic block, just before us
              b->_nodes.insert( l++, copy );
            }
            // Insert the copy in the use-def chain
            n->set_req(idx, copy );
            // Extend ("register allocate") the names array for the copy.
            _phc._names.extend( copy->_idx, name );
            _phc._cfg._bbs.map( copy->_idx, b );
          }

        } // End of is two-adr

        // Insert a copy at a debug use for a lrg which has high frequency
        if( b->_freq < OPTO_DEBUG_SPLIT_FREQ || b->is_uncommon(_phc._cfg._bbs) ) {
          // Walk the debug inputs to the node and check for lrg freq
          JVMState* jvms = n->jvms();
          uint debug_start = jvms ? jvms->debug_start() : 999999;
          uint debug_end   = jvms ? jvms->debug_end()   : 999999;
          for(uint inpidx = debug_start; inpidx < debug_end; inpidx++) {
            // Do not split monitors; they are only needed for debug table
            // entries and need no code.
            if( jvms->is_monitor_use(inpidx) ) continue;
            Node *inp = n->in(inpidx);
            uint nidx = _phc.n2lidx(inp);
            LRG &lrg = lrgs(nidx);

            // If this lrg has a high frequency use/def
            if( lrg._maxfreq >= _phc.high_frequency_lrg() ) {
              // If the live range is also live out of this block (like it
              // would be for a fast/slow idiom), the normal spill mechanism
              // does an excellent job.  If it is not live out of this block
              // (like it would be for debug info to uncommon trap) splitting
              // the live range now allows a better allocation in the high
              // frequency blocks.
              //   Build_IFG_virtual has converted the live sets to
              // live-IN info, not live-OUT info.
              uint k;
              for( k=0; k < b->_num_succs; k++ )
                if( _phc._live->live(b->_succs[k])->member( nidx ) )
                  break;      // Live in to some successor block?
              if( k < b->_num_succs )
                continue;     // Live out; do not pre-split
              // Split the lrg at this use
              const RegMask *rm = C->matcher()->idealreg2spillmask[inp->ideal_reg()];
              Node *copy = new (C) MachSpillCopyNode( inp, *rm, *rm );
              // Insert the copy in the use-def chain
              n->set_req(inpidx, copy );
              // Insert the copy in the basic block, just before us
              b->_nodes.insert( l++, copy );
              // Extend ("register allocate") the names array for the copy.
              _phc.new_lrg( copy, _phc._maxlrg++ );
              _phc._cfg._bbs.map( copy->_idx, b );
              //tty->print_cr("Split a debug use in Aggressive Coalesce");
            }  // End of if high frequency use/def
          }  // End of for all debug inputs
        }  // End of if low frequency safepoint

      } // End of if Phi

    } // End of for all instructions
  } // End of for all blocks
}
Example #21
0
void buildModChain(FHEcontext &context, long nLevels, long nDgts,long extraBits)
{
#ifdef NO_HALF_SIZE_PRIME
  long nPrimes = nLevels;
#else
  long nPrimes = (nLevels+1)/2;
  // The first prime should be of half the size. The code below tries to find
  // a prime q0 of this size where q0-1 is divisible by 2^k * m for some k>1.

  long twoM = 2 * context.zMStar.getM();
  long bound = (1L << (context.bitsPerLevel-1));
  while (twoM < bound/(2*context.bitsPerLevel))
    twoM *= 2; // divisible by 2^k * m  for a larger k

  bound = bound - (bound % twoM) +1; // = 1 mod 2m
  long q0 = context.AddPrime(bound, twoM, false); 
  // add next prime to chain
  
  assert(q0 != 0);
  nPrimes--;
#endif

  // Choose the next primes as large as possible
  if (nPrimes>0) AddPrimesByNumber(context, nPrimes);

  // calculate the size of the digits

  if (nDgts > nPrimes) nDgts = nPrimes; // sanity checks
  if (nDgts <= 0) nDgts = 1;
  context.digits.resize(nDgts); // allocate space

  IndexSet s1;
  double sizeSoFar = 0.0;
  double maxDigitSize = 0.0;
  if (nDgts>1) { // we break ciphetext into a few digits when key-switching
    double dsize = context.logOfProduct(context.ctxtPrimes)/nDgts; // estimate

    // A hack: we break the current digit after the total size of all digits
    // so far "almost reaches" the next multiple of dsize, upto 1/3 of a level
    double target = dsize-(context.bitsPerLevel/3.0);
    long idx = context.ctxtPrimes.first();
    for (long i=0; i<nDgts-1; i++) { // set all digits but the last
      IndexSet s;
      while (idx <= context.ctxtPrimes.last() && (empty(s)||sizeSoFar<target)) {
        s.insert(idx);
	sizeSoFar += log((double)context.ithPrime(idx));
	idx = context.ctxtPrimes.next(idx);
      }
      assert (!empty(s));
      context.digits[i] = s;
      s1.insert(s);
      double thisDigitSize = context.logOfProduct(s);
      if (maxDigitSize < thisDigitSize) maxDigitSize = thisDigitSize;
      target += dsize;
    }
    // The ctxt primes that are left (if any) form the last digit
    IndexSet s = context.ctxtPrimes / s1;
    if (!empty(s)) {
      context.digits[nDgts-1] = s;
      double thisDigitSize = context.logOfProduct(s);
      if (maxDigitSize < thisDigitSize) maxDigitSize = thisDigitSize;
    }
    else { // If last digit is empty, remove it
      nDgts--;
      context.digits.resize(nDgts);
    }
  }
  else { // only one digit
    maxDigitSize = context.logOfProduct(context.ctxtPrimes);
    context.digits[0] = context.ctxtPrimes;
  }

  // Add special primes to the chain for the P factor of key-switching
  long p2r = context.alMod.getPPowR();
  double sizeOfSpecialPrimes
    = maxDigitSize + log(nDgts) + log(context.stdev *2)
      + log((double)p2r) + (extraBits*log(2.0));

  AddPrimesBySize(context, sizeOfSpecialPrimes, true);
}