<commit_before>/* The Computer Language Benchmarks Game
   http://shootout.alioth.debian.org/

   contributed by <NAME>, <NAME>, <NAME>
   derived from the GNU C version by Bonzini, Bartlett, and Mellor
*/

use GMP;

config const n = 50;                // Compute n digits of Pi, 50 by default

proc main() {
  for (d,i) in zip(gen_digits(n), 1..) {
    write(d);
    if i % 10 == 0 then
      writeln("\t:",i);
  }
}


iter gen_digits(numDigits) {
  var numer, accum, denom, tmp1, tmp2: mpz_t;

  mpz_init_set_ui(numer, 1);               // numer = 1
  mpz_init_set_ui(accum, 0);               // accum = 0
  mpz_init_set_ui(denom, 1);               // denom = 1
  mpz_init(tmp1);                          // init tmp1
  mpz_init(tmp2);                          // init tmp2

  var k: c_ulong;
  for i in 1..numDigits {
    do {
      do {
        k += 1;
        const y2 = 2 * k + 1;

        //
        // Compute the next term
        //
        mpz_mul_2exp(tmp1, numer, 1);      // tmp1  = numer * 2
        mpz_add(accum, accum, tmp1);	   // accum += numer * 2
        mpz_mul_ui(accum, accum, y2);	   // accum *= (2k+1)
        mpz_mul_ui(numer, numer, k);       // numer *= k
        mpz_mul_ui(denom, denom, y2);      // denom *= (2k+1)

        //
        // Continue looping until the digit is ready
        //
      } while (mpz_cmp(numer, accum) > 0); // while numer > accum

      //
      // Compute (numer * 3 + accum)
      //
      mpz_mul_2exp(tmp1, numer, 1);        // tmp1 = numer * 2
      mpz_add(tmp1, tmp1, numer);          // tmp1 += numer
      mpz_add(tmp1, tmp1, accum);          // tmp1 += accum

      //      
      // tmp1 = tmp1 / denom; tmp2 = tmp1 % denom
      //
      mpz_fdiv_qr(tmp1, tmp2, tmp1, denom);

      //
      // Now, if (numer * 3 + accum) % denom + numer
      // == (numer * 4 + accum) % denom
      //
      mpz_add(tmp2, tmp2, numer);
    } while (mpz_cmp(tmp2, denom) >= 0);   // while tmp2 >= denom

    //
    // compute and yield the digit, d
    //
    const d = mpz_get_ui(tmp1);            // get least significant digit
    yield d;

    //
    // eliminate digit d
    //
    mpz_submul_ui(accum, denom, d);        // accum = (accum - denom) * d
    mpz_mul_ui(accum, accum, 10);          // accum *= 10
    mpz_mul_ui(numer, numer, 10);          // numer *= 10
  }
}<commit_msg>D'oh!  Let's try that new pidigits version again.<commit_after>/* The Computer Language Benchmarks Game
   http://shootout.alioth.debian.org/

   contributed by <NAME>, <NAME>, <NAME>
   derived from the GNU C version by Ledrug
*/

use GMP;

config const n = 50;                // Compute n digits of Pi, 50 by default

proc main() {
  for (d,i) in zip(gen_digits(n), 1..) {
    write(d);
    if i % 10 == 0 then
      writeln("\t:",i);
  }
}


iter gen_digits(numDigits) {
  var tmp1, tmp2, acc, den, num: mpz_t;

  mpz_init(tmp1);                          // init tmp1
  mpz_init(tmp2);                          // init tmp2
  mpz_init_set_ui(acc, 0);                 // acc = 0
  mpz_init_set_ui(den, 1);                 // den = 1
  mpz_init_set_ui(num, 1);                 // num = 1

  var d, k: c_ulong;

  for i in 1..numDigits {
    do {
      do {
        k += 1;
        const k2 = 2 * k + 1;

        //
        // Compute the next term
        //
        mpz_addmul_ui(acc, num, 2);        // acc += num * 2
        mpz_mul_ui(acc, acc, k2);	   // acc *= (2k+1)
        mpz_mul_ui(den, den, k2);          // den *= (2k+1)
        mpz_mul_ui(num, num, k);           // num *= k

        //
        // Continue looping until the digit is ready
        //
      } while (mpz_cmp(num, acc) > 0);     // while num > acc

      d = extract_digit(3);
    } while (d != extract_digit(4));       // while the 3rd digit, d != the 4th

    yield d;                               // once it differs, yield it

    //
    // eliminate digit d
    //
    mpz_submul_ui(acc, den, d);            // acc = (acc - den) * d
    mpz_mul_ui(acc, acc, 10);              // acc *= 10
    mpz_mul_ui(num, num, 10);              // num *= 10
  }

  //
  // Helper function to extract the nth digit
  //
  proc extract_digit(nth: c_ulong) {
    mpz_mul_ui(tmp1, num, nth);              // tmp1 = num * nth
    mpz_add(tmp2, tmp1, acc);                // tmp2 = tmp1 + acc
    mpz_tdiv_q(tmp1, tmp2, den);             // tmp1 = tmp2 / den
    
    return mpz_get_ui(tmp1);                 // convert tmp1 to a c_uint
  }
}


{'fraction_non_alphanumeric': 0.13910702266098274, 'fraction_numerical': 0.029616333856854388, 'mean_word_length': 1.4373974849644615, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5393204', 'n_tokens_mistral': 1694, 'n_tokens_neox': 1586, 'n_words': 437}