Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

""" 

Big O for various types (power series, p-adics, etc.) 

 

.. SEEALSO:: 

 

- `asymptotic expansions <../../../asymptotic/index.html>`_ 

- `p-adic numbers <../../../padics/index.html>`_ 

- `power series <../../../power_series/index.html>`_ 

- `polynomials <../../../polynomial_rings/index.html>`_ 

""" 

from __future__ import absolute_import 

from six import integer_types 

 

import sage.arith.all as arith 

from . import laurent_series_ring_element 

import sage.rings.padics.factory as padics_factory 

import sage.rings.padics.padic_generic_element as padic_generic_element 

from . import power_series_ring_element 

from . import integer 

from . import rational 

from sage.rings.polynomial.polynomial_element import Polynomial 

from . import multi_power_series_ring_element 

 

 

def O(*x, **kwds): 

""" 

Big O constructor for various types. 

 

EXAMPLES: 

 

This is useful for writing power series elements:: 

 

sage: R.<t> = ZZ[['t']] 

sage: (1+t)^10 + O(t^5) 

1 + 10*t + 45*t^2 + 120*t^3 + 210*t^4 + O(t^5) 

 

A power series ring is created implicitly if a polynomial 

element is passed:: 

 

sage: R.<x> = QQ['x'] 

sage: O(x^100) 

O(x^100) 

sage: 1/(1+x+O(x^5)) 

1 - x + x^2 - x^3 + x^4 + O(x^5) 

sage: R.<u,v> = QQ[[]] 

sage: 1 + u + v^2 + O(u, v)^5 

1 + u + v^2 + O(u, v)^5 

 

This is also useful to create `p`-adic numbers:: 

 

sage: O(7^6) 

O(7^6) 

sage: 1/3 + O(7^6) 

5 + 4*7 + 4*7^2 + 4*7^3 + 4*7^4 + 4*7^5 + O(7^6) 

 

It behaves well with respect to adding negative powers of `p`:: 

 

sage: a = O(11^-32); a 

O(11^-32) 

sage: a.parent() 

11-adic Field with capped relative precision 20 

 

There are problems if you add a rational with very negative 

valuation to an `O`-Term:: 

 

sage: 11^-12 + O(11^15) 

11^-12 + O(11^8) 

 

The reason that this fails is that the constructor doesn't know 

the right precision cap to use. If you cast explicitly or use 

other means of element creation, you can get around this issue:: 

 

sage: K = Qp(11, 30) 

sage: K(11^-12) + O(11^15) 

11^-12 + O(11^15) 

sage: 11^-12 + K(O(11^15)) 

11^-12 + O(11^15) 

sage: K(11^-12, absprec = 15) 

11^-12 + O(11^15) 

sage: K(11^-12, 15) 

11^-12 + O(11^15) 

 

We can also work with `asymptotic expansions`_:: 

 

sage: A.<n> = AsymptoticRing(growth_group='QQ^n * n^QQ * log(n)^QQ', coefficient_ring=QQ); A 

Asymptotic Ring <QQ^n * n^QQ * log(n)^QQ> over Rational Field 

sage: O(n) 

O(n) 

 

TESTS:: 

 

sage: var('x, y') 

(x, y) 

sage: O(x) 

Traceback (most recent call last): 

... 

ArithmeticError: O(x) not defined 

sage: O(y) 

Traceback (most recent call last): 

... 

ArithmeticError: O(y) not defined 

sage: O(x, y) 

Traceback (most recent call last): 

... 

ArithmeticError: O(x, y) not defined 

sage: O(4, 2) 

Traceback (most recent call last): 

... 

ArithmeticError: O(4, 2) not defined 

""" 

if len(x) > 1: 

if isinstance(x[0], multi_power_series_ring_element.MPowerSeries): 

return multi_power_series_ring_element.MO(x, **kwds) 

else: 

raise ArithmeticError("O(%s) not defined" % 

(', '.join(str(e) for e in x),)) 

 

x = x[0] 

 

if isinstance(x, power_series_ring_element.PowerSeries): 

return x.parent()(0, x.degree(), **kwds) 

 

elif isinstance(x, Polynomial): 

if x.parent().ngens() != 1: 

raise NotImplementedError("completion only currently defined " 

"for univariate polynomials") 

if not x.is_monomial(): 

raise NotImplementedError("completion only currently defined " 

"for the maximal ideal (x)") 

return x.parent().completion(x.parent().gen())(0, x.degree(), **kwds) 

 

elif isinstance(x, laurent_series_ring_element.LaurentSeries): 

return laurent_series_ring_element.LaurentSeries(x.parent(), 0).\ 

add_bigoh(x.valuation(), **kwds) 

 

elif isinstance(x, integer_types + (integer.Integer, rational.Rational)): 

# p-adic number 

if x <= 0: 

raise ArithmeticError("x must be a prime power >= 2") 

F = arith.factor(x) 

if len(F) != 1: 

raise ArithmeticError("x must be prime power") 

p, r = F[0] 

if r >= 0: 

return padics_factory.Zp(p, prec=max(r, 20), 

type='capped-rel')(0, absprec=r, **kwds) 

else: 

return padics_factory.Qp(p, prec=max(r, 20), 

type='capped-rel')(0, absprec=r, **kwds) 

 

elif isinstance(x, padic_generic_element.pAdicGenericElement): 

return x.parent()(0, absprec=x.valuation(), **kwds) 

elif hasattr(x, 'O'): 

return x.O(**kwds) 

raise ArithmeticError("O(%s) not defined" % (x,))