def random(cls, allow_inf=True) -> 'FPVector': bias = (1 << (cls.exponent_size - 1)) - 1 if allow_inf: sign = random.choice([-1, 1]) mantissa = gmpy2.mpfr_random(gmpy2.random_state()) + 1 exp = random.randint(1 - bias, bias + 1) return cls(mantissa * sign * (gmpy2.mpfr(2)**gmpy2.mpfr(exp))) else: sign = random.choice([-1, 1]) mantissa = gmpy2.mpfr_random(gmpy2.random_state()) + 1 exp = random.randint(1 - bias, bias) return cls(mantissa * sign * (gmpy2.mpfr(2)**gmpy2.mpfr(exp)))
def process_f_with_multiplicative_group(N): while True: j = gmpy2.mpz_random(random_state, int(lg(N))) + 1 r = gmpy2.mpz_random(random_state, 2**j) if j < threshold_bits: # For small numbers, run the old process_f # Multiplicative group hint can be computed later r = gmpy2.mpz_random(random_state, 2**j) q = 2**j + r if q > N: continue p, alpha = prime_power(q) if not p: continue l = gmpy2.mpfr_random(random_state) if l < delta_n(N, p, alpha) * 2**int(lg(q)): return p, alpha, {} else: # Generate a random factored number between (2 ** j - 1) and (2 ** (j + 1) - 2) # This is so that we get the multiplicative group of q x, xf = process_r(2**(j + 1) - 2) q = x + 1 if q > N: continue p, alpha = prime_power(q) if not p: continue l = gmpy2.mpfr_random(random_state) if l < delta_n(N, p, alpha) * 2**int(lg(q)): if alpha == 1: phi_hint = xf else: # This is a special case: in this case xf isn't the multiplicative group # But luckily since p^alpha - 1 = (p - 1) * (1 + p + ... + p^(alpha - 1)) # we will still have all the factors to get the factorisation of p - 1 phi_hint = [] remaining_x = x for f in xf: if remaining_x % f == 0: phi_hint.append(f) remaining_x /= f if remaining_x == 1: break return p, alpha, {p: phi_hint}
def process_r(N): if N < 2**threshold_bits: x = gmpy2.mpz_random(random_state, (N + 1) // 2) + N // 2 + 1 return x, factor_N(x) while True: p, alpha = process_f(N) q = p**alpha Nprime = int(N // q) y, yf = process_r(Nprime) x = y * q l = gmpy2.mpfr_random(random_state) if l < gmpy2.log(N // 2) / gmpy2.log(x): return x, [p] * alpha + yf
def process_f(N): while True: j = gmpy2.mpz_random(random_state, int(lg(N))) + 1 r = gmpy2.mpz_random(random_state, 2**j) q = 2**j + r if q > N: continue p, alpha = prime_power(q) if not p: continue l = gmpy2.mpfr_random(random_state) if l < delta_n(N, p, alpha) * 2**int(lg(q)): return p, alpha
def process_r_with_multiplicative_group(N): if N < 2**threshold_bits: x = gmpy2.mpz_random(random_state, (N + 1) // 2) + N // 2 + 1 xf = factor_N(x) # No factorisation hints for small factors, we can easily generate them later return x, xf, {} while True: p, alpha, phi_hint = process_f_with_multiplicative_group(N) q = p**alpha Nprime = int(N // q) y, yf, phi_hint2 = process_r_with_multiplicative_group(Nprime) x = y * q l = gmpy2.mpfr_random(random_state) if l < gmpy2.log(N // 2) / gmpy2.log(x): phi_hint.update(phi_hint2) return x, [p] * alpha + yf, phi_hint
def random(): seed = int(os.urandom(BYTES).encode('hex'), 16) return gmpy2.mpfr_random(gmpy2.random_state(seed))