private static void _Mul(ref BigInt C, ref BigInt B1, ref BigInt B2, signt ResultSign) { ulong Tmp; B2 = (BigInt)B1.SameSize(B2); C.Resize((short)(2 * B1.Spart + 1)); for (int i = 0; i < B2.Spart; i++) { for (int j = 0; j < B1.Spart; j++) { ulong B1Val = B1.Value[j], B2Val = B2.Value[i]; Tmp = B1Val * B2Val; C.AddCell2((short)(i + j), Tmp); } } C.Sign = ResultSign; }
private static void _Add(ref BigInt C, BigInt B1, BigInt B2, signt ResultSign) { ulong Tmp, Over = 0; B2 = (BigInt)B1.SameSize(B2); C.Resize((short)(B1.Spart + 1)); for (int i = 0; i < B1.Spart; i++) { ulong B1Val = B1.Value[i], B2Val = B2.Value[i]; Tmp = B1Val + B2Val + Over; C.Value[i] = (uint)(Tmp & CELL_MASK); Over = (Tmp >> CELL_SIZE) & CELL_MASK; } C.Value[B1.Spart] = (uint)Over; C.Sign = ResultSign; }
private static void _MulKara(ref BigInt C, ref BigInt B1, ref BigInt B2, signt ResultSign) { short B1Spart = B1.Spart; short B2Spart = B2.Spart; B1.Reduce(); B2.Reduce(); B2 = (BigInt)B1.SameSize(B2); C.Resize((short)(2 * B1.Spart + 1)); if (B1.Spart <= SPART_LIMIT || ((B1Spart < SPART_LIMIT && (B2Spart - B1Spart) > SPART_LIMIT) || (B2Spart < SPART_LIMIT && (B1Spart - B2Spart) > SPART_LIMIT))) { _Mul(ref C, ref B1, ref B2, ResultSign); } else { B1.Reduce(); B2.Reduce(); short Part = B1.Spart < B2.Spart ? (short)(B1.Spart / 2) : (short)(B2.Spart / 2); //short PartCopy = Part; //while (PartCopy != 0 && PartCopy < (B1.Spart < B2.Spart ? B1.Spart : B2.Spart) && CELL_SIZE % PartCopy != 0) //{ // PartCopy++; //} //if (PartCopy != 0 && CELL_SIZE % PartCopy == 0) //{ // Part = PartCopy; //} //else //{ // PartCopy = Part; // while (PartCopy > 0 && CELL_SIZE % PartCopy != 0) // { // PartCopy--; // } // Part = PartCopy; //} B2 = (BigInt)B1.SameSize(B2); BigInt D = new BigInt(B1.Size, 0), E = new BigInt(B1.Size, 0); BigInt F = new BigInt(B1.Size, 0), G = new BigInt(B1.Size, 0); BigInt Z0 = new BigInt(B1.Size, 0), Z1 = new BigInt(B1.Size, 0), Z2 = new BigInt(B1.Size, 0); // C := Z2 * (Base ^ (2 * Part)) + (Z1 - Z2 - Z0) * (Base ^ Part) + Z0 B1.Split(ref D, ref E, Part); B2.Split(ref F, ref G, Part); // K = D + E // L = F + G BigInt K = D + E; BigInt L = F + G; // Z0 := E*G // Z1 := K*L // Z2 := D*F _MulKara(ref Z0, ref E, ref G, ResultSign); _MulKara(ref Z1, ref K, ref L, ResultSign); _MulKara(ref Z2, ref D, ref F, ResultSign); Z0.Reduce(); Z1.Reduce(); Z2.Reduce(); // Z2Copy = Z2 * (Base ^ (2 * Part)) BigInt Z2Copy = Z2.Clone(); for (int i = 0; i < 2 * Part; i++) { // Z2 * Base // Base = 2 ^ CELL_SIZE Z2Copy.ShiftLeft(CELL_SIZE); } // (Z1 - Z2 - Z0) * (Base ^ Part) BigInt ZDiff = Z1 - Z2 - Z0; for (int i = 0; i < Part; i++) { // ZDiff * Base // Base = 2 ^ CELL_SIZE ZDiff.ShiftLeft(CELL_SIZE); } C = Z2Copy + ZDiff + Z0; C.Reduce(); } }