Bonjour,
Je suis actuellement en-train de développer une API C++ pour les grands entiers, j'ai donc récupéré beaucoup de code sur le web en vu de produire un code le plus rapide possible. J'ai trouvé cet algorithme (en java) de calcul de l'inverse modulo qui marche très bien et qui est largement plus rapide que l'algorithme d'Euclide étendu.Source ici
J'aimerais bien en savoir un peu plus sur cette méthode, malheureusement le code n'est pas très lisible. Si quelqu'un reconnait la méthode utilisée, merci de poster un petit message...
Merci...
Code:/***********************************************************************/ /* NAME: ModInvBigNbr */ /* */ /* PURPOSE: Find the inverse multiplicative modulo v. */ /* */ /* The algorithm terminates with u1 = u^(-1) MOD v. */ /***********************************************************************/ void ModInvBigNbr(long[] a, long[] inv, long[] b, int NumberLength) { nbGCD++; int i; int Dif, E; int st1, st2; long Yaa, Yab; // 2^E * A' = Yaa A + Yab B long Yba, Ybb; // 2^E * B' = Yba A + Ybb B long Ygb0; // 2^E * Mu' = Yaa Mu + Yab Gamma + Ymb0 B0 long Ymb0; // 2^E * Gamma' = Yba Mu + Ybb Gamma + Ygb0 B0 int Iaa, Iab, Iba, Ibb; long Tmp1, Tmp2, Tmp3, Tmp4, Tmp5; int B0l; int invB0l; int Al, Bl, T1, Gl, Ml, P; long carry1, carry2, carry3, carry4; int Yaah, Yabh, Ybah, Ybbh; int Ymb0h, Ygb0h; long Pr1, Pr2, Pr3, Pr4, Pr5, Pr6, Pr7; long[] B = this.biTmp; long[] CalcAuxModInvA = this.CalcAuxGcdU; long[] CalcAuxModInvB = this.CalcAuxGcdV; long[] CalcAuxModInvMu = this.CalcAuxGcdT; // Cannot be inv long[] CalcAuxModInvGamma = inv; Convert31To32Bits(a, CalcAuxModInvA, NumberLength); Convert31To32Bits(b, CalcAuxModInvB, NumberLength); System.arraycopy(CalcAuxModInvB, 0, B, 0, NumberLength); B0l = (int)B[0]; invB0l = B0l; // 2 least significant bits of inverse correct. invB0l = invB0l * (2 - B0l * invB0l); // 4 LSB of inverse correct. invB0l = invB0l * (2 - B0l * invB0l); // 8 LSB of inverse correct. invB0l = invB0l * (2 - B0l * invB0l); // 16 LSB of inverse correct. invB0l = invB0l * (2 - B0l * invB0l); // 32 LSB of inverse correct. for (i = NumberLength - 1; i >= 0; i--) { CalcAuxModInvGamma[i] = 0; CalcAuxModInvMu[i] = 0; } CalcAuxModInvMu[0] = 1; Dif = 0; outer_loop : for (;;) { Iaa = Ibb = 1; Iab = Iba = 0; Al = (int) CalcAuxModInvA[0]; Bl = (int) CalcAuxModInvB[0]; E = 0; P = 1; if (Bl == 0) { for (i = NumberLength - 1; i >= 0; i--) { if (CalcAuxModInvB[i] != 0) break; } if (i < 0) break; // Go out of loop if CalcAuxModInvB = 0 } for (;;) { T1 = 0; while ((Bl & 1) == 0) { if (E == 31) { Yaa = Iaa; Yab = Iab; Yba = Iba; Ybb = Ibb; Gl = (int) CalcAuxModInvGamma[0]; Ml = (int) CalcAuxModInvMu[0]; Dif++; T1++; Yaa <<= T1; Yab <<= T1; Ymb0 = (- (int) Yaa * Ml - (int) Yab * Gl) * invB0l; Ygb0 = (-Iba * Ml - Ibb * Gl) * invB0l; carry1 = carry2 = carry3 = carry4 = 0; Yaah = (int) (Yaa >> 32); Yabh = (int) (Yab >> 32); Ybah = (int) (Yba >> 32); Ybbh = (int) (Ybb >> 32); Ymb0h = (int) (Ymb0 >> 32); Ygb0h = (int) (Ygb0 >> 32); Yaa &= 0xFFFFFFFFL; Yab &= 0xFFFFFFFFL; Yba &= 0xFFFFFFFFL; Ybb &= 0xFFFFFFFFL; Ymb0 &= 0xFFFFFFFFL; Ygb0 &= 0xFFFFFFFFL; st1 = Yaah * 6 + Yabh * 2 + Ymb0h; st2 = Ybah * 6 + Ybbh * 2 + Ygb0h; for (i = 0; i < NumberLength; i++) { Pr1 = Yaa * (Tmp1 = CalcAuxModInvMu[i]); Pr2 = Yab * (Tmp2 = CalcAuxModInvGamma[i]); Pr3 = Ymb0 * (Tmp3 = B[i]); Pr4 = (Pr1 & 0xFFFFFFFFL) + (Pr2 & 0xFFFFFFFFL) + (Pr3 & 0xFFFFFFFFL) + carry3; Pr5 = Yaa * (Tmp4 = CalcAuxModInvA[i]); Pr6 = Yab * (Tmp5 = CalcAuxModInvB[i]); Pr7 = (Pr5 & 0xFFFFFFFFL) + (Pr6 & 0xFFFFFFFFL) + carry1; switch (st1) { case -9 : carry3 = -Tmp1 - Tmp2 - Tmp3; carry1 = -Tmp4 - Tmp5; break; case -8 : carry3 = -Tmp1 - Tmp2; carry1 = -Tmp4 - Tmp5; break; case -7 : carry3 = -Tmp1 - Tmp3; carry1 = -Tmp4; break; case -6 : carry3 = -Tmp1; carry1 = -Tmp4; break; case -5 : carry3 = -Tmp1 + Tmp2 - Tmp3; carry1 = -Tmp4 + Tmp5; break; case -4 : carry3 = -Tmp1 + Tmp2; carry1 = -Tmp4 + Tmp5; break; case -3 : carry3 = -Tmp2 - Tmp3; carry1 = -Tmp5; break; case -2 : carry3 = -Tmp2; carry1 = -Tmp5; break; case -1 : carry3 = -Tmp3; carry1 = 0; break; case 0 : carry3 = 0; carry1 = 0; break; case 1 : carry3 = Tmp2 - Tmp3; carry1 = Tmp5; break; case 2 : carry3 = Tmp2; carry1 = Tmp5; break; case 3 : carry3 = Tmp1 - Tmp2 - Tmp3; carry1 = Tmp4 - Tmp5; break; case 4 : carry3 = Tmp1 - Tmp2; carry1 = Tmp4 - Tmp5; break; case 5 : carry3 = Tmp1 - Tmp3; carry1 = Tmp4; break; case 6 : carry3 = Tmp1; carry1 = Tmp4; break; case 7 : carry3 = Tmp1 + Tmp2 - Tmp3; carry1 = Tmp4 + Tmp5; break; case 8 : carry3 = Tmp1 + Tmp2; carry1 = Tmp4 + Tmp5; break; } carry3 += (Pr1 >>> 32) + (Pr2 >>> 32) + (Pr3 >>> 32) + (Pr4 >> 32); carry1 += (Pr5 >>> 32) + (Pr6 >>> 32) + (Pr7 >> 32); if (i > 0) { CalcAuxModInvMu[i - 1] = Pr4 & 0xFFFFFFFFL; CalcAuxModInvA[i - 1] = Pr7 & 0xFFFFFFFFL; } Pr1 = Yba * Tmp1; Pr2 = Ybb * Tmp2; Pr3 = Ygb0 * Tmp3; Pr4 = (Pr1 & 0xFFFFFFFFL) + (Pr2 & 0xFFFFFFFFL) + (Pr3 & 0xFFFFFFFFL) + carry4; Pr5 = Yba * Tmp4; Pr6 = Ybb * Tmp5; Pr7 = (Pr5 & 0xFFFFFFFFL) + (Pr6 & 0xFFFFFFFFL) + carry2; switch (st2) { case -9 : carry4 = -Tmp1 - Tmp2 - Tmp3; carry2 = -Tmp4 - Tmp5; break; case -8 : carry4 = -Tmp1 - Tmp2; carry2 = -Tmp4 - Tmp5; break; case -7 : carry4 = -Tmp1 - Tmp3; carry2 = -Tmp4; break; case -6 : carry4 = -Tmp1; carry2 = -Tmp4; break; case -5 : carry4 = -Tmp1 + Tmp2 - Tmp3; carry2 = -Tmp4 + Tmp5; break; case -4 : carry4 = -Tmp1 + Tmp2; carry2 = -Tmp4 + Tmp5; break; case -3 : carry4 = -Tmp2 - Tmp3; carry2 = -Tmp5; break; case -2 : carry4 = -Tmp2; carry2 = -Tmp5; break; case -1 : carry4 = -Tmp3; carry2 = 0; break; case 0 : carry4 = 0; carry2 = 0; break; case 1 : carry4 = Tmp2 - Tmp3; carry2 = Tmp5; break; case 2 : carry4 = Tmp2; carry2 = Tmp5; break; case 3 : carry4 = Tmp1 - Tmp2 - Tmp3; carry2 = Tmp4 - Tmp5; break; case 4 : carry4 = Tmp1 - Tmp2; carry2 = Tmp4 - Tmp5; break; case 5 : carry4 = Tmp1 - Tmp3; carry2 = Tmp4; break; case 6 : carry4 = Tmp1; carry2 = Tmp4; break; case 7 : carry4 = Tmp1 + Tmp2 - Tmp3; carry2 = Tmp4 + Tmp5; break; case 8 : carry4 = Tmp1 + Tmp2; carry2 = Tmp4 + Tmp5; break; } carry4 += (Pr1 >>> 32) + (Pr2 >>> 32) + (Pr3 >>> 32) + (Pr4 >> 32); carry2 += (Pr5 >>> 32) + (Pr6 >>> 32) + (Pr7 >> 32); if (i > 0) { CalcAuxModInvGamma[i - 1] = Pr4 & 0xFFFFFFFFL; CalcAuxModInvB[i - 1] = Pr7 & 0xFFFFFFFFL; } } if ((int) CalcAuxModInvA[i - 1] < 0) { carry1 -= Yaa; carry2 -= Yba; } if ((int) CalcAuxModInvB[i - 1] < 0) { carry1 -= Yab; carry2 -= Ybb; } if ((int) CalcAuxModInvMu[i - 1] < 0) { carry3 -= Yaa; carry4 -= Yba; } if ((int) CalcAuxModInvGamma[i - 1] < 0) { carry3 -= Yab; carry4 -= Ybb; } CalcAuxModInvA[i - 1] = carry1 & 0xFFFFFFFFL; CalcAuxModInvB[i - 1] = carry2 & 0xFFFFFFFFL; CalcAuxModInvMu[i - 1] = carry3 & 0xFFFFFFFFL; CalcAuxModInvGamma[i - 1] = carry4 & 0xFFFFFFFFL; continue outer_loop; } Bl >>= 1; Dif++; E++; P *= 2; T1++; } /* end while */ Iaa <<= T1; Iab <<= T1; if (Dif >= 0) { Dif = -Dif; if (((Al + Bl) & 3) == 0) { T1 = Iba; Iba += Iaa; Iaa = T1; T1 = Ibb; Ibb += Iab; Iab = T1; T1 = Bl; Bl += Al; Al = T1; } else { T1 = Iba; Iba -= Iaa; Iaa = T1; T1 = Ibb; Ibb -= Iab; Iab = T1; T1 = Bl; Bl -= Al; Al = T1; } } else { if (((Al + Bl) & 3) == 0) { Iba += Iaa; Ibb += Iab; Bl += Al; } else { Iba -= Iaa; Ibb -= Iab; Bl -= Al; } } Dif--; } } if (CalcAuxModInvA[0] != 1) { SubtractBigNbr32(B, CalcAuxModInvMu, CalcAuxModInvMu); } if ((int) CalcAuxModInvMu[i = NumberLength - 1] < 0) { AddBigNbr32(B, CalcAuxModInvMu, CalcAuxModInvMu); } for (; i >= 0; i--) { if (B[i] != CalcAuxModInvMu[i]) break; } if (i < 0 || B[i] < CalcAuxModInvMu[i]) { // If B < Mu SubtractBigNbr32(CalcAuxModInvMu, B, CalcAuxModInvMu); // Mu <- Mu - B } Convert32To31Bits(CalcAuxModInvMu, inv, NumberLength); }
-----