Esempio n. 1
0
        /// <summary>
        /// Create a new RelationTable that is the inverse of this relation.
        /// </summary>
        /// <remarks>
        /// Very useful for calculating, for example, pip dependents based on pip dependencies, or
        /// per-file producers based on per-pip files produced.
        /// </remarks>
        public RelationTable <TToId, TFromId> Invert()
        {
            RelationTable <TToId, TFromId> result = new RelationTable <TToId, TFromId>(RelatedTable, BaseTableOpt);

            // We will use result.Values to accumulate the counts as usual.
            result.SingleValues.Fill(RelatedTable.Count, 0);
            // And we will use result.m_offsets to store the offsets as usual.
            result.Offsets.Fill(RelatedTable.Count, 0);

            int sum = 0;

            foreach (TFromId id in BaseTableOpt.Ids)
            {
                foreach (TToId relatedId in this[id])
                {
                    result.SingleValues[relatedId.FromId() - 1]++;
                    sum++;
                }
            }

            // Now we can calculate m_offsets.
            result.CalculateOffsets();

            // And we know the necessary size of m_relations.
            result.MultiValues.Capacity = sum;
            result.MultiValues.Fill(sum, default);

            // Allocate an array of positions to track how many relations we have filled in.
            SpannableList <int> positions = new SpannableList <int>(RelatedTable.Count + 1);

            positions.Fill(RelatedTable.Count + 1, 0);

            // And accumulate all the inverse relations.
            foreach (TFromId id in BaseTableOpt.Ids)
            {
                foreach (TToId relatedId in this[id])
                {
                    int relatedIdInt  = relatedId.FromId() - 1;
                    int idInt         = id.FromId() - 1;
                    int offset        = result.Offsets[relatedIdInt];
                    int position      = positions[relatedIdInt];
                    int relationIndex = result.Offsets[relatedIdInt] + positions[relatedIdInt];
                    result.MultiValues[relationIndex] = id;
                    positions[relatedIdInt]++;
                    if (positions[relatedIdInt] > result.SingleValues[relatedIdInt])
                    {
                        // this is a logic bug, should never happen
                        throw new Exception(
                                  $"RelationTable.Inverse: logic exception: positions[{relatedIdInt}] = {positions[relatedIdInt]}, result.SingleValues[{relatedIdInt}] = {result.SingleValues[relatedIdInt]}");
                    }
                    else if (positions[relatedIdInt] == result.SingleValues[relatedIdInt])
                    {
                        // all the relations for this ID are known. now, we have to sort them.
                        Span <TFromId> finalSpan =
                            result.MultiValues.AsSpan().Slice(result.Offsets[relatedIdInt], result.SingleValues[relatedIdInt]);
                        SpanUtilities.Sort(finalSpan, (id1, id2) => id1.FromId().CompareTo(id2.FromId()));
                    }
                }
            }

            // TODO: error check that there are no zero entries in m_relations

            return(result);
        }
Esempio n. 2
0
 /// <summary>
 /// Hashing.
 /// </summary>
 public int GetHashCode([DisallowNull] CharSpan obj) => SpanUtilities.GetHashCode(obj.AsSpan(m_stringTable), CharToInt);