Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/rings/fraction_field_element.pyx
8817 views
1
"""
2
Fraction Field Elements
3
4
AUTHORS:
5
6
- William Stein (input from David Joyner, David Kohel, and Joe Wetherell)
7
8
- Sebastian Pancratz (2010-01-06): Rewrite of addition, multiplication and
9
derivative to use Henrici's algorithms [Ho72]
10
11
REFERENCES:
12
13
.. [Ho72] E. Horowitz, "Algorithms for Rational Function Arithmetic
14
Operations", Annual ACM Symposium on Theory of Computing, Proceedings of
15
the Fourth Annual ACM Symposium on Theory of Computing, pp. 108--118, 1972
16
17
"""
18
19
#*****************************************************************************
20
#
21
# Sage: System for Algebra and Geometry Experimentation
22
#
23
# Copyright (C) 2005 William Stein <[email protected]>
24
#
25
# Distributed under the terms of the GNU General Public License (GPL)
26
#
27
# This code is distributed in the hope that it will be useful,
28
# but WITHOUT ANY WARRANTY; without even the implied warranty of
29
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30
# General Public License for more details.
31
#
32
# The full text of the GPL is available at:
33
#
34
# http://www.gnu.org/licenses/
35
#*****************************************************************************
36
37
import operator
38
39
from sage.structure.element cimport FieldElement, ModuleElement, RingElement, \
40
Element
41
from sage.structure.element import parent
42
43
import integer_ring
44
from integer_ring import ZZ
45
from rational_field import QQ
46
47
import sage.misc.latex as latex
48
49
def is_FractionFieldElement(x):
50
"""
51
Returns whether or not ``x`` is a :class`FractionFieldElement`.
52
53
EXAMPLES::
54
55
sage: from sage.rings.fraction_field_element import is_FractionFieldElement
56
sage: R.<x> = ZZ[]
57
sage: is_FractionFieldElement(x/2)
58
False
59
sage: is_FractionFieldElement(2/x)
60
True
61
sage: is_FractionFieldElement(1/3)
62
False
63
"""
64
return isinstance(x, FractionFieldElement)
65
66
cdef class FractionFieldElement(FieldElement):
67
"""
68
EXAMPLES::
69
70
sage: K, x = FractionField(PolynomialRing(QQ, 'x')).objgen()
71
sage: K
72
Fraction Field of Univariate Polynomial Ring in x over Rational Field
73
sage: loads(K.dumps()) == K
74
True
75
sage: f = (x^3 + x)/(17 - x^19); f
76
(x^3 + x)/(-x^19 + 17)
77
sage: loads(f.dumps()) == f
78
True
79
80
TESTS:
81
82
Test if :trac:`5451` is fixed::
83
84
sage: A = FiniteField(9,'theta')['t']
85
sage: K.<t> = FractionField(A)
86
sage: f= 2/(t^2+2*t); g =t^9/(t^18 + t^10 + t^2);f+g
87
(2*t^15 + 2*t^14 + 2*t^13 + 2*t^12 + 2*t^11 + 2*t^10 + 2*t^9 + t^7 + t^6 + t^5 + t^4 + t^3 + t^2 + t + 1)/(t^17 + t^9 + t)
88
89
Test if :trac:`8671` is fixed::
90
91
sage: P.<n> = QQ[]
92
sage: F = P.fraction_field()
93
sage: P.one_element()//F.one_element()
94
1
95
sage: F.one_element().quo_rem(F.one_element())
96
(1, 0)
97
"""
98
cdef object __numerator
99
cdef object __denominator
100
101
def __init__(self, parent, numerator, denominator=1,
102
coerce=True, reduce=True):
103
"""
104
Initialize ``self``.
105
106
EXAMPLES::
107
108
sage: from sage.rings.fraction_field_element import FractionFieldElement
109
sage: K.<x> = Frac(ZZ['x'])
110
sage: FractionFieldElement(K, x, 4)
111
x/4
112
sage: FractionFieldElement(K, x, x, reduce=False)
113
x/x
114
sage: f = FractionFieldElement(K, 'hi', 1, coerce=False, reduce=False)
115
sage: f.numerator()
116
'hi'
117
118
sage: x = var('x')
119
sage: K((x + 1)/(x^2 + x + 1))
120
(x + 1)/(x^2 + x + 1)
121
sage: K(355/113)
122
355/113
123
124
"""
125
FieldElement.__init__(self, parent)
126
if coerce:
127
self.__numerator = parent.ring()(numerator)
128
self.__denominator = parent.ring()(denominator)
129
else:
130
self.__numerator = numerator
131
self.__denominator = denominator
132
if reduce and parent.is_exact():
133
try:
134
self.reduce()
135
except ArithmeticError:
136
pass
137
if self.__denominator.is_zero():
138
raise ZeroDivisionError, "fraction field element division by zero"
139
140
def _im_gens_(self, codomain, im_gens):
141
"""
142
EXAMPLES::
143
144
sage: F = ZZ['x,y'].fraction_field()
145
sage: x,y = F.gens()
146
sage: K = GF(7)['a,b'].fraction_field()
147
sage: a,b = K.gens()
148
149
::
150
151
sage: phi = F.hom([a+b, a*b], K)
152
sage: phi(x+y) # indirect doctest
153
a*b + a + b
154
155
::
156
157
sage: (x^2/y)._im_gens_(K, [a+b, a*b])
158
(a^2 + 2*a*b + b^2)/(a*b)
159
sage: (x^2/y)._im_gens_(K, [a, a*b])
160
a/b
161
"""
162
nnum = codomain.coerce(self.__numerator._im_gens_(codomain, im_gens))
163
nden = codomain.coerce(self.__denominator._im_gens_(codomain, im_gens))
164
return codomain.coerce(nnum/nden)
165
166
def reduce(self):
167
"""
168
Divides out the gcd of the numerator and denominator.
169
170
Automatically called for exact rings, but because it may be
171
numerically unstable for inexact rings it must be called manually
172
in that case.
173
174
EXAMPLES::
175
176
sage: R.<x> = RealField(10)[]
177
sage: f = (x^2+2*x+1)/(x+1); f
178
(x^2 + 2.0*x + 1.0)/(x + 1.0)
179
sage: f.reduce(); f
180
x + 1.0
181
"""
182
try:
183
g = self.__numerator.gcd(self.__denominator)
184
if not g.is_unit():
185
num, _ = self.__numerator.quo_rem(g)
186
den, _ = self.__denominator.quo_rem(g)
187
else:
188
num = self.__numerator
189
den = self.__denominator
190
if not den.is_one() and den.is_unit():
191
try:
192
num *= den.inverse_of_unit()
193
den = den.parent().one_element()
194
except Exception:
195
pass
196
self.__numerator = num
197
self.__denominator = den
198
except AttributeError:
199
raise ArithmeticError, "unable to reduce because lack of gcd or quo_rem algorithm"
200
except TypeError:
201
raise ArithmeticError, "unable to reduce because gcd algorithm doesn't work on input"
202
except NotImplementedError:
203
raise ArithmeticError("unable to reduce because gcd algorithm not implemented on input")
204
205
def __copy__(self):
206
"""
207
Make a copy of ``self``.
208
209
EXAMPLES::
210
211
sage: R.<x,y> = ZZ[]
212
sage: f = x/y+1; f
213
(x + y)/y
214
sage: copy(f)
215
(x + y)/y
216
"""
217
return self.__class__(self._parent, self.__numerator,
218
self.__denominator, coerce=False, reduce=False)
219
220
def numerator(self):
221
"""
222
Return the numerator of ``self``.
223
224
EXAMPLES::
225
226
sage: R.<x,y> = ZZ[]
227
sage: f = x/y+1; f
228
(x + y)/y
229
sage: f.numerator()
230
x + y
231
"""
232
return self.__numerator
233
234
def denominator(self):
235
"""
236
Return the denominator of ``self``.
237
238
EXAMPLES::
239
240
sage: R.<x,y> = ZZ[]
241
sage: f = x/y+1; f
242
(x + y)/y
243
sage: f.denominator()
244
y
245
"""
246
return self.__denominator
247
248
249
def is_square(self,root=False):
250
"""
251
Returns whether or not ``self`` is a perfect square. If the optional
252
argument ``root`` is ``True``, then also returns a square root (or
253
``None``, if the fraction field element is not square).
254
255
INPUT:
256
257
- ``root`` -- whether or not to also return a square
258
root (default: ``False``)
259
260
OUTPUT:
261
262
- ``bool`` - whether or not a square
263
264
- ``object`` - (optional) an actual square root if
265
found, and None otherwise.
266
267
EXAMPLES::
268
269
sage: R.<t> = QQ[]
270
sage: (1/t).is_square()
271
False
272
sage: (1/t^6).is_square()
273
True
274
sage: ((1+t)^4/t^6).is_square()
275
True
276
sage: (4*(1+t)^4/t^6).is_square()
277
True
278
sage: (2*(1+t)^4/t^6).is_square()
279
False
280
sage: ((1+t)/t^6).is_square()
281
False
282
283
sage: (4*(1+t)^4/t^6).is_square(root=True)
284
(True, (2*t^2 + 4*t + 2)/t^3)
285
sage: (2*(1+t)^4/t^6).is_square(root=True)
286
(False, None)
287
288
sage: R.<x> = QQ[]
289
sage: a = 2*(x+1)^2 / (2*(x-1)^2); a
290
(2*x^2 + 4*x + 2)/(2*x^2 - 4*x + 2)
291
sage: a.numerator().is_square()
292
False
293
sage: a.is_square()
294
True
295
sage: (0/x).is_square()
296
True
297
"""
298
a = self.numerator()
299
b = self.denominator()
300
if not root:
301
return (a*b).is_square( root = False )
302
is_sqr, sq_rt = (a*b).is_square( root = True )
303
if is_sqr:
304
return True, self._parent( sq_rt/b )
305
return False, None
306
307
308
def __hash__(self):
309
"""
310
This function hashes in a special way to ensure that generators of
311
a ring `R` and generators of a fraction field of `R` have the same
312
hash. This enables them to be used as keys interchangeably in a
313
dictionary (since ``==`` will claim them equal). This is particularly
314
useful for methods like ``subs`` on ``ParentWithGens`` if you are
315
passing a dictionary of substitutions.
316
317
EXAMPLES::
318
319
sage: R.<x>=ZZ[]
320
sage: hash(R.0)==hash(FractionField(R).0)
321
True
322
sage: ((x+1)/(x^2+1)).subs({x:1})
323
1
324
sage: d={x:1}
325
sage: d[FractionField(R).0]
326
1
327
sage: R.<x>=QQ[] # this probably has a separate implementation from ZZ[]
328
sage: hash(R.0)==hash(FractionField(R).0)
329
True
330
sage: d={x:1}
331
sage: d[FractionField(R).0]
332
1
333
sage: R.<x,y,z>=ZZ[] # this probably has a separate implementation from ZZ[]
334
sage: hash(R.0)==hash(FractionField(R).0)
335
True
336
sage: d={x:1}
337
sage: d[FractionField(R).0]
338
1
339
sage: R.<x,y,z>=QQ[] # this probably has a separate implementation from ZZ[]
340
sage: hash(R.0)==hash(FractionField(R).0)
341
True
342
sage: ((x+1)/(x^2+1)).subs({x:1})
343
1
344
sage: d={x:1}
345
sage: d[FractionField(R).0]
346
1
347
sage: hash(R(1)/R(2))==hash(1/2)
348
True
349
"""
350
# This is same algorithm as used for members of QQ
351
#cdef long n, d
352
n = hash(self.__numerator)
353
d = hash(self.__denominator)
354
if d == 1:
355
return n
356
n = n ^ d
357
if n == -1:
358
return -2
359
return n
360
361
def __call__(self, *x, **kwds):
362
"""
363
Evaluate the fraction at the given arguments. This assumes that a
364
call function is defined for the numerator and denominator.
365
366
EXAMPLES::
367
368
sage: x = PolynomialRing(RationalField(),'x',3).gens()
369
sage: f = x[0] + x[1] - 2*x[1]*x[2]
370
sage: f
371
-2*x1*x2 + x0 + x1
372
sage: f(1,2,5)
373
-17
374
sage: h = f /(x[1] + x[2])
375
sage: h
376
(-2*x1*x2 + x0 + x1)/(x1 + x2)
377
sage: h(1,2,5)
378
-17/7
379
sage: h(x0=1)
380
(-2*x1*x2 + x1 + 1)/(x1 + x2)
381
"""
382
return self.__numerator(*x, **kwds) / self.__denominator(*x, **kwds)
383
384
def _is_atomic(self):
385
"""
386
EXAMPLES::
387
388
sage: K.<x> = Frac(ZZ['x'])
389
sage: x._is_atomic()
390
True
391
sage: f = 1/(x+1)
392
sage: f._is_atomic()
393
False
394
"""
395
return self.__numerator._is_atomic() and self.__denominator._is_atomic()
396
397
def _repr_(self):
398
"""
399
Return a string representation of ``self``.
400
401
EXAMPLES::
402
403
sage: K.<x> = Frac(ZZ['x'])
404
sage: repr(x+1) # indirect doctest
405
'x + 1'
406
sage: repr((x+1)/(x-1))
407
'(x + 1)/(x - 1)'
408
sage: repr(1/(x-1))
409
'1/(x - 1)'
410
sage: repr(1/x)
411
'1/x'
412
"""
413
if self.is_zero():
414
return "0"
415
s = "%s"%self.__numerator
416
if self.__denominator != 1:
417
denom_string = str( self.__denominator )
418
if self.__denominator._is_atomic() and not ('*' in denom_string or '/' in denom_string):
419
s = "%s/%s"%(self.__numerator._coeff_repr(no_space=False),denom_string)
420
else:
421
s = "%s/(%s)"%(self.__numerator._coeff_repr(no_space=False),denom_string)
422
return s
423
424
def _latex_(self):
425
r"""
426
Return a latex representation of this fraction field element.
427
428
EXAMPLES::
429
430
sage: R = PolynomialRing(QQ, 'x')
431
sage: F = R.fraction_field()
432
sage: x = F.gen()
433
sage: a = x^2 / 1
434
sage: latex(a) # indirect doctest
435
x^{2}
436
sage: latex(x^2/(x^2+1))
437
\frac{x^{2}}{x^{2} + 1}
438
sage: a = 1/x
439
sage: latex(a)
440
\frac{1}{x}
441
442
TESTS::
443
444
sage: R = RR['x'] # Inexact, so no reduction.
445
sage: F = Frac(R)
446
sage: from sage.rings.fraction_field_element import FractionFieldElement
447
sage: z = FractionFieldElement(F, 0, R.gen(), coerce=False)
448
sage: z.numerator() == 0
449
True
450
sage: z.denominator() == R.gen()
451
True
452
sage: latex(z) # indirect doctest
453
0
454
"""
455
if self.is_zero():
456
return "0"
457
if self.__denominator == 1:
458
return latex.latex(self.__numerator)
459
return "\\frac{%s}{%s}"%(latex.latex(self.__numerator),
460
latex.latex(self.__denominator))
461
462
def _magma_init_(self, magma):
463
"""
464
Return a string representation of ``self`` Magma can understand.
465
466
EXAMPLES::
467
468
sage: R.<x> = ZZ[]
469
sage: magma((x^2 + x + 1)/(x + 1)) # optional - magma # indirect doctest
470
(x^2 + x + 1)/(x + 1)
471
472
::
473
474
sage: R.<x,y> = QQ[]
475
sage: magma((x+y)/x) # optional - magma
476
(x + y)/x
477
"""
478
pgens = magma(self._parent).gens()
479
480
s = self._repr_()
481
for i, j in zip(self._parent.variable_names(), pgens):
482
s = s.replace(i, j.name())
483
484
return s
485
486
cpdef ModuleElement _add_(self, ModuleElement right):
487
"""
488
Computes the sum of ``self`` and ``right``.
489
490
INPUT:
491
492
- ``right`` -- ``ModuleElement`` to add to ``self``
493
494
OUTPUT:
495
496
- Sum of ``self`` and ``right``
497
498
EXAMPLES::
499
500
sage: K.<x,y> = Frac(ZZ['x,y'])
501
sage: x+y # indirect doctest
502
x + y
503
sage: 1/x + 1/y
504
(x + y)/(x*y)
505
sage: 1/x + 1/(x*y)
506
(y + 1)/(x*y)
507
sage: Frac(CDF['x']).gen() + 3
508
x + 3.0
509
"""
510
rnum = self.__numerator
511
rden = self.__denominator
512
snum = (<FractionFieldElement> right).__numerator
513
sden = (<FractionFieldElement> right).__denominator
514
515
if (rnum.is_zero()):
516
return <FractionFieldElement> right
517
if (snum.is_zero()):
518
return self
519
520
if self._parent.is_exact():
521
try:
522
d = rden.gcd(sden)
523
if d.is_unit():
524
return self.__class__(self._parent, rnum*sden + rden*snum,
525
rden*sden, coerce=False, reduce=False)
526
else:
527
rden = rden // d
528
sden = sden // d
529
tnum = rnum * sden + rden * snum
530
if tnum.is_zero():
531
return self.__class__(self._parent, tnum,
532
self._parent.ring().one_element(), coerce=False,
533
reduce=False)
534
else:
535
tden = self.__denominator * sden
536
e = tnum.gcd(d)
537
if not e.is_unit():
538
tnum = tnum // e
539
tden = tden // e
540
if not tden.is_one() and tden.is_unit():
541
try:
542
tnum = tnum * tden.inverse_of_unit()
543
tden = self._parent.ring().one_element()
544
except AttributeError:
545
pass
546
except NotImplementedError:
547
pass
548
return self.__class__(self._parent, tnum, tden,
549
coerce=False, reduce=False)
550
except AttributeError:
551
pass
552
except NotImplementedError:
553
pass
554
except TypeError:
555
pass
556
557
rnum = self.__numerator
558
rden = self.__denominator
559
snum = (<FractionFieldElement> right).__numerator
560
sden = (<FractionFieldElement> right).__denominator
561
562
return self.__class__(self._parent, rnum*sden + rden*snum, rden*sden,
563
coerce=False, reduce=False)
564
565
cpdef ModuleElement _sub_(self, ModuleElement right):
566
"""
567
Computes the difference of ``self`` and ``right``.
568
569
INPUT:
570
571
- ``right`` - ``ModuleElement`` to subtract from ``self``
572
573
OUTPUT:
574
575
- Difference of ``self`` and ``right``
576
577
EXAMPLES::
578
579
sage: K.<t> = Frac(GF(7)['t'])
580
sage: t - 1/t # indirect doctest
581
(t^2 + 6)/t
582
"""
583
return self._add_(-right)
584
585
cpdef RingElement _mul_(self, RingElement right):
586
"""
587
Computes the product of ``self`` and ``right``.
588
589
INPUT:
590
591
- ``right`` - ``RingElement`` to multiply with ``self``
592
593
OUTPUT:
594
595
- Product of ``self`` and ``right``
596
597
EXAMPLES::
598
599
sage: K.<t> = Frac(GF(7)['t'])
600
sage: a = t/(1+t)
601
sage: b = 3/t
602
sage: a*b # indirect doctest
603
3/(t + 1)
604
"""
605
rnum = self.__numerator
606
rden = self.__denominator
607
snum = (<FractionFieldElement> right).__numerator
608
sden = (<FractionFieldElement> right).__denominator
609
610
if (rnum.is_zero() or snum.is_zero()):
611
return self._parent.zero_element()
612
613
if self._parent.is_exact():
614
try:
615
d1 = rnum.gcd(sden)
616
d2 = snum.gcd(rden)
617
if not d1.is_unit():
618
rnum = rnum // d1
619
sden = sden // d1
620
if not d2.is_unit():
621
rden = rden // d2
622
snum = snum // d2
623
tnum = rnum * snum
624
tden = rden * sden
625
if not tden.is_one() and tden.is_unit():
626
try:
627
tnum = tnum * tden.inverse_of_unit()
628
tden = self._parent.ring().one_element()
629
except AttributeError:
630
pass
631
except NotImplementedError:
632
pass
633
return self.__class__(self._parent, tnum, tden,
634
coerce=False, reduce=False)
635
except AttributeError:
636
pass
637
except NotImplementedError:
638
pass
639
except TypeError:
640
pass
641
642
rnum = self.__numerator
643
rden = self.__denominator
644
snum = (<FractionFieldElement> right).__numerator
645
sden = (<FractionFieldElement> right).__denominator
646
647
return self.__class__(self._parent, rnum * snum, rden * sden,
648
coerce=False, reduce=False)
649
650
cpdef RingElement _div_(self, RingElement right):
651
"""
652
Computes the quotient of ``self`` and ``right``.
653
654
INPUT:
655
656
- ``right`` -- ``RingElement`` that is the divisor
657
658
OUTPUT:
659
660
Quotient of ``self`` and ``right``
661
662
EXAMPLES::
663
664
sage: K.<x,y,z> = Frac(ZZ['x,y,z'])
665
sage: a = (x+1)*(x+y)/(z-3) # indirect doctest
666
sage: b = (x+y)/(z-1)
667
sage: a/b
668
(x*z - x + z - 1)/(z - 3)
669
"""
670
snum = (<FractionFieldElement> right).__numerator
671
sden = (<FractionFieldElement> right).__denominator
672
673
if snum.is_zero():
674
raise ZeroDivisionError, "fraction field element division by zero"
675
676
rightinv = self.__class__(self._parent, sden, snum,
677
coerce=True, reduce=False)
678
679
return self._mul_(rightinv)
680
681
def __int__(self):
682
"""
683
EXAMPLES::
684
685
sage: K = Frac(ZZ['x'])
686
sage: int(K(-3))
687
-3
688
sage: K.<x> = Frac(RR['x'])
689
sage: x/x
690
x/x
691
sage: int(x/x)
692
1
693
sage: int(K(.5))
694
0
695
"""
696
if self.__denominator != 1:
697
self.reduce()
698
if self.__denominator == 1:
699
return int(self.__numerator)
700
else:
701
raise TypeError, "denominator must equal 1"
702
703
def _integer_(self, Z=ZZ):
704
"""
705
EXAMPLES::
706
707
sage: K = Frac(ZZ['x'])
708
sage: K(5)._integer_()
709
5
710
sage: K.<x> = Frac(RR['x'])
711
sage: ZZ(2*x/x)
712
2
713
"""
714
if self.__denominator != 1:
715
self.reduce()
716
if self.__denominator == 1:
717
return Z(self.__numerator)
718
raise TypeError, "no way to coerce to an integer."
719
720
def _rational_(self, Q=QQ):
721
"""
722
EXAMPLES::
723
724
sage: K.<x> = Frac(QQ['x'])
725
sage: K(1/2)._rational_()
726
1/2
727
sage: K(1/2 + x/x)._rational_()
728
3/2
729
"""
730
return Q(self.__numerator) / Q(self.__denominator)
731
732
def __long__(self):
733
"""
734
EXAMPLES::
735
736
sage: K.<x> = Frac(QQ['x'])
737
sage: long(K(3))
738
3L
739
sage: long(K(3/5))
740
0L
741
"""
742
return long(int(self))
743
744
def __pow__(self, right, dummy):
745
r"""
746
Returns self raised to the `right^{th}` power.
747
748
Note that we need to check whether or not right is negative so we
749
don't set ``__numerator`` or ``__denominator`` to an element of the
750
fraction field instead of the underlying ring.
751
752
EXAMPLES::
753
754
sage: R = QQ['x','y']
755
sage: FR = R.fraction_field()
756
sage: x,y = FR.gens()
757
sage: a = x^2; a
758
x^2
759
sage: type(a.numerator())
760
<type 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'>
761
sage: type(a.denominator())
762
<type 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'>
763
sage: a = x^(-2); a
764
1/x^2
765
sage: type(a.numerator())
766
<type 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'>
767
sage: type(a.denominator())
768
<type 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'>
769
sage: x^0
770
1
771
sage: ((x+y)/(x-y))^2
772
(x^2 + 2*x*y + y^2)/(x^2 - 2*x*y + y^2)
773
sage: ((x+y)/(x-y))^-2
774
(x^2 - 2*x*y + y^2)/(x^2 + 2*x*y + y^2)
775
sage: ((x+y)/(x-y))^0
776
1
777
"""
778
snum = (<FractionFieldElement> self).__numerator
779
sden = (<FractionFieldElement> self).__denominator
780
if right == 0:
781
R = self.parent().ring()
782
return self.__class__(self.parent(),
783
R.one_element(), R.one_element(),
784
coerce=False, reduce=False)
785
elif right > 0:
786
return self.__class__(self.parent(),
787
snum**right, sden**right,
788
coerce=False, reduce=False)
789
else:
790
right = -right
791
return self.__class__(self.parent(),
792
sden**right, snum**right,
793
coerce=False, reduce=False)
794
795
def __neg__(self):
796
"""
797
EXAMPLES::
798
799
sage: K.<t> = Frac(GF(5)['t'])
800
sage: f = (t^2+t)/(t+2); f
801
(t^2 + t)/(t + 2)
802
sage: -f
803
(4*t^2 + 4*t)/(t + 2)
804
"""
805
return self.__class__(self._parent,
806
-self.__numerator, self.__denominator,
807
coerce=False, reduce=False)
808
809
def __abs__(self):
810
"""
811
EXAMPLES::
812
813
sage: from sage.rings.fraction_field_element import FractionFieldElement
814
sage: abs(FractionFieldElement(QQ, -2, 3, coerce=False))
815
2/3
816
"""
817
return abs(self.__numerator)/abs(self.__denominator)
818
819
def __invert__(self):
820
"""
821
EXAMPLES::
822
823
sage: K.<t> = Frac(GF(7)['t'])
824
sage: f = (t^2+5)/(t-1)
825
sage: ~f
826
(t + 6)/(t^2 + 5)
827
"""
828
if self.is_zero():
829
raise ZeroDivisionError, "Cannot invert 0"
830
return self.__class__(self._parent,
831
self.__denominator, self.__numerator, coerce=False, reduce=False)
832
833
def __float__(self):
834
"""
835
EXAMPLES::
836
837
sage: K.<x,y> = Frac(ZZ['x,y'])
838
sage: float(x/x + y/y)
839
2.0
840
"""
841
return float(self.__numerator) / float(self.__denominator)
842
843
def __richcmp__(left, right, int op):
844
"""
845
EXAMPLES::
846
847
sage: K.<x,y> = Frac(ZZ['x,y'])
848
sage: x > y
849
True
850
sage: 1 > y
851
False
852
"""
853
return (<Element>left)._richcmp(right, op)
854
855
cdef int _cmp_c_impl(self, Element other) except -2:
856
"""
857
EXAMPLES::
858
859
sage: K.<t> = Frac(GF(7)['t'])
860
sage: t/t == 1
861
True
862
sage: t+1/t == (t^2+1)/t
863
True
864
sage: t == t/5
865
False
866
"""
867
return cmp(self.__numerator * \
868
(<FractionFieldElement>other).__denominator,
869
self.__denominator*(<FractionFieldElement>other).__numerator)
870
871
def valuation(self, v=None):
872
"""
873
Return the valuation of ``self``, assuming that the numerator and
874
denominator have valuation functions defined on them.
875
876
EXAMPLES::
877
878
sage: x = PolynomialRing(RationalField(),'x').gen()
879
sage: f = (x^3 + x)/(x^2 - 2*x^3)
880
sage: f
881
(x^2 + 1)/(-2*x^2 + x)
882
sage: f.valuation()
883
-1
884
sage: f.valuation(x^2+1)
885
1
886
"""
887
return self.__numerator.valuation(v) - self.__denominator.valuation(v)
888
889
def __nonzero__(self):
890
"""
891
Return ``True`` if this element is nonzero.
892
893
EXAMPLES::
894
895
sage: F = ZZ['x,y'].fraction_field()
896
sage: x,y = F.gens()
897
sage: t = F(0)/x
898
sage: t.__nonzero__()
899
False
900
901
::
902
903
sage: (1/x).__nonzero__()
904
True
905
"""
906
return not self.__numerator.is_zero()
907
908
def is_zero(self):
909
"""
910
Return ``True`` if this element is equal to zero.
911
912
EXAMPLES::
913
914
sage: F = ZZ['x,y'].fraction_field()
915
sage: x,y = F.gens()
916
sage: t = F(0)/x
917
sage: t.is_zero()
918
True
919
sage: u = 1/x - 1/x
920
sage: u.is_zero()
921
True
922
sage: u.parent() is F
923
True
924
"""
925
return self.__numerator.is_zero()
926
927
def is_one(self):
928
"""
929
Return ``True`` if this element is equal to one.
930
931
EXAMPLES::
932
933
sage: F = ZZ['x,y'].fraction_field()
934
sage: x,y = F.gens()
935
sage: (x/x).is_one()
936
True
937
sage: (x/y).is_one()
938
False
939
"""
940
return self.__numerator == self.__denominator
941
942
def _symbolic_(self, ring):
943
"""
944
Return ``self`` as a fraction in the ring ``ring``. Used for
945
:func:`symbolic_expression` in creating a symbolic expression of
946
``self``.
947
948
EXAMPLES::
949
950
sage: F = ZZ['x,y'].fraction_field()
951
sage: x,y = F.gens()
952
sage: elt = (2*x + 2*y) / (3*x - 3*y); elt
953
(2*x + 2*y)/(3*x - 3*y)
954
sage: elt._symbolic_(SR)
955
2/3*(x + y)/(x - y)
956
sage: symbolic_expression(elt)
957
2/3*(x + y)/(x - y)
958
"""
959
return ring(self.__numerator)/ring(self.__denominator)
960
961
def __reduce__(self):
962
"""
963
For pickling.
964
965
EXAMPLES::
966
967
sage: F = ZZ['x,y'].fraction_field()
968
sage: f = F.random_element()
969
sage: loads(f.dumps()) == f
970
True
971
"""
972
return (make_element,
973
(self._parent, self.__numerator, self.__denominator))
974
975
976
class FractionFieldElement_1poly_field(FractionFieldElement):
977
"""
978
A fraction field element where the parent is the fraction field of a
979
univariate polynomial ring.
980
981
Many of the functions here are included for coherence with number fields.
982
"""
983
def is_integral(self):
984
"""
985
Returns whether this element is actually a polynomial.
986
987
EXAMPLES::
988
989
sage: R.<t> = QQ[]
990
sage: elt = (t^2 + t - 2) / (t + 2); elt # == (t + 2)*(t - 1)/(t + 2)
991
t - 1
992
sage: elt.is_integral()
993
True
994
sage: elt = (t^2 - t) / (t+2); elt # == t*(t - 1)/(t + 2)
995
(t^2 - t)/(t + 2)
996
sage: elt.is_integral()
997
False
998
"""
999
if self.denominator() != 1:
1000
self.reduce()
1001
return self.denominator() == 1
1002
1003
def support(self):
1004
"""
1005
Returns a sorted list of primes dividing either the numerator or
1006
denominator of this element.
1007
1008
EXAMPLES::
1009
1010
sage: R.<t> = QQ[]
1011
sage: h = (t^14 + 2*t^12 - 4*t^11 - 8*t^9 + 6*t^8 + 12*t^6 - 4*t^5 - 8*t^3 + t^2 + 2)/(t^6 + 6*t^5 + 9*t^4 - 2*t^2 - 12*t - 18)
1012
sage: h.support()
1013
[t - 1, t + 3, t^2 + 2, t^2 + t + 1, t^4 - 2]
1014
"""
1015
L = [fac[0] for fac in self.numerator().factor()] + [fac[0] for fac in self.denominator().factor()]
1016
L.sort()
1017
return L
1018
1019
1020
def make_element(parent, numerator, denominator):
1021
"""
1022
Used for unpickling :class:`FractionFieldElement` objects (and subclasses).
1023
1024
EXAMPLES::
1025
1026
sage: from sage.rings.fraction_field_element import make_element
1027
sage: R = ZZ['x,y']
1028
sage: x,y = R.gens()
1029
sage: F = R.fraction_field()
1030
sage: make_element(F, 1+x, 1+y)
1031
(x + 1)/(y + 1)
1032
"""
1033
1034
return parent._element_class(parent, numerator, denominator)
1035
1036
def make_element_old(parent, cdict):
1037
"""
1038
Used for unpickling old :class:`FractionFieldElement` pickles.
1039
1040
EXAMPLES::
1041
1042
sage: from sage.rings.fraction_field_element import make_element_old
1043
sage: R.<x,y> = ZZ[]
1044
sage: F = R.fraction_field()
1045
sage: make_element_old(F, {'_FractionFieldElement__numerator':x+y,'_FractionFieldElement__denominator':x-y})
1046
(x + y)/(x - y)
1047
"""
1048
return FractionFieldElement(parent,
1049
cdict['_FractionFieldElement__numerator'],
1050
cdict['_FractionFieldElement__denominator'],
1051
coerce=False, reduce=False)
1052
1053
1054