/// <summary>Check that the columns and sizes are consistent.
        /// Inconsistencies include:
        /// <ul>
        /// <li> arrays and sizes have different lengths.
        /// <li> an element of arrays is not a primitive array.
        /// <li> the size of an array is not divisible by the sizes entry.
        /// <li> the number of rows differs for the columns.
        /// </ul>
        /// </summary>
        /// <param name="arrays">The arrays defining the columns.</param>
        /// <param name="sizes">The number of elements in each row for the column.</param>
        protected internal virtual void CheckArrayConsistency(Object[] arrays, int[] sizes)
        {
            // This routine throws an error if it detects an inconsistency
            // between the arrays being read in.

            // First check that the lengths of the two arrays are the same.
            if (arrays.Length != sizes.Length)
            {
                throw new TableException("readArraysAsColumns: Incompatible arrays and sizes.");
            }

            // Now check that that we fill up all of the arrays exactly.
            int ratio   = 0;
            int rowSize = 0;

            //this.types = new char[arrays.Length];
            this.bases = new Type[arrays.Length];

            // Check for a null table.
//			bool nullTable = true;

            for (int i = 0; i < arrays.Length; i += 1)
            {
                ratio = CheckColumnConsistency((Array)arrays[i], ratio, sizes[i]);

                rowSize += sizes[i] * ArrayFuncs.GetBaseLength(arrays[i]);
                //types[i] = classname[1];
                bases[i] = ArrayFuncs.GetBaseClass(arrays[i]);
            }

            this.nrow    = ratio;
            this.rowSize = rowSize;
            this.arrays  = arrays;
            this.sizes   = sizes;
        }
        /// <summary>Add a row to the table.  This method is very inefficient
        /// for adding multiple rows and should be avoided if possible.
        /// </summary>
        public virtual void AddRow(Object[] row)
        {
            if (arrays.Length == 0)
            {
                for (int i = 0; i < row.Length; i += 1)
                {
                    AddColumn((Array)row[i], ((Array)row[i]).Length);
                }
            }
            else
            {
                if (row.Length != arrays.Length)
                {
                    throw new TableException("Row length mismatch");
                }

                for (int i = 0; i < row.Length; i += 1)
                {
                    if (row[i].GetType() != arrays[i].GetType() || ((Array)row[i]).Length != sizes[i])
                    {
                        throw new TableException("Row column mismatch at column:" + i);
                    }
                    Object xarray = ArrayFuncs.NewInstance(bases[i], (nrow + 1) * sizes[i]);
                    Array.Copy((Array)arrays[i], 0, (Array)xarray, 0, nrow * sizes[i]);
                    Array.Copy((Array)row[i], 0, (Array)xarray, nrow * sizes[i], sizes[i]);
                    arrays[i] = xarray;
                }
                InitializePointers();
                nrow += 1;
            }
        }
        /// <summary>Get a element of the table.</summary>
        /// <param name="row">The row desired.</param>
        /// <param name="col">The column desired.</param>
        /// <returns> A primitive array containing the information.  Note
        /// that an array will be returned even if the element
        /// is a scalar.</returns>
        public virtual Object GetElement(int row, int col)
        {
            Array x = ArrayFuncs.NewInstance(bases[col], sizes[col]);

            Array.Copy((Array)arrays[col], sizes[col] * row, x, 0, sizes[col]);
            return(x);
        }
Exemple #4
0
        // suggested in .99.1 version:
        /// Delete a contiguous set of rows from the table.
        /// <param name="row">The row (0-indexed) to be deleted.</param>
        /// <param name="length">The number of rows to be deleted.</param>
        /// <exception cref="TableException"> TableException Thrown when the new data
        /// is not of the same type as the data it replaces.</exception>
        public void DeleteRows(int row, int length)
        {
            if (row < 0 || length < 0 || row + length > nrow)
            {
                throw new TableException("Invalid request to delete rows start: " + row + " length:" + length +
                                         " for table with " + nrow + " rows.");
            }

            if (length == 0)
            {
                return;
            }

            for (int col = 0; col < arrays.Length; col += 1)
            {
                int    sz      = sizes[col];
                int    newSize = sz * (nrow - length);
                Object newArr  = ArrayFuncs.NewInstance(bases[col], newSize);

                // Copy whatever comes before the deletion
                Array.Copy((System.Array)arrays[col], 0, (System.Array)newArr, 0, row * sz);

                // Copy whatever comes after the deletion
                Array.Copy((System.Array)arrays[col], (row + length) * sz,
                           (System.Array)newArr, row * sz, (nrow - row - length) * sz);
                arrays[col] = newArr;
            }
            nrow -= length;
            InitializePointers();
        }
        /// <summary>Add a column</summary>
        public virtual void AddColumn(Array newColumn, int size)
        {
            nrow = CheckColumnConsistency(newColumn, nrow, size);

            rowSize += nrow * ArrayFuncs.GetBaseLength(newColumn);

            GetNumberOfRows();

            int ncol = arrays.Length;

            Object[] newArrays = new Object[ncol + 1];
            int[]    newSizes  = new int[ncol + 1];
            Type[]   newBases  = new Type[ncol + 1];
//			char[] newTypes = new char[ncol + 1];

            Array.Copy(arrays, 0, newArrays, 0, ncol);
            Array.Copy(sizes, 0, newSizes, 0, ncol);
            Array.Copy(bases, 0, newBases, 0, ncol);
//			Array.Copy(types, 0, newTypes, 0, ncol);

            arrays = newArrays;
            sizes  = newSizes;
            bases  = newBases;
//			types = newTypes;

            arrays[ncol] = newColumn;
            sizes[ncol]  = size;
            bases[ncol]  = ArrayFuncs.GetBaseClass(newColumn);
//			types[ncol] = classname[1];
            AddPointer(newColumn);
        }
Exemple #6
0
        /// <summary>Create an array of a type given by new type with
        /// the dimensionality given in array.</summary>
        /// <param name="array">A possibly multidimensional array to be converted.</param>
        /// <param name="newType">The desired output type.  This should be one of the
        /// class descriptors for primitive numeric data, e.g., double.type.</param>
        public static System.Object MimicArray(System.Object array, System.Type newType)
        {
            if (array == null || !array.GetType().IsArray)
            {
                return(null);
            }

            int dims = array.GetType().GetArrayRank();

            Object mimic;

            if (dims > 1)
            {
                Object[] xarray = (Object[])array;
                int[]    dimens = new int[dims];
                dimens[0] = xarray.Length; // Leave other dimensions at 0.

                mimic = ArrayFuncs.NewInstance(newType, dimens);

                for (int i = 0; i < xarray.Length; i += 1)
                {
                    System.Object temp = MimicArray(xarray[i], newType);
                    ((System.Object[])mimic)[i] = temp;
                }
            }
            else
            {
                mimic = ArrayFuncs.NewInstance(newType, GetDimensions(array));
            }

            return(mimic);
        }
        /// <summary>Modify a row of data.</summary>
        /// <param name="row">The row to be modified.</param>
        /// <param name="x">  The data to be modified.  This should be an
        /// array of objects.  It is described as an Object
        /// here since other table implementations may
        /// use other methods to store the data (e.g.,</param>
        /// <seealso cref="">ColumnTable.getColumn.</seealso>
        public virtual void SetRow(int row, Object x)
        {
            if (ArrayFuncs.CountDimensions(x) != 1)           //!(x is Object[]))
            {
                throw new TableException("setRow: Incompatible row");
            }

            for (int col = 0; col < arrays.Length; col += 1)
            {
                SetElement(row, col, ((Array)x).GetValue(col));
            }
        }
Exemple #8
0
        // suggested in .99.1 version:
        /// Delete a contiguous set of columns from the table.
        /// <param name="start">The column (0-indexed) to be deleted.</param>
        /// <param name="len">The number of rows to be deleted.</param>
        /// <exception cref="TableException"> TableException Thrown when the new data
        /// is not of the same type as the data it replaces.</exception>
        public int DeleteColumns(int start, int len)
        {
            int ncol = arrays.Length;

            if (start < 0 || len < 0 || start + len > ncol)
            {
                throw new TableException("Invalid request to delete columns start: " + start + " length:" + len +
                                         " for table with " + ncol + " columns.");
            }

            if (len == 0)
            {
                return(rowSize);
            }

            for (int i = start; i < start + len; i += 1)
            {
                rowSize -= sizes[i] * ArrayFuncs.GetBaseLength(arrays[i]);
            }

            int ocol = ncol;

            ncol -= len;

            Object[] newArrays = new Object[ncol];
            int[]    newSizes  = new int   [ncol];
            Type[]   newBases  = new Type  [ncol];
            char[]   newTypes  = new char  [ncol];

            Array.Copy(arrays, 0, newArrays, 0, start);
            Array.Copy(sizes, 0, newSizes, 0, start);
            Array.Copy(bases, 0, newBases, 0, start);
            //    Array.Copy(types, 0, newTypes, 0, start);

            int rem = ocol - (start + len);

            Array.Copy(arrays, start + len, newArrays, start, rem);
            Array.Copy(sizes, start + len, newSizes, start, rem);
            Array.Copy(bases, start + len, newBases, start, rem);
            //    Array.Copy(types, start + len, newTypes, start, rem);


            arrays = newArrays;
            sizes  = newSizes;
            bases  = newBases;
            //    types  = newTypes;

            InitializePointers();
            return(rowSize);
        }
        /// <summary>Modify an element of the table.</summary>
        /// <param name="row">The row containing the element.</param>
        /// <param name="col">The column containing the element.</param>
        /// <param name="x">  The new datum.  This should be 1-d primitive array.</param>
        /// <exception cref=""> TableException Thrown when the new data
        /// is not of the same type as the data it replaces.</exception>
        public virtual void SetElement(int row, int col, Object x)
        {
            //String classname = x.GetType().FullName;

            //if(!classname.Equals("[" + types[col]))
            if (!(ArrayFuncs.CountDimensions(x) == 1 &&
                  bases[col].Equals(ArrayFuncs.GetBaseClass(x))))
            {
                throw new TableException("setElement: Incompatible element type");
            }

            if (((Array)x).Length != sizes[col])
            {
                throw new TableException("setElement: Incompatible element size");
            }

            Array.Copy((Array)x, 0, (Array)arrays[col], sizes[col] * row, sizes[col]);
        }
Exemple #10
0
        private int CheckColumnConsistency(Array data, int ratio, int size)
        {
            //if (classname[0] != '[' || classname.Length != 2)
            if (ArrayFuncs.CountDimensions(data) != 1 || !ArrayFuncs.GetBaseClass(data).IsPrimitive)
            {
                throw new TableException("Non-primitive array for column");
            }

            int thisSize = data.Length;

            // suggested in .99.2 version: change
            if (thisSize == 0 && size != 0 && ratio != 0 || thisSize != 0 && size == 0)
            {
                throw new TableException("Size mismatch in column");
            }

            // The row size must evenly divide the size of the array.
            if (size != 0 && thisSize % size != 0)
            {
                throw new TableException("Row size does not divide array for column");
            }

            // Finally the ratio of sizes must be the same for all columns -- this
            // is the number of rows in the table.
            int thisRatio = 0;

            if (size > 0)
            {
                thisRatio = thisSize / size;

                if (ratio != 0 && (thisRatio != ratio))
                {
                    throw new TableException("Different number of rows in different columns");
                }
            }
            if (thisRatio > 0)
            {
                return(thisRatio);
            }
            else
            {
                return(ratio);
            }
        }
Exemple #11
0
        /// <summary>Try to create a deep clone of an Array or a standard clone of a scalar.
        /// The object may comprise arrays of any primitive type or any Object type which
        /// implements Cloneable.  However, if the Object is some kind of collection,
        /// e.g., a Vector then only a shallow copy of that object is made.  I.e., deep
        /// refers only to arrays.
        /// </summary>
        /// <param name="o">The object to be copied.</param>

        /*TODO: If multidimension array is passed as an input, it is getting flattened out
         * TODO: For normal multidimension, we get an error because NewInstance always returns Jagged array.*/
        public static System.Object DeepClone(System.Object o)
        {
            if (o == null)
            {
                return(null);
            }
            if (!o.GetType().IsArray)
            {
                return(GenericClone(o));
            }

            Array a = (Array)o;

            if (ArrayFuncs.IsArrayOfArrays(o))
            {
                Array result = NewInstance(o.GetType().GetElementType(), a.Length);
                for (int i = 0; i < result.Length; ++i)
                {
                    result.SetValue(DeepClone(a.GetValue(i)), i);
                }

                return(result);
            }
            else
            {
                int[] lengths = new int[a.Rank];
                for (int i = 0; i < lengths.Length; ++i)
                {
                    lengths[i] = a.GetLength(i);
                }
                Array result = ArrayFuncs.NewInstance(o.GetType().GetElementType(), lengths);
                Array.Copy(a, result, a.Length);

                return(result);
            }
            return(null);
        }
Exemple #12
0
        /// <summary>This routine provides efficient writing of arrays of any primitive type.
        /// The String class is also handled but it is an error to invoke this
        /// method with an object that is not an array of these types.  If the
        /// array is multidimensional, then it calls itself recursively to write
        /// the entire array.  Strings are written using the standard
        /// 1 byte format (i.e., as in writeBytes).
        /// *
        /// If the array is an array of objects, then writePrimitiveArray will
        /// be called for each element of the array.
        /// *
        /// </summary>
        /// <param name="o"> The object to be written.  It must be an array of a primitive
        /// type, Object, or String.</param>
        public override void WriteArray(Object o)
        {
            if (!o.GetType().IsArray)
            {
                throw new IOException("Invalid object passed to BufferedDataStream.Write" + o.GetType().FullName);
            }
            Type type = o.GetType();
            int  rank = ((Array)o).Rank;

            // Is this a multidimensional array?  If so process recursively.
            if (ArrayFuncs.GetDimensions(o).Length > 1)
            //if(o.GetType().GetArrayRank() > 1 || (((Array)o).GetValue(0)).GetType().IsArray)
            {
                if (ArrayFuncs.IsArrayOfArrays(o))
                {
                    IEnumerator i = ((Array)o).GetEnumerator();
                    for (bool ok = i.MoveNext(); ok; ok = i.MoveNext())
                    {
                        WriteArray(i.Current);
                    }
                }
                else
                {
                    throw new IOException("Rectangular array write not supported.");
                }
            }
            else
            {
                // This is a one-d array.  Process it using our special functions.
                Type t = o.GetType().GetElementType();

                if (typeof(bool).Equals(t))
                {
                    Write((bool[])o, 0, ((bool[])o).Length);
                }
                else if (typeof(byte).Equals(t))
                {
                    Write((byte[])o, 0, ((byte[])o).Length);
                }
                else if (typeof(sbyte).Equals(t))
                {
                    Write((sbyte[])o, 0, ((sbyte[])o).Length);
                }
                else if (typeof(char).Equals(t))
                {
                    Write((char[])o, 0, ((char[])o).Length);
                }
                else if (typeof(short).Equals(t))
                {
                    Write((short[])o, 0, ((short[])o).Length);
                }
                else if (typeof(int).Equals(t))
                {
                    Write((int[])o, 0, ((int[])o).Length);
                }
                else if (typeof(long).Equals(t))
                {
                    Write((long[])o, 0, ((long[])o).Length);
                }
                else if (typeof(float).Equals(t))
                {
                    Write((float[])o, 0, ((float[])o).Length);
                }
                else if (typeof(double).Equals(t))
                {
                    Write((double[])o, 0, ((double[])o).Length);
                }
                else if (typeof(String).Equals(t))
                {
                    Write((String[])o, 0, ((String[])o).Length);
                }
                else
                {
                    throw new IOException("Invalid object passed to BufferedDataStream.WriteArray: " + o.GetType().FullName);
                }
            }
        }
Exemple #13
0
        /// <summary>Read recursively over a multi-dimensional array.</summary>
        /// <returns> The number of bytes read.</returns>
        protected int primitiveArrayRecurse(Object o)
        {
            if (o == null)
            {
                return(primitiveArrayCount);
            }

            if (!o.GetType().IsArray)
            {
                throw new IOException("Invalid object passed to BufferedDataStream.ReadArray:" + o.GetType().FullName);
            }

            // Is this a multidimensional array?  If so process recursively.
            //if(o.GetType().GetArrayRank() > 1 || ((Array)o).GetValue(0).GetType().IsArray)
            if (ArrayFuncs.GetDimensions(o).Length > 1)
            {
                if (ArrayFuncs.IsArrayOfArrays(o))
                {
                    IEnumerator i = ((Array)o).GetEnumerator();
                    for (bool ok = i.MoveNext(); ok; ok = i.MoveNext())
                    {
                        primitiveArrayRecurse(i.Current);
                    }
                }
                else
                {
                    throw new IOException("Rectangular array read not supported.");
                }
            }
            else
            {
                // This is a one-d array.  Process it using our special functions.
                Type t = o.GetType().GetElementType();
                if (typeof(bool).Equals(t))
                {
                    primitiveArrayCount += Read((bool[])o, 0, ((bool[])o).Length);
                }
                else if (typeof(byte).Equals(t))
                {
                    primitiveArrayCount += Read((byte[])o, 0, ((byte[])o).Length);
                }
                else if (typeof(sbyte).Equals(t))
                {
                    primitiveArrayCount += Read((sbyte[])o, 0, ((sbyte[])o).Length);
                }
                else if (typeof(char).Equals(t))
                {
                    primitiveArrayCount += Read((char[])o, 0, ((char[])o).Length);
                }
                else if (typeof(short).Equals(t))
                {
                    primitiveArrayCount += Read((short[])o, 0, ((short[])o).Length);
                }
                else if (typeof(int).Equals(t))
                {
                    primitiveArrayCount += Read((int[])o, 0, ((int[])o).Length);
                }
                else if (typeof(long).Equals(t))
                {
                    primitiveArrayCount += Read((long[])o, 0, ((long[])o).Length);
                }
                else if (typeof(float).Equals(t))
                {
                    primitiveArrayCount += Read((float[])o, 0, ((float[])o).Length);
                }
                else if (typeof(double).Equals(t))
                {
                    primitiveArrayCount += Read((double[])o, 0, ((double[])o).Length);
                }
                else
                {
                    throw new IOException("Invalid object passed to BufferedDataStream.ReadArray: " + o.GetType().FullName);
                }
            }

            return(primitiveArrayCount);
        }
        public void TestArrayFuncs()
        {
            // Check GetBaseClass(), GetBaseLength() and ComputeSize() methods
            int[,,] test1 = new int[10, 9, 8];
            bool[][] test2 = new bool[4][];
            test2[0] = new bool[5];
            test2[1] = new bool[4];
            test2[2] = new bool[3];
            test2[3] = new bool[2];

            double[,] test3 = new double[10, 20];
            System.Text.StringBuilder[,] test4 = new System.Text.StringBuilder[3, 2];

            Assert.AreEqual(typeof(int), ArrayFuncs.GetBaseClass(test1));
            Assert.AreEqual(4, ArrayFuncs.GetBaseLength(test1));
            Assert.AreEqual(4 * 8 * 9 * 10, ArrayFuncs.ComputeSize(test1));

            Assert.AreEqual(typeof(bool), ArrayFuncs.GetBaseClass(test2));
            Assert.AreEqual(1, ArrayFuncs.GetBaseLength(test2));
            Assert.AreEqual(1 * (2 + 3 + 4 + 5), ArrayFuncs.ComputeSize(test2));

            Assert.AreEqual(typeof(double), ArrayFuncs.GetBaseClass(test3));
            Assert.AreEqual(8, ArrayFuncs.GetBaseLength(test3));
            Assert.AreEqual(8 * 10 * 20, ArrayFuncs.ComputeSize(test3));

            Assert.AreEqual(typeof(System.Text.StringBuilder), ArrayFuncs.GetBaseClass(test4));
            Assert.AreEqual(-1, ArrayFuncs.GetBaseLength(test4));
            Assert.AreEqual(0, ArrayFuncs.ComputeSize(test4));


            Object[] agg = new Object[4];
            agg[0] = test1;
            agg[1] = test2;
            agg[2] = test3;
            agg[3] = test4;

            Assert.AreEqual(typeof(Object), ArrayFuncs.GetBaseClass(agg));
            Assert.AreEqual(-1, ArrayFuncs.GetBaseLength(agg));


            // Add up all the primitive arrays and ignore the objects.
            Assert.AreEqual(2880 + 14 + 1600 + 0, ArrayFuncs.ComputeSize(agg));

            for (int i = 0; i < ((Array)test1).GetLength(0); i += 1)
            {
                for (int j = 0; j < ((Array)test1).GetLength(1); j += 1)
                {
                    for (int k = 0; k < ((Array)test1).GetLength(2); k += 1)
                    {
                        test1[i, j, k] = i + j + k;
                    }
                }
            }

            /*
             * // Check DeepClone() method: Does not work for multi-dimension Array.
             * int[,,] test5 = (int[,,]) ArrayFuncs.DeepClone(test1);
             *
             *  Assert.AreEqual("deepClone()", true, ArrayFuncs.ArrayEquals(test1, test5));
             *  test5[1,1,1] = -3;
             *  Assert.AreEqual("arrayEquals()", false, ArrayFuncs.ArrayEquals(test1, test5));
             */

            // Check Flatten() method
            int[] dimsOrig = ArrayFuncs.GetDimensions(test1);
            int[] test6    = (int[])ArrayFuncs.Flatten(test1);

            int[] dims = ArrayFuncs.GetDimensions(test6);

            Assert.AreEqual(3, dimsOrig.Length);
            Assert.AreEqual(10, dimsOrig[0]);
            Assert.AreEqual(9, dimsOrig[1]);
            Assert.AreEqual(8, dimsOrig[2]);
            Assert.AreEqual(1, dims.Length);


            // Check Curl method
            int[]   newdims   = { 8, 9, 10 };
            Array[] test7     = (Array[])ArrayFuncs.Curl(test6, newdims);
            int[]   dimsAfter = ArrayFuncs.GetDimensions(test7);

            Assert.AreEqual(3, dimsAfter.Length);
            Assert.AreEqual(8, dimsAfter[0]);
            Assert.AreEqual(9, dimsAfter[1]);
            Assert.AreEqual(10, dimsAfter[2]);


            /*
             * // Check Convert Array method: Implemented in Java Package
             * byte[,,] xtest1 = (byte[,,]) ArrayFuncs.convertArray(test1, typeof(byte));
             *
             * Assert.AreEqual("convertArray(toByte)", typeof(byte), ArrayFuncs.GetBaseClass(xtest1));
             * Assert.AreEqual("convertArray(tobyte)", test1[3,3,3], (int)xtest1[3,3,3]);
             *
             * double[,,] xtest2 = (double[,,]) ArrayFuncs.convertArray(test1, typeof(double));
             * Assert.AreEqual("convertArray(toByte)", typeof(double), ArrayFuncs.GetBaseClass(xtest2));
             * Assert.AreEqual("convertArray(tobyte)", test1[3,3,3], (int)xtest2[3,3,3]);
             */

            // Check NewInstance method
            int[] xtest3 = (int[])ArrayFuncs.NewInstance(typeof(int), 20);
            int[] xtd    = ArrayFuncs.GetDimensions(xtest3);
            Assert.AreEqual(1, xtd.Length);
            Assert.AreEqual(20, xtd[0]);
            Array[] xtest4 = (Array[])ArrayFuncs.NewInstance(typeof(double), new int[] { 5, 4, 3, 2 });

            xtd = ArrayFuncs.GetDimensions(xtest4);
            Assert.AreEqual(4, xtd.Length);
            Assert.AreEqual(5, xtd[0]);
            Assert.AreEqual(4, xtd[1]);
            Assert.AreEqual(3, xtd[2]);
            Assert.AreEqual(2, xtd[3]);
            Assert.AreEqual(120, ArrayFuncs.CountElements(xtest4));

            /*
             * // Check TestPattern method: Implemented in Java package, not in C#.
             * ArrayFuncs.TestPattern(xtest4, (byte)-1);
             *
             * Assert.AreEqual("testPattern()", (double) -1,  xtest4[0,0,0,0]);
             * Assert.AreEqual("testPattern()", (double) 118, xtest4[4,3,2,1]);
             * double[] xtest4x = (double[])ArrayFuncs.GetBaseArray(xtest4);
             *
             * Assert.AreEqual("getBaseArray()", 2, xtest4x.Length);
             */


            // Check ArrayEquals method
            double[] x = { 1, 2, 3, 4, 5 };
            double[] y = new double[x.Length];
            for (int i = 0; i < y.Length; i += 1)
            {
                y[i] = x[i] + 1E-10;
            }

            Assert.AreEqual(false, ArrayFuncs.ArrayEquals(x, y));
            Assert.AreEqual(true, ArrayFuncs.ArrayEquals(x, y, 0d, 1e-9));
            Assert.AreEqual(true, ArrayFuncs.ArrayEquals(x, y, 1E-5, 1e-9));
            Assert.AreEqual(false, ArrayFuncs.ArrayEquals(x, y, 0d, 1e-11));
            Assert.AreEqual(false, ArrayFuncs.ArrayEquals(x, y, 1E-5, 0d));

            float[] fx = { 1, 2, 3, 4, 5 };
            float[] fy = new float[fx.Length];
            for (int i = 0; i < fy.Length; i += 1)
            {
                fy[i] = fx[i] + 1E-5F;
            }

            Assert.AreEqual(false, ArrayFuncs.ArrayEquals(fx, fy));
            Assert.AreEqual(true, ArrayFuncs.ArrayEquals(fx, fy, 1E-4, 0d));
            Assert.AreEqual(false, ArrayFuncs.ArrayEquals(fx, fy, 1E-6, 0d));
            Assert.AreEqual(false, ArrayFuncs.ArrayEquals(fx, fy, 0d, 0d));
            Assert.AreEqual(false, ArrayFuncs.ArrayEquals(fx, fy, 0d, 1E-4));
        }