Module: HenselCode::Tools
- Included in:
- GAdicBase, PAdicBase, Polynomial
- Defined in:
- lib/hensel_code/tools.rb
Overview
Required basics of number generation and modular
Instance Method Summary collapse
- #crt(moduli, remainders) ⇒ Object
- #eea_core(num1, num2, bound = 0) ⇒ Object
- #extended_gcd(num1, num2) ⇒ Object
- #mod_inverse(num, mod) ⇒ Object
- #random_distinct_numbers(type, quantity, bits) ⇒ Object
- #random_integer(bits) ⇒ Object
- #random_prime(bits) ⇒ Object
- #random_rational(bits) ⇒ Object
Instance Method Details
#crt(moduli, remainders) ⇒ Object
81 82 83 84 85 86 87 88 89 90 |
# File 'lib/hensel_code/tools.rb', line 81 def crt(moduli, remainders) g = moduli.inject(:*) result = 0 moduli.zip(remainders) do |modulus, remainder| g_prime = g / modulus g_prime_inverse = mod_inverse(g_prime, modulus) result += ((g_prime * g_prime_inverse * remainder)) end result % g end |
#eea_core(num1, num2, bound = 0) ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/hensel_code/tools.rb', line 48 def eea_core(num1, num2, bound = 0) setup = bound.zero? ? [1, 0] : [0, 1] x0, x1, y0, y1 = [num1, num2] + setup i = 1 while x1 > bound q = x0 / x1 x0, x1 = x1, x0 - (q * x1) y0, y1 = y1, y0 - (q * y1) i += 1 end [x0, y0, i, x1, y1] end |
#extended_gcd(num1, num2) ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/hensel_code/tools.rb', line 61 def extended_gcd(num1, num2) if num1.negative? x, y = extended_gcd(-num1, num2) [x, -y] elsif num2.negative? x, y = extended_gcd(num1, -num2) [x, y] else x, y = eea_core(num1, num2) [x, y] end end |
#mod_inverse(num, mod) ⇒ Object
74 75 76 77 78 79 |
# File 'lib/hensel_code/tools.rb', line 74 def mod_inverse(num, mod) x, y, = extended_gcd(num, mod) raise ZeroDivisionError, "#{num} has no inverse modulo #{mod}" unless x == 1 y % mod end |
#random_distinct_numbers(type, quantity, bits) ⇒ Object
39 40 41 42 43 44 45 46 |
# File 'lib/hensel_code/tools.rb', line 39 def random_distinct_numbers(type, quantity, bits) numbers = [send("random_#{type}", bits)] while numbers.size < quantity number = send("random_#{type}", bits) numbers << number unless numbers.include?(number) end numbers end |
#random_integer(bits) ⇒ Object
6 7 8 |
# File 'lib/hensel_code/tools.rb', line 6 def random_integer(bits) OpenSSL::BN.rand(bits).to_i end |
#random_prime(bits) ⇒ Object
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/hensel_code/tools.rb', line 19 def random_prime(bits) # The OpenSSL library only generates random primes from 16 bits on # The 3513 is the first 16-bit number # which means there are 3512 primes under 16 bits in length # Therefore for allowing values for the parameter 'bits' between 2 and 15, # we generate all primes from 2 to 15 bits using Ruby's Prime library # and select only those with bit length equal to the value of 'bits' # so we sample one element # We only do this if the value of 'bits' is less than 16, otherwise we # use OpenSSL to generate the prime if bits >= 2 && bits < 16 primes = Prime.first(3512) primes.select { |p| p.bit_length == bits }.sample elsif bits >= 16 OpenSSL::BN.generate_prime(bits).to_i else raise BadBitRangeForRandomPrime, "The bit length must be greater than or equal to 2" end end |
#random_rational(bits) ⇒ Object
10 11 12 13 14 15 16 17 |
# File 'lib/hensel_code/tools.rb', line 10 def random_rational(bits) numbers = [random_integer(bits)] while numbers.size < 2 num = random_integer(bits) numbers << num if numbers.last.gcd(num) == 1 end Rational(*numbers) end |