congruence_solver 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -18,129 +18,129 @@ static int NEXT_INTEGER = FIRST_PRIME;
18
18
 
19
19
 
20
20
  int * primes(int length){
21
- int * rtrn_list = calloc(length, sizeof(int));
21
+ int * rtrn_list = calloc(length, sizeof(int));
22
22
 
23
- expand_prime_list_to_length(length);
23
+ expand_prime_list_to_length(length);
24
24
 
25
- if(rtrn_list != NULL){
26
- memcpy(rtrn_list, PRIME_LIST, length*sizeof(int));
27
- }
25
+ if(rtrn_list != NULL){
26
+ memcpy(rtrn_list, PRIME_LIST, length*sizeof(int));
27
+ }
28
28
 
29
- return rtrn_list;
29
+ return rtrn_list;
30
30
  }
31
31
 
32
32
 
33
33
  int * primes_upto(int max){
34
- int * rtrn_list;
35
- int i;
34
+ int * rtrn_list;
35
+ int i;
36
36
 
37
- expand_prime_list_past(max);
37
+ expand_prime_list_past(max);
38
38
 
39
- for(i = PRIME_LIST_LENGTH; i > 0; i--){
40
- if(PRIME_LIST[i-1] <= max){
41
- rtrn_list = calloc(i+1, sizeof(int));
42
- rtrn_list[0] = i;
43
- memcpy(rtrn_list+1, PRIME_LIST, i*sizeof(int));
44
- return rtrn_list;
45
- }
46
- }
39
+ for(i = PRIME_LIST_LENGTH; i > 0; i--){
40
+ if(PRIME_LIST[i-1] <= max){
41
+ rtrn_list = calloc(i+1, sizeof(int));
42
+ rtrn_list[0] = i;
43
+ memcpy(rtrn_list+1, PRIME_LIST, i*sizeof(int));
44
+ return rtrn_list;
45
+ }
46
+ }
47
47
 
48
- return NULL;
48
+ return NULL;
49
49
  }
50
50
 
51
51
 
52
52
  int * prime_factors(int n){
53
- int * rtrn_list = malloc(sizeof(int));
54
- int rtrn_list_length = 0;
55
- int least_div;
53
+ int * rtrn_list = malloc(sizeof(int));
54
+ int rtrn_list_length = 0;
55
+ int least_div;
56
56
 
57
- while(n != 1){
58
- least_div = least_divisor(n);
59
- rtrn_list = realloc(rtrn_list, (rtrn_list_length+2)*sizeof(int));
60
- rtrn_list[++rtrn_list_length] = least_div;
57
+ while(n != 1){
58
+ least_div = least_divisor(n);
59
+ rtrn_list = realloc(rtrn_list, (rtrn_list_length+2)*sizeof(int));
60
+ rtrn_list[++rtrn_list_length] = least_div;
61
61
 
62
- if(least_div == n){
63
- break;
64
- }
62
+ if(least_div == n){
63
+ break;
64
+ }
65
65
 
66
- while(n % least_div == 0){
67
- n /= least_div;
68
- }
69
- }
66
+ while(n % least_div == 0){
67
+ n /= least_div;
68
+ }
69
+ }
70
70
 
71
- rtrn_list[0] = rtrn_list_length;
71
+ rtrn_list[0] = rtrn_list_length;
72
72
 
73
- return rtrn_list;
73
+ return rtrn_list;
74
74
  }
75
75
 
76
76
 
77
77
  static int least_divisor(int n){
78
- //Calculate maximum for least divisor (sqrt)
79
- int least_div_max = sqrt(n) + 1;
80
- int i;
81
- //Expand prime list up to the least divisor
82
- expand_prime_list_past(least_div_max);
78
+ //Calculate maximum for least divisor (sqrt)
79
+ int least_div_max = sqrt(n) + 1;
80
+ int i;
81
+ //Expand prime list up to the least divisor
82
+ expand_prime_list_past(least_div_max);
83
83
 
84
84
 
85
- for(i = 0; PRIME_LIST[i] < least_div_max; i++){
86
- if(n % PRIME_LIST[i] == 0){
87
- return PRIME_LIST[i];
88
- }
89
- }
85
+ for(i = 0; PRIME_LIST[i] < least_div_max; i++){
86
+ if(n % PRIME_LIST[i] == 0){
87
+ return PRIME_LIST[i];
88
+ }
89
+ }
90
90
 
91
- return n;
91
+ return n;
92
92
  }
93
93
 
94
94
 
95
95
  static void expand_prime_list_to_length(int length){
96
96
 
97
- if(PRIME_LIST_MAX_LENGTH < length){
98
- PRIME_LIST_MAX_LENGTH = 2*length;
99
- PRIME_LIST = realloc(PRIME_LIST, PRIME_LIST_MAX_LENGTH*sizeof(int));
100
- }
97
+ if(PRIME_LIST_MAX_LENGTH < length){
98
+ PRIME_LIST_MAX_LENGTH = 2*length;
99
+ PRIME_LIST = realloc(PRIME_LIST, PRIME_LIST_MAX_LENGTH*sizeof(int));
100
+ }
101
101
 
102
- while(PRIME_LIST_LENGTH < length){
103
- if( !any_divisors(PRIME_LIST, PRIME_LIST_LENGTH, NEXT_INTEGER) ){
104
- PRIME_LIST[PRIME_LIST_LENGTH++] = NEXT_INTEGER;
105
- }
102
+ while(PRIME_LIST_LENGTH < length){
103
+ if( !any_divisors(PRIME_LIST, PRIME_LIST_LENGTH, NEXT_INTEGER) ){
104
+ PRIME_LIST[PRIME_LIST_LENGTH++] = NEXT_INTEGER;
105
+ }
106
106
 
107
- NEXT_INTEGER++;
108
- }
107
+ NEXT_INTEGER++;
108
+ }
109
109
 
110
110
  }
111
111
 
112
112
 
113
113
  static void expand_prime_list_past(int max){
114
- if(PRIME_LIST == NULL){
115
- //TODO: find better heuristic limit on memory necessary to allocate
116
- PRIME_LIST_MAX_LENGTH = (max/2) + 1;
117
- PRIME_LIST = calloc(PRIME_LIST_MAX_LENGTH, sizeof(int));
118
- PRIME_LIST[0] = NEXT_INTEGER++;
119
- PRIME_LIST_LENGTH = 1;
120
- }
121
-
122
- while(PRIME_LIST[PRIME_LIST_LENGTH-1] <= max){
123
- while(any_divisors(PRIME_LIST, PRIME_LIST_LENGTH, NEXT_INTEGER) ){
124
- NEXT_INTEGER++;
125
- }
126
-
127
- if( PRIME_LIST_MAX_LENGTH <= PRIME_LIST_LENGTH){
128
- PRIME_LIST_MAX_LENGTH *= 2;
129
- PRIME_LIST = realloc(PRIME_LIST, PRIME_LIST_MAX_LENGTH*sizeof(int));
130
- }
131
-
132
- PRIME_LIST[PRIME_LIST_LENGTH++] = NEXT_INTEGER;
133
- }
114
+ if(PRIME_LIST == NULL){
115
+ //TODO: find better heuristic limit on memory necessary to allocate
116
+ PRIME_LIST_MAX_LENGTH = (max/2) + 1;
117
+ PRIME_LIST = calloc(PRIME_LIST_MAX_LENGTH, sizeof(int));
118
+ PRIME_LIST[0] = NEXT_INTEGER++;
119
+ PRIME_LIST_LENGTH = 1;
120
+ }
121
+
122
+ while(PRIME_LIST[PRIME_LIST_LENGTH-1] <= max){
123
+ while(any_divisors(PRIME_LIST, PRIME_LIST_LENGTH, NEXT_INTEGER) ){
124
+ NEXT_INTEGER++;
125
+ }
126
+
127
+ if( PRIME_LIST_MAX_LENGTH <= PRIME_LIST_LENGTH){
128
+ PRIME_LIST_MAX_LENGTH *= 2;
129
+ PRIME_LIST = realloc(PRIME_LIST, PRIME_LIST_MAX_LENGTH*sizeof(int));
130
+ }
131
+
132
+ PRIME_LIST[PRIME_LIST_LENGTH++] = NEXT_INTEGER;
133
+ }
134
134
  }
135
135
 
136
136
 
137
137
  static int any_divisors(int * div_list, int length, int num){
138
- int i;
139
- for(i = 0; i < length; i++){
140
- if(num % div_list[i] == 0){
141
- return 1;
142
- }
143
- }
144
-
145
- return 0;
138
+ int i;
139
+ for(i = 0; i < length; i++){
140
+ if(num % div_list[i] == 0){
141
+ return 1;
142
+ }
143
+ }
144
+
145
+ return 0;
146
146
  }
@@ -1,5 +1,5 @@
1
1
  #define NUM_OF_MOD_INV_TESTS 4
2
- #define NUM_OF_MOD_PRODUCT_TESTS 4
2
+ #define NUM_OF_MOD_PRODUCT_TESTS 3
3
3
  #define NUM_OF_MOD_POWER_TESTS 4
4
4
  #define NUM_OF_COPRIME_TESTS 5
5
5
  #define NUM_OF_TOTIENT_TESTS 6
@@ -11,15 +11,15 @@ int TOTIENT_EVALS[NUM_OF_TOTIENT_TESTS] = {1, 1, 2, 40, 100, 3680};
11
11
  int COPRIME_NUM_PAIRS[NUM_OF_COPRIME_TESTS][2] = {{3,5}, {9, 28}, {100, 34}, {1000512415, 557825}, {2286144, 1515839}};
12
12
  int COPRIME_EVALS[NUM_OF_COPRIME_TESTS] = {1, 1, 0, 0, 1};
13
13
 
14
- int MOD_PRODUCT_NUM_PAIRS[NUM_OF_MOD_PRODUCT_TESTS][2] = {{5,6}, {41,3}, {16, 98}, {105, 203}};
15
- int MOD_PRODUCT_MODS[NUM_OF_MOD_PRODUCT_TESTS] = {10, 8, 19, 98};
16
- int MOD_PRODUCT_PRODUCTS[NUM_OF_MOD_PRODUCT_TESTS] = {0, 3, 10, 49};
14
+ int MOD_PRODUCT_NUM_PAIRS[NUM_OF_MOD_PRODUCT_TESTS][2] = {{5,6}, {41,3}, {16, 3}};
15
+ int MOD_PRODUCT_MODS[NUM_OF_MOD_PRODUCT_TESTS] = {10, 8, 19};
16
+ int MOD_PRODUCT_PRODUCTS[NUM_OF_MOD_PRODUCT_TESTS] = {0, 3, 10};
17
17
 
18
- int MOD_INV_NUMS[NUM_OF_MOD_INV_TESTS] = {5, 4, 53, 129};
18
+ int MOD_INV_NUMS[NUM_OF_MOD_INV_TESTS] = {5, 4, 53, 3};
19
19
  int MOD_INV_MODS[NUM_OF_MOD_INV_TESTS] = {12, 23, 105, 7};
20
20
  int MOD_INV_INVS[NUM_OF_MOD_INV_TESTS] = {5, 6, 2, 5};
21
21
 
22
- int MOD_POWER_NUMS[NUM_OF_MOD_POWER_TESTS] = {5, 19, 41, 100};
22
+ int MOD_POWER_NUMS[NUM_OF_MOD_POWER_TESTS] = {3, 19, 6, 7};
23
23
  int MOD_POWER_MODS[NUM_OF_MOD_POWER_TESTS] = {4, 23, 7, 33};
24
24
  int MOD_POWER_POWERS[NUM_OF_MOD_POWER_TESTS] = {10, 3, 4, 635};
25
- int MOD_POWER_EVALS[NUM_OF_MOD_POWER_TESTS] ={1, 5, 1, 1};
25
+ int MOD_POWER_EVALS[NUM_OF_MOD_POWER_TESTS] ={1, 5, 1, 10};
@@ -13,7 +13,7 @@ int main(){
13
13
  failures += solve_congruence_test(POL_3_DEGREE, POL_3_COEFFS, POL_3_MOD, NUM_OF_POL_3_SOLS, POL_3_SOLS);
14
14
  failures += solve_congruence_test(POL_4_DEGREE, POL_4_COEFFS, POL_4_MOD, NUM_OF_POL_4_SOLS, POL_4_SOLS);
15
15
  failures += solve_congruence_test(POL_5_DEGREE, POL_5_COEFFS, POL_5_MOD, NUM_OF_POL_5_SOLS, POL_5_SOLS);
16
-
16
+ failures += solve_congruence_test(POL_6_DEGREE, POL_6_COEFFS, POL_6_MOD, NUM_OF_POL_6_SOLS, POL_6_SOLS);
17
17
 
18
18
  return failures;
19
19
  }
@@ -54,7 +54,7 @@ int solve_congruence_test(int func_degree, int * func_coeffs, int mod, int num_o
54
54
 
55
55
  print_polynomial_inline(func_degree, func_coeffs);
56
56
 
57
- printf(" = 0: %d given instead of %d.\n\n", solutions_to_test[i+1], solutions[i]);
57
+ printf(" = 0 (mod %d): %d given instead of %d.\n\n", mod, solutions_to_test[i+1], solutions[i]);
58
58
 
59
59
  return 1;
60
60
  }
@@ -105,6 +105,24 @@
105
105
  #define POL_5_SOL_7 299584
106
106
  #define POL_5_SOL_8 313399
107
107
 
108
+ #define POL_6_DEGREE 5
109
+ #define POL_6_COEFF_0 1
110
+ #define POL_6_COEFF_1 2
111
+ #define POL_6_COEFF_2 1
112
+ #define POL_6_COEFF_3 -1
113
+ #define POL_6_COEFF_4 0
114
+ #define POL_6_COEFF_5 -3
115
+ #define POL_6_MOD 49
116
+ #define NUM_OF_POL_6_SOLS 8
117
+ #define POL_6_SOL_0 1
118
+ #define POL_6_SOL_1 8
119
+ #define POL_6_SOL_2 15
120
+ #define POL_6_SOL_3 22
121
+ #define POL_6_SOL_4 26
122
+ #define POL_6_SOL_5 29
123
+ #define POL_6_SOL_6 36
124
+ #define POL_6_SOL_7 43
125
+
108
126
 
109
127
  int POL_1_COEFFS[POL_1_DEGREE+1] = {POL_1_COEFF_0,
110
128
  POL_1_COEFF_1,
@@ -201,4 +219,21 @@ int POL_5_SOLS[NUM_OF_POL_5_SOLS] = {POL_5_SOL_0,
201
219
  POL_5_SOL_5,
202
220
  POL_5_SOL_6,
203
221
  POL_5_SOL_7,
204
- POL_5_SOL_8};
222
+ POL_5_SOL_8};
223
+
224
+ int POL_6_COEFFS[POL_6_DEGREE+1] = {POL_6_COEFF_0,
225
+ POL_6_COEFF_1,
226
+ POL_6_COEFF_2,
227
+ POL_6_COEFF_3,
228
+ POL_6_COEFF_4,
229
+ POL_6_COEFF_5
230
+ };
231
+
232
+ int POL_6_SOLS[NUM_OF_POL_6_SOLS] = {POL_6_SOL_0,
233
+ POL_6_SOL_1,
234
+ POL_6_SOL_2,
235
+ POL_6_SOL_3,
236
+ POL_6_SOL_4,
237
+ POL_6_SOL_5,
238
+ POL_6_SOL_6,
239
+ POL_6_SOL_7};
@@ -1,3 +1,3 @@
1
1
  module CongruenceSolver
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.1"
3
3
  end
@@ -1,116 +1,116 @@
1
1
  class PolynomialInterpreter
2
- module Errors
3
- POLYNOMIAL_INVALID = ArgumentError.new "polynomial invalid"
4
- CONGRUENCE_INVALID = ArgumentError.new "congruence invalid"
5
- LHS_POLYNOMIAL_INVALID = ArgumentError.new "lhs polynomial invalid"
6
- RHS_POLYNOMIAL_INVALID = ArgumentError.new "rhs polynomial invalid"
7
- MOD_INVALID = ArgumentError.new "mod invalid"
8
- end
9
-
10
-
11
- def self.read_congruence(input_congruence)
12
- match_data = input_congruence.match(/^(.*)=(.*) +(?:mod +(.*)|\(mod +(.*)\))$/)
13
-
14
- if match_data.nil?
15
- raise Errors::CONGRUENCE_INVALID
16
- end
17
-
18
- lhs = match_data[1]
19
- rhs = match_data[2]
20
- mod = match_data[3] || match_data[4]
21
-
22
- begin
23
- lh_coeffs = read_coeffs(lhs.gsub(" ", ""))
24
- rescue ArgumentError => e
25
- if(e == Errors::POLYNOMIAL_INVALID)
26
- raise Errors::LHS_POLYNOMIAL_INVALID
27
- else
28
- raise e
29
- end
30
- end
31
-
32
- begin
33
- rh_coeffs = read_coeffs(rhs.gsub(" ", ""))
34
- rescue ArgumentError => e
35
- if e == Errors::POLYNOMIAL_INVALID
36
- raise Errors::RHS_POLYNOMIAL_INVALID
37
- else
38
- raise e
39
- end
40
- end
41
-
42
- if mod !~ /\d+/ or mod.to_i < 2
43
- raise Errors::MOD_INVALID
44
- end
45
-
46
- 0.upto rh_coeffs.length-1 do |idx|
47
- unless rh_coeffs[idx].nil?
48
- lh_coeffs[idx] ||= 0
49
- lh_coeffs[idx] -= rh_coeffs[idx]
50
- end
51
- end
52
-
53
- [lh_coeffs, mod.to_i]
54
- end
55
-
56
- def self.read_coeffs(input_polynomial)
57
- if input_polynomial == ""
58
- raise Errors::POLYNOMIAL_INVALID
59
- end
60
-
61
- last_var = nil
62
- coeffs = Array.new
63
-
64
- loop do
65
- input_polynomial.slice!(/^(\d+)\*?/)
66
- match_data_coe = Regexp.last_match
67
-
68
- input_polynomial.slice!(/^([a-zA-Z])(?:\^(\d+))?/)
69
- match_data_exp = Regexp.last_match
70
-
71
- if match_data_coe.nil? and match_data_exp.nil?
72
- raise ArgumentError, INVALID_POLYNOMIAL_MSG
73
- else
74
- if match_data_exp.nil?
75
- coe = match_data_coe[1].to_i
76
- exp = 0
77
- else
78
- unless last_var.nil? or last_var == match_data_exp[1]
79
- raise Errors::POLYNOMIAL_INVALID
80
- end
81
-
82
- last_var = match_data_exp[1]
83
-
84
- if match_data_coe.nil?
85
- coe = 1
86
- else
87
- coe = match_data_coe[1].to_i
88
- end
89
-
90
- if match_data_exp[2].nil?
91
- exp = 1
92
- else
93
- exp = match_data_exp[2].to_i
94
- end
95
- end
96
- end
97
-
98
- coeffs[exp] ||= 0
99
- coeffs[exp] += coe.to_i
100
-
101
- break if input_polynomial.length == 0
102
-
103
- op = input_polynomial.slice!(0)
104
-
105
- unless op.match /[-+]/
106
- raise Errors::POLYNOMIAL_INVALID
107
- end
108
- end
109
-
110
- 0.upto(coeffs.length-1) do |idx|
111
- coeffs[idx] ||= 0
112
- end
113
-
114
- coeffs
115
- end
2
+ module Errors
3
+ POLYNOMIAL_INVALID = ArgumentError.new "polynomial invalid"
4
+ CONGRUENCE_INVALID = ArgumentError.new "congruence invalid"
5
+ LHS_POLYNOMIAL_INVALID = ArgumentError.new "lhs polynomial invalid"
6
+ RHS_POLYNOMIAL_INVALID = ArgumentError.new "rhs polynomial invalid"
7
+ MOD_INVALID = ArgumentError.new "mod invalid"
8
+ end
9
+
10
+
11
+ def self.read_congruence(input_congruence)
12
+ match_data = input_congruence.match(/^(.*)=(.*) +(?:mod +(.*)|\(mod +(.*)\))$/)
13
+
14
+ if match_data.nil?
15
+ raise Errors::CONGRUENCE_INVALID
16
+ end
17
+
18
+ lhs = match_data[1]
19
+ rhs = match_data[2]
20
+ mod = match_data[3] || match_data[4]
21
+
22
+ begin
23
+ lh_coeffs = read_coeffs(lhs.gsub(" ", ""))
24
+ rescue ArgumentError => e
25
+ if(e == Errors::POLYNOMIAL_INVALID)
26
+ raise "#{lhs}:#{Errors::RHS_POLYNOMIAL_INVALID}"
27
+ else
28
+ raise e
29
+ end
30
+ end
31
+
32
+ begin
33
+ rh_coeffs = read_coeffs(rhs.gsub(" ", ""))
34
+ rescue ArgumentError => e
35
+ if e == Errors::POLYNOMIAL_INVALID
36
+ raise "#{rhs}:#{Errors::RHS_POLYNOMIAL_INVALID}"
37
+ else
38
+ raise e
39
+ end
40
+ end
41
+
42
+ if mod !~ /\d+/ or mod.to_i < 2
43
+ raise Errors::MOD_INVALID
44
+ end
45
+
46
+ 0.upto rh_coeffs.length-1 do |idx|
47
+ unless rh_coeffs[idx].nil?
48
+ lh_coeffs[idx] ||= 0
49
+ lh_coeffs[idx] -= rh_coeffs[idx]
50
+ end
51
+ end
52
+
53
+ [lh_coeffs, mod.to_i]
54
+ end
55
+
56
+ def self.read_coeffs(input_polynomial)
57
+ if input_polynomial == ""
58
+ raise Errors::POLYNOMIAL_INVALID
59
+ end
60
+
61
+ last_var = nil
62
+ coeffs = Array.new
63
+
64
+ loop do
65
+ input_polynomial.slice!(/^(\d+)\*?/)
66
+ match_data_coe = Regexp.last_match
67
+
68
+ input_polynomial.slice!(/^([a-zA-Z])(?:\^(\d+))?/)
69
+ match_data_exp = Regexp.last_match
70
+
71
+ if match_data_coe.nil? and match_data_exp.nil?
72
+ raise Errors::POLYNOMIAL_INVALID
73
+ else
74
+ if match_data_exp.nil?
75
+ coe = match_data_coe[1].to_i
76
+ exp = 0
77
+ else
78
+ unless last_var.nil? or last_var == match_data_exp[1]
79
+ raise Errors::POLYNOMIAL_INVALID
80
+ end
81
+
82
+ last_var = match_data_exp[1]
83
+
84
+ if match_data_coe.nil?
85
+ coe = 1
86
+ else
87
+ coe = match_data_coe[1].to_i
88
+ end
89
+
90
+ if match_data_exp[2].nil?
91
+ exp = 1
92
+ else
93
+ exp = match_data_exp[2].to_i
94
+ end
95
+ end
96
+ end
97
+
98
+ coeffs[exp] ||= 0
99
+ coeffs[exp] += coe.to_i
100
+
101
+ break if input_polynomial.length == 0
102
+
103
+ op = input_polynomial.slice!(0)
104
+
105
+ unless op.match /[-+]/
106
+ raise Errors::POLYNOMIAL_INVALID
107
+ end
108
+ end
109
+
110
+ 0.upto(coeffs.length-1) do |idx|
111
+ coeffs[idx] ||= 0
112
+ end
113
+
114
+ coeffs
115
+ end
116
116
  end
@@ -1,38 +1,38 @@
1
1
  require "congruence_solver"
2
2
 
3
3
  RSpec.describe CongruenceSolver do
4
- describe "::lift" do
5
- it "expects 3 arguments" do
6
- expect {CongruenceSolver.lift()}.to raise_error ArgumentError
7
- expect {CongruenceSolver.lift(0)}.to raise_error ArgumentError
8
- expect {CongruenceSolver.lift([1,2], 3)}.not_to raise_error
9
- expect {CongruenceSolver.lift([1], [1], nil)}.to raise_error ArgumentError
10
- end
11
-
12
-
13
- it "solves individual polynomial congruences defined by their coefficients and mod" do
14
- coeffs = [-1, 0, 4]
15
- mod = 5
16
- expect(CongruenceSolver.lift(coeffs, mod).sort).to eq [2, 3]
17
-
18
- coeffs = [-3, 4, 9]
19
- mod = 49
20
- expect(CongruenceSolver.lift(coeffs, mod).sort).to eq []
21
-
22
- coeffs = [1, -4, 4]
23
- mod = 5104
24
- expect(CongruenceSolver.lift(coeffs, mod).sort).to eq []
25
-
26
- coeffs = [4, -4, 1]
27
- mod = 5104
28
- expect(CongruenceSolver.lift(coeffs, mod).sort).to eq [2, 1278, 2554, 3830]
29
-
30
- coeffs = Array.new(500, 0)
31
- coeffs[0] = -1
32
- coeffs[500] = 1
33
- mod = 15
34
- expect(CongruenceSolver.lift(coeffs, mod).sort).to eq [1, 2, 4, 7, 8, 11, 13, 14]
35
- end
36
-
37
- end
4
+ describe "::lift" do
5
+ it "expects 3 arguments" do
6
+ expect {CongruenceSolver.lift()}.to raise_error ArgumentError
7
+ expect {CongruenceSolver.lift(0)}.to raise_error ArgumentError
8
+ expect {CongruenceSolver.lift([1,2], 3)}.not_to raise_error
9
+ expect {CongruenceSolver.lift([1], [1], nil)}.to raise_error ArgumentError
10
+ end
11
+
12
+
13
+ it "solves individual polynomial congruences defined by their coefficients and mod" do
14
+ coeffs = [-1, 0, 4]
15
+ mod = 5
16
+ expect(CongruenceSolver.lift(coeffs, mod).sort).to eq [2, 3]
17
+
18
+ coeffs = [-3, 4, 9]
19
+ mod = 49
20
+ expect(CongruenceSolver.lift(coeffs, mod).sort).to eq []
21
+
22
+ coeffs = [1, -4, 4]
23
+ mod = 5104
24
+ expect(CongruenceSolver.lift(coeffs, mod).sort).to eq []
25
+
26
+ coeffs = [4, -4, 1]
27
+ mod = 5104
28
+ expect(CongruenceSolver.lift(coeffs, mod).sort).to eq [2, 1278, 2554, 3830]
29
+
30
+ coeffs = Array.new(500, 0)
31
+ coeffs[0] = -1
32
+ coeffs[500] = 1
33
+ mod = 15
34
+ expect(CongruenceSolver.lift(coeffs, mod).sort).to eq [1, 2, 4, 7, 8, 11, 13, 14]
35
+ end
36
+
37
+ end
38
38
  end