congruence_solver 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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