congruence_solver 0.3.1 → 0.3.2

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.
@@ -1,146 +1,146 @@
1
- #include "prime_gen.h"
2
- #include <stdlib.h>
3
- #include <string.h>
4
- #include <stdio.h>
5
- #include <math.h>
6
-
7
- #define FIRST_PRIME 2
8
-
9
- static void expand_prime_list_to_length(int length);
10
- static void expand_prime_list_past(int max);
11
- static int any_divisors(int * div_list, int length, int num);
12
- static int least_divisor(int n);
13
-
14
- static int * PRIME_LIST = NULL;
15
- static int PRIME_LIST_LENGTH = 0;
16
- static int PRIME_LIST_MAX_LENGTH = 0;
17
- static int NEXT_INTEGER = FIRST_PRIME;
18
-
19
-
20
- int * primes(int length){
21
- int * rtrn_list = calloc(length, sizeof(int));
22
-
23
- expand_prime_list_to_length(length);
24
-
25
- if(rtrn_list != NULL){
26
- memcpy(rtrn_list, PRIME_LIST, length*sizeof(int));
27
- }
28
-
29
- return rtrn_list;
30
- }
31
-
32
-
33
- int * primes_upto(int max){
34
- int * rtrn_list;
35
- int i;
36
-
37
- expand_prime_list_past(max);
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
- }
47
-
48
- return NULL;
49
- }
50
-
51
-
52
- int * prime_factors(int n){
53
- int * rtrn_list = malloc(sizeof(int));
54
- int rtrn_list_length = 0;
55
- int least_div;
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;
61
-
62
- if(least_div == n){
63
- break;
64
- }
65
-
66
- while(n % least_div == 0){
67
- n /= least_div;
68
- }
69
- }
70
-
71
- rtrn_list[0] = rtrn_list_length;
72
-
73
- return rtrn_list;
74
- }
75
-
76
-
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);
83
-
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
- }
90
-
91
- return n;
92
- }
93
-
94
-
95
- static void expand_prime_list_to_length(int length){
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
- }
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
- }
106
-
107
- NEXT_INTEGER++;
108
- }
109
-
110
- }
111
-
112
-
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
- }
134
- }
135
-
136
-
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;
146
- }
1
+ #include "prime_gen.h"
2
+ #include <stdlib.h>
3
+ #include <string.h>
4
+ #include <stdio.h>
5
+ #include <math.h>
6
+
7
+ #define FIRST_PRIME 2
8
+
9
+ static void expand_prime_list_to_length(int length);
10
+ static void expand_prime_list_past(int max);
11
+ static int any_divisors(int * div_list, int length, int num);
12
+ static int least_divisor(int n);
13
+
14
+ static int * PRIME_LIST = NULL;
15
+ static int PRIME_LIST_LENGTH = 0;
16
+ static int PRIME_LIST_MAX_LENGTH = 0;
17
+ static int NEXT_INTEGER = FIRST_PRIME;
18
+
19
+
20
+ int * primes(int length){
21
+ int * rtrn_list = calloc(length, sizeof(int));
22
+
23
+ expand_prime_list_to_length(length);
24
+
25
+ if(rtrn_list != NULL){
26
+ memcpy(rtrn_list, PRIME_LIST, length*sizeof(int));
27
+ }
28
+
29
+ return rtrn_list;
30
+ }
31
+
32
+
33
+ int * primes_upto(int max){
34
+ int * rtrn_list;
35
+ int i;
36
+
37
+ expand_prime_list_past(max);
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
+ }
47
+
48
+ return NULL;
49
+ }
50
+
51
+
52
+ int * prime_factors(int n){
53
+ int * rtrn_list = malloc(sizeof(int));
54
+ int rtrn_list_length = 0;
55
+ int least_div;
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;
61
+
62
+ if(least_div == n){
63
+ break;
64
+ }
65
+
66
+ while(n % least_div == 0){
67
+ n /= least_div;
68
+ }
69
+ }
70
+
71
+ rtrn_list[0] = rtrn_list_length;
72
+
73
+ return rtrn_list;
74
+ }
75
+
76
+
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);
83
+
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
+ }
90
+
91
+ return n;
92
+ }
93
+
94
+
95
+ static void expand_prime_list_to_length(int length){
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
+ }
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
+ }
106
+
107
+ NEXT_INTEGER++;
108
+ }
109
+
110
+ }
111
+
112
+
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
+ }
134
+ }
135
+
136
+
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;
146
+ }
@@ -1,10 +1,10 @@
1
- #ifndef H_PRIME_GEN
2
- #define H_PRIME_GEN
3
- int * primes(int n);
4
-
5
- //Generation of primes is currently time-prohibitive when generating up to large maximums.
6
- //This should be acceptable for prime factorization because although naive the algorithm is
7
- //somewhat optimized to detect relatively large prime factors.
8
- int * primes_upto(int max);
9
- int * prime_factors(int n);
1
+ #ifndef H_PRIME_GEN
2
+ #define H_PRIME_GEN
3
+ int * primes(int n);
4
+
5
+ //Generation of primes is currently time-prohibitive when generating up to large maximums.
6
+ //This should be acceptable for prime factorization because although naive the algorithm is
7
+ //somewhat optimized to detect relatively large prime factors.
8
+ int * primes_upto(int max);
9
+ int * prime_factors(int n);
10
10
  #endif
@@ -1,3 +1,3 @@
1
1
  module CongruenceSolver
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
@@ -1,116 +1,113 @@
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 "#{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
- end
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
25
+ raise Errors::LHS_POLYNOMIAL_INVALID
26
+ end
27
+
28
+ begin
29
+ rh_coeffs = read_coeffs(rhs.gsub(" ", ""))
30
+ rescue ArgumentError
31
+ raise Errors::RHS_POLYNOMIAL_INVALID
32
+ end
33
+
34
+ if mod !~ /\d+/ or mod.to_i < 2
35
+ raise Errors::MOD_INVALID
36
+ end
37
+
38
+ 0.upto rh_coeffs.length-1 do |idx|
39
+ unless rh_coeffs[idx].nil?
40
+ lh_coeffs[idx] ||= 0
41
+ lh_coeffs[idx] -= rh_coeffs[idx]
42
+ end
43
+ end
44
+
45
+ [lh_coeffs, mod.to_i]
46
+ end
47
+
48
+ def self.read_coeffs(input_polynomial)
49
+ if input_polynomial == ""
50
+ raise Errors::POLYNOMIAL_INVALID
51
+ end
52
+
53
+ last_var = nil
54
+ coeffs = Array.new
55
+
56
+ unless input_polynomial[0].match /[-+]/
57
+ input_polynomial = "+" + input_polynomial
58
+ end
59
+
60
+ while input_polynomial.length > 0 do
61
+ op = input_polynomial.slice!(0)
62
+ unless op =~ /[-+]/
63
+ raise Errors::POLYNOMIAL_INVALID
64
+ end
65
+
66
+ input_polynomial.slice!(/^(\d+)\*?/)
67
+ match_data_coe = Regexp.last_match
68
+
69
+ input_polynomial.slice!(/^([a-zA-Z])(?:\^(\d+))?/)
70
+ match_data_exp = Regexp.last_match
71
+
72
+ if match_data_coe.nil? and match_data_exp.nil?
73
+ raise Errors::POLYNOMIAL_INVALID
74
+ else
75
+ if match_data_exp.nil?
76
+ coe = match_data_coe[1].to_i
77
+ exp = 0
78
+ else
79
+ unless last_var.nil? or last_var == match_data_exp[1]
80
+ raise Errors::POLYNOMIAL_INVALID
81
+ end
82
+
83
+ last_var = match_data_exp[1]
84
+
85
+ if match_data_coe.nil?
86
+ coe = 1
87
+ else
88
+ coe = match_data_coe[1].to_i
89
+ end
90
+
91
+ if match_data_exp[2].nil?
92
+ exp = 1
93
+ else
94
+ exp = match_data_exp[2].to_i
95
+ end
96
+ end
97
+ end
98
+
99
+ coeffs[exp] ||= 0
100
+ if op == "-"
101
+ coeffs[exp] -= coe.to_i
102
+ else
103
+ coeffs[exp] += coe.to_i
104
+ end
105
+ end
106
+
107
+ 0.upto(coeffs.length-1) do |idx|
108
+ coeffs[idx] ||= 0
109
+ end
110
+
111
+ coeffs
112
+ end
113
+ end