@@ -14,15 +14,21 @@ Convert PARI objects to Sage types
14
14
# http://www.gnu.org/licenses/
15
15
# *****************************************************************************
16
16
17
+ from cysignals.signals cimport sig_on, sig_off
18
+
17
19
from cypari2.types cimport (GEN, typ, t_INT, t_FRAC, t_REAL, t_COMPLEX,
18
20
t_INTMOD, t_PADIC, t_INFINITY, t_VEC, t_COL,
19
21
t_VECSMALL, t_MAT, t_STR,
20
22
lg, precp)
21
23
from cypari2.pari_instance cimport prec_words_to_bits
22
- from cypari2.paridecl cimport gel, inf_get_sign
23
-
24
- from sage.rings.integer cimport Integer
25
- from sage.rings.rational cimport Rational
24
+ from cypari2.paridecl cimport *
25
+ from cypari2.gen cimport objtogen
26
+ from cypari2.stack cimport new_gen
27
+ from .convert_gmp cimport INT_to_mpz, new_gen_from_mpz_t, new_gen_from_mpq_t, INTFRAC_to_mpq
28
+
29
+ from sage.libs.gmp.mpz cimport mpz_fits_slong_p, mpz_sgn, mpz_get_ui, mpz_set, mpz_set_si
30
+ from sage.libs.gmp.mpq cimport mpq_denref, mpq_numref
31
+ from sage.rings.integer cimport smallInteger
26
32
from sage.rings.all import RealField, ComplexField, QuadraticField
27
33
from sage.matrix.args cimport MatrixArgs
28
34
from sage.rings.padics.factory import Qp
@@ -315,3 +321,209 @@ cpdef gen_to_sage(Gen z, locals=None):
315
321
from sage.misc.sage_eval import sage_eval
316
322
locals = {} if locals is None else locals
317
323
return sage_eval(str (z), locals = locals )
324
+
325
+
326
+ cpdef set_integer_from_gen(Integer self , Gen x):
327
+ r """
328
+ EXAMPLES::
329
+
330
+ sage: [Integer(pari(x)) for x in [1, 2^60, 2., GF(3)(1), GF(9,'a')(2) ]]
331
+ [1, 1152921504606846976, 2, 1, 2 ]
332
+ sage: Integer( pari( 2. 1)) # indirect doctest
333
+ Traceback ( most recent call last) :
334
+ ...
335
+ TypeError: Attempt to coerce non-integral real number to an Integer
336
+ """
337
+ # Simplify and lift until we get an integer
338
+ while typ((< Gen> x).g) != t_INT:
339
+ x = x.simplify()
340
+ paritype = typ((< Gen> x).g)
341
+ if paritype == t_INT:
342
+ break
343
+ elif paritype == t_REAL:
344
+ # Check that the fractional part is zero
345
+ if not x.frac().gequal0():
346
+ raise TypeError (" Attempt to coerce non-integral real number to an Integer" )
347
+ # floor yields an integer
348
+ x = x.floor()
349
+ break
350
+ elif paritype == t_PADIC:
351
+ if x._valp() < 0 :
352
+ raise TypeError (" Cannot convert p-adic with negative valuation to an integer" )
353
+ # Lifting a PADIC yields an integer
354
+ x = x.lift()
355
+ break
356
+ elif paritype == t_INTMOD:
357
+ # Lifting an INTMOD yields an integer
358
+ x = x.lift()
359
+ break
360
+ elif paritype == t_POLMOD:
361
+ x = x.lift()
362
+ elif paritype == t_FFELT:
363
+ # x = (f modulo defining polynomial of finite field);
364
+ # we extract f.
365
+ sig_on()
366
+ x = new_gen(FF_to_FpXQ_i((< Gen> x).g))
367
+ else :
368
+ raise TypeError (" Unable to coerce PARI %s to an Integer" % x)
369
+
370
+ # Now we have a true PARI integer, convert it to Sage
371
+ INT_to_mpz(self .value, (< Gen> x).g)
372
+
373
+
374
+ cpdef Gen new_gen_from_integer(Integer self ):
375
+ """
376
+ TESTS::
377
+
378
+ sage: Rational(pari(2)) # indirect doctest
379
+ 2
380
+ sage: Rational(pari(-1))
381
+ -1
382
+ """
383
+ return new_gen_from_mpz_t(self .value)
384
+
385
+
386
+ cpdef set_rational_from_gen(Rational self , Gen x):
387
+ r """
388
+ EXAMPLES::
389
+
390
+ sage: [Rational(pari(x)) for x in [1, 1/2, 2^60, 2., GF(3)(1), GF(9,'a')(2) ]]
391
+ [1, 1/2, 1152921504606846976, 2, 1, 2 ]
392
+ sage: Rational( pari( 2. 1)) # indirect doctest
393
+ Traceback ( most recent call last) :
394
+ ...
395
+ TypeError: Attempt to coerce non-integral real number to an Integer
396
+ """
397
+ x = x.simplify()
398
+ if is_rational_t(typ((< Gen> x).g)):
399
+ INTFRAC_to_mpq(self .value, (< Gen> x).g)
400
+ else :
401
+ a = Integer(x)
402
+ mpz_set(mpq_numref(self .value), a.value)
403
+ mpz_set_si(mpq_denref(self .value), 1 )
404
+
405
+
406
+ cpdef Gen new_gen_from_rational(Rational self ):
407
+ """
408
+ TESTS::
409
+
410
+ sage: Integer(pari(2/2)) # indirect doctest
411
+ 1
412
+ sage: Rational(pari(-1/2))
413
+ -1/2
414
+ """
415
+ return new_gen_from_mpq_t(self .value)
416
+
417
+
418
+ cpdef list pari_divisors_small(Integer self ):
419
+ r """
420
+ Return the list of divisors of this number using PARI ``divisorsu``.
421
+
422
+ .. SEEALSO::
423
+
424
+ This method is better used through :meth:`sage. rings. integer. Integer. divisors`.
425
+
426
+ EXAMPLES::
427
+
428
+ sage: from sage. libs. pari. convert_sage import pari_divisors_small
429
+ sage: pari_divisors_small( 4)
430
+ [1, 2, 4 ]
431
+
432
+ The integer must fit into an unsigned long::
433
+
434
+ sage: pari_divisors_small( -4)
435
+ Traceback ( most recent call last) :
436
+ ...
437
+ AssertionError
438
+ sage: pari_divisors_small( 2** 65)
439
+ Traceback ( most recent call last) :
440
+ ...
441
+ AssertionError
442
+ """
443
+ # we need n to fit into a long and not a unsigned long in order to use
444
+ # smallInteger
445
+ assert mpz_fits_slong_p(self .value) and mpz_sgn(self .value) > 0
446
+
447
+ cdef unsigned long n = mpz_get_ui(self .value)
448
+
449
+ global avma
450
+ cdef pari_sp ltop = avma
451
+ cdef GEN d
452
+ cdef list output
453
+
454
+ try :
455
+ sig_on()
456
+ d = divisorsu(n)
457
+ sig_off()
458
+ output = [smallInteger(d[i]) for i in range (1 ,lg(d))]
459
+ return output
460
+ finally :
461
+ avma = ltop
462
+
463
+
464
+ cpdef pari_is_prime(Integer p):
465
+ r """
466
+ Return whether ``p`` is a prime.
467
+
468
+ The caller must ensure that ``p. value`` fits in a long.
469
+
470
+ EXAMPLES::
471
+
472
+ sage: from sage. libs. pari. convert_sage import pari_is_prime
473
+ sage: pari_is_prime( 2)
474
+ True
475
+ sage: pari_is_prime( 3)
476
+ True
477
+ sage: pari_is_prime( 1)
478
+ False
479
+ sage: pari_is_prime( 4)
480
+ False
481
+
482
+ Its recommended to use :meth:`sage. rings. integer. Integer. is_prime`, which checks overflow.
483
+ The following is incorrect, because the number does not fit into a long::
484
+
485
+ sage: pari_is_prime( 2** 64 + 2)
486
+ True
487
+ """
488
+ return bool (uisprime(mpz_get_ui(p.value)))
489
+
490
+
491
+ cpdef pari_is_prime_power(Integer q, bint get_data):
492
+ r """
493
+ Return whether ``q`` is a prime power.
494
+
495
+ The caller must ensure that ``q. value`` fits in a long.
496
+
497
+ OUTPUT:
498
+
499
+ If ``get_data`` return a tuple of the prime and the exponent.
500
+ Otherwise return a boolean.
501
+
502
+ EXAMPLES::
503
+
504
+ sage: from sage. libs. pari. convert_sage import pari_is_prime_power
505
+ sage: pari_is_prime_power( 2, False)
506
+ True
507
+ sage: pari_is_prime_power( 2, True)
508
+ ( 2, 1)
509
+ sage: pari_is_prime_power( 4, False)
510
+ True
511
+ sage: pari_is_prime_power( 4, True)
512
+ ( 2, 2)
513
+ sage: pari_is_prime_power( 6, False)
514
+ False
515
+ sage: pari_is_prime_power( 6, True)
516
+ ( 6, 0)
517
+
518
+ Its recommended to use :meth:`sage. rings. integer. Integer. is_prime_power`, which checks overflow.
519
+ The following is incorrect, because the number does not fit into a long::
520
+
521
+ sage: pari_is_prime_power( 2** 64 + 2, False)
522
+ True
523
+ """
524
+ cdef long p, n
525
+ n = uisprimepower(mpz_get_ui(q.value), < ulong* > (& p))
526
+ if n:
527
+ return (smallInteger(p), smallInteger(n)) if get_data else True
528
+ else :
529
+ return (q, smallInteger(0 )) if get_data else False
0 commit comments