<commit_before>export function methods(intOps, intTypes, typeName = 'Fraction') {

  class Fraction {
    constructor(numer, denom) {
      this.numer = numer;
      this.denom = denom;
    }

    toString() {
      return this.numer.toString() + '/' + this.denom.toString();
    }

    get __typeName() { return typeName; }
  };


  const toJS = n => intOps.toJS(n.numer) / intOps.toJS(n.denom);


  const _mod = (a, b) => intOps.minus(a, intOps.times(intOps.idiv(a, b), b));

  const _gcd = (a, b) => {
    a = intOps.abs(a);
    b = intOps.abs(b);

    while (intOps.sgn(b) > 0)
      [a, b] = [b, _mod(a, b)];

    return a;
  };


  const make = (numer, denom) => {
    const s = intOps.sgn(denom);

    if (s < 0)
      return make(intOps.negative(numer), intOps.negative(denom));
    else if (s == 0)
      throw new Error('fraction has zero denominator');
    else {
      const a = _gcd(denom, numer);
      const n = intOps.idiv(numer, a);
      const d = intOps.idiv(denom, a);

      if (intOps.cmp(d, 1) == 0 || intOps.sgn(n) == 0)
        return n;
      else
        return new Fraction(n, d);
    }
  };


  const parse = s => {
    const parts = s.split('/');
    if (parts.length == 1)
      return intOps.integer(parts[0]);
    else if (parts.length == 2)
      return make(intOps.integer(parts[0]), intOps.integer(parts[1]));
    else
      throw new Error(`expected an integer or fraction literal, got ${s}`);
  };


  const promote = n => new Fraction(n, 1);

  const negative = q => new Fraction(intOps.negative(q.numer), q.denom);
  const abs      = q => new Fraction(intOps.abs(q.numer), q.denom);
  const sgn      = q => intOps.sgn(q.numer);


  const floor = q => {
    return intOps.idiv(q.numer, q.denom);
  };

  const ceil = q => {
    return intOps.idiv(intOps.plus(q.numer, intOps.minus(q.denom, 1)),
                       q.denom);
  };

  const cmp = (q, r) => sgn(minus(q, r));


  const plus = function plus(q, r) {
    const a = _gcd(q.denom, r.denom);
    const s = intOps.idiv(r.denom, a);
    const t = intOps.idiv(q.denom, a);

    return make(intOps.plus(intOps.times(s, q.numer), intOps.times(t, r.numer)),
                intOps.times(s, q.denom));
  };


  const minus = (q, r) => plus(q, negative(r));


  const times = function times(q, r) {
    const a = _gcd(q.numer, r.denom);
    const b = _gcd(q.denom, r.numer);

    return make(intOps.times(intOps.idiv(q.numer, a), intOps.idiv(r.numer, b)),
                intOps.times(intOps.idiv(q.denom, b), intOps.idiv(r.denom, a)));
  };


  const div = (q, r) => times(q, new Fraction(r.denom, r.numer));<commit_msg>fix cmp() on fractions when difference is integer<commit_after>export function methods(intOps, intTypes, typeName = 'Fraction') {

  class Fraction {
    constructor(numer, denom) {
      this.numer = numer;
      this.denom = denom;
    }

    toString() {
      return this.numer.toString() + '/' + this.denom.toString();
    }

    get __typeName() { return typeName; }
  };


  const toJS = n => intOps.toJS(n.numer) / intOps.toJS(n.denom);


  const _mod = (a, b) => intOps.minus(a, intOps.times(intOps.idiv(a, b), b));

  const _gcd = (a, b) => {
    a = intOps.abs(a);
    b = intOps.abs(b);

    while (intOps.sgn(b) > 0)
      [a, b] = [b, _mod(a, b)];

    return a;
  };


  const make = (numer, denom) => {
    const s = intOps.sgn(denom);

    if (s < 0)
      return make(intOps.negative(numer), intOps.negative(denom));
    else if (s == 0)
      throw new Error('fraction has zero denominator');
    else {
      const a = _gcd(denom, numer);
      const n = intOps.idiv(numer, a);
      const d = intOps.idiv(denom, a);

      if (intOps.cmp(d, 1) == 0 || intOps.sgn(n) == 0)
        return n;
      else
        return new Fraction(n, d);
    }
  };


  const parse = s => {
    const parts = s.split('/');
    if (parts.length == 1)
      return intOps.integer(parts[0]);
    else if (parts.length == 2)
      return make(intOps.integer(parts[0]), intOps.integer(parts[1]));
    else
      throw new Error(`expected an integer or fraction literal, got ${s}`);
  };


  const promote = n => new Fraction(n, 1);

  const negative = q => new Fraction(intOps.negative(q.numer), q.denom);
  const abs      = q => new Fraction(intOps.abs(q.numer), q.denom);
  const sgn      = q => intOps.sgn(q.numer);


  const floor = q => {
    return intOps.idiv(q.numer, q.denom);
  };

  const ceil = q => {
    return intOps.idiv(intOps.plus(q.numer, intOps.minus(q.denom, 1)),
                       q.denom);
  };

  const cmp = (q, r) => {
    const d = minus(q, r);
    return intOps.sgn(d.numer == null ? d : d.numer);
  };


  const plus = function plus(q, r) {
    const a = _gcd(q.denom, r.denom);
    const s = intOps.idiv(r.denom, a);
    const t = intOps.idiv(q.denom, a);

    return make(intOps.plus(intOps.times(s, q.numer), intOps.times(t, r.numer)),
                intOps.times(s, q.denom));
  };


  const minus = (q, r) => plus(q, negative(r));


  const times = function times(q, r) {
    const a = _gcd(q.numer, r.denom);
    const b = _gcd(q.denom, r.numer);

    return make(intOps.times(intOps.idiv(q.numer, a), intOps.idiv(r.numer, b)),
                intOps.times(intOps.idiv(q.denom, b), intOps.idiv(r.denom, a)));
  };


  const div = (q, r) => times(q, new Fraction(r.denom, r.numer));
{'fraction_non_alphanumeric': 0.17591897974493623, 'fraction_numerical': 0.004876219054763691, 'mean_word_length': 2.481070496083551, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1982690', 'n_tokens_mistral': 2115, 'n_tokens_neox': 2018, 'n_words': 479}