def frobenius_trace(curve): """ Compute the trace of the Frobenius endomorphism for the given EllpiticCurve @p curve. This is an implementation of Schoof's original algorithm for counting the points of an elliptic curve over a finite field. @return The trace @f$ t @f$ of the Frobenius endomorphism. The number of points on the curve then is @f$ q + 1 - t @f$, where @f$ q @f$ is the size of the finite field over which the curve was defined. """ # Initialize variables and parameters trace_congruences = [] search_range = possible_frobenius_trace_range(curve.field()) upper_prime_bound = inverse_primorial( len(search_range), shunned=curve.field().characteristic()) # Collect the congruence equations (avoid multivariate # polynomial arithmetic by handling 2-torsion separately) trace_congruences.append(frobenius_trace_mod_2(curve)) torsion_group = LTorsionGroup(curve) for prime in primes_range(3, upper_prime_bound + 1): if prime != curve.field().characteristic(): trace_congruences.append( frobenius_trace_mod_l(torsion_group(prime))) # Recover the unique valid trace representative trace_congruence = solve_congruence_equations(trace_congruences) return representative_in_range(trace_congruence, search_range)
def greedy_prime_factors(n, shunned=0): """ Return a list of the first primes whose product is greater than, or equal to @p n, but do not use @p shunned. For example, if @p n is 14, then the returned list will consist of 3 and 5, but not 2, because 3 times 5 is greater than 14. The function behaves like inverse_primorial() except that it removes unnecessary smaller primes. @note Canceling of unnecessary primes follows a greedy algorithm. Therefore the choice of primes might be suboptimal; perfect choice, however, is an NP-complete problem (KNAPSACK). @note This function uses primes_range() to obtain a list of primes. See the notes there for use case limitations. """ primes = primes_range(2, n + 1) # Find the smallest product of primes that is at least n, but don't use # the shunned prime. product = 1 for index, prime in enumerate(primes): if prime != shunned: product *= prime if product >= n: break # Throw away excess primes primes = primes[:index + 1] if shunned in primes: primes.remove(shunned) # Try to cancel unnecessary primes, largest first. # (This greedy search is not optimal; however, we did not set out to solve # the KNAPSACK problem, did we?) for index, prime in enumerate(reversed(primes)): canceled_product = product / prime if canceled_product >= n: product = canceled_product primes[-(index + 1)] = 0 return list(filter(None, primes))
def greedy_prime_factors(n, shunned=0): """ Return a list of the first primes whose product is greater than, or equal to @p n, but do not use @p shunned. For example, if @p n is 14, then the returned list will consist of 3 and 5, but not 2, because 3 times 5 is greater than 14. The function behaves like inverse_primorial() except that it removes unnecessary smaller primes. @note Canceling of unnecessary primes follows a greedy algorithm. Therefore the choice of primes might be suboptimal; perfect choice, however, is an NP-complete problem (KNAPSACK). @note This function uses primes_range() to obtain a list of primes. See the notes there for use case limitations. """ primes = primes_range( 2, n+1 ) # Find the smallest product of primes that is at least n, but don't use # the shunned prime. product = 1 for index, prime in enumerate( primes ): if prime != shunned: product *= prime if product >= n: break # Throw away excess primes primes = primes[ : index+1 ] if shunned in primes: primes.remove( shunned ) # Try to cancel unnecessary primes, largest first. # (This greedy search is not optimal; however, we did not set out to solve # the KNAPSACK problem, did we?) for index, prime in enumerate( reversed( primes ) ): canceled_product = product / prime if canceled_product >= n: product = canceled_product primes[ -(index+1) ] = 0 return list( filter( None, primes ) )
def frobenius_trace(curve): """ Compute the trace of the Frobenius endomorphism for the given EllpiticCurve @p curve. This is an implementation of Schoof's original algorithm for counting the points of an elliptic curve over a finite field. @return The trace @f$ t @f$ of the Frobenius endomorphism. The number of points on the curve then is @f$ q + 1 - t @f$, where @f$ q @f$ is the size of the finite field over which the curve was defined. """ # Initialize variables and parameters trace_congruences = [] search_range = possible_frobenius_trace_range( curve.field() ) upper_prime_bound = inverse_primorial( len(search_range), shunned = curve.field().characteristic() ) # Collect the congruence equations (avoid multivariate # polynomial arithmetic by handling 2-torsion separately) trace_congruences.append( frobenius_trace_mod_2( curve ) ) torsion_group = LTorsionGroup( curve ) for prime in primes_range( 3, upper_prime_bound+1 ): if prime != curve.field().characteristic(): trace_congruences.append( frobenius_trace_mod_l( torsion_group( prime ) ) ) # Recover the unique valid trace representative trace_congruence = solve_congruence_equations( trace_congruences ) return representative_in_range( trace_congruence, search_range )
def test_iterable(self): """Iterable return type""" self.assert_([2, 3, 5] == [p for p in primes_range(2, 6)])
def test_empty(self): """Empty primes interval""" self.assert_(not primes_range(3, 2))
def test_upper_bound(self): """Exclusive upper bound""" self.assert_(list(primes_range(1, 7)) == [2, 3, 5])
def test_lower_bound(self): """Inclusive lower bound""" self.assert_(list(primes_range(3, 10)) == [3, 5, 7])
def test_results(self): """Sample results""" self.assert_(list(primes_range(1, 10)) == [2, 3, 5, 7])
def test_iterable(self): """Iterable return type""" self.assert_( [2, 3, 5] == [ p for p in primes_range(2, 6) ] )
def test_empty(self): """Empty primes interval""" self.assert_( not primes_range(3, 2) )
def test_upper_bound(self): """Exclusive upper bound""" self.assert_( list(primes_range(1, 7)) == [2, 3, 5] )
def test_lower_bound(self): """Inclusive lower bound""" self.assert_( list(primes_range(3, 10)) == [3, 5, 7] )
def test_results(self): """Sample results""" self.assert_( list(primes_range(1, 10)) == [2, 3, 5, 7] )