congruence_solver 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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