12ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/* GENERATED SOURCE. DO NOT MODIFY. */
2f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// © 2016 and later: Unicode, Inc. and others.
3f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License
42ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/*
52ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller*******************************************************************************
62ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller* Copyright (C) 2013-2014, International Business Machines
72ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller* Corporation and others.  All Rights Reserved.
82ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller*******************************************************************************
92ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller* CollationRootElements.java, ported from collationrootelements.h/.cpp
102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller*
112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller* C++ version created on: 2013mar01
122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller* created by: Markus W. Scherer
132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller*/
142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpackage android.icu.impl.coll;
162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/**
182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Container and access methods for collation elements and weights
192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * that occur in the root collator.
202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Needed for finding boundaries for building a tailoring.
212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * This class takes and returns 16-bit secondary and tertiary weights.
23836e6b40a94ec3fb7545a76cb072960442b7eee9Neil Fuller * @hide Only a subset of ICU is exposed in Android
242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */
252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpublic final class CollationRootElements {
262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public CollationRootElements(long[] rootElements) {
272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        elements = rootElements;
282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Higher than any root primary.
322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final long PRIMARY_SENTINEL = 0xffffff00L;
342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Flag in a root element, set if the element contains secondary & tertiary weights,
372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * rather than a primary.
382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int SEC_TER_DELTA_FLAG = 0x80;
402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Mask for getting the primary range step value from a primary-range-end element.
422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int PRIMARY_STEP_MASK = 0x7f;
442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Index of the first CE with a non-zero tertiary weight.
472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Same as the start of the compact root elements table.
482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int IX_FIRST_TERTIARY_INDEX = 0;
502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Index of the first CE with a non-zero secondary weight.
522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    static final int IX_FIRST_SECONDARY_INDEX = 1;
542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Index of the first CE with a non-zero primary weight.
562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    static final int IX_FIRST_PRIMARY_INDEX = 2;
582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Must match Collation.COMMON_SEC_AND_TER_CE.
602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    static final int IX_COMMON_SEC_AND_TER_CE = 3;
622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Secondary & tertiary boundaries.
642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Bits 31..24: [fixed last secondary common byte 45]
652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Bits 23..16: [fixed first ignorable secondary byte 80]
662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Bits 15.. 8: reserved, 0
672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Bits  7.. 0: [fixed first ignorable tertiary byte 3C]
682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    static final int IX_SEC_TER_BOUNDARIES = 4;
702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The current number of indexes.
722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Currently the same as elements[IX_FIRST_TERTIARY_INDEX].
732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    static final int IX_COUNT = 5;
752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the boundary between tertiary weights of primary/secondary CEs
782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * and those of tertiary CEs.
792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * This is the upper limit for tertiaries of primary/secondary CEs.
802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * This minus one is the lower limit for tertiaries of tertiary CEs.
812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public int getTertiaryBoundary() {
832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return ((int)elements[IX_SEC_TER_BOUNDARIES] << 8) & 0xff00;
842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the first assigned tertiary CE.
882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    long getFirstTertiaryCE() {
902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return elements[(int)elements[IX_FIRST_TERTIARY_INDEX]] & ~SEC_TER_DELTA_FLAG;
912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the last assigned tertiary CE.
952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    long getLastTertiaryCE() {
972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return elements[(int)elements[IX_FIRST_SECONDARY_INDEX] - 1] & ~SEC_TER_DELTA_FLAG;
982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the last common secondary weight.
1022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * This is the lower limit for secondaries of primary CEs.
1032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public int getLastCommonSecondary() {
1052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return ((int)elements[IX_SEC_TER_BOUNDARIES] >> 16) & 0xff00;
1062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the boundary between secondary weights of primary CEs
1102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * and those of secondary CEs.
1112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * This is the upper limit for secondaries of primary CEs.
1122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * This minus one is the lower limit for secondaries of secondary CEs.
1132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public int getSecondaryBoundary() {
1152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return ((int)elements[IX_SEC_TER_BOUNDARIES] >> 8) & 0xff00;
1162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the first assigned secondary CE.
1202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    long getFirstSecondaryCE() {
1222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return elements[(int)elements[IX_FIRST_SECONDARY_INDEX]] & ~SEC_TER_DELTA_FLAG;
1232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the last assigned secondary CE.
1272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    long getLastSecondaryCE() {
1292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return elements[(int)elements[IX_FIRST_PRIMARY_INDEX] - 1] & ~SEC_TER_DELTA_FLAG;
1302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the first assigned primary weight.
1342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    long getFirstPrimary() {
1362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return elements[(int)elements[IX_FIRST_PRIMARY_INDEX]];  // step=0: cannot be a range end
1372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the first assigned primary CE.
1412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    long getFirstPrimaryCE() {
1432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return Collation.makeCE(getFirstPrimary());
1442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the last root CE with a primary weight before p.
1482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Intended only for reordering group boundaries.
1492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    long lastCEWithPrimaryBefore(long p) {
1512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(p == 0) { return 0; }
1522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        assert(p > elements[(int)elements[IX_FIRST_PRIMARY_INDEX]]);
1532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int index = findP(p);
1542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long q = elements[index];
1552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long secTer;
1562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(p == (q & 0xffffff00L)) {
1572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // p == elements[index] is a root primary. Find the CE before it.
1582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // We must not be in a primary range.
1592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            assert((q & PRIMARY_STEP_MASK) == 0);
1602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            secTer = elements[index - 1];
1612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if((secTer & SEC_TER_DELTA_FLAG) == 0) {
1622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // Primary CE just before p.
1632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                p = secTer & 0xffffff00L;
1642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                secTer = Collation.COMMON_SEC_AND_TER_CE;
1652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else {
1662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // secTer = last secondary & tertiary for the previous primary
1672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                index -= 2;
1682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                for(;;) {
1692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    p = elements[index];
1702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if((p & SEC_TER_DELTA_FLAG) == 0) {
1712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        p &= 0xffffff00L;
1722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        break;
1732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
1742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    --index;
1752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
1762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
1772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
1782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // p > elements[index] which is the previous primary.
1792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // Find the last secondary & tertiary weights for it.
1802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            p = q & 0xffffff00L;
1812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            secTer = Collation.COMMON_SEC_AND_TER_CE;
1822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            for(;;) {
1832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                q = elements[++index];
1842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if((q & SEC_TER_DELTA_FLAG) == 0) {
1852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // We must not be in a primary range.
1862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    assert((q & PRIMARY_STEP_MASK) == 0);
1872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    break;
1882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
1892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                secTer = q;
1902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
1912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return (p << 32) | (secTer & ~SEC_TER_DELTA_FLAG);
1932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the first root CE with a primary weight of at least p.
1972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Intended only for reordering group boundaries.
1982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    long firstCEWithPrimaryAtLeast(long p) {
2002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(p == 0) { return 0; }
2012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int index = findP(p);
2022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(p != (elements[index] & 0xffffff00L)) {
2032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            for(;;) {
2042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                p = elements[++index];
2052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if((p & SEC_TER_DELTA_FLAG) == 0) {
2062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // First primary after p. We must not be in a primary range.
2072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    assert((p & PRIMARY_STEP_MASK) == 0);
2082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    break;
2092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
2102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // The code above guarantees that p has at most 3 bytes: (p & 0xff) == 0.
2132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return (p << 32) | Collation.COMMON_SEC_AND_TER_CE;
2142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the primary weight before p.
2182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * p must be greater than the first root primary.
2192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    long getPrimaryBefore(long p, boolean isCompressible) {
2212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int index = findPrimary(p);
2222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int step;
2232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long q = elements[index];
2242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(p == (q & 0xffffff00L)) {
2252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // Found p itself. Return the previous primary.
2262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // See if p is at the end of a previous range.
2272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            step = (int)q & PRIMARY_STEP_MASK;
2282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if(step == 0) {
2292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // p is not at the end of a range. Look for the previous primary.
2302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                do {
2312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    p = elements[--index];
2322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                } while((p & SEC_TER_DELTA_FLAG) != 0);
2332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return p & 0xffffff00L;
2342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
2362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // p is in a range, and not at the start.
2372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            long nextElement = elements[index + 1];
2382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            assert(isEndOfPrimaryRange(nextElement));
2392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            step = (int)nextElement & PRIMARY_STEP_MASK;
2402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // Return the previous range primary.
2422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if((p & 0xffff) == 0) {
2432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return Collation.decTwoBytePrimaryByOneStep(p, isCompressible, step);
2442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
2452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return Collation.decThreeBytePrimaryByOneStep(p, isCompressible, step);
2462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /** Returns the secondary weight before [p, s]. */
2502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    int getSecondaryBefore(long p, int s) {
2512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int index;
2522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int previousSec, sec;
2532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(p == 0) {
2542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            index = (int)elements[IX_FIRST_SECONDARY_INDEX];
2552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // Gap at the beginning of the secondary CE range.
2562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            previousSec = 0;
2572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            sec = (int)(elements[index] >> 16);
2582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
2592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            index = findPrimary(p) + 1;
2602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            previousSec = Collation.BEFORE_WEIGHT16;
2612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            sec = (int)getFirstSecTerForPrimary(index) >>> 16;
2622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        assert(s >= sec);
2642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        while(s > sec) {
2652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            previousSec = sec;
2662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            assert((elements[index] & SEC_TER_DELTA_FLAG) != 0);
2672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            sec = (int)(elements[index++] >> 16);
2682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        assert(sec == s);
2702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return previousSec;
2712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /** Returns the tertiary weight before [p, s, t]. */
2742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    int getTertiaryBefore(long p, int s, int t) {
2752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        assert((t & ~Collation.ONLY_TERTIARY_MASK) == 0);
2762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int index;
2772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int previousTer;
2782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long secTer;
2792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(p == 0) {
2802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if(s == 0) {
2812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                index = (int)elements[IX_FIRST_TERTIARY_INDEX];
2822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // Gap at the beginning of the tertiary CE range.
2832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                previousTer = 0;
2842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else {
2852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                index = (int)elements[IX_FIRST_SECONDARY_INDEX];
2862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                previousTer = Collation.BEFORE_WEIGHT16;
2872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            secTer = elements[index] & ~SEC_TER_DELTA_FLAG;
2892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
2902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            index = findPrimary(p) + 1;
2912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            previousTer = Collation.BEFORE_WEIGHT16;
2922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            secTer = getFirstSecTerForPrimary(index);
2932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long st = ((long)s << 16) | t;
2952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        while(st > secTer) {
2962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if((int)(secTer >> 16) == s) { previousTer = (int)secTer; }
2972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            assert((elements[index] & SEC_TER_DELTA_FLAG) != 0);
2982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            secTer = elements[index++] & ~SEC_TER_DELTA_FLAG;
2992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        assert(secTer == st);
3012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return previousTer & 0xffff;
3022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
3032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
3052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Finds the index of the input primary.
3062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * p must occur as a root primary, and must not be 0.
3072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    int findPrimary(long p) {
3092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // Requirement: p must occur as a root primary.
3102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        assert((p & 0xff) == 0);  // at most a 3-byte primary
3112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int index = findP(p);
3122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // If p is in a range, then we just assume that p is an actual primary in this range.
3132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // (Too cumbersome/expensive to check.)
3142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // Otherwise, it must be an exact match.
3152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        assert(isEndOfPrimaryRange(elements[index + 1]) || p == (elements[index] & 0xffffff00L));
3162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return index;
3172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
3182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
3202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the primary weight after p where index=findPrimary(p).
3212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * p must be at least the first root primary.
3222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    long getPrimaryAfter(long p, int index, boolean isCompressible) {
3242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        assert(p == (elements[index] & 0xffffff00L) || isEndOfPrimaryRange(elements[index + 1]));
3252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long q = elements[++index];
3262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int step;
3272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if((q & SEC_TER_DELTA_FLAG) == 0 && (step = (int)q & PRIMARY_STEP_MASK) != 0) {
3282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // Return the next primary in this range.
3292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if((p & 0xffff) == 0) {
3302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return Collation.incTwoBytePrimaryByOffset(p, isCompressible, step);
3312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else {
3322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return Collation.incThreeBytePrimaryByOffset(p, isCompressible, step);
3332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
3352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // Return the next primary in the list.
3362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            while((q & SEC_TER_DELTA_FLAG) != 0) {
3372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                q = elements[++index];
3382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            assert((q & PRIMARY_STEP_MASK) == 0);
3402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return q;
3412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
3432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
3442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the secondary weight after [p, s] where index=findPrimary(p)
3452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * except use index=0 for p=0.
3462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
3472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * <p>Must return a weight for every root [p, s] as well as for every weight
3482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * returned by getSecondaryBefore(). If p!=0 then s can be BEFORE_WEIGHT16.
3492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
3502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * <p>Exception: [0, 0] is handled by the CollationBuilder:
3512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Both its lower and upper boundaries are special.
3522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    int getSecondaryAfter(int index, int s) {
3542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long secTer;
3552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int secLimit;
3562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(index == 0) {
3572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // primary = 0
3582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            assert(s != 0);
3592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            index = (int)elements[IX_FIRST_SECONDARY_INDEX];
3602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            secTer = elements[index];
3612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // Gap at the end of the secondary CE range.
3622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            secLimit = 0x10000;
3632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
3642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            assert(index >= (int)elements[IX_FIRST_PRIMARY_INDEX]);
3652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            secTer = getFirstSecTerForPrimary(index + 1);
3662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // If this is an explicit sec/ter unit, then it will be read once more.
3672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // Gap for secondaries of primary CEs.
3682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            secLimit = getSecondaryBoundary();
3692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for(;;) {
3712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int sec = (int)(secTer >> 16);
3722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if(sec > s) { return sec; }
3732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            secTer = elements[++index];
3742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if((secTer & SEC_TER_DELTA_FLAG) == 0) { return secLimit; }
3752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
3772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
3782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the tertiary weight after [p, s, t] where index=findPrimary(p)
3792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * except use index=0 for p=0.
3802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
3812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * <p>Must return a weight for every root [p, s, t] as well as for every weight
3822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * returned by getTertiaryBefore(). If s!=0 then t can be BEFORE_WEIGHT16.
3832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
3842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * <p>Exception: [0, 0, 0] is handled by the CollationBuilder:
3852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Both its lower and upper boundaries are special.
3862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    int getTertiaryAfter(int index, int s, int t) {
3882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long secTer;
3892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int terLimit;
3902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(index == 0) {
3912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // primary = 0
3922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if(s == 0) {
3932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                assert(t != 0);
3942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                index = (int)elements[IX_FIRST_TERTIARY_INDEX];
3952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // Gap at the end of the tertiary CE range.
3962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                terLimit = 0x4000;
3972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else {
3982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                index = (int)elements[IX_FIRST_SECONDARY_INDEX];
3992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // Gap for tertiaries of primary/secondary CEs.
4002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                terLimit = getTertiaryBoundary();
4012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
4022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            secTer = elements[index] & ~SEC_TER_DELTA_FLAG;
4032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
4042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            assert(index >= (int)elements[IX_FIRST_PRIMARY_INDEX]);
4052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            secTer = getFirstSecTerForPrimary(index + 1);
4062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // If this is an explicit sec/ter unit, then it will be read once more.
4072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            terLimit = getTertiaryBoundary();
4082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
4092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long st = (((long)s & 0xffffffffL) << 16) | t;
4102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for(;;) {
4112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if(secTer > st) {
4122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                assert((secTer >> 16) == s);
4132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return (int)secTer & 0xffff;
4142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
4152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            secTer = elements[++index];
4162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // No tertiary greater than t for this primary+secondary.
4172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if((secTer & SEC_TER_DELTA_FLAG) == 0 || (secTer >> 16) > s) { return terLimit; }
4182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            secTer &= ~SEC_TER_DELTA_FLAG;
4192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
4202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
4212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
4232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the first secondary & tertiary weights for p where index=findPrimary(p)+1.
4242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
4252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private long getFirstSecTerForPrimary(int index) {
4262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long secTer = elements[index];
4272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if((secTer & SEC_TER_DELTA_FLAG) == 0) {
4282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // No sec/ter delta.
4292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return Collation.COMMON_SEC_AND_TER_CE;
4302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
4312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        secTer &= ~SEC_TER_DELTA_FLAG;
4322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if(secTer > Collation.COMMON_SEC_AND_TER_CE) {
4332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // Implied sec/ter.
4342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return Collation.COMMON_SEC_AND_TER_CE;
4352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
4362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // Explicit sec/ter below common/common.
4372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return secTer;
4382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
4392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
4412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Finds the largest index i where elements[i]<=p.
4422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Requires first primary<=p<0xffffff00 (PRIMARY_SENTINEL).
4432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Does not require that p is a root collator primary.
4442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
4452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private int findP(long p) {
4462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // p need not occur as a root primary.
4472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // For example, it might be a reordering group boundary.
4482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        assert((p >> 24) != Collation.UNASSIGNED_IMPLICIT_BYTE);
4492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // modified binary search
4502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int start = (int)elements[IX_FIRST_PRIMARY_INDEX];
4512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        assert(p >= elements[start]);
4522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int limit = elements.length - 1;
4532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        assert(elements[limit] >= PRIMARY_SENTINEL);
4542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        assert(p < elements[limit]);
4552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        while((start + 1) < limit) {
4562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // Invariant: elements[start] and elements[limit] are primaries,
4572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // and elements[start]<=p<=elements[limit].
458f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            int i = (int)(((long)start + (long)limit) / 2);
4592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            long q = elements[i];
4602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if((q & SEC_TER_DELTA_FLAG) != 0) {
4612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // Find the next primary.
4622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                int j = i + 1;
4632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                for(;;) {
4642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if(j == limit) { break; }
4652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    q = elements[j];
4662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if((q & SEC_TER_DELTA_FLAG) == 0) {
4672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        i = j;
4682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        break;
4692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
4702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    ++j;
4712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
4722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if((q & SEC_TER_DELTA_FLAG) != 0) {
4732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    // Find the preceding primary.
4742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    j = i - 1;
4752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    for(;;) {
4762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        if(j == start) { break; }
4772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        q = elements[j];
4782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        if((q & SEC_TER_DELTA_FLAG) == 0) {
4792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            i = j;
4802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            break;
4812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        }
4822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        --j;
4832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
4842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if((q & SEC_TER_DELTA_FLAG) != 0) {
4852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        // No primary between start and limit.
4862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        break;
4872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
4882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
4892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
4902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if(p < (q & 0xffffff00L)) {  // Reset the "step" bits of a range end primary.
4912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                limit = i;
4922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else {
4932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                start = i;
4942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
4952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
4962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return start;
4972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
4982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static boolean isEndOfPrimaryRange(long q) {
5002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return (q & SEC_TER_DELTA_FLAG) == 0 && (q & PRIMARY_STEP_MASK) != 0;
5012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
5022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
5042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Data structure: See ICU4C source/i18n/collationrootelements.h.
5052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
5062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private long[] elements;
5072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller}
508