Ticket #5945: trac_5945-461rc0.patch
| File trac_5945-461rc0.patch, 21.9 KB (added by spancratz, 2 years ago) |
|---|
-
module_list.py
# HG changeset patch # User Sebastian Pancratz <sage@pancratz.org> # Date 1294633352 28800 # Node ID 095f6085dfb00318fe068410e42561dddc74bc27 # Parent 765e07e05a78260d992cef6656f80a0cb4e6e35f [mq]: trac_5945 * * * finished diff -r 99907a4478f7 module_list.py
a b 1175 1175 1176 1176 Extension('sage.rings.integer', 1177 1177 sources = ['sage/rings/integer.pyx'], 1178 libraries=['ntl', 'gmp', 'pari'], 1179 depends = numpy_depends), 1178 libraries=['ntl', 'gmp', 'pari', 'flint'], 1179 include_dirs = [SAGE_INC + '/FLINT/'], 1180 depends = numpy_depends + flint_depends), 1180 1181 1181 1182 Extension('sage.rings.integer_ring', 1182 1183 sources = ['sage/rings/integer_ring.pyx'], -
sage/libs/flint/long_extras.pxd
diff -r 99907a4478f7 sage/libs/flint/long_extras.pxd
a b 6 6 7 7 cdef extern from "FLINT/long_extras.h": 8 8 9 ctypedef struct factor_t: 10 int num 11 unsigned long p[15] 12 unsigned long exp[15] 13 9 14 cdef unsigned long z_randint(unsigned long limit) 10 15 11 16 cdef unsigned long z_randbits(unsigned long bits) -
sage/misc/sageinspect.py
diff -r 99907a4478f7 sage/misc/sageinspect.py
a b 1053 1053 A cython function with default arguments (one of which is a string):: 1054 1054 1055 1055 sage: sage_getdef(sage.rings.integer.Integer.factor, obj_name='factor') 1056 "factor(algorithm='pari', proof=True, limit=None )"1056 "factor(algorithm='pari', proof=True, limit=None, int_=False, verbose=0)" 1057 1057 1058 1058 This used to be problematic, but was fixed in #10094:: 1059 1059 -
sage/rings/arith.py
diff -r 99907a4478f7 sage/rings/arith.py
a b 2076 2076 else: 2077 2077 return ZZ(n).trial_division(bound) 2078 2078 2079 def __factor_using_trial_division(n):2080 """2081 Returns the factorization of the integer n as a sorted list of2082 tuples (p,e).2083 2084 INPUT:2085 2086 2087 - ``n`` - an integer2088 2089 2090 OUTPUT:2091 2092 2093 - ``list`` - factorization of n2094 2095 EXAMPLES::2096 2097 sage: from sage.rings.arith import __factor_using_trial_division2098 sage: __factor_using_trial_division(100)2099 [(2, 2), (5, 2)]2100 """2101 if n in [-1, 0, 1]: return []2102 if n < 0: n = -n2103 F = []2104 while n != 1:2105 p = trial_division(n)2106 e = 12107 n /= p2108 while n%p == 0:2109 e += 1; n /= p2110 F.append((p,e))2111 F.sort()2112 return F2113 2114 def __factor_using_pari(n, int_=False, debug_level=0, proof=None):2115 """2116 Factors an integer using pari.2117 2118 INPUT:2119 2120 - ``n`` - an integer2121 2122 EXAMPLES::2123 2124 sage: from sage.rings.arith import __factor_using_pari2125 sage: __factor_using_pari(100)2126 [(2, 2), (5, 2)]2127 sage: __factor_using_pari(720)2128 [(2, 4), (3, 2), (5, 1)]2129 """2130 if proof is None:2131 from sage.structure.proof.proof import get_flag2132 proof = get_flag(proof, "arithmetic")2133 if int_:2134 Z = int2135 else:2136 Z = ZZ2137 prev = pari.get_debug_level()2138 2139 if prev != debug_level:2140 pari.set_debug_level(debug_level)2141 2142 F = pari(n).factor(proof=proof)2143 B = F[0]2144 e = F[1]2145 v = [(Z(B[i]),Z(e[i])) for i in xrange(len(B))]2146 2147 if prev != debug_level:2148 pari.set_debug_level(prev)2149 2150 return v2151 2152 2153 #todo: add a limit option to factor, so it will only split off2154 # primes at most a given limit.2155 2156 2079 def factor(n, proof=None, int_=False, algorithm='pari', verbose=0, **kwds): 2157 2080 """ 2158 Returns the factorization of n. The result depends on the type of2159 n.2160 2161 If n is an integer, factor returns the factorization of the2162 integer n as an object of type Factorization.2081 Returns the factorization of ``n``. The result depends on the 2082 type of ``n``. 2083 2084 If ``n`` is an integer, returns the factorization as an object 2085 of type ``Factorization``. 2163 2086 2164 2087 If n is not an integer, ``n.factor(proof=proof, **kwds)`` gets called. 2165 2088 See ``n.factor??`` for more documentation in this case. 2166 2089 2167 2090 .. warning:: 2168 2091 2169 This means that applying factorto an integer result of2092 This means that applying ``factor`` to an integer result of 2170 2093 a symbolic computation will not factor the integer, because it is 2171 2094 considered as an element of a larger symbolic ring. 2172 2095 … … 2176 2099 sage: is_prime(f(3)) 2177 2100 False 2178 2101 sage: factor(f(3)) 2179 9 2102 9 2180 2103 2181 2104 INPUT: 2182 2105 … … 2200 2123 variable is set to this; e.g., set to 4 or 8 to see lots of output 2201 2124 during factorization. 2202 2125 2203 2204 OUTPUT: factorization of n 2126 OUTPUT: 2127 2128 - factorization of n 2205 2129 2206 2130 The qsieve and ecm commands give access to highly optimized 2207 2131 implementations of algorithms for doing certain integer … … 2261 2185 sage: factor(2^(2^7)+1) 2262 2186 59649589127497217 * 5704689200685129054721 2263 2187 2264 Sage calls PARI's factor, which has proof False by default. Sage2265 has a global proof flag, set to True by default (see2266 :mod:`sage.structure.proof.proof`, or proof.[tab]). To override the default,2267 call this function with proof=False.2188 Sage calls PARI's factor, which has proof False by default. 2189 Sage has a global proof flag, set to True by default (see 2190 :mod:`sage.structure.proof.proof`, or proof.[tab]). To override 2191 the default, call this function with proof=False. 2268 2192 2269 2193 :: 2270 2194 … … 2273 2197 2274 2198 :: 2275 2199 2276 sage: factor(2^197 + 1) # takes a long time (e.g., 3 seconds!)2200 sage: factor(2^197 + 1) # long time 2277 2201 3 * 197002597249 * 1348959352853811313 * 251951573867253012259144010843 2278 2202 2279 2203 Any object which has a factor method can be factored like this:: … … 2296 2220 [4, 3, 5, 7] 2297 2221 2298 2222 """ 2299 if not isinstance(n, (int,long, integer.Integer)): 2300 # this happens for example if n = x**2 + y**2 + 2*x*y 2223 if isinstance(n, (int, long)): 2224 n = ZZ(n) 2225 2226 if isinstance(n, integer.Integer): 2227 return n.factor(proof=proof, algorithm=algorithm, 2228 int_ = int_, verbose=verbose) 2229 else: 2230 # e.g. n = x**2 + y**2 + 2*x*y 2301 2231 try: 2302 2232 return n.factor(proof=proof, **kwds) 2303 2233 except AttributeError: 2304 2234 raise TypeError, "unable to factor n" 2305 except TypeError: # just in case factor method doesn't have a proof option. 2235 except TypeError: 2236 # Just in case factor method doesn't have a proof option. 2306 2237 try: 2307 2238 return n.factor(**kwds) 2308 2239 except AttributeError: 2309 2240 raise TypeError, "unable to factor n" 2310 #n = abs(n) 2311 n = ZZ(n) 2312 if n < 0: 2313 unit = ZZ(-1) 2314 n = -n 2315 else: 2316 unit = ZZ(1) 2317 2318 if n == 0: 2319 raise ArithmeticError, "Prime factorization of 0 not defined." 2320 if n == 1: 2321 return factorization.Factorization([], unit) 2322 2323 if n < 10000000000000: 2324 return factorization.Factorization(__factor_using_trial_division(n), unit) 2325 2326 if algorithm == 'pari': 2327 return factorization.Factorization(__factor_using_pari(n, 2328 int_=int_, debug_level=verbose, proof=proof), unit) 2329 elif algorithm in ['kash', 'magma']: 2330 if algorithm == 'kash': 2331 from sage.interfaces.all import kash as I 2332 else: 2333 from sage.interfaces.all import magma as I 2334 F = I.eval('Factorization(%s)'%n) 2335 i = F.rfind(']') + 1 2336 F = F[:i] 2337 F = F.replace("<","(").replace(">",")") 2338 F = eval(F) 2339 if not int_: 2340 F = [(ZZ(a), ZZ(b)) for a,b in F] 2341 return factorization.Factorization(F, unit) 2342 else: 2343 raise ValueError, "Algorithm is not known" 2344 2345 2346 def prime_divisors(n): 2241 2242 def prime_divisors(n): 2347 2243 """ 2348 2244 The prime divisors of the integer n, sorted in increasing order. If 2349 2245 n is negative, we do *not* include -1 among the prime divisors, -
sage/rings/integer.pyx
diff -r 99907a4478f7 sage/rings/integer.pyx
a b 163 163 cdef double ceil_c "ceil" (double) 164 164 165 165 from sage.libs.pari.gen cimport gen as pari_gen, PariInstance 166 from sage.libs.flint.long_extras cimport * 166 167 167 168 import sage.rings.infinity 168 169 import sage.libs.pari.all … … 2950 2951 2951 2952 def trial_division(self, long bound=LONG_MAX): 2952 2953 """ 2953 Return smallest prime divisor of self up to limit, or 2954 abs(self) if no such divisor is found. 2955 2956 INPUT: 2957 - ``bound`` -- positive integer 2954 Return smallest prime divisor of self up to bound, 2955 or abs(self) if no such divisor is found. 2956 2957 INPUT: 2958 2959 - ``bound`` -- a positive integer that fits in a C signed long 2958 2960 2959 2961 OUTPUT: 2962 2960 2963 - a positive integer 2961 2964 2962 2965 EXAMPLES:: 2963 2966 2964 2967 sage: n = next_prime(10^6)*next_prime(10^7); n.trial_division() … … 3055 3058 mpz_abs(x.value, self.value) 3056 3059 return x 3057 3060 3058 def _factor_trial_division(self, l imit):3061 def _factor_trial_division(self, long limit=LONG_MAX): 3059 3062 """ 3060 3063 Return partial factorization of self obtained using trial division 3061 3064 for all primes up to limit, where limit must fit in a signed int. 3062 3065 3063 3066 INPUT: 3064 3067 3065 3066 - ``limit`` - integer that fits in a signed int 3067 3068 3069 ALGORITHM: Uses Pari. 3068 - ``limit`` - integer that fits in a C signed long 3070 3069 3071 3070 EXAMPLES:: 3072 3071 … … 3076 3075 sage: n._factor_trial_division(2000) 3077 3076 2 * 11 * 1531 * 27325696005058797691594630609938486205809701 3078 3077 """ 3079 import sage.structure.factorization as factorization 3080 F = self._pari_().factor(limit) 3078 from sage.structure.factorization_integer import IntegerFactorization 3079 cdef Integer n = PY_NEW(Integer), p, unit 3080 cdef unsigned long e 3081 3082 if mpz_sgn(self.value) > 0: 3083 mpz_set(n.value, self.value) 3084 unit = ONE 3085 else: 3086 mpz_neg(n.value,self.value) 3087 unit = PY_NEW(Integer) 3088 mpz_set_si(unit.value, -1) 3089 3090 F = [] 3091 while mpz_cmpabs_ui(n.value, 1): 3092 p = n.trial_division(bound=limit) 3093 e = mpz_remove(n.value, n.value, p.value) 3094 F.append((p,e)) 3095 3096 return IntegerFactorization(F, unit=unit, unsafe=True, 3097 sort=False, simplify=False) 3098 3099 def __factor_using_pari(n, int_=False, debug_level=0, proof=None): 3100 """ 3101 Factors this (positive) integer using PARI. 3102 3103 This method returns a list of pairs, not a ``Factorization`` 3104 object. The first element of each pair is the factor, of type 3105 ``Integer`` if ``int_`` is ``False`` or ``int`` otherwise, 3106 the second element is the positive exponent, of type ``int``. 3107 3108 INPUT: 3109 3110 - ``int_`` -- (default: ``False``), whether the factors are 3111 of type ``int`` instead of ``Integer`` 3112 3113 - ``debug_level`` -- (default: 0), debug level of the call 3114 to PARI 3115 3116 - ``proof`` -- (default: ``None``), whether the factors are 3117 required to be proven prime; if ``None``, the global default 3118 is used 3119 3120 OUTPUT: 3121 3122 - a list of pairs 3123 3124 EXAMPLES:: 3125 3126 sage: factor(2**72 - 3, algorithm='pari') # indirect doctest 3127 83 * 131 * 294971519 * 1472414939 3128 """ 3129 from sage.libs.pari.gen import pari 3130 3131 if proof is None: 3132 from sage.structure.proof.proof import get_flag 3133 proof = get_flag(proof, "arithmetic") 3134 3135 prev = pari.get_debug_level() 3136 3137 if prev != debug_level: 3138 pari.set_debug_level(debug_level) 3139 3140 F = pari(n).factor(proof=proof) 3081 3141 B, e = F 3082 return factorization.Factorization([(the_integer_ring(B[i]), the_integer_ring(e[i])) for i in range(len(B))]) 3083 3084 def factor(self, algorithm='pari', proof=True, limit=None): 3085 """ 3086 Return the prime factorization of the integer as a list of pairs 3087 `(p,e)`, where `p` is prime and `e` is a 3088 positive integer. 3089 3090 INPUT: 3091 3142 if int_: 3143 v = [(int(B[i]), int(e[i])) for i in xrange(len(B))] 3144 else: 3145 v = [(Integer(B[i]), int(e[i])) for i in xrange(len(B))] 3146 3147 if prev != debug_level: 3148 pari.set_debug_level(prev) 3149 3150 return v 3151 3152 def factor(self, algorithm='pari', proof=None, limit=None, int_=False, 3153 verbose=0): 3154 """ 3155 Return the prime factorization of this integer as a list of pairs 3156 `(p, e)`, where `p` is prime and `e` is a positive integer. 3157 3158 INPUT: 3092 3159 3093 3160 - ``algorithm`` - string 3094 3161 3095 - ``'pari'`` - (default) use the PARI clibrary3096 3097 - ``'kash'`` - use KASH computer algebra system (requires3098 the optional kash package be installed)3162 - ``'pari'`` - (default) use the PARI library 3163 3164 - ``'kash'`` - use the KASH computer algebra system (requires 3165 the optional kash package) 3099 3166 3100 3167 - ``proof`` - bool (default: True) whether or not to 3101 3168 prove primality of each factor (only applicable for PARI). … … 3104 3171 given it must fit in a signed int, and the factorization is done 3105 3172 using trial division and primes up to limit. 3106 3173 3107 3108 3174 EXAMPLES:: 3109 3175 3110 3176 sage: n = 2^100 - 1; n.factor() … … 3131 3197 ... 3132 3198 ValueError: Algorithm is not known 3133 3199 """ 3200 from sage.structure.factorization import Factorization 3201 from sage.structure.factorization_integer import IntegerFactorization 3202 3203 cdef Integer n, p, unit 3204 cdef int i 3205 cdef factor_t f 3206 3207 if mpz_sgn(self.value) == 0: 3208 raise ArithmeticError, "Prime factorization of 0 not defined." 3209 3210 if mpz_sgn(self.value) > 0: 3211 n = self 3212 unit = ONE 3213 else: 3214 n = PY_NEW(Integer) 3215 unit = PY_NEW(Integer) 3216 mpz_neg(n.value, self.value) 3217 mpz_set_si(unit.value, -1) 3218 3219 if mpz_cmpabs_ui(n.value, 1) == 0: 3220 return IntegerFactorization([], unit=unit, unsafe=True, 3221 sort=False, simplify=False) 3222 3134 3223 if limit is not None: 3135 3224 return self._factor_trial_division(limit) 3136 import sage.rings.integer_ring 3137 return sage.rings.integer_ring.factor(self, algorithm=algorithm, proof=proof) 3225 3226 if proof is None: 3227 from sage.structure.proof.proof import get_flag 3228 proof = get_flag(proof, "arithmetic") 3229 3230 if mpz_fits_slong_p(n.value): 3231 z_factor(&f, mpz_get_ui(n.value), proof) 3232 F = [(Integer(f.p[i]), int(f.exp[i])) for i from 0 <= i < f.num] 3233 F.sort() 3234 return IntegerFactorization(F, unit=unit, unsafe=True, 3235 sort=False, simplify=False) 3236 3237 if mpz_sizeinbase(n.value, 2) < 40: 3238 return self._factor_trial_division() 3239 3240 if algorithm == 'pari': 3241 F = n.__factor_using_pari(int_=int_, debug_level=verbose, proof=proof) 3242 F.sort() 3243 return IntegerFactorization(F, unit=unit, unsafe=True, 3244 sort=False, simplify=False) 3245 elif algorithm in ['kash', 'magma']: 3246 if algorithm == 'kash': 3247 from sage.interfaces.all import kash as I 3248 else: 3249 from sage.interfaces.all import magma as I 3250 F = I.eval('Factorization(%s)'%n) 3251 i = F.rfind(']') + 1 3252 F = F[:i] 3253 F = F.replace("<","(").replace(">",")") 3254 F = eval(F) 3255 if not int_: 3256 F = [(Integer(a), int(b)) for a,b in F] 3257 return Factorization(F, unit) 3258 else: 3259 raise ValueError, "Algorithm is not known" 3138 3260 3139 3261 def _factor_cunningham(self, proof=True): 3140 3262 """ -
sage/rings/integer_ring.pyx
diff -r 99907a4478f7 sage/rings/integer_ring.pyx
a b 80 80 81 81 import ring 82 82 83 arith = None 84 cdef void late_import(): 85 global arith 86 if arith is None: 87 import sage.rings.arith 88 arith = sage.rings.arith 89 83 90 cdef int number_of_integer_rings = 0 84 91 85 92 def is_IntegerRing(x): … … 1054 1061 """ 1055 1062 return ZZ 1056 1063 1057 def factor( n, algorithm='pari', proof=True):1064 def factor(*args, **kwds): 1058 1065 """ 1059 Return the factorization of the positive integer `n` as a 1060 sorted list of tuples `(p_i,e_i)` such that 1061 `n=\prod p_i^{e_i}`. 1062 1063 For further documentation see sage.rings.arith.factor() 1064 1066 This function is deprecated. To factor an Integer `n`, call `n.factor()`. 1067 For other objects, use the factor method from sage.rings.arith. 1068 1065 1069 EXAMPLE:: 1066 1067 sage: sage.rings.integer_ring.factor(420) 1068 2^2 * 3 * 5 * 7 1070 1071 sage: sage.rings.integer_ring.factor(1) 1072 doctest:...: DeprecationWarning: This function is deprecated... 1073 1 1069 1074 """ 1070 import sage.rings.arith 1071 return sage.rings.arith.factor(n, algorithm=algorithm, proof=proof) 1072 1075 from sage.misc.misc import deprecation 1076 deprecation("This function is deprecated. Call the factor method of an Integer," 1077 +"or sage.arith.factor instead.") 1078 #deprecated 4.6.2 1079 1080 late_import() 1081 return arith.factor(*args, **kwds) 1082 1073 1083 import sage.misc.misc 1074 1084 def crt_basis(X, xgcd=None): 1075 1085 """ -
new file sage/structure/factorization_integer.py
diff -r 99907a4478f7 sage/structure/factorization_integer.py
- + 1 from sage.structure.factorization import Factorization 2 3 from sage.rings.integer_ring import ZZ 4 5 class IntegerFactorization(Factorization): 6 """ 7 A lightweight class for an ``IntegerFactorization`` object, 8 inheriting from the more general ``Factorization`` class. 9 10 In the ``Factorization`` class the user has to create a list 11 containing the factorization data, which is then passed to the 12 actual ``Factorization`` object upon initialization. 13 14 However, for the typical use of integer factorization via 15 the ``Integer.factor()`` method in ``sage.rings.integer`` 16 this is noticeably too much overhead, slowing down the 17 factorization of integers of up to about 40 bits by a factor 18 of around 10. Moreover, the initialization done in the 19 ``Factorization`` class is typically unnecessary: the caller 20 can guarantee that the list contains pairs of an ``Integer`` 21 and an ``int``, as well as that the list is sorted. 22 23 AUTHOR: 24 25 - Sebastian Pancratz (2010-01-10) 26 """ 27 28 def __init__(self, x, unit=None, cr=False, sort=True, simplify=True, 29 unsafe=False): 30 """ 31 Sets ``self`` to the factorization object with list ``x``, 32 which must be a sorted list of pairs, where each pair contains 33 a factor and an exponent. 34 35 If the flag ``unsafe`` is set to ``False`` this method delegates 36 the initialization to the parent class, which means that a rather 37 lenient and careful way of initialization is chosen. For example, 38 elements are coerced or converted into the right parents, multiple 39 occurrences of the same factor are collected (in the commutative 40 case), the list is sorted (unless ``sort`` is ``False``) etc. 41 42 However, if the flag is set to ``True``, no error handling is 43 carried out. The list ``x`` is assumed to list of pairs. The 44 type of the factors is assumed to be constant across all factors: 45 either ``Integer`` (the generic case) or ``int`` (as supported 46 by the flag ``int_`` of the ``factor()`` method). The type of 47 the exponents is assumed to be ``int``. The list ``x`` itself 48 will be referenced in this factorization object and hence the 49 caller is responsible for not changing the list after creating 50 the factorization. The unit is assumed to be either ``None`` or 51 of type ``Integer``, taking one of the values `+1` or `-1`. 52 53 EXAMPLES:: 54 55 sage: factor(15) 56 3 * 5 57 """ 58 if unsafe: 59 if unit is None: 60 self._Factorization__unit = sage.rings.integer.ONE 61 else: 62 self._Factorization__unit = unit 63 64 self._Factorization__x = x 65 self._Factorization__universe = ZZ 66 self._Factorization__cr = cr 67 68 if sort: 69 self.sort() 70 if simplify: 71 self.simplify() 72 73 else: 74 super(IntegerFactorization, self).__init__(x, 75 unit=unit, cr=cr, sort=sort, simplify=simplify) 76 77 def __sort__(self, _cmp=None): 78 """ 79 Sort the factors in this factorization. 80 81 INPUT: 82 83 - ``_cmp`` - (default: None) comparison function 84 85 EXAMPLES:: 86 87 sage: F = factor(15) 88 sage: F.sort(_cmp = lambda x,y: -cmp(x,y)) 89 sage: F 90 5 * 3 91 """ 92 self.__x.sort(_cmp) 93
