hensel_code 0.3.0 → 0.4.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
  SHA256:
3
- metadata.gz: 50f6a13e6cba426fca07fa46a610b85ef7fae043a4a380481cb20ab6df14de3a
4
- data.tar.gz: 89ac88e608472e67fe00238d1e974462747870bf13aa6f85d2391c559656cfcf
3
+ metadata.gz: 9fe4ccc09920268da571091821a4f4c3d05be182a9c54807099e97710a6c25b3
4
+ data.tar.gz: de54128ac780eea4fae8f739216b35da2912a42f739f9fd0e66bd09738c9109c
5
5
  SHA512:
6
- metadata.gz: d67e6bdb32a0a1c70fecc6b00a6d5a3e7b7a6ca426446b02c9b44e3c84f059dccf79e17d6567013ec61f2ddb2641fdc41f34b0887dc36bc287cba89452329398
7
- data.tar.gz: 7f4c9d9deb9edb968e99ad1c67e7cb597789169af91c6c83c9c1288990c531d7fcd732065cd71ce4a7f3cb6fd364667d2cd92932a5c20a4b0dad89bdf0b088d7
6
+ metadata.gz: 8a08b73aeec51d006064ab31ea7324ab3d2cc8f82cecb866b3fe81432eb710045be9b0b77d6da01b624f8a102b2aa06765b8b231dff6e6c01602a10603e40081
7
+ data.tar.gz: 55380ace482bbbafcca376d87ab48db7061efe2a263195cc4627f078afe307800a2cb12a82e59ba7e41c291ce2c28f55db0232bcd57e3c5884ac8ca848a6e61e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [0.4.0] - 2022-03-29
2
+ - Add the fourth type of supported Hensel code: the finite-segement g-adic Hensel code.
3
+
4
+ ## [0.3.1] - 2022-03-25
5
+ - Fix the method `random_distinct_numbers` in `Tools` which was allowing duplicated random numbers.
6
+
1
7
  ## [0.3.0] - 2022-03-12
2
8
 
3
9
  - Add the `Polynomial` class for arithmetic with fixed-length polynomials
data/Gemfile CHANGED
@@ -17,6 +17,6 @@ gem "rubocop-rake", "~> 0.6"
17
17
 
18
18
  gem "minitest-reporters", "~> 1.5"
19
19
 
20
- gem "prime", "~> 0.1.2"
21
-
22
20
  gem "codecov", require: false, group: :test
21
+
22
+ gem "simplecov-console", "~>0.9", require: false
data/Gemfile.lock CHANGED
@@ -1,7 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hensel_code (0.3.0)
4
+ hensel_code (0.4.1)
5
+ openssl (~> 3.0.0)
6
+ prime (~> 0.1.2)
5
7
 
6
8
  GEM
7
9
  remote: https://rubygems.org/
@@ -19,6 +21,7 @@ GEM
19
21
  builder
20
22
  minitest (>= 5.0)
21
23
  ruby-progressbar
24
+ openssl (3.0.0)
22
25
  parallel (1.21.0)
23
26
  parser (3.1.1.0)
24
27
  ast (~> 2.4.1)
@@ -49,9 +52,15 @@ GEM
49
52
  docile (~> 1.1)
50
53
  simplecov-html (~> 0.11)
51
54
  simplecov_json_formatter (~> 0.1)
55
+ simplecov-console (0.9.1)
56
+ ansi
57
+ simplecov
58
+ terminal-table
52
59
  simplecov-html (0.12.3)
53
60
  simplecov_json_formatter (0.1.4)
54
61
  singleton (0.1.1)
62
+ terminal-table (3.0.2)
63
+ unicode-display_width (>= 1.1.1, < 3)
55
64
  unicode-display_width (2.1.0)
56
65
 
57
66
  PLATFORMS
@@ -63,11 +72,11 @@ DEPENDENCIES
63
72
  hensel_code!
64
73
  minitest (~> 5.0)
65
74
  minitest-reporters (~> 1.5)
66
- prime (~> 0.1.2)
67
75
  rake (~> 13.0)
68
76
  rubocop (~> 1.21)
69
77
  rubocop-minitest (~> 0.17.2)
70
78
  rubocop-rake (~> 0.6)
79
+ simplecov-console (~> 0.9)
71
80
 
72
81
  BUNDLED WITH
73
82
  2.3.8
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ![example workflow](https://github.com/davidwilliam/hensel_code/actions/workflows/main.yml/badge.svg) [![codecov](https://codecov.io/gh/davidwilliam/hensel_code/branch/main/graph/badge.svg?token=XJ0C0U7P2M)](https://codecov.io/gh/davidwilliam/hensel_code) [![Ruby Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop/rubocop) ![GitHub](https://img.shields.io/github/license/davidwilliam/hensel_code) ![Gem](https://img.shields.io/gem/v/hensel_code) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/davidwilliam/hensel_code)
4
4
 
5
- ***NOTICE:*** this README is beign constantly updated. I am currently focused on coding since I want to release as many different types of Hensel codes as possible. At the same time, I want this README to be as informative as possible even for those completely unfamiliar with p-adic numbers and Hensel codes. Therefore, even not in the pace I would want, I will continue to add information to the README to facilitate the use of the gem and to give some practical ideas of the computational possibilities enabled by it.
5
+ ***NOTICE:*** this README is beign constantly updated. I am currently focused on coding since I want to release as many different types of Hensel codes and as many interesting features as time allows. At the same time, I want this README to be as informative as possible even for those completely unfamiliar with p-adic numbers and Hensel codes.
6
6
 
7
7
  Hensel Code allows you to homomorphically encode rational numbers as integers using the finite-segment p-adic arithmetic, also known as Hensel codes.
8
8
 
@@ -14,6 +14,12 @@ Rao also remarks that the theory of Hensel codes, although lifted from the p-adi
14
14
 
15
15
  A p-adic number can be uniquely written as a inifite p-adic expansion, for `p` prime, where the associated coefficients are integers between `0` and `p - 1`. When this p-adic expansion is finite in length, then we have a finite-segment p-adic expansion. When we only consider the constant term of a p-adic expansion, then we have a truncated finite-segment p-adic expansion. There many types of representations of rationals lifted from the p-adic number theory, and therefore many types of Hensel codes.
16
16
 
17
+ ## History
18
+
19
+ The theory of p-adic numbers was introduced by Kurt Hensel in the early 1900's ([Theorie der algebraischen Zahlen](https://books.google.com/books?hl=en&lr=&id=0w3vAAAAMAAJ&oi=fnd&pg=PR3&dq=Theorie+der+algebraischen+Zahlen&ots=kQfsAd0GYZ&sig=dGsTggln9njYkc2zNYT5hkk2lXU#v=onepage&q=Theorie%20der%20algebraischen%20Zahlen&f=false)). Introductions to p-adic numbers are provided by George Bachman (Introduction to p-Adic Numbers and Valuation Theory), Neal Koblitz ([P-Adic Numbers, P-Adic Analysis, and Zeta Functions](https://books.google.com/books?hl=en&lr=&id=8sTgBwAAQBAJ&oi=fnd&pg=PA1&dq=P-Adic+Numbers,+P-Adic+Analysis,+and+Zeta+Functions&ots=fWIImSqW7-&sig=29LdWtpjSkmQ2kWvVFDmmG5SsOo#v=onepage&q=P-Adic%20Numbers%2C%20P-Adic%20Analysis%2C%20and%20Zeta%20Functions&f=false)), Kurt Mahler ([Introduction to p-adic numbers and their functions](https://books.google.com/books?hl=en&lr=&id=kbc8AAAAIAAJ&oi=fnd&pg=PA1&dq=Introduction+to+P-Adic+Numbers+and+Their+Functions&ots=GFpDeD8vMG&sig=TNSPVG0YA676rlflM9CfogQP7t8)), and Fernando Gouveia ([p-adic Number](https://books.google.com/books?hl=en&lr=&id=VWjsDwAAQBAJ&oi=fnd&pg=PR5&ots=MdgpeNTWLX&sig=9LzgTUkSzN76E1EOD7wna0c8S0I#v=onepage&q&f=false)).
20
+
21
+ The foundation of the particular application of finite-segement p-adic arithemetic (also known as Hensel codes) for error-free computation can be found in the works of Alparslan, Krishnamurthy, Rao, and Subramanian (Finite p-adic number systems with possible applications, [Finite segmentp-adic number systems with applications to exact computation](https://link.springer.com/article/10.1007/BF03051174), [p-Adic arithmetic procedures for exact matrix computations](https://link.springer.com/article/10.1007/BF03046725), [Error-Free Polynomial Matrix Computations](https://link.springer.com/book/10.1007/978-1-4612-5118-7)), Gregory ([Methods and Applications of Error-Free Computation](https://link.springer.com/book/10.1007/978-1-4612-5242-9), [Error-free computation with rational numbers](https://link.springer.com/article/10.1007/BF01933164), [Error-free computation with finite number systems](https://dl.acm.org/doi/abs/10.1145/1057502.1057503?casa_token=LTLotJJYEPAAAAAA:PQwNY8-RcpuSQyfCkEMv1xIpd10RlR-y7JeTWkCkYNQ3c1IroGEGzk4TVH_5JJ954sJsvcHRlTldtQ), [The use of finite-segmentp-adic arithmetic for exact computation](https://link.springer.com/article/10.1007/BF01930898)), Miola ([Algebraic approach to p-adic conversion of rational numbers](https://www.sciencedirect.com/science/article/abs/pii/002001908490022X)), Morrison ([Parallel p-adic computation](https://www.sciencedirect.com/science/article/abs/pii/0020019088901597)). Many algorithms, ideas, and concepts in Hensel codes are greatly benefitted by the remarkable series The Art of Computer Programming by Donald Knuth.
22
+
17
23
  ## Mathematical Background
18
24
 
19
25
  In our Wiki, you can find a brief [introduction to the mathematical background on Hensel codes](https://github.com/davidwilliam/hensel_code/wiki/Mathematical-Background). We will continue to update that area as we update the gem.
@@ -45,6 +51,7 @@ There are several types of Hensel codes in the finite-segment p-adic number theo
45
51
  1. Truncated finite-segment p-adic Hensel codes
46
52
  2. Finite-segment p-adic Hensel codes
47
53
  3. Truncated finite-segment g-adic Hensel codes
54
+ 4. Finite-segmenet g-adic Hensel codes
48
55
 
49
56
  For each type of supported Hensel code I will briefly discuss their properties and capabilities as well as unique features that make each type of Hensel code distinct from each other.
50
57
 
@@ -620,7 +627,75 @@ h4.to_r
620
627
  # => (84245698732457344123/198437243845987593234524)
621
628
  ```
622
629
 
623
- ### Class Aliases
630
+ ## Finite-segment g-adic Hensel codes
631
+
632
+ ### Description
633
+ The finite-segment g-adic Hensel codes are analogous to the relationship between truncated finite p-adic expansions and finite p-adic expansions. With the finite-segement g-adic Hensel codes, we have a collection of fixed-degree univariate polynomials for each one of `k` distinct primes used to compute a g-adic Hensel code.
634
+
635
+ ### Unique Benefits
636
+
637
+ Finite-segement g-adic Hensel codes combine the best of two worlds: multiple independent Hensel codes which can be computed in parallel / in a distributed manner and computations using fixed-degree polynomials where for each `b`-bit prime `p_i`, the maximum expansion of all computations will take at most `1 + 2b` bits. Combining parallel/distributed computation with minimal computation expansion can be beneficial for a number of applications including massive parallel computations and egde computing.
638
+
639
+ ### Usage
640
+ ```ruby
641
+ primes = [241, 251, 257]
642
+ r = 3
643
+ rat1 = Rational(2,3)
644
+ rat2 = Rational(5,9)
645
+ h1 = HenselCode::FiniteGadicExpansion.new primes, r, rat1
646
+ # => <HenselCode: ["81 + 80p + 80p^2", "168 + 83p + 167p^2", "172 + 85p + 171p^2"]>
647
+ h2 = HenselCode::FiniteGadicExpansion.new primes, r, rat2
648
+ # => <HenselCode: ["188 + 26p + 107p^2", "140 + 111p + 139p^2", "229 + 199p + 142p^2"]>
649
+ h1.to_r
650
+ # => (2/3)
651
+ h2.to_r
652
+ # => (5/9)
653
+ h1.to_a
654
+ # => [[81, 80, 80], [168, 83, 167], [172, 85, 171]]
655
+ h2.to_a
656
+ # => [[188, 26, 107], [140, 111, 139], [229, 199, 142]]
657
+ ```
658
+
659
+ ### Arithmetic
660
+ ```ruby
661
+ h1_plus_h2 = h1 + h2
662
+ # => <HenselCode: ["28 + 107p + 187p^2", "57 + 195p + 55p^2", "144 + 28p + 57p^2"]>
663
+ h1_minus_h2 = h1 - h2
664
+ # => <HenselCode: ["134 + 53p + 214p^2", "28 + 223p + 27p^2", "200 + 142p + 28p^2"]>
665
+ h1_times_h2 = h1 * h2
666
+ # => <HenselCode: ["45 + 98p + 71p^2", "177 + 241p + 92p^2", "67 + 133p + 9p^2"]>
667
+ h1_div_h2 = h1 / h2
668
+ # => <HenselCode: ["194 + 192p + 192p^2", "202 + 200p + 200p^2", "104 + 51p + 154p^2"]>
669
+ h2.inverse
670
+ # => <HenselCode: ["50 + 48p + 48p^2", "52 + 50p + 50p^2", "156 + 205p + 102p^2"]>
671
+ h1 * h2.inverse
672
+ # => <HenselCode: ["194 + 192p + 192p^2", "202 + 200p + 200p^2", "104 + 51p + 154p^2"]>
673
+ h2 * h2.inverse
674
+ # => <HenselCode: ["1 + 0p + 0p^2", "1 + 0p + 0p^2", "1 + 0p + 0p^2"]>
675
+ ```
676
+
677
+ and we can check that
678
+
679
+ ```ruby
680
+ h1_plus_h2.to_r
681
+ # => (11/9)
682
+ rat1 + rat2
683
+ # => (11/9)
684
+ h1_minus_h2.to_r
685
+ # => (1/9)
686
+ rat1 - rat2
687
+ # => (1/9)
688
+ h1_times_h2.to_r
689
+ # => (10/27)
690
+ rat1 * rat2
691
+ # => (10/27)
692
+ h1_div_h2.to_r
693
+ # => (6/5)
694
+ rat1 / rat2
695
+ # => (6/5)
696
+ ```
697
+
698
+ ## Class Aliases
624
699
 
625
700
  Since some classes can have long names, here are some aliases that can be used for keeping the lines of code shorter:
626
701
 
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/hensel_code/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "hensel_code"
7
+ spec.version = HenselCode::VERSION
8
+ spec.authors = ["David William Silva"]
9
+ spec.email = ["contact@davidwsilva.com"]
10
+
11
+ spec.summary = "Error-free computation with homomorphic encoding of rational numbers."
12
+ spec.description = "A Ruby library for error-free computation via homomorphic encoding of rational numbers."
13
+ spec.homepage = "https://github.com/davidwilliam/hensel_code"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 2.6.0"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = "https://github.com/davidwilliam/hensel_code"
19
+ spec.metadata["changelog_uri"] = "https://github.com/davidwilliam/hensel_code/blob/main/CHANGELOG.md"
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
+ `git ls-files -z`.split("\x0").reject do |f|
25
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
26
+ end
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ # Uncomment to register a new dependency of your gem
33
+ spec.add_dependency "openssl", "~> 3.0.0"
34
+ spec.add_dependency "prime", "~> 0.1.2"
35
+
36
+ # For more information and examples about making a new gem, check out our
37
+ # guide at: https://bundler.io/guides/creating_gem.html
38
+ spec.metadata["rubygems_mfa_required"] = "true"
39
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HenselCode
4
+ # truncated finite g-adic expansion hensel code class
5
+ class FiniteGadicExpansion < GAdicBase
6
+ def modululi
7
+ primes.map { |prime| prime**exponent }
8
+ end
9
+
10
+ def to_a
11
+ hensel_code.map(&:to_a)
12
+ end
13
+
14
+ def to_s
15
+ hensel_code.map(&:to_s).to_s
16
+ end
17
+
18
+ def inspect
19
+ "<HenselCode: #{self}>"
20
+ end
21
+
22
+ def inverse
23
+ new_hensel_code = hensel_code.map(&:inverse)
24
+ self.class.new primes, exponent, new_hensel_code
25
+ end
26
+
27
+ private
28
+
29
+ def evaluate(operation, other)
30
+ new_hensel_code = hensel_code.zip(other.hensel_code).map { |pair| pair[0].send(operation, pair[1]) }
31
+ self.class.new primes, exponent, new_hensel_code
32
+ end
33
+
34
+ def valid_number?(number)
35
+ if number.is_a?(Rational)
36
+ @rational = number
37
+ elsif number.is_a?(Array) && number.map(&:class).uniq == [HenselCode::FinitePadicExpansion]
38
+ @hensel_code = number
39
+ decode
40
+ else
41
+ message = "number must be a Rational or an\
42
+ Array of finite p-adic Hensel codes and it was a #{number.class}"
43
+ raise WrongHenselCodeInputType, message
44
+ end
45
+ end
46
+
47
+ def valid_hensel_code?(new_hensel_code)
48
+ condition = new_hensel_code.is_a?(Array) && new_hensel_code.map(&:class).uniq == [HenselCode::FPE]
49
+ message = "must be an array of finite p-adic Hensel codes"
50
+ raise WrongHenselCodeInputType, message unless condition
51
+ end
52
+
53
+ def encode
54
+ @g = primes.inject(:*)
55
+ @hensel_code = primes.map do |prime|
56
+ FinitePadicExpansion.new prime, exponent, rational
57
+ end
58
+ end
59
+
60
+ def decode
61
+ hs = hensel_code.map { |h| h.to_truncated.hensel_code }
62
+ h = TruncatedFinitePadicExpansion.new g, exponent, crt(modululi, hs)
63
+ @rational = h.to_r
64
+ end
65
+ end
66
+ end
@@ -40,7 +40,7 @@ module HenselCode
40
40
  numbers = [send("random_#{type}", bits)]
41
41
  while numbers.size < quantity
42
42
  number = send("random_#{type}", bits)
43
- numbers << number if number != numbers.last
43
+ numbers << number unless numbers.include?(number)
44
44
  end
45
45
  numbers
46
46
  end
@@ -38,8 +38,9 @@ module HenselCode
38
38
  @hensel_code = number
39
39
  decode
40
40
  else
41
- raise WrongHenselCodeInputType, "number must be a Rational or an\
42
- Array of truncated p-adic Hensel codes and it was a #{number.class}"
41
+ message = "number must be a Rational or an\
42
+ Array of truncated p-adic Hensel codes and it was a #{number.class}"
43
+ raise WrongHenselCodeInputType, message
43
44
  end
44
45
  end
45
46
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HenselCode
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.1"
5
5
  end
data/lib/hensel_code.rb CHANGED
@@ -23,11 +23,13 @@ module HenselCode
23
23
  autoload :GAdicVerifier, "hensel_code/gadic_verifier"
24
24
  autoload :ModularArithmetic, "hensel_code/modular_arithmetic"
25
25
  autoload :FinitePadicExpansion, "hensel_code/finite_padic_expansion"
26
+ autoload :FiniteGadicExpansion, "hensel_code/finite_gadic_expansion"
26
27
  autoload :TruncatedFinitePadicExpansion, "hensel_code/truncated_finite_padic_expansion"
27
28
  autoload :TruncatedFiniteGadicExpansion, "hensel_code/truncated_finite_gadic_expansion"
28
29
 
29
30
  # aliases for classes with long names
30
31
  TFPE = TruncatedFinitePadicExpansion
32
+ FPE = TruncatedFinitePadicExpansion
31
33
  HCWDPAE = HenselCodesWithDifferentPrimesAndExponents
32
34
  WHIT = WrongHenselCodeInputType
33
35
  end
metadata CHANGED
@@ -1,16 +1,45 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hensel_code
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David William Silva
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-03-13 00:00:00.000000000 Z
12
- dependencies: []
13
- description: A Ruby library for homomorphically representing rational numbers as integers.
11
+ date: 2022-04-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: openssl
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 3.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 3.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: prime
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.1.2
41
+ description: A Ruby library for error-free computation via homomorphic encoding of
42
+ rational numbers.
14
43
  email:
15
44
  - contact@davidwsilva.com
16
45
  executables: []
@@ -26,7 +55,9 @@ files:
26
55
  - README.md
27
56
  - Rakefile
28
57
  - codecov
58
+ - hensel_code.gemspec
29
59
  - lib/hensel_code.rb
60
+ - lib/hensel_code/finite_gadic_expansion.rb
30
61
  - lib/hensel_code/finite_padic_expansion.rb
31
62
  - lib/hensel_code/gadic_base.rb
32
63
  - lib/hensel_code/gadic_verifier.rb
@@ -65,5 +96,5 @@ requirements: []
65
96
  rubygems_version: 3.3.3
66
97
  signing_key:
67
98
  specification_version: 4
68
- summary: Homomorphic encoding of rational numbers.
99
+ summary: Error-free computation with homomorphic encoding of rational numbers.
69
100
  test_files: []