congruence_solver 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +9 -6
- data/.gitmodules +0 -4
- data/.rspec +2 -2
- data/README.md +51 -64
- data/Rakefile +107 -87
- data/bench/bench_tools.rb +32 -32
- data/bench/solve_congruence_bm.rb +70 -70
- data/bin/{csolve.rb → csolve} +53 -53
- data/bin/setup +0 -0
- data/congruence_solver.gemspec +32 -38
- data/ext/congruence_solver/Makefile +17 -17
- data/ext/congruence_solver/arith_utils.c +135 -135
- data/ext/congruence_solver/arith_utils.h +9 -9
- data/ext/congruence_solver/congruence_solver.c +85 -85
- data/ext/congruence_solver/congruences.c +226 -226
- data/ext/congruence_solver/congruences.h +6 -6
- data/ext/congruence_solver/extconf.rb +15 -15
- data/ext/congruence_solver/prime_gen.c +146 -146
- data/ext/congruence_solver/prime_gen.h +9 -9
- data/lib/congruence_solver/version.rb +1 -1
- data/lib/polynomial_interpreter.rb +113 -116
- data/license.txt +201 -0
- data/spec/congruence_solver_spec.rb +41 -38
- data/spec/csolve_spec.rb +99 -89
- data/spec/spec_helper.rb +96 -96
- metadata +14 -19
- data/ext/congruence_solver/.gitignore +0 -2
- data/ext/congruence_solver/test/arith_utils_test.c +0 -106
- data/ext/congruence_solver/test/arith_utils_test.h +0 -25
- data/ext/congruence_solver/test/congruences_test.c +0 -78
- data/ext/congruence_solver/test/congruences_test.h +0 -239
- data/ext/congruence_solver/test/prime_gen_test.c +0 -83
- data/ext/congruence_solver/test/prime_gen_test.h +0 -141
data/bin/{csolve.rb → csolve}
RENAMED
@@ -1,54 +1,54 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'congruence_solver'
|
3
|
-
require "polynomial_interpreter"
|
4
|
-
|
5
|
-
|
6
|
-
SOLVE_CONGRUENCE_BENCH_FILE = "../bench/solve_congruence_bm.rb"
|
7
|
-
|
8
|
-
|
9
|
-
if ARGV.pop == "bench"
|
10
|
-
require_relative SOLVE_CONGRUENCE_BENCH_FILE
|
11
|
-
exit(0)
|
12
|
-
end
|
13
|
-
|
14
|
-
CONGRUENCE_FORMAT = "(lhs polynomial) = (rhs polynomial) mod (modulus)"
|
15
|
-
CONGRUENCE_INVALID_MSG = "Congruence invalid: congruences must be of form:\n#{CONGRUENCE_FORMAT}"
|
16
|
-
POLYNOMIAL_FORMAT = "ax^b+cx^d...\n(integer coefficients, positive integer exponents, order irrelevant)"
|
17
|
-
LHS_INVALID_MSG = "Left hand polynomial invalid: polynomials must be of form: #{POLYNOMIAL_FORMAT}"
|
18
|
-
RHS_INVALID_MSG = "Right hand polynomial invalid: polynomials must be of form: #{POLYNOMIAL_FORMAT}"
|
19
|
-
MOD_INVALID_MSG = "Mod invalid: modulus must be an integer greater than 2"
|
20
|
-
|
21
|
-
puts "Congruence to solve:"
|
22
|
-
|
23
|
-
begin
|
24
|
-
coeffs, mod = PolynomialInterpreter.read_congruence(STDIN.gets)
|
25
|
-
rescue ArgumentError => e
|
26
|
-
if(e == PolynomialInterpreter::Errors::CONGRUENCE_INVALID)
|
27
|
-
STDERR.puts CONGRUENCE_INVALID_MSG
|
28
|
-
exit(1)
|
29
|
-
|
30
|
-
elsif(e == PolynomialInterpreter::Errors::LHS_POLYNOMIAL_INVALID)
|
31
|
-
STDERR.puts LHS_INVALID_MSG
|
32
|
-
exit(1)
|
33
|
-
|
34
|
-
elsif(e == PolynomialInterpreter::Errors::RHS_POLYNOMIAL_INVALID)
|
35
|
-
STDERR.puts RHS_INVALID_MSG
|
36
|
-
exit(1)
|
37
|
-
|
38
|
-
elsif(e == PolynomialInterpreter::Errors::MOD_INVALID)
|
39
|
-
STDERR.puts MOD_INVALID_MSG
|
40
|
-
exit(1)
|
41
|
-
|
42
|
-
else
|
43
|
-
raise e
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
solutions = CongruenceSolver.lift(coeffs, mod).sort
|
48
|
-
|
49
|
-
if solutions.empty?
|
50
|
-
puts "No solution."
|
51
|
-
else
|
52
|
-
puts "Solutions:"
|
53
|
-
solutions.each_with_index {|sol, i| puts "(#{i}) #{sol}"}
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'congruence_solver'
|
3
|
+
require "polynomial_interpreter"
|
4
|
+
|
5
|
+
|
6
|
+
SOLVE_CONGRUENCE_BENCH_FILE = "../bench/solve_congruence_bm.rb"
|
7
|
+
|
8
|
+
|
9
|
+
if ARGV.pop == "bench"
|
10
|
+
require_relative SOLVE_CONGRUENCE_BENCH_FILE
|
11
|
+
exit(0)
|
12
|
+
end
|
13
|
+
|
14
|
+
CONGRUENCE_FORMAT = "(lhs polynomial) = (rhs polynomial) mod (modulus)"
|
15
|
+
CONGRUENCE_INVALID_MSG = "Congruence invalid: congruences must be of form:\n#{CONGRUENCE_FORMAT}"
|
16
|
+
POLYNOMIAL_FORMAT = "ax^b+cx^d...\n(integer coefficients, positive integer exponents, order irrelevant)"
|
17
|
+
LHS_INVALID_MSG = "Left hand polynomial invalid: polynomials must be of form: #{POLYNOMIAL_FORMAT}"
|
18
|
+
RHS_INVALID_MSG = "Right hand polynomial invalid: polynomials must be of form: #{POLYNOMIAL_FORMAT}"
|
19
|
+
MOD_INVALID_MSG = "Mod invalid: modulus must be an integer greater than 2"
|
20
|
+
|
21
|
+
puts "Congruence to solve:"
|
22
|
+
|
23
|
+
begin
|
24
|
+
coeffs, mod = PolynomialInterpreter.read_congruence(STDIN.gets)
|
25
|
+
rescue ArgumentError => e
|
26
|
+
if(e == PolynomialInterpreter::Errors::CONGRUENCE_INVALID)
|
27
|
+
STDERR.puts CONGRUENCE_INVALID_MSG
|
28
|
+
exit(1)
|
29
|
+
|
30
|
+
elsif(e == PolynomialInterpreter::Errors::LHS_POLYNOMIAL_INVALID)
|
31
|
+
STDERR.puts LHS_INVALID_MSG
|
32
|
+
exit(1)
|
33
|
+
|
34
|
+
elsif(e == PolynomialInterpreter::Errors::RHS_POLYNOMIAL_INVALID)
|
35
|
+
STDERR.puts RHS_INVALID_MSG
|
36
|
+
exit(1)
|
37
|
+
|
38
|
+
elsif(e == PolynomialInterpreter::Errors::MOD_INVALID)
|
39
|
+
STDERR.puts MOD_INVALID_MSG
|
40
|
+
exit(1)
|
41
|
+
|
42
|
+
else
|
43
|
+
raise e
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
solutions = CongruenceSolver.lift(coeffs, mod).sort
|
48
|
+
|
49
|
+
if solutions.empty?
|
50
|
+
puts "No solution."
|
51
|
+
else
|
52
|
+
puts "Solutions:"
|
53
|
+
solutions.each_with_index {|sol, i| puts "(#{i}) #{sol}"}
|
54
54
|
end
|
data/bin/setup
CHANGED
File without changes
|
data/congruence_solver.gemspec
CHANGED
@@ -1,38 +1,32 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'congruence_solver/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "congruence_solver"
|
8
|
-
spec.version = CongruenceSolver::VERSION
|
9
|
-
spec.
|
10
|
-
spec.
|
11
|
-
|
12
|
-
|
13
|
-
spec.
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
spec.files
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
spec.
|
28
|
-
spec.
|
29
|
-
spec.
|
30
|
-
|
31
|
-
spec.
|
32
|
-
|
33
|
-
spec.add_development_dependency "bundler", "~> 1.10"
|
34
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
35
|
-
spec.add_development_dependency "rspec", "~> 2.4"
|
36
|
-
spec.add_development_dependency "rake-compiler", "~>0.9"
|
37
|
-
spec.add_development_dependency "os", "~>0.9"
|
38
|
-
end
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'congruence_solver/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "congruence_solver"
|
8
|
+
spec.version = CongruenceSolver::VERSION
|
9
|
+
spec.license = "Apache-2.0"
|
10
|
+
spec.authors = ["lane"]
|
11
|
+
spec.email = ["lane.barlow@gmail.com"]
|
12
|
+
|
13
|
+
spec.summary = "A gem for solving polynomial congruences."
|
14
|
+
spec.description = "Provides a class (CongruenceSolver) for finding the modular zeros of a
|
15
|
+
polynomial (given the coefficients and modulus) and a binary (csolve) to
|
16
|
+
to solve your congruences at the command line."
|
17
|
+
spec.homepage = "https://github.com/laneb/congruence_solver"
|
18
|
+
|
19
|
+
spec.files = `git ls-files`.split("\n")
|
20
|
+
spec.files += `(ls ext/congruence_solver)`.split("\n").map { |fname| "ext/congruence_solver/" + fname}
|
21
|
+
spec.bindir = "bin"
|
22
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
23
|
+
spec.require_paths = ["lib"]
|
24
|
+
|
25
|
+
spec.extensions << "ext/congruence_solver/extconf.rb"
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
28
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
29
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
30
|
+
spec.add_development_dependency "rake-compiler", "~>0.9"
|
31
|
+
spec.add_development_dependency "os", "~>0.9"
|
32
|
+
end
|
@@ -1,18 +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
|
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
18
|
|
@@ -1,136 +1,136 @@
|
|
1
|
-
#include <stdio.h>
|
2
|
-
#include <stdlib.h>
|
3
|
-
#include "prime_gen.h"
|
4
|
-
#include "arith_utils.h"
|
5
|
-
|
6
|
-
//Expects 0 <= x,y < mod
|
7
|
-
int mod_sum(int x, int y, int mod){
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
}
|
16
|
-
|
17
|
-
|
18
|
-
int mod_inv(int n, int mod){
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
}
|
38
|
-
|
39
|
-
|
40
|
-
int coprime(int n1, int n2){
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
}
|
59
|
-
|
60
|
-
|
61
|
-
int mod_product(int num1, int num2, int mod){
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
}
|
71
|
-
|
72
|
-
//expects 0 <= n < mod
|
73
|
-
int mod_power(int n, int power, int mod){
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
}
|
83
|
-
|
84
|
-
|
85
|
-
int totient(int n){
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
}
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
int mod_eval_polynomial(int degree, int coeffs[], int mod, int x){
|
105
|
-
int tot = coeffs[degree];
|
106
|
-
int i;
|
107
|
-
|
108
|
-
for(i = degree - 1; i >= 0; i--){
|
109
|
-
tot = mod_product(tot, x, mod);
|
110
|
-
tot = mod_sum(tot, coeffs[i], mod);
|
111
|
-
}
|
112
|
-
|
113
|
-
return tot;
|
114
|
-
}
|
115
|
-
|
116
|
-
|
117
|
-
long eval_polynomial(int degree, int coeffs[], int x){
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
}
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
/*
|
133
|
-
int * linear_diophantine_solution(int order, int coeffs[], int scal){
|
134
|
-
|
135
|
-
*=}
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include "prime_gen.h"
|
4
|
+
#include "arith_utils.h"
|
5
|
+
|
6
|
+
//Expects 0 <= x,y < mod
|
7
|
+
int mod_sum(int x, int y, int mod){
|
8
|
+
if(y >= mod - x){
|
9
|
+
return y - (mod - x);
|
10
|
+
}
|
11
|
+
|
12
|
+
else{
|
13
|
+
return y + x;
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
|
18
|
+
int mod_inv(int n, int mod){
|
19
|
+
int y, a;
|
20
|
+
|
21
|
+
if(n!=0){
|
22
|
+
|
23
|
+
while(n<0){
|
24
|
+
n+=mod;
|
25
|
+
}
|
26
|
+
|
27
|
+
for(y = 1; y < mod; y++){
|
28
|
+
a = mod_product(y, n, mod);
|
29
|
+
|
30
|
+
if(a == 1){
|
31
|
+
return y;
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
return 0;
|
37
|
+
}
|
38
|
+
|
39
|
+
|
40
|
+
int coprime(int n1, int n2){
|
41
|
+
//naive algorithm but efficient when n1 has already been factorized
|
42
|
+
int * n1Factors = prime_factors(n1);
|
43
|
+
int numOfFactors = *n1Factors;
|
44
|
+
int * factors = n1Factors+1;
|
45
|
+
int shareFactor = 0;
|
46
|
+
int i;
|
47
|
+
|
48
|
+
for(i=0; i<numOfFactors; i++){
|
49
|
+
if(n2 % factors[i] == 0){
|
50
|
+
shareFactor = 1;
|
51
|
+
break;
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
free(n1Factors);
|
56
|
+
|
57
|
+
return !shareFactor;
|
58
|
+
}
|
59
|
+
|
60
|
+
|
61
|
+
int mod_product(int num1, int num2, int mod){
|
62
|
+
int prod = 0;
|
63
|
+
int i;
|
64
|
+
|
65
|
+
for(i = 0; i < num1; i++){
|
66
|
+
prod = mod_sum(prod, num2, mod);
|
67
|
+
}
|
68
|
+
|
69
|
+
return prod;
|
70
|
+
}
|
71
|
+
|
72
|
+
//expects 0 <= n < mod
|
73
|
+
int mod_power(int n, int power, int mod){
|
74
|
+
int product = n;
|
75
|
+
int i;
|
76
|
+
|
77
|
+
for(i = 1; i < power; i++){
|
78
|
+
product = mod_product(product, n, mod);
|
79
|
+
}
|
80
|
+
|
81
|
+
return product;
|
82
|
+
}
|
83
|
+
|
84
|
+
|
85
|
+
int totient(int n){
|
86
|
+
int * divisorList = prime_factors(n);
|
87
|
+
int listLength = divisorList[0];
|
88
|
+
int * divisors = divisorList+1;
|
89
|
+
int i;
|
90
|
+
|
91
|
+
for(i = 0; i < listLength; i++){
|
92
|
+
n *= (divisors[i] - 1);
|
93
|
+
n /= divisors[i];
|
94
|
+
}
|
95
|
+
|
96
|
+
free(divisorList);
|
97
|
+
|
98
|
+
return n;
|
99
|
+
}
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
|
104
|
+
int mod_eval_polynomial(int degree, int coeffs[], int mod, int x){
|
105
|
+
int tot = coeffs[degree];
|
106
|
+
int i;
|
107
|
+
|
108
|
+
for(i = degree - 1; i >= 0; i--){
|
109
|
+
tot = mod_product(tot, x, mod);
|
110
|
+
tot = mod_sum(tot, coeffs[i], mod);
|
111
|
+
}
|
112
|
+
|
113
|
+
return tot;
|
114
|
+
}
|
115
|
+
|
116
|
+
|
117
|
+
long eval_polynomial(int degree, int coeffs[], int x){
|
118
|
+
long int sum = coeffs[0];
|
119
|
+
long int powx;
|
120
|
+
int i;
|
121
|
+
|
122
|
+
for(i = 1, powx = x; i <= degree; i++, powx*=x){
|
123
|
+
sum += powx*coeffs[i];
|
124
|
+
}
|
125
|
+
|
126
|
+
return sum;
|
127
|
+
}
|
128
|
+
|
129
|
+
|
130
|
+
|
131
|
+
|
132
|
+
/*
|
133
|
+
int * linear_diophantine_solution(int order, int coeffs[], int scal){
|
134
|
+
|
135
|
+
*=}
|
136
136
|
*/
|
@@ -1,10 +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);
|
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
10
|
#endif
|