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 +4 -4
- data/congruence_solver.gemspec +7 -2
- data/ext/congruence_solver/.gitignore +2 -0
- data/ext/congruence_solver/Makefile +18 -0
- data/ext/congruence_solver/arith_utils.c +139 -0
- data/ext/congruence_solver/arith_utils.h +10 -0
- data/ext/congruence_solver/congruence_solver.c +85 -0
- data/ext/congruence_solver/congruences.c +199 -0
- data/ext/congruence_solver/congruences.h +7 -0
- data/ext/congruence_solver/extconf.rb +26 -1
- data/ext/congruence_solver/prime_gen.c +146 -0
- data/ext/congruence_solver/prime_gen.h +10 -0
- data/ext/congruence_solver/test/arith_utils_test.c +106 -0
- data/ext/congruence_solver/test/arith_utils_test.h +25 -0
- data/ext/congruence_solver/test/congruences_test.c +78 -0
- data/ext/congruence_solver/test/congruences_test.h +204 -0
- data/ext/congruence_solver/test/prime_gen_test.c +83 -0
- data/ext/congruence_solver/test/prime_gen_test.h +141 -0
- data/lib/congruence_solver/version.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb92ff33b8d060a03e8a3d7012e4245a39df5583
|
4
|
+
data.tar.gz: b07e0989fc34a3c4126e4dbfff4100b2dc8d9f5f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f904157465b3870e19e18b7e5d567a99cd3012a52f9c892eb5ebeaf51eaa08e8cabee1979bb386b1c52be0640b9eac60803f6f562333e4c8232f24b01a9a2d98
|
7
|
+
data.tar.gz: 1c912d27c225d6b9d6cd06d5b0509a406ae336714dbb1f63c3af778f7dc62358afdfbd319891e1745bf455ed66f1f87d795d5d816b5ac3902dd080edf9c8982a
|
data/congruence_solver.gemspec
CHANGED
@@ -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
|
-
|
21
|
-
|
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,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
|
-
|
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};
|
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.
|
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
|
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
|