Changeset 31359 in project


Ignore:
Timestamp:
09/10/14 15:19:58 (5 years ago)
Author:
sjamaan
Message:

numbers: Allocate string directly in GCable memory. Replace floating-point calculations to get the base & steps with a simple loop, which is just as fast.

File:
1 edited

Legend:

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

    r31358 r31359  
    14571457static void digits_to_integer_2(C_word c, C_word self, C_word result);
    14581458static void bignum_to_digits_2(C_word c, C_word self, C_word working_copy);
     1459static void bignum_to_digits_3(C_word c, C_word self, C_word string);
    14591460static void flo_to_int_2(C_word c, C_word self, C_word result);
    14601461static C_word ilen(C_uword x);
     
    21922193         old_big = C_block_item(self, 2),
    21932194         radix = C_unfix(C_block_item(self, 3)),
    2194          *start = C_bignum_digits(working_copy),
    2195          *scan = start + C_bignum_size(working_copy) - 1,
    2196          digit, large_digit, steps, i, base, len;
    2197   char *buf, *index;
    2198   char *characters = "0123456789abcdef";
    2199   C_word *tmp, ret;
     2195         len;
    22002196
    22012197  /* Copy the old bignum's digits as-is into our working copy */
     
    22092205  assert(radix > 1 && C_fitsinbignumhalfdigitp(radix));
    22102206
    2211   /* Calculate the largest power of radix that fits a halfdigit. */
    2212   steps = floor(log((double)((C_word)1 << C_BIGNUM_HALF_DIGIT_SHIFT - 1)) /
    2213                 log((double)radix));
    2214   base = pow((double)radix, (double)steps);
    2215 
    22162207  /* A sloppy over-approximation of the number of radix digits we
    22172208   * need.  Due to the algorithm chopping off slices of "base" size at
     
    22202211   * an optional sign.
    22212212   */
    2222   len = ((C_bignum_size(working_copy)+1)*C_BIGNUM_DIGIT_LENGTH) / (ilen(radix)-1) + 1;
    2223   buf = C_malloc(len);
    2224   if (buf == NULL) {
    2225     fprintf(stderr, "out of memory - can not allocate string");
    2226     exit(EXIT_FAILURE);
    2227   }
    2228   index = buf + len - 1;
     2213  len = (C_bignum_size(old_big)+1)*C_BIGNUM_DIGIT_LENGTH / (ilen(radix)-1) + 1;
     2214
     2215  /* Nice: We can recycle the current closure */
     2216  C_set_block_item(self, 0, (C_word)bignum_to_digits_3);
     2217  /* item 1 is still the same continuation */
     2218  C_set_block_item(self, 2, working_copy);
     2219
     2220  C_allocate_vector(6, (C_word)NULL, self, C_fix(len),
     2221                    /* Byte vec, no initialization, align at 8 bytes */
     2222                    C_SCHEME_TRUE, C_SCHEME_FALSE, C_SCHEME_FALSE);
     2223}
     2224
     2225static void
     2226bignum_to_digits_3(C_word c, C_word self, C_word string)
     2227{
     2228  static char *characters = "0123456789abcdef";
     2229  C_word k = C_block_item(self, 1),
     2230         working_copy = C_block_item(self, 2),
     2231         radix = C_unfix(C_block_item(self, 3)),
     2232         *start = C_bignum_digits(working_copy),
     2233         *scan = start + C_bignum_size(working_copy) - 1,
     2234         len = C_header_size(string),
     2235         digit, large_digit, steps, i, base;
     2236  char *buf = C_c_string(string), *index = buf + len - 1;
     2237
     2238  /* Calculate the largest power of radix that fits a halfdigit:
     2239   * steps = log10(2^halfdigit_bits), base = 10^steps
     2240   */
     2241  for(steps = 0, base = radix; C_fitsinbignumhalfdigitp(base); base *= radix)
     2242    steps++;
     2243
     2244  /* Back down: we overshot in the loop */
     2245  base /= radix;
    22292246
    22302247  while (start <= scan) {
     
    22492266    *--index = '-';
    22502267
    2251   /* XXX TODO: Check if memory is available with C_demand() */
    2252   tmp = C_alloc(C_SIZEOF_STRING(len - (index - buf)));
    2253   ret = C_string(&tmp, len - (index - buf), index);
    2254   C_free(buf);
    2255   C_kontinue(k, ret);
     2268  len -= index - buf; /* Shorten with distance between start and index. */
     2269  C_memmove(buf, index, len); /* Move start of number to begin of string. */
     2270  C_block_header(string) = C_STRING_TYPE | len; /* Mutate string length. */
     2271  C_kontinue(k, string);
    22562272}
    22572273
Note: See TracChangeset for help on using the changeset viewer.