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;
    }