//#define CIL_EMIT //#define FCTC_STATS using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Threading; using System.Threading.Tasks; using miew.Debugging; using miew.Enumerable; using miew.String; namespace agree { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public partial struct FeatureInfo { public FeatureInfo(String feature, int i_feat, Type maximal_type) { this.i_feat = i_feat; this.feature = feature; this.maximal_type = maximal_type; this.c_failures = 0; } public int i_feat; public String feature; public Type maximal_type; public long c_failures; #if DEBUG public static explicit operator FeatureInfo(int i_feat) { return Grammar._singleton.tm.feat_arr[i_feat]; } #endif }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DebuggerDisplay("{ToString(),nq}")] public sealed class FeatureConfig : IList<int> { public readonly static FeatureConfig Empty = new FeatureConfig(null, null, 0, new int[0]); public class Manager : ICollection<FeatureConfig> { readonly TypeMgr tm; int c_feat_max = 0; public Manager(TypeMgr tm) { this.tm = tm; pod.Add(String.Empty, Empty); } public Dictionary<String, FeatureConfig> pod = new Dictionary<String, FeatureConfig>(); public FeatureConfig Get(Type for_example, IEnumerable<int> rgfix) { if (!rgfix.Any()) return FeatureConfig.Empty; int[] rg = rgfix.Select(ix => new { tm.feat_arr[ix].maximal_type.m_level, ix }) .OrderBy(a => a.m_level) .ThenBy(a => a.ix) .Select(a => a.ix) .ToArray(); String s = rg.Select(ix => ix.ToString()).StringJoin("-"); if (rg.Length > c_feat_max) c_feat_max = rg.Length; FeatureConfig fc; if (!pod.TryGetValue(s, out fc)) pod.Add(s, fc = new FeatureConfig(tm, for_example, pod.Count, rg)); return fc; } public int MaxFeaturesPerType { get { return c_feat_max; } } public void RetuneAll() { Task.Factory.StartNew(() => { #if false /// experiment with putting (only) the most failed path (i.e. SYNSEM) _last_, under the idea that it /// is already handled by quick-check. int ifeat_max_fail = -1; if (tm.g.qcs != null) ifeat_max_fail = tm.feat_arr.ArgMax(fi => fi.c_failures).i_feat; #endif foreach (FeatureConfig fc in pod.Values) { if (fc.rg_fix.Length > 1) { /// note: depends on atomic publishing fc.rg_fix_autotune = fc.rg_fix .OrderByDescending(fix => //fix == ifeat_max_fail ? -1 : tm.feat_arr[fix].c_failures) .ToArray(); } } }); } public bool Contains(FeatureConfig item) { return pod.ContainsValue(item); } public void CopyTo(FeatureConfig[] array, int arrayIndex) { pod.Values.CopyTo(array, arrayIndex); } public int Count { get { return pod.Count; } } public bool IsReadOnly { get { return true; } } public bool Remove(FeatureConfig item) { throw new InvalidOperationException(); } public void Add(FeatureConfig item) { throw new InvalidOperationException(); } public void Clear() { throw new InvalidOperationException(); } public IEnumerator<FeatureConfig> GetEnumerator() { return pod.Values.AsEnumerable<FeatureConfig>().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } }; unsafe FeatureConfig(TypeMgr tm, Type for_example, int ix, int[] rgfix) { this.tm = tm; this.rg_fix = this.rg_fix_autotune = rgfix; this.fc_ix = ix; //this._u_destr = rg_fix.Length == 0 ? (del_u_destr)_u_destr_internal_empty : _first_time; if (rg_fix.Length == 0) return; int max = int.MinValue; int min = int.MaxValue; foreach (int fix in rgfix) { if (fix < min) min = fix; if (fix > max) max = fix; } int range = max - min + 1; modulus = rg_fix.Length; if (modulus > 1) { int gen = 0; int* test_arr = stackalloc int[range]; while (modulus <= range) { gen++; foreach (int fix in rg_fix) { int slot = fix % modulus; if (test_arr[slot] == gen) goto collision; test_arr[slot] = gen; } goto mod_ok; collision: modulus++; } throw new Exception(); } mod_ok: this.fstfs = new FeatureSlotTfs(this, for_example); } [DebuggerBrowsable(DebuggerBrowsableState.Never)] readonly TypeMgr tm; public TypeMgr TypeMgr { get { return tm; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] readonly int fc_ix; public int ConfigIndex { get { return fc_ix; } } readonly public int[] rg_fix; public int[] rg_fix_autotune; readonly public int modulus; readonly public FeatureSlotTfs fstfs; public override String ToString() { return String.Format("#{0} {1}", fc_ix, rg_fix.Select(i => tm.feat_arr[i].feature.ToUpper()).StringJoin(" ")); } public int this[int index] { get { return rg_fix[index]; } set { throw new InvalidOperationException(); } } public int IndexOf(int item) { for (int j = 0; j < rg_fix.Length; j++) if (rg_fix[j] == item) return j; return -1; } public bool Contains(int item) { for (int j = 0; j < rg_fix.Length; j++) if (rg_fix[j] == item) return true; return false; } public void CopyTo(int[] array, int arrayIndex) { for (int j = 0; j < rg_fix.Length; j++) array[arrayIndex++] = rg_fix[j]; } public int Count { get { return rg_fix.Length; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] public bool IsReadOnly { get { return true; } } public void Insert(int index, int item) { throw new InvalidOperationException(); } public void Add(int item) { throw new InvalidOperationException(); } public void Clear() { throw new InvalidOperationException(); } public bool Remove(int item) { throw new InvalidOperationException(); } public void RemoveAt(int index) { throw new InvalidOperationException(); } #if false public delegate bool del_u_destr(Unification u, int m1, TfsEdge te2, Func<ConstraintPool, int, Edge, TfsEdge, bool> fn); public del_u_destr _u_destr; bool _first_time(Unification u, int m1, TfsEdge te2, Func<ConstraintPool, int, Edge, TfsEdge, bool> fn) { _u_destr = emit_DestructiveUnify( //u.TargetTray); u, m1, te2, fn); return _u_destr(u, m1, te2, fn); } del_u_destr emit_DestructiveUnify(//Tray tr) Unification u, int m1, TfsEdge te2, Func<ConstraintPool, int, Edge, TfsEdge, bool> fn) { #if CIL_EMIT Tray tr = u.TargetTray; System.Type[] t_args = { typeof(FeatureConfig), // arg.0 'this' typeof(Unification), // arg.1 'u' typeof(int), // arg.2 'm1' typeof(TfsEdge), // arg.3 'te2' typeof(Func<ConstraintPool, int, Edge, TfsEdge, bool>) // arg.4 'fn' }; DynamicMethod dm = new DynamicMethod(String.Empty, typeof(bool), t_args, typeof(FeatureConfig), true); ILGenerator il = dm.GetILGenerator(); il.DeclareLocal(typeof(Tray)); // loc.0 'tr' il.DeclareLocal(typeof(int)); // loc.1 'm2' il.DeclareLocal(typeof(ConstraintPool[])); // loc.2 'rgcp' il.DeclareLocal(typeof(ConstraintPool)); // loc.3 'cp' il.DeclareLocal(typeof(Edge)); // loc.4 'ne1' il.DeclareLocal(typeof(Edge)); // loc.5 'ge' /// tr = u.TargetTray /// rgcp = tr.Pools; il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Call, typeof(Unification).GetMethod("get_TargetTray")); il.Emit(OpCodes.Dup); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldfld, typeof(Tray).GetField("Pools")); il.Emit(OpCodes.Stloc_2); /// m2 = te2.Edge.Mark il.Emit(OpCodes.Ldarga_S, 3); il.Emit(OpCodes.Ldfld, typeof(TfsEdge).GetField("Edge")); il.Emit(OpCodes.Ldfld, typeof(Edge).GetField("Mark")); il.Emit(OpCodes.Stloc_1); foreach (int fix in rg_fix) { ConstraintPool cp = tr.Pools[fix]; Label l_next_iter = il.DefineLabel(); /// cp = rgcp[@fix] il.Emit(OpCodes.Ldloc_2); il.Emit(OpCodes.Ldc_I4, fix); il.Emit(OpCodes.Ldelem_Ref); il.Emit(OpCodes.Stloc_3); /// danger: overwriting te2.Edge now; original mark is preserved in m2 /// if (cp.TryGetEdge(m2, &te2.Edge)) cp.emit_TryGetEdge(il, g => il.Emit(OpCodes.Ldloc_3), g => il.Emit(OpCodes.Ldloc_1), g => { il.Emit(OpCodes.Ldarga_S, 3); il.Emit(OpCodes.Ldflda, typeof(TfsEdge).GetField("Edge")); }); il.Emit(OpCodes.Brfalse, l_next_iter); /// cp.TryGetEdge(m1, out ne1); cp.emit_TryGetEdge(il, g => il.Emit(OpCodes.Ldloc_3), g => il.Emit(OpCodes.Ldarg_2), g => { il.Emit(OpCodes.Ldloca_S, 4); il.Emit(OpCodes.Ldflda, typeof(TfsEdge).GetField("Edge")); }); il.Emit(OpCodes.Pop); il.MarkLabel(l_next_iter); } /// return true il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Ret); del_u_destr test = (del_u_destr)dm.CreateDelegate(typeof(del_u_destr), this); bool xt = test(u, m1, te2, fn); Console.WriteLine(xt); #endif //return _emit_u_destr_closure(u, m1, te2, fn); return _u_destr_internal; //return (del_u_destr)dm.CreateDelegate(typeof(del_u_destr), this); } del_u_destr _emit_u_destr_closure(Unification _u, int _m1, TfsEdge _te2, Func<ConstraintPool, int, Edge, TfsEdge, bool> _fn) { #if false //Console.WriteLine("{0} {1}", cfg_ix, rg_fix.Select(ix => ix.ToString()).StringJoin("-")); Tray tr = _u.TargetTray; ConstraintPool[] rgcp = rg_fix.Select(i => tr.Pools[i]).ToArray(); return new del_u_destr((u, m1, te2, fn) => { int m2 = te2.Edge.Mark; ConstraintPool cp; Edge ne1; Edge ge; ////////////////////////////////////////////////// cp = rgcp[0]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (ConstraintPool _cp in rgcp) if (_cp.TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 1) return true; ////////////////////////////////////////////////// cp = rgcp[1]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (ConstraintPool _cp in rgcp) if (_cp.TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 2) return true; ////////////////////////////////////////////////// cp = rgcp[2]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (ConstraintPool _cp in rgcp) if (_cp.TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 3) return true; ////////////////////////////////////////////////// cp = rgcp[3]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (ConstraintPool _cp in rgcp) if (_cp.TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 4) return true; ////////////////////////////////////////////////// cp = rgcp[4]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (ConstraintPool _cp in rgcp) if (_cp.TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 5) return true; ////////////////////////////////////////////////// cp = rgcp[5]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (ConstraintPool _cp in rgcp) if (_cp.TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 6) return true; ////////////////////////////////////////////////// cp = rgcp[6]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (ConstraintPool _cp in rgcp) if (_cp.TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 7) return true; ////////////////////////////////////////////////// cp = rgcp[7]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (ConstraintPool _cp in rgcp) if (_cp.TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 8) return true; ////////////////////////////////////////////////// cp = rgcp[8]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (ConstraintPool _cp in rgcp) if (_cp.TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 9) return true; ////////////////////////////////////////////////// cp = rgcp[9]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (ConstraintPool _cp in rgcp) if (_cp.TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 10) return true; ////////////////////////////////////////////////// cp = rgcp[10]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (ConstraintPool _cp in rgcp) if (_cp.TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 11) return true; ////////////////////////////////////////////////// cp = rgcp[11]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (ConstraintPool _cp in rgcp) if (_cp.TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 12) return true; ////////////////////////////////////////////////// cp = rgcp[12]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (ConstraintPool _cp in rgcp) if (_cp.TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 13) return true; ////////////////////////////////////////////////// cp = rgcp[13]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (ConstraintPool _cp in rgcp) if (_cp.TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } return true; }); #endif return null; } bool _u_destr_internal_empty(Unification u, int m1, TfsEdge te2, Func<ConstraintPool, int, Edge, TfsEdge, bool> fn) { return true; } #if true bool _u_destr_internal(Unification u, int m1, TfsEdge te2, Func<ConstraintPool, int, Edge, TfsEdge, bool> fn) { #if false Tray tr = u.TargetTray; int m2 = te2.Edge.Mark; ConstraintPool[] rgcp = tr.Pools; ConstraintPool cp; Edge ne1; Edge ge; ////////////////////////////////////////////////// cp = rgcp[rg_fix[0]]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (int j in rg_fix) if (rgcp[j].TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 1) return true; ////////////////////////////////////////////////// cp = rgcp[rg_fix[1]]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (int j in rg_fix) if (rgcp[j].TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 2) return true; ////////////////////////////////////////////////// cp = rgcp[rg_fix[2]]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (int j in rg_fix) if (rgcp[j].TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 3) return true; ////////////////////////////////////////////////// cp = rgcp[rg_fix[3]]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (int j in rg_fix) if (rgcp[j].TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 4) return true; ////////////////////////////////////////////////// cp = rgcp[rg_fix[4]]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (int j in rg_fix) if (rgcp[j].TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 5) return true; ////////////////////////////////////////////////// cp = rgcp[rg_fix[5]]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (int j in rg_fix) if (rgcp[j].TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 6) return true; ////////////////////////////////////////////////// cp = rgcp[rg_fix[6]]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (int j in rg_fix) if (rgcp[j].TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 7) return true; ////////////////////////////////////////////////// cp = rgcp[rg_fix[7]]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (int j in rg_fix) if (rgcp[j].TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 8) return true; ////////////////////////////////////////////////// cp = rgcp[rg_fix[8]]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (int j in rg_fix) if (rgcp[j].TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 9) return true; ////////////////////////////////////////////////// cp = rgcp[rg_fix[9]]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (int j in rg_fix) if (rgcp[j].TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 10) return true; ////////////////////////////////////////////////// cp = rgcp[rg_fix[10]]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (int j in rg_fix) if (rgcp[j].TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 11) return true; ////////////////////////////////////////////////// cp = rgcp[rg_fix[11]]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (int j in rg_fix) if (rgcp[j].TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 12) return true; ////////////////////////////////////////////////// cp = rgcp[rg_fix[12]]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (int j in rg_fix) if (rgcp[j].TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } if (rg_fix.Length == 13) return true; ////////////////////////////////////////////////// cp = rgcp[rg_fix[13]]; if (cp.TryGetEdge(m2, out te2.Edge)) { cp.TryGetEdge(m1, out ne1); if (ne1.Mark != te2.Edge.Mark || ne1.FlagsId != te2.Edge.FlagsId) { if (!fn(cp, m1, ne1, te2)) { foreach (int j in rg_fix) if (rgcp[j].TryRemoveEdge(m1, out ge)) tr.RudeTruncate(ge); return false; } } if (m1 != m2 && te2.IsTarget) u._prune_below(cp, m2); } #endif return true; } #endif #endif _int_enumerable ie = null; public IEnumerator<int> GetEnumerator() { ie = ie ?? new _int_enumerable(this); return ie.GetEnumerator(); } IEnumerator System.Collections.IEnumerable.GetEnumerator() { ie = ie ?? new _int_enumerable(this); return ie.GetEnumerator(); } class _int_enumerable : IEnumerable<int> { Func<int>[] rgfn; static Func<int>[] lfn = null; public _int_enumerable(FeatureConfig fc) { if (lfn == null) Interlocked.CompareExchange(ref lfn, new Func<int>[fc.tm.Features.Count], null); this.rgfn = fc.rg_fix.Select(i => { if (i >= lfn.Length || lfn[i] == null) { DynamicMethod dm = new DynamicMethod(String.Empty, typeof(int), null, typeof(_int_enumerable), true); ILGenerator il = dm.GetILGenerator(256); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Ret); lfn[i] = (Func<int>)dm.CreateDelegate(typeof(Func<int>)); } return lfn[i]; }).ToArray(); } public IEnumerator<int> GetEnumerator() { return new _enum(rgfn); } IEnumerator System.Collections.IEnumerable.GetEnumerator() { return new _enum(rgfn); } class _enum : IEnumerator<int> { uint ix = 0xFFFFFFFF; Func<int> cur = null; Func<int>[] rgfn; public _enum(Func<int>[] rgfn) { this.rgfn = rgfn; } public int Current { get { return cur(); } } object IEnumerator.Current { get { return cur(); } } public bool MoveNext() { if (++ix >= rgfn.Length) return false; cur = rgfn[ix]; return true; } public void Reset() { ix = 0xFFFFFFFF; cur = null; } public void Dispose() { } }; }; }; }