Skip to content

Commit deb4448

Browse files
Merge pull request #44 from oscarbenjamin/pr_sympy_integration
Add missing operations for fmpz and fmpq
2 parents 027dd1f + 2d4cfa9 commit deb4448

File tree

4 files changed

+465
-58
lines changed

4 files changed

+465
-58
lines changed

src/flint/_flint.pxd

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ cdef extern from "flint/fmpz.h":
267267
void fmpz_pow_ui(fmpz_t f, fmpz_t g, ulong exp)
268268
void fmpz_powm_ui(fmpz_t f, fmpz_t g, ulong exp, fmpz_t m)
269269
void fmpz_powm(fmpz_t f, fmpz_t g, fmpz_t e, fmpz_t m)
270+
int fmpz_pow_fmpz(fmpz_t f, const fmpz_t g, const fmpz_t x)
270271
int fmpz_sqrtmod(fmpz_t b, fmpz_t a, fmpz_t p)
271272
void fmpz_sqrt(fmpz_t f, fmpz_t g)
272273
void fmpz_sqrtrem(fmpz_t f, fmpz_t r, fmpz_t g)
@@ -310,6 +311,10 @@ cdef extern from "flint/fmpz.h":
310311
int fmpz_jacobi(const fmpz_t a, const fmpz_t p)
311312
int fmpz_is_prime(const fmpz_t n)
312313
int fmpz_is_probabprime(const fmpz_t n)
314+
void fmpz_complement(fmpz_t r, const fmpz_t f)
315+
void fmpz_and(fmpz_t r, const fmpz_t a, const fmpz_t b)
316+
void fmpz_or(fmpz_t r, const fmpz_t a, const fmpz_t b)
317+
void fmpz_xor(fmpz_t r, const fmpz_t a, const fmpz_t b)
313318

314319
cdef extern from "flint/fmpz_factor.h":
315320
ctypedef struct fmpz_factor_struct:
@@ -547,6 +552,7 @@ cdef extern from "flint/fmpq.h":
547552
void fmpq_div(fmpq_t res, fmpq_t op1, fmpq_t op2)
548553
void fmpq_div_fmpz(fmpq_t res, fmpq_t op, fmpz_t x)
549554
int fmpq_mod_fmpz(fmpz_t res, fmpq_t x, fmpz_t mod)
555+
int fmpq_pow_fmpz(fmpq_t a, const fmpq_t b, const fmpz_t e)
550556
int fmpq_reconstruct_fmpz(fmpq_t res, fmpz_t a, fmpz_t m)
551557
int fmpq_reconstruct_fmpz_2(fmpq_t res, fmpz_t a, fmpz_t m, fmpz_t N, fmpz_t D)
552558
mp_bitcnt_t fmpq_height_bits(fmpq_t x)

src/flint/fmpq.pyx

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)