I have a list of indexed triangles for which I need to generate adjacency data. I've already written a brute force algorithm that creates 3 edge data structures for each triangle and then compares the edge structures with those of other triangles like so:

```
public struct AdjEdge
        {
            public Vector3 _ref0;
            public Vector3 _ref1;
            public int _edge;
            public int _face;
            public bool _parsed;

            public AdjEdge(Vector3 ref0, Vector3 ref1, int edge, int face)
            {
                _ref0 = ref0;
                _ref1 = ref1;
                _edge = edge;
                _face = face;
                _parsed = false;
            }
        }

private static int[] GenerateAdjacency(Vector3[] positions,
            List<int> positionIndices)
        {
            int ncFaces = positionIndices.Count / 3;
            int ncVertices = positions.Length;

            // inst. adjacency array and set all values to -1
            int[] adjacency = Enumerable.Repeat(-1, 3 * ncFaces).ToArray();
            if (adjacency == null)
                throw new OutOfMemoryException("Failed to allocate memory for adjacency data");

            List<AdjEdge> edges = new List<AdjEdge>();

            for (int i = 0; i < positionIndices.Count; i+=3)
            {
                int iFace = i / 3;
                edges.Add(new AdjEdge(positions[positionIndices[i + 0]], positions[positionIndices[i + 1]], 0, iFace));
                edges.Add(new AdjEdge(positions[positionIndices[i + 1]], positions[positionIndices[i + 2]], 1, iFace));
                edges.Add(new AdjEdge(positions[positionIndices[i + 2]], positions[positionIndices[i + 0]], 2, iFace));
            }

            for (int i = 0; i < edges.Count - 1; ++i)
            {
                AdjEdge edgeA = edges[i];
                if (edgeA._parsed)
                    continue;

                for (int j = 3 - (i % 3) + i; j < edges.Count; ++j)
                {
                    AdjEdge edgeB = edges[j];
                    if (edgeB._parsed)
                        continue;
                    // CompareVectors() returns true if the vectors are separated by a distance less than 1e-6f
                    if (CompareVectors(edgeA._ref0, edgeB._ref1)
                        && CompareVectors(edgeA._ref1, edgeB._ref0))
                    {
                        adjacency[3 * edgeA._face + edgeA._edge] = edgeB._face;
                        adjacency[3 * edgeB._face + edgeB._edge] = edgeA._face;
                        edgeA._parsed = true;
                        edgeB._parsed = true;
                        break;
                    }
                }
            }

            return adjacency;
        }

```

Needless to say, time complexity is an issue here. What is the most efficient method for generating adjacency when comparing position data using an epsilon?