//#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() { }
};
};
};
}