public static MutableInteger SetGreatestCommonDivisor(this MutableInteger c, MutableInteger a, MutableInteger b, MutableIntegerStore store) { var reg1 = store.Allocate(); if (a.IsZero) c.Set(b); else if (b.IsZero) c.Set(a); else { reg1.Set(a); c.Set(b); while (true) { reg1.Modulo(c); if (reg1.IsZero) break; c.Modulo(reg1); if (c.IsZero) { c.Set(reg1); break; } } } store.Release(reg1); return c; }
public static MutableInteger SetModularInverse(this MutableInteger c, MutableInteger a, MutableInteger b, MutableIntegerStore store) { var p = store.Allocate().Set(a); var q = store.Allocate().Set(b); var x0 = store.Allocate().Set(1); var x1 = store.Allocate().Set(0); var quotient = store.Allocate(); var remainder = store.Allocate(); var product = store.Allocate(); while (!q.IsZero) { remainder.Set(p).ModuloWithQuotient(q, quotient); var tmpp = p; p = q; q = tmpp.Set(remainder); var tmpx = x1; x1 = x0.Subtract(product.SetProduct(quotient, x1)); x0 = tmpx; } c.Set(x0); if (c.Sign == -1) c.Add(b); store.Release(p); store.Release(q); store.Release(x0); store.Release(x1); store.Release(quotient); store.Release(remainder); return c; }
public static MutableInteger SetModularInversePowerOfTwoModulus(this MutableInteger c, MutableInteger d, int n, MutableIntegerStore store) { // See 9.2 in: http://gmplib.org/~tege/divcnst-pldi94.pdf c.Set(d); var two = store.Allocate().Set(2); var reg1 = store.Allocate(); var reg2 = store.Allocate(); for (int m = 3; m < n; m *= 2) { reg1.Set(c); reg2.SetProduct(reg1, d); reg2.Mask(n); reg2.SetDifference(two, reg2); c.SetProduct(reg1, reg2); c.Mask(n); } if (c.Sign == -1) c.Add(reg1.Set(1).LeftShift(n)); store.Release(two); store.Release(reg1); store.Release(reg2); return c; }
private int TauSumInnerWorkerLarge(UInt128 y, ulong imin, ulong imax) { #if false var sum = (uint)0; for (var i = imin; i < imax; i++) sum ^= (uint)(y / i); return (int)(sum & 1); #endif #if false var yRep = (MutableInteger)y; var xRep = yRep.Copy(); var iRep = (MutableInteger)imin; var store = new MutableIntegerStore(4); var sum = (uint)0; for (var i = imin; i < imax; i++) { sum ^= xRep.Set(yRep).Divide(iRep, store).LeastSignificantWord; iRep.Increment(); } return (int)(sum & 1); #endif #if false // The quantity floor(y/d) is odd iff y mod 2d >= d. var sum = (ulong)0; for (var i = imin; i < imax; i++) sum ^= y % (i << 1) - i; sum >>= 63; if (((imax - imin) & 1) != 0) sum ^= 1; return (int)(sum & 1); #endif #if false if (y.IsPowerOfTwo) { var uBits = y.GetBitLength() - 32; var sum = (uint)0; var y0 = (UInt128)y.LeastSignificantWord; var y12 = (ulong)(y >> 32); for (var i = imin; i < imax; i++) { var y12mod = y12 % i; var yPrime = y0 + ((y12 % i) << 32); var shift = 64 - i.GetBitCount(); sum ^= (uint)(y / i); } return (int)(sum & 1); } #endif #if false var sum = (uint)0; var i = imax - 1; var current = (ulong)(y / (i + 1)); var delta = (ulong)(y / i - current); var mod = (long)(y - (UInt128)current * (i + 1)); var imid = Math.Max(imin, (ulong)(y >> (64 - safetyBits))); while (i >= imid) { mod += (long)(current - delta * i); current += delta; if (mod >= (long)i) { ++delta; ++current; mod -= (long)i; if (mod >= (long)i) break; } else if (mod < 0) { --delta; --current; mod += (long)i; } Debug.Assert(y / i == current); sum ^= (uint)current; --i; } while (i >= imin) { sum ^= (uint)(y / i); --i; } return (int)(sum & 1); #endif #if true var sum = (uint)0; var i = imax - 1; var current = (ulong)(y / (i + 1)); var delta = (ulong)(y / i) - current; var mod = (long)(y - (UInt128)current * (i + 1)); var imid = Math.Max(imin, (ulong)(y >> (64 - safetyBits))); var deltai = delta * (i + 1); while (i >= imid) { deltai -= delta; mod += (long)(current - deltai); if (mod >= (long)i) { ++delta; deltai += i; mod -= (long)i; if (mod >= (long)i) break; } else if (mod < 0) { --delta; deltai -= i; mod += (long)i; } current += delta; Debug.Assert(y / i == current); sum ^= (uint)current; --i; } while (i >= imin) { sum ^= (uint)(y / i); --i; } return (int)(sum & 1); #endif }