
public final class Arrays
{
    private Arrays() {}


    public static Object subarray(Object array, int start, int n)
    {
        Object subarray = java.lang.reflect.Array.newInstance(
                                array.getClass().getComponentType(), n);
        System.arraycopy(array, start, subarray, 0, n);
        return subarray;
    }
    public static Object[] subarray(Object arrayOfArrays[],
                                    int startRow, int nRows,
                                    int startCol, int nCols)
    {
        Object subarrayOfArrays[] = (Object[])java.lang.reflect.Array.newInstance(arrayOfArrays.getClass().getComponentType(), nRows);
        for (int iRow = 0; (iRow) < (nRows); ++iRow)
            subarrayOfArrays[iRow] = subarray(arrayOfArrays[startRow+iRow],
                                              startCol, nCols);
        return subarrayOfArrays;
    }
    public static Object subarray(Object arrayOfArraysOfArrays[][],
                                  int startLayer, int nLayers,
                                  int startRow, int nRows,
                                  int startCol, int nCols)
    {
        Object subarrayOfArraysOfArrays[][] = (Object[][])java.lang.reflect.Array.newInstance(arrayOfArraysOfArrays.getClass().getComponentType(), nLayers);
        for (int iLayer = 0; (iLayer) < (nLayers); ++iLayer)
            subarrayOfArraysOfArrays[iLayer] = subarray(arrayOfArraysOfArrays[startLayer+iLayer],
                                                        startRow, nRows,
                                                        startCol, nCols);
        return subarrayOfArraysOfArrays;
    }

    public static Object subarray(Object array, int start, int n, boolean which[])
    {
        int subarrayLength = subarrayLength(array, start, n, 1, which);
        Object subarray = java.lang.reflect.Array.newInstance(
                                array.getClass().getComponentType(), subarrayLength);
        int iNew = 0;
        for (int iOld = 0; (iOld) < (n); ++iOld)
        {
            if (which == null
             || which[start+iOld])
            java.lang.reflect.Array.set(subarray, iNew++,
                java.lang.reflect.Array.get(array, start+iOld));
        }
        { if (!(iNew == subarrayLength)) throw new Error("Assertion failed at "+"Arrays.java"+"("+71 +"): " + "iNew == subarrayLength" + ""); };
        return subarray;
    }

    public static Object subarray(Object array, boolean which[])
    {
        if (which == null)
            return array;
        return subarray(array, 0, java.lang.reflect.Array.getLength(array), which);
    }




    public static double[] append(double v[], double last)
    {
        int i, n = v.length;
        double result[] = new double[n+1];
        System.arraycopy(v, 0, result, 0, n);
        result[n] = last;
        return result;
    }
    public static int[] append(int v[], int last)
    {
        int i, n = v.length;
        int result[] = new int[n+1];
        System.arraycopy(v, 0, result, 0, n);
        result[n] = last;
        return result;
    }

    public static Object append(Object array,
                                Object last)
    {
        int n = java.lang.reflect.Array.getLength(array);
        Object result = java.lang.reflect.Array.newInstance(
                                array.getClass().getComponentType(), n+1);
        System.arraycopy(array, 0, result, 0, n);
        java.lang.reflect.Array.set(result, n, last);
        return result;
    }

    public static Object append2(Object array,
                                 Object secondToLast,
                                 Object last)
    {
        return append(append(array, secondToLast),last);
    }





    public static Object concat(Object array0,
                                Object array1)
    {



        int n0 = java.lang.reflect.Array.getLength(array0);
        int n1 = java.lang.reflect.Array.getLength(array1);
        Object newArray = java.lang.reflect.Array.newInstance(
                                    array0.getClass().getComponentType(),
                                    n0 + n1);
        System.arraycopy(array0, 0, newArray, 0, n0);
        System.arraycopy(array1, 0, newArray, n0, n1);
        return newArray;
    }

    public static Object concat3(Object a0, Object a1, Object a2)
    {

        return flatten(new Object[]{a0,a1,a2}, 0, 2);
    }

    public static void copy(Object to, Object from, int depth)
    {
        { if (!(depth >= 1)) throw new Error("Assertion failed at "+"Arrays.java"+"("+155 +"): " + "depth >= 1" + ""); };
        {
            int n = java.lang.reflect.Array.getLength(from);
            { if (!(n == java.lang.reflect.Array.getLength(to))) throw new Error("Assertion failed at "+"Arrays.java"+"("+158 +"): " + "n == java.lang.reflect.Array.getLength(to)" + ""); };
            if (depth == 1)
                System.arraycopy(from, 0,
                                 to, 0,
                                 n);
            else
                for (int i = 0; (i) < (n); ++i)
                    copy(java.lang.reflect.Array.get(to, i),
                         java.lang.reflect.Array.get(from, i),
                         depth-1);
        }
    }
    public static Object copy(Object from, int depth)
    {
        if (depth == 0)
            return from;
        { if (!(depth >= 1)) throw new Error("Assertion failed at "+"Arrays.java"+"("+174 +"): " + "depth >= 1" + ""); };
        {
            int n = java.lang.reflect.Array.getLength(from);
            Object to = java.lang.reflect.Array.newInstance(
                                from.getClass().getComponentType(),
                                n);
            if (depth == 1)
                System.arraycopy(from, 0,
                                 to, 0,
                                 n);
            else
                for (int i = 0; (i) < (n); ++i)
                    java.lang.reflect.Array.set(to, i,
                                copy(java.lang.reflect.Array.get(from,i),
                                     depth-1));
            return to;
        }
    }
    
    public static Object get(Object array, Object indices)
    {
        Class indicesClass = indices.getClass();


        if (true)
        {
            if (indicesClass == int[].class)
            {
                int ints[] = (int[])indices;
                int n = ints.length;
                Object result = java.lang.reflect.Array.newInstance(array.getClass().getComponentType(), n);
                for (int i = 0; (i) < (n); ++i)
                    java.lang.reflect.Array.set(result, i,
                            java.lang.reflect.Array.get(array, ints[i]));
                return result;
            }
        }

{ if (!(false)) throw new Error("Assertion failed at "+"Arrays.java"+"("+223 +"): " + "false" + ""); };

        if (indicesClass == Integer.class)
            return java.lang.reflect.Array.get(array, ((Integer)indices).intValue());
        int n = java.lang.reflect.Array.getLength(indices);
        Object result = java.lang.reflect.Array.newInstance(
                getClassOfArrayOf(array.getClass().getComponentType(), getDim(indices)-1),
                n);
        for (int i = 0; (i) < (n); ++i)
        {
            java.lang.reflect.Array.set(result, i,
                get(array, java.lang.reflect.Array.get(indices, i)));
        }
        return result;
    }

    public static Object[] nodupUsingEqualsSymbol(Object[] oldArray)
    {
        int oldI, oldN = oldArray.length;
        Object newArray[] = (Object[])java.lang.reflect.Array.newInstance(
                                    oldArray.getClass().getComponentType(),
                                    oldN);
        int newN = 0;
        for (oldI = 0; (oldI) < (oldN); ++oldI)
        {
            if (oldI == 0
             || oldArray[oldI] != oldArray[oldI-1])
                newArray[newN++] = oldArray[oldI];
        }
        return (Object[])subarray(newArray, 0, newN);
    }







    public static Object[] insertAtNullOrAppend(Object[] array,
                                                Object item)
    {
        {
            int ind = indexOfUsingEqualsSymbol(array, null);
            if (ind != -1)
            {
                array[ind] = item;
                return array;
            }
        }

        {
            int n = array.length;
            int newN = ((n+1)>=(n*3/2)?(n+1):(n*3/2));
            Object newArray[] = (Object[])java.lang.reflect.Array.newInstance(
                                    array.getClass().getComponentType(), newN);
            System.arraycopy(array, 0, newArray, 0, n);
            newArray[n] = item;
            return newArray;
        }
    }

    public static int numNonNulls(Object[] array)
    {
        int numNonNulls = 0;
        int i, n = array.length;
        for (i = 0; (i) < (n); ++i)
            if (array[i] != null)
                numNonNulls++;
        return numNonNulls;
    }

    public static int arrayLength(Object array,
                                  int depth)
    {
        return arrayLength(array, depth, null);
    }

    public static int arrayLength(Object array, int depth, boolean which[])
    {
        if (depth == 0)
            return 1;
        int n = java.lang.reflect.Array.getLength(array);
        return subarrayLength(array, 0, n, depth, which);
    }

    public static int subarrayLength(Object array,
                                     int start, int n,
                                     int depth,
                                     boolean which[])
    {
        { if (!(depth >= 1)) throw new Error("Assertion failed at "+"Arrays.java"+"("+339 +"): " + "depth >= 1" + ""); };
        {
            if (depth == 1)
            {
                if (which == null)
                {



                    return n;
                }
                else
                {
                    int sum = 0;
                    for (int i = 0; (i) < (n); ++i)
                        if (which[start+i])
                            sum++;
                    return sum;
                }
            }
        }
        int sum = 0;
        for (int i = 0; (i) < (n); ++i)
        {
            if (which == null
             || which[start+i])
            sum += arrayLength(((Object[])array)[start+i], depth-1);
        }
        return sum;
    }


    public static Object arrayLengths(Object array,
                                      int startDepth,
                                      int furtherDepth)
    {

        if (startDepth == 0)
            return new Integer(arrayLength(array, furtherDepth));

        int n = java.lang.reflect.Array.getLength(array);
        if (startDepth == 1)
        {
            int result[] = new int[n];
            for (int i = 0; (i) < (n); ++i)
                result[i] = arrayLength(java.lang.reflect.Array.get(array,i),
                                        furtherDepth);
            return result;
        }


        Object temp[] = new Object[n];
        for (int i = 0; (i) < (n); ++i)
            temp[i] = arrayLengths(java.lang.reflect.Array.get(array,i),
                                   startDepth-1,
                                   furtherDepth);
        Object result = java.lang.reflect.Array.newInstance(
                                                  temp[0].getClass(), n);
        System.arraycopy(temp, 0, result, 0, n);
        return result;
    }



    public static int getDim(Object array)
    {
        int dim = 0;
        Class c = array.getClass();
        while ((c = c.getComponentType()) != null)
            dim++;
        return dim;
    }
    private static Class getClassOfArrayOf(Class clazz, int dim)
    {
        for (int i = 0; (i) < (dim); ++i)
            clazz = java.lang.reflect.Array.newInstance(clazz,0).getClass();
        return clazz;
    }
    private static Class getComponentType(Class clazz, int depth)
    {
        for (int i = 0; (i) < (depth); ++i)
            clazz = clazz.getComponentType();
        return clazz;
    }






    public static int getDimExtent(Object array)
    {
        if (array == null)
            return 0;
        Class c = array.getClass();
        if (!c.isArray())
            return 0;
        int n = java.lang.reflect.Array.getLength(array);
        int maxComponentDim = 0;
        for (int i = 0; (i) < (n); ++i)
        {
            int componentDim = getDimExtent(java.lang.reflect.Array.get(array,i));
            maxComponentDim = ((maxComponentDim)>=(componentDim)?(maxComponentDim):(componentDim));
        }
        return maxComponentDim + 1;
    }

    public static Object makeArrayOfIndices(Object array, int depth)
    {
        int currentIndex[] = new int[depth];
        return _makeArrayOfIndices(array, depth, currentIndex);
    }

        private static Object _makeArrayOfIndices(Object array, int depth, int currentIndex[])
        {
            if (depth == 0)
                return (int[])Arrays.copy(currentIndex, 1);

            int arrayLength = java.lang.reflect.Array.getLength(array);
            int fullDepth = currentIndex.length;
            int indexIntoCurrentIndex = currentIndex.length - depth;

            if (depth == 1)
            {
                int inds[][] = new int[arrayLength][fullDepth];
                for (int i = 0; (i) < (arrayLength); ++i)
                {
                    currentIndex[indexIntoCurrentIndex] = i;
                    System.arraycopy(currentIndex, 0,
                                     inds[i], 0,
                                     fullDepth);
                }
                return inds;
            }
            else
            {
                { if (!(depth > 1)) throw new Error("Assertion failed at "+"Arrays.java"+"("+487 +"): " + "depth > 1" + ""); };
                Object inds[] = (Object[])java.lang.reflect.Array.newInstance(
                                    Arrays.getClassOfArrayOf(int[].class, depth-1),
                                    arrayLength);
                { if (!(getDim(inds) == depth+1)) throw new Error("Assertion failed at "+"Arrays.java"+"("+491 +"): " + "getDim(inds) == depth+1" + ""); };
                for (int i = 0; (i) < (arrayLength); ++i)
                {
                    currentIndex[indexIntoCurrentIndex] = i;
                    inds[i] = _makeArrayOfIndices(java.lang.reflect.Array.get(array, i), depth-1, currentIndex);
                }
                return inds;
            }
        }


    public static Object removeNulls(Object oldArray[])
    {
        int nOld = oldArray.length;
        int nNew = 0;
        for (int iOld = 0; (iOld) < (nOld); ++iOld)
            if (oldArray[iOld] != null)
                nNew++;
        Object newArray[] = (Object[])java.lang.reflect.Array.newInstance(oldArray.getClass().getComponentType(), nNew);
        int iNew = 0;
        for (int iOld = 0; (iOld) < (nOld); ++iOld)
        {
            Object oldItem = oldArray[iOld];
            if (oldItem != null)
                newArray[iNew++] = oldItem;
        }
        return newArray;
    }

    public static Object flatten(Object array,
                                 int startDepth,
                                 int furtherDepth)
    {
        if (furtherDepth == 1)
            return array;
        int nFlat = arrayLength(array, (startDepth==0 ? furtherDepth : 1));
        Object flatArray = java.lang.reflect.Array.newInstance(
                       getComponentType(getUnwrappedClass(array), furtherDepth),
                       nFlat);
        if (startDepth == 0)
        {
            int pos = _flatten(flatArray, 0, array, furtherDepth);
            { if (!(pos == nFlat)) throw new Error("Assertion failed at "+"Arrays.java"+"("+541 +"): " + "pos == nFlat" + ""); };
        }
        else
        {
            { if (!(startDepth >= 1)) throw new Error("Assertion failed at "+"Arrays.java"+"("+545 +"): " + "startDepth >= 1" + ""); };
            for (int i = 0; (i) < (nFlat); ++i)
                java.lang.reflect.Array.set(flatArray,i,
                            flatten(java.lang.reflect.Array.get(array,i),
                                    startDepth-1,
                                    furtherDepth));
        }
        return flatArray;
    }


        private static int _flatten(Object dest,
                                    int pos,
                                    Object array,
                                    int nDimsToFlattenIntoOne)
        {
            if (nDimsToFlattenIntoOne == 0)
            {
                java.lang.reflect.Array.set(dest, pos, array);
                pos++;
            }
            else if (nDimsToFlattenIntoOne == 1)
            {
                int n = java.lang.reflect.Array.getLength(array);
                System.arraycopy(array, 0,
                                 dest, pos,
                                 n);
                pos += n;
            }
            else
            {
                { if (!(nDimsToFlattenIntoOne >= 2)) throw new Error("Assertion failed at "+"Arrays.java"+"("+576 +"): " + "nDimsToFlattenIntoOne >= 2" + ""); };
                int n = java.lang.reflect.Array.getLength(array);
                for (int i = 0; (i) < (n); ++i)
                    pos = _flatten(dest, pos,
                                   java.lang.reflect.Array.get(array,i),
                                   nDimsToFlattenIntoOne-1);
            }
            return pos;
        }

    public static Object flatten(Object array,
                                 int startDepth,
                                 int furtherDepth,
                                 boolean which[])
    {
        return flatten(subarray(array,which), startDepth, furtherDepth);
    }




    public static void fill(Object array, Object item)
    {
        int n = java.lang.reflect.Array.getLength(array);
        for (int i = 0; (i) < (n); ++i)
            java.lang.reflect.Array.set(array, i, item);
    }

    public static Object fill(int n, Object item)
    {
        Object result = java.lang.reflect.Array.newInstance(
                                            getUnwrappedClass(item), n);
        fill(result, item);
        return result;
    }
    public static int[] fill(int n, int item)
    {
        return (int[])fill(n, new Integer(item));
    }

    public static void reverse(int to[], int from[])
    {
        int n = from.length;
        { if (!(n == to.length)) throw new Error("Assertion failed at "+"Arrays.java"+"("+619 +"): " + "n == to.length" + ""); };
        if (to == from)
        {
            int temp;
            int halfN = n/2;
            for (int i = 0; (i) < (halfN); ++i)
                {temp=(to[i]);to[i]=(to[n-1-i]);to[n-1-i]=(temp);};
        }
        else
        {
            for (int i = 0; (i) < (n); ++i)
                to[i] = from[n-1-i];
        }
    }
    public static void reverse(Object to, Object from)
    {
        int n = java.lang.reflect.Array.getLength(from);
        { if (!(n == java.lang.reflect.Array.getLength(to))) throw new Error("Assertion failed at "+"Arrays.java"+"("+636 +"): " + "n == java.lang.reflect.Array.getLength(to)" + ""); };
        if (to == from)
        {
            int halfN = n/2;
            for (int i = 0; (i) < (halfN); ++i)
                swap(to, i, to, n-1-i);
        }
        else
        {
            for (int i = 0; (i) < (n); ++i)
                java.lang.reflect.Array.set(to, i,
                                    java.lang.reflect.Array.get(from, i));
        }
    }




    public static void swap(Object array0, int i0,
                            Object array1, int i1)
    {
        Object temp = java.lang.reflect.Array.get(array0, i0);
        java.lang.reflect.Array.set(array0, i0,
                                    java.lang.reflect.Array.get(array1, i1));
        java.lang.reflect.Array.set(array1, i1, temp);
    }







    public static Object singleton(Object item)
    {
        return fill(1, item);
    }


    public static int indexOf(boolean Array[], boolean item)
    {
        int i, n = Array.length;
        for (i = 0; (i) < (n); ++i)
            if (Array[i] == item)
                return i;
        return -1;
    }
    public static int indexOf(int Array[], int item)
    {
        int i, n = Array.length;
        for (i = 0; (i) < (n); ++i)
            if (Array[i] == item)
                return i;
        return -1;
    }
    public static int indexOfUsingEqualsSymbol(Object Array[], Object item)
    {
        int i, n = Array.length;
        for (i = 0; (i) < (n); ++i)
            if (Array[i] == item)
                return i;
        return -1;
    }





    public static Class getUnwrappedClass(Object item)
    {
        return item instanceof Number ?
                   item instanceof Byte ? byte.class :
                   item instanceof Double ? double.class :
                   item instanceof Float ? float.class :
                   item instanceof Integer ? int.class :
                   item instanceof Long ? long.class :
                   item instanceof Short ? short.class :
                   item.getClass() :
               item instanceof Boolean ? boolean.class :
               item instanceof Character ? char.class :
               item.getClass();
    }
    public static Class getWrapperClass(Class c)
    {
        if (!c.isPrimitive())
            return c;
        return c == byte.class ? Byte.class :
               c == double.class ? Double.class :
               c == float.class ? Float.class :
               c == int.class ? Integer.class :
               c == long.class ? Long.class :
               c == short.class ? Short.class :
               c == boolean.class ? Boolean.class :
               c == char.class ? Character.class :
               c;
    }





    public static int randomIndex(int n, java.util.Random rng)
    {
        if (n<=0)
            throw new IllegalArgumentException("n must be positive");

        if ((n & -n) == n)

            return (int)((n * (long)(rng.nextInt()&~(1<<31))) >> 31);

        int bits, val;
        do {

            bits = rng.nextInt()&~(1<<31);
            val = bits % n;
        } while(bits - val + (n-1) < 0);
        return val;
    }





    public static void shuffle(Object array, java.util.Random rng)
    {
        int n = java.lang.reflect.Array.getLength(array);
        for (int i = 1; i < n; ++i)
        {
            int j = randomIndex(i+1, rng);
            if (j != i)
                swap(array, i, array, j);
        }
    }


    public static String toString(Object array,
                                  String preSepSuf[][ ],
                                  int indexIntoPSS)
    {
        if (array == null)
            return "null";




        if (!array.getClass().isArray())
            return array.toString();

        String prefix = preSepSuf[indexIntoPSS][0];
        String separator = preSepSuf[indexIntoPSS][1];
        String suffix = preSepSuf[indexIntoPSS][2];

        int n = java.lang.reflect.Array.getLength(array);
        StringBuffer sb = new StringBuffer();
        sb.append(prefix);
        for (int i = 0; (i) < (n); ++i)
        {
            sb.append(toString(java.lang.reflect.Array.get(array, i),
                               preSepSuf,
                               indexIntoPSS+1));
            if (i+1 < n)
                sb.append(separator);
        }
        sb.append(suffix);
        return sb.toString();
    }

    public static String toString(Object array,
                                  String prefix,
                                  String separator,
                                  String suffix)
    {
        if (array == null)
            return "null";
        return toString(array,
                        (String[][ ])fill(
                                              getDimExtent(array),
                                              new String[]{prefix,
                                                           separator,
                                                           suffix}),
                        0);
    }

    public static String toStringCompact(Object array)
    {
        return toString(array, "{", ",", "}");
    }


    public static String toStringNonCompact(Object array,
                                            String indentString,
                                            String indentIncr)
    {
        String newline = System.getProperty("line.separator");
        int nDims = getDimExtent(array);
        String pss[][] = new String[nDims][ ];
        String levelIndentString = indentString;
        for (int iDim = 0; (iDim) < (nDims); ++iDim)
        {
            String pre, sep, suf;
            if (nDims-iDim == 1)
            {
                pre = levelIndentString + "{";
                sep = ",";
                suf = "}";
            }
            else
            {
                pre = levelIndentString + "{" + newline;
                sep = "," + newline;
                suf = newline + levelIndentString + "}";
            }
            pss[iDim] = new String[] {pre,sep,suf};
            levelIndentString += indentIncr;
        }
        return toString(array, pss, 0);
    }

    public static Object fromString(String s)
        throws java.text.ParseException
    {
        java.text.ParsePosition pos = new java.text.ParsePosition(0);
        Object obj = new ArrayFormat().parseObjectSucceedOrThrowAnException(s, pos, s.length());
        return obj;
    }





    public static class ArrayFormat
        extends java.text.Format
    {




            public StringBuffer format(Object obj, StringBuffer toAppendTo, java.text.FieldPosition pos)
            {
                toAppendTo.append(toStringCompact(obj));

                return toAppendTo;
            }

            public Object parseObject(String s, java.text.ParsePosition pos)
            {
                int startPos = pos.getIndex();
                try
                {
                    return parseObjectSucceedOrThrowAnException(s, pos, s.length());
                }
                catch (java.text.ParseException e)
                {
                    pos.setIndex(startPos);
                    return null;
                }
            }







            public Object parseObjectSucceedOrThrowAnException(String s, java.text.ParsePosition pos, int end)
                throws java.text.ParseException
            {
                return parseObject(s, pos, end,
                                   guessClass(s, pos.getIndex(), s.length()));
            }

            private String removeComments(String in)
            {
                StringBuffer sb = new StringBuffer();
                boolean inSlashSlashComment = false;
                int nIn = in.length();
                for (int iIn = 0; (iIn) < (nIn); ++iIn)
                {
                    char c = in.charAt(iIn);
                    if (c == '/'
                     && iIn+1 < nIn
                     && in.charAt(iIn+1) == '/')
                        inSlashSlashComment = true;
                    else if (c == '\n')
                        inSlashSlashComment = false;

                    if (!inSlashSlashComment)
                        sb.append(c);
                }
                return sb.toString();
            }

            public Object parseObject(String s,
                                      java.text.ParsePosition pos,
                                      int end,
                                      Class clazz)
                throws java.text.ParseException
            {
                s = removeComments(s);
                Object obj = null;
                if (clazz.isArray())
                {

                    int i = pos.getIndex();
                    do {while ((i) < (end) && Character.isWhitespace(s.charAt(i))) i++;} while (false);
                    if (end-i >= 4
                     && s.startsWith("null", i))
                    {
                        i += 4;
                        obj = null;
                    }
                    else if (end-i >= 1 && s.charAt(i) == '{')
                    {
                        i++;
                        do {while ((i) < (end) && Character.isWhitespace(s.charAt(i))) i++;} while (false);
                        if (end-i >= 1 && s.charAt(i) == '}')
                        {
                            i++;
                            obj = java.lang.reflect.Array.newInstance(clazz.getComponentType(),0);
                        }
                        else
                        {
                            java.util.Vector v = new java.util.Vector();
                            while (true)
                            {
                                pos.setIndex(i);
                                v.addElement(parseObject(s, pos,
                                                         end,
                                                         clazz.getComponentType()));
                                i = pos.getIndex();

                                do {while ((i) < (end) && Character.isWhitespace(s.charAt(i))) i++;} while (false);


                                if (end-i >= 1 && s.charAt(i) == ',')
                                {
                                    i++;
                                    do {while ((i) < (end) && Character.isWhitespace(s.charAt(i))) i++;} while (false);
                                    if (end-i >= 1 && s.charAt(i) == '}')
                                    {
                                        i++;
                                        break;
                                    }
                                }
                                else if (end-i >= 1 && s.charAt(i) == '}')
                                {
                                    i++;
                                    break;
                                }
                                else
                                {
                                    if (end-i >= 1)
                                        throw new java.text.ParseException("unexpected char '"+s.charAt(i)+"' between array elements", i);
                                    else
                                        throw new java.text.ParseException("unmatched '{'", i);
                                }
                            }
                            obj = java.lang.reflect.Array.newInstance(clazz.getComponentType(),v.size());
                            if (false)
                            {
                                v.copyInto((Object[])obj);
                            }
                            else
                            {
                                int n = v.size();
                                for (int ii = 0; (ii) < (n); ++ii)
                                    java.lang.reflect.Array.set(obj,ii,
                                                                v.elementAt(ii));
                            }
                        }
                    }
                    else
                        throw new java.text.ParseException("can't parse array", i);
                    pos.setIndex(i);
                }
                else if (clazz == boolean.class)
                {
                    int i = pos.getIndex();
                    if (end-i >= 4
                     && s.startsWith("true", i))
                    {
                        i += 4;
                        obj = new Boolean(true);
                    }
                    else if (end-i >= 5
                          && s.startsWith("false", i))
                    {
                        i += 5;
                        obj = new Boolean(false);
                    }
                    else
                    {
                        throw new java.text.ParseException("Unmatched '{'", i);
                    }
                    pos.setIndex(i);
                }
                else if (clazz == char.class)
                {

                    int i = pos.getIndex();
                    { if (!(end-i >= 3 && s.charAt(i+0) == '\'' && s.charAt(i+2) == '\'')) throw new Error("Assertion failed at "+

 "Arrays.java"
                    +"("+

 1038

                    +"): " + "end-i >= 3 && s.charAt(i+0) == '\\'' && s.charAt(i+2) == '\\''" + ""); }

                                                 ;
                    obj = new Character(s.charAt(i+1));
                    i += 3;
                    pos.setIndex(i);
                }
                else
                {
                    Class wrapperClass = getWrapperClass(clazz);
                    if (!Number.class.isAssignableFrom(wrapperClass))
                        throw new java.text.ParseException("Don't know how to parse class "+clazz.getName()+"",pos.getIndex());

                    java.text.NumberFormat numberFormat = java.text.NumberFormat.getNumberInstance();

                    int startPos = pos.getIndex();
                    Number number = parseTakingParsePositionAndThrowingParseException(numberFormat, s, pos);
                    if (pos.getIndex() > end)
                    {



                        pos.setIndex(startPos);
                        s = s.substring(0, end);
                        number = parseTakingParsePositionAndThrowingParseException(numberFormat, s, pos);
                    }



                    {
                        int commaInd = s.indexOf(',', startPos);
                        if (commaInd != -1
                         && commaInd < end
                         && pos.getIndex() > commaInd)
                        {
                            pos.setIndex(startPos);
                            s = s.substring(0, commaInd);
                            number = parseTakingParsePositionAndThrowingParseException(numberFormat, s, pos);
                        }
                    }

                    if (number.getClass() == wrapperClass)
                        obj = number;
                    else
                    {
                        if (wrapperClass == Byte.class)
                            obj = new Byte(number.byteValue());
                        else if (wrapperClass == Double.class)
                            obj = new Double(number.doubleValue());
                        else if (wrapperClass == Float.class)
                            obj = new Float(number.floatValue());
                        else if (wrapperClass == Integer.class)
                            obj = new Integer(number.intValue());
                        else if (wrapperClass == Long.class)
                            obj = new Long(number.longValue());
                        else if (wrapperClass == Short.class)
                            obj = new Short(number.shortValue());
                        else
                            throw new java.text.ParseException("Don't know how to parse class "+clazz.getName()+"",startPos);
                    }
                }

                return obj;
            }






            private static Class guessClass(String s, int start, int end)
                throws java.text.ParseException
            {




                Class primType = (s.indexOf("true") != -1 ? boolean.class :
                                  s.indexOf("false") != -1 ? boolean.class :
                                  s.indexOf(".") != -1 ? double.class :
                                  s.indexOf("E") != -1 ? double.class :
                                  s.indexOf("e") != -1 ? double.class :
                                  s.indexOf("f") != -1 ? float.class :
                                  s.indexOf("F") != -1 ? float.class :




                                  s.indexOf("'") != -1 ? char.class : int.class);
                int nDims = braceDepth(s, start, end);






                Class clazz;
                {

                    clazz = primType;
                    for (int iDim = 0; (iDim) < (nDims); ++iDim)
                        clazz = java.lang.reflect.Array.newInstance(clazz,0).getClass();
                }
                return clazz;
            }
            private static int braceDepth(String s, int start, int end)
                throws java.text.ParseException
            {
                if (end-start == 0)
                    return 0;

                do {while ((start) < (end) && Character.isWhitespace(s.charAt(start))) start++;} while (false);

                if (end-start >= 4
                 && s.startsWith("null", start))
                    return 1;

                if (start < end
                 && s.charAt(start) == '{')
                {
                    int level = 0, maxLevel = 0;
                    for (int i = start; i < end; ++i)
                    for (; i < end; ++i)
                    {
                        char c = s.charAt(i);
                        if (c == '{')
                        {
                            level++;
                            maxLevel = ((level)>=(maxLevel)?(level):(maxLevel));
                        }
                        else if (c == '}')
                        {
                            level--;
                            if (level == 0)
                                break;
                        }
                        else if (end-i >= 4
                              && s.startsWith("null", i))
                            maxLevel = ((level+1)>=(maxLevel)?(level+1):(maxLevel));
                    }
                    if (level != 0)
                        throw new java.text.ParseException("Unmatched '{'", start);
                    return maxLevel;
                }
                return 0;
            }

            private static Object parseObjectTakingParsePositionAndThrowingParseException(java.text.Format format, String s, java.text.ParsePosition pos)
                throws java.text.ParseException
            {
                Object obj = format.parseObject(s, pos);
                if (obj != null)
                    return obj;

                int startPos = pos.getIndex();
                String subS = s.substring(startPos);
                try
                {
                    obj = format.parseObject(subS);
                }
                catch (java.text.ParseException e)
                {

                    throw new java.text.ParseException(e.getMessage(),
                                                       startPos + e.getErrorOffset());
                }
                { if (!(false)) throw new Error("Assertion failed at "+"Arrays.java"+"("+1209 +"): " + "false" + ""); };
                return null;
            }
            private static Number parseTakingParsePositionAndThrowingParseException(java.text.NumberFormat numberFormat, String s, java.text.ParsePosition pos)
                throws java.text.ParseException
            {
                return (Number)parseObjectTakingParsePositionAndThrowingParseException(numberFormat, s, pos);
            }


    }






    public static void main(String args[])
    {
        if (true)
        {
            String s = "  {  {  {  1  ,  2  }  ,  null  }  }  ";
            {System.out.print("    ");System.out.println("s" + " = " + (s));};
            java.text.ParsePosition pos = new java.text.ParsePosition(0);
            try
            {
                Object b = new ArrayFormat().parseObjectSucceedOrThrowAnException(s, pos, s.length());
                System.out.println("    " + "b" + " = " + Arrays.toStringCompact(b));
            }
            catch (java.text.ParseException e)
            {
                System.err.println("Oh no! (at position "+e.getErrorOffset()+")");
                e.printStackTrace();
            }
        }


        if (true)
        {
            double a[][][] = {
                {
                    {0,1},
                },
                {
                    {6,5,4,3},
                },
                {
                },
                {
                    {6,5,4,3},
                    {0},
                    {},
                },
            };
            System.out.println("    " + "makeArrayOfIndices(a,0)" + " = " + Arrays.toStringCompact(makeArrayOfIndices(a,0)));
            System.out.println("    " + "makeArrayOfIndices(a,1)" + " = " + Arrays.toStringCompact(makeArrayOfIndices(a,1)));
            System.out.println("    " + "makeArrayOfIndices(a,2)" + " = " + Arrays.toStringCompact(makeArrayOfIndices(a,2)));
            System.out.println("    " + "makeArrayOfIndices(a,3)" + " = " + Arrays.toStringCompact(makeArrayOfIndices(a,3)));
            System.out.println("    " + "flatten(a,0,0)" + " = " + Arrays.toStringCompact(flatten(a,0,0)));
            System.out.println("    " + "flatten(a,0,1)" + " = " + Arrays.toStringCompact(flatten(a,0,1)));
            System.out.println("    " + "flatten(a,0,2)" + " = " + Arrays.toStringCompact(flatten(a,0,2)));
            System.out.println("    " + "flatten(a,0,3)" + " = " + Arrays.toStringCompact(flatten(a,0,3)));
            System.out.println("    " + "flatten(a,1,0)" + " = " + Arrays.toStringCompact(flatten(a,1,0)));
            System.out.println("    " + "flatten(a,1,1)" + " = " + Arrays.toStringCompact(flatten(a,1,1)));
            System.out.println("    " + "flatten(a,1,2)" + " = " + Arrays.toStringCompact(flatten(a,1,2)));
            System.out.println("    " + "flatten(a,2,0)" + " = " + Arrays.toStringCompact(flatten(a,2,0)));
            System.out.println("    " + "flatten(a,2,1)" + " = " + Arrays.toStringCompact(flatten(a,2,1)));
            System.out.println("    " + "flatten(a,3,0)" + " = " + Arrays.toStringCompact(flatten(a,3,0)));
        }

        if (true)
        {
            int a[][][] = {
                {
                    {1,2,3},
                    {4,5,6},
                },
                null,
                {
                    null,
                    {7,8,9},
                    null,
                    null,
                    {},
                    null,
                },
                {},
            };
            String s = toStringCompact(a);
            {System.out.print("    ");System.out.println("s" + " = " + (s));};
            java.text.ParsePosition pos = new java.text.ParsePosition(0);
            try
            {
                Object b = new ArrayFormat().parseObjectSucceedOrThrowAnException(s, pos, s.length());
                System.out.println("    " + "b" + " = " + Arrays.toStringCompact(b));
            }
            catch (java.text.ParseException e)
            {
                System.err.println("Oh no! (at position "+e.getErrorOffset()+")");
                e.printStackTrace();
            }
        }

        if (true)
        {
            java.util.Random rng = new java.util.Random(0);
            for (int i = 0; (i) < (100); ++i)
            {
                if (i == 0)
                    continue;
                System.out.println(i+":");
                for (int j = 0; (j) < (100); ++j)
                {
                    int n = randomIndex(i, rng);
                    System.out.print(" " + randomIndex(i, rng));
                    { if (!(((0 <=(n))&&((n)< i)))) throw new Error("Assertion failed at "+"Arrays.java"+"("+1324 +"): " + "INRANGE(0 <=, n, < i)" + ""); };
                }
                System.out.println();
            }
        }

    }

}
