⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 integer.cc

📁 Gambit 是一个游戏库理论软件
💻 CC
📖 第 1 页 / 共 5 页
字号:
  else if (xl == 0)    r = Ialloc(r, y->s, yl, ysgn, yl);  else if (xsgn == ysgn)  {    if (xrsame || yrsame)      r = Iresize(r, calc_len(xl, yl, 1));    else      r = Icalloc(r, calc_len(xl, yl, 1));    r->sgn = xsgn;    unsigned short* rs = r->s;    const unsigned short* as;    const unsigned short* bs;    const unsigned short* topa;    const unsigned short* topb;    if (xl >= yl)    {      as =  (xrsame)? r->s : x->s;      topa = &(as[xl]);      bs =  (yrsame)? r->s : y->s;      topb = &(bs[yl]);    }    else    {      bs =  (xrsame)? r->s : x->s;      topb = &(bs[xl]);      as =  (yrsame)? r->s : y->s;      topa = &(as[yl]);    }    unsigned long sum = 0;    while (bs < topb)    {      sum += (unsigned long)(*as++) + (unsigned long)(*bs++);      *rs++ = extract(sum);      sum = down(sum);    }    while (sum != 0 && as < topa)    {      sum += (unsigned long)(*as++);      *rs++ = extract(sum);      sum = down(sum);    }    if (sum != 0)      *rs = extract(sum);    else if (rs != as)      while (as < topa)        *rs++ = *as++;  }  else  {    int comp = ucompare(x, y);    if (comp == 0)      r = Icopy_zero(r);    else    {      if (xrsame || yrsame)        r = Iresize(r, calc_len(xl, yl, 0));      else        r = Icalloc(r, calc_len(xl, yl, 0));      unsigned short* rs = r->s;      const unsigned short* as;      const unsigned short* bs;      const unsigned short* topa;      const unsigned short* topb;      if (comp > 0)      {        as =  (xrsame)? r->s : x->s;        topa = &(as[xl]);        bs =  (yrsame)? r->s : y->s;        topb = &(bs[yl]);        r->sgn = xsgn;      }      else      {        bs =  (xrsame)? r->s : x->s;        topb = &(bs[xl]);        as =  (yrsame)? r->s : y->s;        topa = &(as[yl]);        r->sgn = ysgn;      }      unsigned long hi = 1;      while (bs < topb)      {        hi += (unsigned long)(*as++) + I_MAXNUM - (unsigned long)(*bs++);        *rs++ = extract(hi);        hi = down(hi);      }      while (hi == 0 && as < topa)      {        hi = (unsigned long)(*as++) + I_MAXNUM;        *rs++ = extract(hi);        hi = down(hi);      }      if (rs != as)        while (as < topa)          *rs++ = *as++;    }  }  Icheck(r);  return r;}IntRep* add(const IntRep* x, int negatex, long y, IntRep* r){  nonnil(x);  int xl = x->len;  int xsgn = (negatex && xl != 0) ? !x->sgn : x->sgn;  int xrsame = x == r;  int ysgn = (y >= 0);  unsigned long uy = (ysgn)? y : -y;  if (y == 0)    r = Ialloc(r, x->s, xl, xsgn, xl);  else if (xl == 0)    r = Icopy_long(r, y);  else if (xsgn == ysgn)  {    if (xrsame)      r = Iresize(r, calc_len(xl, SHORT_PER_LONG, 1));    else      r = Icalloc(r, calc_len(xl, SHORT_PER_LONG, 1));    r->sgn = xsgn;    unsigned short* rs = r->s;    const unsigned short* as =  (xrsame)? r->s : x->s;    const unsigned short* topa = &(as[xl]);    unsigned long sum = 0;    while (as < topa && uy != 0)    {      unsigned long u = extract(uy);      uy = down(uy);      sum += (unsigned long)(*as++) + u;      *rs++ = extract(sum);      sum = down(sum);    }    while (sum != 0 && as < topa)    {      sum += (unsigned long)(*as++);      *rs++ = extract(sum);      sum = down(sum);    }    if (sum != 0)      *rs = extract(sum);    else if (rs != as)      while (as < topa)        *rs++ = *as++;  }  else  {    unsigned short tmp[SHORT_PER_LONG];    int yl = 0;    while (uy != 0)    {      tmp[yl++] = extract(uy);      uy = down(uy);    }    int comp = xl - yl;    if (comp == 0)      comp = docmp(x->s, tmp, yl);    if (comp == 0)      r = Icopy_zero(r);    else    {      if (xrsame)        r = Iresize(r, calc_len(xl, yl, 0));      else        r = Icalloc(r, calc_len(xl, yl, 0));      unsigned short* rs = r->s;      const unsigned short* as;      const unsigned short* bs;      const unsigned short* topa;      const unsigned short* topb;      if (comp > 0)      {        as =  (xrsame)? r->s : x->s;        topa = &(as[xl]);        bs =  tmp;        topb = &(bs[yl]);        r->sgn = xsgn;      }      else      {        bs =  (xrsame)? r->s : x->s;        topb = &(bs[xl]);        as =  tmp;        topa = &(as[yl]);        r->sgn = ysgn;      }      unsigned long hi = 1;      while (bs < topb)      {        hi += (unsigned long)(*as++) + I_MAXNUM - (unsigned long)(*bs++);        *rs++ = extract(hi);        hi = down(hi);      }      while (hi == 0 && as < topa)      {        hi = (unsigned long)(*as++) + I_MAXNUM;        *rs++ = extract(hi);        hi = down(hi);      }      if (rs != as)        while (as < topa)          *rs++ = *as++;    }  }  Icheck(r);  return r;}IntRep* multiply(const IntRep* x, const IntRep* y, IntRep* r){  nonnil(x);  nonnil(y);  int xl = x->len;  int yl = y->len;  int rl = xl + yl;  int rsgn = x->sgn == y->sgn;  int xrsame = x == r;  int yrsame = y == r;  int xysame = x == y;    if (xl == 0 || yl == 0)    r = Icopy_zero(r);  else if (xl == 1 && x->s[0] == 1)    r = Icopy(r, y);  else if (yl == 1 && y->s[0] == 1)    r = Icopy(r, x);  else if (!(xysame && xrsame))  {    if (xrsame || yrsame)      r = Iresize(r, rl);    else      r = Icalloc(r, rl);    unsigned short* rs = r->s;    unsigned short* topr = &(rs[rl]);    // use best inner/outer loop params given constraints    unsigned short* currentr;    const unsigned short* bota;    const unsigned short* as;    const unsigned short* botb;    const unsigned short* topb;    if (xrsame)                     {       currentr = &(rs[xl-1]);      bota = rs;      as = currentr;      botb = y->s;      topb = &(botb[yl]);    }    else if (yrsame)    {      currentr = &(rs[yl-1]);      bota = rs;      as = currentr;      botb = x->s;      topb = &(botb[xl]);    }    else if (xl <= yl)    {      currentr = &(rs[xl-1]);      bota = x->s;      as = &(bota[xl-1]);      botb = y->s;      topb = &(botb[yl]);    }    else    {      currentr = &(rs[yl-1]);      bota = y->s;      as = &(bota[yl-1]);      botb = x->s;      topb = &(botb[xl]);    }    while (as >= bota)    {      unsigned long ai = (unsigned long)(*as--);      unsigned short* rs = currentr--;      *rs = 0;      if (ai != 0)      {        unsigned long sum = 0;        const unsigned short* bs = botb;        while (bs < topb)        {          sum += ai * (unsigned long)(*bs++) + (unsigned long)(*rs);          *rs++ = extract(sum);          sum = down(sum);        }        while (sum != 0 && rs < topr)        {          sum += (unsigned long)(*rs);          *rs++ = extract(sum);          sum = down(sum);        }      }    }  }  else                          // x, y, and r same; compute over diagonals  {    r = Iresize(r, rl);    unsigned short* botr = r->s;    unsigned short* topr = &(botr[rl]);    unsigned short* rs =   &(botr[rl - 2]);    const unsigned short* bota = (xrsame)? botr : x->s;    const unsigned short* loa =  &(bota[xl - 1]);    const unsigned short* hia =  loa;    for (; rs >= botr; --rs)    {      const unsigned short* h = hia;      const unsigned short* l = loa;      unsigned long prod = (unsigned long)(*h) * (unsigned long)(*l);      *rs = 0;      for(;;)      {        unsigned short* rt = rs;        unsigned long sum = prod + (unsigned long)(*rt);        *rt++ = extract(sum);        sum = down(sum);        while (sum != 0 && rt < topr)        {          sum += (unsigned long)(*rt);          *rt++ = extract(sum);          sum = down(sum);        }        if (h > l)        {          rt = rs;          sum = prod + (unsigned long)(*rt);          *rt++ = extract(sum);          sum = down(sum);          while (sum != 0 && rt < topr)          {            sum += (unsigned long)(*rt);            *rt++ = extract(sum);            sum = down(sum);          }          if (--h >= ++l)            prod = (unsigned long)(*h) * (unsigned long)(*l);          else            break;        }        else          break;      }      if (loa > bota)        --loa;      else        --hia;    }  }  r->sgn = rsgn;  Icheck(r);  return r;}IntRep* multiply(const IntRep* x, long y, IntRep* r){  nonnil(x);  int xl = x->len;      if (xl == 0 || y == 0)    r = Icopy_zero(r);  else if (y == 1)    r = Icopy(r, x);  else  {    int ysgn = y >= 0;    int rsgn = x->sgn == ysgn;    unsigned long uy = (ysgn)? y : -y;    unsigned short tmp[SHORT_PER_LONG];    int yl = 0;    while (uy != 0)    {      tmp[yl++] = extract(uy);      uy = down(uy);    }    int rl = xl + yl;    int xrsame = x == r;    if (xrsame)      r = Iresize(r, rl);    else      r = Icalloc(r, rl);    unsigned short* rs = r->s;    unsigned short* topr = &(rs[rl]);    unsigned short* currentr;    const unsigned short* bota;    const unsigned short* as;    const unsigned short* botb;    const unsigned short* topb;    if (xrsame)    {       currentr = &(rs[xl-1]);      bota = rs;      as = currentr;      botb = tmp;      topb = &(botb[yl]);    }    else if (xl <= yl)    {      currentr = &(rs[xl-1]);      bota = x->s;      as = &(bota[xl-1]);      botb = tmp;      topb = &(botb[yl]);    }    else    {      currentr = &(rs[yl-1]);      bota = tmp;      as = &(bota[yl-1]);      botb = x->s;      topb = &(botb[xl]);    }    while (as >= bota)    {      unsigned long ai = (unsigned long)(*as--);      unsigned short* rs = currentr--;      *rs = 0;      if (ai != 0)      {        unsigned long sum = 0;        const unsigned short* bs = botb;        while (bs < topb)        {          sum += ai * (unsigned long)(*bs++) + (unsigned long)(*rs);          *rs++ = extract(sum);          sum = down(sum);        }        while (sum != 0 && rs < topr)        {          sum += (unsigned long)(*rs);          *rs++ = extract(sum);          sum = down(sum);        }      }    }    r->sgn = rsgn;  }  Icheck(r);  return r;}// main division routinestatic void do_divide(unsigned short* rs,                      const unsigned short* ys, int yl,                      unsigned short* qs, int ql){  const unsigned short* topy = &(ys[yl]);  unsigned short d1 = ys[yl - 1];  unsigned short d2 = ys[yl - 2];   int l = ql - 1;  int i = l + yl;    for (; l >= 0; --l, --i)  {    unsigned short qhat;       // guess q    if (d1 == rs[i])		qhat = (unsigned short) I_MAXNUM;    else    {      unsigned long lr = up((unsigned long)rs[i]) | rs[i-1];		qhat = (unsigned short) (lr / d1);    }    for(;;)     // adjust q, use docmp to avoid overflow problems    {      unsigned short ts[3];      unsigned long prod = (unsigned long)d2 * (unsigned long)qhat;      ts[0] = extract(prod);      prod = down(prod) + (unsigned long)d1 * (unsigned long)qhat;      ts[1] = extract(prod);      ts[2] = extract(down(prod));      if (docmp(ts, &(rs[i-2]), 3) > 0)        --qhat;      else        break;    };        // multiply & subtract        const unsigned short* yt = ys;    unsigned short* rt = &(rs[l]);    unsigned long prod = 0;    unsigned long hi = 1;    while (yt < topy)    {      prod = (unsigned long)qhat * (unsigned long)(*yt++) + down(prod);      hi += (unsigned long)(*rt) + I_MAXNUM - (unsigned long)(extract(prod));      *rt++ = extract(hi);      hi = down(hi);    }    hi += (unsigned long)(*rt) + I_MAXNUM - (unsigned long)(down(prod));    *rt = extract(hi);    hi = down(hi);        // off-by-one, add back        if (hi == 0)    {      --qhat;      yt = ys;      rt = &(rs[l]);      hi = 0;      while (yt < topy)      {        hi = (unsigned long)(*rt) + (unsigned long)(*yt++) + down(hi);        *rt++ = extract(hi);      }      *rt = 0;    }    if (qs != 0)      qs[l] = qhat;  }}// divide by single digit, return remainder// if q != 0, then keep the result in q, else just compute remstatic int unscale(const unsigned short* x, int xl, unsigned short y,                   unsigned short* q){  if (xl == 0 || y == 1)    return 0;  else if (q != 0)  {    unsigned short* botq = q;    unsigned short* qs = &(botq[xl - 1]);    const unsigned short* xs = &(x[xl - 1]);    unsigned long rem = 0;    while (qs >= botq)    {      rem = up(rem) | *xs--;      unsigned long u = rem / y;      *qs-- = extract(u);      rem -= u * y;    }    int r = extract(rem);    return r;  }  else                          // same loop, a bit faster if just need rem  {    const unsigned short* botx = x;    const unsigned short* xs = &(botx[xl - 1]);    unsigned long rem = 0;    while (xs >= botx)    {      rem = up(rem) | *xs--;      unsigned long u = rem / y;      rem -= u * y;    }    int r = extract(rem);    return r;  }}IntRep* div(const IntRep* x, const IntRep* y, IntRep* q){  nonnil(x);  nonnil(y);  int xl = x->len;  int yl = y->len;  // if (yl == 0) (*lib_error_handler)("gInteger", "attempted division by zero");  assert(yl != 0);  int comp = ucompare(x, y);  int xsgn = x->sgn;  int ysgn = y->sgn;  int samesign = xsgn == ysgn;  if (comp < 0)    q = Icopy_zero(q);  else if (comp == 0)    q = Icopy_one(q, samesign);  else if (yl == 1)  {    q = Icopy(q, x);    unscale(q->s, q->len, y->s[0], q->s);  }  else  {    IntRep* yy = 0;    IntRep* r  = 0;	 unsigned short prescale = (unsigned short) (I_RADIX / (1 + y->s[yl - 1]));    if (prescale != 1 || y == q)    {      yy = multiply(y, ((long)prescale & I_MAXNUM), yy);      r = multiply(x, ((long)prescale & I_MAXNUM), r);    }    else    {      yy = (IntRep*)y;      r = Icalloc(r, xl + 1);      scpy(x->s, r->s, xl);    }    int ql = xl - yl + 1;          q = Icalloc(q, ql);    do_divide(r->s, yy->s, yl, q->s, ql);    if (yy != y && !STATIC_IntRep(yy)) delete yy;    if (!STATIC_IntRep(r)) delete r;  }  q->sgn = samesign;  Icheck(q);  return q;}IntRep* div(const IntRep* x, long y, IntRep* q){  nonnil(x);  int xl = x->len;  // if (y == 0) (*lib_error_handler)("gInteger", "attempted division by zero");  assert(y != 0);  unsigned short ys[SHORT_PER_LONG];  unsigned long u;  int ysgn = y >= 0;  if (ysgn)    u = y;  else    u = -y;  int yl = 0;  while (u != 0)  {    ys[yl++] = extract(u);    u = down(u);  }  int comp = xl - yl;  if (comp == 0) comp = docmp(x->s, ys, xl);  int xsgn = x->sgn;  int samesign = xsgn == ysgn;  if (comp < 0)    q = Icopy_zero(q);  else if (comp == 0)  {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -