@@ -101,6 +101,13 @@ cdef class fmpq(flint_scalar):
101101 p = property(numer)
102102 q = property(denom)
103103
104+ # These are the property names in the numeric tower.
105+ numerator = property(numer)
106+ denominator = property(denom)
107+
108+ def __reduce__ (self ):
109+ return (fmpq, (int (self .p), int (self .q)))
110+
104111 def repr (self ):
105112 if self .q == 1 :
106113 return " fmpq(%s )" % self .p
@@ -122,9 +129,24 @@ cdef class fmpq(flint_scalar):
122129 else :
123130 return " %s /%s " % (self .p.str(** kwargs), self .q.str(** kwargs))
124131
132+ def __int__ (self ):
133+ return int (self .trunc())
134+
135+ def __floor__ (self ):
136+ return self .floor()
137+
138+ def __ceil__ (self ):
139+ return self .ceil()
140+
141+ def __trunc__ (self ):
142+ return self .trunc()
143+
125144 def __nonzero__ (self ):
126145 return not fmpq_is_zero(self .val)
127146
147+ def __round__ (self , ndigits = None ):
148+ return self .round(ndigits)
149+
128150 def __pos__ (self ):
129151 return self
130152
@@ -335,6 +357,37 @@ cdef class fmpq(flint_scalar):
335357 fmpz_cdiv_q(r.val, fmpq_numref(self .val), fmpq_denref(self .val))
336358 return r
337359
360+ def trunc (self ):
361+ """
362+ Truncation function.
363+
364+ >>> fmpq(3,2).trunc()
365+ 1
366+ >>> fmpq(-3,2).trunc()
367+ -1
368+ """
369+ cdef fmpz r = fmpz.__new__ (fmpz)
370+ fmpz_tdiv_q(r.val, fmpq_numref(self .val), fmpq_denref(self .val))
371+ return r
372+
373+ def round (self , ndigits = None ):
374+ """
375+ Rounding function.
376+
377+ >>> fmpq(3,2).round()
378+ 2
379+ >>> fmpq(-3,2).round()
380+ -2
381+ """
382+ from fractions import Fraction
383+ fself = Fraction(int (self .p), int (self .q))
384+ if ndigits is not None :
385+ fround = round (fself, ndigits)
386+ return fmpq(fround.numerator, fround.denominator)
387+ else :
388+ fround = round (fself)
389+ return fmpz(fround)
390+
338391 def __hash__ (self ):
339392 from fractions import Fraction
340393 return hash (Fraction(int (self .p), int (self .q), _normalize = False ))
@@ -359,20 +412,28 @@ cdef class fmpq(flint_scalar):
359412 return max (b1, b2)
360413
361414 def __pow__ (self , n , z ):
415+ cdef fmpz_struct nval[1 ]
416+ cdef int ntype = FMPZ_UNKNOWN
362417 cdef fmpq v
418+ cdef int success
363419 cdef long e
420+
364421 assert z is None
365- e = n
366- if type (self ) is fmpq:
367- v = fmpq.__new__ (fmpq)
368- if e >= 0 :
369- fmpz_pow_ui(fmpq_numref(v.val), fmpq_numref((< fmpq> self ).val), e)
370- fmpz_pow_ui(fmpq_denref(v.val), fmpq_denref((< fmpq> self ).val), e)
371- else :
372- if fmpq_is_zero((< fmpq> self ).val):
373- raise ZeroDivisionError
374- fmpz_pow_ui(fmpq_denref(v.val), fmpq_numref((< fmpq> self ).val), - e)
375- fmpz_pow_ui(fmpq_numref(v.val), fmpq_denref((< fmpq> self ).val), - e)
376- return v
377- return NotImplemented
378422
423+ ntype = fmpz_set_any_ref(nval, n)
424+ if ntype == FMPZ_UNKNOWN:
425+ return NotImplemented
426+
427+ if fmpq_is_zero((< fmpq> self ).val) and fmpz_sgn(nval) == - 1 :
428+ if ntype == FMPZ_TMP: fmpz_clear(nval)
429+ raise ZeroDivisionError
430+
431+ v = fmpq.__new__ (fmpq)
432+ success = fmpq_pow_fmpz(v.val, (< fmpq> self ).val, nval)
433+
434+ if ntype == FMPZ_TMP: fmpz_clear(nval)
435+
436+ if success:
437+ return v
438+ else :
439+ raise OverflowError (" fmpq_pow_fmpz(): exponent too large" )
0 commit comments