congruence_solver 0.2.0 → 0.3.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b8cdf5634b888651240db1d379330c26e0915815
4
- data.tar.gz: cb6e241768d62d727196d40600aed3da6c8d8cbd
3
+ metadata.gz: eb92ff33b8d060a03e8a3d7012e4245a39df5583
4
+ data.tar.gz: b07e0989fc34a3c4126e4dbfff4100b2dc8d9f5f
5
5
  SHA512:
6
- metadata.gz: c656aba94e133852ff5a6cb03cb4e4d35e7df80bc60205254caf6ffb1b8bb486121c939a2f8c63dce9dc3881b7ad48840d7a63619b1839faa18acca2148a72bb
7
- data.tar.gz: 84930366fe58c6f75167c673b180b5d1dcc89e38540160f0281b1c10ba100eb7603d23f63ea6346d8ea7117030ae2274d27f82433cc9c5542aa9496d3ee4f146
6
+ metadata.gz: f904157465b3870e19e18b7e5d567a99cd3012a52f9c892eb5ebeaf51eaa08e8cabee1979bb386b1c52be0640b9eac60803f6f562333e4c8232f24b01a9a2d98
7
+ data.tar.gz: 1c912d27c225d6b9d6cd06d5b0509a406ae336714dbb1f63c3af778f7dc62358afdfbd319891e1745bf455ed66f1f87d795d5d816b5ac3902dd080edf9c8982a
@@ -17,8 +17,13 @@ Gem::Specification.new do |spec|
17
17
 
18
18
  spec.files = `git ls-files`.split("\n")
19
19
  spec.files += `git submodule --quiet foreach pwd`.split("\n").map do |abs_dir|
20
- rel_dir = abs_dir.gsub(Dir::pwd, "")
21
- Dir::entries(rel_dir).select {|f| File::file? f}
20
+ abs_dir = abs_dir.gsub(/^c:/, "C:")
21
+ root = Dir::pwd
22
+ dir_in_proj = abs_dir.gsub(/^#{root}\/?/, "")
23
+ Dir::chdir(abs_dir)
24
+ files = `git ls-files`.split("\n")
25
+ Dir::chdir(root)
26
+ files.map {|fname| "#{dir_in_proj}/#{fname}"}
22
27
  end.flatten
23
28
  spec.bindir = "bin"
24
29
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
@@ -0,0 +1,2 @@
1
+ todo
2
+ *.exe
@@ -0,0 +1,18 @@
1
+
2
+ congruences_test: congruences.c test/congruences_test.c test/congruences_test.h arith_utils.c prime_gen.c
3
+ gcc -g prime_gen.c arith_utils.c congruences.c test/congruences_test.c -o congruences_test
4
+
5
+ arith_utils_test: arith_utils.c test/arith_utils_test.c test/arith_utils_test.h prime_gen.c
6
+ gcc -g prime_gen.c arith_utils.c test/arith_utils_test.c -o arith_utils_test
7
+
8
+ prime_gen_test: prime_gen.c test/prime_gen_test.c test/prime_gen_test.h
9
+ gcc -g prime_gen.c test/prime_gen_test.c -o prime_gen_test
10
+
11
+ test: prime_gen_test arith_utils_test congruences_test
12
+ ./prime_gen_test
13
+ ./arith_utils_test
14
+ ./congruences_test
15
+
16
+ clean:
17
+ rm -f prime_gen_test.exe arith_utils_test.exe congruences_test.exe
18
+
@@ -0,0 +1,139 @@
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include "prime_gen.h"
4
+ #include "arith_utils.h"
5
+
6
+
7
+ int mod_sum(int x, int y, int mod){
8
+ x %= mod;
9
+ y %= mod;
10
+
11
+ if(y >= mod - x){
12
+ return y - (mod - x);
13
+ }
14
+
15
+ else{
16
+ return y + x;
17
+ }
18
+ }
19
+
20
+
21
+ int mod_inv(int n, int mod){
22
+ int y, a;
23
+
24
+ if(n!=0){
25
+
26
+ while(n<0){
27
+ n+=mod;
28
+ }
29
+
30
+ for(y = 1; y < mod; y++){
31
+ a = mod_product(y, n, mod);
32
+
33
+ if(a == 1){
34
+ return y;
35
+ }
36
+ }
37
+ }
38
+
39
+ return 0;
40
+ }
41
+
42
+
43
+ int coprime(int n1, int n2){
44
+ //naive algorithm but efficient when n1 has already been factorized
45
+ int * n1Factors = prime_factors(n1);
46
+ int numOfFactors = *n1Factors;
47
+ int * factors = n1Factors+1;
48
+ int shareFactor = 0;
49
+ int i;
50
+
51
+ for(i=0; i<numOfFactors; i++){
52
+ if(n2 % factors[i] == 0){
53
+ shareFactor = 1;
54
+ break;
55
+ }
56
+ }
57
+
58
+ free(n1Factors);
59
+
60
+ return !shareFactor;
61
+ }
62
+
63
+
64
+ int mod_product(int num1, int num2, int mod){
65
+ int prod = 0;
66
+ int i;
67
+
68
+ for(i = 0; i < num1; i++){
69
+ prod = mod_sum(prod, num2, mod);
70
+ }
71
+
72
+ return prod;
73
+ }
74
+
75
+
76
+ int mod_power(int n, int power, int mod){
77
+ int product = n;
78
+ int i;
79
+
80
+ for(i = 1; i < power; i++){
81
+ product = mod_product(product, n, mod);
82
+ }
83
+
84
+ return product;
85
+ }
86
+
87
+
88
+ int totient(int n){
89
+ int * divisorList = prime_factors(n);
90
+ int listLength = divisorList[0];
91
+ int * divisors = divisorList+1;
92
+ int i;
93
+
94
+ for(i = 0; i < listLength; i++){
95
+ n *= (divisors[i] - 1);
96
+ n /= divisors[i];
97
+ }
98
+
99
+ free(divisorList);
100
+
101
+ return n;
102
+ }
103
+
104
+
105
+
106
+
107
+ int mod_eval_polynomial(int degree, int coeffs[], int mod, int x){
108
+ int sum = coeffs[0];
109
+ int i;
110
+
111
+ for(i = 1; i <= degree; i++){
112
+ sum += mod_power(x, i, mod)*coeffs[i];
113
+ sum %= mod;
114
+ }
115
+
116
+ return sum;
117
+ }
118
+
119
+
120
+ long eval_polynomial(int degree, int coeffs[], int x){
121
+ long int sum = coeffs[0];
122
+ long int powx;
123
+ int i;
124
+
125
+ for(i = 1, powx = x; i <= degree; i++, powx*=x){
126
+ sum += powx*coeffs[i];
127
+ }
128
+
129
+ return sum;
130
+ }
131
+
132
+
133
+
134
+
135
+ /*
136
+ int * linear_diophantine_solution(int order, int coeffs[], int scal){
137
+
138
+ *=}
139
+ */
@@ -0,0 +1,10 @@
1
+ #ifndef H_ARITH_UTILS
2
+ #define H_ARITH_UTILS
3
+ int mod_inv(int n, int mod);
4
+ int mod_product(int n1, int n2, int mod);
5
+ int mod_power(int n, int power, int mod);
6
+ int mod_eval_polynomial(int degree, int coeffs[], int mod, int x);
7
+ long eval_polynomial(int degree, int coeffs[], int x);
8
+ int coprime(int n1, int n2);
9
+ int totient(int n);
10
+ #endif
@@ -0,0 +1,85 @@
1
+ #include <ruby.h>
2
+ #include "congruences.h"
3
+ #include "arith_utils.h"
4
+ #include "prime_gen.h"
5
+
6
+
7
+ VALUE CongruenceSolver = Qnil;
8
+
9
+ void Init_congruence_solver();
10
+ VALUE method_congruence_solver_lift(VALUE self, VALUE funcCoeffs, VALUE mod);
11
+ VALUE method_congruence_solver_brute_force(VALUE self, VALUE funcoeffs, VALUE mod);
12
+ //VALUE method_congruence_solver_solve_system_of_congruences(VALUE self, VALUE funcDegreeAry, VALUE aryOfFuncCoeffArys, VALUE modAry);
13
+
14
+
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);
20
+
21
+ rb_define_singleton_method(CongruenceSolver, "brute_force",
22
+ method_congruence_solver_brute_force, 2);
23
+
24
+ /*rb_define_singleton_method(CongruenceSolver, "solve_system_of_congruences",
25
+ method_congruence_solver_solve_system_of_congruence, 3);
26
+ */
27
+ }
28
+
29
+
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);
35
+
36
+ int intFuncDegree = RARRAY_LEN(funcCoeffs)-1;
37
+ int * intFuncCoeffs = calloc(intFuncDegree+1, sizeof(int));
38
+
39
+ for(i = 0; i <= intFuncDegree; i++){
40
+ intFuncCoeffs[i] = NUM2INT(rb_ary_entry(funcCoeffs, i));
41
+ }
42
+
43
+ intSolutions = brute_force_congruence(intFuncDegree, intFuncCoeffs, intMod);
44
+ rbSolutions = rb_ary_new2(intSolutions[0]);
45
+
46
+ for(i=0; i<intSolutions[0]; i++){
47
+ rb_ary_store(rbSolutions, i, INT2NUM(intSolutions[i+1]));
48
+ }
49
+
50
+
51
+ free(intFuncCoeffs);
52
+ free(intSolutions);
53
+
54
+ return rbSolutions;
55
+ }
56
+
57
+
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);
63
+
64
+ int intFuncDegree = RARRAY_LEN(funcCoeffs)-1;
65
+ int * intFuncCoeffs = calloc(intFuncDegree+1, sizeof(int));
66
+
67
+ for(i=0; i<=intFuncDegree; i++){
68
+ intFuncCoeffs[i] = NUM2INT(rb_ary_entry(funcCoeffs, i));
69
+ }
70
+
71
+
72
+ intSolutions = solve_congruence(intFuncDegree, intFuncCoeffs, intMod);
73
+ rbSolutions = rb_ary_new2(intSolutions[0]);
74
+
75
+ for(i=0; i<intSolutions[0]; i++){
76
+ rb_ary_store(rbSolutions, i, INT2NUM(intSolutions[i+1]));
77
+ }
78
+
79
+
80
+ free(intFuncCoeffs);
81
+ free(intSolutions);
82
+
83
+ return rbSolutions;
84
+ }
85
+
@@ -0,0 +1,199 @@
1
+ #include "arith_utils.h"
2
+ #include "prime_gen.h"
3
+ #include <stdlib.h>
4
+ #include <stdio.h>
5
+
6
+ static int * solve_prime_power_congruence(int degree, int coeffs[], int prime, int power);
7
+ static int * solve_system_of_order_1_congruence_sets(int numOfSets, int * lengthsOfSets, int ** sets, int mods[]);
8
+
9
+ 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;
14
+
15
+ for(i=1; i<numberOfEquations; i++){
16
+ m *= mods[i];
17
+ }
18
+
19
+ for(i=0; i<numberOfEquations; i++){
20
+ modCoeff = m/mods[i];
21
+ x += modCoeff*mod_inv(modCoeff, mods[i])*scals[i];
22
+ }
23
+
24
+ return x % m;
25
+ }
26
+
27
+
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;
46
+ }
47
+
48
+
49
+ static int * solve_prime_power_congruence(int funcDegree, int funcCoeffs[], int prime, int power){
50
+
51
+ int * baseSolutionList;
52
+ int numOfBaseSolutions;
53
+ int * baseSolutions;
54
+
55
+ int * liftedSolutions;
56
+ int numOfLiftedSolutions;
57
+
58
+ int derivDegree;
59
+ int * derivCoeffs;
60
+ int deriv;
61
+ long int divFunc;
62
+
63
+ int j, t;
64
+ int currentMod;
65
+
66
+ if(power == 1){
67
+ return brute_force_congruence(funcDegree, funcCoeffs, prime);
68
+ }
69
+
70
+ baseSolutionList = solve_prime_power_congruence(funcDegree, funcCoeffs, prime, power-1);
71
+ numOfBaseSolutions = *baseSolutionList;
72
+ baseSolutions = baseSolutionList+1;
73
+
74
+ liftedSolutions = calloc(prime*numOfBaseSolutions+1, sizeof(int));
75
+ numOfLiftedSolutions = 0;
76
+
77
+ derivDegree = funcDegree-1;
78
+ derivCoeffs = calloc(derivDegree+1, sizeof(int));
79
+
80
+ currentMod = prime;
81
+ for(j = 1; j < power; j++){
82
+ currentMod *= prime;
83
+ }
84
+
85
+ for(j = 0; j <= derivDegree; j++){
86
+ derivCoeffs[j] = funcCoeffs[j+1]*(j+1);
87
+ }
88
+
89
+
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;
93
+
94
+ if(deriv % prime != 0){
95
+ t = (-divFunc*mod_inv(deriv, prime) % prime) + prime;
96
+ liftedSolutions[++numOfLiftedSolutions] = baseSolutions[j] + t*prime;
97
+ }
98
+
99
+ else if(divFunc % prime == 0){
100
+ for(t = 1; t <= prime; t++){
101
+ liftedSolutions[++numOfLiftedSolutions] = baseSolutions[j] + t*(currentMod/prime);
102
+ }
103
+ }
104
+ }
105
+
106
+
107
+ *liftedSolutions = numOfLiftedSolutions;
108
+
109
+ free(derivCoeffs);
110
+ free(baseSolutionList);
111
+
112
+ return liftedSolutions;
113
+ }
114
+
115
+
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
+
147
+ int * solve_congruence(int funcDegree, int funcCoeffs[], int mod){
148
+ int * solutionList;
149
+
150
+ int * modFactorList = prime_factors(mod);
151
+ int numOfModFactors = *modFactorList;
152
+ int * modFactors = modFactorList+1;
153
+
154
+ int * * primePowerSolutions = calloc(numOfModFactors, sizeof(int *));
155
+ int * primePowers = calloc(numOfModFactors, sizeof(int));
156
+ int * primePowerSolutionLengths = calloc(numOfModFactors, sizeof(int *));
157
+
158
+ int power;
159
+ int i;
160
+
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
+
170
+ primePowerSolutions[i] = solve_prime_power_congruence(funcDegree, funcCoeffs, modFactors[i], power);
171
+ primePowerSolutionLengths[i] = *(primePowerSolutions[i]++);
172
+ }
173
+
174
+
175
+ solutionList = solve_system_of_order_1_congruence_sets(numOfModFactors, primePowerSolutionLengths, primePowerSolutions, primePowers);
176
+
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
+
185
+ return solutionList;
186
+ }
187
+
188
+ /*
189
+ 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
+ */
@@ -0,0 +1,7 @@
1
+ #ifndef H_CONGRUENCES
2
+ #define H_CONGRUENCES
3
+ int chinese_remainder_solution(int numOfEquations, int scals[], int mods[]);
4
+ int * solve_congruence(int funcDegree, int funcCoeffs[], int mod);
5
+ int * brute_force_congruence(int degree, int coeffs[], int primeMod);
6
+ //int * solve_system_of_congruences(int numOfFuncs, int * funcDegrees, int ** funcCoeffs, int * mods);
7
+ #endif
@@ -1,4 +1,29 @@
1
1
  require "mkmf"
2
2
 
3
+ EXT_H = %w[
4
+ arith_utils.h
5
+ congruences.h
6
+ prime_gen.h
7
+ ]
3
8
 
4
- create_makefile "congruence_solver"
9
+ EXT_C = %w[
10
+ arith_utils.c
11
+ congruence_solver.c
12
+ congruences.c
13
+ prime_gen.c
14
+ ]
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
+ create_makefile "congruence_solver/congruence_solver"
@@ -0,0 +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
+ }
@@ -0,0 +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);
10
+ #endif
@@ -0,0 +1,106 @@
1
+ #include <stdio.h>
2
+ #include "../arith_utils.h"
3
+ #include "arith_utils_test.h"
4
+
5
+ int main(){
6
+ int failures = 0;
7
+ int i;
8
+
9
+ for(i = 0; i < NUM_OF_MOD_INV_TESTS; i++){
10
+ failures += mod_inv_test(MOD_INV_NUMS[i], MOD_INV_MODS[i], MOD_INV_INVS[i]);
11
+ }
12
+
13
+ for(i = 0; i < NUM_OF_MOD_PRODUCT_TESTS; i++){
14
+ failures += mod_product_test(MOD_PRODUCT_NUM_PAIRS[i], MOD_PRODUCT_MODS[i], MOD_PRODUCT_PRODUCTS[i]);
15
+ }
16
+
17
+ for(i = 0; i < NUM_OF_MOD_POWER_TESTS; i++){
18
+ failures += mod_power_test(MOD_POWER_NUMS[i], MOD_POWER_MODS[i], MOD_POWER_POWERS[i], MOD_POWER_EVALS[i]);
19
+ }
20
+
21
+ for(i = 0; i < NUM_OF_COPRIME_TESTS; i++){
22
+ failures += coprime_test(COPRIME_NUM_PAIRS[i], COPRIME_EVALS[i]);
23
+ }
24
+
25
+ for(i = 0; i < NUM_OF_TOTIENT_TESTS; i++){
26
+ failures += totient_test(TOTIENT_NUMS[i], TOTIENT_EVALS[i]);
27
+ }
28
+
29
+ printf("%d functions failing in arith_utils.c\n\n", failures);
30
+ return failures;
31
+ }
32
+
33
+
34
+ int totient_test(int num, int tot){
35
+ int eval_totient = totient(num);
36
+
37
+ if(tot != eval_totient){
38
+ printf("Totient of %d incorrectly evaluated: %d given instead of %d.\n",
39
+ num, eval_totient, tot);
40
+ return 1;
41
+ }
42
+
43
+ else{
44
+ return 0;
45
+ }
46
+ }
47
+
48
+
49
+ int coprime_test(int * pair, int isCoprime){
50
+ int evalCoprime = coprime(pair[0], pair[1]);
51
+
52
+ if(isCoprime && !evalCoprime){
53
+ printf("%d and %d incorrectly evaluated as not coprime.\n",
54
+ pair[0], pair[1]);
55
+ return 1;
56
+ }
57
+
58
+ else if(!isCoprime && evalCoprime){
59
+ printf("%d and %d incorrectly evaluated as coprime.\n",
60
+ pair[0], pair[1]);
61
+ return 1;
62
+ }
63
+
64
+ else{
65
+ return 0;
66
+ }
67
+ }
68
+
69
+
70
+ int mod_power_test(int num, int mod, int pwr, int mdpwr){
71
+ int mdpwrEval = mod_power(num, pwr, mod);
72
+
73
+ if(mdpwrEval != mdpwr){
74
+ printf("Incorrect evaluation of %d^%d mod %d: %d instead of %d.\n",
75
+ num, pwr, mod, mdpwrEval, mdpwr);
76
+ return 1;
77
+ }
78
+
79
+ return 0;
80
+ }
81
+
82
+
83
+ int mod_product_test(int * pair, int mod, int product){
84
+ int prod = mod_product(pair[0], pair[1], mod);
85
+
86
+ if(prod != product){
87
+ printf("Incorrect evaluation of %d*%d mod %d: %d instead of %d.\n",
88
+ pair[0], pair[1], mod, prod, product);
89
+ return 1;
90
+ }
91
+
92
+ return 0;
93
+ }
94
+
95
+
96
+ int mod_inv_test(int num, int mod, int inv){
97
+ int invEval = mod_inv(num, mod);
98
+
99
+ if(inv != invEval){
100
+ printf("Incorrect evaluation of %d^-1 mod %d: %d instead of %d.\n", num, mod, invEval, inv);
101
+ return 1;
102
+ }
103
+
104
+ return 0;
105
+ }
106
+
@@ -0,0 +1,25 @@
1
+ #define NUM_OF_MOD_INV_TESTS 4
2
+ #define NUM_OF_MOD_PRODUCT_TESTS 4
3
+ #define NUM_OF_MOD_POWER_TESTS 4
4
+ #define NUM_OF_COPRIME_TESTS 5
5
+ #define NUM_OF_TOTIENT_TESTS 6
6
+ #define NUM_OF_MOD_EVAL_POLYNOMIAL_TESTS 1
7
+
8
+ int TOTIENT_NUMS[NUM_OF_TOTIENT_TESTS] = {1, 2, 3, 41, 125, 9400};
9
+ int TOTIENT_EVALS[NUM_OF_TOTIENT_TESTS] = {1, 1, 2, 40, 100, 3680};
10
+
11
+ int COPRIME_NUM_PAIRS[NUM_OF_COPRIME_TESTS][2] = {{3,5}, {9, 28}, {100, 34}, {1000512415, 557825}, {2286144, 1515839}};
12
+ int COPRIME_EVALS[NUM_OF_COPRIME_TESTS] = {1, 1, 0, 0, 1};
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};
17
+
18
+ int MOD_INV_NUMS[NUM_OF_MOD_INV_TESTS] = {5, 4, 53, 129};
19
+ int MOD_INV_MODS[NUM_OF_MOD_INV_TESTS] = {12, 23, 105, 7};
20
+ int MOD_INV_INVS[NUM_OF_MOD_INV_TESTS] = {5, 6, 2, 5};
21
+
22
+ int MOD_POWER_NUMS[NUM_OF_MOD_POWER_TESTS] = {5, 19, 41, 100};
23
+ int MOD_POWER_MODS[NUM_OF_MOD_POWER_TESTS] = {4, 23, 7, 33};
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};
@@ -0,0 +1,78 @@
1
+ #include <stdio.h>
2
+ #include "../congruences.h"
3
+ #include "congruences_test.h"
4
+
5
+ void print_polynomial_inline(int func_degree, int * func_coeffs);
6
+ int solve_congruence_test(int func_degree, int * func_coeffs, int mod, int num_of_solutions, int * solutions);
7
+
8
+ int main(){
9
+ int failures = 0;
10
+
11
+ failures += solve_congruence_test(POL_1_DEGREE, POL_1_COEFFS, POL_1_MOD, NUM_OF_POL_1_SOLS, POL_1_SOLS);
12
+ failures += solve_congruence_test(POL_2_DEGREE, POL_2_COEFFS, POL_2_MOD, NUM_OF_POL_2_SOLS, POL_2_SOLS);
13
+ failures += solve_congruence_test(POL_3_DEGREE, POL_3_COEFFS, POL_3_MOD, NUM_OF_POL_3_SOLS, POL_3_SOLS);
14
+ failures += solve_congruence_test(POL_4_DEGREE, POL_4_COEFFS, POL_4_MOD, NUM_OF_POL_4_SOLS, POL_4_SOLS);
15
+ failures += solve_congruence_test(POL_5_DEGREE, POL_5_COEFFS, POL_5_MOD, NUM_OF_POL_5_SOLS, POL_5_SOLS);
16
+
17
+
18
+ return failures;
19
+ }
20
+
21
+ int int_array_cmp_func(const void * a, const void * b){
22
+ return *((int *)a) - *((int *) b);
23
+ }
24
+
25
+ int solve_congruence_test(int func_degree, int * func_coeffs, int mod, int num_of_solutions, int * solutions){
26
+ int * solutions_to_test = solve_congruence(func_degree, func_coeffs, mod);
27
+ int i, j;
28
+
29
+ qsort(solutions_to_test+1, solutions_to_test[0], sizeof(int), int_array_cmp_func);
30
+ qsort(solutions, num_of_solutions, sizeof(int), int_array_cmp_func);
31
+
32
+ if(num_of_solutions != solutions_to_test[0]){
33
+ printf("Incorrect number of solutions found for congruence ");
34
+ print_polynomial_inline(func_degree, func_coeffs);
35
+ printf(" = 0 (mod %d): %d given instead of %d.\n\n", mod, solutions_to_test[0], num_of_solutions);
36
+
37
+ printf("The following solutions were found: \n");
38
+ for(i = 0; i < solutions_to_test[0]; i++){
39
+ printf("(%d) %d\n", i, solutions_to_test[i+1]);
40
+ }
41
+
42
+ printf("\nwhere the actual solutions are\n\n");
43
+
44
+ for(i = 0; i < num_of_solutions; i++){
45
+ printf("(%d) %d\n", i, solutions[i]);
46
+ }
47
+
48
+ return 1;
49
+ }
50
+
51
+ for(i = 0; i < num_of_solutions; i++){
52
+ if(solutions[i] != solutions_to_test[i+1]){
53
+ printf("Incorrect %dth solution (after sorting) to congruence ", i);
54
+
55
+ print_polynomial_inline(func_degree, func_coeffs);
56
+
57
+ printf(" = 0: %d given instead of %d.\n\n", solutions_to_test[i+1], solutions[i]);
58
+
59
+ return 1;
60
+ }
61
+ }
62
+
63
+ printf("Correct number of solutions (%d) found for congruence ", num_of_solutions);
64
+ print_polynomial_inline(func_degree, func_coeffs);
65
+ printf(" = 0 (mod %d) without error.\n\n", mod);
66
+
67
+ return 0;
68
+ }
69
+
70
+ void print_polynomial_inline(int func_degree, int * func_coeffs){
71
+ int j;
72
+
73
+ for(j = func_degree; j >= 1; j--){
74
+ printf("%d*x^%d + ", func_coeffs[j], j);
75
+ }
76
+
77
+ printf("%d", func_coeffs[0]);
78
+ }
@@ -0,0 +1,204 @@
1
+ #define POL_1_DEGREE 4
2
+ #define POL_1_COEFF_0 0
3
+ #define POL_1_COEFF_1 9
4
+ #define POL_1_COEFF_2 0
5
+ #define POL_1_COEFF_3 2
6
+ #define POL_1_COEFF_4 1
7
+ #define POL_1_MOD 99
8
+ #define NUM_OF_POL_1_SOLS 12
9
+ #define POL_1_SOL_0 0
10
+ #define POL_1_SOL_1 6
11
+ #define POL_1_SOL_2 30
12
+ #define POL_1_SOL_3 33
13
+ #define POL_1_SOL_4 39
14
+ #define POL_1_SOL_5 52
15
+ #define POL_1_SOL_6 61
16
+ #define POL_1_SOL_7 63
17
+ #define POL_1_SOL_8 66
18
+ #define POL_1_SOL_9 72
19
+ #define POL_1_SOL_10 88
20
+ #define POL_1_SOL_11 96
21
+
22
+
23
+ #define POL_2_DEGREE 6
24
+ #define POL_2_COEFF_0 -1
25
+ #define POL_2_COEFF_1 0
26
+ #define POL_2_COEFF_2 0
27
+ #define POL_2_COEFF_3 0
28
+ #define POL_2_COEFF_4 0
29
+ #define POL_2_COEFF_5 0
30
+ #define POL_2_COEFF_6 1
31
+ #define POL_2_MOD 700
32
+ #define NUM_OF_POL_2_SOLS 24
33
+ #define POL_2_SOL_0 1
34
+ #define POL_2_SOL_1 51
35
+ #define POL_2_SOL_2 99
36
+ #define POL_2_SOL_3 101
37
+ #define POL_2_SOL_4 149
38
+ #define POL_2_SOL_5 151
39
+ #define POL_2_SOL_6 199
40
+ #define POL_2_SOL_7 201
41
+ #define POL_2_SOL_8 249
42
+ #define POL_2_SOL_9 251
43
+ #define POL_2_SOL_10 299
44
+ #define POL_2_SOL_11 349
45
+ #define POL_2_SOL_12 351
46
+ #define POL_2_SOL_13 401
47
+ #define POL_2_SOL_14 449
48
+ #define POL_2_SOL_15 451
49
+ #define POL_2_SOL_16 499
50
+ #define POL_2_SOL_17 501
51
+ #define POL_2_SOL_18 549
52
+ #define POL_2_SOL_19 551
53
+ #define POL_2_SOL_20 599
54
+ #define POL_2_SOL_21 601
55
+ #define POL_2_SOL_22 649
56
+ #define POL_2_SOL_23 699
57
+
58
+ #define POL_3_DEGREE 9
59
+ #define POL_3_COEFF_0 -11
60
+ #define POL_3_COEFF_1 0
61
+ #define POL_3_COEFF_2 0
62
+ #define POL_3_COEFF_3 3
63
+ #define POL_3_COEFF_4 0
64
+ #define POL_3_COEFF_5 0
65
+ #define POL_3_COEFF_6 0
66
+ #define POL_3_COEFF_7 0
67
+ #define POL_3_COEFF_8 0
68
+ #define POL_3_COEFF_9 10
69
+ #define POL_3_MOD 49
70
+ #define NUM_OF_POL_3_SOLS 0
71
+
72
+ #define POL_4_DEGREE 2
73
+ #define POL_4_COEFF_0 4
74
+ #define POL_4_COEFF_1 -4
75
+ #define POL_4_COEFF_2 1
76
+ #define POL_4_MOD 5104
77
+ #define NUM_OF_POL_4_SOLS 4
78
+ #define POL_4_SOL_0 2
79
+ #define POL_4_SOL_1 1278
80
+ #define POL_4_SOL_2 2554
81
+ #define POL_4_SOL_3 3830
82
+
83
+ #define POL_5_DEGREE 11
84
+ #define POL_5_COEFF_0 0
85
+ #define POL_5_COEFF_1 2
86
+ #define POL_5_COEFF_2 0
87
+ #define POL_5_COEFF_3 0
88
+ #define POL_5_COEFF_4 0
89
+ #define POL_5_COEFF_5 0
90
+ #define POL_5_COEFF_6 0
91
+ #define POL_5_COEFF_7 0
92
+ #define POL_5_COEFF_8 0
93
+ #define POL_5_COEFF_9 0
94
+ #define POL_5_COEFF_10 0
95
+ #define POL_5_COEFF_11 1
96
+ #define POL_5_MOD 401249
97
+ #define NUM_OF_POL_5_SOLS 9
98
+ #define POL_5_SOL_0 0
99
+ #define POL_5_SOL_1 87850
100
+ #define POL_5_SOL_2 101665
101
+ #define POL_5_SOL_3 105867
102
+ #define POL_5_SOL_4 193717
103
+ #define POL_5_SOL_5 207532
104
+ #define POL_5_SOL_6 295382
105
+ #define POL_5_SOL_7 299584
106
+ #define POL_5_SOL_8 313399
107
+
108
+
109
+ int POL_1_COEFFS[POL_1_DEGREE+1] = {POL_1_COEFF_0,
110
+ POL_1_COEFF_1,
111
+ POL_1_COEFF_2,
112
+ POL_1_COEFF_3,
113
+ POL_1_COEFF_4};
114
+ int POL_1_SOLS[NUM_OF_POL_1_SOLS] = {POL_1_SOL_0,
115
+ POL_1_SOL_1,
116
+ POL_1_SOL_2,
117
+ POL_1_SOL_3,
118
+ POL_1_SOL_4,
119
+ POL_1_SOL_5,
120
+ POL_1_SOL_6,
121
+ POL_1_SOL_7,
122
+ POL_1_SOL_8,
123
+ POL_1_SOL_9,
124
+ POL_1_SOL_10,
125
+ POL_1_SOL_11};
126
+
127
+ int POL_2_COEFFS[POL_2_DEGREE+1] = {POL_2_COEFF_0,
128
+ POL_2_COEFF_1,
129
+ POL_2_COEFF_2,
130
+ POL_2_COEFF_3,
131
+ POL_2_COEFF_4,
132
+ POL_2_COEFF_5,
133
+ POL_2_COEFF_6};
134
+
135
+ int POL_2_SOLS[NUM_OF_POL_2_SOLS] = {POL_2_SOL_0,
136
+ POL_2_SOL_1,
137
+ POL_2_SOL_2,
138
+ POL_2_SOL_3,
139
+ POL_2_SOL_4,
140
+ POL_2_SOL_5,
141
+ POL_2_SOL_6,
142
+ POL_2_SOL_7,
143
+ POL_2_SOL_8,
144
+ POL_2_SOL_9,
145
+ POL_2_SOL_10,
146
+ POL_2_SOL_11,
147
+ POL_2_SOL_12,
148
+ POL_2_SOL_13,
149
+ POL_2_SOL_14,
150
+ POL_2_SOL_15,
151
+ POL_2_SOL_16,
152
+ POL_2_SOL_17,
153
+ POL_2_SOL_18,
154
+ POL_2_SOL_19,
155
+ POL_2_SOL_20,
156
+ POL_2_SOL_21,
157
+ POL_2_SOL_22,
158
+ POL_2_SOL_23};
159
+
160
+ int POL_3_COEFFS[POL_3_DEGREE+1] = {POL_3_COEFF_0,
161
+ POL_3_COEFF_1,
162
+ POL_3_COEFF_2,
163
+ POL_3_COEFF_3,
164
+ POL_3_COEFF_4,
165
+ POL_3_COEFF_5,
166
+ POL_3_COEFF_6,
167
+ POL_3_COEFF_7,
168
+ POL_3_COEFF_8,
169
+ POL_3_COEFF_9
170
+ };
171
+
172
+ int * POL_3_SOLS = NULL;
173
+
174
+ int POL_4_COEFFS[POL_4_DEGREE+1] = {POL_4_COEFF_0,
175
+ POL_4_COEFF_1,
176
+ POL_4_COEFF_2};
177
+
178
+ int POL_4_SOLS[NUM_OF_POL_4_SOLS] = {POL_4_SOL_0,
179
+ POL_4_SOL_1,
180
+ POL_4_SOL_2,
181
+ POL_4_SOL_3};
182
+
183
+ int POL_5_COEFFS[POL_5_DEGREE+1] = {POL_5_COEFF_0,
184
+ POL_5_COEFF_1,
185
+ POL_5_COEFF_2,
186
+ POL_5_COEFF_3,
187
+ POL_5_COEFF_4,
188
+ POL_5_COEFF_5,
189
+ POL_5_COEFF_6,
190
+ POL_5_COEFF_7,
191
+ POL_5_COEFF_8,
192
+ POL_5_COEFF_9,
193
+ POL_5_COEFF_10,
194
+ POL_5_COEFF_11};
195
+
196
+ int POL_5_SOLS[NUM_OF_POL_5_SOLS] = {POL_5_SOL_0,
197
+ POL_5_SOL_1,
198
+ POL_5_SOL_2,
199
+ POL_5_SOL_3,
200
+ POL_5_SOL_4,
201
+ POL_5_SOL_5,
202
+ POL_5_SOL_6,
203
+ POL_5_SOL_7,
204
+ POL_5_SOL_8};
@@ -0,0 +1,83 @@
1
+ #include <stdio.h>
2
+ #include "../prime_gen.h"
3
+ #include "prime_gen_test.h"
4
+
5
+
6
+
7
+ int main(){
8
+ int failures = 0;
9
+ int i;
10
+ int * prime_ary_to_test = primes_upto(MAX_PRIME_FOR_PRIMES_UPTO_TEST)+1;
11
+
12
+ for(i=0; PRIME_ARY[i] <= MAX_PRIME_FOR_PRIMES_UPTO_TEST; i++){
13
+ if(PRIME_ARY[i] != prime_ary_to_test[i]){
14
+ printf("%dth prime incorrect: %d given instead of %d.\n\n", i, prime_ary_to_test[i], PRIME_ARY[i]);
15
+ failures += 1;
16
+ }
17
+ }
18
+
19
+ printf("Primes up to %d generated without error.\n\n", MAX_PRIME_FOR_PRIMES_UPTO_TEST);
20
+
21
+ prime_ary_to_test = primes(LIST_LENGTH_FOR_PRIMES_TEST);
22
+
23
+ for(i = 0; i < LIST_LENGTH_FOR_PRIMES_TEST; i++){
24
+ if(PRIME_ARY[i] != prime_ary_to_test[i]){
25
+ printf("%dth prime incorrect: %d given instead of %d.\n\n", i, prime_ary_to_test[i], PRIME_ARY[i]);
26
+ failures += 1;
27
+ }
28
+ }
29
+
30
+ printf("First %d primes generated without error.\n\n", LIST_LENGTH_FOR_PRIMES_TEST);
31
+
32
+ //Due to the implementation of prime generation and calculation of a maximum divisor
33
+ //2 (and 3, for the same reason) arises as a corner case
34
+ failures += prime_factors_test(2, FACTORS_OF_2, 1);
35
+
36
+ //Factorization of a prime should return an array containig a 1 followed by the prime itself.
37
+ failures += prime_factors_test(PRIME_TO_FACTOR, FACTORS_OF_PRIME, 1);
38
+
39
+ //Factorization of a composite should return an array containing the number of factors and the
40
+ //followed by the factors.
41
+ failures += prime_factors_test(SMALL_COMPOSITE, FACTORS_OF_SMALL_COMPOSITE, NUM_OF_SMALL_COMPOSITE_FACTORS);
42
+
43
+ //Factorization of composites with factors to powers greater than 1 should still only list each factor once.
44
+ failures += prime_factors_test(COMPOSITE_WITH_REPEATED_FACTORS, REPEATED_FACTORS, NUM_OF_REPEATED_FACTORS);
45
+
46
+ //Original implementation ran took several minutes to generate the primes necessary
47
+ //to factor large numbers.
48
+ printf("Beginning to factor a large composite number (%d). A stall here would indicate slow execution.\n",
49
+ LARGE_COMPOSITE);
50
+ failures += prime_factors_test(LARGE_COMPOSITE, FACTORS_OF_LARGE_COMPOSITE, NUM_OF_LARGE_COMPOSITE_FACTORS);
51
+
52
+ //Optimized implementation leverages the least prime factor (once discovered) to minimize the amount of prime generation necessary
53
+ //This method will still falter somewhat when the smallest prime factors are large.
54
+ printf("Beginning to factor a composite with no small prime factors (%d). A stall here would indicate slow execution.\n",
55
+ COMPOSITE_WITH_LARGE_FACTORS);
56
+ failures += prime_factors_test(COMPOSITE_WITH_LARGE_FACTORS, LARGE_FACTORS, NUM_OF_LARGE_FACTORS);
57
+
58
+ return failures;
59
+ }
60
+
61
+
62
+ int prime_factors_test(int num, int * expected_factors, int num_of_expected_factors){
63
+ int * factor_list = prime_factors(num);
64
+ int i;
65
+
66
+ if(factor_list[0] != num_of_expected_factors){
67
+ printf("Incorrect factorization of prime %d: %d factors given instead of %d.\n\n", num, factor_list[0], num_of_expected_factors);
68
+ return 1;
69
+ }
70
+
71
+ else{
72
+ for(i = 0; i < num_of_expected_factors; i++){
73
+ if(factor_list[i+1] != expected_factors[i]){
74
+ printf("Incorrect 0th factor of %d: %d given.\n\b", num, factor_list[1]);
75
+ return 1;
76
+ }
77
+ }
78
+ }
79
+
80
+ printf("%d factored correctly.\n\n", num);
81
+
82
+ return 0;
83
+ }
@@ -0,0 +1,141 @@
1
+ #define MAX_PRIME_FOR_PRIMES_UPTO_TEST 6000
2
+ #define LIST_LENGTH_FOR_PRIMES_TEST 1000
3
+ #define PRIME_TO_FACTOR 41
4
+
5
+ #define SMALL_COMPOSITE 19110
6
+ #define NUM_OF_SMALL_COMPOSITE_FACTORS 5
7
+ #define SMALL_COMP_FACTOR_1 2
8
+ #define SMALL_COMP_FACTOR_2 3
9
+ #define SMALL_COMP_FACTOR_3 5
10
+ #define SMALL_COMP_FACTOR_4 7
11
+ #define SMALL_COMP_FACTOR_5 13
12
+
13
+ #define LARGE_COMPOSITE 94122948
14
+ #define NUM_OF_LARGE_COMPOSITE_FACTORS 5
15
+ #define LARGE_COMP_FACTOR_1 2
16
+ #define LARGE_COMP_FACTOR_2 3
17
+ #define LARGE_COMP_FACTOR_3 17
18
+ #define LARGE_COMP_FACTOR_4 223
19
+ #define LARGE_COMP_FACTOR_5 2069
20
+
21
+ #define COMPOSITE_WITH_REPEATED_FACTORS 108
22
+ #define NUM_OF_REPEATED_FACTORS 2
23
+ #define REPEATED_FACTOR_1 2
24
+ #define REPEATED_FACTOR_2 3
25
+
26
+ #define COMPOSITE_WITH_LARGE_FACTORS 24147371
27
+ #define NUM_OF_LARGE_FACTORS 2
28
+ #define LARGE_FACTOR_1 4909
29
+ #define LARGE_FACTOR_2 4919
30
+
31
+ const int PRIME_ARY[1000] = {
32
+ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
33
+ 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
34
+ 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
35
+ 127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
36
+ 179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
37
+ 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
38
+ 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
39
+ 353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
40
+ 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
41
+ 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
42
+ 547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
43
+ 607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
44
+ 661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
45
+ 739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
46
+ 811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
47
+ 877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
48
+ 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013,
49
+ 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069,
50
+ 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151,
51
+ 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,
52
+ 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
53
+ 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
54
+ 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451,
55
+ 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
56
+ 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583,
57
+ 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657,
58
+ 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
59
+ 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
60
+ 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889,
61
+ 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987,
62
+ 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053,
63
+ 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129,
64
+ 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213,
65
+ 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287,
66
+ 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357,
67
+ 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423,
68
+ 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531,
69
+ 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617,
70
+ 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687,
71
+ 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741,
72
+ 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819,
73
+ 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
74
+ 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
75
+ 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079,
76
+ 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181,
77
+ 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257,
78
+ 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331,
79
+ 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413,
80
+ 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511,
81
+ 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571,
82
+ 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643,
83
+ 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727,
84
+ 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821,
85
+ 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907,
86
+ 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989,
87
+ 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057,
88
+ 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139,
89
+ 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231,
90
+ 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297,
91
+ 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409,
92
+ 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493,
93
+ 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583,
94
+ 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657,
95
+ 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751,
96
+ 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831,
97
+ 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937,
98
+ 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003,
99
+ 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087,
100
+ 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179,
101
+ 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279,
102
+ 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387,
103
+ 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443,
104
+ 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521,
105
+ 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639,
106
+ 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693,
107
+ 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
108
+ 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857,
109
+ 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939,
110
+ 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053,
111
+ 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133,
112
+ 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221,
113
+ 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301,
114
+ 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367,
115
+ 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
116
+ 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571,
117
+ 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673,
118
+ 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761,
119
+ 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833,
120
+ 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917,
121
+ 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997,
122
+ 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103,
123
+ 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207,
124
+ 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297,
125
+ 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411,
126
+ 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499,
127
+ 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561,
128
+ 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643,
129
+ 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723,
130
+ 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829,
131
+ 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919,
132
+ };
133
+
134
+ const int FACTORS_OF_2[1] = {2};
135
+ const int FACTORS_OF_PRIME[1] = {PRIME_TO_FACTOR};
136
+ const int FACTORS_OF_SMALL_COMPOSITE[NUM_OF_SMALL_COMPOSITE_FACTORS] = {SMALL_COMP_FACTOR_1, SMALL_COMP_FACTOR_2, SMALL_COMP_FACTOR_3,
137
+ SMALL_COMP_FACTOR_4, SMALL_COMP_FACTOR_5};
138
+ const int FACTORS_OF_LARGE_COMPOSITE[NUM_OF_LARGE_COMPOSITE_FACTORS] = {LARGE_COMP_FACTOR_1, LARGE_COMP_FACTOR_2, LARGE_COMP_FACTOR_3,
139
+ LARGE_COMP_FACTOR_4, LARGE_COMP_FACTOR_5};
140
+ const int LARGE_FACTORS[NUM_OF_LARGE_FACTORS] = {LARGE_FACTOR_1, LARGE_FACTOR_2};
141
+ const int REPEATED_FACTORS[NUM_OF_REPEATED_FACTORS] = {REPEATED_FACTOR_1, REPEATED_FACTOR_2};
@@ -1,3 +1,3 @@
1
1
  module CongruenceSolver
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: congruence_solver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - lane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-31 00:00:00.000000000 Z
11
+ date: 2016-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -90,7 +90,22 @@ files:
90
90
  - bin/csolve.rb
91
91
  - bin/setup
92
92
  - congruence_solver.gemspec
93
+ - ext/congruence_solver/.gitignore
94
+ - ext/congruence_solver/Makefile
95
+ - ext/congruence_solver/arith_utils.c
96
+ - ext/congruence_solver/arith_utils.h
97
+ - ext/congruence_solver/congruence_solver.c
98
+ - ext/congruence_solver/congruences.c
99
+ - ext/congruence_solver/congruences.h
93
100
  - ext/congruence_solver/extconf.rb
101
+ - ext/congruence_solver/prime_gen.c
102
+ - ext/congruence_solver/prime_gen.h
103
+ - ext/congruence_solver/test/arith_utils_test.c
104
+ - ext/congruence_solver/test/arith_utils_test.h
105
+ - ext/congruence_solver/test/congruences_test.c
106
+ - ext/congruence_solver/test/congruences_test.h
107
+ - ext/congruence_solver/test/prime_gen_test.c
108
+ - ext/congruence_solver/test/prime_gen_test.h
94
109
  - lib/congruence_solver.rb
95
110
  - lib/congruence_solver/version.rb
96
111
  - lib/polynomial_interpreter.rb