Skip to content
Snippets Groups Projects
NativeData.java 44.7 KiB
Newer Older
  • Learn to ignore specific revisions
  • /****************************************************************************
     * NCSA HDF                                                                 *
    
     * National Computational Science Alliance                                   *
    
     * University of Illinois at Urbana-Champaign                               *
     * 605 E. Springfield, Champaign IL 61820                                   *
     *                                                                          *
     * Center for Information Sciences and Databases, ETH Zurich, Switzerland   *
     *                                                                          *
     * For conditions of distribution and use, see the accompanying             *
     * COPYING file.                                                            *
     *                                                                          *
     ****************************************************************************/
    
    package ch.systemsx.cisd.base.convert;
    
    
    import java.nio.ByteBuffer;
    
    
    import ch.systemsx.cisd.base.utilities.NativeLibraryUtilities;
    
    /**
     * This class encapsulates native methods to deal with arrays of numbers, converting from numbers to
     * bytes and bytes to numbers.
     * <p>
    
    brinn's avatar
    brinn committed
     * These routines are used by class <b>HDFArray</b> to pass data to and from the HDF5 library.
    
     * <p>
     * Methods copyXxxToByte() convert a Java array of primitive numbers (int, short, ...) to a Java
     * array of bytes. Methods copyByteToXxx() convert from a Java array of bytes into a Java array of
     * primitive numbers (int, short, ...)
     * <p>
    
    brinn's avatar
    brinn committed
     * Variant interfaces convert only a sub-array.
     * <p>
     * The class has optimized methods using jni-libraries for some common platforms and a pure-java
     * implementation (called <i>javamode</i> if the jni-libraries are not available). If you want to
     * enforce <i>javamode</i>, you need to pass the property <code>nativedata.javamode=true</code> to
     * the JRE.
    
        private static final boolean useNativeLib;
    
            if (Boolean.getBoolean("nativedata.javamode"))
            {
                useNativeLib = false;
            } else
    
                useNativeLib = NativeLibraryUtilities.loadNativeLibrary("nativedata");
    
            }
        }
    
        /** Size of a <code>short</code> value in <code>byte</code>s. */
        public final static int SHORT_SIZE = 2;
    
    
        /** Size of a <code>char</code> value in <code>byte</code>s. */
        public final static int CHAR_SIZE = 2;
    
    
        /** Size of an <code>int</code> value in <code>byte</code>s. */
        public final static int INT_SIZE = 4;
    
        /** Size of a <code>long</code> value in <code>byte</code>s. */
        public final static int LONG_SIZE = 8;
    
        /** Size of a <code>float</code> value in <code>byte</code>s. */
        public final static int FLOAT_SIZE = 4;
    
        /** Size of a <code>double</code> value in <code>byte</code>s. */
        public final static int DOUBLE_SIZE = 8;
    
        /** Byte Order enumeration. */
        // Implementation note: the ordinal of the entries needs to be understood by the native methods
        public enum ByteOrder
        {
            /** <code>byte[]</code> is in native byte order (that is: don't change byte order) */
    
            NATIVE(java.nio.ByteOrder.nativeOrder()),
    
            /** <code>byte[]</code> is in little endian byte order */
    
            LITTLE_ENDIAN(java.nio.ByteOrder.LITTLE_ENDIAN),
    
            /** <code>byte[]</code> is in big endian byte order */
    
            BIG_ENDIAN(java.nio.ByteOrder.BIG_ENDIAN);
    
            private final java.nio.ByteOrder nioByteOrder;
    
            ByteOrder(java.nio.ByteOrder nioByteOrder)
            {
                this.nioByteOrder = nioByteOrder;
            }
    
            java.nio.ByteOrder getNioByteOrder()
            {
                return nioByteOrder;
            }
    
    
            static ByteOrder getNativeByteOrder()
    
            {
                return NATIVE.nioByteOrder.equals(LITTLE_ENDIAN.nioByteOrder) ? LITTLE_ENDIAN
                        : BIG_ENDIAN;
            }
    
        /**
         * Returns <code>true</code> if this platform is a little-endian platform and <code>false</code>
         * , if it is a big-endian platform.
         */
    
        private static native boolean isLittleEndian();
    
        /**
         * Copies a range from an array of <code>int</code> into an array of <code>byte</code>.
         * 
         * @param inData The input array of <code>int</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>int</code> to
         *            start
         * @param outData The output array of <code>byte</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>byte</code> to
         *            start
         * @param len The number of <code>int</code> to copy
         * @param byteOrder The ordinal of {@link ByteOrder}, encoding what byte order the
         *            <var>outData</var> should be in.
         */
    
        private static native void copyIntToByte(int[] inData, int inStart, byte[] outData,
                int outStart, int len, int byteOrder);
    
    
        /**
         * Copies a range from an array of <code>byte</code> into an array of <code>int</code>.
         * 
         * @param inData The input array of <code>byte</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>byte</code> to
         *            start
         * @param outData The output array of <code>int</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>int</code> to
         *            start
         * @param len The number of <code>int</code> to copy
         * @param byteOrder The ordinal of {@link ByteOrder}, encoding what byte order the
         *            <var>outData</var> should be in.
         */
    
        private static native void copyByteToInt(byte[] inData, int inStart, int[] outData,
                int outStart, int len, int byteOrder);
    
    
        /**
         * Copies a range from an array of <code>long</code> into an array of <code>byte</code>.
         * 
         * @param inData The input array of <code>long</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>long</code> to
         *            start
         * @param outData The output array of <code>byte</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>byte</code> to
         *            start
         * @param len The number of <code>long</code> to copy
         * @param byteOrder The ordinal of {@link ByteOrder}, encoding what byte order the
         *            <var>outData</var> should be in.
         */
    
        private static native void copyLongToByte(long[] inData, int inStart, byte[] outData,
                int outStart, int len, int byteOrder);
    
    
        /**
         * Copies a range from an array of <code>byte</code> into an array of <code>long</code>.
         * 
         * @param inData The input array of <code>byte</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>byte</code> to
         *            start
         * @param outData The output array of <code>long</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>long</code> to
         *            start
         * @param len The number of <code>long</code> to copy
         * @param byteOrder The ordinal of {@link ByteOrder}, encoding what byte order the
         *            <var>outData</var> should be in.
         */
    
        private static native void copyByteToLong(byte[] inData, int inStart, long[] outData,
                int outStart, int len, int byteOrder);
    
    
        /**
         * Copies a range from an array of <code>short</code> into an array of <code>byte</code>.
         * 
         * @param inData The input array of <code>short</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>short</code> to
         *            start
         * @param outData The output array of <code>byte</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>byte</code> to
         *            start
         * @param len The number of <code>short</code> to copy
         * @param byteOrder The ordinal of {@link ByteOrder}, encoding what byte order the
         *            <var>outData</var> should be in.
         */
    
        private static native void copyShortToByte(short[] inData, int inStart, byte[] outData,
                int outStart, int len, int byteOrder);
    
    
        /**
         * Copies a range from an array of <code>byte</code> into an array of <code>short</code>.
         * 
         * @param inData The input array of <code>byte</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>byte</code> to
         *            start
         * @param outData The output array of <code>short</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>short</code> to
         *            start
         * @param len The number of <code>short</code> to copy
         * @param byteOrder The ordinal of {@link ByteOrder}, encoding what byte order the
         *            <var>outData</var> should be in.
         */
    
        private static native void copyByteToShort(byte[] inData, int inStart, short[] outData,
                int outStart, int len, int byteOrder);
    
        /**
         * Copies a range from an array of <code>char</code> into an array of <code>byte</code>.
         * 
         * @param inData The input array of <code>char</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>char</code> to
         *            start
         * @param outData The output array of <code>byte</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>byte</code> to
         *            start
         * @param len The number of <code>char</code> to copy
         * @param byteOrder The ordinal of {@link ByteOrder}, encoding what byte order the
         *            <var>outData</var> should be in.
         */
        private static native void copyCharToByte(char[] inData, int inStart, byte[] outData,
                int outStart, int len, int byteOrder);
    
        /**
         * Copies a range from an array of <code>byte</code> into an array of <code>char</code>.
         * 
         * @param inData The input array of <code>byte</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>byte</code> to
         *            start
         * @param outData The output array of <code>char</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>char</code> to
         *            start
         * @param len The number of <code>char</code> to copy
         * @param byteOrder The ordinal of {@link ByteOrder}, encoding what byte order the
         *            <var>outData</var> should be in.
         */
        private static native void copyByteToChar(byte[] inData, int inStart, char[] outData,
                int outStart, int len, int byteOrder);
    
    
        /**
         * Copies a range from an array of <code>float</code> into an array of <code>byte</code>.
         * 
         * @param inData The input array of <code>float</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>float</code> to
         *            start
         * @param outData The output array of <code>byte</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>byte</code> to
         *            start
         * @param len The number of <code>float</code> to copy
         * @param byteOrder The ordinal of {@link ByteOrder}, encoding what byte order the
         *            <var>outData</var> should be in.
         */
    
        private static native void copyFloatToByte(float[] inData, int inStart, byte[] outData,
                int outStart, int len, int byteOrder);
    
    
        /**
         * Copies a range from an array of <code>byte</code> into an array of <code>float</code>.
         * 
         * @param inData The input array of <code>byte</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>byte</code> to
         *            start
         * @param outData The output array of <code>float</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>float</code> to
         *            start
         * @param len The number of <code>float</code> to copy
         * @param byteOrder The ordinal of {@link ByteOrder}, encoding what byte order the
         *            <var>outData</var> should be in.
         */
    
        private static native void copyByteToFloat(byte[] inData, int inStart, float[] outData,
                int outStart, int len, int byteOrder);
    
    
        /**
         * Copies a range from an array of <code>double</code> into an array of <code>byte</code>.
         * 
         * @param inData The input array of <code>double</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>double</code> to
         *            start
         * @param outData The output array of <code>byte</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>byte</code> to
         *            start
         * @param len The number of <code>double</code> to copy
         * @param byteOrder The ordinal of {@link ByteOrder}, encoding what byte order the
         *            <var>outData</var> should be in.
         */
    
        private static native void copyDoubleToByte(double[] inData, int inStart, byte[] outData,
                int outStart, int len, int byteOrder);
    
    
        /**
         * Copies a range from an array of <code>byte</code> into an array of <code>double</code>.
         * 
         * @param inData The input array of <code>byte</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>byte</code> to
         *            start
         * @param outData The output array of <code>double</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>double</code> to
         *            start
         * @param len The number of <code>double</code> to copy
         * @param byteOrder The ordinal of {@link ByteOrder}, encoding what byte order the
         *            <var>outData</var> should be in.
         */
    
        private static native void copyByteToDouble(byte[] inData, int inStart, double[] outData,
                int outStart, int len, int byteOrder);
    
    
        //
        // Public
        //
    
        /** Call to ensure that the native library is loaded. */
        public static void ensureNativeLibIsLoaded()
        {
        }
    
        /**
         * Returns <code>true</code>, if this class uses the native library and <code>false</code>
         * otherwise.
         */
        public static boolean isUseNativeLib()
        {
            return useNativeLib;
        }
    
    
        /**
         * Returns the native byte order of the host running this JRE.
         */
        public static ByteOrder getNativeByteOrder()
        {
    
            return ByteOrder.getNativeByteOrder();
    
        }
    
        /**
         * Changes the byte order of the bytes constituting <var>s</var>.
         */
        public static short changeByteOrder(short s)
        {
            return (short) ((s << 8) | ((s >> 8) & 0xff));
        }
    
        /**
         * Changes the byte order of the bytes constituting <var>c</var>.
         */
        public static char changeByteOrder(char c)
        {
            return (char) ((c << 8) | ((c >> 8) & 0xff));
        }
    
        /**
         * Changes the byte order of the bytes constituting <var>i</var>.
         */
        public static int changeByteOrder(int i)
        {
            return ((changeByteOrder((short) i) << 16) | (changeByteOrder((short) (i >> 16)) & 0xffff));
        }
    
        /**
         * Changes the byte order of the bytes constituting <var>f</var>.
         */
        public static float changeByteOrder(float f)
        {
            return Float.intBitsToFloat(changeByteOrder(Float.floatToRawIntBits(f)));
        }
    
        /**
         * Changes the byte order of the bytes constituting <var>l</var>.
         */
        public static long changeByteOrder(long l)
        {
            return (((long) changeByteOrder((int) (l)) << 32) | (changeByteOrder((int) (l >> 32)) & 0xffffffffL));
        }
    
        /**
         * Changes the byte order of the bytes constituting <var>d</var>.
         */
        public static double changeByteOrder(double d)
        {
            return Double.longBitsToDouble(changeByteOrder(Double.doubleToRawLongBits(d)));
    
        /**
         * Copies a range from an array of <code>int</code> into an array of <code>byte</code>.
         * 
         * @param inData The input array of <code>int</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>int</code> to
         *            start
         * @param outData The output array of <code>byte</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>byte</code> to
         *            start
         * @param len The number of <code>int</code> to copy
         * @param byteOrder The {@link ByteOrder}, encoding what byte order the <var>outData</var>
         *            should be in.
         */
        public static void copyIntToByte(int[] inData, int inStart, byte[] outData, int outStart,
                int len, ByteOrder byteOrder)
        {
    
            if (useNativeLib)
            {
                copyIntToByte(inData, inStart, outData, outStart, len, byteOrder.ordinal());
            } else
            {
                final ByteBuffer bb = ByteBuffer.wrap(outData, outStart, len * INT_SIZE);
                bb.order(byteOrder.getNioByteOrder());
                bb.asIntBuffer().put(inData, inStart, len);
            }
    
        }
    
        /**
         * Copies a range from an array of <code>byte</code> into an array of <code>int</code>.
         * 
         * @param inData The input array of <code>byte</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>byte</code> to
         *            start
         * @param outData The output array of <code>int</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>int</code> to
         *            start
         * @param len The number of <code>int</code> to copy
         * @param byteOrder The {@link ByteOrder}, encoding what byte order the <var>outData</var>
         *            should be in.
         */
        public static void copyByteToInt(byte[] inData, int inStart, int[] outData, int outStart,
                int len, ByteOrder byteOrder)
        {
    
            if (useNativeLib)
            {
                copyByteToInt(inData, inStart, outData, outStart, len, byteOrder.ordinal());
            } else
            {
                final ByteBuffer bb = ByteBuffer.wrap(inData, inStart, len * INT_SIZE);
                bb.order(byteOrder.getNioByteOrder());
                bb.asIntBuffer().get(outData, outStart, len);
            }
    
        }
    
        /**
         * Copies a range from an array of <code>long</code> into an array of <code>byte</code>.
         * 
         * @param inData The input array of <code>long</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>long</code> to
         *            start
         * @param outData The output array of <code>byte</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>byte</code> to
         *            start
         * @param len The number of <code>long</code> to copy
         * @param byteOrder The {@link ByteOrder}, encoding what byte order the <var>outData</var>
         *            should be in.
         */
        public static void copyLongToByte(long[] inData, int inStart, byte[] outData, int outStart,
                int len, ByteOrder byteOrder)
        {
    
            if (useNativeLib)
            {
                copyLongToByte(inData, inStart, outData, outStart, len, byteOrder.ordinal());
            } else
            {
                final ByteBuffer bb = ByteBuffer.wrap(outData, outStart, len * LONG_SIZE);
                bb.order(byteOrder.getNioByteOrder());
                bb.asLongBuffer().put(inData, inStart, len);
            }
    
        }
    
        /**
         * Copies a range from an array of <code>byte</code> into an array of <code>long</code>.
         * 
         * @param inData The input array of <code>byte</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>byte</code> to
         *            start
         * @param outData The output array of <code>long</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>long</code> to
         *            start
         * @param len The number of <code>long</code> to copy
         * @param byteOrder The {@link ByteOrder}, encoding what byte order the <var>outData</var>
         *            should be in.
         */
        public static void copyByteToLong(byte[] inData, int inStart, long[] outData, int outStart,
                int len, ByteOrder byteOrder)
        {
    
            if (useNativeLib)
            {
                copyByteToLong(inData, inStart, outData, outStart, len, byteOrder.ordinal());
            } else
            {
                final ByteBuffer bb = ByteBuffer.wrap(inData, inStart, len * LONG_SIZE);
                bb.order(byteOrder.getNioByteOrder());
                bb.asLongBuffer().get(outData, outStart, len);
            }
    
        }
    
        /**
         * Copies a range from an array of <code>short</code> into an array of <code>byte</code>.
         * 
         * @param inData The input array of <code>short</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>short</code> to
         *            start
         * @param outData The output array of <code>byte</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>byte</code> to
         *            start
         * @param len The number of <code>short</code> to copy
         * @param byteOrder The {@link ByteOrder}, encoding what byte order the <var>outData</var>
         *            should be in.
         */
        public static void copyShortToByte(short[] inData, int inStart, byte[] outData, int outStart,
                int len, ByteOrder byteOrder)
        {
    
            if (useNativeLib)
            {
                copyShortToByte(inData, inStart, outData, outStart, len, byteOrder.ordinal());
            } else
            {
                final ByteBuffer bb = ByteBuffer.wrap(outData, outStart, len * SHORT_SIZE);
                bb.order(byteOrder.getNioByteOrder());
                bb.asShortBuffer().put(inData, inStart, len);
            }
    
        /**
         * Copies a range from an array of <code>char</code> into an array of <code>byte</code>.
         * 
         * @param inData The input array of <code>char</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>char</code> to
         *            start
         * @param outData The output array of <code>byte</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>byte</code> to
         *            start
         * @param len The number of <code>char</code> to copy
         * @param byteOrder The {@link ByteOrder}, encoding what byte order the <var>outData</var>
         *            should be in.
         */
        public static void copyCharToByte(char[] inData, int inStart, byte[] outData, int outStart,
                int len, ByteOrder byteOrder)
        {
            if (useNativeLib)
            {
                copyCharToByte(inData, inStart, outData, outStart, len, byteOrder.ordinal());
            } else
            {
                final ByteBuffer bb = ByteBuffer.wrap(outData, outStart, len * SHORT_SIZE);
                bb.order(byteOrder.getNioByteOrder());
                bb.asCharBuffer().put(inData, inStart, len);
            }
        }
    
    
        /**
         * Copies a range from an array of <code>byte</code> into an array of <code>short</code>.
         * 
         * @param inData The input array of <code>byte</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>byte</code> to
         *            start
         * @param outData The output array of <code>short</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>short</code> to
         *            start
         * @param len The number of <code>short</code> to copy
         * @param byteOrder The {@link ByteOrder}, encoding what byte order the <var>outData</var>
         *            should be in.
         */
        public static void copyByteToShort(byte[] inData, int inStart, short[] outData, int outStart,
                int len, ByteOrder byteOrder)
        {
    
            if (useNativeLib)
            {
                copyByteToShort(inData, inStart, outData, outStart, len, byteOrder.ordinal());
            } else
            {
                final ByteBuffer bb = ByteBuffer.wrap(inData, inStart, len * SHORT_SIZE);
                bb.order(byteOrder.getNioByteOrder());
                bb.asShortBuffer().get(outData, outStart, len);
            }
    
        /**
         * Copies a range from an array of <code>byte</code> into an array of <code>char</code>.
         * 
         * @param inData The input array of <code>byte</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>byte</code> to
         *            start
         * @param outData The output array of <code>short</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>short</code> to
         *            start
         * @param len The number of <code>short</code> to copy
         * @param byteOrder The {@link ByteOrder}, encoding what byte order the <var>outData</var>
         *            should be in.
         */
        public static void copyByteToChar(byte[] inData, int inStart, char[] outData, int outStart,
                int len, ByteOrder byteOrder)
        {
            if (useNativeLib)
            {
                copyByteToChar(inData, inStart, outData, outStart, len, byteOrder.ordinal());
            } else
            {
                final ByteBuffer bb = ByteBuffer.wrap(inData, inStart, len * CHAR_SIZE);
                bb.order(byteOrder.getNioByteOrder());
                bb.asCharBuffer().get(outData, outStart, len);
            }
        }
    
    
        /**
         * Copies a range from an array of <code>float</code> into an array of <code>byte</code>.
         * 
         * @param inData The input array of <code>float</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>float</code> to
         *            start
         * @param outData The output array of <code>byte</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>byte</code> to
         *            start
         * @param len The number of <code>float</code> to copy
         * @param byteOrder The {@link ByteOrder}, encoding what byte order the <var>outData</var>
         *            should be in.
         */
        public static void copyFloatToByte(float[] inData, int inStart, byte[] outData, int outStart,
                int len, ByteOrder byteOrder)
        {
    
            if (useNativeLib)
            {
                copyFloatToByte(inData, inStart, outData, outStart, len, byteOrder.ordinal());
            } else
            {
                final ByteBuffer bb = ByteBuffer.wrap(outData, outStart, len * FLOAT_SIZE);
                bb.order(byteOrder.getNioByteOrder());
                bb.asFloatBuffer().put(inData, inStart, len);
            }
    
        }
    
        /**
         * Copies a range from an array of <code>byte</code> into an array of <code>float</code>.
         * 
         * @param inData The input array of <code>byte</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>byte</code> to
         *            start
         * @param outData The output array of <code>float</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>float</code> to
         *            start
         * @param len The number of <code>float</code> to copy
         * @param byteOrder The {@link ByteOrder}, encoding what byte order the <var>outData</var>
         *            should be in.
         */
        public static void copyByteToFloat(byte[] inData, int inStart, float[] outData, int outStart,
                int len, ByteOrder byteOrder)
        {
    
            if (useNativeLib)
            {
                copyByteToFloat(inData, inStart, outData, outStart, len, byteOrder.ordinal());
            } else
            {
                final ByteBuffer bb = ByteBuffer.wrap(inData, inStart, len * FLOAT_SIZE);
                bb.order(byteOrder.getNioByteOrder());
                bb.asFloatBuffer().get(outData, outStart, len);
            }
    
        }
    
        /**
         * Copies a range from an array of <code>double</code> into an array of <code>byte</code>.
         * 
         * @param inData The input array of <code>double</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>double</code> to
         *            start
         * @param outData The output array of <code>byte</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>byte</code> to
         *            start
         * @param len The number of <code>double</code> to copy
         * @param byteOrder The {@link ByteOrder}, encoding what byte order the <var>outData</var>
         *            should be in.
         */
        public static void copyDoubleToByte(double[] inData, int inStart, byte[] outData, int outStart,
                int len, ByteOrder byteOrder)
        {
    
            if (useNativeLib)
            {
                copyDoubleToByte(inData, inStart, outData, outStart, len, byteOrder.ordinal());
            } else
            {
                final ByteBuffer bb = ByteBuffer.wrap(outData, outStart, len * DOUBLE_SIZE);
                bb.order(byteOrder.getNioByteOrder());
                bb.asDoubleBuffer().put(inData, inStart, len);
            }
    
        }
    
        /**
         * Copies a range from an array of <code>byte</code> into an array of <code>double</code>.
         * 
         * @param inData The input array of <code>byte</code> values.
         * @param inStart The position in the input array <code>inData</code> of <code>byte</code> to
         *            start
         * @param outData The output array of <code>double</code> values.
         * @param outStart The start in the output array <code>byteData</code> of <code>double</code> to
         *            start
         * @param len The number of <code>double</code> to copy
         * @param byteOrder The {@link ByteOrder}, encoding what byte order the <var>outData</var>
         *            should be in.
         */
        public static void copyByteToDouble(byte[] inData, int inStart, double[] outData, int outStart,
                int len, ByteOrder byteOrder)
        {
    
            if (useNativeLib)
            {
                copyByteToDouble(inData, inStart, outData, outStart, len, byteOrder.ordinal());
            } else
            {
                final ByteBuffer bb = ByteBuffer.wrap(inData, inStart, len * DOUBLE_SIZE);
                bb.order(byteOrder.getNioByteOrder());
                bb.asDoubleBuffer().get(outData, outStart, len);
            }
    
        /**
         * Converts a <code>byte[]</code> array into a <code>char[]</code> array.
         * 
         * @param byteArr The <code>byte[]</code> to convert.
         * @param byteOrder The byte order of <var>byteArr</var>.
         * @param start The position in the <var>byteArr</var> to start the conversion.
         * @param len The number of <code>short</code> values to convert.
         * @return The <code>char[]</code> array.
         */
        public static char[] byteToChar(byte[] byteArr, ByteOrder byteOrder, int start, int len)
        {
            final char[] array = new char[len];
            copyByteToChar(byteArr, start, array, 0, len, byteOrder);
            return array;
        }
    
        /**
         * Converts a <code>byte[]</code> array into a <code>char[]</code> array.
         * 
         * @param byteArr The <code>byte[]</code> to convert.
         * @param byteOrder The byte order of <var>byteArr</var>.
         * @return The <code>char[]</code> array.
         */
        public static char[] byteToChar(byte[] byteArr, ByteOrder byteOrder)
        {
            if (byteArr.length % CHAR_SIZE != 0)
            {
                throw new IllegalArgumentException("Length of byteArr does not match size of data type");
            }
            final int len = byteArr.length / SHORT_SIZE;
            final char[] array = new char[len];
            copyByteToChar(byteArr, 0, array, 0, len, byteOrder);
            return array;
        }
    
    
        /**
         * Converts a <code>byte[]</code> array into a <code>short[]</code> array.
         * 
         * @param byteArr The <code>byte[]</code> to convert.
         * @param byteOrder The byte order of <var>byteArr</var>.
         * @param start The position in the <var>byteArr</var> to start the conversion.
         * @param len The number of <code>short</code> values to convert.
         * @return The <code>short[]</code> array.
         */
        public static short[] byteToShort(byte[] byteArr, ByteOrder byteOrder, int start, int len)
        {
            final short[] array = new short[len];
    
            copyByteToShort(byteArr, start, array, 0, len, byteOrder);
    
            return array;
        }
    
        /**
         * Converts a <code>byte[]</code> array into a <code>short[]</code> array.
         * 
         * @param byteArr The <code>byte[]</code> to convert.
         * @param byteOrder The byte order of <var>byteArr</var>.
         * @return The <code>short[]</code> array.
         */
        public static short[] byteToShort(byte[] byteArr, ByteOrder byteOrder)
        {
            if (byteArr.length % SHORT_SIZE != 0)
            {
                throw new IllegalArgumentException("Length of byteArr does not match size of data type");
            }
            final int len = byteArr.length / SHORT_SIZE;
            final short[] array = new short[len];
    
            copyByteToShort(byteArr, 0, array, 0, len, byteOrder);
    
            return array;
        }
    
        /**
         * Converts a <code>short[]</code> array to a <code>byte[]</code> array.
         * 
         * @param data The array to convert.
         * @param byteOrder The byte order of the returned <code>byte[]</code>.
         * @param start The position in <var>data</var> to start the conversion.
         * @param len The number of <code>short</code> values to convert.
         * @return The converted <code>byte[]</code> array.
         */
        public static byte[] shortToByte(short[] data, ByteOrder byteOrder, int start, int len)
        {
            final byte[] byteArr = new byte[SHORT_SIZE * len];
    
            copyShortToByte(data, start, byteArr, 0, len, byteOrder);
    
            return byteArr;
        }
    
        /**
         * Converts a <code>short[]</code> array to a <code>byte[]</code> array.
         * 
         * @param data The array to convert.
         * @param byteOrder The byte order of the returned <code>byte[]</code>.
         * @return The converted <code>byte[]</code> array.
         */
        public static byte[] shortToByte(short[] data, ByteOrder byteOrder)
        {
            final byte[] byteArr = new byte[SHORT_SIZE * data.length];
    
            copyShortToByte(data, 0, byteArr, 0, data.length, byteOrder);
    
    
        /**
         * Converts a <code>char[]</code> array to a <code>byte[]</code> array.
         * 
         * @param data The array to convert.
         * @param byteOrder The byte order of the returned <code>byte[]</code>.
         * @param start The position in <var>data</var> to start the conversion.
         * @param len The number of <code>char</code> values to convert.
         * @return The converted <code>byte[]</code> array.
         */
        public static byte[] charToByte(char[] data, ByteOrder byteOrder, int start, int len)
        {
            final byte[] byteArr = new byte[CHAR_SIZE * len];
            copyCharToByte(data, start, byteArr, 0, len, byteOrder);
            return byteArr;
        }
    
        /**
         * Converts a <code>char[]</code> array to a <code>byte[]</code> array.
         * 
         * @param data The array to convert.
         * @param byteOrder The byte order of the returned <code>byte[]</code>.
         * @return The converted <code>byte[]</code> array.
         */
        public static byte[] charToByte(char[] data, ByteOrder byteOrder)
        {
            final byte[] byteArr = new byte[CHAR_SIZE * data.length];
            copyCharToByte(data, 0, byteArr, 0, data.length, byteOrder);
            return byteArr;
        }
    
    
        /**
         * Converts a <code>byte[]</code> array into an <code>int[]</code> array.
         * 
         * @param byteArr The <code>byte[]</code> to convert.
         * @param byteOrder The byte order of <var>byteArr</var>.
         * @param start The position in the <var>byteArr</var> to start the conversion.
         * @param len The number of <code>int</code> values to convert.
         * @return The <code>int[]</code> array.
         */
        public static int[] byteToInt(byte[] byteArr, ByteOrder byteOrder, int start, int len)
        {
            final int[] array = new int[len];
    
            copyByteToInt(byteArr, start, array, 0, len, byteOrder);
    
            return array;
        }
    
        /**
         * Converts a <code>byte[]</code> array into an <code>int[]</code> array.
         * 
         * @param byteArr The <code>byte[]</code> to convert.
         * @param byteOrder The byte order of <var>byteArr</var>.
         * @return The <code>int[]</code> array.
         */
        public static int[] byteToInt(byte[] byteArr, ByteOrder byteOrder)
        {
            if (byteArr.length % INT_SIZE != 0)
            {
                throw new IllegalArgumentException("Length of byteArr does not match size of data type");
            }
            final int len = byteArr.length / INT_SIZE;
            final int[] array = new int[len];
    
            copyByteToInt(byteArr, 0, array, 0, len, byteOrder);
    
            return array;
        }
    
        /**
         * Converts a <code>int[]</code> array to a <code>byte[]</code> array.
         * 
         * @param data The array to convert.
         * @param byteOrder The byte order of the returned <code>byte[]</code>.
         * @param start The position in <var>data</var> to start the conversion.
         * @param len The number of <code>int</code> values to convert.
         * @return The converted <code>byte[]</code> array.
         */
        public static byte[] intToByte(int[] data, ByteOrder byteOrder, int start, int len)
        {
            final byte[] byteArr = new byte[INT_SIZE * len];
    
            copyIntToByte(data, start, byteArr, 0, len, byteOrder);
    
            return byteArr;
        }
    
        /**
         * Converts a <code>int[]</code> array to a <code>byte[]</code> array.
         * 
         * @param data The array to convert.
         * @param byteOrder The byte order of the returned <code>byte[]</code>.
         * @return The converted <code>byte[]</code> array.
         */
        public static byte[] intToByte(int[] data, ByteOrder byteOrder)
        {
            final byte[] byteArr = new byte[INT_SIZE * data.length];
    
            copyIntToByte(data, 0, byteArr, 0, data.length, byteOrder);
    
            return byteArr;
        }
    
        /**
         * Converts a <code>byte[]</code> array into a <code>long[]</code> array.
         * 
         * @param byteArr The <code>byte[]</code> to convert.
         * @param byteOrder The byte order of <var>byteArr</var>.
         * @param start The position in the <var>byteArr</var> to start the conversion.
         * @param len The number of <code>long</code> values to convert.
         * @return The <code>long[]</code> array.
         */
        public static long[] byteToLong(byte[] byteArr, ByteOrder byteOrder, int start, int len)
        {
            final long[] array = new long[len];
    
            copyByteToLong(byteArr, start, array, 0, len, byteOrder);
    
            return array;
        }
    
        /**
         * Converts a <code>byte[]</code> array into a <code>long[]</code> array.
         * 
         * @param byteArr The <code>byte[]</code> to convert.
         * @param byteOrder The byte order of <var>byteArr</var>.
         * @return The <code>long[]</code> array.
         */
        public static long[] byteToLong(byte[] byteArr, ByteOrder byteOrder)
        {
            if (byteArr.length % LONG_SIZE != 0)
            {
                throw new IllegalArgumentException("Length of byteArr does not match size of data type");
            }
            final int len = byteArr.length / LONG_SIZE;
            final long[] array = new long[len];
    
            copyByteToLong(byteArr, 0, array, 0, len, byteOrder);
    
            return array;
        }
    
        /**
         * Converts a <code>long[]</code> array to a <code>byte[]</code> array.
         * 
         * @param data The array to convert.
         * @param byteOrder The byte order of the returned <code>byte[]</code>.
         * @param start The position in <var>data</var> to start the conversion.
         * @param len The number of <code>long</code> values to convert.
         * @return The converted <code>byte[]</code> array.
         */
        public static byte[] longToByte(long[] data, ByteOrder byteOrder, int start, int len)
        {
            final byte[] byteArr = new byte[LONG_SIZE * len];
    
            copyLongToByte(data, start, byteArr, 0, len, byteOrder);
    
            return byteArr;
        }
    
        /**
         * Converts a <code>long[]</code> array to a <code>byte[]</code> array.
         * 
         * @param data The array to convert.
         * @param byteOrder The byte order of the returned <code>byte[]</code>.
         * @return The converted <code>byte[]</code> array.
         */
        public static byte[] longToByte(long[] data, ByteOrder byteOrder)
        {
            final byte[] byteArr = new byte[LONG_SIZE * data.length];
    
            copyLongToByte(data, 0, byteArr, 0, data.length, byteOrder);
    
            return byteArr;
        }
    
        /**
         * Converts a <code>byte[]</code> array into a <code>float[]</code> array.
         * 
         * @param byteArr The <code>byte[]</code> to convert.
         * @param byteOrder The byte order of <var>byteArr</var>.
         * @param start The position in the <var>byteArr</var> to start the conversion.
         * @param len The number of <code>float</code> values to convert.
         * @return The <code>float[]</code> array.
         */
        public static float[] byteToFloat(byte[] byteArr, ByteOrder byteOrder, int start, int len)
        {
            final float[] array = new float[len];
    
            copyByteToFloat(byteArr, start, array, 0, len, byteOrder);
    
            return array;
        }
    
        /**
         * Converts a <code>byte[]</code> array into a <code>float[]</code> array.
         * 
         * @param byteArr The <code>byte[]</code> to convert.
         * @param byteOrder The byte order of <var>byteArr</var>.
         * @return The <code>float[]</code> array.
         */
        public static float[] byteToFloat(byte[] byteArr, ByteOrder byteOrder)
        {
            if (byteArr.length % FLOAT_SIZE != 0)
            {
                throw new IllegalArgumentException("Length of byteArr does not match size of data type");
            }
            final int len = byteArr.length / FLOAT_SIZE;
            final float[] array = new float[len];
    
            copyByteToFloat(byteArr, 0, array, 0, len, byteOrder);
    
            return array;
        }
    
        /**
         * Converts a <code>float[]</code> array to a <code>byte[]</code> array.
         * 
         * @param data The array to convert.
         * @param byteOrder The byte order of the returned <code>byte[]</code>.
         * @param start The position in <var>data</var> to start the conversion.
         * @param len The number of <code>float</code> values to convert.
         * @return The converted <code>byte[]</code> array.
         */
        public static byte[] floatToByte(float[] data, ByteOrder byteOrder, int start, int len)