void DTW::smoothData(VectorDouble &data,UINT smoothFactor,VectorDouble &resultsData){ const UINT M = (UINT)data.size(); const UINT N = (UINT) floor(double(M)/double(smoothFactor)); resultsData.resize(N,0); for(UINT i=0; i<N; i++) resultsData[i]=0.0; if(smoothFactor==1 || M<smoothFactor){ resultsData = data; return; } for(UINT i=0; i<N; i++){ double mean = 0.0; UINT index = i*smoothFactor; for(UINT x=0; x<smoothFactor; x++){ mean += data[index+x]; } resultsData[i] = mean/smoothFactor; } //Add on the data that does not fit into the window if(M%smoothFactor!=0.0){ double mean = 0.0; for(UINT i=N*smoothFactor; i<M; i++) mean += data[i]; mean/=M-(N*smoothFactor); //Add one to the end of the vector VectorDouble tempVector(N+1); for(UINT i=0; i<N; i++) tempVector[i] = resultsData[i]; tempVector[N] = mean; resultsData = tempVector; } }
static void RadixSort( std::vector<MortonPrimitive> *v ) { std::vector<MortonPrimitive> tempVector( v->size() ); const int bitsPerPass = 6; const int nBits = 30; wxASSERT( (nBits % bitsPerPass) == 0 ); const int nPasses = nBits / bitsPerPass; for( int pass = 0; pass < nPasses; ++pass ) { // Perform one pass of radix sort, sorting _bitsPerPass_ bits const int lowBit = pass * bitsPerPass; // Set in and out vector pointers for radix sort pass std::vector<MortonPrimitive> &in = (pass & 1) ? tempVector : *v; std::vector<MortonPrimitive> &out = (pass & 1) ? *v : tempVector; // Count number of zero bits in array for current radix sort bit const int nBuckets = 1 << bitsPerPass; int bucketCount[nBuckets] = {0}; const int bitMask = (1 << bitsPerPass) - 1; for( uint32_t i = 0; i < in.size(); ++i ) { const MortonPrimitive &mp = in[i]; int bucket = (mp.mortonCode >> lowBit) & bitMask; wxASSERT( (bucket >= 0) && (bucket < nBuckets) ); ++bucketCount[bucket]; } // Compute starting index in output array for each bucket int startIndex[nBuckets]; startIndex[0] = 0; for( int i = 1; i < nBuckets; ++i ) startIndex[i] = startIndex[i - 1] + bucketCount[i - 1]; // Store sorted values in output array for( uint32_t i = 0; i < in.size(); ++i ) { const MortonPrimitive &mp = in[i]; int bucket = (mp.mortonCode >> lowBit) & bitMask; out[startIndex[bucket]++] = mp; } } // Copy final result from _tempVector_, if needed if( nPasses & 1 ) std::swap( *v, tempVector ); }
AttributesImpl& AttributesImpl::operator=(const AttributesImpl& theRHS) { if (this != &theRHS) { // Note that we can't chain up to our base class operator=() // because it's private. // Some temporary structures to hold everything // until we're done. AttributesVectorType tempVector(getMemoryManager()); const unsigned int theLength = theRHS.getLength(); if (theLength > 0) { // Reserve the appropriate capacity right now... tempVector.reserve(theLength); // This will delete everything in tempVector when we're done... CollectionDeleteGuard<AttributesVectorType, DeleteFunctor<AttributeVectorEntryExtended> > theGuard(tempVector); typedef AttributesVectorType::const_iterator const_iterator; const const_iterator theEnd = theRHS.m_attributesVector.end(); // Copy the vector entries, and build the index map... for(const_iterator i = theRHS.m_attributesVector.begin(); i != theEnd; ++i) { AttributeVectorEntryExtended* const theEntry = *i; assert(theEntry != 0); // Add the item... tempVector.push_back( getNewEntry( &*theEntry->m_Name.begin(), &*theEntry->m_Type.begin(), &*theEntry->m_Value.begin(), &*theEntry->m_uri.begin(), &*theEntry->m_localName.begin())); } // OK, we're safe, so swap the contents of the // containers. This is guaranteed not to throw. m_attributesVector.swap(tempVector); } assert(getLength() == theLength); } return *this; }
void Vector::rotate_around(float yz, float xz, float xy, const Vector & origin){ Vector tempVector(*this); tempVector.subtract(origin); //m_start->set(origin); x() = origin.x(); y() = origin.y(); z() = origin.z(); tempVector.rotateXY(xy); tempVector.rotateXZ(xz); tempVector.rotateYZ(yz); //m_start->add(tempVector); x() += tempVector.x(); y() += tempVector.y(); z() += tempVector.z(); }
void updateAverage(vector<bool> Fprev, vector<bool> F, int frame, Parameters param, int gameId){ assert (Fprev.size() == F.size()); assert (F.size() == NUM_BITS); bool toPrint = false; vector<int> tempVector(2 * NUM_BITS, 0); for(int i = 0; i < NUM_BITS; i++){ if(!Fprev[i] && F[i]){ // 0->1 frequency[i] = (frequency[i] * (frame - 1) + 1) / frame; tempVector[i] = 1; if(frame > FRAMES_TO_WAIT && frequency[i] < param.freqThreshold){ tempVector[i] = 2; //1 denotes flip, 2 denotes relevant flip toPrint = true; } } else{ frequency[i] = (frequency[i] * (frame - 1) + 0) / frame; } if(Fprev[i] && !F[i]){ // 1->0 frequency[i + NUM_BITS] = (frequency[i + NUM_BITS] * (frame - 1) + 1) / frame; tempVector[i + NUM_BITS] = 1; if(frame > FRAMES_TO_WAIT && frequency[i + NUM_BITS] < param.freqThreshold){ tempVector[i + NUM_BITS] = 2; toPrint = true; } } else{ frequency[i + NUM_BITS] = (frequency[i + NUM_BITS] * (frame - 1) + 0) / frame; } } ofstream myFileBits, myFileBytes; myFileBits.open (param.outputPath + "_bits.csv", ios::app); if(toPrint){ for(int i = 0; i < tempVector.size(); i++){ if(param.toReportAll == 1 && tempVector[i] != 0){ myFileBits << i << ","; } if(param.toReportAll == 0 && tempVector[i] == 2){ myFileBits << i << ","; } } myFileBits << endl; } myFileBits.close(); }
vector<char> Sparse6Writer::encodeNumberOfNodes(unsigned number) { vector<char> result; // three cases if (number <= 62) result.push_back(number+63); else /* if(number <= 258047) */ { // the first characer is 126 result.push_back(126); BitVector tempVector(number); tempVector.padL(18); result.push_back(tempVector.getIntBit(0, 6)); result.push_back(tempVector.getIntBit(6, 6)); result.push_back(tempVector.getIntBit(12, 6)); } return result; }
void CContinuousActionSigmoidPolicy::getNoise(CStateCollection *state, CContinuousActionData *action, CContinuousActionData *l_noise) { if (randomControllerMode == INTERN_RANDOM_CONTROLLER) { ColumnVector tempVector(this->contAction->getNumDimensions()); policy->getNextContinuousAction(state, l_noise); tempVector = *action; for (int i = 0; i < tempVector.nrows(); i ++) { double umax = getContinuousActionProperties()->getMaxActionValue(i); double umin = getContinuousActionProperties()->getMinActionValue(i); double width = umax - umin; double actionValue = tempVector.element(i); actionValue = (actionValue - umin) / (umax - umin); if (actionValue <= 0.0001) { actionValue = 0.0001; } else { if (actionValue >= 0.9999) { actionValue = 0.9999; } } actionValue = (- log(1 / actionValue - 1) + 2) * width / 4 + umin; tempVector.element(i) = actionValue; } *l_noise *= -1; *l_noise += tempVector; } else { CContinuousActionController::getNoise(state, action, l_noise); } }
intrusive_ptr<Pipeline> Pipeline::splitForSharded() { /* create an initialize the shard spec we'll return */ intrusive_ptr<Pipeline> pShardPipeline(new Pipeline(pCtx)); pShardPipeline->collectionName = collectionName; pShardPipeline->explain = explain; /* put the source list aside */ SourceVector tempVector(sourceVector); sourceVector.clear(); /* Run through the pipeline, looking for points to split it into shard pipelines, and the rest. */ while(!tempVector.empty()) { intrusive_ptr<DocumentSource> &pSource = tempVector.front(); /* hang on to this in advance, in case it is a group */ DocumentSourceGroup *pGroup = dynamic_cast<DocumentSourceGroup *>(pSource.get()); /* move the source from the tempVector to the shard sourceVector */ pShardPipeline->sourceVector.push_back(pSource); tempVector.erase(tempVector.begin()); /* If we found a group, that's a split point. */ if (pGroup) { /* start this pipeline with the group merger */ sourceVector.push_back(pGroup->createMerger()); /* and then add everything that remains and quit */ for(size_t tempn = tempVector.size(), tempi = 0; tempi < tempn; ++tempi) sourceVector.push_back(tempVector[tempi]); break; } } return pShardPipeline; }
void FVector::fn4(FVector *dest, const FVector *v1, const FVector *v2) { FVector tempVector(v1->_x + v2->_x, v1->_y + v2->_y, v1->_z + v2->_z); tempVector.fn3(); *dest = tempVector; }
DWORD WINAPI CTcpServerSocketHelper::_ReadDataThreadProc(LPVOID lpParam) { CTcpServerSocketHelper *This = (CTcpServerSocketHelper *)lpParam; DWORD dwResult = -1; DWORD dwIndex = 0; DWORD dwVectorSize = 0; while (TRUE) { EnterCriticalSection(&This->m_cs); vector<SOCKET> tempVector(This->m_AcceptSocketVector); LeaveCriticalSection(&This->m_cs); dwVectorSize = (DWORD)tempVector.size(); for (dwIndex=0; dwIndex < dwVectorSize; ++dwIndex) { SOCKET hSock = tempVector[dwIndex]; BOOL bErr = FALSE; if (This->IsSocketReadable(0,bErr,hSock)) { DWORD dwSize = 64*1024; BYTE *pyBuf = new BYTE[dwSize]; assert(pyBuf); if (This->ReceiveData(pyBuf,&dwSize,hSock)) { //This->m_pEvent->OnDataIn(hSock, pyBuf, dwSize); if (dwSize==0) { //接收失败!对方已经关闭了连接? This->CloseSocket(hSock); //1) 从This->m_AcceptSocketVector erase this socket EnterCriticalSection(&This->m_cs); vector<SOCKET>::iterator sckVect = This->m_AcceptSocketVector.begin(); for (;sckVect!=This->m_AcceptSocketVector.end();) { if (*sckVect==hSock) { sckVect = This->m_AcceptSocketVector.erase(sckVect); break; } else { ++sckVect; } } LeaveCriticalSection(&This->m_cs); // 2) This->m_pEvent->OnSocketClose(...) This->m_pEvent->OnSocketClose(hSock,1); } else { This->m_pEvent->OnDataIn(hSock, pyBuf, dwSize); } } else { //接收失败!对方已经关闭了连接? This->CloseSocket(hSock); //1) 从This->m_AcceptSocketVector erase this socket EnterCriticalSection(&This->m_cs); vector<SOCKET>::iterator sckVect = This->m_AcceptSocketVector.begin(); for (;sckVect!=This->m_AcceptSocketVector.end();) { if (*sckVect==hSock) { sckVect = This->m_AcceptSocketVector.erase(sckVect); break; } else { ++sckVect; } } LeaveCriticalSection(&This->m_cs); // 2) This->m_pEvent->OnSocketClose(...) This->m_pEvent->OnSocketClose(hSock,1); } delete [] pyBuf; } else { if (bErr) { //接收失败!对方已经关闭了连接? This->CloseSocket(hSock); //1) 从This->m_AcceptSocketVector erase this socket EnterCriticalSection(&This->m_cs); vector<SOCKET>::iterator sckVect = This->m_AcceptSocketVector.begin(); for (;sckVect!=This->m_AcceptSocketVector.end();) { if (*sckVect==hSock) { sckVect = This->m_AcceptSocketVector.erase(sckVect); break; } else { ++sckVect; } } LeaveCriticalSection(&This->m_cs); // 2) This->m_pEvent->OnSocketClose(...) This->m_pEvent->OnSocketClose(hSock,1); } } } if (::WaitForSingleObject(This->m_hTerminateReadDataThreadEvent, 500)==WAIT_OBJECT_0) { break; } } dwResult = 0; return dwResult; }
void AffineDeformationFast::calcA() { int i,j; double sumofwpx,sumofwpy; Point *pstar=new Point[commonPoint.size()]; if(sumofw!=NULL) { delete[] sumofw; sumofw=NULL; } sumofw=new double[commonPoint.size()]; w.clear();//w[非控制点下标][控制点下标] vector<double> tempVector(oldControlPoint.size(),0.0); precomputedpart=commonPoint; for(i=0;i<commonPoint.size();i++) { if(isControlPoint(commonPoint[i])>=0)//是控制点,不需要计算w值 { w.push_back(tempVector); continue; } sumofw[i]=0.0; sumofwpx=0.0; sumofwpy=0.0; for(j=0;j<oldControlPoint.size();j++) { double t1=oldControlPoint[j].xx-commonPoint[i].xx; double t2=oldControlPoint[j].yy-commonPoint[i].yy; t1=1.0/pow(t1*t1+t2*t2,alpha); sumofw[i]+=t1; sumofwpx+=t1*oldControlPoint[j].xx; sumofwpy+=t1*oldControlPoint[j].yy; tempVector[j]=t1; } pstar[i].xx=sumofwpx/sumofw[i]; pstar[i].yy=sumofwpy/sumofw[i]; precomputedpart[i].xx=commonPoint[i].xx-pstar[i].xx; precomputedpart[i].yy=commonPoint[i].yy-pstar[i].yy; w.push_back(tempVector); cleartempMatrix(); for(j=0;j<oldControlPoint.size();j++) { double a=oldControlPoint[j].xx-pstar[i].xx; double b=oldControlPoint[j].yy-pstar[i].yy; tempMatrix[0][0]+=tempVector[j]*a*a; tempMatrix[1][1]+=tempVector[j]*b*b; a*=b; tempMatrix[0][1]+=tempVector[j]*a; tempMatrix[1][0]+=tempVector[j]*a; } double tt,dt=tempMatrix[0][0]*tempMatrix[1][1]-tempMatrix[0][1]*tempMatrix[1][0]; doubleswap(tempMatrix[0][0],tempMatrix[1][1]); tempMatrix[0][0]/=dt; tempMatrix[1][1]/=dt; tempMatrix[0][1]/=(-dt); tempMatrix[1][0]/=(-dt); tt=precomputedpart[i].xx*tempMatrix[0][0]+precomputedpart[i].yy*tempMatrix[1][0]; dt=precomputedpart[i].xx*tempMatrix[0][1]+precomputedpart[i].yy*tempMatrix[1][1]; precomputedpart[i].xx=tt; precomputedpart[i].yy=dt; } A.clear();//A[非控制点下标][控制点下标] for(i=0;i<commonPoint.size();i++) { if(isControlPoint(commonPoint[i])>=0)//是控制点,不需要计算w值 { A.push_back(tempVector); continue; } for(j=0;j<oldControlPoint.size();j++) { Point tempPoint; tempPoint.xx=oldControlPoint[j].xx-pstar[i].xx; tempPoint.yy=oldControlPoint[j].yy-pstar[i].yy; tempVector[j]=w[i][j]*(precomputedpart[i].xx*tempPoint.xx+precomputedpart[i].yy*tempPoint.yy); } A.push_back(tempVector); } delete[] pstar; isPreComputed=true; }
intrusive_ptr<Pipeline> Pipeline::parseCommand( string &errmsg, BSONObj &cmdObj, const intrusive_ptr<ExpressionContext> &pCtx) { intrusive_ptr<Pipeline> pPipeline(new Pipeline(pCtx)); vector<BSONElement> pipeline; /* gather the specification for the aggregation */ for(BSONObj::iterator cmdIterator = cmdObj.begin(); cmdIterator.more(); ) { BSONElement cmdElement(cmdIterator.next()); const char *pFieldName = cmdElement.fieldName(); /* look for the aggregation command */ if (!strcmp(pFieldName, commandName)) { pPipeline->collectionName = cmdElement.String(); continue; } /* check for the collection name */ if (!strcmp(pFieldName, pipelineName)) { pipeline = cmdElement.Array(); continue; } /* check for explain option */ if (!strcmp(pFieldName, explainName)) { pPipeline->explain = cmdElement.Bool(); continue; } /* if the request came from the router, we're in a shard */ if (!strcmp(pFieldName, fromRouterName)) { pCtx->setInShard(cmdElement.Bool()); continue; } /* check for debug options */ if (!strcmp(pFieldName, splitMongodPipelineName)) { pPipeline->splitMongodPipeline = true; continue; } /* Ignore $auth information sent along with the command. The authentication system will * use it, it's not a part of the pipeline. */ if (!strcmp(pFieldName, AuthenticationTable::fieldName.c_str())) { continue; } /* we didn't recognize a field in the command */ ostringstream sb; sb << "unrecognized field \"" << cmdElement.fieldName(); errmsg = sb.str(); return intrusive_ptr<Pipeline>(); } /* If we get here, we've harvested the fields we expect for a pipeline. Set up the specified document source pipeline. */ SourceVector *pSourceVector = &pPipeline->sourceVector; // shorthand /* iterate over the steps in the pipeline */ const size_t nSteps = pipeline.size(); for(size_t iStep = 0; iStep < nSteps; ++iStep) { /* pull out the pipeline element as an object */ BSONElement pipeElement(pipeline[iStep]); uassert(15942, str::stream() << "pipeline element " << iStep << " is not an object", pipeElement.type() == Object); BSONObj bsonObj(pipeElement.Obj()); // Parse a pipeline stage from 'bsonObj'. uassert(16435, "A pipeline stage specification object must contain exactly one field.", bsonObj.nFields() == 1); BSONElement stageSpec = bsonObj.firstElement(); const char* stageName = stageSpec.fieldName(); // Create a DocumentSource pipeline stage from 'stageSpec'. StageDesc key; key.pName = stageName; const StageDesc* pDesc = (const StageDesc*) bsearch(&key, stageDesc, nStageDesc, sizeof(StageDesc), stageDescCmp); uassert(16436, str::stream() << "Unrecognized pipeline stage name: '" << stageName << "'", pDesc); intrusive_ptr<DocumentSource> stage = (*pDesc->pFactory)(&stageSpec, pCtx); verify(stage); stage->setPipelineStep(iStep); pSourceVector->push_back(stage); } /* if there aren't any pipeline stages, there's nothing more to do */ if (!pSourceVector->size()) return pPipeline; /* Move filters up where possible. CW TODO -- move filter past projections where possible, and noting corresponding field renaming. */ /* Wherever there is a match immediately following a sort, swap them. This means we sort fewer items. Neither changes the documents in the stream, so this transformation shouldn't affect the result. We do this first, because then when we coalesce operators below, any adjacent matches will be combined. */ for(size_t srcn = pSourceVector->size(), srci = 1; srci < srcn; ++srci) { intrusive_ptr<DocumentSource> &pSource = pSourceVector->at(srci); if (dynamic_cast<DocumentSourceMatch *>(pSource.get())) { intrusive_ptr<DocumentSource> &pPrevious = pSourceVector->at(srci - 1); if (dynamic_cast<DocumentSourceSort *>(pPrevious.get())) { /* swap this item with the previous */ intrusive_ptr<DocumentSource> pTemp(pPrevious); pPrevious = pSource; pSource = pTemp; } } } /* Coalesce adjacent filters where possible. Two adjacent filters are equivalent to one filter whose predicate is the conjunction of the two original filters' predicates. For now, capture this by giving any DocumentSource the option to absorb it's successor; this will also allow adjacent projections to coalesce when possible. Run through the DocumentSources, and give each one the opportunity to coalesce with its successor. If successful, remove the successor. Move all document sources to a temporary list. */ SourceVector tempVector(*pSourceVector); pSourceVector->clear(); /* move the first one to the final list */ pSourceVector->push_back(tempVector[0]); /* run through the sources, coalescing them or keeping them */ for(size_t tempn = tempVector.size(), tempi = 1; tempi < tempn; ++tempi) { /* If we can't coalesce the source with the last, then move it to the final list, and make it the new last. (If we succeeded, then we're still on the same last, and there's no need to move or do anything with the source -- the destruction of tempVector will take care of the rest.) */ intrusive_ptr<DocumentSource> &pLastSource = pSourceVector->back(); intrusive_ptr<DocumentSource> &pTemp = tempVector.at(tempi); verify(pTemp && pLastSource); if (!pLastSource->coalesce(pTemp)) pSourceVector->push_back(pTemp); } /* optimize the elements in the pipeline */ for(SourceVector::iterator iter(pSourceVector->begin()), listEnd(pSourceVector->end()); iter != listEnd; ++iter) { if (!*iter) { errmsg = "Pipeline received empty document as argument"; return intrusive_ptr<Pipeline>(); } (*iter)->optimize(); } return pPipeline; }
intrusive_ptr<Pipeline> Pipeline::parseCommand( string &errmsg, BSONObj &cmdObj, const intrusive_ptr<ExpressionContext> &pCtx) { intrusive_ptr<Pipeline> pPipeline(new Pipeline(pCtx)); vector<BSONElement> pipeline; /* gather the specification for the aggregation */ for(BSONObj::iterator cmdIterator = cmdObj.begin(); cmdIterator.more(); ) { BSONElement cmdElement(cmdIterator.next()); const char *pFieldName = cmdElement.fieldName(); /* look for the aggregation command */ if (!strcmp(pFieldName, commandName)) { pPipeline->collectionName = cmdElement.String(); continue; } /* check for the collection name */ if (!strcmp(pFieldName, pipelineName)) { pipeline = cmdElement.Array(); continue; } /* check for explain option */ if (!strcmp(pFieldName, explainName)) { pPipeline->explain = cmdElement.Bool(); continue; } /* if the request came from the router, we're in a shard */ if (!strcmp(pFieldName, fromRouterName)) { pCtx->setInShard(cmdElement.Bool()); continue; } /* check for debug options */ if (!strcmp(pFieldName, splitMongodPipelineName)) { pPipeline->splitMongodPipeline = true; continue; } /* Ignore $auth information sent along with the command. The authentication system will * use it, it's not a part of the pipeline. */ if (!strcmp(pFieldName, AuthenticationTable::fieldName.c_str())) { continue; } /* we didn't recognize a field in the command */ ostringstream sb; sb << "unrecognized field \"" << cmdElement.fieldName(); errmsg = sb.str(); return intrusive_ptr<Pipeline>(); } /* If we get here, we've harvested the fields we expect for a pipeline. Set up the specified document source pipeline. */ SourceVector *pSourceVector = &pPipeline->sourceVector; // shorthand /* iterate over the steps in the pipeline */ const size_t nSteps = pipeline.size(); for(size_t iStep = 0; iStep < nSteps; ++iStep) { /* pull out the pipeline element as an object */ BSONElement pipeElement(pipeline[iStep]); uassert(15942, str::stream() << "pipeline element " << iStep << " is not an object", pipeElement.type() == Object); BSONObj bsonObj(pipeElement.Obj()); intrusive_ptr<DocumentSource> pSource; /* use the object to add a DocumentSource to the processing chain */ BSONObjIterator bsonIterator(bsonObj); while(bsonIterator.more()) { BSONElement bsonElement(bsonIterator.next()); const char *pFieldName = bsonElement.fieldName(); /* select the appropriate operation and instantiate */ StageDesc key; key.pName = pFieldName; const StageDesc *pDesc = (const StageDesc *) bsearch(&key, stageDesc, nStageDesc, sizeof(StageDesc), stageDescCmp); if (pDesc) { pSource = (*pDesc->pFactory)(&bsonElement, pCtx); pSource->setPipelineStep(iStep); } else { ostringstream sb; sb << "Pipeline::run(): unrecognized pipeline op \"" << pFieldName; errmsg = sb.str(); return intrusive_ptr<Pipeline>(); } } pSourceVector->push_back(pSource); } /* if there aren't any pipeline stages, there's nothing more to do */ if (!pSourceVector->size()) return pPipeline; /* Move filters up where possible. CW TODO -- move filter past projections where possible, and noting corresponding field renaming. */ /* Wherever there is a match immediately following a sort, swap them. This means we sort fewer items. Neither changes the documents in the stream, so this transformation shouldn't affect the result. We do this first, because then when we coalesce operators below, any adjacent matches will be combined. */ for(size_t srcn = pSourceVector->size(), srci = 1; srci < srcn; ++srci) { intrusive_ptr<DocumentSource> &pSource = pSourceVector->at(srci); if (dynamic_cast<DocumentSourceMatch *>(pSource.get())) { intrusive_ptr<DocumentSource> &pPrevious = pSourceVector->at(srci - 1); if (dynamic_cast<DocumentSourceSort *>(pPrevious.get())) { /* swap this item with the previous */ intrusive_ptr<DocumentSource> pTemp(pPrevious); pPrevious = pSource; pSource = pTemp; } } } /* Move limits in front of skips. This is more optimal for sharding * since currently, we can only split the pipeline at a single source * and it is better to limit the results coming from each shard */ for(int i = pSourceVector->size() - 1; i >= 1 /* not looking at 0 */; i--) { DocumentSourceLimit* limit = dynamic_cast<DocumentSourceLimit*>((*pSourceVector)[i].get()); DocumentSourceSkip* skip = dynamic_cast<DocumentSourceSkip*>((*pSourceVector)[i-1].get()); if (limit && skip) { // Increase limit by skip since the skipped docs now pass through the $limit limit->setLimit(limit->getLimit() + skip->getSkip()); swap((*pSourceVector)[i], (*pSourceVector)[i-1]); // Start at back again. This is needed to handle cases with more than 1 $limit // (S means skip, L means limit) // // These two would work without second pass (assuming back to front ordering) // SL -> LS // SSL -> LSS // // The following cases need a second pass to handle the second limit // SLL -> LLS // SSLL -> LLSS // SLSL -> LLSS i = pSourceVector->size(); // decremented before next pass } } /* Coalesce adjacent filters where possible. Two adjacent filters are equivalent to one filter whose predicate is the conjunction of the two original filters' predicates. For now, capture this by giving any DocumentSource the option to absorb it's successor; this will also allow adjacent projections to coalesce when possible. Run through the DocumentSources, and give each one the opportunity to coalesce with its successor. If successful, remove the successor. Move all document sources to a temporary list. */ SourceVector tempVector(*pSourceVector); pSourceVector->clear(); /* move the first one to the final list */ pSourceVector->push_back(tempVector[0]); /* run through the sources, coalescing them or keeping them */ for(size_t tempn = tempVector.size(), tempi = 1; tempi < tempn; ++tempi) { /* If we can't coalesce the source with the last, then move it to the final list, and make it the new last. (If we succeeded, then we're still on the same last, and there's no need to move or do anything with the source -- the destruction of tempVector will take care of the rest.) */ intrusive_ptr<DocumentSource> &pLastSource = pSourceVector->back(); intrusive_ptr<DocumentSource> &pTemp = tempVector.at(tempi); if (!pTemp || !pLastSource) { errmsg = "Pipeline received empty document as argument"; return intrusive_ptr<Pipeline>(); } if (!pLastSource->coalesce(pTemp)) pSourceVector->push_back(pTemp); } /* optimize the elements in the pipeline */ for(SourceVector::iterator iter(pSourceVector->begin()), listEnd(pSourceVector->end()); iter != listEnd; ++iter) { if (!*iter) { errmsg = "Pipeline received empty document as argument"; return intrusive_ptr<Pipeline>(); } (*iter)->optimize(); } return pPipeline; }