OSDN Git Service

ver1.1
[nysol/mining.git] / zdd / lib / SAPPOROBDD / src / BDD+ / CtoI.cc
diff --git a/zdd/lib/SAPPOROBDD/src/BDD+/CtoI.cc b/zdd/lib/SAPPOROBDD/src/BDD+/CtoI.cc
new file mode 100755 (executable)
index 0000000..b7d21fc
--- /dev/null
@@ -0,0 +1,1070 @@
+/******************************************
+ * Combination-to-Integer function class  *
+ * (SAPPORO-1.56) - Body                  *
+ * (C) Shin-ichi MINATO  (June 8, 2013)  *
+ ******************************************/
+
+#include "CtoI.h"
+
+static const char BC_CtoI_MULT = 40;
+static const char BC_CtoI_DIV =  41;
+static const char BC_CtoI_TV =  42;
+static const char BC_CtoI_TVI =  43;
+
+static const char BC_CtoI_RI =  44;
+static const char BC_CtoI_FPA =  45;
+static const char BC_CtoI_FPAV =  46;
+static const char BC_CtoI_FPM =  47;
+static const char BC_CtoI_FPC =  48;
+static const char BC_CtoI_MEET =  49;
+
+//----------- Macros for operation cache -----------
+#define CtoI_CACHE_CHK_RETURN(op, fx, gx) \
+  { ZBDD z = BDD_CacheZBDD(op, fx, gx); \
+    if(z != -1) return CtoI(z); \
+    BDD_RECUR_INC; }
+
+#define CtoI_CACHE_ENT_RETURN(op, fx, gx, h) \
+  { BDD_RECUR_DEC; \
+    if(h != CtoI_Null()) BDD_CacheEnt(op, fx, gx, h._zbdd.GetID()); \
+    return h; }
+
+//-------------- Public Methods -----------
+CtoI::CtoI(int n)
+{
+  if(n == 0) _zbdd = 0;
+  else if(n == 1) _zbdd = 1;
+  else if(n < 0)
+  {
+    if((n = -n) < 0) BDDerr("CtoI::CtoI(): overflow.", n);
+    *this = -CtoI(n);
+  }
+  else
+  {
+    *this = 0;
+    CtoI a = 1;
+    while(n)
+    {
+      if(n & 1) *this += a;
+      a += a;
+      n >>= 1;
+    }
+  }
+}
+
+int CtoI::TopItem() const
+{
+  int v = Top();
+  if(BDD_LevOfVar(v) <= BDD_TopLev()) return v;
+  int v0 = Factor0(v).TopItem();
+  int v1 = Factor1(v).TopItem();
+  return (BDD_LevOfVar(v0) > BDD_LevOfVar(v1))? v0: v1;
+}
+
+int CtoI::TopDigit() const
+{
+  int v = Top();
+  if(BDD_LevOfVar(v) <= BDD_TopLev()) return 0;
+  int d0 = Factor0(v).TopDigit();
+  int d1 = Factor1(v).TopDigit() + (1 << (BDDV_SysVarTop - v));
+  return (d0 > d1)? d0: d1;
+}
+
+CtoI CtoI::FilterThen(const CtoI& a) const
+{
+  if(*this == 0) return 0;
+  if(*this == CtoI_Null()) return CtoI_Null();
+  CtoI aa = a.IsBool()? a: a.NonZero();
+  if(aa == 0) return 0;
+  if(IsBool()) return CtoI_Intsec(*this, aa);
+  int v = Top();
+  return CtoI_Union(Factor0(v).FilterThen(aa),
+                 Factor1(v).FilterThen(aa).AffixVar(v));
+}
+
+CtoI CtoI::FilterElse(const CtoI& a) const
+{
+  if(*this == 0) return 0;
+  if(*this == CtoI_Null()) return CtoI_Null();
+  CtoI aa = a.IsBool()? a: a.NonZero();
+  if(aa == 0) return *this;
+  if(IsBool()) return CtoI_Diff(*this, aa);
+  int v = Top();
+  return CtoI_Union(Factor0(v).FilterElse(aa),
+                 Factor1(v).FilterElse(aa).AffixVar(v));
+}
+
+CtoI CtoI::FilterRestrict(const CtoI& a) const
+{
+  CtoI th = IsBool()? *this: NonZero();
+  CtoI aa = a.IsBool()? a: a.NonZero();
+  return FilterThen(CtoI(th._zbdd.Restrict(aa._zbdd)));
+}
+
+CtoI CtoI::FilterPermit(const CtoI& a) const
+{
+  CtoI th = IsBool()? *this: NonZero();
+  CtoI aa = a.IsBool()? a: a.NonZero();
+  return FilterThen(CtoI(th._zbdd.Permit(aa._zbdd)));
+}
+
+CtoI CtoI::FilterPermitSym(int n) const
+{
+  CtoI th = IsBool()? *this: NonZero();
+  return FilterThen(CtoI(th._zbdd.PermitSym(n)));
+}
+
+CtoI CtoI::NonZero() const
+{
+  if(IsBool()) return *this;
+  int v = Top();
+  return CtoI_Union(Factor0(v).NonZero(), Factor1(v).NonZero());
+}
+
+CtoI CtoI::ConstTerm() const
+{
+  if(IsBool()) return CtoI_Intsec(*this, 1);
+  int v = Top();
+  return CtoI_Union(Factor0(v).ConstTerm(),
+         Factor1(v).ConstTerm().AffixVar(v));
+}
+
+CtoI CtoI::Digit(int index) const
+{
+  if(index < 0) BDDerr("CtoI::Digit(): invalid index.", index);
+  CtoI a = *this;
+  for(int i=0; i<BDDV_SysVarTop; i++)
+  {
+    if(index == 0) break;
+    if(index & 1) a = a.Factor1(BDDV_SysVarTop - i);
+    else a = a.Factor0(BDDV_SysVarTop - i);
+    if(a == CtoI_Null()) break;
+    index >>= 1;
+  }
+  while(! a.IsBool()) a = a.Factor0(a.Top());
+  return a;
+}
+
+CtoI CtoI::EQ_Const(const CtoI& a) const
+{
+  return CtoI_Diff(NonZero(), NE_Const(a));
+}
+
+CtoI CtoI::NE_Const(const CtoI& a) const
+{
+  if(a == 0) return CtoI_NE(*this, 0);
+  return CtoI_NE(*this, a * NonZero());
+}
+
+CtoI CtoI::GT_Const(const CtoI& a) const
+{
+  if(a == 0) return CtoI_GT(*this, 0);
+  return CtoI_GT(*this, a * NonZero());
+}
+
+CtoI CtoI::GE_Const(const CtoI& a) const
+{
+  if(a == 0) return CtoI_GE(*this, 0);
+  return CtoI_GE(*this, a * NonZero());
+}
+
+CtoI CtoI::LT_Const(const CtoI& a) const
+{
+  if(a == 0) return CtoI_GT(0, *this);
+  return CtoI_GT(a * NonZero(), *this);
+}
+
+CtoI CtoI::LE_Const(const CtoI& a) const
+{
+  if(a == 0) return CtoI_GE(0, *this);
+  return CtoI_GE(a * NonZero(), *this);
+}
+
+CtoI CtoI::MaxVal() const
+{
+  if(*this == CtoI_Null()) return 0;
+  CtoI a = *this;
+  CtoI cond = NonZero();
+  CtoI c = 0;
+  while(a != 0)
+  {
+    int td = a.TopDigit();
+    CtoI d = Digit(td);
+    if(td & 1)
+    {
+      CtoI cond0 = CtoI_Diff(cond, d);
+      if(cond0 != 0) cond = cond0;
+      else c = CtoI_Union(c, CtoI(1).ShiftDigit(td));
+    }
+    else
+    {
+      CtoI cond0 = CtoI_Intsec(cond, d);
+      if(cond0 != 0)
+      {
+        cond = cond0;
+       c = CtoI_Union(c, CtoI(1).ShiftDigit(td));
+      }
+    }
+    if(td == 0) break;
+    a = CtoI_Diff(a, d.ShiftDigit(td));
+  }
+  return c;
+}
+
+CtoI CtoI::MinVal() const { return - (- *this).MaxVal(); }
+
+CtoI CtoI::TimesSysVar(int v) const
+{
+  if(v > BDDV_SysVarTop || v <= 0)
+    BDDerr("CtoI::TimesSysVar(): invalid var ID.", v);
+  if(*this == 0) return *this;
+  if(*this == CtoI_Null()) return *this;
+  CtoI a0 = Factor0(v);
+  CtoI a1 = Factor1(v);
+  if(a1 == 0) return a0.AffixVar(v);
+  return CtoI_Union(a0.AffixVar(v), a1.TimesSysVar(v-1));
+}
+
+CtoI CtoI::DivBySysVar(int v) const
+{
+  if(v > BDDV_SysVarTop || v <= 0)
+    BDDerr("CtoI::DivBySysVar(): invalid var ID.", v);
+  if(*this == 0) return *this;
+  if(*this == CtoI_Null()) return *this;
+  CtoI a0 = Factor0(v);
+  CtoI a1 = Factor1(v);
+  if(a0.IsBool()) return a1;
+  return CtoI_Union(a1, a0.AffixVar(v).DivBySysVar(v-1));
+}
+
+CtoI CtoI::ShiftDigit(int pow) const
+{
+  CtoI a = *this;
+  int v = BDDV_SysVarTop;
+  int i = (pow >= 0)? pow: -pow; 
+  while(i)
+  {
+    if(i & 1)
+    {
+      if(pow > 0) a = a.TimesSysVar(v);
+      else a = a.DivBySysVar(v);
+    }
+    i >>= 1;
+    v--;
+  }
+  return a;
+}
+
+bddword CtoI::Size() const { return _zbdd.Size(); }
+
+int CtoI::GetInt() const
+{
+  if(*this == CtoI_Null()) return 0;
+  if(IsBool()) return (CtoI_Intsec(*this, 1)== 0)? 0: 1;
+  int v = Top();
+  CtoI a;
+  if((a=Factor0(v)) == CtoI_Null()) return 0;
+  int n = a.GetInt();
+  if((a=Factor1(v)) == CtoI_Null()) return 0;
+  if(v == BDDV_SysVarTop) return n - (a.GetInt() << 1);
+  return n + (a.GetInt() << (1<< (BDDV_SysVarTop - v)));
+}
+
+int CtoI::StrNum10(char* s) const
+{
+  if(*this == CtoI_Null()) { sprintf(s, "0"); return 1; }
+  if(! IsConst()) return FilterThen(1).StrNum10(s);
+  int td = TopDigit();
+  if(td & 1)
+  {
+    if((- *this).StrNum10(s)) return 1;
+    int len = strlen(s);
+    for(int i=len; i>=0; i--) s[i+1] = s[i];
+    s[0] = '-';
+    return 0;
+  }
+
+  CtoI a = *this;
+  int i=0;
+  char s0[12];
+  if(td >= 20)
+  {
+    const int width = 9;
+    CtoI shift = 1000000000; // 10 ** width 
+    while(1)
+    {
+      CtoI p = a / shift;
+      if(p == 0) break;
+      CtoI q = a - p * shift;
+      if(q == CtoI_Null()) { sprintf(s, "0"); return 1; }
+      sprintf(s0, "%09d", q.GetInt());
+      for(int j=i-1; j>=0; j--) s[j+width] = s[j];
+      for(int j=0; j<width; j++) s[j] = s0[j];
+      i += width;
+      a = p;
+    }
+  }
+  sprintf(s0, "%d", a.GetInt());
+  int len = strlen(s0);
+  for(int j=i-1; j>=0; j--) s[j+len] = s[j];
+  for(int j=0; j<len; j++) s[j] = s0[j];
+  i += len;
+  s[i] = 0;
+  return 0;
+}
+
+int CtoI::StrNum16(char* s) const
+{
+  if(*this == CtoI_Null()) { sprintf(s, "0"); return 1; }
+  if(! IsConst()) return FilterThen(1).StrNum16(s);
+  int td = TopDigit();
+  if(td & 1)
+  {
+    if((- *this).StrNum16(s)) return 1;
+    int len = strlen(s);
+    for(int i=len; i>=0; i--) s[i+1] = s[i];
+    s[0] = '-';
+    return 0;
+  }
+
+  CtoI a = *this;
+  int i=0;
+  char s0[12];
+  if(td >= 20)
+  {
+    const int width = 6;
+    CtoI shift = 0x1000000; // 0x10 ** width 
+    while(1)
+    {
+      CtoI p = a / shift;
+      if(p == 0) break;
+      CtoI q = a - p * shift;
+      if(q == CtoI_Null()) { sprintf(s, "0"); return 1; }
+      sprintf(s0, "%06X", q.GetInt());
+      for(int j=i-1; j>=0; j--) s[j+width] = s[j];
+      for(int j=0; j<width; j++) s[j] = s0[j];
+      i += width;
+      a = p;
+    }
+  }
+  sprintf(s0, "%X", a.GetInt());
+  int len = strlen(s0);
+  for(int j=i-1; j>=0; j--) s[j+len] = s[j];
+  for(int j=0; j<len; j++) s[j] = s0[j];
+  i += len;
+  s[i] = 0;
+  return 0;
+}
+
+static int Depth;
+static int* S_Var;
+static int PFflag;
+static int PF(CtoI);
+static int PF(CtoI a)
+{
+  if(a.IsConst())
+  {
+    if(a.TopDigit() & 1) { cout << " -"; a = -a; }
+    else if(PFflag == 1) cout << " +";
+
+    PFflag = 1;
+    int c1 = (a != 1);
+    if(c1 || Depth == 0)
+    {
+      char s[80];
+      a.StrNum10(s);
+      cout << " " << s;
+    }
+    for(int i=0; i<Depth; i++) cout << " v" << S_Var[i];
+    cout.flush();
+    return 0;
+  }
+
+  int v = a.TopItem();
+  CtoI b = a.Factor1(v);
+  if(b == CtoI_Null()) return 1;
+  S_Var[Depth] = v;
+  Depth++;
+  if(PF(b) == 1) return 1;
+
+  Depth--;
+  b = a.Factor0(v);
+  if(b == 0) return 0;
+  if(b == CtoI_Null()) return 1;
+  return PF(b);
+}
+
+int CtoI::PutForm() const
+{
+  if(*this == CtoI_Null()) return 1;
+  
+  if(*this == 0) cout << " 0";
+  else
+  {
+    int v = TopItem();
+    Depth = 0;
+    S_Var = new int[v];
+    PFflag = 0;
+    int err = PF(*this);
+    delete[] S_Var;
+    if(err == 1)
+    {
+      cout << "...\n";
+      cout.flush();
+      return 1;
+    }
+  }
+  cout << "\n";
+  cout.flush();
+  return 0;
+}
+
+void CtoI::Print() const { _zbdd.Print(); }
+
+CtoI CtoI::CountTerms() const
+{
+  if(IsBool()) return TotalVal();
+  return NonZero().TotalVal();
+}
+
+CtoI CtoI::TotalVal() const
+{
+  if(*this == CtoI_Null()) return *this;
+  int top = Top();
+  if(top == 0) return *this;
+
+  bddword x = _zbdd.GetID();
+  CtoI_CACHE_CHK_RETURN(BC_CtoI_TV, x, 0);
+
+  CtoI c = Factor0(top).TotalVal();
+  if(c != CtoI_Null())
+  {
+    if(IsBool())
+      c += Factor1(top).TotalVal();
+    else
+      c += Factor1(top).TotalVal().ShiftDigit(1<<(BDDV_SysVarTop - top));
+  }
+
+  CtoI_CACHE_ENT_RETURN(BC_CtoI_TV, x, 0, c);
+}
+
+CtoI CtoI::TotalValItems() const
+{
+  if(*this == CtoI_Null()) return *this;
+  int top = Top();
+  if(top == 0) return CtoI(0);
+
+  bddword x = _zbdd.GetID();
+  CtoI_CACHE_CHK_RETURN(BC_CtoI_TVI, x, 0);
+
+  CtoI c = Factor0(top).TotalValItems();
+  if(c != CtoI_Null())
+  {
+    CtoI a1 = Factor1(top);
+    if(IsBool())
+      c += a1.TotalValItems() + a1.TotalVal().AffixVar(top);
+    else
+      c += a1.TotalValItems().ShiftDigit(1<<(BDDV_SysVarTop - top));
+  }
+
+  CtoI_CACHE_ENT_RETURN(BC_CtoI_TVI, x, 0, c);
+}
+
+CtoI CtoI::ReduceItems(const CtoI& b) const
+{
+  if(*this == CtoI_Null()) return *this;
+  if(b == CtoI_Null()) return b;
+  if(! b.IsBool()) return ReduceItems(b.NonZero());
+  int atop = Top();
+  int btop = b.Top();
+  int top = (BDD_LevOfVar(atop) > BDD_LevOfVar(btop))? atop: btop;
+  if(top == 0) return *this;
+
+  bddword ax = _zbdd.GetID();
+  bddword bx = b._zbdd.GetID();
+  CtoI_CACHE_CHK_RETURN(BC_CtoI_RI, ax, bx);
+
+  CtoI c = CtoI(0);
+  if(BDD_LevOfVar(btop) > BDD_LevOfVar(atop))
+    c = ReduceItems(b.Factor0(btop));
+  else if(!IsBool())
+    c = Factor0(atop).ReduceItems(b)
+      + Factor1(atop).ReduceItems(b).ShiftDigit(1<<(BDDV_SysVarTop - atop));
+  else if(BDD_LevOfVar(btop) == BDD_LevOfVar(atop))
+    c = Factor0(atop).ReduceItems(b) + Factor1(atop).ReduceItems(b);
+  else
+  {
+    c = Factor0(atop).ReduceItems(b.Factor0(atop))
+      + Factor1(atop).ReduceItems(b.Factor0(atop)).AffixVar(atop);
+  }
+
+  CtoI_CACHE_ENT_RETURN(BC_CtoI_RI, ax, bx, c);
+}
+
+CtoI CtoI::FreqPatA(int Val) const
+{
+  if(*this == CtoI_Null()) return *this;
+  if(IsConst()) return (GetInt() >= Val)? CtoI(1): CtoI(0);
+
+  int ax = _zbdd.GetID();
+  CtoI_CACHE_CHK_RETURN(BC_CtoI_FPA, ax, Val);
+
+  int top = TopItem();
+  CtoI f1 = Factor1(top);
+
+  CtoI f = f1;
+  int tv = 1 << f.TopDigit();
+  CtoI f2 = f1;
+  if(tv -(tv>>1) < Val)
+  {
+    tv = 0;
+    while(f != CtoI(0))
+    {
+      int d = f.TopDigit();
+      CtoI fd = f.Digit(d);
+      if(d & 1)
+      {
+        tv -= fd.GetZBDD().Card() << d;
+        if(tv >= Val) break;
+      }
+      else
+      {
+        tv += fd.GetZBDD().Card() << d;
+        if((tv>>1) >= Val) break;
+      }
+      f -= fd.ShiftDigit(d);
+    }
+    if(tv < Val) f2 = CtoI(0);
+  }
+
+  CtoI h1 = f2.FreqPatA(Val);
+  CtoI h = CtoI_Union(h1, h1.AffixVar(top));
+  CtoI f0 = Factor0(top);
+  if(f0 != CtoI(0))
+  {
+    //CtoI f1v = f1.GE_Const(CtoI(Val));
+    f0 = f0.FilterElse(h1);
+    if(f0 != CtoI(0))
+    {
+      f1 = f1.FilterElse(h1);
+      h = CtoI_Union(h, (f0 + f1).FreqPatA(Val));
+    }
+  }
+
+  CtoI_CACHE_ENT_RETURN(BC_CtoI_FPA, ax, Val, h);
+}
+
+CtoI CtoI::FreqPatA2(int Val) const
+{
+  if(*this == CtoI_Null()) return *this;
+  if(IsConst()) return (GetInt() >= Val)? CtoI(1): CtoI(0);
+
+  int ax = _zbdd.GetID();
+  CtoI_CACHE_CHK_RETURN(BC_CtoI_FPA, ax, Val);
+
+  int top = TopItem();
+  CtoI f1 = Factor1(top);
+
+  CtoI f = f1;
+  int tv = 1 << f.TopDigit();
+  CtoI f2 = f1;
+  if(tv -(tv>>1) < Val)
+  {
+    tv = 0;
+    while(f != CtoI(0))
+    {
+      int d = f.TopDigit();
+      CtoI fd = f.Digit(d);
+      if(d & 1)
+      {
+        tv -= fd.GetZBDD().Card() << d;
+        if(tv >= Val) break;
+      }
+      else
+      {
+        tv += fd.GetZBDD().Card() << d;
+        if((tv>>1) >= Val) break;
+      }
+      f -= fd.ShiftDigit(d);
+    }
+    if(tv < Val) f2 = CtoI(0);
+  }
+
+  int sz = f2.Size();
+  CtoI s = f2.TotalValItems().LT_Const(CtoI(Val));
+  f2 = f2.ReduceItems(s);
+  cout << (float) (sz - f2.Size())/sz << " ";
+  cout.flush();
+
+  CtoI h1 = f2.FreqPatA2(Val);
+  CtoI h = CtoI_Union(h1, h1.AffixVar(top));
+  CtoI f0 = Factor0(top);
+  if(f0 != CtoI(0))
+  {
+    //CtoI f1v = f1.GE_Const(CtoI(Val));
+    f0 = f0.FilterElse(h1);
+    if(f0 != CtoI(0))
+    {
+      f1 = f1.FilterElse(h1);
+      h = CtoI_Union(h, (f0 + f1).FreqPatA2(Val));
+    }
+  }
+
+  CtoI_CACHE_ENT_RETURN(BC_CtoI_FPA, ax, Val, h);
+}
+
+CtoI CtoI::FreqPatAV(int Val) const
+{
+  if(*this == CtoI_Null()) return *this;
+  if(IsConst()) return (GetInt() >= Val)? *this: CtoI(0);
+
+  int ax = _zbdd.GetID();
+  CtoI_CACHE_CHK_RETURN(BC_CtoI_FPAV, ax, Val);
+
+  int top = TopItem();
+  CtoI f1 = Factor1(top);
+
+  CtoI f = f1;
+  int tv = 1 << f.TopDigit();
+  CtoI f2 = f1;
+  if(tv -(tv>>1) < Val)
+  {
+    tv = 0;
+    while(f != CtoI(0))
+    {
+      int d = f.TopDigit();
+      CtoI fd = f.Digit(d);
+      if(d & 1)
+      {
+        tv -= fd.GetZBDD().Card() << d;
+        if(tv >= Val) break;
+      }
+      else
+      {
+        tv += fd.GetZBDD().Card() << d;
+        if((tv>>1) >= Val) break;
+      }
+      f -= fd.ShiftDigit(d);
+    }
+    if(tv < Val) f2 = CtoI(0);
+  }
+
+  CtoI h1 = f2.FreqPatAV(Val);
+  CtoI h = h1.AffixVar(top);
+
+  CtoI f0 = Factor0(top);
+  if(f0 == CtoI(0)) h = CtoI_Union(h, h1);
+  else h = CtoI_Union(h, (f0 + f1).FreqPatAV(Val));
+
+  CtoI_CACHE_ENT_RETURN(BC_CtoI_FPAV, ax, Val, h);
+}
+
+CtoI CtoI::FreqPatM(int Val) const
+{
+  if(*this == CtoI_Null()) return *this;
+  if(IsConst()) return (GetInt() >= Val)? CtoI(1): CtoI(0);
+
+  int ax = _zbdd.GetID();
+  CtoI_CACHE_CHK_RETURN(BC_CtoI_FPM, ax, Val);
+
+  int top = TopItem();
+  CtoI f1 = Factor1(top);
+
+  CtoI f = f1;
+  int tv = 1 << f.TopDigit();
+  CtoI f2 = f1;
+  if(tv -(tv>>1) < Val)
+  {
+    tv = 0;
+    while(f != CtoI(0))
+    {
+      int d = f.TopDigit();
+      CtoI fd = f.Digit(d);
+      if(d & 1)
+      {
+        tv -= fd.GetZBDD().Card() << d;
+        if(tv >= Val) break;
+      }
+      else
+      {
+        tv += fd.GetZBDD().Card() << d;
+        if((tv>>1) >= Val) break;
+      }
+      f -= fd.ShiftDigit(d);
+    }
+    if(tv < Val) f2 = CtoI(0);
+  }
+
+  CtoI h1 = f2.FreqPatM(Val);
+  CtoI h = h1.AffixVar(top);
+  CtoI f0 = Factor0(top);
+  if(f0 != CtoI(0))
+  {
+    f0 = CtoI_Diff(f0, f0.FilterPermit(h1));
+    if(f0 != CtoI(0))
+    {
+      f1 = CtoI_Diff(f1, f1.FilterPermit(h1));
+      f2 = (f0 + f1).FreqPatM(Val);
+      h = CtoI_Union(h, CtoI_Diff(f2, f2.FilterPermit(h1)));
+    }
+  }
+
+  CtoI_CACHE_ENT_RETURN(BC_CtoI_FPM, ax, Val, h);
+}
+
+CtoI CtoI::FreqPatC(int Val) const
+{
+  if(*this == CtoI_Null()) return *this;
+  if(IsConst()) return (GetInt() >= Val)? CtoI(1): CtoI(0);
+
+  int ax = _zbdd.GetID();
+  CtoI_CACHE_CHK_RETURN(BC_CtoI_FPC, ax, Val);
+
+  int top = TopItem();
+  CtoI f1 = Factor1(top);
+
+  CtoI f = f1;
+  int tv = 1 << f.TopDigit();
+  CtoI f2 = f1;
+  if(tv -(tv>>1) < Val)
+  {
+    tv = 0;
+    while(f != CtoI(0))
+    {
+      int d = f.TopDigit();
+      CtoI fd = f.Digit(d);
+      if(d & 1)
+      {
+        tv -= fd.GetZBDD().Card() << d;
+        if(tv >= Val) break;
+      }
+      else
+      {
+        tv += fd.GetZBDD().Card() << d;
+        if((tv>>1) >= Val) break;
+      }
+      f -= fd.ShiftDigit(d);
+    }
+    if(tv < Val) f2 = CtoI(0);
+  }
+
+  CtoI h1 = f2.FreqPatC(Val);
+  CtoI h = h1.AffixVar(top);
+  CtoI f0 = Factor0(top);
+  if(f0 != CtoI(0))
+  {
+    h1 -= h1.FilterPermit(f0);
+    h = CtoI_Union(h, (f0 + f1).FreqPatC(Val).FilterElse(h1));
+  }
+
+  CtoI_CACHE_ENT_RETURN(BC_CtoI_FPC, ax, Val, h);
+}
+
+//----------- External functions -----------
+
+CtoI operator+(const CtoI& a, const CtoI& b)
+{
+  CtoI c = CtoI_Intsec(a, b);
+  CtoI s = CtoI_Diff(CtoI_Union(a, b), c);
+  if(c == 0) return s;
+  if(s == CtoI_Null()) return s;
+  BDD_RECUR_INC;
+  CtoI h = s - c.ShiftDigit(1);
+  BDD_RECUR_DEC;
+  return h;
+}
+
+CtoI operator-(const CtoI& a, const CtoI& b)
+{
+  CtoI c = CtoI_Diff(b, a);
+  CtoI s = CtoI_Union(CtoI_Diff(a, b), c);
+  if(c == 0) return s;
+  if(s == CtoI_Null()) return s;
+  BDD_RECUR_INC;
+  CtoI h = s + c.ShiftDigit(1);
+  BDD_RECUR_DEC;
+  return h;
+}
+
+CtoI operator *(const CtoI& ac, const CtoI& bc)
+{
+  if(ac == 1) return bc;
+  if(bc == 1) return ac;
+  if(ac == CtoI_Null()) return ac;
+  if(bc == CtoI_Null()) return bc;
+  if(ac == 0) return 0;
+  if(bc == 0) return 0;
+
+  CtoI a = ac; CtoI b = bc;
+  int atop = a.Top(); int btop = b.Top();
+  if(BDD_LevOfVar(atop) < BDD_LevOfVar(btop))
+  {
+    a = bc; b = ac;
+    atop = a.Top(); btop = b.Top();
+  }
+
+  bddword ax = a._zbdd.GetID();
+  bddword bx = b._zbdd.GetID();
+  if(atop == btop && ax < bx)
+  {
+    a = bc; b = ac;
+    ax = a._zbdd.GetID(); bx = b._zbdd.GetID();
+  }
+
+  CtoI_CACHE_CHK_RETURN(BC_CtoI_MULT, ax, bx);
+
+  CtoI a0 = a.Factor0(atop);
+  CtoI a1 = a.Factor1(atop);
+  CtoI c;
+  if(atop != btop)
+  {
+    if(BDD_LevOfVar(atop) <= BDD_TopLev())
+      c = CtoI_Union(a0*b, (a1*b).AffixVar(atop));
+    else c = a0*b + (a1*b).TimesSysVar(atop);
+  }
+  else
+  {
+    CtoI b0 = b.Factor0(atop);
+    CtoI b1 = b.Factor1(atop);
+    if(BDD_LevOfVar(atop) <= BDD_TopLev())
+      c = CtoI_Union(a0*b0, (a1*b0 + a0*b1 + a1*b1).AffixVar(atop));
+    else if(atop > 1)
+      c = a0*b0 + (a1*b0 + a0*b1).TimesSysVar(atop)
+        + (a1*b1).TimesSysVar(atop - 1);
+    else BDDerr("CtoI::operator*(): SysVar overflow.");
+  }
+
+  CtoI_CACHE_ENT_RETURN(BC_CtoI_MULT, ax, bx, c);
+}
+
+CtoI operator /(const CtoI& ac, const CtoI& bc)
+{
+  if(ac == CtoI_Null()) return ac;
+  if(bc == CtoI_Null()) return bc;
+  if(ac == 0) return 0;
+  if(ac == bc) return 1;
+  if(bc == 0) BDDerr("CtoI::operator/(): Divide by zero.");
+
+  CtoI a = ac; CtoI b = bc;
+  bddword ax = a._zbdd.GetID();
+  bddword bx = b._zbdd.GetID();
+  CtoI_CACHE_CHK_RETURN(BC_CtoI_DIV, ax, bx);
+
+  int v = b.TopItem();
+  CtoI c;
+  if(v == 0)
+  {
+    if(b.TopDigit() & 1) { a = -a; b = -b; }
+    if(b == 1) return a;
+    CtoI p = a.FilterThen(CtoI_GT(a, 0));
+    if(a != p) c = (p / b) - ((p - a)/ b);
+    else
+    {
+      int atd = a.TopDigit();
+      int btd = b.TopDigit();
+      if(atd < btd) return 0;
+      c = a.Digit(atd);
+      if(atd > btd) c = c.ShiftDigit(atd - btd - 2);
+      else
+      {
+        CtoI cond = CtoI_GE(a, c * b);
+        a = a.FilterThen(cond);
+        c = c.FilterThen(cond); 
+      }
+      c += (a - c * b)/ b;
+    }
+  }
+  else
+  {
+    CtoI a0 = a.Factor0(v);
+    CtoI a1 = a.Factor1(v);
+    CtoI b0 = b.Factor0(v);
+    CtoI b1 = b.Factor1(v);
+  
+    c = a1 / b1;
+    if(c != 0)
+      if(b0 != 0)
+      {
+        CtoI c0 = a0 / b0;
+        c = CtoI_ITE(CtoI_LT(c.Abs(), c0.Abs()), c, c0);
+      }
+  }
+  
+  CtoI_CACHE_ENT_RETURN(BC_CtoI_DIV, ax, bx, c);
+}
+
+CtoI CtoI_GT(const CtoI& ac, const CtoI& bc)
+{
+  CtoI a = ac; CtoI b = bc;
+  CtoI open = CtoI_Union(a, b).NonZero();
+  CtoI awin = 0;
+  CtoI bwin = 0;
+  CtoI awin0, bwin0;
+
+  while(open != 0)
+  {
+    int atd = a.TopDigit();
+    int btd = b.TopDigit();
+    int td = (atd > btd)? atd: btd;
+    CtoI aa = a.Digit(td);
+    CtoI bb = b.Digit(td);
+    if(td & 1)
+    {
+      awin0 = CtoI_Diff(bb, aa);
+      bwin0 = CtoI_Diff(aa, bb);
+    }
+    else
+    {
+      awin0 = CtoI_Diff(aa, bb);
+      bwin0 = CtoI_Diff(bb, aa);
+    }
+    awin = CtoI_Union(awin, awin0);
+    open = CtoI_Diff(open, awin0);
+    bwin = CtoI_Union(bwin, bwin0);
+    open = CtoI_Diff(open, bwin0);
+    if(open == CtoI_Null()) return CtoI_Null();
+    if(td == 0) break;
+    a = CtoI_Diff(a, aa.ShiftDigit(td)).FilterThen(open);
+    b = CtoI_Diff(b, bb.ShiftDigit(td)).FilterThen(open);
+  }
+  return awin;
+}
+
+CtoI CtoI_GE(const CtoI& ac, const CtoI& bc)
+{
+  CtoI a = ac; CtoI b = bc;
+  CtoI open = CtoI_Union(a, b).NonZero();
+  CtoI awin = 0;
+  CtoI bwin = 0;
+  CtoI awin0, bwin0;
+
+  while(open != 0)
+  {
+    int atd = a.TopDigit();
+    int btd = b.TopDigit();
+    int td = (atd > btd)? atd: btd;
+    CtoI aa = a.Digit(td);
+    CtoI bb = b.Digit(td);
+    if(td & 1)
+    {
+      awin0 = CtoI_Diff(bb, aa);
+      bwin0 = CtoI_Diff(aa, bb);
+    }
+    else
+    {
+      awin0 = CtoI_Diff(aa, bb);
+      bwin0 = CtoI_Diff(bb, aa);
+    }
+    awin = CtoI_Union(awin, awin0);
+    open = CtoI_Diff(open, awin0);
+    bwin = CtoI_Union(bwin, bwin0);
+    open = CtoI_Diff(open, bwin0);
+    if(open == CtoI_Null()) return CtoI_Null();
+    if(td == 0) break;
+    a = CtoI_Diff(a, aa.ShiftDigit(td)).FilterThen(open);
+    b = CtoI_Diff(b, bb.ShiftDigit(td)).FilterThen(open);
+  }
+  return CtoI_Union(awin, open);
+}
+
+static CtoI atoiX(char *, int, int);
+static CtoI atoiX(char* s, int base, int blk)
+{
+  int times = 1;
+  for(int i=0; i<blk; i++) times *= base;
+  CtoI shift = times;
+  int p = 0;
+  int len = strlen(s);
+  char *s0 = new char[blk + 1];
+  CtoI a = 0;
+  while(len - p > blk)
+  {
+    a *= shift;
+    strncpy(s0, s+p, blk);
+    a += CtoI((int)strtol(s0, 0, base));
+    p += blk;
+  }
+  if(len > blk)
+  {
+    times = 1;
+    for(int i=p; i<len; i++) times *= base;
+    a *= CtoI(times);
+  }
+  strncpy(s0, s+p, blk);
+  a += CtoI((int)strtol(s0, 0, base));
+  delete[] s0;
+  return a;
+}
+       
+CtoI CtoI_atoi(char* s)
+{
+  if(s[0] == '0')
+  {
+    switch(s[1])
+    {
+    case 'x':
+    case 'X':
+      return atoiX(s+2, 16, 7);
+    case 'b':
+    case 'B':
+      return atoiX(s+2, 2, 30);
+    default:
+      ;
+    }
+  }
+  return atoiX(s, 10, 7);
+}
+
+CtoI CtoI_Meet(const CtoI& ac, const CtoI& bc)
+{
+  if(ac == CtoI_Null()) return ac;
+  if(bc == CtoI_Null()) return bc;
+  if(ac == 0) return 0;
+  if(bc == 0) return 0;
+  if(ac == 1 && bc == 1) return 1;
+
+  CtoI a = ac; CtoI b = bc;
+  int atop = ac.Top(); int btop = bc.Top();
+  if(BDD_LevOfVar(atop) < BDD_LevOfVar(btop))
+  {
+    a = bc; b = ac;
+    atop = a.Top(); btop = b.Top();
+  }
+
+  bddword ax = a._zbdd.GetID();
+  bddword bx = b._zbdd.GetID();
+  if(atop == btop && ax < bx)
+  {
+    a = bc; b = ac;
+    ax = a._zbdd.GetID(); bx = b._zbdd.GetID();
+  }
+
+  CtoI_CACHE_CHK_RETURN(BC_CtoI_MEET, ax, bx);
+
+  CtoI a0 = a.Factor0(atop);
+  CtoI a1 = a.Factor1(atop);
+  CtoI c;
+  if(atop != btop)
+  {
+    if(a.IsBool())
+      c = CtoI_Meet(a0, b) + CtoI_Meet(a1, b);
+    else c = CtoI_Meet(a0, b) + CtoI_Meet(a1, b).TimesSysVar(atop);
+  }
+  else
+  {
+    CtoI b0 = b.Factor0(atop);
+    CtoI b1 = b.Factor1(atop);
+    if(a.IsBool())
+      c = CtoI_Union(
+            CtoI_Meet(a0, b0) + CtoI_Meet(a1, b0) + CtoI_Meet(a0, b1), 
+           CtoI_Meet(a1, b1).AffixVar(atop));
+    else if(atop > 1)
+      c = CtoI_Meet(a0, b0)
+        + (CtoI_Meet(a1, b0) + CtoI_Meet(a0, b1)).TimesSysVar(atop)
+        + CtoI_Meet(a1, b1).TimesSysVar(atop - 1);
+    else BDDerr("CtoI_Meet(): SysVar overflow.");
+  }
+
+  CtoI_CACHE_ENT_RETURN(BC_CtoI_MEET, ax, bx, c);
+}
+