[Python-checkins] r46768 - sandbox/trunk/decimal-c/_decimal.c

Jim Jewett jimjjewett at gmail.com
Mon Jun 12 20:06:58 CEST 2006


It might be time to be more explicit in the documentation about what a
"limb" is.

>From a quick scan, it seems to be a group of 3 digits that are handled
together for space efficiency.  But that doesn't quite make sense --
why 3-digit (=10 bit) limbs instead of 4-digit (same storage
requirement) or 9digit (since you're using C longs anyway).  There may
be good reasons involving delayed normalization, but they should be
documented.  Or it may be that I'm way off base, in which case the
real explanation should be documeted.

-jJ

On 6/9/06, mateusz.rukowicz <python-checkins at python.org> wrote:
> Author: mateusz.rukowicz
> Date: Fri Jun  9 12:03:15 2006
> New Revision: 46768
>
> Modified:
>    sandbox/trunk/decimal-c/_decimal.c
> Log:
> Switched to 'limbs' instead of 'digits', some functions still calculates digits - this will be removed.
>
>
> Modified: sandbox/trunk/decimal-c/_decimal.c
> ==============================================================================
> --- sandbox/trunk/decimal-c/_decimal.c  (original)
> +++ sandbox/trunk/decimal-c/_decimal.c  Fri Jun  9 12:03:15 2006
> @@ -168,6 +168,27 @@
>         }
>  }
>
> +static void
> +_limb_fill(long *self, long ndigits, long x)
> +{
> +       //TODO
> +}
> +
> +static long
> +_limb_get_digit(long *self, long ndigits, long i)
> +{
> +       long pos = ndigits - i - 1;
> +       long limb = pos / LOG;
> +       pos %= LOG;
> +       long tmp = self[limb];
> +       while(pos)
> +       {
> +                       tmp/=10;
> +                       pos --;
> +       }
> +       return tmp%10;
> +}
> +
>  /* helpful macros ************************************************************/
>
>  /* if we later decide to call this module "squeaky" */
> @@ -374,7 +395,10 @@
>      res = _new_decimalobj(type, thing->ob_size, sign, 0);
>      if (!res) return NULL;
>      for (i = 0; i < thing->ob_size; i++)
> -        res->digits[i] = thing->digits[i];
> +        res->digits[i] = thing->digits[i];     /* DELETE */
> +
> +       for (i = 0; i< res->limb_count;i++)
> +               res->limbs[i] = thing->limbs[i];
>      return res;
>  }
>
> @@ -478,6 +502,7 @@
>              if (res) {
>                  for (i = 0; i < ctx->prec; i++)
>                      res->digits[i] = 9;
> +                               _limb_fill(res->limbs, ctx->prec, 9);
>                  return res;
>              }
>          }
> @@ -490,6 +515,7 @@
>              if (res) {
>                  for (i = 0; i < ctx->prec; i++)
>                      res->digits[i] = 9;
> +                               _limb_fill(res->limbs, ctx->prec, 9);
>                  return res;
>              }
>          }
> @@ -666,10 +692,10 @@
>         i = 0;
>         while(new->limbs[i] >= BASE)
>         {
> +                       assert(i+1 < new->limb_count);
>                         new->limbs[i] -= BASE;
>                         new->limbs[i+1] ++;
>                         i++;
> -                       assert(i+1 < new->limb_count);
>         }
>      return new;
>  }
> @@ -700,9 +726,9 @@
>          new->digits[i] = self->digits[i];
>         _limb_first_n_digits(self->limbs, self->ob_size, 0, new->limbs, prec);
>
> -    if (!new) return NULL;
>      for (i = prec; i < self->ob_size; i++)
> -        if (self->digits[i] > 0) {
> +               if(_limb_get_digit(self->limbs,self->ob_size, i) > 0){          /* SLOW */
> +//        if (self->digits[i] > 0) {
>              new2 = _decimal_increment(new, 1, ctx);
>              Py_DECREF(new);
>              if (!new2)
> @@ -728,8 +754,9 @@
>  {
>      decimalobject *new;
>      assert(expdiff > 0);
> -    if (self->ob_size > prec && self->digits[prec] >= 5) {
> -        new = _decimal_increment(tmp, 1, ctx);
> +//    if (self->ob_size > prec && self->digits[prec] >= 5) {
> +       if(self->ob_size > prec && _limb_get_digit(self->limbs, self->ob_size, prec) >= 5){     /* SLOW */
> +               new = _decimal_increment(tmp, 1, ctx);
>          Py_DECREF(tmp);
>          if (!new) return NULL;
>          if (new->ob_size > prec) {
> @@ -756,11 +783,11 @@
>          tmp->digits[i] = self->digits[i];
>
>         last = _limb_first_n_digits(self->limbs, self->ob_size, 0, tmp->limbs, prec);
> -       last = self->digits[prec];
>         assert(self->digits[prec] == last);
>      if (last == 5) {
>          for (i = prec+1; i < self->ob_size; i++) {
> -            if (self->digits[i] != 0)
> +                       if(_limb_get_digit(self->limbs, self->ob_size, i) != 0) /* SLOW */
> +    //        if (self->digits[i] != 0)
>                  return _do_round_half_up(self, prec, expdiff, ctx, tmp);
>          }
>          /* self ends in 5000...., so tmp is okay */
> @@ -785,11 +812,13 @@
>         assert(last == self->digits[prec]);
>      if (last == 5) {
>          for (i = prec+1; i < self->ob_size; i++) {
> -            if (self->digits[i] != 0)
> +                       if(_limb_get_digit(self->limbs, self->ob_size, i) != 0) /* SLOW */
> +//            if (self->digits[i] != 0)
>                  return _do_round_half_up(self, prec, expdiff, ctx, tmp);
>          }
> -        if ((self->digits[prec-1] & 1) == 0)
> -            return tmp;
> +//        if ((self->digits[prec-1] & 1) == 0)
> +               if((_limb_get_digit(self->limbs, self->ob_size, i)&1) == 0)
> +                       return tmp;
>      }
>      return _do_round_half_up(self, prec, expdiff, ctx, tmp);
>  }
> @@ -875,6 +904,7 @@
>          if (!new) return NULL;
>          while (i--)
>              new->digits[i] = 0;
> +               _limb_fill(new->limbs, new->ob_size,0);
>
>          if (handle_Rounded(ctx, NULL) != 0) {
>              Py_DECREF(new);
> @@ -889,6 +919,7 @@
>          new->digits[0] = 0;
>          for (i = 1; i < new->ob_size; i++)
>              new->digits[i] = self->digits[i-1];
> +               _limb_first_n_digits(self->limbs, self->ob_size, -1, new->limbs, new->ob_size);
>          prec = 1;
>      } else if (prec < 0) {
>          new = _NEW_decimalobj(2, self->sign,
> @@ -896,6 +927,7 @@
>          if (!new) return NULL;
>          new->digits[0] = 0;
>          new->digits[1] = 1;
> +               new->limbs[0] = 1;
>          prec = 1;
>      } else {
>          new = _decimal_get_copy(self);
> @@ -918,14 +950,17 @@
>          for (i = new->ob_size; i < new2->ob_size; i++) {
>              new2->digits[i] = 0;
>          }
> +
> +               _limb_first_n_digits(new->limbs, new->ob_size, 0, new2->limbs, new2->ob_size);
>          Py_DECREF(new);
>          return new2;
>      }
>
>      /* Maybe all the lost digits are 0. */
>      for (i = expdiff; i < self->ob_size; i++) {
> -        if (self->digits[i] > 0)
> -            goto no_way;
> +//        if (self->digits[i] > 0)
> +               if(_limb_get_digit(self->limbs, self->ob_size, i) > 0)
> +                       goto no_way;
>      }
>      /* All lost digits are 0, so just clobber new */
>      new->ob_size = prec;
> @@ -996,6 +1031,7 @@
>          if (!ans)
>              return NULL;
>          ans->digits[0] = 0;
> +               ans->limbs[0] = 0;
>          return ans;
>      }
>
> @@ -1013,6 +1049,7 @@
>              return NULL;
>          ans->digits[0] = 0;
>          ans->digits[1] = 1;
> +               ans->limbs[0] = 1;
>          digits = 1;
>      } else {
>          ans = _NEW_decimalobj(self->ob_size+1, self->sign, self->exp);
> @@ -1021,6 +1058,7 @@
>          for (i = 0; i < self->ob_size; i++)
>              ans->digits[i+1] = self->digits[i];
>          ans->digits[0] = 0;
> +               _limb_first_n_digits(self->limbs, self->ob_size, -1, ans->limbs, ans->ob_size);
>      }
>
>      tmp = _decimal_round(ans, digits, ctx, rounding);
> @@ -1807,7 +1845,7 @@
>  }
>
>
> -static PyObject *
> +static PyObject *      /* TODO review that */
>  _do_decimal_str(decimalobject *d, contextobject *context, int engineering)
>  {
>      char *outbuf;
> @@ -1876,8 +1914,9 @@
>      }
>      if (engineering) { /* eng has no leading zeros */
>          for (i = 0, j = 0; i < imax; i++) {
> -            if (d->digits[j] == 0) {
> -                j++;
> +//            if (d->digits[j] == 0) {
> +                       if(_limb_get_digit(d->limbs, d->ob_size, j) == 0){
> +                               j++;
>              } else {
>                  break;
>              }
> @@ -1889,8 +1928,9 @@
>              SANITY_CHECK(p);
>              continue;
>          } else {
> -            p += sprintf(p, "%d", d->digits[j]);
> -            SANITY_CHECK(p);
> +//            p += sprintf(p, "%d", d->digits[j]);
> +                       p += sprintf(p, "%d", _limb_get_digit(d->limbs, d->ob_size, j));        /* SLOW */
> +                       SANITY_CHECK(p);
>              j++;
>          }
>      }
> @@ -2453,9 +2493,12 @@
>      long i;
>      if (ISSPECIAL(self))
>          return 1;
> -    for (i = 0; i < self->ob_size; i++)
> -        if (self->digits[i] != 0) return 1;
> -    return 0;
> +//    for (i = 0; i < self->ob_size; i++)
> +//        if (self->digits[i] != 0) return 1;
> +
> +       for(i=0;i<self->limb_count;i++)
> +               if(self->limbs[i] != 0) return 1;
> +       return 0;
>  }
>
>
> @@ -2877,7 +2920,7 @@
>         {
>                 item = PyTuple_GET_ITEM(digtup, i);
>                 long x;
> -               if(PyInt_AsLong(item))
> +               if(PyInt_Check(item))
>                         x = PyInt_AsLong(item);
>                 else if (PyLong_Check(item)) {
>                         x = PyLong_AsLong(item);
> _______________________________________________
> Python-checkins mailing list
> Python-checkins at python.org
> http://mail.python.org/mailman/listinfo/python-checkins
>


More information about the Python-checkins mailing list