Changeset 31407 in project


Ignore:
Timestamp:
09/12/14 12:25:43 (5 years ago)
Author:
sjamaan
Message:

numbers: Roll trimming and normalizing of bignums into one function, simplifying the returning of bignums, as well as offering a tiny performance improvement.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • release/4/numbers/trunk/numbers-c.c

    r31405 r31407  
    13361336
    13371337    *scan_r = 0; /* Ensure trimming works.  TODO: set length directly? */
    1338     C_bignum_destructive_trim(result);
    1339     C_kontinue(k, result); /* Normalize unnecessary; we added to a bignum. */
     1338    C_kontinue(k, C_bignum_normalize(result));
    13401339  }
    13411340}
     
    14371436    (*scan_r++) = (*scan_x++);
    14381437
    1439   C_bignum_destructive_trim(result); /* Last digit may be 0. */
    1440   C_kontinue(k, C_bignum_normalize(result)); /* Might've reduced to fixnum */
     1438  C_kontinue(k, C_bignum_normalize(result));
    14411439}
    14421440
     
    15651563}
    15661564
    1567 /* Normalization of the bignum's representation: remove trailing zeroes. */
    1568 void C_ccall
    1569 C_bignum_destructive_trim(C_word big)
    1570 {
    1571   C_word *start = C_bignum_digits(big);
    1572   C_word *last_digit = start + C_bignum_size(big);
    1573   C_word *scan = last_digit;
    1574 
    1575   while ((start <= scan) && ((*--scan) == 0))
    1576     ;
    1577   scan += 1;
    1578 
    1579   if (scan < last_digit) {
    1580     C_word len = scan - start;
    1581     /* Mutate vector size of internal bignum vector. */
    1582     C_block_header(C_internal_bignum(big)) = (C_STRING_TYPE | C_wordstobytes(len+1));
    1583     /* Set internal header. */
    1584     C_bignum_header(big) = (C_bignum_header(big) & C_BIGNUM_HEADER_SIGN_BIT) | len;
    1585   }
    1586 }
    1587 
    1588 /* Actual normalization: return a fixnum if the value fits. */
     1565/* Normalization: scan trailing zeroes, then return a fixnum if the
     1566 * value fits, or trim the bignum's length. */
    15891567C_word C_ccall
    15901568C_bignum_normalize(C_word big)
    15911569{
    1592   switch (C_bignum_size(big)) {
     1570  C_word *start = C_bignum_digits(big);
     1571  C_word *last_digit = start + C_bignum_size(big) - 1;
     1572  C_word *scan = last_digit, length;
     1573
     1574  while (scan >= start && *scan == 0)
     1575    scan--;
     1576  length = scan - start + 1;
     1577 
     1578  switch (length) {
    15931579  case 0:
    15941580    return C_fix(0);
    15951581  case 1:
    1596     return C_fix(C_bignum_negativep(big) ?
    1597                  -C_bignum_digits(big)[0] :
    1598                  C_bignum_digits(big)[0]);
     1582    return C_fix(C_bignum_negativep(big) ? -*start : *start);
    15991583  case 2:
    1600     if (C_bignum_negativep(big) &&
    1601         C_bignum_digits(big)[1] == 1 && C_bignum_digits(big)[0] == 0)
     1584    if (C_bignum_negativep(big) && *scan == 1 && *start == 0)
    16021585      return C_fix(C_MOST_NEGATIVE_FIXNUM);
     1586    /* FALLTHROUGH */
    16031587  default:
     1588    if (scan < last_digit) {
     1589      /* Mutate vector size of internal bignum vector. */
     1590      C_block_header(C_internal_bignum(big)) = (C_STRING_TYPE | C_wordstobytes(length+1));
     1591      /* Set internal header. */
     1592      C_bignum_header(big) = (C_bignum_header(big) & C_BIGNUM_HEADER_SIGN_BIT) | length;
     1593    }
    16041594    return big;
    16051595  }
     
    16751665  *end_digit = bignum_digits_destructive_scale_up_with_carry(digits, end_digit,
    16761666                                                             C_unfix(fixy), 0);
    1677   C_bignum_destructive_trim(new_big);
    16781667  C_kontinue(k, C_bignum_normalize(new_big));
    16791668}
     
    18161805    (*scan_r) += carry;
    18171806  }
    1818   C_bignum_destructive_trim(result);
    18191807  C_kontinue(k, C_bignum_normalize(result));
    18201808}
     
    19011889  if (carry) (*last_digit++) = carry; /* Move end */
    19021890
    1903   C_bignum_destructive_trim(result);
    19041891  C_kontinue(k, C_bignum_normalize(result));
    19051892}
     
    20582045    (*--scan) = 0;
    20592046
    2060   C_bignum_destructive_trim(result);
    20612047  C_kontinue(k, C_bignum_normalize(result));
    20622048}
     
    22152201    *scanr =  (*scanx++ & C_BIGNUM_DIGIT_MASK) >> bit_offset;
    22162202  }
    2217   C_bignum_destructive_trim(result);
    22182203  C_kontinue(k, C_bignum_normalize(result));
    22192204}
     
    23062291    *scan = ((double)rand())/(RAND_MAX + 1.0) * (double)((C_word)1 << C_BIGNUM_DIGIT_LENGTH);
    23072292
    2308   C_bignum_destructive_trim(result);
    23092293  C_kontinue(k, C_bignum_normalize(result));
    23102294}
     
    23752359                                  digit1 ^ digit2;
    23762360  }
    2377   C_bignum_destructive_trim(result);
    23782361  C_kontinue(k, C_bignum_normalize(result));
    23792362}
     
    24762459    }
    24772460  }
    2478   C_bignum_destructive_trim(result);
    24792461  C_kontinue(k, C_bignum_normalize(result));
    24802462}
     
    25402522  assert(C_fitsinbignumhalfdigitp(remainder));
    25412523
    2542   C_bignum_destructive_trim(quotient);
    25432524  quotient = C_bignum_normalize(quotient);
    25442525
     
    25842565      (*scan) = qj;
    25852566    }
    2586     C_bignum_destructive_trim(quotient);
    25872567    quotient = C_bignum_normalize(quotient);
    25882568  } else {
Note: See TracChangeset for help on using the changeset viewer.