Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/symbolic/constants_c.pyx
4097 views
1
"""
2
Wrapper around Pynac's constants
3
"""
4
###############################################################################
5
# Sage: Open Source Mathematical Software
6
# Copyright (C) 2008 William Stein <[email protected]>
7
# Copyright (C) 2008 Burcin Erocal <[email protected]>
8
# 2009 Mike Hansen <[email protected]>
9
# Distributed under the terms of the GNU General Public License (GPL),
10
# version 2 or any later version. The full text of the GPL is available at:
11
# http://www.gnu.org/licenses/
12
###############################################################################
13
from sage.symbolic.expression cimport Expression, new_Expression_from_GEx
14
from sage.symbolic.ring import SR
15
16
from sage.libs.ginac cimport *
17
include "../ext/stdsage.pxi"
18
19
cdef extern from "pynac/constant.h":
20
pass
21
22
cdef class PynacConstant:
23
def __cinit__(self, name, texname, domain_string):
24
"""
25
Creates a constant in Pynac.
26
27
EXAMPLES:
28
29
sage: from sage.symbolic.constants_c import PynacConstant
30
sage: f = PynacConstant('foo', 'foo', 'real')
31
sage: f
32
foo
33
34
Note that this just creates a 'constant' object and not an
35
expression. If you want to work with this constant, you'll
36
have to use the result of :meth:`expression`::
37
38
sage: foo = f.expression()
39
sage: foo + 2
40
foo + 2
41
"""
42
cdef unsigned domain
43
if domain_string == 'complex':
44
domain = domain_complex
45
elif domain_string == 'real':
46
domain = domain_real
47
elif domain_string == 'positive':
48
domain = domain_positive
49
else:
50
raise ValueError
51
52
self._name = name
53
54
#For the constants explicitly defined in constant.cpp in the Pynac
55
#library, we use those symbols.
56
if self._name == "pi":
57
self.pointer = <GConstant *>&g_Pi
58
elif self._name == "catalan":
59
self.pointer = <GConstant *>&g_Catalan
60
elif self._name == "euler_gamma":
61
self.pointer = <GConstant *>&g_Euler
62
else:
63
GConstant_construct(&self.object, name, texname, domain)
64
self.pointer = &self.object
65
66
def __dealloc__(self):
67
if self.pointer == & self.object:
68
GConstant_destruct(&self.object)
69
70
def serial(self):
71
"""
72
Returns the underlying Pynac serial for this constant.
73
74
EXAMPLES::
75
76
sage: from sage.symbolic.constants_c import PynacConstant
77
sage: f = PynacConstant('foo', 'foo', 'real')
78
sage: f.serial() #random
79
15
80
"""
81
return int(self.pointer.get_serial())
82
83
def name(self):
84
"""
85
Returns the name of this constant.
86
87
EXAMPLES::
88
89
sage: from sage.symbolic.constants_c import PynacConstant
90
sage: f = PynacConstant('foo', 'foo', 'real')
91
sage: f.name()
92
'foo'
93
"""
94
return self._name
95
96
def __repr__(self):
97
"""
98
EXAMPLES::
99
100
sage: from sage.symbolic.constants_c import PynacConstant
101
sage: f = PynacConstant('foo', 'foo', 'real'); f
102
foo
103
"""
104
return self.name()
105
106
def expression(self):
107
"""
108
Returns this constant as an Expression.
109
110
EXAMPLES::
111
112
sage: from sage.symbolic.constants_c import PynacConstant
113
sage: f = PynacConstant('foo', 'foo', 'real')
114
sage: f + 2
115
Traceback (most recent call last):
116
...
117
TypeError: unsupported operand parent(s) for '+': '<type 'sage.symbolic.constants_c.PynacConstant'>' and 'Integer Ring'
118
119
sage: foo = f.expression(); foo
120
foo
121
sage: foo + 2
122
foo + 2
123
"""
124
return new_Expression_from_GEx(SR, <GEx>(self.pointer[0]))
125
126
# keep exp(1) for fast access
127
# this is initialized in the constructor of the class E below to prevent
128
# circular imports while loading the library
129
130
# Note, the nearest IEEE 754 value of e is NOT the same as the correctly
131
# rounded decimal value of e.
132
# The numerical value of e = 2.71828182845904523536...
133
# Correctly rounded decimal number = 2.7182818284590452
134
# Nearest IEEE 754 format number = 2.7182818284590451
135
# Value returned on some or all AMD/Intel CPUs = 2.7182818284590451
136
# On Sun Blade 1000 with SPARC processors = 2.7182818284590455
137
138
cdef object exp_one
139
140
cdef class E(Expression):
141
def __init__(self):
142
r"""
143
Dummy class to represent base of the natural logarithm.
144
145
The base of the natural logarithm ``e`` is not a constant in GiNaC/Sage.
146
It is represented by ``exp(1)``.
147
148
This class provides a dummy object that behaves well under addition,
149
multiplication, etc. and on exponentiation calls the function ``exp``.
150
151
EXAMPLES:
152
153
The constant defined at the top level is just ``exp(1)``::
154
155
sage: e.operator()
156
exp
157
sage: e.operands()
158
[1]
159
160
Arithmetic works::
161
162
sage: e + 2
163
e + 2
164
sage: 2 + e
165
e + 2
166
sage: 2*e
167
2*e
168
sage: e*2
169
2*e
170
sage: x*e
171
x*e
172
sage: var('a,b')
173
(a, b)
174
sage: t = e^(a+b); t
175
e^(a + b)
176
sage: t.operands()
177
[a + b]
178
179
Numeric evaluation, conversion to other systems, and pickling works
180
as expected. Note that these are properties of the :func:`exp` function,
181
not this class::
182
183
sage: RR(e)
184
2.71828182845905
185
sage: R = RealField(200); R
186
Real Field with 200 bits of precision
187
sage: R(e)
188
2.7182818284590452353602874713526624977572470936999595749670
189
sage: em = 1 + e^(1-e); em
190
e^(-e + 1) + 1
191
sage: R(em)
192
1.1793740787340171819619895873183164984596816017589156131574
193
sage: maxima(e).float()
194
2.718281828459045
195
sage: t = mathematica(e) # optional
196
sage: t # optional
197
E
198
sage: float(t) # optional
199
2.718281828459045...
200
201
sage: loads(dumps(e))
202
e
203
204
sage: float(e)
205
2.718281828459045...
206
sage: e.__float__()
207
2.718281828459045...
208
sage: e._mpfr_(RealField(100))
209
2.7182818284590452353602874714
210
sage: e._real_double_(RDF)
211
2.71828182846
212
sage: import sympy
213
sage: sympy.E == e # indirect doctest
214
True
215
216
TESTS::
217
218
sage: t = e^a; t
219
e^a
220
sage: t^b
221
(e^a)^b
222
sage: SR(1).exp()
223
e
224
225
Testing that it works with matrices (see :trac:`4735`)::
226
227
sage: m = matrix(QQ, 2, 2, [1,0,0,1])
228
sage: e^m
229
[e 0]
230
[0 e]
231
"""
232
global exp_one
233
exp_one = SR.one_element().exp()
234
Expression.__init__(self, SR, exp_one)
235
236
def __pow__(left, right, dummy):
237
"""
238
Call the `exp` function when taking powers of `e`.
239
240
EXAMPLES::
241
242
sage: var('a,b')
243
(a, b)
244
sage: t = e^a; t
245
e^a
246
sage: t.operator()
247
exp
248
sage: t.operands()
249
[a]
250
251
As opposed to::
252
253
sage: u = SR(1).exp()^a; u
254
e^a
255
sage: u.operator()
256
<built-in function pow>
257
sage: u.operands()
258
[e, a]
259
260
It also works with matrices (see :trac:`4735`)::
261
262
sage: m = matrix(QQ, 2, 2, [1,0,0,1])
263
sage: e^m
264
[e 0]
265
[0 e]
266
sage: A = matrix(RDF, [[1,2],[3,4]])
267
sage: e^A
268
[51.9689561987 74.736564567]
269
[112.104846851 164.073803049]
270
"""
271
if PY_TYPE_CHECK(left, E):
272
if PY_TYPE_CHECK(right, E):
273
return exp_one.exp()
274
try:
275
return right.exp()
276
except AttributeError:
277
return SR(right).exp()
278
else:
279
return SR(left)**exp_one
280
281
282