anchor.diff:  
   // Interface for modular reduction.
   abstract class _BigIntReduction {
  -  // Return the number of digits used by r_digits.
  -  int convert(_BigIntImpl x, Uint32List r_digits);
  -  int mul(Uint32List xDigits, int xUsed, Uint32List yDigits, int yUsed,
  +  int get _normModulusUsed;
  +  // Return the number of digits used by resultDigits.
  +  int _convert(_BigIntImpl x, Uint32List resultDigits);
  +  int _mul(Uint32List xDigits, int xUsed, Uint32List yDigits, int yUsed,
         Uint32List resultDigits);
  -  int sqr(Uint32List xDigits, int xUsed, Uint32List resultDigits);
  +  int _sqr(Uint32List xDigits, int xUsed, Uint32List resultDigits);
   
     // Return x reverted to _BigIntImpl.
  -  _BigIntImpl revert(Uint32List xDigits, int xUsed);
  +  _BigIntImpl _revert(Uint32List xDigits, int xUsed);
   }
   
  +// Montgomery reduction on _BigIntImpl.
  +class _BigIntMontgomeryReduction implements _BigIntReduction {
  +  final _BigIntImpl _modulus;
  +  int _normModulusUsed; // Even if processing 64-bit (digit pairs).
  +  Uint32List _modulusDigits;
  +  Uint32List _args;
  +  int _digitsPerStep; // Number of digits processed in one step. 1 or 2.
  +  static const int _xDigit = 0; // Index of digit of x.
  +  static const int _xHighDigit = 1; // Index of high digit of x (64-bit only).
  +  static const int _rhoDigit = 2; // Index of digit of rho.
  +  static const int _rhoHighDigit = 3; // Index of high digit of rho (64-bit).
  +  static const int _muDigit = 4; // Index of mu.
  +  static const int _muHighDigit = 5; // Index of high 32-bits of mu (64-bit).
  +
  +  _BigIntMontgomeryReduction(this._modulus) {
  +    _modulusDigits = _modulus._digits;
  +    _args = _newDigits(6);
  +    // Determine if we can process digit pairs by calling an intrinsic.
  +    _digitsPerStep = _mulMod(_args, _args, 0);
  +    _args[_xDigit] = _modulusDigits[0];
  +    if (_digitsPerStep == 1) {
  +      _normModulusUsed = _modulus._used;
  +      _invDigit(_args);
  +    } else {
  +      assert(_digitsPerStep == 2);
  +      _normModulusUsed = _modulus._used + (_modulus._used & 1);
  +      _args[_xHighDigit] = _modulusDigits[1];
  +      _invDigitPair(_args);
  +    }
  +  }
  +
  +  // Calculates -1/x % _digitBase, x is 32-bit digit.
  +  //         xy == 1 (mod m)
  +  //         xy =  1+km
  +  //   xy(2-xy) = (1+km)(1-km)
  +  // x(y(2-xy)) = 1-k^2 m^2
  +  // x(y(2-xy)) == 1 (mod m^2)
  +  // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
  +  // Should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
  +  //
  +  // Operation:
  +  //   args[_rhoDigit] = 1/args[_xDigit] mod _digitBase.
  +  static void _invDigit(Uint32List args) {
  +    var x = args[_xDigit];
  +    var y = x & 3; // y == 1/x mod 2^2
  +    y = (y * (2 - (x & 0xf) * y)) & 0xf; // y == 1/x mod 2^4
  +    y = (y * (2 - (x & 0xff) * y)) & 0xff; // y == 1/x mod 2^8
  +    y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16
  +    y = (y * (2 - x * y % _BigIntImpl._digitBase)) % _BigIntImpl._digitBase;
  +    // y == 1/x mod _digitBase
  +    y = -y; // We really want the negative inverse.
  +    args[_rhoDigit] = y & _BigIntImpl._digitMask;
  +    assert(((x * y) & _BigIntImpl._digitMask) == _BigIntImpl._digitMask);
  +  }
  +
  +  // Calculates -1/x % _digitBase^2, x is a pair of 32-bit digits.
  +  // Operation:
  +  //   args[_rhoDigit.._rhoHighDigit] =
  +  //     1/args[_xDigit.._xHighDigit] mod _digitBase^2.
  +  static void _invDigitPair(Uint32List args) {
  +    var two = _BigIntImpl.two;
  +    var mask32 = _BigIntImpl._oneDigitMask;
  +    var mask64 = _BigIntImpl._twoDigitMask;
  +    var xl = args[_xDigit]; // Lower 32-bit digit of x.
  +    var y = xl & 3; // y == 1/x mod 2^2
  +    y = (y * (2 - (xl & 0xf) * y)) & 0xf; // y == 1/x mod 2^4
  +    y = (y * (2 - (xl & 0xff) * y)) & 0xff; // y == 1/x mod 2^8
  +    y = (y * (2 - (((xl & 0xffff) * y) & 0xffff))) & 0xffff;
  +    // y == 1/x mod 2^16
  +    y = (y * (2 - ((xl * y) & 0xffffffff))) & 0xffffffff; // y == 1/x mod 2^32
  +    var x = (args[_xHighDigit] << _BigIntImpl._digitBits) | xl;
  +    y *= 2 - x * y; // Masking with 2^64-1 is implied by 64-bit arithmetic.
  +    // y == 1/x mod _digitBase^2
  +    y = -y; // We really want the negative inverse.
  +    args[_rhoDigit] = y & _BigIntImpl._digitMask;
  +    args[_rhoHighDigit] =
  +        (y >> _BigIntImpl._digitBits) & _BigIntImpl._digitMask;
  +    assert(x * y == -1);
  +  }
  +
  +  // Operation:
  +  //   args[_muDigit] = args[_rhoDigit]*digits[i] mod _digitBase.
  +  //   Returns 1.
  +  // Note: Intrinsics on 64-bit platforms process digit pairs at even indices:
  +  //   args[_muDigit.._muHighDigit] =
  +  //     args[_rhoDigit.._rhoHighDigit] * digits[i..i+1] mod _digitBase^2.
  +  //   Returns 2.
  +  static int _mulMod(Uint32List args, Uint32List digits, int i) {
  +    var rhol = args[_rhoDigit] & _BigIntImpl._halfDigitMask;
  +    var rhoh = args[_rhoDigit] >> _BigIntImpl._halfDigitBits;
  +    var dh = digits[i] >> _BigIntImpl._halfDigitBits;
  +    var dl = digits[i] & _BigIntImpl._halfDigitMask;
  +    args[_muDigit] = (dl * rhol +
  +            (((dl * rhoh + dh * rhol) & _BigIntImpl._halfDigitMask) <<
  +                _BigIntImpl._halfDigitBits)) &
  +        _BigIntImpl._digitMask;
  +    return 1;
  +  }
  +
  +  // result = x*R mod _modulus.
  +  // Returns resultUsed.
  +  int _convert(_BigIntImpl x, Uint32List resultDigits) {
  +    // Montgomery reduction only works if abs(x) < _modulus.
  +    assert(x.abs() < _modulus);
  +    assert(_digitsPerStep == 1 || _normModulusUsed.isEven);
  +    var result = x.abs()._dlShift(_normModulusUsed)._rem(_modulus);
  +    if (x._isNegative && !result._isNegative && result._used > 0) {
  +      result = _modulus - result;
  +    }
  +    var used = result._used;
  +    var digits = result._digits;
  +    var i = used + (used & 1);
  +    while (--i >= 0) {
  +      resultDigits[i] = digits[i];
  +    }
  +    return used;
  +  }
  +
  +  _BigIntImpl _revert(Uint32List xDigits, int xUsed) {
  +    var resultDigits = _newDigits(2 * _normModulusUsed);
  +    var i = xUsed + (xUsed & 1);
  +    while (--i >= 0) {
  +      resultDigits[i] = xDigits[i];
  +    }
  +    var resultUsed = _reduce(resultDigits, xUsed);
  +    return new _BigIntImpl._(false, resultUsed, resultDigits);
  +  }
  +
  +  // x = x/R mod _modulus.
  +  // Returns xUsed.
  +  int _reduce(Uint32List xDigits, int xUsed) {
  +    while (xUsed < 2 * _normModulusUsed) {
  +      // Pad x so _mulAdd has enough room later.
  +      xDigits[xUsed++] = 0;
  +    }
  +    var i = 0;
  +    while (i < _normModulusUsed) {
  +      var d = _mulMod(_args, xDigits, i);
  +      assert(d == _digitsPerStep);
  +      d = _BigIntImpl._mulAdd(
  +          _args, _muDigit, _modulusDigits, 0, xDigits, i, _normModulusUsed);
  +      assert(d == _digitsPerStep);
  +      i += d;
  +    }
  +    // Clamp x.
  +    while (xUsed > 0 && xDigits[xUsed - 1] == 0) {
  +      --xUsed;
  +    }
  +    xUsed = _BigIntImpl._drShiftDigits(xDigits, xUsed, i, xDigits);
  +    if (_BigIntImpl._compareDigits(
  +            xDigits, xUsed, _modulusDigits, _normModulusUsed) >=
  +        0) {
  +      _BigIntImpl._absSub(
  +          xDigits, xUsed, _modulusDigits, _normModulusUsed, xDigits);
  +    }
  +    // Clamp x.
  +    while (xUsed > 0 && xDigits[xUsed - 1] == 0) {
  +      --xUsed;
  +    }
  +    return xUsed;
  +  }
  +
  +  int _sqr(Uint32List xDigits, int xUsed, Uint32List resultDigits) {
  +    var resultUsed = _BigIntImpl._sqrDigits(xDigits, xUsed, resultDigits);
  +    return _reduce(resultDigits, resultUsed);
  +  }
  +
  +  int _mul(Uint32List xDigits, int xUsed, Uint32List yDigits, int yUsed,
  +      Uint32List resultDigits) {
  +    var resultUsed =
  +        _BigIntImpl._mulDigits(xDigits, xUsed, yDigits, yUsed, resultDigits);
  +    return _reduce(resultDigits, resultUsed);
  +  }
  +}
  +
   // Modular reduction using "classic" algorithm.
  -class _BigIntClassic implements _BigIntReduction {
  +class _BigIntClassicReduction implements _BigIntReduction {
     final _BigIntImpl _modulus; // Modulus.
  -  final _BigIntImpl _normalizedModulus; // Normalized _modulus.
  -
  -  _BigIntClassic(this._modulus)
  -      : _normalizedModulus = _modulus <<
  -            (_BigIntImpl._digitBits -
  -                _modulus._digits[_modulus._used - 1].bitLength);
  -
  -  int convert(_BigIntImpl x, Uint32List resultDigits) {
  +  int _normModulusUsed;
  +  _BigIntImpl _normModulus; // Normalized _modulus.
  +  Uint32List _normModulusDigits;
  +  Uint32List _negNormModulusDigits; // Negated _normModulus digits.
  +  int _modulusNsh; // Normalization shift amount.
  +  Uint32List _args; // Top _normModulus digit(s) and place holder for estimated
  +  // quotient digit(s).
  +  Uint32List _tmpDigits; // Temporary digits used during reduction.
  +
  +  _BigIntClassicReduction(this._modulus) {
  +    // Preprocess arguments to _remDigits.
  +    var nsh =
  +        _BigIntImpl._digitBits - _modulus._digits[_modulus._used - 1].bitLength;
  +    // For 64-bit processing, make sure _negNormModulusDigits has an even number
  +    // of digits.
  +    if (_modulus._used.isOdd) {
  +      nsh += _BigIntImpl._digitBits;
  +    }
  +    _modulusNsh = nsh;
  +    _normModulus = _modulus << nsh;
  +    _normModulusUsed = _normModulus._used;
  +    _normModulusDigits = _normModulus._digits;
  +    assert(_normModulusUsed.isEven);
  +    _args = _newDigits(4);
  +    _args[_BigIntImpl._divisorLowTopDigit] =
  +        _normModulusDigits[_normModulusUsed - 2];
  +    _args[_BigIntImpl._divisorTopDigit] =
  +        _normModulusDigits[_normModulusUsed - 1];
  +    // Negate _normModulus so we can use _mulAdd instead of
  +    // unimplemented  _mulSub.
  +    var negNormModulus =
  +        _BigIntImpl.one._dlShift(_normModulusUsed) - _normModulus;
  +    if (negNormModulus._used < _normModulusUsed) {
  +      _negNormModulusDigits = _BigIntImpl._cloneDigits(
  +          negNormModulus._digits, 0, _normModulusUsed, _normModulusUsed);
  +    } else {
  +      _negNormModulusDigits = negNormModulus._digits;
  +    }
  +    // _negNormModulusDigits is read-only and has _normModulusUsed digits (possibly
  +    // including several leading zeros) plus a leading zero for 64-bit
  +    // processing.
  +    _tmpDigits = _newDigits(2 * _normModulusUsed);
  +  }
  +
  +  int _convert(_BigIntImpl x, Uint32List resultDigits) {
       var digits;
       var used;
       if (x._isNegative || x.compareTo(_modulus) >= 0) {
  
positive.code:       used = x._used;
        digits = x._digits;
      }
      var i = used; // Copy leading zero if any.
      while (--i >= 0) {
        resultDigits[i] = digits[i];
      }
      return used;
    }
  
    _BigIntImpl revert(Uint32List xDigits, int xUsed) {
      return new _BigIntImpl._(false, xUsed, xDigits);
    }
  
  
negative.code:   ///
    /// The [source] (substring) must be a valid hex literal.
    static _BigIntImpl _parseHex(String source, int startPos, bool isNegative) {
      int hexCharsPerDigit = _digitBits ~/ 4;
      int sourceLength = source.length - startPos;
      int used = (sourceLength + hexCharsPerDigit - 1) ~/ hexCharsPerDigit;
      var digits = _newDigits(used);
  
      int lastDigitLength = sourceLength - (used - 1) * hexCharsPerDigit;
      int digitIndex = used - 1;
      int i = startPos;
      int digit = 0;
      for (int j = 0; j < lastDigitLength; j++) {
        var value = _codeUnitToRadixValue(source.codeUnitAt(i++));
        if (value >= 16) return null;
        digit = digit * 16 + value;
      }
      digits[digitIndex--] = digit;
  
      while (i < source.length) {
        digit = 0;
        for (int j = 0; j < hexCharsPerDigit; j++) {
          var value = _codeUnitToRadixValue(source.codeUnitAt(i++));
          if (value >= 16) return null;
          digit = digit * 16 + value;
        }
        digits[digitIndex--] = digit;
      }
      if (used == 1 && digits[0] == 0) return zero;
      return new _BigIntImpl._(isNegative, used, digits);
    }
  
    /// Parses the given [source] as a [radix] literal.
  