/* * Finds the set of SSATmps that should be considered for allocation * to a full XMM register. These are the SSATmps that satisfy all the * following conditions: * a) it requires 2 64-bit registers * b) it's defined in a load instruction * c) all its uses are simple stores to memory * * The computed set of SSATmps is stored in m_fullXMMCandidates. */ void LinearScan::findFullXMMCandidates() { boost::dynamic_bitset<> notCandidates(m_irFactory->numTmps()); m_fullXMMCandidates.reset(); for (auto* block : m_blocks) { for (auto& inst : *block) { for (SSATmp& tmp : inst.dsts()) { if (tmp.numNeededRegs() == 2 && inst.isLoad()) { m_fullXMMCandidates[tmp.id()] = true; } } int idx = 0; for (SSATmp* tmp : inst.srcs()) { if (tmp->numNeededRegs() == 2 && !inst.storesCell(idx)) { notCandidates[tmp->id()] = true; } idx++; } } } m_fullXMMCandidates -= notCandidates; }
void reset () { flags_.reset(); }
std::vector<unsigned int> generateBondHashes(const ROMol &mol, boost::dynamic_bitset<>& atomsInPath, const std::vector<const Bond *>& bondCache, const std::vector<short>& isQueryBond, const PATH_TYPE &path, bool useBondOrder, std::vector<boost::uint32_t> *atomInvariants){ PRECONDITION(!atomInvariants || atomInvariants->size() >= mol.getNumAtoms(), "bad atomInvariants size"); std::vector<unsigned int> bondHashes; atomsInPath.reset(); bool queryInPath=false; std::vector<unsigned int> atomDegrees(mol.getNumAtoms(),0); for(unsigned int i=0;i<path.size() && !queryInPath;++i){ const Bond *bi = bondCache[path[i]]; atomDegrees[bi->getBeginAtomIdx()]++; atomDegrees[bi->getEndAtomIdx()]++; atomsInPath.set(bi->getBeginAtomIdx()); atomsInPath.set(bi->getEndAtomIdx()); if(isQueryBond[path[i]]) queryInPath=true; } if(queryInPath){ return bondHashes; } // ----------------- // calculate the bond hashes: std::vector<unsigned int> bondNbrs(path.size(),0); bondHashes.reserve(path.size()+1); for(unsigned int i=0;i<path.size();++i){ const Bond *bi = bondCache[path[i]]; #ifdef REPORT_FP_STATS if (std::find(atomsToUse.begin(), atomsToUse.end(), bi->getBeginAtomIdx()) == atomsToUse.end()) { atomsToUse.push_back(bi->getBeginAtomIdx()); } if (std::find(atomsToUse.begin(), atomsToUse.end(), bi->getEndAtomIdx()) == atomsToUse.end()) { atomsToUse.push_back(bi->getEndAtomIdx()); } #endif for(unsigned int j=i+1;j<path.size();++j){ const Bond *bj = bondCache[path[j]]; if(bi->getBeginAtomIdx()==bj->getBeginAtomIdx() || bi->getBeginAtomIdx()==bj->getEndAtomIdx() || bi->getEndAtomIdx()==bj->getBeginAtomIdx() || bi->getEndAtomIdx()==bj->getEndAtomIdx() ){ ++bondNbrs[i]; ++bondNbrs[j]; } } #ifdef VERBOSE_FINGERPRINTING std::cerr << " bond(" << i << "):" << bondNbrs[i] << std::endl; #endif // we have the count of neighbors for bond bi, compute its hash: unsigned int a1Hash = (*atomInvariants)[bi->getBeginAtomIdx()]; unsigned int a2Hash = (*atomInvariants)[bi->getEndAtomIdx()]; unsigned int deg1=atomDegrees[bi->getBeginAtomIdx()]; unsigned int deg2=atomDegrees[bi->getEndAtomIdx()]; if(a1Hash<a2Hash){ std::swap(a1Hash,a2Hash); std::swap(deg1,deg2); } else if(a1Hash==a2Hash && deg1<deg2){ std::swap(deg1,deg2); } unsigned int bondHash=1; if(useBondOrder){ if(bi->getIsAromatic() || bi->getBondType()==Bond::AROMATIC){ // makes sure aromatic bonds always hash as aromatic bondHash = Bond::AROMATIC; } else { bondHash = bi->getBondType(); } } boost::uint32_t ourHash=bondNbrs[i]; gboost::hash_combine(ourHash,bondHash); gboost::hash_combine(ourHash,a1Hash); gboost::hash_combine(ourHash,deg1); gboost::hash_combine(ourHash,a2Hash); gboost::hash_combine(ourHash,deg2); bondHashes.push_back(ourHash); //std::cerr<<" "<<bi->getIdx()<<" "<<a1Hash<<"("<<deg1<<")"<<"-"<<a2Hash<<"("<<deg2<<")"<<" "<<bondHash<<" -> "<<ourHash<<std::endl; } return bondHashes; }
// finds all possible chiral special cases. // at the moment this is just candidates for ring stereochemistry void findChiralAtomSpecialCases(ROMol &mol, boost::dynamic_bitset<> &possibleSpecialCases) { PRECONDITION(possibleSpecialCases.size() >= mol.getNumAtoms(), "bit vector too small"); possibleSpecialCases.reset(); if (!mol.getRingInfo()->isInitialized()) { VECT_INT_VECT sssrs; MolOps::symmetrizeSSSR(mol, sssrs); } boost::dynamic_bitset<> atomsSeen(mol.getNumAtoms()); boost::dynamic_bitset<> atomsUsed(mol.getNumAtoms()); boost::dynamic_bitset<> bondsSeen(mol.getNumBonds()); for (ROMol::AtomIterator ait = mol.beginAtoms(); ait != mol.endAtoms(); ++ait) { const Atom *atom = *ait; if (atomsSeen[atom->getIdx()]) continue; if (atom->getChiralTag() == Atom::CHI_UNSPECIFIED || atom->hasProp(common_properties::_CIPCode) || !mol.getRingInfo()->numAtomRings(atom->getIdx()) || !atomIsCandidateForRingStereochem(mol, atom)) { continue; } // do a BFS from this ring atom along ring bonds and find other // stereochemistry candidates. std::list<const Atom *> nextAtoms; // start with finding viable neighbors ROMol::OEDGE_ITER beg, end; boost::tie(beg, end) = mol.getAtomBonds(atom); while (beg != end) { unsigned int bidx = mol[*beg]->getIdx(); if (!bondsSeen[bidx]) { bondsSeen.set(bidx); if (mol.getRingInfo()->numBondRings(bidx)) { const Atom *oatom = mol[*beg]->getOtherAtom(atom); if (!atomsSeen[oatom->getIdx()]) { nextAtoms.push_back(oatom); atomsUsed.set(oatom->getIdx()); } } } ++beg; } INT_VECT ringStereoAtoms(0); if (!nextAtoms.empty()) { atom->getPropIfPresent(common_properties::_ringStereoAtoms, ringStereoAtoms); } while (!nextAtoms.empty()) { const Atom *ratom = nextAtoms.front(); nextAtoms.pop_front(); atomsSeen.set(ratom->getIdx()); if (ratom->getChiralTag() != Atom::CHI_UNSPECIFIED && !ratom->hasProp(common_properties::_CIPCode) && atomIsCandidateForRingStereochem(mol, ratom)) { int same = (ratom->getChiralTag() == atom->getChiralTag()) ? 1 : -1; ringStereoAtoms.push_back(same * (ratom->getIdx() + 1)); INT_VECT oringatoms(0); ratom->getPropIfPresent(common_properties::_ringStereoAtoms, oringatoms); oringatoms.push_back(same * (atom->getIdx() + 1)); ratom->setProp(common_properties::_ringStereoAtoms, oringatoms, true); possibleSpecialCases.set(ratom->getIdx()); possibleSpecialCases.set(atom->getIdx()); } // now push this atom's neighbors boost::tie(beg, end) = mol.getAtomBonds(ratom); while (beg != end) { unsigned int bidx = mol[*beg]->getIdx(); if (!bondsSeen[bidx]) { bondsSeen.set(bidx); if (mol.getRingInfo()->numBondRings(bidx)) { const Atom *oatom = mol[*beg]->getOtherAtom(ratom); if (!atomsSeen[oatom->getIdx()] && !atomsUsed[oatom->getIdx()]) { nextAtoms.push_back(oatom); atomsUsed.set(oatom->getIdx()); } } } ++beg; } } // end of BFS if (ringStereoAtoms.size() != 0) { atom->setProp(common_properties::_ringStereoAtoms, ringStereoAtoms, true); // because we're only going to hit each ring atom once, the first atom we // encounter in a ring is going to end up with all the other atoms set as // stereoAtoms, but each of them will only have the first atom present. We // need to fix that. because the traverse from the first atom only // followed ring bonds, these things are all by definition in one ring // system. (Q: is this true if there's a spiro center in there?) INT_VECT same(mol.getNumAtoms(), 0); BOOST_FOREACH (int ringAtomEntry, ringStereoAtoms) { int ringAtomIdx = ringAtomEntry < 0 ? -ringAtomEntry - 1 : ringAtomEntry - 1; same[ringAtomIdx] = ringAtomEntry; } for (INT_VECT_CI rae = ringStereoAtoms.begin(); rae != ringStereoAtoms.end(); ++rae) { int ringAtomEntry = *rae; int ringAtomIdx = ringAtomEntry < 0 ? -ringAtomEntry - 1 : ringAtomEntry - 1; INT_VECT lringatoms(0); mol.getAtomWithIdx(ringAtomIdx) ->getPropIfPresent(common_properties::_ringStereoAtoms, lringatoms); CHECK_INVARIANT(lringatoms.size() > 0, "no other ring atoms found."); for (INT_VECT_CI orae = rae + 1; orae != ringStereoAtoms.end(); ++orae) { int oringAtomEntry = *orae; int oringAtomIdx = oringAtomEntry < 0 ? -oringAtomEntry - 1 : oringAtomEntry - 1; int theseDifferent = (ringAtomEntry < 0) ^ (oringAtomEntry < 0); lringatoms.push_back(theseDifferent ? -(oringAtomIdx + 1) : (oringAtomIdx + 1)); INT_VECT olringatoms(0); mol.getAtomWithIdx(oringAtomIdx) ->getPropIfPresent(common_properties::_ringStereoAtoms, olringatoms); CHECK_INVARIANT(olringatoms.size() > 0, "no other ring atoms found."); olringatoms.push_back(theseDifferent ? -(ringAtomIdx + 1) : (ringAtomIdx + 1)); mol.getAtomWithIdx(oringAtomIdx) ->setProp(common_properties::_ringStereoAtoms, olringatoms); } mol.getAtomWithIdx(ringAtomIdx) ->setProp(common_properties::_ringStereoAtoms, lringatoms); } } else {
/****************************************************************************** * Performs the actual rejection of particles. ******************************************************************************/ size_t SliceModifier::filterParticles(boost::dynamic_bitset<>& mask, TimePoint time, TimeInterval& validityInterval) { // Get the required input properties. ParticlePropertyObject* const posProperty = expectStandardProperty(ParticleProperty::PositionProperty); ParticlePropertyObject* const selProperty = applyToSelection() ? inputStandardProperty(ParticleProperty::SelectionProperty) : nullptr; OVITO_ASSERT(posProperty->size() == mask.size()); OVITO_ASSERT(!selProperty || selProperty->size() == mask.size()); FloatType sliceWidth = 0; if(_widthCtrl) sliceWidth = _widthCtrl->getFloatValue(time, validityInterval); sliceWidth *= 0.5; Plane3 plane = slicingPlane(time, validityInterval); size_t na = 0; boost::dynamic_bitset<>::size_type i = 0; const Point3* p = posProperty->constDataPoint3(); const Point3* p_end = p + posProperty->size(); if(sliceWidth <= 0) { if(selProperty) { const int* s = selProperty->constDataInt(); for(; p != p_end; ++p, ++s, ++i) { if(*s && plane.pointDistance(*p) > 0) { mask.set(i); na++; } else mask.reset(i); } } else { for(; p != p_end; ++p, ++i) { if(plane.pointDistance(*p) > 0) { mask.set(i); na++; } else mask.reset(i); } } } else { bool invert = inverse(); if(selProperty) { const int* s = selProperty->constDataInt(); for(; p != p_end; ++p, ++s, ++i) { if(*s && invert == (plane.classifyPoint(*p, sliceWidth) == 0)) { mask.set(i); na++; } else mask.reset(i); } } else { for(; p != p_end; ++p, ++i) { if(invert == (plane.classifyPoint(*p, sliceWidth) == 0)) { mask.set(i); na++; } else mask.reset(i); } } } return na; }