[llvm] [APInt] Restore multiplicativeInverse with explicit modulus and better testing (PR #87812)

Jay Foad via llvm-commits llvm-commits at lists.llvm.org
Sat Apr 6 00:42:29 PDT 2024


================
@@ -3258,6 +3258,54 @@ TEST(APIntTest, MultiplicativeInverseExaustive) {
   }
 }
 
+TEST(APIntTest, ModularMultiplicativeInverseSpecific) {
+  // Test a single modulus for all known inverses and non-inverses.
+  int BitWidth = 8;
+  APInt Modulus(BitWidth, 26);
+  int Values[12] = {1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25};
+  int Inverses[12] = {1, 9, 21, 15, 3, 19, 7, 23, 11, 5, 17, 25};
+  int NonInvertibleElements[14] = {0,  2,  4,  6,  8,  10, 12,
+                                   13, 14, 16, 18, 20, 22, 24};
+
+  for (size_t i = 0; i < 12; ++i) {
+    APInt V(BitWidth, Values[i]);
+    APInt Inv = V.multiplicativeInverse(Modulus);
+    EXPECT_EQ(Inv, Inverses[i]);
+  }
+
+  for (size_t i = 0; i < 14; ++i) {
+    APInt V(BitWidth, NonInvertibleElements[i]);
+    APInt Inv = V.multiplicativeInverse(Modulus);
+    EXPECT_EQ(Inv, 0);
+  }
+}
+
+TEST(APIntTest, ModularMultiplicativeInverseExaustive) {
+  // Test all moduli and all values up to 8 bits using a gcd test to determine
+  // if a multiplicative inverse exists.
+  int BitWidth = 8;
+  for (unsigned Modulus = 2; Modulus < (1u << BitWidth); ++Modulus) {
+    for (unsigned Value = 0; Value < Modulus; ++Value) {
+      APInt M(BitWidth, Modulus);
+      APInt V(BitWidth, Value);
+      EXPECT_TRUE(V.ult(M))
+          << "Expected " << V << " ult " << M << ", but it was not";
+      APInt MulInv = V.multiplicativeInverse(M);
+      if (APIntOps::GreatestCommonDivisor(V, M).isOne()) {
+        EXPECT_FALSE(MulInv.isZero());
----------------
jayfoad wrote:

Personally I wouldn't bother with this. If MulInv was zero there's no way the isOne test below could succeed.

https://github.com/llvm/llvm-project/pull/87812


More information about the llvm-commits mailing list