public object Clone() { LongPolynomial2 p = new LongPolynomial2((long[])coeffs.Clone()); p.numCoeffs = numCoeffs; return(p); }
/** * Subtracts another polynomial which must have the same number of coefficients, * and applies an AND mask to the upper and lower halves of each coefficients. * * @param b another polynomial * @param mask a bit mask less than 2048 to apply to each 11-bit coefficient */ public void SubAnd(LongPolynomial2 b, int mask) { long longMask = (((long)mask) << 24) + mask; for (int i = 0; i < b.coeffs.Length; i++) { coeffs[i] = (0x0800000800000L + coeffs[i] - b.coeffs[i]) & longMask; } }
/** * Subtracts another polynomial which can have a different number of coefficients. * * @param b another polynomial */ private void Sub(LongPolynomial2 b) { if (b.coeffs.Length > coeffs.Length) { Array.Copy(coeffs, coeffs, b.coeffs.Length); } for (int i = 0; i < b.coeffs.Length; i++) { coeffs[i] = (0x0800000800000L + coeffs[i] - b.coeffs[i]) & 0x7FF0007FFL; } }
/** * Adds another polynomial which can have a different number of coefficients. * * @param b another polynomial */ private void Add(LongPolynomial2 b) { if (b.coeffs.Length > coeffs.Length) { long[] temp = new long[b.coeffs.Length]; Array.Copy(coeffs, temp, coeffs.Length); coeffs = temp; } for (int i = 0; i < b.coeffs.Length; i++) { coeffs[i] = (coeffs[i] + b.coeffs[i]) & 0x7FF0007FFL; } }
/** * Computes the inverse mod q from the inverse mod 2 * * @param Fq * @param q * @return The inverse of this polynomial mod q */ private IntegerPolynomial Mod2ToModq(IntegerPolynomial Fq, int q) { //if (Util.is64BitJVM() && q == 2048) if (true && q == 2048) { LongPolynomial2 thisLong = new LongPolynomial2(this); LongPolynomial2 FqLong = new LongPolynomial2(Fq); int v = 2; while (v < q) { v *= 2; LongPolynomial2 temp = (LongPolynomial2)FqLong.Clone(); temp.mult2And(v - 1); FqLong = thisLong.Multiply(FqLong).Multiply(FqLong); temp.SubAnd(FqLong, v - 1); FqLong = temp; } return(FqLong.ToIntegerPolynomial()); } else { int v = 2; while (v < q) { v *= 2; int[] copy = new int[Fq.coeffs.Length]; Array.Copy(Fq.coeffs, copy, Fq.coeffs.Length); IntegerPolynomial temp = new IntegerPolynomial(copy); temp.Multiply2(v); Fq = Multiply(Fq, v).Multiply(Fq, v); temp.Sub(Fq, v); Fq = temp; } return(Fq); } }
/** * Karazuba multiplication */ private LongPolynomial2 MultiplyRecursive(LongPolynomial2 poly2) { long[] a = coeffs; long[] b = poly2.coeffs; int n = poly2.coeffs.Length; if (n <= 32) { int cn = 2 * n; LongPolynomial2 c = new LongPolynomial2(new long[cn]); for (int k = 0; k < cn; k++) { for (int i = System.Math.Max(0, k - n + 1); i <= System.Math.Min(k, n - 1); i++) { long c0 = a[k - i] * b[i]; long cu = c0 & 0x7FF000000L + (c0 & 2047); long co = (c0.UnsignedRightShift(48)) & 2047; //>>> 48 c.coeffs[k] = (c.coeffs[k] + cu) & 0x7FF0007FFL; c.coeffs[k + 1] = (c.coeffs[k + 1] + co) & 0x7FF0007FFL; } } return(c); } else { int n1 = n / 2; long[] a1Temp = new long[n1]; long[] a2Temp = new long[n - n1]; long[] b1Temp = new long[n1]; long[] b2Temp = new long[n - n1]; Array.Copy(a, a1Temp, n1); Array.Copy(a, n1, a2Temp, 0, n - n1); Array.Copy(b, b1Temp, n1); Array.Copy(b, n1, b2Temp, 0, n - n1); LongPolynomial2 a1 = new LongPolynomial2(a1Temp); LongPolynomial2 a2 = new LongPolynomial2(a2Temp); LongPolynomial2 b1 = new LongPolynomial2(b1Temp); LongPolynomial2 b2 = new LongPolynomial2(b2Temp); LongPolynomial2 A = (LongPolynomial2)a1.Clone(); A.Add(a2); LongPolynomial2 B = (LongPolynomial2)b1.Clone(); B.Add(b2); LongPolynomial2 c1 = a1.MultiplyRecursive(b1); LongPolynomial2 c2 = a2.MultiplyRecursive(b2); LongPolynomial2 c3 = A.MultiplyRecursive(B); c3.Sub(c1); c3.Sub(c2); LongPolynomial2 c = new LongPolynomial2(2 * n); for (int i = 0; i < c1.coeffs.Length; i++) { c.coeffs[i] = c1.coeffs[i] & 0x7FF0007FFL; } for (int i = 0; i < c3.coeffs.Length; i++) { c.coeffs[n1 + i] = (c.coeffs[n1 + i] + c3.coeffs[i]) & 0x7FF0007FFL; } for (int i = 0; i < c2.coeffs.Length; i++) { c.coeffs[2 * n1 + i] = (c.coeffs[2 * n1 + i] + c2.coeffs[i]) & 0x7FF0007FFL; } return(c); } }