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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
//! Library implementing solvers for linear and quadratic modular equations.
//!
//! As it's described in Wikipedia, modular arithmetic is a system of arithmetic
//! where elements of the system (i.e., integers) wrap around after reaching
//! a specific boundary value called modulus.
//!
//! Before giving a concrete definition for such arithmetic system the following congruence
//! relation needs to be introduced: Given a positive integer n > 1, integer x is said
//! to be congruent to integer y, if n divides their difference (written mathematically
//! as n | (x - y)). In this case integers x and y are in a relation which is denoted
//! by x ≡ y (mod n) and importantly this relation is an equivalence relation.
//!
//! Modular arithmetic system is constructed such that the elements of it are so
//! called residue or congruence classes \[x\], where one class \[x\] is consisting
//! of all the integers congruent to x modulo n, or in other words all integers of
//! the form {..., x - n, x, x + n, ...} = {x + k * n}, k being any integer. Hence,
//! in principle, all of these integers {x + k * n} are valid representatives of
//! their residue class \[x\] but the common way is to use the smallest nonnegative
//! integer (modulo n) to represent the residue class. As the congruence relation
//! is an equivalence relation, every integer can belong to only one residue class.
//!
//! When listing all possible residue classes modulo n, {\[0\], \[1\], ..., \[n - 1\]},
//! and equipping this set with addition and multiplication operations (operations are
//! basically functions), the ring of integers modulo n is formed. This ring is commonly
//! denoted by Z/nZ where n represents the modulo. Mentioned binary operations are
//! well-defined due to the fact that the congruence relation is an equivalence relation.
//! If the modulo is a prime number, the ring becomes actually a field. These fields
//! are more easier to work with since every nonzero element has a multiplicative inverse.
//!
//! Now in the context of rings and fields, it's meaningful to speak of equations
//! and this library implements solvers for linear and quadratic equations. Linear modular
//! equations are generally much easier to solve than their quadratic counterparts.
//! Structs `LinEq` and `LinEqSigned` defines linear equation types and their `solve`
//! methods actually solve the equations. Similarly for quadratic case, structs
//! `QuadEq` and `QuadEqSigned` define equation types and their `solve` methods can
//! be used to actually solve the equations.
//!
//! Next follows few examples of linear equations of the form ax + b = c (mod n).
//!
//! ```
//! use modular_equations::LinEq;
//!
//! let lin_eq = LinEq::<u32> {
//! a: 13,
//! b: 17,
//! c: 5,
//! modu: 29,
//! };
//! let sol = lin_eq.solve();
//!
//! // Residue class [8] is the correct solution (smallest nonnegative member)
//! assert!(sol.is_some() && sol.unwrap()[0] == 8);
//! ```
//!
//! Following linear equation doesn't have solution
//!
//! ```
//! use modular_equations::LinEqSigned;
//!
//! let lin_eq = LinEqSigned::<i8, u8> {
//! a: -3,
//! b: -1,
//! c: 3,
//! modu: 9
//! };
//!
//! assert_eq!(lin_eq.solve(), None);
//! ```
//!
//! If any of the coefficients (a, b, ...) is signed, one must use the signed type equation
//! `LinEqSigned` as above. Modulo must always be unsigned type. Every negative integer
//! in the ring can be turned to the smallest nonnegative representative of the
//! corresponding residue class \[x\]. Related to this fact there are few technical
//! restrictions, the first being that the used signed type (e.g. i32) must have
//! the arith::SignCast trait implemented and that trait requires the signed and
//! unsigned types to be compatible (i.e., have the same size in bytes). In addition,
//! as the smallest negative integer of each type doesn't have an absolute value in
//! two's complement, they will trigger immediate None return value if used as coefficients
//! in linear or quadratic equations.
//!
//! One important use case for linear equations is to find multiplicative inverses as
//! the following example tries to do for 17 in Z/255Z
//!
//! ```
//! use modular_equations::LinEq;
//!
//! let lin_eq = LinEq::<u8> {a: 17, b: 0, c: 1, modu: u8::MAX};
//!
//! // 17 doesn't have multiplicative inverse in this case
//! assert_eq!(lin_eq.solve(), None);
//! ```
//!
//! As mentioned above, quadratic equations of the form ax^2 + bx + c = d (mod n)
//! are typically much harder to solve than their linear counterparts. In particular,
//! this is the case when the modulo is a composite number as this requires
//! factorization of the modulo to its prime factors and solving the equation for
//! each of these prime factors before combining the final solution using the
//! Chinese remainder theorem.
//!
//! Consider now an example of solving a quadratic modular equation. As the d
//! coefficient is negative, the signed equation type `QuadEqSigned` must be used.
//!
//! ```
//! use modular_equations::QuadEqSigned;
//!
//! let quad_eq = QuadEqSigned::<i64, u64> {
//! a: 1,
//! b: 1,
//! c: 1,
//! d: -1,
//! modu: 22,
//! };
//!
//! match quad_eq.solve() {
//! Some(sols) if sols.len() == 4 => {
//! // Correct solution consists of four residue classes
//! assert_eq!(sols, vec![4, 6, 15, 17]);
//! }
//! _ => assert!(false),
//! }
//! ```
//!
//! An important use case for quadratic equations is to check whether a specific
//! integer q is a quadratic residue meaning that there exists an integer x s.t.
//! x^2 ≡ q (mod n) holds. Following example considers a case where for a relatively
//! large prime modulo it is checked whether 1 is quadratic residue.
//!
//! ```
//! use modular_equations::QuadEq;
//!
//! let quad_eq = QuadEq::<u128> {
//! a: 1,
//! b: 0,
//! c: 0,
//! d: 1,
//! modu: 340_282_366_920_938_463_463_374_607_431_768_211_297,
//! };
//!
//! if let Some(x) = quad_eq.solve() {
//! // There should be two solutions `x`, thus q=1 is a quadratic residue
//! assert_eq!(x.len(), 2);
//! assert!(x[0] == 1 && x[1] == quad_eq.modu - 1);
//! } else {
//! assert!(false);
//! }
//! ```
//!
//! As a warning note, some equations have a huge amount of solutions and in these cases
//! the solver might slow down considerable or even panic when the solution count
//! exceeds usize::MAX. But these are really special cases and usually not very
//! much of interest.
//!
use ;
use ;
use Hash;
use ;
use ;
pub use ;
pub use ;