void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { mwSize n; /* output data */ double *ancestors; /* arguments */ const mxArray* dag; const mxArray* s; if (nrhs != 2) { mexErrMsgTxt("2 inputs required."); } dag = prhs[0]; s = prhs[1]; n = mxGetN(dag); /* The first input must be a sparse matrix. */ if (mxGetM(dag) != mxGetN(dag) || mxIsSparse(dag) || !mxIsDouble(dag)) { mexErrMsgTxt("Input must be a noncomplex square non-sparse matrix of type 'double'."); } plhs[0] = mxCreateDoubleMatrix(1,n,mxREAL); ancestors = mxGetPr(plhs[0]); findAncestors(mxGetPr(dag), ancestors, (int) *mxGetPr(s)-1, n); }
bool localeDataIsCloseToUsEnglish(const char *region) { const uint32_t locale = packLocale(ENGLISH_CHARS, region); ssize_t stop_list_index; findAncestors(nullptr, &stop_list_index, locale, LATIN_CHARS, ENGLISH_STOP_LIST, 2); // A locale is like US English if we see "en" before "en-001" in its ancestor list. return stop_list_index == 0; // 'en' is first in ENGLISH_STOP_LIST }
void findAncestors(const double *dag, double *ancestors, int i, int n) { int cur; // Now visit each parent for(cur = 0; cur < n; ++cur) { if(!ancestors[cur] && *(dag + i * n + cur)) { ancestors[cur] = 1; findAncestors(dag, ancestors, cur, n); } } }
size_t findDistance(uint32_t supported, const char *script, const uint32_t *request_ancestors, size_t request_ancestors_count) { ssize_t request_ancestors_index; const size_t supported_ancestor_count = findAncestors( nullptr, &request_ancestors_index, supported, script, request_ancestors, request_ancestors_count); // Since both locales share the same root, there will always be a shared // ancestor, so the distance in the parent tree is the sum of the distance // of 'supported' to the lowest common ancestor (number of ancestors // written for 'supported' minus 1) plus the distance of 'request' to the // lowest common ancestor (the index of the ancestor in request_ancestors). return supported_ancestor_count + request_ancestors_index - 1; }
int localeDataCompareRegions( const char *left_region, const char *right_region, const char *requested_language, const char *requested_script, const char *requested_region) { if (left_region[0] == right_region[0] && left_region[1] == right_region[1]) { return 0; } uint32_t left = packLocale(requested_language, left_region); uint32_t right = packLocale(requested_language, right_region); const uint32_t request = packLocale(requested_language, requested_region); // If one and only one of the two locales is a special Spanish locale, we // replace it with es-419. We don't do the replacement if the other locale // is already es-419, or both locales are special Spanish locales (when // es-US is being compared to es-MX). const bool leftIsSpecialSpanish = isSpecialSpanish(left); const bool rightIsSpecialSpanish = isSpecialSpanish(right); if (leftIsSpecialSpanish && !rightIsSpecialSpanish && right != LATIN_AMERICAN_SPANISH) { left = LATIN_AMERICAN_SPANISH; } else if (rightIsSpecialSpanish && !leftIsSpecialSpanish && left != LATIN_AMERICAN_SPANISH) { right = LATIN_AMERICAN_SPANISH; } uint32_t request_ancestors[MAX_PARENT_DEPTH + 1]; ssize_t left_right_index; // Find the parents of the request, but stop as soon as we saw left or right const std::array<uint32_t, 2> left_and_right = {{left, right}}; const size_t ancestor_count = findAncestors( request_ancestors, &left_right_index, request, requested_script, left_and_right.data(), left_and_right.size()); if (left_right_index == 0) { // We saw left earlier return 1; } if (left_right_index == 1) { // We saw right earlier return -1; } // If we are here, neither left nor right are an ancestor of the // request. This means that all the ancestors have been computed and // the last ancestor is just the language by itself. We will use the // distance in the parent tree for determining the better match. const size_t left_distance = findDistance( left, requested_script, request_ancestors, ancestor_count); const size_t right_distance = findDistance( right, requested_script, request_ancestors, ancestor_count); if (left_distance != right_distance) { return (int) right_distance - (int) left_distance; // smaller distance is better } // If we are here, left and right are equidistant from the request. We will // try and see if any of them is a representative locale. const bool left_is_representative = isRepresentative(left, requested_script); const bool right_is_representative = isRepresentative(right, requested_script); if (left_is_representative != right_is_representative) { return (int) left_is_representative - (int) right_is_representative; } // We have no way of figuring out which locale is a better match. For // the sake of stability, we consider the locale with the lower region // code (in dictionary order) better, with two-letter codes before // three-digit codes (since two-letter codes are more specific). return (int64_t) right - (int64_t) left; }