using System;
using System.IO;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using miew.Debugging;
using miew.Enumerable;
using miew.String;
namespace agree
{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public abstract partial class Tfs : ISysObj
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public Double MarkDensity
{
get
{
HashSet<int> in_marks = InMarks;
if (in_marks.Count == 0)
return 0;
int range = in_marks.Max() - in_marks.Min() + 1;
return (double)in_marks.Count / range;
}
}
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public HashSet<int> InMarks
{
get { return FeatMarkEdges.Select(fme => fme.mark).ToHashSet(); }
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public HashSet<FeatMark> FeatMarksBelow
{
get
{
if (Edge.Mark == 0)
return FeatMark.EmptyHashSet;
return new FeatMarkGatherer(this, Edge, new HashSet<FeatMark>()).Result;
}
}
public void GatherFeatMarksBelow(HashSet<FeatMark> hs)
{
if (Edge.Mark != 0)
new FeatMarkGatherer(this, Edge, hs);
}
sealed class FeatMarkGatherer
{
Tfs tfs;
int[][] rgrgfix;
HashSet<FeatMark> hs;
public FeatMarkGatherer(Tfs tfs, Edge e, HashSet<FeatMark> hs)
{
this.tfs = tfs;
this.rgrgfix = tfs.tm.rgrgfix_by_type;
this.hs = hs ?? new HashSet<FeatMark>();
_gather(e);
}
void _gather(Edge e)
{
foreach (int i_feat in rgrgfix[(int)(e.FlagsId & Edge.Flag.MultiIdMask)])
{
Edge ne;
FeatMark fm;
if (tfs.TryGetEdge(i_feat, e.Mark, out ne) && !hs.Contains(fm = new FeatMark(i_feat, e.Mark)))
{
hs.Add(fm);
if (ne.Mark != 0)
_gather(ne);
}
}
}
public HashSet<FeatMark> Result { get { return hs; } }
};
public struct FeatMarkEdgeGatherer
{
Tfs tfs;
int[][] rgrgfix;
HashSet<FeatMark> hs;
int in_filter, out_filter;
public FeatMarkEdgeGatherer(Tfs tfs, int in_filter = int.MaxValue, int out_filter = int.MaxValue)
{
this.tfs = tfs;
this.rgrgfix = tfs.tm.rgrgfix_by_type;
this.in_filter = in_filter;
this.out_filter = out_filter;
this.hs = new HashSet<FeatMark>();
}
public IEnumerable<FeatMarkEdge> Gather(Edge e)
{
foreach (int i_feat in rgrgfix[(int)(e.FlagsId & Edge.Flag.MultiIdMask)])
{
Edge ne;
FeatMark fm;
if (tfs.TryGetEdge(i_feat, e.Mark, out ne) && !hs.Contains(fm = new FeatMark(i_feat, e.Mark)))
{
hs.Add(fm);
if ((in_filter == int.MaxValue || e.Mark == in_filter) &&
(out_filter == int.MaxValue || ne.Mark == out_filter))
yield return new FeatMarkEdge(i_feat, e.Mark, ne);
if (ne.Mark != 0)
foreach (var fme in Gather(ne))
yield return fme;
}
}
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public HashSet<TfsFeatMark> TfsFeatMarksBelow
{
get
{
if (Edge.Mark == 0)
return TfsFeatMark.EmptyHashSet;
return new TfsFeatMarkGatherer(this, Edge, new HashSet<TfsFeatMark>()).Result;
}
}
public void GatherTfsFeatMarksBelow(HashSet<TfsFeatMark> hs)
{
if (Edge.Mark != 0)
new TfsFeatMarkGatherer(this, Edge, hs);
}
sealed class TfsFeatMarkGatherer
{
Tfs tfs;
int[][] rgrgfix;
HashSet<TfsFeatMark> hs;
public TfsFeatMarkGatherer(Tfs tfs, Edge e, HashSet<TfsFeatMark> hs)
{
this.tfs = tfs;
this.rgrgfix = tfs.tm.rgrgfix_by_type;
this.hs = hs ?? new HashSet<TfsFeatMark>();
_gather(e);
}
void _gather(Edge e)
{
foreach (int i_feat in rgrgfix[(int)(e.FlagsId & Edge.Flag.MultiIdMask)])
{
Edge ne;
TfsFeatMark tfm;
if (tfs.TryGetEdge(i_feat, e.Mark, out ne) && !hs.Contains(tfm = new TfsFeatMark(tfs, i_feat, e.Mark)))
{
hs.Add(tfm);
if (ne.Mark != 0)
_gather(ne);
}
}
}
public HashSet<TfsFeatMark> Result { get { return hs; } }
};
public int GarbageReport(TextWriter tw)
{
HashSet<FeatMark> reachable = FeatMarksBelow;
int ec = EdgeCount;
if (reachable.Count != ec)
{
tw.WriteLine("TFS {0} ({1}): {2} reachable, {3} items", Name, GetType().Name, reachable.Count, ec);
HashSet<FeatMark> all = FeatMarkEdges.Select(fme => fme.FeatMark).ToHashSet();
all.ExceptWith(reachable);
foreach (FeatMark fm in all)
tw.WriteLine("\t{0,3} {1,-13} {2}", fm.m, tm.feat_arr[fm.i_feat].feature.ToUpper(), GetEdge(fm.i_feat, fm.m));
}
return reachable.Count;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if DEBUG
long _h = -1;
public long TfsHash()
{
if (_h == -1)
_h = TfsHash(Edge);
return _h;
}
#else
public long TfsHash()
{
return TfsHash(Edge);
}
#endif
public long TfsHash(Edge e)
{
return e.Mark != 0 ? new TfsHashGatherer(this, e).Result : (long)((int)e.FlagsId ^ 0x12345678);
}
sealed class TfsHashGatherer : HashSet<FeatMark>
{
Tfs tfs;
TypeMgr tm;
long h = 0;
public TfsHashGatherer(Tfs tfs, Edge e)
{
this.tfs = tfs;
this.tm = tfs.tm;
_gather(e, 1);
}
void _gather(Edge e, int level)
{
foreach (int i_feat in tm.rgrgfix_by_type[(int)(e.FlagsId & Edge.Flag.MultiIdMask)])
{
Edge ne;
if (tfs.TryGetEdge(i_feat, e.Mark, out ne))
{
h += (((long)(uint)i_feat << 32) | (long)(uint)ne.FlagsId) * level;
FeatMark fm = new FeatMark(i_feat, e.Mark);
if (!this.Contains(fm))
{
this.Add(fm);
if ((ne.FlagsId & Edge.Flag.EtmNonBareType) != 0)
_gather(ne, level + 1);
}
}
}
}
public long Result { get { return h; } }
};
#if RUDE_TRUNCATE
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void RudeTruncate(Edge e)
{
new RudeTruncator(this, e);
}
sealed class RudeTruncator
{
Tfs tfs;
TypeMgr tm;
HashSet<Edge> corefs = null;
public RudeTruncator(Tfs tfs, Edge e)
{
this.tfs = tfs;
this.tm = tfs.tm;
_rude_truncate(e);
}
void _rude_truncate(Edge e)
{
foreach (int i_feat in tm.rgrgfix_by_type[(int)(e.FlagsId & Edge.Flag.MultiIdMask)])
{
Edge ne;
if (tfs.TryGetEdge(i_feat, e.Mark, out ne))
{
bool f_descend = true;
if (ne.FlagsId < 0)
{
if (corefs == null)
corefs = new HashSet<Edge> { ne };
else if (!corefs.Contains(ne))
corefs.Add(ne);
else
f_descend = false;
}
if (f_descend && (ne.FlagsId & Edge.Flag.EtmNonBareType) != 0)
_rude_truncate(ne);
tfs.RemoveEdge(i_feat, e.Mark);
}
}
}
};
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public String ToPathList(bool f_marks = false)
{
return new PathLister(this, Edge, null, f_marks).ToString();
}
public String ToPathList(String label, bool f_marks = false)
{
return new PathLister(this, Edge, label, f_marks).ToString();
}
public String ToPathList(Edge edge, String label, bool f_marks = false)
{
return new PathLister(this, edge, label, f_marks).ToString();
}
sealed public class PathLister : List<String>
{
Tfs tfs;
TypeMgr tm;
Stack<String> stack = new Stack<String>();
Dictionary<Edge, int> d = null;
int coref_tag = 0;
bool f_marks;
bool f_internal;
HashSet<FeatMark> reachable = null;
public PathLister(Tfs tfs, Edge e, String label, bool f_marks, HashSet<FeatMark> reachable = null, bool f_internal = false)
{
this.tfs = tfs;
this.tm = tfs.tm;
this.f_marks = f_marks;
this.f_internal = f_internal;
this.reachable = reachable;
if (label != null)
this.Add(String.Format(";;;;;;;;; ({0})", label));
_list_paths(e, null);
}
void _list_paths(Edge e, String s_usage)
{
bool f_descend = true;
Type t;
if (tm.IsTopId(e))
{
t = tm.TopType;
f_descend = false;
}
else
t = tm.GetEdgeType(e.FlagsId);
String s = String.Format("{0} {1}", stack.Reverse().StringJoin("."), t);
if (tm.IsStringValue(e.FlagsId))
s += " “" + tm.GetStringValue(e.FlagsId) + "”";
if (e.FlagsId < 0)
{
if (d == null)
d = new Dictionary<Edge, int>();
int cre;
if (f_internal)
{
cre = e.Mark;
if (!d.ContainsKey(e))
d.Add(e, 1);
else
f_descend = false;
}
else
{
if (!d.TryGetValue(e, out cre))
d.Add(e, cre = coref_tag++);
else
f_descend = false;
}
if (!f_internal)
s += " #" + cre.ToString();
}
if (f_internal)
#if DEBUG
s += " " + Edge.FormatMark(e);
#else
s += " " + e.Mark.ToString();
#endif
if (s_usage != null)
s += " in-use by " + s_usage;
this.Add(s);
if (f_descend && e.Mark != 0)
{
/// this determines the order of coref tag numbering. it used to be specified here with
/// .OrderBy(cp => cp.IntroducedBy.m_level) but this is not needed so long as the feature index order
/// in the type is kept this way, as it is at this time.
foreach (int i_feat in tm.rgrgfix_by_type[(int)(e.FlagsId & Edge.Flag.MultiIdMask)])
{
Edge q;
String usage = null;
#if DEBUG
if (reachable != null && reachable.Contains(new FeatMark(i_feat, e.Mark)))
usage = tfs.Roots.FindRootData(e.Mark).ToString();
#endif
if (tfs.TryGetEdge(i_feat, e.Mark, out q))
{
stack.Push(tm.feat_arr[i_feat].feature.ToUpper());
_list_paths(q, usage);
stack.Pop();
}
}
}
}
public override string ToString() { return this.StringJoin(Environment.NewLine) + Environment.NewLine; }
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class MonospaceFormatter
{
TypeMgr tm;
Tfs tfs;
Dictionary<Edge, int> corefs = new Dictionary<Edge, int>();
bool f_uncons_top = true;
bool f_unfill = true;
int[] feature_order = null;
IDictionary<String, String> type_name_remapping = null;
public MonospaceFormatter(TypeMgr tm)
{
this.tm = tm;
}
public int[] FeatureDisplayOrder
{
get { return feature_order; }
set { feature_order = value; }
}
public bool Unfill
{
get { return f_unfill; }
set { f_unfill = value; }
}
/// <summary>
/// Type names can be substituted to account for e.g. different glb number assignments in a comparison
/// system.
/// </summary>
public IDictionary<String, String> TypeNameRemapping
{
get { return type_name_remapping; }
set { type_name_remapping = value; }
}
/// <summary>
/// Note: Single-threaded (use of corefs)
/// </summary>
public String FormatEdge(Tfs tfs)
{
this.tfs = tfs;
corefs.Clear();
String r = tm.GetEdgeType(tfs.Edge.FlagsId).Name;
String s = _format_edge(0, tfs.Edge);
if (s != String.Empty)
r += Environment.NewLine + s;
return r;
}
String _format_edge(int indent, Edge e)
{
var rgcr = (f_uncons_top ?
tfs.AllConstraintRefs(e) :
tfs.ConstrainedRefsOnly(e))
.ToArray();
if (rgcr.Length == 0)
return String.Empty;
if (feature_order != null)
rgcr = rgcr.OrderBy(cr => Array.IndexOf<int>(feature_order, cr.i_feat)).ToArray();
int feat_max = rgcr.Max(cr => cr.Feature.Length) + 1;
String s_indent = new String(' ', indent);
StringBuilder sb = new StringBuilder();
bool f_first = true;
foreach (ConstraintRef cr in rgcr)
{
Edge ne = cr.Constraint;
if (f_first)
{
sb.Append(s_indent + "[ ");
f_first = false;
}
else
sb.Append("," + Environment.NewLine + s_indent + " ");
sb.Append(cr.Feature.ToUpper().PadRight(feat_max));
bool f_old_coref = false;
String coref_text = String.Empty;
if (ne.IsCoreferenced)
{
int i_coref;
if (!corefs.TryGetValue(ne, out i_coref))
{
i_coref = corefs.Count + 1;
corefs.Add(ne, i_coref);
coref_text = String.Format("#{0}:", i_coref);
}
else
{
coref_text = "#" + i_coref.ToString();
f_old_coref = true;
}
sb.Append(coref_text);
}
if (!f_old_coref)
{
String s_type;
if (tm.IsStringValue(ne.FlagsId))
s_type = "\"" + tm.GetStringValue(ne.FlagsId) + "\"";
else
{
s_type = tm.GetEdgeType(ne.FlagsId).Name;
String s_tmp;
if (type_name_remapping != null && type_name_remapping.TryGetValue(s_type, out s_tmp))
s_type = s_tmp;
}
sb.Append(s_type);
if (!f_unfill || !tfs.CanUnfill(cr))
{
String cons = _format_edge(indent + feat_max + 2 + coref_text.Length, ne);
if (cons.Length > 0)
sb.Append(Environment.NewLine + cons);
}
}
}
sb.Append(" ]");
return sb.ToString();
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public bool CanUnfill(ConstraintRef cr)
{
Edge e = cr.Constraint;
Type t0 = tm.GetEdgeType(e.FlagsId);
foreach (int fix in t0.fc.rg_fix)
{
Edge ne;
if (TryGetEdge(fix, e.Mark, out ne))
{
Edge ne2;
TryGetEdge(fix, t0.Expanded.Edge.Mark, out ne2);
Type t3 = tm.GetEdgeType(ne2.FlagsId);
if (ne.IsCoreferenced)
return false;
if (tm.GetEdgeType(ne.FlagsId) != t3)
return false;
if (ne.Mark != 0 && !CanUnfill(new ConstraintRef(this, e, fix)))
return false;
}
}
return true;
}
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
RootAnalysis ra;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public RootAnalysis Roots
{
get { return ra = ra ?? new RootAnalysis(this); }
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class RootAnalysis
{
Tfs tfs;
TypeMgr tm;
Dictionary<int, RootEdgeData> roots = new Dictionary<int, RootEdgeData>();
public RootAnalysis(Tfs tfs)
{
this.tfs = tfs;
this.tm = tfs.tm;
foreach (Instance t in tm.AllInstances)
{
int mx_d;
mx_d = t.Definition.Edge.Mark;
if (mx_d != 0)
{
int mx_e = 0;
if (t.IsExpanded)
{
if ((mx_e = t.Expanded.Edge.Mark) != 0 && mx_e != mx_d)
roots.Add(mx_e, new RootEdgeData(t, RootEdgeType.Expanded, mx_e));
}
if (mx_d == mx_e)
roots.Add(mx_d, new RootEdgeData(t, RootEdgeType.ExpandedDefinition, mx_d));
else
roots.Add(mx_d, new RootEdgeData(t, RootEdgeType.Definition, mx_d));
}
}
}
[Flags]
public enum RootEdgeType
{
Unknown = 0,
Definition = 1,
Expanded = 2,
ExpandedDefinition = 3,
CycleDetected = 4,
};
[DebuggerDisplay("{ToString(),nq}")]
public struct RootEdgeData
{
public RootEdgeData(Instance t, RootEdgeType ret, int mark)
{
this.t = t;
this.ret = ret;
this.mark = mark;
}
public Instance t;
public RootEdgeType ret;
public int mark;
#if DEBUG
public override String ToString()
{
if (ret == RootEdgeType.Unknown || ret == RootEdgeType.CycleDetected)
return ret.ToString();
return String.Format("{0} {1} {2}", t.Name, ret, Edge.FormatMark(new Edge(0, mark)));
}
#endif
};
public Instance FindRoot(int m)
{
RootEdgeData red;
return roots.TryGetValue(tfs.FindTop(m), out red) ? red.t : null;
}
public RootEdgeData FindRootData(int m)
{
RootEdgeData red;
return roots.TryGetValue(tfs.FindTop(m), out red) ? red : default(RootEdgeData);
}
[DebuggerDisplay("{ToString(),nq}")]
public struct TaggedFsPath
{
public RootEdgeData red;
public FsPath fsp;
public override string ToString()
{
return String.Format("{0} {1}", red.ret == RootEdgeType.Unknown ? "???" : red.ToString(), fsp.ToString());
}
};
};
public int FindTop(int mark)
{
int top_mark = mark;
restart:
foreach (var fme in this.FeatMarkEdges)
{
if (fme.e.Mark == top_mark)
{
top_mark = fme.mark;
goto restart;
}
}
return top_mark;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void CleanGarbage(HashSet<FeatMark> reachable)
{
//HashSet<FeatMark> pool_pms = new HashSet<FeatMark>(this.FeatMarkEdges.Select(fme => fme.FeatMark));
//HashSet<FeatMark> garbage = new HashSet<FeatMark>(pool_pms.Except(reachable));
//foreach (Edge gedge in TreeTops(garbage))
// if (gedge.Mark != 0)
// RudeTruncate(gedge);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public IEnumerable<Edge> TreeTops(IEnumerable<FeatMark> set)
{
HashSet<FeatMark> hs = new HashSet<FeatMark>(set);
foreach (FeatMark fm in set)
hs.ExceptWith(AllFeatMarks(fm.Constraint(this)));
return hs._GroupBy(fm => fm.m)
.Select(g =>
{
Type tx = tm.GlbOfMany(g.Select(pm => pm.i_feat)) ?? tm.TopType;
return new Edge((Edge.Flag)tx.m_id, g.Key);
});
}
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public IDictionary<Edge, ReentrancyFinder.Entry> Reentrancies
{
get { return this.GetReentrancies(Edge); }
}
public IDictionary<Edge, ReentrancyFinder.Entry> GetReentrancies(Edge e)
{
return e.Mark != 0 ? new ReentrancyFinder(this, e).Result : ReentrancyFinder.NoCorefs;
}
#if DEBUG
public virtual void CheckCoreferences()
{
//var dfe = GetReentrancies(Edge);
//if (dfe.Count != 0 && this.CorefTallies.Any(kvp => dfe[kvp.Key].Count != kvp.Value))
//{
// if (Debugger.IsAttached)
// Debugger.Break();
// else
// throw new Exception();
//}
}
#endif
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public sealed class ReentrancyFinder
{
public readonly static IDictionary<Edge, Entry> NoCorefs = new Dictionary<Edge, Entry>();
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class Entry : HashSet<ConstraintRef>
{
public Entry(ConstraintRef cref_first, int i_tag)
{
this.cref_display = cref_first;
this.i_tag = i_tag;
}
readonly public int i_tag;
public ConstraintRef cref_display;
public override String ToString() { return String.Format("#{0} in-edges: {1}", i_tag, this.Count); }
};
readonly Tfs tfs;
readonly TypeMgr tm;
Dictionary<Edge, Entry> dict = null;
int coref_tag;
public ReentrancyFinder(Tfs tfs, Edge e)
{
Debug.Assert(e.Mark != 0);
this.tfs = tfs;
this.tm = tfs.tm;
this.coref_tag = 0;
_get_reentrancies(e);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void _get_reentrancies(Edge e)
{
/// this determines the order of coref tag numbering. it used to be specified here with
/// .OrderBy(cp => cp.IntroducedBy.m_level) but this is not needed so long as the feature index order
/// in the type is kept this way, as it is at this time.
foreach (int i_feat in tm.rgrgfix_by_type[(int)(e.FlagsId & Edge.Flag.MultiIdMask)])
{
Edge next_edge;
if (tfs.TryGetEdge(i_feat, e.Mark, out next_edge))
{
if (next_edge.FlagsId < 0)
{
ConstraintRef cref = new ConstraintRef(tfs, e, i_feat);
Entry cre;
if (dict == null)
dict = new Dictionary<Edge, Entry>();
else if (dict.TryGetValue(next_edge, out cre))
{
cre.Add(cref);
continue;
}
dict.Add(next_edge, cre = new Entry(cref, coref_tag++));
cre.Add(cref);
}
if ((next_edge.FlagsId & Edge.Flag.EtmMask) == Edge.Flag.EtmNonBareType)
_get_reentrancies(next_edge);
}
}
}
public IDictionary<Edge, Entry> Result { get { return dict ?? NoCorefs; } }
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public unsafe struct EdgeCounter
{
readonly Tfs tfs;
readonly int[][] rgrgfix;
readonly byte[] coref_tallies;
byte* visited;
int c_coref_actual;
int c_edge;
public EdgeCounter(Tfs tfs, Edge e, byte[] coref_tallies)
{
Debug.Assert(e.Mark != 0);
this.tfs = tfs;
this.rgrgfix = tfs.tm.rgrgfix_by_type;
this.coref_tallies = coref_tallies;
byte* pv = stackalloc byte[coref_tallies.Length];
visited = pv;
c_coref_actual = 0;
c_edge = 0;
_tally_section(&e);
}
public int ActualCount { get { return c_coref_actual; } }
public int EdgeCount { get { return c_edge; } }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void _tally_section(Edge* pe)
{
foreach (int i_feat in rgrgfix[(int)(pe->FlagsId & Edge.Flag.MultiIdMask)])
{
Edge ne;
if (tfs.TryGetEdge(i_feat, pe->Mark, out ne))
{
if (ne.FlagsId < 0)
{
int ix = ~ne.Mark;
coref_tallies[ix]++;
if (visited[ix] == 1)
continue;
c_coref_actual++;
visited[ix] = 1;
}
c_edge++;
if ((ne.FlagsId & Edge.Flag.EtmMask) == Edge.Flag.EtmNonBareType)
_tally_section(&ne);
}
}
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public unsafe struct EdgeCounterRestricted
{
readonly Tfs tfs;
readonly int[][] rgrgfix;
readonly byte[] coref_tallies;
readonly byte[] restrictor;
byte* visited;
int c_coref_actual;
int c_edge;
public EdgeCounterRestricted(Tfs tfs, Edge e, byte[] coref_tallies)
{
Debug.Assert(e.Mark != 0);
this.tfs = tfs;
this.rgrgfix = tfs.tm.rgrgfix_by_type;
this.restrictor = tfs.tm.config.parser.packing_restrictor_map;
this.coref_tallies = coref_tallies;
byte* pv = stackalloc byte[coref_tallies.Length];
visited = pv;
c_coref_actual = 0;
c_edge = 0;
_tally_section(&e);
}
public int ActualCount { get { return c_coref_actual; } }
public int EdgeCount { get { return c_edge; } }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void _tally_section(Edge* pe)
{
foreach (int i_feat in rgrgfix[(int)(pe->FlagsId & Edge.Flag.MultiIdMask)])
{
if (restrictor[i_feat] == 1)
continue;
Edge ne;
if (tfs.TryGetEdge(i_feat, pe->Mark, out ne))
{
if (ne.FlagsId < 0)
{
int ix = ~ne.Mark;
coref_tallies[ix]++;
if (visited[ix] == 1)
continue;
c_coref_actual++;
visited[ix] = 1;
}
c_edge++;
if ((ne.FlagsId & Edge.Flag.EtmMask) == Edge.Flag.EtmNonBareType)
_tally_section(&ne);
}
}
}
};
}