congruence_solver 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: eb92ff33b8d060a03e8a3d7012e4245a39df5583
4
- data.tar.gz: b07e0989fc34a3c4126e4dbfff4100b2dc8d9f5f
3
+ metadata.gz: b0efc553f7421a673f9a66fcb7b3b0940f7f2f82
4
+ data.tar.gz: 0146a9f00b2bf9f1ec49ae9180f4b82b817e3bf5
5
5
  SHA512:
6
- metadata.gz: f904157465b3870e19e18b7e5d567a99cd3012a52f9c892eb5ebeaf51eaa08e8cabee1979bb386b1c52be0640b9eac60803f6f562333e4c8232f24b01a9a2d98
7
- data.tar.gz: 1c912d27c225d6b9d6cd06d5b0509a406ae336714dbb1f63c3af778f7dc62358afdfbd319891e1745bf455ed66f1f87d795d5d816b5ac3902dd080edf9c8982a
6
+ metadata.gz: cb9842feb8b1d72d26cfc1b6efbf86dcc357ee1a1c070dedcf6498c6a1c0c33f2cf96a5a9a0db5a224da1a74d751de3d8018dabf5bc9f67ce98126c672ee5e98
7
+ data.tar.gz: 3c3bae47bde1f4d7d5cdd91b157b6a4b3e345859af280db80a5a311bf503577d56b70b7fa2a38829a909bb1e4f0dba93bad284c257a6cfb6b980cbd8c97220b6
data/.gitignore CHANGED
@@ -1,6 +1,6 @@
1
- Gemfile
2
1
  Gemfile.lock
3
2
  tmp/
4
3
  todo
5
4
  lib/congruence_solver/congruence_solver.so
6
- *.gem
5
+ *.gem
6
+ *.html
data/.gitmodules CHANGED
@@ -1,3 +1,4 @@
1
1
  [submodule "ext/congruence_solver"]
2
- path = ext/congruence_solver
3
- url = https://github.com/laneb/congruence_solver_ext.git
2
+ path = ext/congruence_solver
3
+ url = https://github.com/laneb/congruence_solver_ext.git
4
+ branch = master
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in congruence_solver.gemspec
4
+ gemspec
data/README.md CHANGED
@@ -2,25 +2,34 @@
2
2
 
3
3
  CongruenceSolver is a gem for solving polynomial congruences. Should you ever need to solve polynomial congruences and have Ruby installed, this is the gem for you!
4
4
 
5
+ ## Polynomial Congruences
6
+
7
+ Polynomial congruences are the central topic of most elementary number theory and abstract algebra curricula. Similar to an equation, a [congruence](https://en.wikipedia.org/wiki/Modular_equation) is an [equivalence relation](https://en.wikipedia.org/wiki/Equivalence_relation) arising from [modular arithmetic](https://en.wikipedia.org/wiki/Modular_arithmetic) (also knowsn as "clock arithmetic"). For example, the idea "5 hours past 8 is 1" is expressed in the congruence ```8 + 5 = 1 mod 12```. A polynomial congruence is simply a congruence involving a polynomial, like ```x + 5 = 1 mod 12```. The problem of solving a congruence is to find all inputs satisfying the congruence, much like solving an equation (in this case, ```x = 8```). Generally speaking, congruences become more difficult to solve as the degree of the polynomial and the modulus grow. Elementary number theory develops tools like [Hensel Lifting](https://en.wikipedia.org/wiki/Hensel%27s_lemma#Hensel_Lifting) for solving polynomial congruences and the [Chinese Remainder Theorem](https://en.wikipedia.org/wiki/Chinese_remainder_theorem) for solving systems of polynomial congruences. This gem leverages these methods as implemented in C in [congruence_solver_ext](https://github.com/laneb/congruence_solver_ext).
8
+
5
9
  ## Installation
6
10
 
7
- Add this line to your application's Gemfile:
11
+ With [RubyGems](https://rubygems.org/) on your machine, installation is as easy as
12
+ ```shell
13
+ gem install congruence_solver
14
+ ```
15
+
16
+ You may also install via [bundler](http://bundler.io/), by adding this line to your application's Gemfile:
8
17
 
9
18
  ```ruby
10
19
  gem 'congruence_solver'
11
20
  ```
12
21
 
13
- And then execute:
22
+ and executing
14
23
 
15
- $ bundle
16
-
17
- Or install it yourself as:
24
+ ```shell
25
+ $ bundle
26
+ ```
18
27
 
19
- $ gem install congruence_solver
28
+ in the project directory.
20
29
 
21
30
  ## Usage
22
31
 
23
- To solve a polynomial congruence at the command line, simply invoke `csolve` and then enter the congruence at the prompt.
32
+ To solve a polynomial congruence at the command line, simply invoke `csolve` and then enter the congruence at the prompt.
24
33
 
25
34
  ```
26
35
  csolve
@@ -47,9 +56,7 @@ CongruenceSolver.solve_congruence(coeffs, mod).sort #=> [1, 8, 15, 22, 26, 29,
47
56
 
48
57
  ## Development
49
58
 
50
- After checking out the repo, run `bundle install` to install dependencies. Then, run `rake spec` to run the tests, or rake bench to run the benchmark.
51
-
52
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
59
+ After checking out the repo, run `bundle install` to install dependencies and `bundle exec rake update_ext` to pull and compile the extension. Then, run `bundle exec rake spec` to run the tests, or `bundle exec rake bench` to run the benchmark. To build and install this gem onto your local machine, run `bundle exec rake install`.
53
60
 
54
61
  ## Contributing
55
62
 
data/Rakefile CHANGED
@@ -1,23 +1,13 @@
1
1
  #require "bundler/gem_tasks"
2
2
  require "rspec/core/rake_task"
3
- require 'rake/extensiontask'
3
+ require "rake/extensiontask"
4
+ require "os"
4
5
 
5
6
 
6
-
7
-
8
- =begin
9
- namespace :test do
10
- desc "Compile and unit test C extensions"
11
- Rspec::Core::RakeTask.new :c => :compile_c do |t|
12
- t.rspec_opts = C_SPEC_FILE
13
- end
14
- end
15
- =end
16
-
17
7
  #exe runs the csolve binary
18
8
  task :exe do
19
- $LOAD_PATH << "#{Dir.pwd}/lib/"
20
- require_relative "bin/csolve.rb"
9
+ $LOAD_PATH << "#{Dir.pwd}/lib/"
10
+ require_relative "bin/csolve.rb"
21
11
  end
22
12
 
23
13
  #spec runs all RSpec examples
@@ -26,27 +16,71 @@ RSpec::Core::RakeTask.new :spec
26
16
  #uses task template provided by rake-compiler to run the extension compilation
27
17
  #workflow. Task name: compile (do not use task name: ext)
28
18
  Rake::ExtensionTask.new 'congruence_solver' do |ext|
29
- ext.lib_dir = "lib/congruence_solver"
19
+ ext.lib_dir = "lib/congruence_solver"
30
20
  end
31
21
 
32
22
  task :bench do
33
- $LOAD_PATH << "#{Dir.pwd}/lib/"
34
- Dir.foreach("bench") do |bm_file|
35
- path = "bench/#{bm_file}"
36
- if File.file? path and path =~ "_bm.rb^"
37
- require_relative path
38
- end
39
- end
23
+ $LOAD_PATH << "#{Dir.pwd}/lib/"
24
+ Dir.foreach("bench") do |bm_file|
25
+ path = "bench/#{bm_file}"
26
+ if File.file? path and path =~ "_bm.rb^"
27
+ require_relative path
28
+ end
29
+ end
30
+ end
31
+
32
+ #update submodule containing extension.
33
+
34
+ task :fetch_ext do
35
+ EXT_DIR = "ext/congruence_solver"
36
+ `git submodule update --init --remote #{EXT_DIR}`
40
37
  end
41
38
 
39
+
42
40
  #executes compile task defined above, then cleans up the tmp directory that
43
41
  #rake-compiler leaves behind for some reason
44
- task :compile_c => :compile do
45
- CLEAN_CMD = "rmdir /s /q tmp"
46
- system CLEAN_CMD
42
+ task :compile_ext => :compile do
43
+ if OS.windows? then
44
+ `rmdir /s /q tmp`
45
+ else
46
+ `rm -rf tmp`
47
+ end
47
48
  end
48
49
 
49
50
 
51
+ task :update_ext => [:fetch_ext, :compile_ext]
52
+
53
+
54
+ task :clean do
55
+ FILES_TO_RM_ARY = %w[congruence_solver-*.gem
56
+ lib/congruence_solver/congruence_solver.so]
57
+
58
+ file_to_rm_str = FILES_TO_RM_ARY.inject("") {|file_list, file| file_list += file + " "}
59
+
60
+ if OS.windows?
61
+ `rm -f #{file_to_rm_str}`
62
+ else
63
+ `rm -f #{file_to_rm_str}`
64
+ end
65
+ end
66
+
67
+
68
+ task :build => [:compile_ext] do
69
+ GEMSPEC = "congruence_solver.gemspec"
70
+ `gem build #{GEMSPEC}`
71
+ end
72
+
73
+
74
+ task :install => [:clean, :build] do
75
+ dot_gem_files = Dir.entries(Dir.pwd).select {|f| f =~ /congruence_solver\-.*\.gem/}
76
+ if dot_gem_files.empty?
77
+ STDERR.puts "Failed to build gem. Exiting."
78
+ elsif dot_gem_files.length > 1
79
+ STDERR.puts "Error: conflicting .gem files in directory. Exiting."
80
+ else
81
+ `gem install #{dot_gem_files.first}`
82
+ end
83
+ end
50
84
 
51
85
 
52
86
 
data/bench/bench_tools.rb CHANGED
@@ -1,33 +1,33 @@
1
1
 
2
2
  def polynomial_to_s(coeffs)
3
- polynomial = ""
4
- is_first_term = true
3
+ polynomial = ""
4
+ is_first_term = true
5
5
 
6
- coeffs.reverse.each_with_index do |coe, idx|
7
- exp = coeffs.length - idx - 1
8
- if coe != 0
9
- if is_first_term
10
- is_first_term = false
11
- else
12
- if coe < 0
13
- polynomial << " - "
14
- else
15
- polynomial << " + "
16
- end
17
- end
6
+ coeffs.reverse.each_with_index do |coe, idx|
7
+ exp = coeffs.length - idx - 1
8
+ if coe != 0
9
+ if is_first_term
10
+ is_first_term = false
11
+ else
12
+ if coe < 0
13
+ polynomial << " - "
14
+ else
15
+ polynomial << " + "
16
+ end
17
+ end
18
18
 
19
- if coe.abs > 1 or (coe.abs == 1 and exp < 2)
20
- polynomial << coe.abs.to_s
21
- end
19
+ if coe.abs > 1 or (coe.abs == 1 and exp < 2)
20
+ polynomial << coe.abs.to_s
21
+ end
22
22
 
23
- if exp > 0
24
- polynomial << "x"
25
- if exp > 1
26
- polynomial << "^#{exp}"
27
- end
28
- end
29
- end
30
- end
23
+ if exp > 0
24
+ polynomial << "x"
25
+ if exp > 1
26
+ polynomial << "^#{exp}"
27
+ end
28
+ end
29
+ end
30
+ end
31
31
 
32
- polynomial
32
+ polynomial
33
33
  end
@@ -14,58 +14,58 @@ SMALL_FACTORED_LARGE_MOD = 510510
14
14
 
15
15
 
16
16
  def solve_congruence_brute_force(coeffs, mod)
17
- solutions = []
17
+ solutions = []
18
18
 
19
- 0.upto(mod) do |x|
20
- sum = 0
19
+ 0.upto(mod) do |x|
20
+ sum = 0
21
21
 
22
- coeffs.each_with_index do |coe, exp|
23
- sum = (sum + coe*x**exp) % mod
24
- end
22
+ coeffs.each_with_index do |coe, exp|
23
+ sum = (sum + coe*x**exp) % mod
24
+ end
25
25
 
26
- if sum == 0 then solutions << x end
27
- end
26
+ if sum == 0 then solutions << x end
27
+ end
28
28
 
29
- solutions
29
+ solutions
30
30
  end
31
31
 
32
32
 
33
33
  def bm_solve_congruence(coeffs, mod)
34
- puts "Solving #{polynomial_to_s(coeffs)} = 0 mod #{mod}"
34
+ puts "Solving #{polynomial_to_s(coeffs)} = 0 mod #{mod}"
35
35
 
36
- rb_bf_solutions = solve_congruence_brute_force(coeffs, mod).sort
37
- #c_bf_solutions = CongruenceSolver.brute_force(coeffs, mod).sort
38
- c_lifting_solutions = CongruenceSolver.lift(coeffs, mod).sort
36
+ rb_bf_solutions = solve_congruence_brute_force(coeffs, mod).sort
37
+ #c_bf_solutions = CongruenceSolver.brute_force(coeffs, mod).sort
38
+ c_lifting_solutions = CongruenceSolver.lift(coeffs, mod).sort
39
39
 
40
- unless rb_bf_solutions == c_lifting_solutions #and c_bf_solutions c_lift_solutions
41
- puts "Solutions do not match:"
42
- puts "Ruby/force solutions #{rb_bf_solutions.inspect}"
43
- #puts "C/force solutions #{c_bf_solutions}"
44
- puts "C/lifting solutions: #{c_lifting_solutions.inspect}"
45
- end
40
+ unless rb_bf_solutions == c_lifting_solutions #and c_bf_solutions c_lift_solutions
41
+ puts "Solutions do not match:"
42
+ puts "Ruby/force solutions #{rb_bf_solutions.inspect}"
43
+ #puts "C/force solutions #{c_bf_solutions}"
44
+ puts "C/lifting solutions: #{c_lifting_solutions.inspect}"
45
+ end
46
46
 
47
- puts "Time measurements:"
47
+ puts "Time measurements:"
48
48
 
49
- Benchmark.bmbm do |bm|
50
- bm.report("Ruby/force") do
51
- solve_congruence_brute_force(coeffs, mod)
52
- end
49
+ Benchmark.bmbm do |bm|
50
+ bm.report("Ruby/force") do
51
+ solve_congruence_brute_force(coeffs, mod)
52
+ end
53
53
  =begin
54
- bm.report("C/force") do
55
- CongruenceSolver.brute_force(coeffs, mod)
56
- end
54
+ bm.report("C/force") do
55
+ CongruenceSolver.brute_force(coeffs, mod)
56
+ end
57
57
  =end
58
- bm.report("C/lifting") do
59
- CongruenceSolver.lift(coeffs, mod)
60
- end
61
- end
58
+ bm.report("C/lifting") do
59
+ CongruenceSolver.lift(coeffs, mod)
60
+ end
61
+ end
62
62
 
63
- print "\n\n"
63
+ print "\n\n"
64
64
  end
65
65
 
66
66
 
67
67
  [SMALL_DEG_POLYNOMIAL_COEFFS, LARGE_DEG_POLYNOMIAL_COEFFS].each do |coeffs|
68
- [SMALL_MOD, MED_MOD, LARGE_MOD, XTRA_LARGE_MOD, XTRA_LARGE_PRIME_MOD, SMALL_FACTORED_LARGE_MOD].each do |mod|
69
- bm_solve_congruence(coeffs, mod)
70
- end
68
+ [SMALL_MOD, MED_MOD, LARGE_MOD, XTRA_LARGE_MOD, XTRA_LARGE_PRIME_MOD, SMALL_FACTORED_LARGE_MOD].each do |mod|
69
+ bm_solve_congruence(coeffs, mod)
70
+ end
71
71
  end
data/bin/csolve.rb CHANGED
@@ -7,8 +7,8 @@ SOLVE_CONGRUENCE_BENCH_FILE = "../bench/solve_congruence_bm.rb"
7
7
 
8
8
 
9
9
  if ARGV.pop == "bench"
10
- require_relative SOLVE_CONGRUENCE_BENCH_FILE
11
- exit(0)
10
+ require_relative SOLVE_CONGRUENCE_BENCH_FILE
11
+ exit(0)
12
12
  end
13
13
 
14
14
  CONGRUENCE_FORMAT = "(lhs polynomial) = (rhs polynomial) mod (modulus)"
@@ -21,34 +21,34 @@ MOD_INVALID_MSG = "Mod invalid: modulus must be an integer greater than 2"
21
21
  puts "Congruence to solve:"
22
22
 
23
23
  begin
24
- coeffs, mod = PolynomialInterpreter.read_congruence(STDIN.gets)
24
+ coeffs, mod = PolynomialInterpreter.read_congruence(STDIN.gets)
25
25
  rescue ArgumentError => e
26
- if(e == PolynomialInterpreter::Errors::CONGRUENCE_INVALID)
27
- STDERR.puts CONGRUENCE_INVALID_MSG
28
- exit(1)
26
+ if(e == PolynomialInterpreter::Errors::CONGRUENCE_INVALID)
27
+ STDERR.puts CONGRUENCE_INVALID_MSG
28
+ exit(1)
29
29
 
30
- elsif(e == PolynomialInterpreter::Errors::LHS_POLYNOMIAL_INVALID)
31
- STDERR.puts LHS_INVALID_MSG
32
- exit(1)
30
+ elsif(e == PolynomialInterpreter::Errors::LHS_POLYNOMIAL_INVALID)
31
+ STDERR.puts LHS_INVALID_MSG
32
+ exit(1)
33
33
 
34
- elsif(e == PolynomialInterpreter::Errors::RHS_POLYNOMIAL_INVALID)
35
- STDERR.puts RHS_INVALID_MSG
36
- exit(1)
34
+ elsif(e == PolynomialInterpreter::Errors::RHS_POLYNOMIAL_INVALID)
35
+ STDERR.puts RHS_INVALID_MSG
36
+ exit(1)
37
37
 
38
- elsif(e == PolynomialInterpreter::Errors::MOD_INVALID)
39
- STDERR.puts MOD_INVALID_MSG
40
- exit(1)
38
+ elsif(e == PolynomialInterpreter::Errors::MOD_INVALID)
39
+ STDERR.puts MOD_INVALID_MSG
40
+ exit(1)
41
41
 
42
- else
43
- raise e
44
- end
42
+ else
43
+ raise e
44
+ end
45
45
  end
46
46
 
47
47
  solutions = CongruenceSolver.lift(coeffs, mod).sort
48
48
 
49
49
  if solutions.empty?
50
- puts "No solution."
50
+ puts "No solution."
51
51
  else
52
- puts "Solutions:"
53
- solutions.each_with_index {|sol, i| puts "(#{i}) #{sol}"}
52
+ puts "Solutions:"
53
+ solutions.each_with_index {|sol, i| puts "(#{i}) #{sol}"}
54
54
  end
@@ -18,12 +18,11 @@ Gem::Specification.new do |spec|
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
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}"}
21
+ dir_in_proj = abs_dir.gsub(/^#{Dir.pwd}\/?/, "")
22
+ Dir.chdir(abs_dir) do
23
+ files = `git ls-files`.split("\n")
24
+ files.map {|fname| "#{dir_in_proj}/#{fname}"}
25
+ end
27
26
  end.flatten
28
27
  spec.bindir = "bin"
29
28
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
@@ -35,4 +34,5 @@ Gem::Specification.new do |spec|
35
34
  spec.add_development_dependency "rake", "~> 10.0"
36
35
  spec.add_development_dependency "rspec", "~> 2.4"
37
36
  spec.add_development_dependency "rake-compiler", "~>0.9"
37
+ spec.add_development_dependency "os", "~>0.9"
38
38
  end
@@ -3,130 +3,127 @@
3
3
  #include "prime_gen.h"
4
4
  #include "arith_utils.h"
5
5
 
6
-
6
+ //Expects 0 <= x,y < mod
7
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
- }
8
+ if(y >= mod - x){
9
+ return y - (mod - x);
10
+ }
14
11
 
15
- else{
16
- return y + x;
17
- }
12
+ else{
13
+ return y + x;
14
+ }
18
15
  }
19
16
 
20
17
 
21
18
  int mod_inv(int n, int mod){
22
- int y, a;
19
+ int y, a;
23
20
 
24
- if(n!=0){
21
+ if(n!=0){
25
22
 
26
- while(n<0){
27
- n+=mod;
28
- }
23
+ while(n<0){
24
+ n+=mod;
25
+ }
29
26
 
30
- for(y = 1; y < mod; y++){
31
- a = mod_product(y, n, mod);
27
+ for(y = 1; y < mod; y++){
28
+ a = mod_product(y, n, mod);
32
29
 
33
- if(a == 1){
34
- return y;
35
- }
36
- }
37
- }
30
+ if(a == 1){
31
+ return y;
32
+ }
33
+ }
34
+ }
38
35
 
39
- return 0;
36
+ return 0;
40
37
  }
41
38
 
42
39
 
43
40
  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;
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;
61
58
  }
62
59
 
63
60
 
64
61
  int mod_product(int num1, int num2, int mod){
65
- int prod = 0;
66
- int i;
62
+ int prod = 0;
63
+ int i;
67
64
 
68
- for(i = 0; i < num1; i++){
69
- prod = mod_sum(prod, num2, mod);
70
- }
65
+ for(i = 0; i < num1; i++){
66
+ prod = mod_sum(prod, num2, mod);
67
+ }
71
68
 
72
- return prod;
69
+ return prod;
73
70
  }
74
71
 
75
-
72
+ //expects 0 <= n < mod
76
73
  int mod_power(int n, int power, int mod){
77
- int product = n;
78
- int i;
74
+ int product = n;
75
+ int i;
79
76
 
80
- for(i = 1; i < power; i++){
81
- product = mod_product(product, n, mod);
82
- }
77
+ for(i = 1; i < power; i++){
78
+ product = mod_product(product, n, mod);
79
+ }
83
80
 
84
- return product;
81
+ return product;
85
82
  }
86
83
 
87
84
 
88
85
  int totient(int n){
89
- int * divisorList = prime_factors(n);
90
- int listLength = divisorList[0];
91
- int * divisors = divisorList+1;
92
- int i;
86
+ int * divisorList = prime_factors(n);
87
+ int listLength = divisorList[0];
88
+ int * divisors = divisorList+1;
89
+ int i;
93
90
 
94
- for(i = 0; i < listLength; i++){
95
- n *= (divisors[i] - 1);
96
- n /= divisors[i];
97
- }
91
+ for(i = 0; i < listLength; i++){
92
+ n *= (divisors[i] - 1);
93
+ n /= divisors[i];
94
+ }
98
95
 
99
- free(divisorList);
96
+ free(divisorList);
100
97
 
101
- return n;
98
+ return n;
102
99
  }
103
100
 
104
101
 
105
102
 
106
103
 
107
104
  int mod_eval_polynomial(int degree, int coeffs[], int mod, int x){
108
- int sum = coeffs[0];
105
+ int tot = coeffs[degree];
109
106
  int i;
110
107
 
111
- for(i = 1; i <= degree; i++){
112
- sum += mod_power(x, i, mod)*coeffs[i];
113
- sum %= mod;
108
+ for(i = degree - 1; i >= 0; i--){
109
+ tot = mod_product(tot, x, mod);
110
+ tot = mod_sum(tot, coeffs[i], mod);
114
111
  }
115
112
 
116
- return sum;
113
+ return tot;
117
114
  }
118
115
 
119
116
 
120
117
  long eval_polynomial(int degree, int coeffs[], int x){
121
- long int sum = coeffs[0];
122
- long int powx;
123
- int i;
118
+ long int sum = coeffs[0];
119
+ long int powx;
120
+ int i;
124
121
 
125
- for(i = 1, powx = x; i <= degree; i++, powx*=x){
126
- sum += powx*coeffs[i];
127
- }
122
+ for(i = 1, powx = x; i <= degree; i++, powx*=x){
123
+ sum += powx*coeffs[i];
124
+ }
128
125
 
129
- return sum;
126
+ return sum;
130
127
  }
131
128
 
132
129