# HG changeset patch
# User André Apitzsch <andre.apitzsch@st.ovgu.de>
# Date 1289383125 -3600
# Node ID c2d3f247e584407759cf852d0188f55c9a14e895
# Parent  09f6bc4be04a7f6e2ad6e574a49a68ce3269c38e
trac 5945: factorization using flint

diff -r 09f6bc4be04a -r c2d3f247e584 module_list.py
--- a/module_list.py	Sun Nov 07 23:55:16 2010 +0100
+++ b/module_list.py	Wed Nov 10 10:58:45 2010 +0100
@@ -1185,7 +1185,9 @@
 
     Extension('sage.rings.fast_arith',
               sources = ['sage/rings/fast_arith.pyx'],
-              libraries=['gmp','pari','csage']), 
+              libraries=['gmp','pari','csage', 'flint'],
+              include_dirs = [SAGE_LOCAL+'/include/FLINT/'],  
+              depends = flint_depends), 
 
     Extension('sage.rings.fraction_field_element',
               sources = ['sage/rings/fraction_field_element.pyx']),
diff -r 09f6bc4be04a -r c2d3f247e584 sage/rings/arith.py
--- a/sage/rings/arith.py	Sun Nov 07 23:55:16 2010 +0100
+++ b/sage/rings/arith.py	Wed Nov 10 10:58:45 2010 +0100
@@ -2142,13 +2142,12 @@
 
 def factor(n, proof=None, int_=False, algorithm='pari', verbose=0, **kwds):
     """
-    Returns the factorization of n. The result depends on the type of
-    n.
-    
-    If n is an integer, factor returns the factorization of the
+    Returns the factorization of `n`. The result depends on the type of `n`.
+    
+    If `n` is an integer, factor returns the factorization of the
     integer n as an object of type Factorization.  
     
-    If n is not an integer, ``n.factor(proof=proof, **kwds)`` gets called. 
+    If `n` is not an integer, ``n.factor(proof=proof, **kwds)`` gets called. 
     See ``n.factor??`` for more documentation in this case.
 
     .. warning::
@@ -2307,8 +2306,8 @@
     if n == 1:
         return factorization.Factorization([], unit)
     
-    if n < 10000000000000:
-        return factorization.Factorization(__factor_using_trial_division(n), unit)
+    if n.nbits() <= fast_arith.flint_bits-1:
+        return factorization.Factorization(fast_arith.flint_factor(n, proof=proof),unit)
     
     if algorithm == 'pari':
         return factorization.Factorization(__factor_using_pari(n,
diff -r 09f6bc4be04a -r c2d3f247e584 sage/rings/fast_arith.pyx
--- a/sage/rings/fast_arith.pyx	Sun Nov 07 23:55:16 2010 +0100
+++ b/sage/rings/fast_arith.pyx	Wed Nov 10 10:58:45 2010 +0100
@@ -52,10 +52,14 @@
 from sage.libs.pari.gen import pari
 from sage.libs.pari.gen cimport gen as pari_gen
 from sage.rings.integer cimport Integer
+from sage.libs.flint.long_extras cimport factor_t, z_factor
 
 cdef extern from "convert.h":
     cdef void t_INT_to_ZZ(mpz_t value, long *g)
 
+cdef extern from "FLINT/flint.h":
+    cdef int FLINT_BITS
+
 cpdef prime_range(start, stop=None, algorithm="pari_primes", bint py_ints=False):
     r"""
     List of all primes between start and stop-1, inclusive.  If the
@@ -431,5 +435,54 @@
         return (n,d)
     
     
+cdef list _flint_factor(unsigned long n, int proof):
+    r"""
+    Return factorization of ``n`` using flint.
+    """
+    cdef factor_t f
+    cdef int i
+    z_factor(&f,n,proof)
+    return [(Integer(f.p[i]),Integer(f.exp[i])) for i from 0 <= i < f.num]
+
+flint_bits = int(FLINT_BITS)
+
+def flint_factor(n, proof=None):
+    r"""
+    Return factorization of `n` using flint.
+
+    INPUT:
+    - ``n`` -- an integer
+    - ``proof`` -- (default: ``None``) if set to ``False`` then the factors are
+            not proved prime, otherwise the result is proved
+
+    OUTPUT:
+        Factorization of `n` as list of (prime,exponent) pairs
     
-    
+    EXAMPLES:
+        sage: from sage.rings.fast_arith import flint_factor
+        sage: flint_factor(1000)
+        [(2, 3), (5, 3)]
+        sage: flint_factor(6806443433, False)
+        [(53, 1), (128423461, 1)]
+        sage: flint_factor(6806443433, 1)
+        [(53, 1), (128423461, 1)]
+        sage: flint_factor(0)
+        [(0, 1)]
+        sage: flint_factor(1)
+        []
+        sage: flint_factor(-1234567)
+        Traceback (most recent call last):
+        ...
+        OverflowError: can't convert negative value to unsigned long
+        sage: flint_factor(2^64+1)
+        Traceback (most recent call last):
+        ...
+        OverflowError: long int too large to convert
+
+ .. NOTE:: `n` has to be non-negative and at most FLINT_BITS-1 bits.
+        Prime test is deterministic up to 10^16.
+    """
+    if proof is None:
+        from sage.structure.proof.proof import get_flag
+        proof = get_flag(proof, "arithmetic")
+    return _flint_factor(n, proof)
