string longestCommonPrefix(vector<string>& strs) { if (strs.size() == 0) return ""; else if (strs.size() == 1) return strs[0]; string cmPrefix = commonPrefix(strs[0], strs[1]); for (int i = 1; i < strs.size(); ++i) { cmPrefix = commonPrefix(cmPrefix, strs[i]); } return cmPrefix; }
int TSHPath::CommonPrefix(LPCTSTR pszFile1, LPCTSTR pszFile2, LPTSTR achPath) { static TModuleProc3<int,LPCTSTR,LPCTSTR,LPTSTR> commonPrefix(GetModule(), CommonPrefixStr); return commonPrefix(pszFile1, pszFile2, achPath); }
string longestCommonPrefix(vector<string>& strs,int left,int right) { if(left == right){ return strs[left]; } int mid = left + (right-left)/2; string lstr = longestCommonPrefix(strs,left,mid); string rstr = longestCommonPrefix(strs,mid+1,right); return commonPrefix(lstr,rstr); }
string longestCommonPrefix(vector<string>& strs) { string res; if(strs.size() == 0) return res; res = strs[0]; for(unsigned int index = 1; index < strs.size(); index++){ commonPrefix(strs[index],res); } return res; }
UTILS_EXPORT QString commonPath(const QStringList &files) { QString common = commonPrefix(files); // Find common directory part: "C:\foo\bar" -> "C:\foo" int lastSeparatorPos = common.lastIndexOf(QLatin1Char('/')); if (lastSeparatorPos == -1) lastSeparatorPos = common.lastIndexOf(QLatin1Char('\\')); if (lastSeparatorPos == -1) return QString(); if (HostOsInfo::isAnyUnixHost() && lastSeparatorPos == 0) // Unix: "/a", "/b" -> '/' lastSeparatorPos = 1; common.truncate(lastSeparatorPos); return common; }
QTCREATOR_UTILS_EXPORT QString commonPath(const QStringList &files) { QString common = commonPrefix(files); // Find common directory part: "C:\foo\bar" -> "C:\foo" int lastSeparatorPos = common.lastIndexOf(QLatin1Char('/')); if (lastSeparatorPos == -1) lastSeparatorPos = common.lastIndexOf(QLatin1Char('\\')); if (lastSeparatorPos == -1) return QString(); #ifdef Q_OS_UNIX if (lastSeparatorPos == 0) // Unix: "/a", "/b" -> '/' lastSeparatorPos = 1; #endif common.truncate(lastSeparatorPos); return common; }
MemTrieNode* MemTrieNode::newBranch(bytesConstRef _k1, std::string const& _v1, bytesConstRef _k2, std::string const& _v2) { unsigned prefix = commonPrefix(_k1, _k2); MemTrieNode* ret; if (_k1.size() == prefix) ret = new TrieBranchNode(_k2[prefix], new TrieLeafNode(_k2.cropped(prefix + 1), _v2), _v1); else if (_k2.size() == prefix) ret = new TrieBranchNode(_k1[prefix], new TrieLeafNode(_k1.cropped(prefix + 1), _v1), _v2); else // both continue after split ret = new TrieBranchNode(_k1[prefix], new TrieLeafNode(_k1.cropped(prefix + 1), _v1), _k2[prefix], new TrieLeafNode(_k2.cropped(prefix + 1), _v2)); if (prefix) // have shared prefix - split. ret = new TrieInfixNode(_k1.cropped(0, prefix), ret); return ret; }
MemTrieNode* TrieInfixNode::insert(bytesConstRef _key, std::string const& _value) { assert(_value.size()); mark(); if (contains(_key)) { m_next = m_next->insert(_key.cropped(m_ext.size()), _value); return this; } else { unsigned prefix = commonPrefix(_key, m_ext); if (prefix) { // one infix becomes two infixes, then insert into the second // instead of pop_front()... trimFront(m_ext, prefix); return new TrieInfixNode(_key.cropped(0, prefix), insert(_key.cropped(prefix), _value)); } else { // split here. auto f = m_ext[0]; trimFront(m_ext, 1); MemTrieNode* n = m_ext.empty() ? m_next : this; if (n != this) { m_next = nullptr; delete this; } TrieBranchNode* ret = new TrieBranchNode(f, n); ret->insert(_key, _value); return ret; } } }
Datum spg_text_picksplit(PG_FUNCTION_ARGS) { spgPickSplitIn *in = (spgPickSplitIn *) PG_GETARG_POINTER(0); spgPickSplitOut *out = (spgPickSplitOut *) PG_GETARG_POINTER(1); text *text0 = DatumGetTextPP(in->datums[0]); int i, commonLen; spgNodePtr *nodes; /* Identify longest common prefix, if any */ commonLen = VARSIZE_ANY_EXHDR(text0); for (i = 1; i < in->nTuples && commonLen > 0; i++) { text *texti = DatumGetTextPP(in->datums[i]); int tmp = commonPrefix(VARDATA_ANY(text0), VARDATA_ANY(texti), VARSIZE_ANY_EXHDR(text0), VARSIZE_ANY_EXHDR(texti)); if (tmp < commonLen) commonLen = tmp; } /* * Limit the prefix length, if necessary, to ensure that the resulting * inner tuple will fit on a page. */ commonLen = Min(commonLen, SPGIST_MAX_PREFIX_LENGTH); /* Set node prefix to be that string, if it's not empty */ if (commonLen == 0) { out->hasPrefix = false; } else { out->hasPrefix = true; out->prefixDatum = formTextDatum(VARDATA_ANY(text0), commonLen); } /* Extract the node label (first non-common byte) from each value */ nodes = (spgNodePtr *) palloc(sizeof(spgNodePtr) * in->nTuples); for (i = 0; i < in->nTuples; i++) { text *texti = DatumGetTextPP(in->datums[i]); if (commonLen < VARSIZE_ANY_EXHDR(texti)) nodes[i].c = *(uint8 *) (VARDATA_ANY(texti) + commonLen); else nodes[i].c = '\0'; /* use \0 if string is all common */ nodes[i].i = i; nodes[i].d = in->datums[i]; } /* * Sort by label bytes so that we can group the values into nodes. This * also ensures that the nodes are ordered by label value, allowing the * use of binary search in searchChar. */ qsort(nodes, in->nTuples, sizeof(*nodes), cmpNodePtr); /* And emit results */ out->nNodes = 0; out->nodeLabels = (Datum *) palloc(sizeof(Datum) * in->nTuples); out->mapTuplesToNodes = (int *) palloc(sizeof(int) * in->nTuples); out->leafTupleDatums = (Datum *) palloc(sizeof(Datum) * in->nTuples); for (i = 0; i < in->nTuples; i++) { text *texti = DatumGetTextPP(nodes[i].d); Datum leafD; if (i == 0 || nodes[i].c != nodes[i - 1].c) { out->nodeLabels[out->nNodes] = UInt8GetDatum(nodes[i].c); out->nNodes++; } if (commonLen < VARSIZE_ANY_EXHDR(texti)) leafD = formTextDatum(VARDATA_ANY(texti) + commonLen + 1, VARSIZE_ANY_EXHDR(texti) - commonLen - 1); else leafD = formTextDatum(NULL, 0); out->leafTupleDatums[nodes[i].i] = leafD; out->mapTuplesToNodes[nodes[i].i] = out->nNodes - 1; } PG_RETURN_VOID(); }
Datum spg_text_choose(PG_FUNCTION_ARGS) { spgChooseIn *in = (spgChooseIn *) PG_GETARG_POINTER(0); spgChooseOut *out = (spgChooseOut *) PG_GETARG_POINTER(1); text *inText = DatumGetTextPP(in->datum); char *inStr = VARDATA_ANY(inText); int inSize = VARSIZE_ANY_EXHDR(inText); uint8 nodeChar = '\0'; int i = 0; int commonLen = 0; /* Check for prefix match, set nodeChar to first byte after prefix */ if (in->hasPrefix) { text *prefixText = DatumGetTextPP(in->prefixDatum); char *prefixStr = VARDATA_ANY(prefixText); int prefixSize = VARSIZE_ANY_EXHDR(prefixText); commonLen = commonPrefix(inStr + in->level, prefixStr, inSize - in->level, prefixSize); if (commonLen == prefixSize) { if (inSize - in->level > commonLen) nodeChar = *(uint8 *) (inStr + in->level + commonLen); else nodeChar = '\0'; } else { /* Must split tuple because incoming value doesn't match prefix */ out->resultType = spgSplitTuple; if (commonLen == 0) { out->result.splitTuple.prefixHasPrefix = false; } else { out->result.splitTuple.prefixHasPrefix = true; out->result.splitTuple.prefixPrefixDatum = formTextDatum(prefixStr, commonLen); } out->result.splitTuple.nodeLabel = UInt8GetDatum(*(prefixStr + commonLen)); if (prefixSize - commonLen == 1) { out->result.splitTuple.postfixHasPrefix = false; } else { out->result.splitTuple.postfixHasPrefix = true; out->result.splitTuple.postfixPrefixDatum = formTextDatum(prefixStr + commonLen + 1, prefixSize - commonLen - 1); } PG_RETURN_VOID(); } } else if (inSize > in->level) { nodeChar = *(uint8 *) (inStr + in->level); } else { nodeChar = '\0'; } /* Look up nodeChar in the node label array */ if (searchChar(in->nodeLabels, in->nNodes, nodeChar, &i)) { /* * Descend to existing node. (If in->allTheSame, the core code will * ignore our nodeN specification here, but that's OK. We still * have to provide the correct levelAdd and restDatum values, and * those are the same regardless of which node gets chosen by core.) */ out->resultType = spgMatchNode; out->result.matchNode.nodeN = i; out->result.matchNode.levelAdd = commonLen + 1; if (inSize - in->level - commonLen - 1 > 0) out->result.matchNode.restDatum = formTextDatum(inStr + in->level + commonLen + 1, inSize - in->level - commonLen - 1); else out->result.matchNode.restDatum = formTextDatum(NULL, 0); } else if (in->allTheSame) { /* * Can't use AddNode action, so split the tuple. The upper tuple * has the same prefix as before and uses an empty node label for * the lower tuple. The lower tuple has no prefix and the same * node labels as the original tuple. */ out->resultType = spgSplitTuple; out->result.splitTuple.prefixHasPrefix = in->hasPrefix; out->result.splitTuple.prefixPrefixDatum = in->prefixDatum; out->result.splitTuple.nodeLabel = UInt8GetDatum('\0'); out->result.splitTuple.postfixHasPrefix = false; } else { /* Add a node for the not-previously-seen nodeChar value */ out->resultType = spgAddNode; out->result.addNode.nodeLabel = UInt8GetDatum(nodeChar); out->result.addNode.nodeN = i; } PG_RETURN_VOID(); }
Datum spg_text_choose(PG_FUNCTION_ARGS) { spgChooseIn *in = (spgChooseIn *) PG_GETARG_POINTER(0); spgChooseOut *out = (spgChooseOut *) PG_GETARG_POINTER(1); text *inText = DatumGetTextPP(in->datum); char *inStr = VARDATA_ANY(inText); int inSize = VARSIZE_ANY_EXHDR(inText); char *prefixStr = NULL; int prefixSize = 0; int commonLen = 0; int16 nodeChar = 0; int i = 0; /* Check for prefix match, set nodeChar to first byte after prefix */ if (in->hasPrefix) { text *prefixText = DatumGetTextPP(in->prefixDatum); prefixStr = VARDATA_ANY(prefixText); prefixSize = VARSIZE_ANY_EXHDR(prefixText); commonLen = commonPrefix(inStr + in->level, prefixStr, inSize - in->level, prefixSize); if (commonLen == prefixSize) { if (inSize - in->level > commonLen) nodeChar = *(unsigned char *) (inStr + in->level + commonLen); else nodeChar = -1; } else { /* Must split tuple because incoming value doesn't match prefix */ out->resultType = spgSplitTuple; if (commonLen == 0) { out->result.splitTuple.prefixHasPrefix = false; } else { out->result.splitTuple.prefixHasPrefix = true; out->result.splitTuple.prefixPrefixDatum = formTextDatum(prefixStr, commonLen); } out->result.splitTuple.nodeLabel = Int16GetDatum(*(unsigned char *) (prefixStr + commonLen)); if (prefixSize - commonLen == 1) { out->result.splitTuple.postfixHasPrefix = false; } else { out->result.splitTuple.postfixHasPrefix = true; out->result.splitTuple.postfixPrefixDatum = formTextDatum(prefixStr + commonLen + 1, prefixSize - commonLen - 1); } PG_RETURN_VOID(); } } else if (inSize > in->level) { nodeChar = *(unsigned char *) (inStr + in->level); } else { nodeChar = -1; } /* Look up nodeChar in the node label array */ if (searchChar(in->nodeLabels, in->nNodes, nodeChar, &i)) { /* * Descend to existing node. (If in->allTheSame, the core code will * ignore our nodeN specification here, but that's OK. We still have * to provide the correct levelAdd and restDatum values, and those are * the same regardless of which node gets chosen by core.) */ int levelAdd; out->resultType = spgMatchNode; out->result.matchNode.nodeN = i; levelAdd = commonLen; if (nodeChar >= 0) levelAdd++; out->result.matchNode.levelAdd = levelAdd; if (inSize - in->level - levelAdd > 0) out->result.matchNode.restDatum = formTextDatum(inStr + in->level + levelAdd, inSize - in->level - levelAdd); else out->result.matchNode.restDatum = formTextDatum(NULL, 0); } else if (in->allTheSame) { /* * Can't use AddNode action, so split the tuple. The upper tuple has * the same prefix as before and uses a dummy node label -2 for the * lower tuple. The lower tuple has no prefix and the same node * labels as the original tuple. * * Note: it might seem tempting to shorten the upper tuple's prefix, * if it has one, then use its last byte as label for the lower tuple. * But that doesn't win since we know the incoming value matches the * whole prefix: we'd just end up splitting the lower tuple again. */ out->resultType = spgSplitTuple; out->result.splitTuple.prefixHasPrefix = in->hasPrefix; out->result.splitTuple.prefixPrefixDatum = in->prefixDatum; out->result.splitTuple.nodeLabel = Int16GetDatum(-2); out->result.splitTuple.postfixHasPrefix = false; } else { /* Add a node for the not-previously-seen nodeChar value */ out->resultType = spgAddNode; out->result.addNode.nodeLabel = Int16GetDatum(nodeChar); out->result.addNode.nodeN = i; } PG_RETURN_VOID(); }
/// <summary> /// Generates the hierarchy. http://devblogs.nvidia.com/parallelforall/wp-content/uploads/sites/3/2012/11/karras2012hpg_paper.pdf /// </summary> /// <param name="boxes">The boxes.</param> void BVH::generateHierarchyFullParallel(std::vector<AABBox>& boxes) { ProgressBar progressBar; #if !_DEBUG #pragma omp parallel for schedule(dynamic,1) #endif for (int i = 0; i < (boxes.size() - 1); i++) { //first, find the range this node corresponds to //d == -1 means range ends at i, d == +1 means range starts at i int d = sign(commonPrefix(boxes, i, i + 1) - commonPrefix(boxes, i, i - 1)); //find a maximum and minimum value for the range this node covers. Must be a power of two for easy binary searching int min = commonPrefix(boxes, i, i - d); int max = 128; while (commonPrefix(boxes, i, i + (max * d)) > min) { max *= 4; } //use binary serach to find the farthest common prefis that is greater than min int l = 0; for (int t = max >> 1; t >= 1; t = t >> 1) { if (commonPrefix(boxes, i, i + (l + t) * d) > min) { //serach to the right of this value l += t; } } //end of range int j = i + l * d; int first = i; if (d < 0) { first = j; j = i; } // Determine where to split the range. int split = findSplit(boxes, first, j); Node* rightChild; if (split == first) { rightChild = &m_leafNodes[split]; } else { rightChild = &m_branchNodes[split]; } Node* leftChild; if (split + 1 == j) { leftChild = &m_leafNodes[split + 1]; } else { leftChild = &m_branchNodes[split + 1]; } // m_branchNodes[i].m = max; // m_branchNodes[i].re = first; // m_branchNodes[i].rs = j; // m_branchNodes[i].s = split; m_branchNodes[i].rightChild = rightChild; m_branchNodes[i].leftChild = leftChild; // leftChild->parent = &m_branchNodes[i]; // rightChild->parent = &m_branchNodes[i]; #pragma omp critical { progressBar.updateProgress(static_cast<int>((static_cast<float>(i) / boxes.size()) * 100)); } } progressBar.end(); }