public LinkedList <Features>[][] FindSimilarsIgnoreNullRadius(int[] featureIDs, int kResults, int nRadiuses, float increment, float bias)
        {
            float[][] queryFeatures = new float[featureIDs.Length][];
            for (int i = 0; i < queryFeatures.Length; i++)
            {
                //queryFeatures[i] = new float[4096];
                queryFeatures[i] = GetFeatures(featureIDs[i]);
            }

            LinkedList <Features>[][] results = new LinkedList <Features> [nRadiuses][];
            for (int i = 0; i < nRadiuses; i++)
            {
                results[i] = new LinkedList <Features> [featureIDs.Length];
                for (int j = 0; j < featureIDs.Length; j++)
                {
                    results[i][j] = new LinkedList <Features>();
                }
            }


            reader.BaseStream.Seek(featureDataStartOffset, SeekOrigin.Begin);
            for (int iFeature = 0; iFeature < FeatureCount; iFeature++)
            {
                if (iFeature % 1000 == 0)
                {
                    Console.WriteLine("Checking feature ID: " + iFeature);
                }
                byte[]  bytes  = reader.ReadBytes(FeatureDimension * sizeof(float));
                float[] floats = new float[FeatureDimension];
                Buffer.BlockCopy(bytes, 0, floats, 0, bytes.Length);

                double nullDistance = Distance.L2(new float[FeatureDimension], floats);

                Parallel.For(0, featureIDs.Length, index =>
                {
                    for (int iRadius = 0; iRadius < nRadiuses; iRadius++)
                    {
                        if (nullDistance < (iRadius * increment) + bias)
                        {
                            continue;
                        }

                        double distance = Distance.L2(queryFeatures[index], floats);

                        if (results[iRadius][index].Count == 0)
                        {
                            results[iRadius][index].AddFirst(new Features(floats, iFeature, distance));
                        }
                        else if (results[iRadius][index].Count < kResults || distance < results[iRadius][index].Last.Value.distance)
                        {
                            LinkedListNode <Features> node = results[iRadius][index].First;
                            while (node != null && node.Value.distance < distance)
                            {
                                node = node.Next;
                            }
                            if (node != null)
                            {
                                results[iRadius][index].AddBefore(node, new Features(floats, iFeature, distance));
                            }
                            else
                            {
                                results[iRadius][index].AddLast(new Features(floats, iFeature, distance));
                            }

                            if (results[iRadius][index].Count > kResults)
                            {
                                results[iRadius][index].RemoveLast();
                            }
                        }
                    }
                });
            }


            return(results);
        }
        public LinkedList <Features>[] FindSimilars(int[] featureIDs, int kResults)
        {
            float[][] queryFeatures = new float[featureIDs.Length][];
            for (int i = 0; i < queryFeatures.Length; i++)
            {
                //queryFeatures[i] = new float[featureDimension];
                queryFeatures[i] = GetFeatures(featureIDs[i]);
            }

            LinkedList <Features>[] results = new LinkedList <Features> [featureIDs.Length];
            for (int i = 0; i < featureIDs.Length; i++)
            {
                results[i] = new LinkedList <Features>();
            }

            reader.BaseStream.Seek(featureDataStartOffset, SeekOrigin.Begin);
            for (int i = 0; i < FeatureCount; i++)
            {
                if (i % 10000 == 0)
                {
                    Console.WriteLine("Checking feature ID: " + i);
                }
                byte[]  bytes  = reader.ReadBytes(FeatureDimension * sizeof(float));
                float[] floats = new float[bytes.Length / sizeof(float)];
                Buffer.BlockCopy(bytes, 0, floats, 0, bytes.Length);

                double[] distances = new double[featureIDs.Length];
                Parallel.For(0, featureIDs.Length, j =>
                {
                    distances[j] = Distance.L2(queryFeatures[j], floats);

                    if (results[j].Count == 0)
                    {
                        results[j].AddFirst(new Features(floats, i, distances[j]));
                    }
                    else if (results[j].Count < kResults || distances[j] < results[j].Last.Value.distance)
                    {
                        LinkedListNode <Features> node = results[j].First;
                        while (node != null && node.Value.distance < distances[j])
                        {
                            node = node.Next;
                        }
                        if (node != null)
                        {
                            results[j].AddBefore(node, new Features(floats, i, distances[j]));
                        }
                        else
                        {
                            results[j].AddLast(new Features(floats, i, distances[j]));
                        }

                        if (results[j].Count > kResults)
                        {
                            results[j].RemoveLast();
                        }
                    }
                });
            }


            return(results);
        }