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.
@@ -13,73 +13,73 @@ VALUE method_congruence_solver_brute_force(VALUE self, VALUE funcoeffs, VALUE mo
13
13
 
14
14
 
15
15
  void Init_congruence_solver(){
16
- CongruenceSolver = rb_define_module("CongruenceSolver");
17
-
18
- rb_define_singleton_method(CongruenceSolver, "lift",
19
- method_congruence_solver_lift, 2);
16
+ CongruenceSolver = rb_define_module("CongruenceSolver");
17
+
18
+ rb_define_singleton_method(CongruenceSolver, "lift",
19
+ method_congruence_solver_lift, 2);
20
20
 
21
- rb_define_singleton_method(CongruenceSolver, "brute_force",
22
- method_congruence_solver_brute_force, 2);
21
+ rb_define_singleton_method(CongruenceSolver, "brute_force",
22
+ method_congruence_solver_brute_force, 2);
23
23
 
24
- /*rb_define_singleton_method(CongruenceSolver, "solve_system_of_congruences",
25
- method_congruence_solver_solve_system_of_congruence, 3);
26
- */
24
+ /*rb_define_singleton_method(CongruenceSolver, "solve_system_of_congruences",
25
+ method_congruence_solver_solve_system_of_congruence, 3);
26
+ */
27
27
  }
28
28
 
29
29
 
30
30
  VALUE method_congruence_solver_brute_force(VALUE self, VALUE funcCoeffs, VALUE mod){
31
- int i;
32
- int * intSolutions;
33
- VALUE rbSolutions;
34
- int intMod = NUM2INT(mod);
31
+ int i;
32
+ int * intSolutions;
33
+ VALUE rbSolutions;
34
+ int intMod = NUM2INT(mod);
35
35
 
36
- int intFuncDegree = RARRAY_LEN(funcCoeffs)-1;
37
- int * intFuncCoeffs = calloc(intFuncDegree+1, sizeof(int));
36
+ int intFuncDegree = RARRAY_LEN(funcCoeffs)-1;
37
+ int * intFuncCoeffs = calloc(intFuncDegree+1, sizeof(int));
38
38
 
39
- for(i = 0; i <= intFuncDegree; i++){
40
- intFuncCoeffs[i] = NUM2INT(rb_ary_entry(funcCoeffs, i));
41
- }
39
+ for(i = 0; i <= intFuncDegree; i++){
40
+ intFuncCoeffs[i] = NUM2INT(rb_ary_entry(funcCoeffs, i));
41
+ }
42
42
 
43
- intSolutions = brute_force_congruence(intFuncDegree, intFuncCoeffs, intMod);
44
- rbSolutions = rb_ary_new2(intSolutions[0]);
43
+ intSolutions = brute_force_congruence(intFuncDegree, intFuncCoeffs, intMod);
44
+ rbSolutions = rb_ary_new2(intSolutions[0]);
45
45
 
46
- for(i=0; i<intSolutions[0]; i++){
47
- rb_ary_store(rbSolutions, i, INT2NUM(intSolutions[i+1]));
48
- }
46
+ for(i=0; i<intSolutions[0]; i++){
47
+ rb_ary_store(rbSolutions, i, INT2NUM(intSolutions[i+1]));
48
+ }
49
49
 
50
50
 
51
- free(intFuncCoeffs);
52
- free(intSolutions);
51
+ free(intFuncCoeffs);
52
+ free(intSolutions);
53
53
 
54
- return rbSolutions;
54
+ return rbSolutions;
55
55
  }
56
56
 
57
57
 
58
58
  VALUE method_congruence_solver_lift(VALUE self, VALUE funcCoeffs, VALUE mod){
59
- int i;
60
- int * intSolutions;
61
- VALUE rbSolutions;
62
- int intMod = NUM2INT(mod);
59
+ int i;
60
+ int * intSolutions;
61
+ VALUE rbSolutions;
62
+ int intMod = NUM2INT(mod);
63
63
 
64
- int intFuncDegree = RARRAY_LEN(funcCoeffs)-1;
65
- int * intFuncCoeffs = calloc(intFuncDegree+1, sizeof(int));
64
+ int intFuncDegree = RARRAY_LEN(funcCoeffs)-1;
65
+ int * intFuncCoeffs = calloc(intFuncDegree+1, sizeof(int));
66
66
 
67
- for(i=0; i<=intFuncDegree; i++){
68
- intFuncCoeffs[i] = NUM2INT(rb_ary_entry(funcCoeffs, i));
69
- }
67
+ for(i=0; i<=intFuncDegree; i++){
68
+ intFuncCoeffs[i] = NUM2INT(rb_ary_entry(funcCoeffs, i));
69
+ }
70
70
 
71
71
 
72
- intSolutions = solve_congruence(intFuncDegree, intFuncCoeffs, intMod);
73
- rbSolutions = rb_ary_new2(intSolutions[0]);
72
+ intSolutions = solve_congruence(intFuncDegree, intFuncCoeffs, intMod);
73
+ rbSolutions = rb_ary_new2(intSolutions[0]);
74
74
 
75
- for(i=0; i<intSolutions[0]; i++){
76
- rb_ary_store(rbSolutions, i, INT2NUM(intSolutions[i+1]));
77
- }
75
+ for(i=0; i<intSolutions[0]; i++){
76
+ rb_ary_store(rbSolutions, i, INT2NUM(intSolutions[i+1]));
77
+ }
78
78
 
79
79
 
80
- free(intFuncCoeffs);
81
- free(intSolutions);
80
+ free(intFuncCoeffs);
81
+ free(intSolutions);
82
82
 
83
- return rbSolutions;
83
+ return rbSolutions;
84
84
  }
85
85
 
@@ -3,197 +3,225 @@
3
3
  #include <stdlib.h>
4
4
  #include <stdio.h>
5
5
 
6
+ static int * adjust_coeffs_to_mod(int degree, int * coeffs, int mod);
6
7
  static int * solve_prime_power_congruence(int degree, int coeffs[], int prime, int power);
7
8
  static int * solve_system_of_order_1_congruence_sets(int numOfSets, int * lengthsOfSets, int ** sets, int mods[]);
8
9
 
9
10
  int chinese_remainder_solution(int numberOfEquations, int scals[], int mods[]){
10
- int i;
11
- int x = 0;
12
- int m = mods[0];
13
- int modCoeff;
11
+ int i;
12
+ int x = 0;
13
+ int m = mods[0];
14
+ int modCoeff;
14
15
 
15
- for(i=1; i<numberOfEquations; i++){
16
- m *= mods[i];
17
- }
16
+ for(i=1; i<numberOfEquations; i++){
17
+ m *= mods[i];
18
+ }
18
19
 
19
- for(i=0; i<numberOfEquations; i++){
20
- modCoeff = m/mods[i];
21
- x += modCoeff*mod_inv(modCoeff, mods[i])*scals[i];
22
- }
20
+ for(i=0; i<numberOfEquations; i++){
21
+ modCoeff = m/mods[i];
22
+ x += modCoeff*mod_inv(modCoeff % mods[i], mods[i])*scals[i];
23
+ }
23
24
 
24
- return x % m;
25
+ return x % m;
25
26
  }
26
27
 
27
28
 
28
- int * brute_force_congruence(int degree, int coeffs[], int primeMod){
29
- //assumes a prime modulus. split congruences of composite modulus into systems of congrueneces
30
- //of prime modulus and/or apply the lifting theorem to make use of this function
31
- //solve a0x^n + a1x^n-1... = 0 (mod mod) where n is the order a0, a1, ... are coeffieicients
32
- int * solutionList = calloc(degree+1, sizeof(int));
33
- int * solutions = solutionList+1;
34
- int numberOfSolutions = 0;
35
- int x;
36
-
37
- for(x = 0; x < primeMod && numberOfSolutions <= degree; x++){
38
- if(mod_eval_polynomial(degree, coeffs, primeMod, x) == 0){
39
- solutions[numberOfSolutions++] = x;
40
- }
41
- }
42
-
43
- *solutionList = numberOfSolutions;
44
-
45
- return solutionList;
29
+ int * adjust_coeffs_to_mod(int degree, int * coeffs, int mod){
30
+ int * adjustedCoeffs = calloc(degree+1, sizeof(int));
31
+ int i;
32
+
33
+ for(i = 0; i <= degree; i++){
34
+ adjustedCoeffs[i] = coeffs[i] % mod;
35
+ if(adjustedCoeffs[i] < 0){
36
+ adjustedCoeffs[i] += mod;
37
+ }
38
+ }
39
+
40
+ return adjustedCoeffs;
46
41
  }
47
42
 
48
43
 
49
- static int * solve_prime_power_congruence(int funcDegree, int funcCoeffs[], int prime, int power){
44
+ int * brute_force_congruence(int degree, int coeffs[], int primeMod){
45
+ //assumes a prime modulus. split congruences of composite modulus into systems of congrueneces
46
+ //of prime modulus and/or apply the lifting theorem to make use of this function
47
+ //solve a0x^n + a1x^n-1... = 0 (mod mod) where n is the order a0, a1, ... are coeffieicients
48
+ //also assumes positive representation of coeffs
49
+ int * adjustedCoeffs = adjust_coeffs_to_mod(degree, coeffs, primeMod);
50
+ int * solutionList = calloc(degree+1, sizeof(int));
51
+ int * solutions = solutionList+1;
52
+ int numberOfSolutions = 0;
53
+ int x;
50
54
 
51
- int * baseSolutionList;
52
- int numOfBaseSolutions;
53
- int * baseSolutions;
54
55
 
55
- int * liftedSolutions;
56
- int numOfLiftedSolutions;
56
+ for(x = 0; x < primeMod && numberOfSolutions <= degree; x++){
57
+ if(mod_eval_polynomial(degree, adjustedCoeffs, primeMod, x) == 0){
58
+ solutions[numberOfSolutions++] = x;
59
+ }
60
+ }
57
61
 
58
- int derivDegree;
59
- int * derivCoeffs;
60
- int deriv;
61
- long int divFunc;
62
+ *solutionList = numberOfSolutions;
62
63
 
63
- int j, t;
64
- int currentMod;
64
+ free(adjustedCoeffs);
65
65
 
66
- if(power == 1){
67
- return brute_force_congruence(funcDegree, funcCoeffs, prime);
68
- }
66
+ return solutionList;
67
+ }
69
68
 
70
- baseSolutionList = solve_prime_power_congruence(funcDegree, funcCoeffs, prime, power-1);
71
- numOfBaseSolutions = *baseSolutionList;
72
- baseSolutions = baseSolutionList+1;
73
69
 
74
- liftedSolutions = calloc(prime*numOfBaseSolutions+1, sizeof(int));
75
- numOfLiftedSolutions = 0;
70
+ static int * solve_prime_power_congruence(int funcDegree, int funcCoeffs[], int prime, int power){
76
71
 
77
- derivDegree = funcDegree-1;
78
- derivCoeffs = calloc(derivDegree+1, sizeof(int));
72
+ int * adjustedCoeffs;
79
73
 
80
- currentMod = prime;
81
- for(j = 1; j < power; j++){
82
- currentMod *= prime;
83
- }
74
+ int * baseSolutionList;
75
+ int numOfBaseSolutions;
76
+ int * baseSolutions;
84
77
 
85
- for(j = 0; j <= derivDegree; j++){
86
- derivCoeffs[j] = funcCoeffs[j+1]*(j+1);
87
- }
78
+ int * liftedSolutions;
79
+ int numOfLiftedSolutions;
88
80
 
81
+ int coeff;
89
82
 
90
- for(j = 0; j < numOfBaseSolutions; j++){
91
- deriv = mod_eval_polynomial(derivDegree, derivCoeffs, prime, baseSolutions[j]);
92
- divFunc = (eval_polynomial(funcDegree, funcCoeffs, baseSolutions[j]) / (currentMod/prime)) % prime;
83
+ int derivDegree;
84
+ int * derivCoeffs;
85
+ int deriv;
86
+ long int divFunc;
93
87
 
94
- if(deriv % prime != 0){
95
- t = (-divFunc*mod_inv(deriv, prime) % prime) + prime;
96
- liftedSolutions[++numOfLiftedSolutions] = baseSolutions[j] + t*prime;
97
- }
88
+ int i, j, t;
89
+ int currentMod;
98
90
 
99
- else if(divFunc % prime == 0){
100
- for(t = 1; t <= prime; t++){
101
- liftedSolutions[++numOfLiftedSolutions] = baseSolutions[j] + t*(currentMod/prime);
102
- }
103
- }
104
- }
91
+ if(power == 1){
92
+ baseSolutions = brute_force_congruence(funcDegree, funcCoeffs, prime);
93
+ return baseSolutions;
94
+ }
105
95
 
96
+ baseSolutionList = solve_prime_power_congruence(funcDegree, funcCoeffs, prime, power-1);
97
+ numOfBaseSolutions = *baseSolutionList;
98
+ baseSolutions = baseSolutionList+1;
106
99
 
107
- *liftedSolutions = numOfLiftedSolutions;
100
+ liftedSolutions = calloc(prime*numOfBaseSolutions+1, sizeof(int));
101
+ numOfLiftedSolutions = 0;
108
102
 
109
- free(derivCoeffs);
110
- free(baseSolutionList);
103
+ derivDegree = funcDegree-1;
104
+ derivCoeffs = calloc(derivDegree+1, sizeof(int));
111
105
 
112
- return liftedSolutions;
113
- }
106
+ currentMod = prime;
107
+ for(j = 1; j < power; j++){
108
+ currentMod *= prime;
109
+ }
114
110
 
111
+ for(j = 0; j <= derivDegree; j++){
112
+ coeff = funcCoeffs[j+1] % prime;
113
+ if(coeff < 0){
114
+ coeff += prime;
115
+ }
116
+ derivCoeffs[j] = mod_product(coeff, j+1, prime);
117
+ }
115
118
 
116
- static int * solve_system_of_order_1_congruence_sets(int numOfSets, int * setLengths, int * * sets, int * mods){
117
- //allocate perumtation array
118
- int * divAry = calloc(numOfSets, sizeof(int));
119
- int * scalAry = calloc(numOfSets, sizeof(int));
120
- int i, j;
121
- int numOfSolutions;
122
- int * solutionAry;
123
- int * dest;
124
- int idx;
125
-
126
- for(i = 0, numOfSolutions = 1; i < numOfSets; i++){
127
- divAry[i] = numOfSolutions;
128
- numOfSolutions *= setLengths[i];
129
- }
130
-
131
- solutionAry = calloc(numOfSolutions+1, sizeof(int));
132
- solutionAry[0] = numOfSolutions;
133
- dest = solutionAry+1;
134
-
135
- for(i = 0; i < numOfSolutions; i++){
136
- for(j = 0; j < numOfSets; j++){
137
- idx = (i / divAry[j]) % setLengths[j];
138
- scalAry[j] = sets[j][idx];
139
- }
140
-
141
- *(dest++) = chinese_remainder_solution(numOfSets, scalAry, mods);
142
- }
143
-
144
- return solutionAry;
145
- }
146
119
 
147
- int * solve_congruence(int funcDegree, int funcCoeffs[], int mod){
148
- int * solutionList;
120
+ for(j = 0; j < numOfBaseSolutions; j++){
149
121
 
150
- int * modFactorList = prime_factors(mod);
151
- int numOfModFactors = *modFactorList;
152
- int * modFactors = modFactorList+1;
122
+ deriv = mod_eval_polynomial(derivDegree, derivCoeffs, prime, baseSolutions[j]);
123
+ divFunc = (eval_polynomial(funcDegree, funcCoeffs, baseSolutions[j]) / (currentMod/prime)) % prime;
153
124
 
154
- int * * primePowerSolutions = calloc(numOfModFactors, sizeof(int *));
155
- int * primePowers = calloc(numOfModFactors, sizeof(int));
156
- int * primePowerSolutionLengths = calloc(numOfModFactors, sizeof(int *));
125
+ if(deriv % prime != 0){
126
+ t = (-divFunc*mod_inv(deriv, prime) % prime) + prime;
127
+ liftedSolutions[++numOfLiftedSolutions] = baseSolutions[j] + t*prime;
128
+ }
157
129
 
158
- int power;
159
- int i;
130
+ else if(divFunc % prime == 0){
131
+ for(t = 1; t <= prime; t++){
132
+ liftedSolutions[++numOfLiftedSolutions] = baseSolutions[j] + t*(currentMod/prime);
133
+ }
134
+ }
135
+ }
160
136
 
161
- for(i = 0; i < numOfModFactors; i++){
162
- primePowers[i] = modFactors[i];
163
- power = 1;
164
-
165
- while(mod % (primePowers[i]*modFactors[i]) == 0){
166
- primePowers[i] *= modFactors[i];
167
- power++;
168
- }
169
137
 
170
- primePowerSolutions[i] = solve_prime_power_congruence(funcDegree, funcCoeffs, modFactors[i], power);
171
- primePowerSolutionLengths[i] = *(primePowerSolutions[i]++);
172
- }
138
+ *liftedSolutions = numOfLiftedSolutions;
173
139
 
140
+ free(derivCoeffs);
141
+ free(baseSolutionList);
174
142
 
175
- solutionList = solve_system_of_order_1_congruence_sets(numOfModFactors, primePowerSolutionLengths, primePowerSolutions, primePowers);
143
+ return liftedSolutions;
144
+ }
176
145
 
177
- for(i = 0; i < numOfModFactors; i++){
178
- free(primePowerSolutions[i] - 1);
179
- }
180
- free(primePowerSolutionLengths);
181
- free(primePowerSolutions);
182
- free(primePowers);
183
- free(modFactorList);
184
146
 
185
- return solutionList;
147
+ static int * solve_system_of_order_1_congruence_sets(int numOfSets, int * setLengths, int * * sets, int * mods){
148
+ //allocate perumtation array
149
+ int * divAry = calloc(numOfSets, sizeof(int));
150
+ int * scalAry = calloc(numOfSets, sizeof(int));
151
+ int i, j;
152
+ int numOfSolutions;
153
+ int * solutionAry;
154
+ int * dest;
155
+ int idx;
156
+
157
+ for(i = 0, numOfSolutions = 1; i < numOfSets; i++){
158
+ divAry[i] = numOfSolutions;
159
+ numOfSolutions *= setLengths[i];
160
+ }
161
+
162
+ solutionAry = calloc(numOfSolutions+1, sizeof(int));
163
+ solutionAry[0] = numOfSolutions;
164
+ dest = solutionAry+1;
165
+
166
+ for(i = 0; i < numOfSolutions; i++){
167
+ for(j = 0; j < numOfSets; j++){
168
+ idx = (i / divAry[j]) % setLengths[j];
169
+ scalAry[j] = sets[j][idx];
170
+ }
171
+
172
+ *(dest++) = chinese_remainder_solution(numOfSets, scalAry, mods);
173
+ }
174
+
175
+ return solutionAry;
176
+ }
177
+
178
+ int * solve_congruence(int funcDegree, int funcCoeffs[], int mod){
179
+ int * solutionList;
180
+
181
+ int * modFactorList = prime_factors(mod);
182
+ int numOfModFactors = *modFactorList;
183
+ int * modFactors = modFactorList+1;
184
+
185
+ int * * primePowerSolutions = calloc(numOfModFactors, sizeof(int *));
186
+ int * primePowers = calloc(numOfModFactors, sizeof(int));
187
+ int * primePowerSolutionLengths = calloc(numOfModFactors, sizeof(int *));
188
+
189
+ int power;
190
+ int i;
191
+
192
+ for(i = 0; i < numOfModFactors; i++){
193
+ primePowers[i] = modFactors[i];
194
+ power = 1;
195
+
196
+ while(mod % (primePowers[i]*modFactors[i]) == 0){
197
+ primePowers[i] *= modFactors[i];
198
+ power++;
199
+ }
200
+
201
+ primePowerSolutions[i] = solve_prime_power_congruence(funcDegree, funcCoeffs, modFactors[i], power);
202
+ primePowerSolutionLengths[i] = *(primePowerSolutions[i]++);
203
+ }
204
+
205
+ solutionList = solve_system_of_order_1_congruence_sets(numOfModFactors, primePowerSolutionLengths, primePowerSolutions, primePowers);
206
+
207
+ for(i = 0; i < numOfModFactors; i++){
208
+ free(primePowerSolutions[i] - 1);
209
+ }
210
+ free(primePowerSolutionLengths);
211
+ free(primePowerSolutions);
212
+ free(primePowers);
213
+ free(modFactorList);
214
+
215
+ return solutionList;
186
216
  }
187
217
 
188
218
  /*
189
219
  int * solve_system_of_congruences(int numOfFuncs, int * funcDegrees, int ** funcCoeffs, int * mods){
190
- int i;
191
- int * * funcSolutionSets = calloc(numOfFuncs, sizeof(int *));
192
-
193
- for(i=0; i<numOfFuncs; i++){
194
- funcSolutionSets[i] = solve_congruence(funcDegrees[i], funcCoeffs[i], mods[i]);
195
- }
196
-
197
- return solve_system_of_congruence_sets(numOfFuncs, funcSolutionSets, mods);
198
- }
199
- */
220
+ int i;
221
+ int * * funcSolutionSets = calloc(numOfFuncs, sizeof(int *));
222
+ for(i=0; i<numOfFuncs; i++){
223
+ funcSolutionSets[i] = solve_congruence(funcDegrees[i], funcCoeffs[i], mods[i]);
224
+ }
225
+ return solve_system_of_congruence_sets(numOfFuncs, funcSolutionSets, mods);
226
+ }
227
+ */
@@ -13,17 +13,4 @@ EXT_C = %w[
13
13
  prime_gen.c
14
14
  ]
15
15
 
16
-
17
- EXT_H.each do |fname|
18
- unless File::exist? fname
19
- raise "Ext header #{fname} does not exist in #{Dir::pwd}"
20
- end
21
- end
22
-
23
- EXT_C.each do |fname|
24
- unless File::exist? fname
25
- raise "Ext file #{fname} does not exist in #{Dir::pwd}"
26
- end
27
- end
28
-
29
16
  create_makefile "congruence_solver/congruence_solver"