Merge branch 'master' of https://source.jalview.org/git/jalviewjs.git
[jalviewjs.git] / src / javajs / util / AU.java
index 1fca3da..50c5912 100644 (file)
-/* $RCSfile$\r
- * $Author: egonw $\r
- * $Date: 2005-11-10 09:52:44 -0600 (Thu, 10 Nov 2005) $\r
- * $Revision: 4255 $\r
- *\r
- * Copyright (C) 2003-2005  The Jmol Development Team\r
- *\r
- * Contact: jmol-developers@lists.sf.net\r
- *\r
- *  This library is free software; you can redistribute it and/or\r
- *  modify it under the terms of the GNU Lesser General Public\r
- *  License as published by the Free Software Foundation; either\r
- *  version 2.1 of the License, or (at your option) any later version.\r
- *\r
- *  This library is distributed in the hope that it will be useful,\r
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- *  Lesser General Public License for more details.\r
- *\r
- *  You should have received a copy of the GNU Lesser General Public\r
- *  License along with this library; if not, write to the Free Software\r
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-package javajs.util;\r
-\r
-// 4/23/15 BH getComponentType fix\r
-\r
-import java.lang.reflect.Array;\r
-\r
-import java.util.Arrays;\r
-import java.util.Hashtable;\r
-import java.util.Map;\r
-\r
-\r
-final public class AU {\r
-\r
-  /**\r
-   * Very important that this not be used with Int32Array or Float32Array,\r
-   * because it is not initialized to all zeros in MSIE 9.\r
-   * \r
-   * @param array\r
-   * @param minimumLength\r
-   * @return array\r
-   */\r
-  public static Object ensureLength(Object array, int minimumLength) {\r
-    if (array != null && getLength(array) >= minimumLength)\r
-      return array;\r
-    return arrayCopyObject(array, minimumLength);\r
-  }\r
-\r
-  public static String[] ensureLengthS(String[] array, int minimumLength) {\r
-    if (array != null && array.length >= minimumLength)\r
-      return array;\r
-    return arrayCopyS(array, minimumLength);\r
-  }\r
-\r
-  public static float[] ensureLengthA(float[] array, int minimumLength) {\r
-    if (array != null && array.length >= minimumLength)\r
-      return array;\r
-    return arrayCopyF(array, minimumLength);\r
-  }\r
-\r
-  public static int[] ensureLengthI(int[] array, int minimumLength) {\r
-    if (array != null && array.length >= minimumLength)\r
-      return array;\r
-    return arrayCopyI(array, minimumLength);\r
-  }\r
-\r
-  public static short[] ensureLengthShort(short[] array, int minimumLength) {\r
-    if (array != null && array.length >= minimumLength)\r
-      return array;\r
-    return arrayCopyShort(array, minimumLength);\r
-  }\r
-\r
-  public static byte[] ensureLengthByte(byte[] array, int minimumLength) {\r
-    if (array != null && array.length >= minimumLength)\r
-      return array;\r
-    return arrayCopyByte(array, minimumLength);\r
-  }\r
-\r
-  /**\r
-   * Very important that this not be used with Int32Array or Float32Array,\r
-   * because it is not initialized to all zeros in MSIE 9.\r
-   * \r
-   * @param array\r
-   * @return array\r
-   */\r
-  public static Object doubleLength(Object array) {\r
-    return arrayCopyObject(array, (array == null ? 16 : 2 * getLength(array)));\r
-  }\r
-\r
-  public static String[] doubleLengthS(String[] array) {\r
-    return arrayCopyS(array, (array == null ? 16 : 2 * array.length));\r
-  }\r
-\r
-  public static float[] doubleLengthF(float[] array) {\r
-    return arrayCopyF(array, (array == null ? 16 : 2 * array.length));\r
-  }\r
-\r
-  public static int[] doubleLengthI(int[] array) {\r
-    return arrayCopyI(array, (array == null ? 16 : 2 * array.length));\r
-  }\r
-\r
-  public static short[] doubleLengthShort(short[] array) {\r
-    return arrayCopyShort(array, (array == null ? 16 : 2 * array.length));\r
-  }\r
-\r
-  public static byte[] doubleLengthByte(byte[] array) {\r
-    return arrayCopyByte(array, (array == null ? 16 : 2 * array.length));\r
-  }\r
-\r
-  public static boolean[] doubleLengthBool(boolean[] array) {\r
-    return arrayCopyBool(array, (array == null ? 16 : 2 * array.length));\r
-  }\r
-\r
-  public static Object deleteElements(Object array, int firstElement,\r
-                                     int nElements) {\r
-    if (nElements == 0 || array == null)\r
-      return array;\r
-    int oldLength = getLength(array);\r
-    if (firstElement >= oldLength)\r
-      return array;\r
-    int n = oldLength - (firstElement + nElements);\r
-    if (n < 0)\r
-      n = 0;\r
-    Object t = newInstanceO(array, firstElement + n);\r
-    if (firstElement > 0)\r
-      System.arraycopy(array, 0, t, 0, firstElement);\r
-    if (n > 0)\r
-      System.arraycopy(array, firstElement + nElements, t, firstElement, n);\r
-    return t;\r
-  }\r
-\r
-  /**\r
-   * note -- cannot copy if array is null!\r
-   * \r
-   * @param array\r
-   * @param newLength\r
-   * @return array\r
-   */\r
-  public static Object arrayCopyObject(Object array, int newLength) {\r
-    //System.out.println("ArrayUtil.copy " + newLength + " " + array + "  ");\r
-    if (array == null) {\r
-      return null; // We can't allocate since we don't know the type of array\r
-    }\r
-    int oldLength = getLength(array);\r
-    if (newLength == oldLength)\r
-      return array;\r
-    Object t = newInstanceO(array, newLength);\r
-    System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength\r
-        : newLength);\r
-    return t;\r
-\r
-  }\r
-\r
-  /**\r
-   * Very important that this not be used with Int32Array or Float32Array,\r
-   * because those need to be initialized to all zeros in MSIE 9, and\r
-   * MSIE 9 cannot distinguish Int32Array or Float32Array from Array.\r
-   * \r
-   * @param array\r
-   * @param n\r
-   * @return array\r
-   */\r
-  private static Object newInstanceO(Object array, int n) {\r
-    /**\r
-     * @j2sNative\r
-     * \r
-     * if (!array.getClass().getComponentType)\r
-     *          return new Array(n);\r
-     * \r
-     */\r
-    {\r
-      return Array.newInstance(array.getClass().getComponentType(), n);\r
-    }\r
-  }\r
-\r
-  public static int getLength(Object array) {\r
-    /**\r
-     * @j2sNative\r
-     * \r
-     *  return array.length\r
-     *   \r
-     */\r
-    {\r
-      return Array.getLength(array);\r
-    }\r
-  }\r
-\r
-  public static String[] arrayCopyS(String[] array, int newLength) {\r
-    if (newLength < 0)\r
-      newLength = array.length;\r
-    String[] t = new String[newLength];\r
-    if (array != null) {\r
-      int oldLength = array.length;\r
-      System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength\r
-          : newLength);\r
-    }\r
-    return t;\r
-  }\r
-\r
-  public static int[][] arrayCopyII(int[][] array, int newLength) {\r
-    int[][] t = newInt2(newLength);\r
-    if (array != null) {\r
-      int oldLength = array.length;\r
-      System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength\r
-          : newLength);\r
-    }\r
-    return t;\r
-  }\r
-\r
-  public static T3[] arrayCopyPt(T3[] array, int newLength) {\r
-    if (newLength < 0)\r
-      newLength = array.length;\r
-    T3[] t = new T3[newLength];\r
-    if (array != null) {\r
-      int oldLength = array.length;\r
-      System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength\r
-          : newLength);\r
-    }\r
-    return t;\r
-  }\r
-\r
-  public static float[] arrayCopyF(float[] array, int newLength) {\r
-    if (newLength < 0)\r
-      newLength = array.length;\r
-    float[] t = new float[newLength];\r
-    if (array != null) {\r
-      int oldLength = array.length;\r
-      System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength\r
-          : newLength);\r
-    }\r
-    return t;\r
-  }\r
-\r
-  public static int[] arrayCopyI(int[] array, int newLength) {\r
-    if (newLength < 0)\r
-      newLength = array.length;\r
-    int[] t = new int[newLength];\r
-    if (array != null) {\r
-      int oldLength = array.length;\r
-      System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength\r
-          : newLength);\r
-    }\r
-    return t;\r
-  }\r
-\r
-  /**\r
-   * a specialized method that allows copying from a starting point either\r
-   * to the end or to the middle (color schemes, especially)\r
-   * @param array\r
-   * @param i0\r
-   * @param n\r
-   * @return array or null\r
-   */\r
-  public static int[] arrayCopyRangeI(int[] array, int i0, int n) {\r
-    if (array == null)\r
-      return null;\r
-    int oldLength = array.length;\r
-    if (n == -1) n = oldLength;\r
-    if (n == -2) n = oldLength / 2;\r
-    n = n - i0;\r
-    int[] t = new int[n];\r
-    System.arraycopy(array, i0, t, 0, n);\r
-    return t;\r
-  }\r
-\r
-  public static int[] arrayCopyRangeRevI(int[] array, int i0, int n) {\r
-    if (array == null)\r
-      return null;\r
-    int[] t = arrayCopyRangeI(array, i0, n);\r
-    if (n < 0)\r
-      n = array.length;\r
-    for (int i = n / 2; --i >= 0;)\r
-      swapInt(t, i, n - 1 - i);\r
-    return t;\r
-  }\r
-\r
-  public static short[] arrayCopyShort(short[] array, int newLength) {\r
-    if (newLength < 0)\r
-      newLength = array.length;\r
-    short[] t = new short[newLength];\r
-    if (array != null) {\r
-      int oldLength = array.length;\r
-      System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength\r
-          : newLength);\r
-    }\r
-    return t;\r
-  }\r
-\r
-  public static byte[] arrayCopyByte(byte[] array, int newLength) {\r
-    if (newLength < 0)\r
-      newLength = array.length;\r
-    byte[] t = new byte[newLength];\r
-    if (array != null) {\r
-      int oldLength = array.length;\r
-      System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength\r
-          : newLength);\r
-    }\r
-    return t;\r
-  }\r
-\r
-  public static boolean[] arrayCopyBool(boolean[] array, int newLength) {\r
-    if (newLength < 0)\r
-      newLength = array.length;\r
-    boolean[] t = new boolean[newLength];\r
-    if (array != null) {\r
-      int oldLength = array.length;\r
-      System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength\r
-          : newLength);\r
-    }\r
-    return t;\r
-  }\r
-\r
-  public static void swapInt(int[] array, int indexA, int indexB) {\r
-    int t = array[indexA];\r
-    array[indexA] = array[indexB];\r
-    array[indexB] = t;\r
-  }\r
-\r
-  /*\r
-  public static void swap(short[] array, int indexA, int indexB) {\r
-    short t = array[indexA];\r
-    array[indexA] = array[indexB];\r
-    array[indexB] = t;\r
-  }\r
-\r
-  public static void swap(float[] array, int indexA, int indexB) {\r
-    float t = array[indexA];\r
-    array[indexA] = array[indexB];\r
-    array[indexB] = t;\r
-  }\r
-  */\r
-  \r
-  public static String dumpArray(String msg, float[][] A, int x1, int x2, int y1, int y2) {\r
-    String s = "dumpArray: " + msg + "\n";\r
-    for (int x = x1; x <= x2; x++)\r
-      s += "\t*" + x + "*";\r
-    for (int y = y2; y >= y1; y--) {\r
-      s += "\n*" + y + "*";\r
-      for (int x = x1; x <= x2; x++)\r
-        s += "\t" + (x < A.length && y < A[x].length ? A[x][y] : Float.NaN);\r
-    }\r
-    return s;\r
-  }\r
-\r
-  public static String dumpIntArray(int[] A, int n) {\r
-    String str = "";\r
-    for (int i = 0; i < n; i++)\r
-      str += " " + A[i];\r
-    return str;\r
-  }\r
-\r
-  public static String sortedItem(Lst<String> v, int n) {\r
-    if (v.size() == 0)\r
-      return null;\r
-    if (v.size() == 1)\r
-      return v.get(0);\r
-    String[] keys = v.toArray(new String[v.size()]);\r
-    Arrays.sort(keys);\r
-    return keys[n % keys.length];\r
-  }\r
-\r
-  /**\r
-   * Helper method for creating a List<Tx>[] without warnings.\r
-   * \r
-   * @param <type> Type of objects in the list.\r
-   * @param size Array size.\r
-   * @return Array of List<type>\r
-   */\r
-  @SuppressWarnings("unchecked")\r
-  public static <type> Lst<type>[] createArrayOfArrayList(int size) {\r
-    return new Lst[size];\r
-  }\r
-\r
-  /**\r
-   * Helper method for creating a Map<K, V>[] without warnings.\r
-   * \r
-   * @param <K> Type of object for the keys in the map.\r
-   * @param <V> Type of object for the values in the map.\r
-   * @param size Array size.\r
-   * @return Array of Map<K, V>\r
-   */\r
-  @SuppressWarnings("unchecked")\r
-  public static <K, V> Map<K, V>[] createArrayOfHashtable(int size) {\r
-    return new Hashtable[size];\r
-  }\r
-\r
-  public static void swap(Object[] o, int i, int j) {\r
-    Object oi = o[i];\r
-    o[i] = o[j];\r
-    o[j] = oi;\r
-  }\r
-\r
-  public static float[][] newFloat2(int n) {\r
-    /**\r
-     * @j2sNative\r
-     * \r
-     * return Clazz.newArray(n, null);\r
-     * \r
-     */\r
-    {\r
-    return new float[n][];\r
-    }\r
-  }\r
-\r
-  public static int[][] newInt2(int n) {\r
-    /**\r
-     * @j2sNative\r
-     * \r
-     * return Clazz.newArray(n, null);\r
-     * \r
-     */\r
-    {\r
-    return new int[n][];\r
-    }\r
-  }\r
-\r
-  public static int[][][] newInt3(int nx, int ny) {\r
-    /**\r
-     * @j2sNative\r
-     * \r
-     * return Clazz.newArray(nx, null);\r
-     * \r
-     */\r
-    {\r
-      return (ny < 0 ? new int[nx][][] : new int[nx][ny][]);\r
-    }\r
-  }\r
-\r
-  public static float[][][] newFloat3(int nx, int ny) {\r
-    /**\r
-     * @j2sNative\r
-     * \r
-     * return Clazz.newArray(nx, null);\r
-     * \r
-     */\r
-    {\r
-      return (ny < 0 ? new float[nx][][] : new float[nx][ny][]);\r
-    }\r
-  }\r
-\r
-  public static int[][][][] newInt4(int n) {\r
-    /**\r
-     * @j2sNative\r
-     * \r
-     * return Clazz.newArray(n, null);\r
-     * \r
-     */\r
-    {\r
-    return new int[n][][][];\r
-    }\r
-  }\r
-\r
-  public static short[][] newShort2(int n) {\r
-    /**\r
-     * @j2sNative\r
-     * \r
-     * return Clazz.newArray(n, null);\r
-     * \r
-     */\r
-    {\r
-    return new short[n][];\r
-    }\r
-  }\r
-\r
-  public static byte[][] newByte2(int n) {\r
-    /**\r
-     * @j2sNative\r
-     * \r
-     * return Clazz.newArray(n, null);\r
-     * \r
-     */\r
-    {\r
-    return new byte[n][];\r
-    }\r
-  }\r
-\r
-  public static double[][] newDouble2(int n) {\r
-    /**\r
-     * @j2sNative\r
-     * \r
-     * return Clazz.newArray(n, null);\r
-     * \r
-     */\r
-    {\r
-    return new double[n][];\r
-    }\r
-  }\r
-\r
-  /**\r
-   * remove all keys from a map that start with given root\r
-   * @param map\r
-   * @param root\r
-   * @return number removed\r
-   */\r
-  public static int removeMapKeys(Map<String, ?> map, String root) {\r
-    Lst<String> list = new Lst<String>();\r
-    for (String key: map.keySet())\r
-      if (key.startsWith(root))\r
-        list.addLast(key);\r
-    for (int i = list.size(); --i >= 0;)\r
-      map.remove(list.get(i));\r
-    return list.size();\r
-  }\r
-\r
-       public static boolean isAS(Object x) {\r
-         /**\r
-          * \r
-          * look also for array with first null element\r
-          * so untypable -- just call it a String[]\r
-          * (group3Lists, created in ModelLoader)\r
-          * \r
-          * @j2sNative\r
-          *  return Clazz.isAS(x);\r
-          */\r
-         {\r
-         return x instanceof String[];\r
-         }\r
-       }\r
-\r
-       public static boolean isASS(Object x) {\r
-         /**\r
-          * @j2sNative\r
-          *  return Clazz.isASS(x);\r
-          */\r
-         {\r
-         return x instanceof String[][];\r
-         }\r
-       }\r
-\r
-       public static boolean isAP(Object x) {\r
-         /**\r
-          * @j2sNative\r
-          *  return Clazz.isAP(x);\r
-          */\r
-         {\r
-         return x instanceof T3[];\r
-         }\r
-       }\r
-\r
-       public static boolean isAF(Object x) {\r
-         /**\r
-          * @j2sNative\r
-          *  return Clazz.isAF(x);\r
-          */\r
-         {\r
-         return x instanceof float[];\r
-         }\r
-       }\r
-\r
-       public static boolean isAFloat(Object x) {\r
-         /**\r
-          * @j2sNative\r
-          *  return Clazz.isAFloat(x);\r
-          */\r
-         {\r
-         return x instanceof Float[];\r
-         }\r
-       }\r
-\r
-       public static boolean isAD(Object x) {\r
-         /**\r
-          * @j2sNative\r
-          *  return Clazz.isAF(x);\r
-          */\r
-         {\r
-         return x instanceof double[];\r
-         }\r
-       }\r
-\r
-       public static boolean isADD(Object x) {\r
-         /**\r
-          * @j2sNative\r
-          *  return Clazz.isAFF(x);\r
-          */\r
-         {\r
-         return x instanceof double[][];\r
-         }\r
-       }\r
-\r
-       public static boolean isAB(Object x) {\r
-         /**\r
-          * @j2sNative\r
-          *  return Clazz.isAI(x);\r
-          */\r
-         {\r
-         return x instanceof byte[];\r
-         }\r
-       }\r
-\r
-       public static boolean isAI(Object x) {\r
-         /**\r
-          * @j2sNative\r
-          *  return Clazz.isAI(x);\r
-          */\r
-         {\r
-         return x instanceof int[];\r
-         }\r
-       }\r
-\r
-       public static boolean isAII(Object x) {\r
-         /**\r
-          * @j2sNative\r
-          *  return Clazz.isAII(x);\r
-          */\r
-         {\r
-         return (x instanceof int[][]);\r
-         }\r
-       }\r
-\r
-       public static boolean isAFF(Object x) {\r
-         /**\r
-          * @j2sNative\r
-          *  return Clazz.isAFF(x);\r
-          */\r
-         {\r
-         return x instanceof float[][];\r
-         }\r
-       }\r
-\r
-       public static boolean isAFFF(Object x) {\r
-         /**\r
-          * @j2sNative\r
-          *  return Clazz.isAFFF(x);\r
-          */\r
-         {\r
-         return x instanceof float[][][];\r
-         }\r
-       }\r
-       \r
-       /**\r
-        * Ensure that we have signed and not unsigned bytes\r
-        * coming out of any process, but particularly out of \r
-        * file reading. \r
-        * \r
-        * @param b\r
-        */\r
-       public static void ensureSignedBytes(byte[] b) {\r
-         /**\r
-          * @j2sNative\r
-          * \r
-          * for (var i = b.length; --i >= 0;) {\r
-          *   var j = b[i] & 0xFF;\r
-          *   if (j >= 0x80) j -= 0x100;\r
-          *   b[i] = j;\r
-          * }\r
-          * \r
-          */\r
-         {\r
-         }\r
-       }\r
-\r
-\r
-}\r
+/* $RCSfile$
+ * $Author: egonw $
+ * $Date: 2005-11-10 09:52:44 -0600 (Thu, 10 Nov 2005) $
+ * $Revision: 4255 $
+ *
+ * Copyright (C) 2003-2005  The Jmol Development Team
+ *
+ * Contact: jmol-developers@lists.sf.net
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+package javajs.util;
+
+// 4/23/15 BH getComponentType fix
+
+import java.lang.reflect.Array;
+
+import java.util.Arrays;
+import java.util.Hashtable;
+import java.util.Map;
+
+
+final public class AU {
+
+  /**
+   * Very important that this not be used with Int32Array or Float32Array,
+   * because it is not initialized to all zeros in MSIE 9.
+   * 
+   * @param array
+   * @param minimumLength
+   * @return array
+   */
+  public static Object ensureLength(Object array, int minimumLength) {
+    if (array != null && getLength(array) >= minimumLength)
+      return array;
+    return arrayCopyObject(array, minimumLength);
+  }
+
+  public static String[] ensureLengthS(String[] array, int minimumLength) {
+    if (array != null && array.length >= minimumLength)
+      return array;
+    return arrayCopyS(array, minimumLength);
+  }
+
+  public static float[] ensureLengthA(float[] array, int minimumLength) {
+    if (array != null && array.length >= minimumLength)
+      return array;
+    return arrayCopyF(array, minimumLength);
+  }
+
+  public static int[] ensureLengthI(int[] array, int minimumLength) {
+    if (array != null && array.length >= minimumLength)
+      return array;
+    return arrayCopyI(array, minimumLength);
+  }
+
+  public static short[] ensureLengthShort(short[] array, int minimumLength) {
+    if (array != null && array.length >= minimumLength)
+      return array;
+    return arrayCopyShort(array, minimumLength);
+  }
+
+  public static byte[] ensureLengthByte(byte[] array, int minimumLength) {
+    if (array != null && array.length >= minimumLength)
+      return array;
+    return arrayCopyByte(array, minimumLength);
+  }
+
+  /**
+   * Very important that this not be used with Int32Array or Float32Array,
+   * because it is not initialized to all zeros in MSIE 9.
+   * 
+   * @param array
+   * @return array
+   */
+  public static Object doubleLength(Object array) {
+    return arrayCopyObject(array, (array == null ? 16 : 2 * getLength(array)));
+  }
+
+  public static String[] doubleLengthS(String[] array) {
+    return arrayCopyS(array, (array == null ? 16 : 2 * array.length));
+  }
+
+  public static float[] doubleLengthF(float[] array) {
+    return arrayCopyF(array, (array == null ? 16 : 2 * array.length));
+  }
+
+  public static int[] doubleLengthI(int[] array) {
+    return arrayCopyI(array, (array == null ? 16 : 2 * array.length));
+  }
+
+  public static short[] doubleLengthShort(short[] array) {
+    return arrayCopyShort(array, (array == null ? 16 : 2 * array.length));
+  }
+
+  public static byte[] doubleLengthByte(byte[] array) {
+    return arrayCopyByte(array, (array == null ? 16 : 2 * array.length));
+  }
+
+  public static boolean[] doubleLengthBool(boolean[] array) {
+    return arrayCopyBool(array, (array == null ? 16 : 2 * array.length));
+  }
+
+  public static Object deleteElements(Object array, int firstElement,
+                                     int nElements) {
+    if (nElements == 0 || array == null)
+      return array;
+    int oldLength = getLength(array);
+    if (firstElement >= oldLength)
+      return array;
+    int n = oldLength - (firstElement + nElements);
+    if (n < 0)
+      n = 0;
+    Object t = newInstanceO(array, firstElement + n);
+    if (firstElement > 0)
+      System.arraycopy(array, 0, t, 0, firstElement);
+    if (n > 0)
+      System.arraycopy(array, firstElement + nElements, t, firstElement, n);
+    return t;
+  }
+
+  /**
+   * note -- cannot copy if array is null!
+   * 
+   * @param array
+   * @param newLength
+   * @return array
+   */
+  public static Object arrayCopyObject(Object array, int newLength) {
+    //System.out.println("ArrayUtil.copy " + newLength + " " + array + "  ");
+    if (array == null) {
+      return null; // We can't allocate since we don't know the type of array
+    }
+    int oldLength = getLength(array);
+    if (newLength == oldLength)
+      return array;
+    Object t = newInstanceO(array, newLength);
+    System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength
+        : newLength);
+    return t;
+
+  }
+
+  /**
+   * Very important that this not be used with Int32Array or Float32Array,
+   * because those need to be initialized to all zeros in MSIE 9, and
+   * MSIE 9 cannot distinguish Int32Array or Float32Array from Array.
+   * 
+   * @param array
+   * @param n
+   * @return array
+   */
+  private static Object newInstanceO(Object array, int n) {
+    /**
+     * @j2sNative
+     * 
+     * if (!array.getClass().getComponentType)
+     *          return new Array(n);
+     * 
+     */
+    {
+      return Array.newInstance(array.getClass().getComponentType(), n);
+    }
+  }
+
+  public static int getLength(Object array) {
+    /**
+     * @j2sNative
+     * 
+     *  return array.length
+     *   
+     */
+    {
+      return Array.getLength(array);
+    }
+  }
+
+  public static String[] arrayCopyS(String[] array, int newLength) {
+    if (newLength < 0)
+      newLength = array.length;
+    String[] t = new String[newLength];
+    if (array != null) {
+      int oldLength = array.length;
+      System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength
+          : newLength);
+    }
+    return t;
+  }
+
+  public static int[][] arrayCopyII(int[][] array, int newLength) {
+    int[][] t = newInt2(newLength);
+    if (array != null) {
+      int oldLength = array.length;
+      System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength
+          : newLength);
+    }
+    return t;
+  }
+
+  public static T3[] arrayCopyPt(T3[] array, int newLength) {
+    if (newLength < 0)
+      newLength = array.length;
+    T3[] t = new T3[newLength];
+    if (array != null) {
+      int oldLength = array.length;
+      System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength
+          : newLength);
+    }
+    return t;
+  }
+
+  public static float[] arrayCopyF(float[] array, int newLength) {
+    if (newLength < 0)
+      newLength = array.length;
+    float[] t = new float[newLength];
+    if (array != null) {
+      int oldLength = array.length;
+      System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength
+          : newLength);
+    }
+    return t;
+  }
+
+  public static int[] arrayCopyI(int[] array, int newLength) {
+    if (newLength < 0)
+      newLength = array.length;
+    int[] t = new int[newLength];
+    if (array != null) {
+      int oldLength = array.length;
+      System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength
+          : newLength);
+    }
+    return t;
+  }
+
+  /**
+   * a specialized method that allows copying from a starting point either
+   * to the end or to the middle (color schemes, especially)
+   * @param array
+   * @param i0
+   * @param n
+   * @return array or null
+   */
+  public static int[] arrayCopyRangeI(int[] array, int i0, int n) {
+    if (array == null)
+      return null;
+    int oldLength = array.length;
+    if (n == -1) n = oldLength;
+    if (n == -2) n = oldLength / 2;
+    n = n - i0;
+    int[] t = new int[n];
+    System.arraycopy(array, i0, t, 0, n);
+    return t;
+  }
+
+  public static int[] arrayCopyRangeRevI(int[] array, int i0, int n) {
+    if (array == null)
+      return null;
+    int[] t = arrayCopyRangeI(array, i0, n);
+    if (n < 0)
+      n = array.length;
+    for (int i = n / 2; --i >= 0;)
+      swapInt(t, i, n - 1 - i);
+    return t;
+  }
+
+  public static short[] arrayCopyShort(short[] array, int newLength) {
+    if (newLength < 0)
+      newLength = array.length;
+    short[] t = new short[newLength];
+    if (array != null) {
+      int oldLength = array.length;
+      System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength
+          : newLength);
+    }
+    return t;
+  }
+
+  public static byte[] arrayCopyByte(byte[] array, int newLength) {
+    if (newLength < 0)
+      newLength = array.length;
+    byte[] t = new byte[newLength];
+    if (array != null) {
+      int oldLength = array.length;
+      System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength
+          : newLength);
+    }
+    return t;
+  }
+
+  public static boolean[] arrayCopyBool(boolean[] array, int newLength) {
+    if (newLength < 0)
+      newLength = array.length;
+    boolean[] t = new boolean[newLength];
+    if (array != null) {
+      int oldLength = array.length;
+      System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength
+          : newLength);
+    }
+    return t;
+  }
+
+  public static void swapInt(int[] array, int indexA, int indexB) {
+    int t = array[indexA];
+    array[indexA] = array[indexB];
+    array[indexB] = t;
+  }
+
+  /*
+  public static void swap(short[] array, int indexA, int indexB) {
+    short t = array[indexA];
+    array[indexA] = array[indexB];
+    array[indexB] = t;
+  }
+
+  public static void swap(float[] array, int indexA, int indexB) {
+    float t = array[indexA];
+    array[indexA] = array[indexB];
+    array[indexB] = t;
+  }
+  */
+  
+  public static String dumpArray(String msg, float[][] A, int x1, int x2, int y1, int y2) {
+    String s = "dumpArray: " + msg + "\n";
+    for (int x = x1; x <= x2; x++)
+      s += "\t*" + x + "*";
+    for (int y = y2; y >= y1; y--) {
+      s += "\n*" + y + "*";
+      for (int x = x1; x <= x2; x++)
+        s += "\t" + (x < A.length && y < A[x].length ? A[x][y] : Float.NaN);
+    }
+    return s;
+  }
+
+  public static String dumpIntArray(int[] A, int n) {
+    String str = "";
+    for (int i = 0; i < n; i++)
+      str += " " + A[i];
+    return str;
+  }
+
+  public static String sortedItem(Lst<String> v, int n) {
+    if (v.size() == 0)
+      return null;
+    if (v.size() == 1)
+      return v.get(0);
+    String[] keys = v.toArray(new String[v.size()]);
+    Arrays.sort(keys);
+    return keys[n % keys.length];
+  }
+
+  /**
+   * Helper method for creating a List<Tx>[] without warnings.
+   * 
+   * @param <type> Type of objects in the list.
+   * @param size Array size.
+   * @return Array of List<type>
+   */
+  @SuppressWarnings("unchecked")
+  public static <type> Lst<type>[] createArrayOfArrayList(int size) {
+    return new Lst[size];
+  }
+
+  /**
+   * Helper method for creating a Map<K, V>[] without warnings.
+   * 
+   * @param <K> Type of object for the keys in the map.
+   * @param <V> Type of object for the values in the map.
+   * @param size Array size.
+   * @return Array of Map<K, V>
+   */
+  @SuppressWarnings("unchecked")
+  public static <K, V> Map<K, V>[] createArrayOfHashtable(int size) {
+    return new Hashtable[size];
+  }
+
+  public static void swap(Object[] o, int i, int j) {
+    Object oi = o[i];
+    o[i] = o[j];
+    o[j] = oi;
+  }
+
+  public static float[][] newFloat2(int n) {
+    /**
+     * @j2sNative
+     * 
+     * return Clazz.newArray(n, null);
+     * 
+     */
+    {
+    return new float[n][];
+    }
+  }
+
+  public static int[][] newInt2(int n) {
+    /**
+     * @j2sNative
+     * 
+     * return Clazz.newArray(n, null);
+     * 
+     */
+    {
+    return new int[n][];
+    }
+  }
+
+  public static int[][][] newInt3(int nx, int ny) {
+    /**
+     * @j2sNative
+     * 
+     * return Clazz.newArray(nx, null);
+     * 
+     */
+    {
+      return (ny < 0 ? new int[nx][][] : new int[nx][ny][]);
+    }
+  }
+
+  public static float[][][] newFloat3(int nx, int ny) {
+    /**
+     * @j2sNative
+     * 
+     * return Clazz.newArray(nx, null);
+     * 
+     */
+    {
+      return (ny < 0 ? new float[nx][][] : new float[nx][ny][]);
+    }
+  }
+
+  public static int[][][][] newInt4(int n) {
+    /**
+     * @j2sNative
+     * 
+     * return Clazz.newArray(n, null);
+     * 
+     */
+    {
+    return new int[n][][][];
+    }
+  }
+
+  public static short[][] newShort2(int n) {
+    /**
+     * @j2sNative
+     * 
+     * return Clazz.newArray(n, null);
+     * 
+     */
+    {
+    return new short[n][];
+    }
+  }
+
+  public static byte[][] newByte2(int n) {
+    /**
+     * @j2sNative
+     * 
+     * return Clazz.newArray(n, null);
+     * 
+     */
+    {
+    return new byte[n][];
+    }
+  }
+
+  public static double[][] newDouble2(int n) {
+    /**
+     * @j2sNative
+     * 
+     * return Clazz.newArray(n, null);
+     * 
+     */
+    {
+    return new double[n][];
+    }
+  }
+
+  /**
+   * remove all keys from a map that start with given root
+   * @param map
+   * @param root
+   * @return number removed
+   */
+  public static int removeMapKeys(Map<String, ?> map, String root) {
+    Lst<String> list = new Lst<String>();
+    for (String key: map.keySet())
+      if (key.startsWith(root))
+        list.addLast(key);
+    for (int i = list.size(); --i >= 0;)
+      map.remove(list.get(i));
+    return list.size();
+  }
+
+       public static boolean isAS(Object x) {
+         /**
+          * 
+          * look also for array with first null element
+          * so untypable -- just call it a String[]
+          * (group3Lists, created in ModelLoader)
+          * 
+          * @j2sNative
+          *  return Clazz.isAS(x);
+          */
+         {
+         return x instanceof String[];
+         }
+       }
+
+       public static boolean isASS(Object x) {
+         /**
+          * @j2sNative
+          *  return Clazz.isASS(x);
+          */
+         {
+         return x instanceof String[][];
+         }
+       }
+
+       public static boolean isAP(Object x) {
+         /**
+          * @j2sNative
+          *  return Clazz.isAP(x);
+          */
+         {
+         return x instanceof T3[];
+         }
+       }
+
+       public static boolean isAF(Object x) {
+         /**
+          * @j2sNative
+          *  return Clazz.isAF(x);
+          */
+         {
+         return x instanceof float[];
+         }
+       }
+
+       public static boolean isAFloat(Object x) {
+         /**
+          * @j2sNative
+          *  return Clazz.isAFloat(x);
+          */
+         {
+         return x instanceof Float[];
+         }
+       }
+
+       public static boolean isAD(Object x) {
+         /**
+          * @j2sNative
+          *  return Clazz.isAF(x);
+          */
+         {
+         return x instanceof double[];
+         }
+       }
+
+       public static boolean isADD(Object x) {
+         /**
+          * @j2sNative
+          *  return Clazz.isAFF(x);
+          */
+         {
+         return x instanceof double[][];
+         }
+       }
+
+       public static boolean isAB(Object x) {
+         /**
+          * @j2sNative
+          *  return Clazz.isAI(x);
+          */
+         {
+         return x instanceof byte[];
+         }
+       }
+
+       public static boolean isAI(Object x) {
+         /**
+          * @j2sNative
+          *  return Clazz.isAI(x);
+          */
+         {
+         return x instanceof int[];
+         }
+       }
+
+       public static boolean isAII(Object x) {
+         /**
+          * @j2sNative
+          *  return Clazz.isAII(x);
+          */
+         {
+         return (x instanceof int[][]);
+         }
+       }
+
+       public static boolean isAFF(Object x) {
+         /**
+          * @j2sNative
+          *  return Clazz.isAFF(x);
+          */
+         {
+         return x instanceof float[][];
+         }
+       }
+
+       public static boolean isAFFF(Object x) {
+         /**
+          * @j2sNative
+          *  return Clazz.isAFFF(x);
+          */
+         {
+         return x instanceof float[][][];
+         }
+       }
+       
+       /**
+        * Ensure that we have signed and not unsigned bytes
+        * coming out of any process, but particularly out of 
+        * file reading. 
+        * 
+        * @param b
+        */
+       public static void ensureSignedBytes(byte[] b) {
+         /**
+          * @j2sNative
+          * 
+          * for (var i = b.length; --i >= 0;) {
+          *   var j = b[i] & 0xFF;
+          *   if (j >= 0x80) j -= 0x100;
+          *   b[i] = j;
+          * }
+          * 
+          */
+         {
+         }
+       }
+
+
+}