summaryrefslogtreecommitdiff
blob: 559cbe51fb281598a72aca2c6a89fa485a6c7f94 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
From a7f911140e7d0a0125653a40aa2c5fe257bd78f5 Mon Sep 17 00:00:00 2001
From: Fredrik Johansson <fredrik.johansson@gmail.com>
Date: Thu, 18 Sep 2014 14:49:05 +0200
Subject: [PATCH] redefine fmpz_invmod to consider any integer invertible mod 1
 (for gmp 6.0 compatibility)

---
 fmpz/doc/fmpz.txt    |  3 ++-
 fmpz/invmod.c        | 11 +++++++++--
 fmpz/test/t-invmod.c | 21 +++++++++++++++++----
 3 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/fmpz/doc/fmpz.txt b/fmpz/doc/fmpz.txt
index fb422d8..2ada719 100644
--- a/fmpz/doc/fmpz.txt
+++ b/fmpz/doc/fmpz.txt
@@ -899,7 +899,8 @@ int fmpz_invmod(fmpz_t f, const fmpz_t g, const fmpz_t h)
     Sets $f$ to the inverse of $g$ modulo $h$.  The value of $h$ may 
     not be $0$ otherwise an exception results.  If the inverse exists 
     the return value will be non-zero, otherwise the return value will
-    be $0$ and the value of $f$ undefined. 
+    be $0$ and the value of $f$ undefined. As a special case, we
+    consider any number invertible modulo $h = \pm 1$, with inverse 0.
 
 void fmpz_negmod(fmpz_t f, const fmpz_t g, const fmpz_t h)
 
diff --git a/fmpz/invmod.c b/fmpz/invmod.c
index a0cf601..0e20f39 100644
--- a/fmpz/invmod.c
+++ b/fmpz/invmod.c
@@ -67,7 +67,11 @@ fmpz_invmod(fmpz_t f, const fmpz_t g, const fmpz_t h)
             if (c2 < WORD(0))
                 c2 = -c2;
             if (c2 == WORD(1))
-                return 0;       /* special case not handled by n_invmod */
+            {
+                fmpz_zero(f);
+                return 1;       /* special case not handled by n_invmod */
+            }
+
             gcd = z_gcdinv(&inv, c1, c2);
 
             return (gcd == UWORD(1) ? fmpz_set_si(f, inv), 1 : 0);
@@ -106,7 +110,10 @@ fmpz_invmod(fmpz_t f, const fmpz_t g, const fmpz_t h)
             if (c2 < WORD(0))
                 c2 = -c2;
             if (c2 == WORD(1))
-                return 0;       /* special case not handled by z_gcd_invert */
+            {
+                fmpz_zero(f);
+                return 1;       /* special case not handled by z_gcd_invert */
+            }
             /* reduce g mod h first */
 
             r = flint_mpz_fdiv_ui(COEFF_TO_PTR(c1), c2);
diff --git a/fmpz/test/t-invmod.c b/fmpz/test/t-invmod.c
index aea236e..8ff1c7f 100644
--- a/fmpz/test/t-invmod.c
+++ b/fmpz/test/t-invmod.c
@@ -30,6 +30,19 @@
 #include "ulong_extras.h"
 #include "fmpz.h"
 
+/* Use the definiton of GMP versions >= 6.0 */
+int
+mpz_invert2(mpz_t a, const mpz_t b, const mpz_t c)
+{
+    if (mpz_cmpabs_ui(c, 1) == 0)
+    {
+        mpz_set_ui(a, 0);
+        return 1;
+    }
+    else
+        return mpz_invert(a, b, c);
+}
+
 int
 main(void)
 {
@@ -63,7 +76,7 @@ main(void)
         fmpz_get_mpz(e, b);
 
         r1 = fmpz_invmod(c, a, b);
-        r2 = mpz_invert(f, d, e);
+        r2 = mpz_invert2(f, d, e);
 
         fmpz_get_mpz(g, c);
 
@@ -106,7 +119,7 @@ main(void)
         fmpz_get_mpz(d, a);
 
         r1 = fmpz_invmod(c, a, a);
-        r2 = mpz_invert(f, d, d);
+        r2 = mpz_invert2(f, d, d);
 
         fmpz_get_mpz(g, c);
 
@@ -149,7 +162,7 @@ main(void)
         fmpz_get_mpz(e, b);
 
         r1 = fmpz_invmod(a, a, b);
-        r2 = mpz_invert(f, d, e);
+        r2 = mpz_invert2(f, d, e);
 
         fmpz_get_mpz(g, a);
 
@@ -192,7 +205,7 @@ main(void)
         fmpz_get_mpz(e, b);
 
         r1 = fmpz_invmod(b, a, b);
-        r2 = mpz_invert(f, d, e);
+        r2 = mpz_invert2(f, d, e);
 
         fmpz_get_mpz(g, b);