congruence_solver 0.3.0 → 0.3.1

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: 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