passagemath-giac 10.5.33__cp310-cp310-musllinux_1_2_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_giac-10.5.33.dist-info/METADATA +153 -0
- passagemath_giac-10.5.33.dist-info/RECORD +34 -0
- passagemath_giac-10.5.33.dist-info/WHEEL +5 -0
- passagemath_giac-10.5.33.dist-info/top_level.txt +2 -0
- passagemath_giac.libs/libcrypto-79ca7c2e.so.3 +0 -0
- passagemath_giac.libs/libcurl-16a78e59.so.4.8.0 +0 -0
- passagemath_giac.libs/libgcc_s-69c45f16.so.1 +0 -0
- passagemath_giac.libs/libgfortran-db0b6589.so.5.0.0 +0 -0
- passagemath_giac.libs/libgiac-6d0de4c7.so.0.0.0 +0 -0
- passagemath_giac.libs/libglpk-aec1f3c8.so.40.3.1 +0 -0
- passagemath_giac.libs/libgmp-8e78bd9b.so.10.5.0 +0 -0
- passagemath_giac.libs/libgsl-75bb3fcc.so.28.0.0 +0 -0
- passagemath_giac.libs/libgslcblas-e0debfeb.so.0.0.0 +0 -0
- passagemath_giac.libs/libintl-3f4788bb.so.8.4.0 +0 -0
- passagemath_giac.libs/libmpfi-8dd9bae1.so.0.0.0 +0 -0
- passagemath_giac.libs/libmpfr-5ff10580.so.6.2.1 +0 -0
- passagemath_giac.libs/libncursesw-13f4e49c.so.6.5 +0 -0
- passagemath_giac.libs/libopenblas_neoversen2p-r0-05b86cab.3.28.so +0 -0
- passagemath_giac.libs/libpari-gmp-tls-e657f88e.so.2.15.5 +0 -0
- passagemath_giac.libs/libreadline-ae76ac25.so.8.2 +0 -0
- passagemath_giac.libs/libssl-7d993165.so.3 +0 -0
- passagemath_giac.libs/libstdc++-1f1a71be.so.6.0.33 +0 -0
- sage/all__sagemath_giac.py +10 -0
- sage/interfaces/all__sagemath_giac.py +1 -0
- sage/interfaces/giac.py +1264 -0
- sage/libs/all__sagemath_giac.py +7 -0
- sage/libs/giac/__init__.py +356 -0
- sage/libs/giac/auto-methods.pxi +16982 -0
- sage/libs/giac/giac.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/libs/giac/giac.pxd +205 -0
- sage/libs/giac/giac.pyx +2074 -0
- sage/libs/giac/keywords.pxi +10 -0
- sage/libs/giac/misc.h +117 -0
- sage_wheels/bin/giac +0 -0
sage/libs/giac/giac.pyx
ADDED
@@ -0,0 +1,2074 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-giac
|
2
|
+
# sage.doctest: needs sage.libs.giac
|
3
|
+
# distutils: libraries = giac
|
4
|
+
# distutils: language = c++
|
5
|
+
# distutils: extra_compile_args = -std=c++11
|
6
|
+
r"""
|
7
|
+
Interface to the c++ giac library.
|
8
|
+
|
9
|
+
Giac is a general purpose Computer algebra system by Bernard Parisse released under GPLv3.
|
10
|
+
|
11
|
+
- http://www-fourier.ujf-grenoble.fr/~parisse/giac.html
|
12
|
+
- It is build on C and C++ libraries: NTL (arithmetic), GSL (numerics), GMP
|
13
|
+
(big integers), MPFR (bigfloats)
|
14
|
+
- It provides fast algorithms for multivariate polynomial operations
|
15
|
+
(product, GCD, factorisation) and
|
16
|
+
- symbolic computations: solver, simplifications, limits/series, integration,
|
17
|
+
summation...
|
18
|
+
- Linear Algebra with numerical or symbolic coefficients.
|
19
|
+
|
20
|
+
AUTHORS:
|
21
|
+
|
22
|
+
- Frederic Han (2013-09-23): initial version
|
23
|
+
- Vincent Delecroix (2020-09-02): move inside Sage source code
|
24
|
+
|
25
|
+
EXAMPLES:
|
26
|
+
|
27
|
+
The class Pygen is the main tool to interact from python/sage with the c++
|
28
|
+
library giac via cython. The initialisation of a Pygen just create an object
|
29
|
+
in giac, but the mathematical computation is not done. This class is mainly
|
30
|
+
for cython users. Here A is a Pygen element, and it is ready for any giac
|
31
|
+
function.::
|
32
|
+
|
33
|
+
sage: from sage.libs.giac.giac import *
|
34
|
+
sage: A = Pygen('2+2')
|
35
|
+
sage: A
|
36
|
+
2+2
|
37
|
+
sage: A.eval()
|
38
|
+
4
|
39
|
+
|
40
|
+
In general, you may prefer to directly create a Pygen and execute the
|
41
|
+
evaluation in giac. This is exactly the meaning of the :func:`libgiac`
|
42
|
+
function.::
|
43
|
+
|
44
|
+
sage: a = libgiac('2+2')
|
45
|
+
sage: a
|
46
|
+
4
|
47
|
+
sage: isinstance(a, Pygen)
|
48
|
+
True
|
49
|
+
|
50
|
+
Most common usage of this package in sage will be with the libgiac() function.
|
51
|
+
This function is just the composition of the Pygen initialisation and the
|
52
|
+
evaluation of this object in giac.::
|
53
|
+
|
54
|
+
sage: x,y,z=libgiac('x,y,z'); # add some giac objects
|
55
|
+
sage: f=(x+3*y)/(x+z+1)^2 -(x+z+1)^2/(x+3*y)
|
56
|
+
sage: f.factor()
|
57
|
+
(3*y-x^2-2*x*z-x-z^2-2*z-1)*(3*y+x^2+2*x*z+3*x+z^2+2*z+1)/((x+z+1)^2*(3*y+x))
|
58
|
+
sage: f.normal()
|
59
|
+
(-x^4-4*x^3*z-4*x^3-6*x^2*z^2-12*x^2*z-5*x^2+6*x*y-4*x*z^3-12*x*z^2-12*x*z-4*x+9*y^2-z^4-4*z^3-6*z^2-4*z-1)/(x^3+3*x^2*y+2*x^2*z+2*x^2+6*x*y*z+6*x*y+x*z^2+2*x*z+x+3*y*z^2+6*y*z+3*y)
|
60
|
+
|
61
|
+
To obtain more hints consider the help of the :func:`libgiac<_giac>`
|
62
|
+
function.::
|
63
|
+
|
64
|
+
sage: libgiac? # doctest: +SKIP
|
65
|
+
|
66
|
+
Some settings of giac are available via the ``giacsettings`` element. (Ex:
|
67
|
+
maximal number of threads in computations, allowing probabilistic algorithms or
|
68
|
+
not...::
|
69
|
+
|
70
|
+
sage: # needs sage.libs.singular
|
71
|
+
sage: R = PolynomialRing(QQ,8,'x')
|
72
|
+
sage: I = sage.rings.ideal.Katsura(R,8)
|
73
|
+
sage: giacsettings.proba_epsilon = 1e-15
|
74
|
+
sage: Igiac = libgiac(I.gens());
|
75
|
+
sage: time Bgiac = Igiac.gbasis([R.gens()],'revlex') # doctest: +SKIP
|
76
|
+
Running a probabilistic check for the reconstructed Groebner basis. If successfull, error probability is less than 1e-15 and is estimated to be less than 10^-109. Use proba_epsilon:=0 to certify (this takes more time).
|
77
|
+
Time: CPU 0.46 s, Wall: 0.50 s
|
78
|
+
sage: giacsettings.proba_epsilon = 0
|
79
|
+
sage: Igiac = libgiac(I.gens())
|
80
|
+
sage: time Bgiac=Igiac.gbasis([R.gens()],'revlex') # doctest: +SKIP
|
81
|
+
Time: CPU 2.74 s, Wall: 2.75 s
|
82
|
+
sage: giacsettings.proba_epsilon = 1e-15
|
83
|
+
|
84
|
+
::
|
85
|
+
|
86
|
+
sage: x = libgiac('x')
|
87
|
+
sage: f = 1/(2+sin(5*x))
|
88
|
+
sage: oldrep = 2/5/sqrt(3)*(atan((2*tan(5*x/2)+1)/sqrt(3))+pi*floor(5*x/2/pi+1/2))
|
89
|
+
sage: newrep = 2/5/sqrt(3)*(atan((-sqrt(3)*sin(5*x)+cos(5*x)+2*sin(5*x)+1)/(sqrt(3)*cos(5*x)+sqrt(3)-2*cos(5*x)+sin(5*x)+2))+5*x/2)
|
90
|
+
sage: ((f.int() - newrep) * (f.int() - oldrep())).normal()
|
91
|
+
0
|
92
|
+
sage: f.series(x,0,3)
|
93
|
+
1/2-5/4*x+25/8*x^2-125/48*x^3+x^4*order_size(x)
|
94
|
+
sage: libgiac(sqrt(5)+pi).approx(100)
|
95
|
+
5.377660631089582934871817052010779119637787758986631545245841837718337331924013898042449233720899343
|
96
|
+
|
97
|
+
TESTS::
|
98
|
+
|
99
|
+
sage: from sage.libs.giac.giac import libgiac
|
100
|
+
sage: libgiac(3^100)
|
101
|
+
515377520732011331036461129765621272702107522001
|
102
|
+
sage: libgiac(-3^100)
|
103
|
+
-515377520732011331036461129765621272702107522001
|
104
|
+
sage: libgiac(-11^1000)
|
105
|
+
-2469932918005826334124088385085221477709733385238396234869182951830739390375433175367866116456946191973803561189036523363533798726571008961243792655536655282201820357872673322901148243453211756020067624545609411212063417307681204817377763465511222635167942816318177424600927358163388910854695041070577642045540560963004207926938348086979035423732739933235077042750354729095729602516751896320598857608367865475244863114521391548985943858154775884418927768284663678512441565517194156946312753546771163991252528017732162399536497445066348868438762510366191040118080751580689254476068034620047646422315123643119627205531371694188794408120267120500325775293645416335230014278578281272863450085145349124727476223298887655183167465713337723258182649072572861625150703747030550736347589416285606367521524529665763903537989935510874657420361426804068643262800901916285076966174176854351055183740078763891951775452021781225066361670593917001215032839838911476044840388663443684517735022039957481918726697789827894303408292584258328090724141496484460001
|
106
|
+
|
107
|
+
Ensure that signed infinities get converted correctly::
|
108
|
+
|
109
|
+
sage: libgiac(+Infinity)
|
110
|
+
+infinity
|
111
|
+
sage: libgiac(-Infinity)
|
112
|
+
-infinity
|
113
|
+
|
114
|
+
.. SEEALSO::
|
115
|
+
|
116
|
+
``libgiac``, ``giacsettings``, ``Pygen``,``loadgiacgen``
|
117
|
+
|
118
|
+
|
119
|
+
GETTING HELP:
|
120
|
+
|
121
|
+
- To obtain some help on a giac keyword use the help() method. In sage the htmlhelp() method for Pygen element is disabled. Just use the ? or .help() method.
|
122
|
+
|
123
|
+
::
|
124
|
+
|
125
|
+
sage: libgiac.gcd? # doctest: +SKIP
|
126
|
+
"Returns the greatest common divisor of 2 polynomials of several variables or of 2 integers or of 2 rationals.
|
127
|
+
(Intg or Poly),(Intg or Poly)
|
128
|
+
gcd(45,75);gcd(15/7,50/9);gcd(x^2-2*x+1,x^3-1);gcd(t^2-2*t+1,t^2+t-2);gcd((x^2-1)*(y^2-1)*z^2,x^3*y^3*z+(-(y^3))*z+x^3*z-z)
|
129
|
+
lcm,euler,modgcd,ezgcd,psrgcd,heugcd,Gcd"
|
130
|
+
|
131
|
+
- You can find full html documentation about the **giac** functions at:
|
132
|
+
|
133
|
+
- http://www-fourier.ujf-grenoble.fr/~parisse/giac/doc/en/cascmd_en/
|
134
|
+
|
135
|
+
- http://www-fourier.ujf-grenoble.fr/~parisse/giac/doc/fr/cascmd_fr/
|
136
|
+
|
137
|
+
- http://www-fourier.ujf-grenoble.fr/~parisse/giac/doc/el/cascmd_el/
|
138
|
+
|
139
|
+
- or in :doc:`$SAGE_LOCAL/share/giac/doc/en/cascmd_en/index.html`
|
140
|
+
|
141
|
+
|
142
|
+
.. NOTE::
|
143
|
+
|
144
|
+
Graphics 2D Output via qcas (the qt frontend to giac) is removed in the
|
145
|
+
sage version of giacpy.
|
146
|
+
"""
|
147
|
+
# ****************************************************************************
|
148
|
+
# Copyright (C) 2012, Frederic Han <frederic.han@imj-prg.fr>
|
149
|
+
# 2020, Vincent Delecroix <20100.delecroix@gmail.com>
|
150
|
+
#
|
151
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
152
|
+
# as published by the Free Software Foundation; either version 2 of
|
153
|
+
# the License, or (at your option) any later version.
|
154
|
+
# https://www.gnu.org/licenses/
|
155
|
+
#*****************************************************************************
|
156
|
+
|
157
|
+
from cysignals.signals cimport *
|
158
|
+
from sys import maxsize as Pymaxint, version_info as Pyversioninfo
|
159
|
+
import os
|
160
|
+
import math
|
161
|
+
|
162
|
+
# sage includes
|
163
|
+
from sage.ext.stdsage cimport PY_NEW
|
164
|
+
from sage.interfaces.giac import giac
|
165
|
+
from sage.libs.gmp.mpz cimport mpz_set
|
166
|
+
from sage.rings.abc import SymbolicRing
|
167
|
+
from sage.rings.integer_ring import ZZ
|
168
|
+
from sage.rings.rational_field import QQ
|
169
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
|
170
|
+
from sage.rings.integer cimport Integer
|
171
|
+
from sage.rings.infinity import AnInfinity
|
172
|
+
from sage.rings.rational cimport Rational
|
173
|
+
from sage.structure.element cimport Matrix, Expression
|
174
|
+
|
175
|
+
|
176
|
+
# Python3 compatibility ############################
|
177
|
+
def encstring23(s):
|
178
|
+
return bytes(s, 'UTF-8')
|
179
|
+
# End of Python3 compatibility #####################
|
180
|
+
|
181
|
+
|
182
|
+
########################################################
|
183
|
+
# A global context pointer. One by giac session.
|
184
|
+
########################################################
|
185
|
+
cdef context * context_ptr = new context()
|
186
|
+
|
187
|
+
# Some global variables for optimisation
|
188
|
+
GIACNULL = Pygen('NULL')
|
189
|
+
|
190
|
+
# Create a giac setting instance
|
191
|
+
giacsettings = GiacSetting()
|
192
|
+
Pygen('I:=sqrt(-1)').eval() # WTF?
|
193
|
+
|
194
|
+
# A function to convert SR Expression with defined giac conversion to a string
|
195
|
+
# for giac/libgiac.
|
196
|
+
# NB: We want to do this without starting an external giac program and
|
197
|
+
# self._giac_() does.
|
198
|
+
try:
|
199
|
+
from sage.symbolic.expression_conversions import InterfaceInit
|
200
|
+
except ImportError:
|
201
|
+
pass
|
202
|
+
else:
|
203
|
+
SRexpressiontoGiac = InterfaceInit(giac)
|
204
|
+
|
205
|
+
|
206
|
+
#######################################################
|
207
|
+
# The wrapper to eval with giac
|
208
|
+
#######################################################
|
209
|
+
# in sage we don't export the giac function. We replace it by libgiac
|
210
|
+
def _giac(s):
|
211
|
+
"""
|
212
|
+
This function evaluate a python/sage object with the giac library. It creates in python/sage a Pygen element and evaluate it with giac:
|
213
|
+
|
214
|
+
EXAMPLES::
|
215
|
+
|
216
|
+
sage: from sage.libs.giac.giac import libgiac
|
217
|
+
sage: x,y = libgiac('x,y')
|
218
|
+
sage: (x+2*y).cos().texpand()
|
219
|
+
cos(x)*(2*cos(y)^2-1)-sin(x)*2*cos(y)*sin(y)
|
220
|
+
|
221
|
+
Coercion, Pygen and internal giac variables: The most useful objects will
|
222
|
+
be the Python object of type Pygen.::
|
223
|
+
|
224
|
+
sage: x,y,z = libgiac('x,y,z')
|
225
|
+
sage: f = sum([x[i] for i in range(5)])^15/(y+z);f.coeff(x[0],12)
|
226
|
+
(455*(x[1])^3+1365*(x[1])^2*x[2]+1365*(x[1])^2*x[3]+1365*(x[1])^2*x[4]+1365*x[1]*(x[2])^2+2730*x[1]*x[2]*x[3]+2730*x[1]*x[2]*x[4]+1365*x[1]*(x[3])^2+2730*x[1]*x[3]*x[4]+1365*x[1]*(x[4])^2+455*(x[2])^3+1365*(x[2])^2*x[3]+1365*(x[2])^2*x[4]+1365*x[2]*(x[3])^2+2730*x[2]*x[3]*x[4]+1365*x[2]*(x[4])^2+455*(x[3])^3+1365*(x[3])^2*x[4]+1365*x[3]*(x[4])^2+455*(x[4])^3)/(y+z)
|
227
|
+
|
228
|
+
Warning: The complex number sqrt(-1) is exported in python as I. (But it
|
229
|
+
may appears as i)::
|
230
|
+
|
231
|
+
sage: libgiac((1+I*sqrt(3))^3).normal()
|
232
|
+
-8
|
233
|
+
sage: libgiac(1+I)
|
234
|
+
1+i
|
235
|
+
|
236
|
+
Python integers and reals can be directly converted to giac.::
|
237
|
+
|
238
|
+
sage: a = libgiac(2^1024);a.nextprime()
|
239
|
+
179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137859
|
240
|
+
sage: libgiac(1.234567).erf().approx(10)
|
241
|
+
0.9191788641
|
242
|
+
|
243
|
+
The Python object y defined above is of type Pygen. It is not an internal
|
244
|
+
giac variable. (Most of the time you won't need to use internal giac
|
245
|
+
variables).::
|
246
|
+
|
247
|
+
sage: libgiac('y:=1'); y
|
248
|
+
1
|
249
|
+
y
|
250
|
+
sage: libgiac.purge('y')
|
251
|
+
1
|
252
|
+
sage: libgiac('y')
|
253
|
+
y
|
254
|
+
|
255
|
+
There are some natural coercion to Pygen elements::
|
256
|
+
|
257
|
+
sage: libgiac(pi)>3.14 ; libgiac(pi) >3.15 ; libgiac(3)==3
|
258
|
+
True
|
259
|
+
False
|
260
|
+
True
|
261
|
+
|
262
|
+
Linear Algebra. In Giac/Xcas vectors are just lists and matrices are lists
|
263
|
+
of list::
|
264
|
+
|
265
|
+
sage: x,y = libgiac('x,y')
|
266
|
+
sage: A = libgiac([[1,2],[3,4]]) # we create a giac matrix from it lines
|
267
|
+
sage: v = libgiac([x,y]); v # a giac vector
|
268
|
+
[x,y]
|
269
|
+
sage: A*v # matrix product with a vector outputs a vector
|
270
|
+
[x+2*y,3*x+4*y]
|
271
|
+
sage: v*v # dot product
|
272
|
+
x*x+y*y
|
273
|
+
|
274
|
+
Remark that ``w=giac([[x],[y]])`` is a matrix of 1 column and 2 rows. It is
|
275
|
+
not a vector so w*w doesn't make sense.::
|
276
|
+
|
277
|
+
sage: w = libgiac([[x],[y]])
|
278
|
+
sage: w.transpose()*w # this matrix product makes sense and output a 1x1 matrix.
|
279
|
+
matrix[[x*x+y*y]]
|
280
|
+
|
281
|
+
In sage affectation doesn't create a new matrix. (cf. pointers) see also
|
282
|
+
the doc of 'Pygen.__setitem__':
|
283
|
+
|
284
|
+
::
|
285
|
+
|
286
|
+
sage: B1=A;
|
287
|
+
sage: B1[0,0]=43; B1 # in place affectation changes both B1 and A
|
288
|
+
[[43,2],[3,4]]
|
289
|
+
sage: A
|
290
|
+
[[43,2],[3,4]]
|
291
|
+
sage: A[0][0]=A[0][0]+1; A # similar as A[0,0]=A[0,0]+1
|
292
|
+
[[44,2],[3,4]]
|
293
|
+
sage: A.pcar(x) # compute the characteristic polynomial of A
|
294
|
+
x^2-48*x+170
|
295
|
+
sage: B2=A.copy() # use copy to create another object
|
296
|
+
sage: B2[0,0]=55; B2 # here A is not modified
|
297
|
+
[[55,2],[3,4]]
|
298
|
+
sage: A
|
299
|
+
[[44,2],[3,4]]
|
300
|
+
|
301
|
+
Sparse Matrices are available via the table function:
|
302
|
+
|
303
|
+
::
|
304
|
+
|
305
|
+
sage: A = libgiac.table(()); A # create an empty giac table
|
306
|
+
table(
|
307
|
+
)
|
308
|
+
sage: A[2,3] = 33; A[0,2] = '2/7' # set nonzero entries of the sparse matrix
|
309
|
+
sage: A*A # basic matrix operation are supported with sparse matrices
|
310
|
+
table(
|
311
|
+
(0,3) = 66/7
|
312
|
+
)
|
313
|
+
sage: D = libgiac.diag([22,3,'1/7']); D # some diagonal matrix
|
314
|
+
[[22,0,0],[0,3,0],[0,0,1/7]]
|
315
|
+
sage: libgiac.table(D) # to create a sparse matrix from an ordinary one
|
316
|
+
table(
|
317
|
+
(0,0) = 22,
|
318
|
+
(1,1) = 3,
|
319
|
+
(2,2) = 1/7
|
320
|
+
)
|
321
|
+
|
322
|
+
But many matrix functions apply only with ordinary matrices so need conversions:
|
323
|
+
|
324
|
+
::
|
325
|
+
|
326
|
+
sage: B1 = A.matrix(); B1 # convert the sparse matrix to a matrix, but the size is minimal
|
327
|
+
[[0,0,2/7,0],[0,0,0,0],[0,0,0,33]]
|
328
|
+
sage: B2 = B1.redim(4,4) # so we may need to resize B1
|
329
|
+
sage: B2.pmin(x)
|
330
|
+
x^3
|
331
|
+
|
332
|
+
Lists of Pygen and Giac lists. Here l1 is a giac list and l2 is a python
|
333
|
+
list of Pygen type objects.
|
334
|
+
|
335
|
+
::
|
336
|
+
|
337
|
+
sage: l1 = libgiac(range(10)); l2=[1/(i^2+1) for i in l1]
|
338
|
+
sage: sum(l2)
|
339
|
+
33054527/16762850
|
340
|
+
|
341
|
+
So l1+l1 is done in giac and means a vector addition. But l2+l2 is done in Python so it is the list concatenation.
|
342
|
+
|
343
|
+
::
|
344
|
+
|
345
|
+
sage: l1+l1
|
346
|
+
[0,2,4,6,8,10,12,14,16,18]
|
347
|
+
sage: l2+l2
|
348
|
+
[1, 1/2, 1/5, 1/10, 1/17, 1/26, 1/37, 1/50, 1/65, 1/82, 1, 1/2, 1/5, 1/10, 1/17, 1/26, 1/37, 1/50, 1/65, 1/82]
|
349
|
+
|
350
|
+
Here V is not a Pygen element. We need to push it to giac to use a giac
|
351
|
+
method like dim, or we need to use an imported function.
|
352
|
+
|
353
|
+
::
|
354
|
+
|
355
|
+
sage: V = [ [x[i]^j for i in range(8)] for j in range(8)]
|
356
|
+
sage: libgiac(V).dim()
|
357
|
+
[8,8]
|
358
|
+
sage: libgiac.det_minor(V).factor()
|
359
|
+
(x[6]-(x[7]))*(x[5]-(x[7]))*(x[5]-(x[6]))*(x[4]-(x[7]))*(x[4]-(x[6]))*(x[4]-(x[5]))*(x[3]-(x[7]))*(x[3]-(x[6]))*(x[3]-(x[5]))*(x[3]-(x[4]))*(x[2]-(x[7]))*(x[2]-(x[6]))*(x[2]-(x[5]))*(x[2]-(x[4]))*(x[2]-(x[3]))*(x[1]-(x[7]))*(x[1]-(x[6]))*(x[1]-(x[5]))*(x[1]-(x[4]))*(x[1]-(x[3]))*(x[1]-(x[2]))*(x[0]-(x[7]))*(x[0]-(x[6]))*(x[0]-(x[5]))*(x[0]-(x[4]))*(x[0]-(x[3]))*(x[0]-(x[2]))*(x[0]-(x[1]))
|
360
|
+
|
361
|
+
Modular objects with ``%``.::
|
362
|
+
|
363
|
+
sage: V = libgiac.ranm(5,6) % 2;
|
364
|
+
sage: V.ker().rowdim()+V.rank()
|
365
|
+
6
|
366
|
+
sage: a = libgiac(7)%3; a; a%0; 7%3
|
367
|
+
1 % 3
|
368
|
+
1
|
369
|
+
1
|
370
|
+
|
371
|
+
Do not confuse with the python integers::
|
372
|
+
|
373
|
+
sage: type(7%3)==type(a);type(a)==type(7%3)
|
374
|
+
False
|
375
|
+
False
|
376
|
+
|
377
|
+
Syntax with reserved or unknown Python/sage symbols. In general equations
|
378
|
+
needs symbols such as ``=``, ``<`` or ``>`` that have another meaning in Python
|
379
|
+
or Sage. So those objects must be quoted.::
|
380
|
+
|
381
|
+
sage: x = libgiac('x')
|
382
|
+
sage: (1+2*sin(3*x)).solve(x).simplify()
|
383
|
+
...list[-pi/18,7*pi/18]
|
384
|
+
|
385
|
+
sage: libgiac.solve('x^3-x>x',x)
|
386
|
+
list[((x>(-sqrt(2))) and (x<0)),x>(sqrt(2))]
|
387
|
+
|
388
|
+
You can also add some hypothesis to a giac symbol::
|
389
|
+
|
390
|
+
sage: libgiac.assume('x>-pi && x<pi')
|
391
|
+
x
|
392
|
+
sage: libgiac.solve('sin(3*x)>2*sin(x)',x)
|
393
|
+
list[((x>(-5*pi/6)) and (x<(-pi/6))),((x>0) and (x<(pi/6))),((x>(5*pi/6)) and (x<pi))]
|
394
|
+
|
395
|
+
To remove those hypothesis use the giac function: ``purge``::
|
396
|
+
|
397
|
+
sage: libgiac.purge('x')
|
398
|
+
assume[[],[line[-pi,pi]],[-pi,pi]]
|
399
|
+
sage: libgiac.solve('x>0')
|
400
|
+
list[x>0]
|
401
|
+
|
402
|
+
Same problems with the ``..``::
|
403
|
+
|
404
|
+
sage: x = libgiac('x')
|
405
|
+
sage: f = 1/(5+cos(4*x))
|
406
|
+
sage: oldrep = 1/2/(2*sqrt(6))*(atan(2*tan(4*x/2)/sqrt(6))+pi*floor(4*x/2/pi+1/2))
|
407
|
+
sage: newrep = 1/2/(2*sqrt(6))*(atan((-sqrt(6)*sin(4*x)+2*sin(4*x))/(sqrt(6)*cos(4*x)+sqrt(6)-2*cos(4*x)+2))+4*x/2)
|
408
|
+
sage: ((f.int(x) - newrep)*(f.int(x)-oldrep)).normal()
|
409
|
+
0
|
410
|
+
sage: libgiac.fMax(f,'x=-0..pi').simplify()
|
411
|
+
pi/4,3*pi/4
|
412
|
+
sage: libgiac.fMax.help() # doctest: +SKIP
|
413
|
+
"Returns the abscissa of the maximum of the expression.
|
414
|
+
Expr,[Var]
|
415
|
+
fMax(-x^2+2*x+1,x)
|
416
|
+
fMin"
|
417
|
+
sage: libgiac.sum(1/(1+x^2),'x=0..infinity').simplify()
|
418
|
+
(pi*exp(pi)^2+pi+exp(pi)^2-1)/(2*exp(pi)^2-2)
|
419
|
+
|
420
|
+
From giac to sage. One can convert a Pygen element to sage with the sage
|
421
|
+
method. Get more details with::
|
422
|
+
|
423
|
+
sage: Pygen.sage? # doctest: +SKIP
|
424
|
+
|
425
|
+
::
|
426
|
+
|
427
|
+
sage: L = libgiac('[1,sqrt(5),[1.3,x]]')
|
428
|
+
sage: L.sage() # All entries are converted recursively
|
429
|
+
[1, sqrt(5), [1.30000000000000, x]]
|
430
|
+
|
431
|
+
To obtain matrices and vectors, use the :meth:`matrix<Pygen._matrix_>` and
|
432
|
+
:meth:`vector<Pygen._vector_>` commands. Get more details with::
|
433
|
+
|
434
|
+
sage: Pygen._matrix_? # doctest: +SKIP
|
435
|
+
sage: Pygen._vector_? # doctest: +SKIP
|
436
|
+
|
437
|
+
::
|
438
|
+
|
439
|
+
sage: n = var('n'); A = matrix([[1,2],[-1,1]])
|
440
|
+
sage: B = libgiac(A).matpow(n) # We compute the symbolic power on A via libgiac
|
441
|
+
sage: C = matrix(SR,B); C # We convert B to sage
|
442
|
+
[ 1/2*(I*sqrt(2) + 1)^n + 1/2*(-I*sqrt(2) + 1)^n -1/2*I*sqrt(2)*(I*sqrt(2) + 1)^n + 1/2*I*sqrt(2)*(-I*sqrt(2) + 1)^n]
|
443
|
+
[ 1/4*I*sqrt(2)*(I*sqrt(2) + 1)^n - 1/4*I*sqrt(2)*(-I*sqrt(2) + 1)^n 1/2*(I*sqrt(2) + 1)^n + 1/2*(-I*sqrt(2) + 1)^n]
|
444
|
+
sage: (C.subs(n=3)-A^3).expand()
|
445
|
+
[0 0]
|
446
|
+
[0 0]
|
447
|
+
|
448
|
+
|
449
|
+
**MEMENTO of usual GIAC functions**:
|
450
|
+
|
451
|
+
- *Expand with simplification*
|
452
|
+
|
453
|
+
* ``ratnormal``, ``normal``, ``simplify`` (from the fastest to the most sophisticated)
|
454
|
+
|
455
|
+
* NB: ``expand`` function doesn't regroup nor cancel terms, so it could be slow. (pedagogical purpose only?)
|
456
|
+
|
457
|
+
- *Factor/Regroup*
|
458
|
+
|
459
|
+
* ``factor``, ``factors``, ``regroup``, ``cfactor``, ``ifactor``
|
460
|
+
|
461
|
+
- *Misc*
|
462
|
+
|
463
|
+
* ``unapply``, ``op``, ``subst``
|
464
|
+
|
465
|
+
- *Polynomials/Fractions*
|
466
|
+
|
467
|
+
* ``coeff``, ``gbasis``, ``greduce``, ``lcoeff``, ``pcoeff``, ``canonical_form``,
|
468
|
+
|
469
|
+
* ``proot``, ``poly2symb``, ``symb2poly``, ``posubLMQ``, ``poslbdLMQ``, ``VAS``, ``tcoeff``, ``valuation``
|
470
|
+
|
471
|
+
* ``gcd``, ``egcd``, ``lcm``, ``quo``, ``rem``, ``quorem``, ``abcuv``, ``chinrem``,
|
472
|
+
|
473
|
+
* ``peval``, ``horner``, ``lagrange``, ``ptayl``, ``spline``, ``sturm``, ``sturmab``
|
474
|
+
|
475
|
+
* ``partfrac``, ``cpartfrac``
|
476
|
+
|
477
|
+
- *Memory/Variables*
|
478
|
+
|
479
|
+
* ``assume``, ``about``, ``purge``, ``ans``
|
480
|
+
|
481
|
+
- *Calculus/Exact*
|
482
|
+
|
483
|
+
* ``linsolve``, ``solve``, ``csolve``, ``desolve``, ``seqsolve``, ``reverse_rsolve``, ``matpow``
|
484
|
+
|
485
|
+
* ``limit``, ``series``, ``sum``, ``diff``, ``fMax``, ``fMin``,
|
486
|
+
|
487
|
+
* ``integrate``, ``subst``, ``ibpdv``, ``ibpu``, ``preval``
|
488
|
+
|
489
|
+
- *Calculus/Exp, Log, powers*
|
490
|
+
|
491
|
+
* ``exp2pow``, ``hyp2exp``, ``expexpand``, ``lin``, ``lncollect``, ``lnexpand``, ``powexpand``, ``pow2exp``
|
492
|
+
|
493
|
+
- *Trigo*
|
494
|
+
|
495
|
+
* ``trigexpand``, ``tsimplify``, ``tlin``, ``tcollect``,
|
496
|
+
|
497
|
+
* ``halftan``, ``cos2sintan``, ``sin2costan``, ``tan2sincos``, ``tan2cossin2``, ``tan2sincos2``, ``trigcos``, ``trigsin``, ``trigtan``, ``shift_phase``
|
498
|
+
|
499
|
+
* ``exp2trig``, ``trig2exp``
|
500
|
+
|
501
|
+
* ``atrig2ln``, ``acos2asin``, ``acos2atan``, ``asin2acos``, ``asin2atan``, ``atan2acos``, ``atan2asin``
|
502
|
+
|
503
|
+
- *Linear Algebra*
|
504
|
+
|
505
|
+
* ``identity``, ``matrix``, ``makemat``, ``syst2mat``, ``matpow``, ``table``, ``redim``
|
506
|
+
|
507
|
+
* ``det``, ``det_minor``, ``rank``, ``ker``, ``image``, ``rref``, ``simplex_reduce``,
|
508
|
+
|
509
|
+
* ``egv``, ``egvl``, ``eigenvalues``, ``pcar``, ``pcar_hessenberg``, ``pmin``,
|
510
|
+
|
511
|
+
* ``jordan``, ``adjoint_matrix``, ``companion``, ``hessenberg``, ``transpose``,
|
512
|
+
|
513
|
+
* ``cholesky``, ``lll``, ``lu``, ``qr``, ``svd``, ``a2q``, ``gauss``, ``gramschmidt``,
|
514
|
+
``q2a``, ``isom``, ``mkisom``
|
515
|
+
|
516
|
+
|
517
|
+
- *Finite Fields*
|
518
|
+
|
519
|
+
* ``%``, ``% 0``, ``mod``, ``GF``, ``powmod``
|
520
|
+
|
521
|
+
|
522
|
+
- *Integers*
|
523
|
+
|
524
|
+
* ``gcd``, ``iabcuv``, ``ichinrem``, ``idivis``, ``iegcd``,
|
525
|
+
|
526
|
+
* ``ifactor``, ``ifactors``, ``iquo``, ``iquorem``, ``irem``,
|
527
|
+
|
528
|
+
* ``is_prime, is_pseudoprime``, ``lcm``, ``mod``, ``nextprime``, ``pa2b2``, ``prevprime``,
|
529
|
+
``smod``, ``euler``, ``fracmod``
|
530
|
+
|
531
|
+
- *List*
|
532
|
+
|
533
|
+
* ``append``, ``accumulate_head_tail``, ``concat``, ``head``, ``makelist``, ``member``, ``mid``, ``revlist``, ``rotate``, ``shift``, ``size``, ``sizes``, ``sort``, ``suppress``, ``tail``
|
534
|
+
|
535
|
+
- *Set*
|
536
|
+
|
537
|
+
* ``intersect``, ``minus``, ``union``, ``is_element``, ``is_included``
|
538
|
+
"""
|
539
|
+
return Pygen(s).eval()
|
540
|
+
|
541
|
+
|
542
|
+
#######################################
|
543
|
+
# A class to adjust giac configuration
|
544
|
+
#######################################
|
545
|
+
cdef class GiacSetting(Pygen):
|
546
|
+
"""
|
547
|
+
A class to customise the Computer Algebra System settings.
|
548
|
+
|
549
|
+
EXAMPLES::
|
550
|
+
|
551
|
+
sage: from sage.libs.giac.giac import giacsettings, libgiac
|
552
|
+
|
553
|
+
``threads`` (maximal number of allowed theads in giac)::
|
554
|
+
|
555
|
+
sage: from sage.libs.giac.giac import giacsettings
|
556
|
+
sage: import os
|
557
|
+
sage: try:
|
558
|
+
....: ncpu = int(os.environ['SAGE_NUM_THREADS'])
|
559
|
+
....: except KeyError:
|
560
|
+
....: ncpu =1
|
561
|
+
sage: giacsettings.threads == ncpu
|
562
|
+
True
|
563
|
+
|
564
|
+
``digits`` (default digit number used for approximations)::
|
565
|
+
|
566
|
+
sage: giacsettings.digits = 20
|
567
|
+
sage: libgiac.approx('1/7')
|
568
|
+
0.14285714285714285714
|
569
|
+
sage: giacsettings.digits = 50
|
570
|
+
sage: libgiac.approx('1/7')
|
571
|
+
0.14285714285714285714285714285714285714285714285714
|
572
|
+
sage: giacsettings.digits = 12
|
573
|
+
|
574
|
+
``sqrtflag`` (flag to allow sqrt extractions during solve and
|
575
|
+
factorizations)::
|
576
|
+
|
577
|
+
sage: giacsettings.sqrtflag = False
|
578
|
+
sage: libgiac('x**2-2').factor()
|
579
|
+
x^2-2
|
580
|
+
sage: giacsettings.sqrtflag = True
|
581
|
+
sage: libgiac('x**2-2').factor()
|
582
|
+
(x-sqrt(2))*(x+sqrt(2))
|
583
|
+
|
584
|
+
``complexflag`` (flag to allow complex number in solving equations or factorizations)::
|
585
|
+
|
586
|
+
sage: giacsettings.complexflag=False;giacsettings.complexflag
|
587
|
+
False
|
588
|
+
sage: libgiac('x**2+4').factor()
|
589
|
+
x^2+4
|
590
|
+
sage: giacsettings.complexflag = True
|
591
|
+
sage: libgiac('x**2+4').factor()
|
592
|
+
(x+2*i)*(x-2*i)
|
593
|
+
|
594
|
+
|
595
|
+
``eval_level`` (recursive level of substitution of variables during an
|
596
|
+
evaluation)::
|
597
|
+
|
598
|
+
sage: giacsettings.eval_level = 1
|
599
|
+
sage: libgiac("purge(a):;b:=a;a:=1;b")
|
600
|
+
"Done",a,1,a
|
601
|
+
sage: giacsettings.eval_level=25; giacsettings.eval_level
|
602
|
+
25
|
603
|
+
sage: libgiac("purge(a):;b:=a;a:=1;b")
|
604
|
+
"Done",a,1,1
|
605
|
+
|
606
|
+
``proba_epsilon`` (maximum probability of a wrong answer with a probabilist
|
607
|
+
algorithm). Set this number to 0 to disable probabilist algorithms
|
608
|
+
(slower)::
|
609
|
+
|
610
|
+
sage: giacsettings.proba_epsilon=0;libgiac('proba_epsilon')
|
611
|
+
0.0
|
612
|
+
sage: giacsettings.proba_epsilon=10^(-13)
|
613
|
+
sage: libgiac('proba_epsilon')<10^(-14)
|
614
|
+
False
|
615
|
+
|
616
|
+
``epsilon`` (value used by the ``epsilon2zero`` function)::
|
617
|
+
|
618
|
+
sage: giacsettings.epsilon = 1e-10
|
619
|
+
sage: P = libgiac('1e-11+x+5')
|
620
|
+
sage: P == x+5
|
621
|
+
False
|
622
|
+
sage: (P.epsilon2zero()).simplify()
|
623
|
+
x+5
|
624
|
+
"""
|
625
|
+
def __repr__(self):
|
626
|
+
return "Giac Settings"
|
627
|
+
|
628
|
+
def _sage_doc_(self):
|
629
|
+
return GiacSetting.__doc__
|
630
|
+
|
631
|
+
property digits:
|
632
|
+
r"""
|
633
|
+
Default digits number used for approximations.
|
634
|
+
|
635
|
+
EXAMPLES::
|
636
|
+
|
637
|
+
sage: from sage.libs.giac.giac import giacsettings, libgiac
|
638
|
+
sage: giacsettings.digits = 20
|
639
|
+
sage: giacsettings.digits
|
640
|
+
20
|
641
|
+
sage: libgiac.approx('1/7')
|
642
|
+
0.14285714285714285714
|
643
|
+
sage: giacsettings.digits=12;
|
644
|
+
"""
|
645
|
+
def __get__(self):
|
646
|
+
return (self.cas_setup()[6])._val
|
647
|
+
|
648
|
+
def __set__(self, value):
|
649
|
+
l = Pygen('cas_setup()').eval()
|
650
|
+
pl = [ i for i in l ]
|
651
|
+
pl[6] = value
|
652
|
+
Pygen('cas_setup(%s)' % pl).eval()
|
653
|
+
|
654
|
+
property sqrtflag:
|
655
|
+
r"""
|
656
|
+
Flag to allow square roots in solving equations or factorizations.
|
657
|
+
"""
|
658
|
+
def __get__(self):
|
659
|
+
return (self.cas_setup()[9])._val == 1
|
660
|
+
|
661
|
+
def __set__(self, value):
|
662
|
+
l = Pygen('cas_setup()').eval()
|
663
|
+
pl = [ i for i in l ]
|
664
|
+
if value:
|
665
|
+
pl[9]=1
|
666
|
+
else:
|
667
|
+
pl[9]=0
|
668
|
+
Pygen('cas_setup(%s)' % pl).eval()
|
669
|
+
|
670
|
+
property complexflag:
|
671
|
+
r"""
|
672
|
+
Flag to allow complex number in solving equations or factorizations.
|
673
|
+
|
674
|
+
EXAMPLES::
|
675
|
+
|
676
|
+
sage: from sage.libs.giac.giac import libgiac, giacsettings
|
677
|
+
sage: giacsettings.complexflag = False
|
678
|
+
sage: giacsettings.complexflag
|
679
|
+
False
|
680
|
+
sage: libgiac('x**2+4').factor()
|
681
|
+
x^2+4
|
682
|
+
sage: giacsettings.complexflag=True;
|
683
|
+
sage: libgiac('x**2+4').factor()
|
684
|
+
(x+2*i)*(x-2*i)
|
685
|
+
"""
|
686
|
+
def __get__(self):
|
687
|
+
return (self.cas_setup()[2])._val == 1
|
688
|
+
|
689
|
+
def __set__(self, value):
|
690
|
+
l = Pygen('cas_setup()').eval()
|
691
|
+
pl = [ i for i in l ]
|
692
|
+
if value:
|
693
|
+
pl[2] = 1
|
694
|
+
else:
|
695
|
+
pl[2] = 0
|
696
|
+
Pygen('cas_setup(%s)' % pl).eval()
|
697
|
+
|
698
|
+
property eval_level:
|
699
|
+
r"""
|
700
|
+
Recursive level of substitution of variables during an evaluation.
|
701
|
+
|
702
|
+
EXAMPLES::
|
703
|
+
|
704
|
+
sage: from sage.libs.giac.giac import giacsettings,libgiac
|
705
|
+
sage: giacsettings.eval_level=1
|
706
|
+
sage: libgiac("purge(a):;b:=a;a:=1;b")
|
707
|
+
"Done",a,1,a
|
708
|
+
sage: giacsettings.eval_level=25; giacsettings.eval_level
|
709
|
+
25
|
710
|
+
sage: libgiac("purge(a):;b:=a;a:=1;b")
|
711
|
+
"Done",a,1,1
|
712
|
+
sage: libgiac.purge('a,b')
|
713
|
+
1,a
|
714
|
+
"""
|
715
|
+
def __get__(self):
|
716
|
+
return (self.cas_setup()[7][3])._val
|
717
|
+
|
718
|
+
def __set__(self, value):
|
719
|
+
l = Pygen('cas_setup()').eval()
|
720
|
+
pl = [ i for i in l ]
|
721
|
+
pl[7] = [l[7][0],l[7][1],l[7][2], value]
|
722
|
+
Pygen('cas_setup(%s)' % pl).eval()
|
723
|
+
|
724
|
+
property proba_epsilon:
|
725
|
+
r"""
|
726
|
+
Maximum probability of a wrong answer with a probabilist algorithm.
|
727
|
+
|
728
|
+
Set this number to 0 to disable probabilist algorithms (slower).
|
729
|
+
|
730
|
+
EXAMPLES::
|
731
|
+
|
732
|
+
sage: from sage.libs.giac.giac import giacsettings,libgiac
|
733
|
+
sage: giacsettings.proba_epsilon=0;libgiac('proba_epsilon')
|
734
|
+
0.0
|
735
|
+
sage: giacsettings.proba_epsilon=10^(-13)
|
736
|
+
sage: libgiac('proba_epsilon')<10^(-14)
|
737
|
+
False
|
738
|
+
"""
|
739
|
+
def __get__(self):
|
740
|
+
return (self.cas_setup()[5][1])._double
|
741
|
+
|
742
|
+
def __set__(self, value):
|
743
|
+
l = Pygen('cas_setup()').eval()
|
744
|
+
pl = [ i for i in l ]
|
745
|
+
pl[5] = [l[5][0],value]
|
746
|
+
Pygen('cas_setup(%s)' % pl).eval()
|
747
|
+
|
748
|
+
property epsilon:
|
749
|
+
r"""
|
750
|
+
Value used by the ``epsilon2zero`` function.
|
751
|
+
|
752
|
+
EXAMPLES::
|
753
|
+
|
754
|
+
sage: from sage.libs.giac.giac import giacsettings,libgiac
|
755
|
+
sage: giacsettings.epsilon = 1e-10
|
756
|
+
sage: P = libgiac('1e-11+x+5')
|
757
|
+
sage: P == x+5
|
758
|
+
False
|
759
|
+
sage: (P.epsilon2zero()).simplify()
|
760
|
+
x+5
|
761
|
+
"""
|
762
|
+
def __get__(self):
|
763
|
+
return (self.cas_setup()[5][0])._double
|
764
|
+
|
765
|
+
def __set__(self, value):
|
766
|
+
l = Pygen('cas_setup()').eval()
|
767
|
+
pl = [ i for i in l ]
|
768
|
+
pl[5] = [value,l[5][1]]
|
769
|
+
Pygen('cas_setup(%s)' % pl).eval()
|
770
|
+
|
771
|
+
property threads:
|
772
|
+
r"""
|
773
|
+
Maximal number of allowed theads in giac.
|
774
|
+
"""
|
775
|
+
def __get__(self):
|
776
|
+
return (self.cas_setup()[7][0])._val
|
777
|
+
|
778
|
+
def __set__(self, value):
|
779
|
+
Pygen('threads:=%s' % str(value)).eval()
|
780
|
+
|
781
|
+
########################################################
|
782
|
+
# #
|
783
|
+
# The python class that points to a cpp giac gen #
|
784
|
+
# #
|
785
|
+
########################################################
|
786
|
+
include 'auto-methods.pxi'
|
787
|
+
|
788
|
+
cdef class Pygen(GiacMethods_base):
|
789
|
+
|
790
|
+
cdef gen * gptr #pointer to the corresponding C++ element of type giac::gen
|
791
|
+
|
792
|
+
def __cinit__(self, s=None):
|
793
|
+
|
794
|
+
#NB: the != here gives problems with the __richcmp__ function
|
795
|
+
#if (s!=None):
|
796
|
+
# so it's better to use isinstance
|
797
|
+
if (isinstance(s, None.__class__)):
|
798
|
+
# Do NOT replace with: self=GIACNULL (cf the doctest in __repr__
|
799
|
+
sig_on()
|
800
|
+
self.gptr = new gen ((<Pygen>GIACNULL).gptr[0])
|
801
|
+
sig_off()
|
802
|
+
return
|
803
|
+
|
804
|
+
if isinstance(s, int):
|
805
|
+
# This looks 100 faster than the str initialisation
|
806
|
+
if s.bit_length() < Pymaxint.bit_length():
|
807
|
+
sig_on()
|
808
|
+
self.gptr = new gen(<long long>s)
|
809
|
+
sig_off()
|
810
|
+
else:
|
811
|
+
sig_on()
|
812
|
+
self.gptr = new gen(pylongtogen(s))
|
813
|
+
sig_off()
|
814
|
+
|
815
|
+
elif isinstance(s, Integer): # for sage int (gmp)
|
816
|
+
sig_on()
|
817
|
+
if (abs(s)>Pymaxint):
|
818
|
+
self.gptr = new gen((<Integer>s).value)
|
819
|
+
else:
|
820
|
+
self.gptr = new gen(<long long>s) # important for pow to have a int
|
821
|
+
sig_off()
|
822
|
+
|
823
|
+
elif isinstance(s, Rational): # for sage rat (gmp)
|
824
|
+
#self.gptr = new gen((<Pygen>(Pygen(s.numerator())/Pygen(s.denominator()))).gptr[0])
|
825
|
+
# FIXME: it's slow
|
826
|
+
sig_on()
|
827
|
+
self.gptr = new gen(GIAC_rdiv(gen((<Integer>(s.numerator())).value),gen((<Integer>(s.denominator())).value)))
|
828
|
+
sig_off()
|
829
|
+
|
830
|
+
elif isinstance(s, Matrix):
|
831
|
+
s = Pygen(s.list()).list2mat(s.ncols())
|
832
|
+
sig_on()
|
833
|
+
self.gptr = new gen((<Pygen>s).gptr[0])
|
834
|
+
sig_off()
|
835
|
+
|
836
|
+
elif isinstance(s, float):
|
837
|
+
sig_on()
|
838
|
+
self.gptr = new gen(<double>s)
|
839
|
+
sig_off()
|
840
|
+
|
841
|
+
elif isinstance(s, Pygen):
|
842
|
+
# in the test: x,y=Pygen('x,y');((x+2*y).sin()).texpand()
|
843
|
+
# the y are lost without this case.
|
844
|
+
sig_on()
|
845
|
+
self.gptr = new gen((<Pygen>s).gptr[0])
|
846
|
+
sig_off()
|
847
|
+
|
848
|
+
elif isinstance(s, (list, range)):
|
849
|
+
sig_on()
|
850
|
+
self.gptr = new gen(_wrap_pylist(<list>s),<short int>0)
|
851
|
+
sig_off()
|
852
|
+
|
853
|
+
elif isinstance(s, tuple):
|
854
|
+
sig_on()
|
855
|
+
self.gptr = new gen(_wrap_pylist(<tuple>s),<short int>1)
|
856
|
+
sig_off()
|
857
|
+
|
858
|
+
# Other types are converted with strings.
|
859
|
+
else:
|
860
|
+
if isinstance(s, Expression):
|
861
|
+
# take account of conversions with key giac in the sage symbol dict
|
862
|
+
try:
|
863
|
+
s = s._giac_init_()
|
864
|
+
except AttributeError:
|
865
|
+
s = SRexpressiontoGiac(s)
|
866
|
+
elif isinstance(s, AnInfinity):
|
867
|
+
s = s._giac_init_()
|
868
|
+
if not isinstance(s, str):
|
869
|
+
s = s.__str__()
|
870
|
+
sig_on()
|
871
|
+
self.gptr = new gen(<string>encstring23(s),context_ptr)
|
872
|
+
sig_off()
|
873
|
+
|
874
|
+
def __dealloc__(self):
|
875
|
+
del self.gptr
|
876
|
+
|
877
|
+
def __repr__(self):
|
878
|
+
# fast evaluation of the complexity of the gen. (it's not the number of char )
|
879
|
+
sig_on()
|
880
|
+
t=GIAC_taille(self.gptr[0], 6000)
|
881
|
+
sig_off()
|
882
|
+
if t < 6000:
|
883
|
+
sig_on()
|
884
|
+
result = GIAC_print(self.gptr[0], context_ptr).c_str().decode()
|
885
|
+
sig_off()
|
886
|
+
return result
|
887
|
+
else:
|
888
|
+
sig_on()
|
889
|
+
result = str(self.type) + "\nResult is too big for Display. If you really want to see it use print"
|
890
|
+
sig_off()
|
891
|
+
return result
|
892
|
+
|
893
|
+
def __str__(self):
|
894
|
+
#if self.gptr == NULL:
|
895
|
+
# return ''
|
896
|
+
sig_on()
|
897
|
+
result = GIAC_print(self.gptr[0], context_ptr).c_str().decode()
|
898
|
+
sig_off()
|
899
|
+
return result
|
900
|
+
|
901
|
+
def __len__(self):
|
902
|
+
"""
|
903
|
+
TESTS::
|
904
|
+
|
905
|
+
sage: from sage.libs.giac.giac import libgiac
|
906
|
+
sage: l=libgiac("seq[]");len(l) # 29552 comment28
|
907
|
+
0
|
908
|
+
"""
|
909
|
+
if (self._type == 7):
|
910
|
+
sig_on()
|
911
|
+
rep=(self.gptr.ref_VECTptr()).size()
|
912
|
+
sig_off()
|
913
|
+
return rep
|
914
|
+
else:
|
915
|
+
sig_on()
|
916
|
+
rep=GIAC_size(self.gptr[0],context_ptr).val
|
917
|
+
sig_off()
|
918
|
+
#GIAC_size return a gen. we take the int: val
|
919
|
+
return rep
|
920
|
+
|
921
|
+
def __getitem__(self, i): #TODO?: add gen support for indexes
|
922
|
+
"""
|
923
|
+
Lists of 10^6 integers should be translated to giac easily
|
924
|
+
|
925
|
+
TESTS::
|
926
|
+
|
927
|
+
sage: from sage.libs.giac.giac import libgiac
|
928
|
+
sage: l=libgiac(list(range(10^6)));l[5]
|
929
|
+
5
|
930
|
+
sage: l[35:50:7]
|
931
|
+
[35,42,49]
|
932
|
+
sage: l[-10^6]
|
933
|
+
0
|
934
|
+
sage: t=libgiac(tuple(range(10)))
|
935
|
+
sage: t[:4:-1]
|
936
|
+
9,8,7,6,5
|
937
|
+
sage: x=libgiac('x'); sum([ x[i] for i in range(5)])^3
|
938
|
+
(x[0]+x[1]+x[2]+x[3]+x[4])^3
|
939
|
+
sage: A=libgiac.ranm(5,10); A[3,7]-A[3][7]
|
940
|
+
0
|
941
|
+
sage: A.transpose()[8,2]-A[2][8]
|
942
|
+
0
|
943
|
+
|
944
|
+
Crash test::
|
945
|
+
|
946
|
+
sage: from sage.libs.giac.giac import Pygen
|
947
|
+
sage: l=Pygen()
|
948
|
+
sage: l[0]
|
949
|
+
Traceback (most recent call last):
|
950
|
+
...
|
951
|
+
IndexError: list index 0 out of range
|
952
|
+
"""
|
953
|
+
cdef gen result
|
954
|
+
|
955
|
+
if(self._type == 7) or (self._type == 12): #if self is a list or a string
|
956
|
+
if isinstance(i, (int, Integer)):
|
957
|
+
n=len(self)
|
958
|
+
if(i<n)and(-i<=n):
|
959
|
+
if(i<0):
|
960
|
+
i=i+n
|
961
|
+
sig_on()
|
962
|
+
result = self.gptr[0][<int>i]
|
963
|
+
sig_off()
|
964
|
+
return _wrap_gen(result)
|
965
|
+
else:
|
966
|
+
raise IndexError('list index %s out of range' % i)
|
967
|
+
else:
|
968
|
+
if isinstance(i, slice):
|
969
|
+
sig_on()
|
970
|
+
result = gen(_getgiacslice(self,i),<short int>self._subtype)
|
971
|
+
sig_off()
|
972
|
+
return _wrap_gen(result)
|
973
|
+
# add support for multi indexes
|
974
|
+
elif isinstance(i, tuple):
|
975
|
+
if(len(i)==2):
|
976
|
+
return self[i[0]][i[1]]
|
977
|
+
elif(len(i)==1):
|
978
|
+
# in case of a tuple like this: (3,)
|
979
|
+
return self[i[0]]
|
980
|
+
else:
|
981
|
+
return self[i[0],i[1]][tuple(i[2:])]
|
982
|
+
else:
|
983
|
+
raise TypeError('gen indexes are not yet implemented')
|
984
|
+
# Here we add support to formal variable indexes:
|
985
|
+
else:
|
986
|
+
cmd = '%s[%s]' % (self, i)
|
987
|
+
ans = Pygen(cmd).eval()
|
988
|
+
# if the answer is a string, it must be an error message because self is not a list or a string
|
989
|
+
if (ans._type == 12):
|
990
|
+
raise TypeError("Error executing code in Giac\nCODE:\n\t%s\nGiac ERROR:\n\t%s" % (cmd, ans))
|
991
|
+
return ans
|
992
|
+
|
993
|
+
def __setitem__(self, key, value):
|
994
|
+
"""
|
995
|
+
Set the value of a coefficient of a giac vector or matrix or list.
|
996
|
+
|
997
|
+
Warning: It is an in place affectation.
|
998
|
+
|
999
|
+
TESTS::
|
1000
|
+
|
1001
|
+
sage: from sage.libs.giac.giac import libgiac
|
1002
|
+
sage: A = libgiac([ [ j+2*i for i in range(3)] for j in range(3)]); A
|
1003
|
+
[[0,2,4],[1,3,5],[2,4,6]]
|
1004
|
+
sage: A[1,2]=44;A
|
1005
|
+
[[0,2,4],[1,3,44],[2,4,6]]
|
1006
|
+
sage: A[2][2]=1/3;A
|
1007
|
+
[[0,2,4],[1,3,44],[2,4,1/3]]
|
1008
|
+
sage: x=libgiac('x')
|
1009
|
+
sage: A[0,0]=x+1/x; A
|
1010
|
+
[[x+1/x,2,4],[1,3,44],[2,4,1/3]]
|
1011
|
+
sage: A[0]=[-1,-2,-3]; A
|
1012
|
+
[[-1,-2,-3],[1,3,44],[2,4,1/3]]
|
1013
|
+
sage: B=A; A[2,2]
|
1014
|
+
1/3
|
1015
|
+
sage: B[2,2]=6 # in place affectation
|
1016
|
+
sage: A[2,2] # so A is also modified
|
1017
|
+
6
|
1018
|
+
sage: A.pcar(x)
|
1019
|
+
x^3-8*x^2-159*x
|
1020
|
+
|
1021
|
+
NB: For Large matrix it seems that the syntax ``A[i][j]=`` is faster that ``A[i,j]=``::
|
1022
|
+
|
1023
|
+
sage: from sage.libs.giac.giac import libgiac
|
1024
|
+
sage: from time import time
|
1025
|
+
sage: A=libgiac.ranm(4000,4000)
|
1026
|
+
sage: t1=time(); A[500][500]=12345;t1=time()-t1
|
1027
|
+
sage: t2=time(); A[501,501]=54321;t2=time()-t2
|
1028
|
+
sage: t1,t2 # doctest: +SKIP
|
1029
|
+
(0.0002014636993408203, 0.05124521255493164)
|
1030
|
+
sage: A[500,500],A[501][501]
|
1031
|
+
(12345, 54321)
|
1032
|
+
"""
|
1033
|
+
cdef gen v
|
1034
|
+
sig_on()
|
1035
|
+
cdef gen g = gen(<string>encstring23('GIACPY_TMP_NAME050268070969290100291003'),context_ptr)
|
1036
|
+
GIAC_sto((<Pygen>self).gptr[0],g,1,context_ptr)
|
1037
|
+
g = gen(<string>encstring23('GIACPY_TMP_NAME050268070969290100291003[%s]' % str(key)), context_ptr)
|
1038
|
+
v=(<Pygen>(Pygen(value).eval())).gptr[0]
|
1039
|
+
GIAC_sto(v, g, 1, context_ptr)
|
1040
|
+
Pygen('purge(GIACPY_TMP_NAME050268070969290100291003):;').eval()
|
1041
|
+
sig_off()
|
1042
|
+
return
|
1043
|
+
|
1044
|
+
def __iter__(self):
|
1045
|
+
"""
|
1046
|
+
Pygen lists of 10^6 elements should be yield.
|
1047
|
+
|
1048
|
+
TESTS::
|
1049
|
+
|
1050
|
+
sage: from sage.libs.giac.giac import libgiac
|
1051
|
+
sage: l = libgiac(range(10^6))
|
1052
|
+
sage: [ i for i in l ] == list(range(10^6))
|
1053
|
+
True
|
1054
|
+
|
1055
|
+
Check for :issue:`18841`::
|
1056
|
+
|
1057
|
+
sage: L = libgiac(range(10))
|
1058
|
+
sage: next(iter(L))
|
1059
|
+
0
|
1060
|
+
"""
|
1061
|
+
cdef int i
|
1062
|
+
for i in range(len(self)):
|
1063
|
+
yield self[i]
|
1064
|
+
|
1065
|
+
def eval(self):
|
1066
|
+
cdef gen result
|
1067
|
+
sig_on()
|
1068
|
+
result = GIAC_protecteval(self.gptr[0],giacsettings.eval_level,context_ptr)
|
1069
|
+
sig_off()
|
1070
|
+
return _wrap_gen(result)
|
1071
|
+
|
1072
|
+
def __add__(self, right):
|
1073
|
+
cdef gen result
|
1074
|
+
if not isinstance(right, Pygen):
|
1075
|
+
right=Pygen(right)
|
1076
|
+
# Curiously this case is important:
|
1077
|
+
# otherwise: f=1/(2+sin(5*x)) crash
|
1078
|
+
if not isinstance(self, Pygen):
|
1079
|
+
self=Pygen(self)
|
1080
|
+
sig_on()
|
1081
|
+
result = (<Pygen>self).gptr[0] + (<Pygen>right).gptr[0]
|
1082
|
+
sig_off()
|
1083
|
+
return _wrap_gen(result)
|
1084
|
+
|
1085
|
+
def __call__(self, *args):
|
1086
|
+
cdef gen result
|
1087
|
+
cdef Pygen pari_unlock = Pygen('pari_unlock()')
|
1088
|
+
cdef gen pari_unlock_result
|
1089
|
+
cdef Pygen right
|
1090
|
+
n = len(args)
|
1091
|
+
if n > 1:
|
1092
|
+
# FIXME? improve with a vector, or improve Pygen(list)
|
1093
|
+
right = Pygen(args).eval()
|
1094
|
+
elif n == 1:
|
1095
|
+
right = Pygen(args[0])
|
1096
|
+
else:
|
1097
|
+
right = GIACNULL
|
1098
|
+
if not isinstance(self, Pygen):
|
1099
|
+
self = Pygen(self)
|
1100
|
+
# Some giac errors such as pari_locked are caught by the try
|
1101
|
+
# so we can't put the sig_on() in the try.
|
1102
|
+
# But now a keyboard interrupt fall back to this sig_on so
|
1103
|
+
# it may have left the giac pari locked.
|
1104
|
+
sig_on()
|
1105
|
+
try:
|
1106
|
+
result = self.gptr[0](right.gptr[0], context_ptr)
|
1107
|
+
except RuntimeError:
|
1108
|
+
# The previous computation might have failed due to a pari_lock
|
1109
|
+
# So we will not raise an exception yet.
|
1110
|
+
pari_unlock_result = GIAC_eval(pari_unlock.gptr[0], <int> 1, context_ptr)
|
1111
|
+
tmp = _wrap_gen(result)
|
1112
|
+
# if pari was not locked in giac, we have locked it, so unlock it.
|
1113
|
+
if tmp == 0:
|
1114
|
+
pari_unlock_result = GIAC_eval(pari_unlock.gptr[0], <int> 1, context_ptr)
|
1115
|
+
tmp = _wrap_gen(result)
|
1116
|
+
raise
|
1117
|
+
else:
|
1118
|
+
result = GIAC_eval(right.gptr[0], <int> 1, context_ptr)
|
1119
|
+
result = self.gptr[0](result, context_ptr)
|
1120
|
+
finally:
|
1121
|
+
sig_off()
|
1122
|
+
return _wrap_gen(result)
|
1123
|
+
|
1124
|
+
def __sub__(self, right):
|
1125
|
+
cdef gen result
|
1126
|
+
if not isinstance(right, Pygen):
|
1127
|
+
right=Pygen(right)
|
1128
|
+
if not isinstance(self, Pygen):
|
1129
|
+
self=Pygen(self)
|
1130
|
+
sig_on()
|
1131
|
+
result = (<Pygen>self).gptr[0] - (<Pygen>right).gptr[0]
|
1132
|
+
sig_off()
|
1133
|
+
return _wrap_gen(result)
|
1134
|
+
|
1135
|
+
def __mul__(self, right):
|
1136
|
+
"""
|
1137
|
+
TESTS::
|
1138
|
+
|
1139
|
+
sage: from sage.libs.giac.giac import libgiac
|
1140
|
+
sage: (sqrt(5)*libgiac('x')).factor() # BUG test could give 0
|
1141
|
+
sqrt(5)*x
|
1142
|
+
sage: (libgiac('x')*sqrt(5)).factor()
|
1143
|
+
sqrt(5)*x
|
1144
|
+
"""
|
1145
|
+
cdef gen result
|
1146
|
+
if not isinstance(right, Pygen):
|
1147
|
+
right = Pygen(right)
|
1148
|
+
if not isinstance(self, Pygen):
|
1149
|
+
self = Pygen(self)
|
1150
|
+
#result = (<Pygen>self).gptr[0] * (<Pygen>right).gptr[0]
|
1151
|
+
#NB: with the natural previous method, the following error generated by
|
1152
|
+
#giac causes python to quit instead of an error message.
|
1153
|
+
#l=Pygen([1,2]);l.transpose()*l;
|
1154
|
+
sig_on()
|
1155
|
+
result = GIAC_giacmul((<Pygen>self).gptr[0], (<Pygen>right).gptr[0],context_ptr)
|
1156
|
+
sig_off()
|
1157
|
+
return _wrap_gen(result)
|
1158
|
+
|
1159
|
+
# PB / in python3 is truediv
|
1160
|
+
def __div__(self, right):
|
1161
|
+
"""
|
1162
|
+
TESTS::
|
1163
|
+
|
1164
|
+
sage: from sage.libs.giac.giac import libgiac
|
1165
|
+
sage: (sqrt(3)/libgiac('x')).factor() # BUG test could give 0
|
1166
|
+
sqrt(3)/x
|
1167
|
+
sage: (libgiac('x')/sqrt(3)).factor()
|
1168
|
+
sqrt(3)*x/3
|
1169
|
+
"""
|
1170
|
+
cdef gen result
|
1171
|
+
if not isinstance(right, Pygen):
|
1172
|
+
right = Pygen(right)
|
1173
|
+
if not isinstance(self, Pygen):
|
1174
|
+
self = Pygen(self)
|
1175
|
+
sig_on()
|
1176
|
+
result = GIAC_giacdiv((<Pygen>self).gptr[0], (<Pygen>right).gptr[0],context_ptr)
|
1177
|
+
sig_off()
|
1178
|
+
return _wrap_gen(result)
|
1179
|
+
|
1180
|
+
def __truediv__(self, right):
|
1181
|
+
cdef gen result
|
1182
|
+
if not isinstance(right, Pygen):
|
1183
|
+
right = Pygen(right)
|
1184
|
+
if not isinstance(self, Pygen):
|
1185
|
+
self = Pygen(self)
|
1186
|
+
sig_on()
|
1187
|
+
result = (<Pygen>self).gptr[0] / (<Pygen>right).gptr[0]
|
1188
|
+
sig_off()
|
1189
|
+
return _wrap_gen(result)
|
1190
|
+
|
1191
|
+
def __pow__(self, right, ignored):
|
1192
|
+
cdef gen result
|
1193
|
+
if not isinstance(right, Pygen):
|
1194
|
+
right = Pygen(right)
|
1195
|
+
if not isinstance(self, Pygen):
|
1196
|
+
self = Pygen(self)
|
1197
|
+
sig_on()
|
1198
|
+
result = GIAC_pow((<Pygen>self).gptr[0], (<Pygen>right).gptr[0], context_ptr )
|
1199
|
+
sig_off()
|
1200
|
+
return _wrap_gen(result)
|
1201
|
+
|
1202
|
+
def __mod__(self, right):
|
1203
|
+
cdef gen result
|
1204
|
+
if not isinstance(right, Pygen):
|
1205
|
+
right = Pygen(right)
|
1206
|
+
if not isinstance(self, Pygen):
|
1207
|
+
self = Pygen(self)
|
1208
|
+
#result = gen(GIAC_makenewvecteur((<Pygen>self).gptr[0],(<Pygen>right).gptr[0]),<short int>1)
|
1209
|
+
#to have an integer output:
|
1210
|
+
#result = GIAC_smod(result,context_ptr)
|
1211
|
+
#we give a modular output:
|
1212
|
+
sig_on()
|
1213
|
+
result = GIAC_giacmod((<Pygen>self).gptr[0], (<Pygen>right).gptr[0],context_ptr)
|
1214
|
+
sig_off()
|
1215
|
+
return _wrap_gen(result)
|
1216
|
+
|
1217
|
+
def __neg__(self):
|
1218
|
+
cdef gen result
|
1219
|
+
if not isinstance(self, Pygen):
|
1220
|
+
self = Pygen(self)
|
1221
|
+
sig_on()
|
1222
|
+
result = GIAC_neg((<Pygen>self).gptr[0])
|
1223
|
+
sig_off()
|
1224
|
+
return _wrap_gen(result)
|
1225
|
+
|
1226
|
+
def __pos__(self):
|
1227
|
+
return self
|
1228
|
+
|
1229
|
+
# To be able to use the eval function before the GiacMethods initialisation
|
1230
|
+
def cas_setup(self, *args):
|
1231
|
+
return Pygen('cas_setup')(self, *args)
|
1232
|
+
|
1233
|
+
def savegen(self, str filename):
|
1234
|
+
"""
|
1235
|
+
Archive a Pygen element to a file in giac compressed format.
|
1236
|
+
|
1237
|
+
Use the loadgiacgen command to get back the Pygen from the file.
|
1238
|
+
In C++ these files can be opened with ``giac::unarchive``.
|
1239
|
+
|
1240
|
+
EXAMPLES::
|
1241
|
+
|
1242
|
+
sage: from sage.libs.giac.giac import *
|
1243
|
+
sage: f=libgiac('(x+y+z+2)**10'); g=f.normal()
|
1244
|
+
sage: g.savegen("fichiertest") # doctest: +SKIP
|
1245
|
+
sage: a=loadgiacgen("fichiertest") # doctest: +SKIP
|
1246
|
+
sage: from tempfile import NamedTemporaryFile
|
1247
|
+
sage: F=NamedTemporaryFile() # chose a temporary file for a test
|
1248
|
+
sage: g.savegen(F.name)
|
1249
|
+
sage: a=loadgiacgen(F.name)
|
1250
|
+
sage: a.factor()
|
1251
|
+
(x+y+z+2)^10
|
1252
|
+
sage: F.close()
|
1253
|
+
"""
|
1254
|
+
sig_on()
|
1255
|
+
GIAC_archive( <string>encstring23(filename), (<Pygen>self).gptr[0], context_ptr)
|
1256
|
+
sig_off()
|
1257
|
+
|
1258
|
+
# NB: with giac <= 1.2.3-57 redim doesn't have a non evaluated for so Pygen('redim') fails.
|
1259
|
+
# hence replacement for redim:
|
1260
|
+
|
1261
|
+
def redim(self, a, b=None):
|
1262
|
+
"""
|
1263
|
+
Increase the size of a matrix when possible, otherwise return ``self``.
|
1264
|
+
|
1265
|
+
EXAMPLES::
|
1266
|
+
|
1267
|
+
sage: from sage.libs.giac.giac import libgiac
|
1268
|
+
sage: C = libgiac([[1,2]])
|
1269
|
+
sage: C.redim(2,3)
|
1270
|
+
[[1,2,0],[0,0,0]]
|
1271
|
+
sage: C.redim(2,1)
|
1272
|
+
[[1,2]]
|
1273
|
+
"""
|
1274
|
+
d=self.dim()
|
1275
|
+
if d.type()==7:
|
1276
|
+
if(a>d[0] and b>=d[1]):
|
1277
|
+
A=self.semi_augment(Pygen((a-d[0],d[1])).matrix())
|
1278
|
+
if(b>d[1]):
|
1279
|
+
A=A.augment(Pygen((a,b-d[1])).matrix())
|
1280
|
+
return A
|
1281
|
+
elif(b>d[1] and a==d[0]):
|
1282
|
+
return self.augment(Pygen((d[0],b-d[1])).matrix())
|
1283
|
+
else:
|
1284
|
+
return self
|
1285
|
+
else:
|
1286
|
+
raise TypeError("self is not a giac List")
|
1287
|
+
|
1288
|
+
# def htmlhelp(self, str lang='en'):
|
1289
|
+
# """
|
1290
|
+
# Open the giac html detailed help about ``self`` in an external browser
|
1291
|
+
|
1292
|
+
# There are currently 3 supported languages: 'en', 'fr', 'el'
|
1293
|
+
|
1294
|
+
# """
|
1295
|
+
# l={'fr':1 , 'en':2, 'el':4}
|
1296
|
+
# if (not lang in ['en', 'fr', 'el']):
|
1297
|
+
# lang='en'
|
1298
|
+
# try:
|
1299
|
+
# url=browser_help(self.gptr[0],l[lang]).decode()
|
1300
|
+
# giacbasedir=GIAC_giac_aide_dir().decode()
|
1301
|
+
# except:
|
1302
|
+
# raise RuntimeError('giac docs dir not found')
|
1303
|
+
# print(url)
|
1304
|
+
# if os.access(giacbasedir,os.F_OK):
|
1305
|
+
# url='file:'+url
|
1306
|
+
# wwwbrowseropen(url)
|
1307
|
+
|
1308
|
+
def _help(self):
|
1309
|
+
return self.findhelp().__str__()
|
1310
|
+
|
1311
|
+
def _sage_doc_(self):
|
1312
|
+
return self._help()
|
1313
|
+
|
1314
|
+
def __doc__(self):
|
1315
|
+
return self._help()
|
1316
|
+
|
1317
|
+
# # # # # # # # # # # # # # # # #
|
1318
|
+
# sage addons
|
1319
|
+
# # # # # # # # # # # # # # # # #
|
1320
|
+
def _latex_(self):
|
1321
|
+
r"""
|
1322
|
+
You can output Giac expressions in latex.
|
1323
|
+
|
1324
|
+
EXAMPLES::
|
1325
|
+
|
1326
|
+
sage: from sage.libs.giac.giac import libgiac
|
1327
|
+
sage: M = matrix(QQ, [[1, 2], [3, 4]])
|
1328
|
+
sage: latex(M)
|
1329
|
+
\left(\begin{array}{rr}
|
1330
|
+
1 & 2 \\
|
1331
|
+
3 & 4
|
1332
|
+
\end{array}\right)
|
1333
|
+
sage: gM = libgiac(M)
|
1334
|
+
sage: latex(gM)
|
1335
|
+
\left...\begin{array}{cc}...1...&...2...\\...3...&...4...\end{array}\right...
|
1336
|
+
sage: gf = libgiac('(x^4 - y)/(y^2-3*x)')
|
1337
|
+
sage: latex(gf) # output changed slightly from 1.5.0-63 to 1.5.0-87
|
1338
|
+
\frac{...x^{4}...-...y...}{...y^{2}-3...x...}
|
1339
|
+
"""
|
1340
|
+
sig_on()
|
1341
|
+
result = GIAC_gen2tex(self.gptr[0], context_ptr).c_str().decode()
|
1342
|
+
sig_off()
|
1343
|
+
return result
|
1344
|
+
|
1345
|
+
def _integer_(self, Z=None):
|
1346
|
+
"""
|
1347
|
+
Convert giac integers or modular integers to sage Integers (via gmp).
|
1348
|
+
|
1349
|
+
EXAMPLES::
|
1350
|
+
|
1351
|
+
sage: from sage.libs.giac.giac import *
|
1352
|
+
sage: a=libgiac('10'); b=libgiac('2**300')
|
1353
|
+
sage: a;type(ZZ(a))
|
1354
|
+
10
|
1355
|
+
<class 'sage.rings.integer.Integer'>
|
1356
|
+
sage: next_prime(b)
|
1357
|
+
2037035976334486086268445688409378161051468393665936250636140449354381299763336706183397533
|
1358
|
+
sage: c=libgiac('2 % nextprime(2**40)')
|
1359
|
+
sage: ZZ(c^1000)
|
1360
|
+
-233775163595
|
1361
|
+
sage: Mod(2,next_prime(2^40))^1000 - ZZ(c^1000)
|
1362
|
+
0
|
1363
|
+
sage: 2^320-(c^320).sage()
|
1364
|
+
0
|
1365
|
+
"""
|
1366
|
+
cdef Integer n = PY_NEW(Integer)
|
1367
|
+
typ = self._type
|
1368
|
+
|
1369
|
+
if(typ == 0):
|
1370
|
+
# giac _INT_ i.e int
|
1371
|
+
return Integer(self._val)
|
1372
|
+
|
1373
|
+
elif(typ == 2):
|
1374
|
+
# giac _ZINT i.e mpz_t
|
1375
|
+
sig_on()
|
1376
|
+
mpz_set(n.value,(self.gptr.ref_ZINTptr())[0])
|
1377
|
+
sig_off()
|
1378
|
+
return n
|
1379
|
+
|
1380
|
+
elif(typ == 15):
|
1381
|
+
# self is a giac modulo
|
1382
|
+
sig_on()
|
1383
|
+
a = _wrap_gen( (self.gptr.ref_MODptr())[0])
|
1384
|
+
# It is useless to get the modulus here
|
1385
|
+
# because the result will be lift to ZZ.
|
1386
|
+
result = ZZ(a)
|
1387
|
+
sig_off()
|
1388
|
+
return result
|
1389
|
+
|
1390
|
+
else:
|
1391
|
+
raise TypeError("cannot convert non giac integers to Integer")
|
1392
|
+
|
1393
|
+
def _rational_(self, Z=None):
|
1394
|
+
"""
|
1395
|
+
Convert giac rationals to sage rationals.
|
1396
|
+
|
1397
|
+
EXAMPLES::
|
1398
|
+
|
1399
|
+
sage: from sage.libs.giac.giac import *
|
1400
|
+
sage: a = libgiac('103993/33102')
|
1401
|
+
sage: b = QQ(a); b
|
1402
|
+
103993/33102
|
1403
|
+
sage: b == a.sage()
|
1404
|
+
True
|
1405
|
+
"""
|
1406
|
+
typ = self._type
|
1407
|
+
# _INT_ or _ZINT
|
1408
|
+
if typ == 0 or typ == 2:
|
1409
|
+
return QQ(ZZ(self))
|
1410
|
+
# _FRAC_
|
1411
|
+
elif typ == 10:
|
1412
|
+
# giac _RAT_
|
1413
|
+
return ZZ(self.numer()) / ZZ(self.denom())
|
1414
|
+
else:
|
1415
|
+
raise TypeError("cannot convert non giac _FRAC_ to QQ")
|
1416
|
+
|
1417
|
+
def sage(self):
|
1418
|
+
r"""
|
1419
|
+
Convert a libgiac expression back to a Sage expression. (could be slow)
|
1420
|
+
|
1421
|
+
This currently does not implement a parser for the Giac output language,
|
1422
|
+
therefore only very simple expressions will convert successfully.
|
1423
|
+
|
1424
|
+
Lists are converted recursively to sage.
|
1425
|
+
|
1426
|
+
CURRENT STATUS:
|
1427
|
+
|
1428
|
+
ZZ, QQ, ZZ/nZZ, strings, are supported, other type are sent to the symbolic ring
|
1429
|
+
via strings. In particular symbolic expressions modulo n should be lift to ZZ
|
1430
|
+
before ( with % 0 ).
|
1431
|
+
|
1432
|
+
EXAMPLES::
|
1433
|
+
|
1434
|
+
sage: from sage.libs.giac.giac import libgiac
|
1435
|
+
sage: m = libgiac('x^2 + 5*y')
|
1436
|
+
sage: m.sage()
|
1437
|
+
x^2 + 5*y
|
1438
|
+
|
1439
|
+
::
|
1440
|
+
|
1441
|
+
sage: m = libgiac('sin(2*sqrt(1-x^2)) * (1 - cos(1/x))^2')
|
1442
|
+
sage: m.trigexpand().sage()
|
1443
|
+
2*cos(sqrt(-x^2 + 1))*cos(1/x)^2*sin(sqrt(-x^2 + 1)) - 4*cos(sqrt(-x^2 + 1))*cos(1/x)*sin(sqrt(-x^2 + 1)) + 2*cos(sqrt(-x^2 + 1))*sin(sqrt(-x^2 + 1))
|
1444
|
+
|
1445
|
+
::
|
1446
|
+
|
1447
|
+
sage: a=libgiac(' 2 % 7')
|
1448
|
+
sage: (a.sage())^6
|
1449
|
+
1
|
1450
|
+
sage: a=libgiac('"une chaine"')
|
1451
|
+
sage: b=a.sage(); b + b
|
1452
|
+
'une chaineune chaine'
|
1453
|
+
sage: isinstance(b,str)
|
1454
|
+
True
|
1455
|
+
|
1456
|
+
The giac entries in the pynac conversion dictionary are used::
|
1457
|
+
|
1458
|
+
sage: x=var('x')
|
1459
|
+
sage: f=libgiac.Gamma
|
1460
|
+
sage: f(4)
|
1461
|
+
6
|
1462
|
+
sage: f(x)
|
1463
|
+
Gamma(sageVARx)
|
1464
|
+
sage: (f(x)).sage()
|
1465
|
+
gamma(x)
|
1466
|
+
|
1467
|
+
Converting a custom name by adding a new entry to the ``symbols_table``::
|
1468
|
+
|
1469
|
+
sage: ex = libgiac('myFun(x)')
|
1470
|
+
sage: sage.symbolic.expression.register_symbol(sin, {'giac':'myFun'})
|
1471
|
+
sage: ex.sage()
|
1472
|
+
sin(x)
|
1473
|
+
"""
|
1474
|
+
typ = self._type
|
1475
|
+
|
1476
|
+
if typ != 7:
|
1477
|
+
# self is not a list
|
1478
|
+
if typ == 0 or typ == 2:
|
1479
|
+
return ZZ(self)
|
1480
|
+
|
1481
|
+
elif typ == 10:
|
1482
|
+
return QQ(self)
|
1483
|
+
|
1484
|
+
elif typ == 15:
|
1485
|
+
# modular integer
|
1486
|
+
sig_on()
|
1487
|
+
a = _wrap_gen( (self.gptr.ref_MODptr())[0])
|
1488
|
+
b = _wrap_gen( (self.gptr.ref_MODptr())[1])
|
1489
|
+
result = IntegerModRing(ZZ(b))(ZZ(a))
|
1490
|
+
sig_off()
|
1491
|
+
return result
|
1492
|
+
|
1493
|
+
elif typ == 12:
|
1494
|
+
# string
|
1495
|
+
sig_on()
|
1496
|
+
result = eval(self.__str__())
|
1497
|
+
sig_off()
|
1498
|
+
return result
|
1499
|
+
|
1500
|
+
else:
|
1501
|
+
from sage.symbolic.ring import SR
|
1502
|
+
return SR(self)
|
1503
|
+
|
1504
|
+
else:
|
1505
|
+
# self is a list
|
1506
|
+
sig_on()
|
1507
|
+
result = [entry.sage() for entry in self]
|
1508
|
+
sig_off()
|
1509
|
+
return result
|
1510
|
+
|
1511
|
+
def _symbolic_(self, R):
|
1512
|
+
r"""
|
1513
|
+
Convert ``self`` object to the ring R via a basic string evaluation. (slow)
|
1514
|
+
|
1515
|
+
EXAMPLES::
|
1516
|
+
|
1517
|
+
sage: from sage.libs.giac.giac import *
|
1518
|
+
sage: u,v=var('u,v');a=libgiac('cos(u+v)').texpand()
|
1519
|
+
sage: simplify(SR(a)+sin(u)*sin(v))
|
1520
|
+
cos(u)*cos(v)
|
1521
|
+
|
1522
|
+
TESTS:
|
1523
|
+
|
1524
|
+
Check that variables and constants are not mixed up (:issue:`30133`)::
|
1525
|
+
|
1526
|
+
sage: ee, ii, pp = SR.var('e,i,pi')
|
1527
|
+
sage: libgiac(ee * ii * pp).sage().variables()
|
1528
|
+
(e, i, pi)
|
1529
|
+
sage: libgiac(e * i * pi).sage().variables()
|
1530
|
+
()
|
1531
|
+
sage: libgiac.integrate(ee^x, x).sage()
|
1532
|
+
e^x/log(e)
|
1533
|
+
sage: y = SR.var('π')
|
1534
|
+
sage: libgiac.integrate(cos(y), y).sage()
|
1535
|
+
sin(π)
|
1536
|
+
"""
|
1537
|
+
if isinstance(R, SymbolicRing):
|
1538
|
+
from sage.calculus.calculus import symbolic_expression_from_string, SR_parser_giac
|
1539
|
+
from sage.symbolic.expression import symbol_table
|
1540
|
+
|
1541
|
+
# Try to convert some functions names to the symbolic ring
|
1542
|
+
lsymbols = symbol_table['giac'].copy()
|
1543
|
+
#lsymbols.update(locals)
|
1544
|
+
try:
|
1545
|
+
result = symbolic_expression_from_string(self.__str__(), lsymbols,
|
1546
|
+
accept_sequence=True,
|
1547
|
+
parser=SR_parser_giac)
|
1548
|
+
return result
|
1549
|
+
|
1550
|
+
except Exception:
|
1551
|
+
raise NotImplementedError("Unable to parse Giac output: %s" % self.__repr__())
|
1552
|
+
else:
|
1553
|
+
try:
|
1554
|
+
result = R(self.__str__())
|
1555
|
+
return result
|
1556
|
+
|
1557
|
+
except Exception:
|
1558
|
+
raise NotImplementedError("Unable to parse Giac output: %s" % self.__repr__())
|
1559
|
+
|
1560
|
+
def _matrix_(self, R=ZZ):
|
1561
|
+
r"""
|
1562
|
+
Return matrix over the (Sage) ring R where self
|
1563
|
+
should be a Giac matrix. The default ring is ZZ.
|
1564
|
+
|
1565
|
+
EXAMPLES::
|
1566
|
+
|
1567
|
+
sage: from sage.libs.giac.giac import *
|
1568
|
+
sage: R.<x,y>=QQ[]
|
1569
|
+
sage: M=libgiac('matrix(4,4,(k,l)->(x^k-y^l))'); M
|
1570
|
+
//...
|
1571
|
+
matrix[[0,1-y,1-y^2,1-y^3],[x-1,x-y,x-y^2,x-y^3],[x^2-1,x^2-y,x^2-y^2,x^2-y^3],[x^3-1,x^3-y,x^3-y^2,x^3-y^3]]
|
1572
|
+
sage: M.eigenvals() # random
|
1573
|
+
0,0,(x^3+x^2+x-y^3-y^2-y+sqrt(x^6+2*x^5+3*x^4-14*x^3*y^3+2*x^3*y^2+2*x^3*y+6*x^3+2*x^2*y^3-14*x^2*y^2+2*x^2*y+5*x^2+2*x*y^3+2*x*y^2-14*x*y+4*x+y^6+2*y^5+3*y^4+6*y^3+5*y^2+4*y-12))/2,(x^3+x^2+x-y^3-y^2-y-sqrt(x^6+2*x^5+3*x^4-14*x^3*y^3+2*x^3*y^2+2*x^3*y+6*x^3+2*x^2*y^3-14*x^2*y^2+2*x^2*y+5*x^2+2*x*y^3+2*x*y^2-14*x*y+4*x+y^6+2*y^5+3*y^4+6*y^3+5*y^2+4*y-12))/2
|
1574
|
+
sage: Z=matrix(R,M);Z
|
1575
|
+
[ 0 -y + 1 -y^2 + 1 -y^3 + 1]
|
1576
|
+
[ x - 1 x - y -y^2 + x -y^3 + x]
|
1577
|
+
[ x^2 - 1 x^2 - y x^2 - y^2 -y^3 + x^2]
|
1578
|
+
[ x^3 - 1 x^3 - y x^3 - y^2 x^3 - y^3]
|
1579
|
+
sage: parent(Z)
|
1580
|
+
Full MatrixSpace of 4 by 4 dense matrices over Multivariate Polynomial Ring in x, y over Rational Field
|
1581
|
+
"""
|
1582
|
+
cdef int c
|
1583
|
+
cdef int r
|
1584
|
+
v = self.dim()
|
1585
|
+
n = (v[0])._val
|
1586
|
+
m = (v[1])._val
|
1587
|
+
from sage.matrix.matrix_space import MatrixSpace
|
1588
|
+
M = MatrixSpace(R, n, m)
|
1589
|
+
sig_on()
|
1590
|
+
entries = [[R((self[r])[c]) for c in range(m)] for r in range(n)]
|
1591
|
+
sig_off()
|
1592
|
+
return M(entries)
|
1593
|
+
|
1594
|
+
def _vector_(self, R=None):
|
1595
|
+
r"""
|
1596
|
+
Return vector over the (Sage) ring R where self
|
1597
|
+
should be a Giac matrix. The default ring is ZZ.
|
1598
|
+
|
1599
|
+
EXAMPLES::
|
1600
|
+
|
1601
|
+
sage: from sage.libs.giac.giac import *
|
1602
|
+
sage: v=libgiac(range(10))
|
1603
|
+
sage: vector(v+v)
|
1604
|
+
(0, 2, 4, 6, 8, 10, 12, 14, 16, 18)
|
1605
|
+
sage: vector(v+v/3,QQ)
|
1606
|
+
(0, 4/3, 8/3, 4, 16/3, 20/3, 8, 28/3, 32/3, 12)
|
1607
|
+
"""
|
1608
|
+
if isinstance(R, None.__class__):
|
1609
|
+
R=ZZ
|
1610
|
+
|
1611
|
+
v = self.dim()
|
1612
|
+
try:
|
1613
|
+
n = v._val
|
1614
|
+
except AttributeError:
|
1615
|
+
raise TypeError("Entry is not a giac vector")
|
1616
|
+
from sage.modules.free_module_element import vector
|
1617
|
+
sig_on()
|
1618
|
+
entries = [R(self[c]) for c in range(n)]
|
1619
|
+
sig_off()
|
1620
|
+
return vector(R,entries)
|
1621
|
+
|
1622
|
+
# # # # # # # # # # # # # # #
|
1623
|
+
|
1624
|
+
def mplot(self):
|
1625
|
+
"""
|
1626
|
+
Basic export of some 2D plots to sage. Only generic plots are supported.
|
1627
|
+
lines, circles, ... are not implemented
|
1628
|
+
"""
|
1629
|
+
from sage.plot.line import line
|
1630
|
+
from sage.plot.scatter_plot import scatter_plot
|
1631
|
+
|
1632
|
+
xyscat = []
|
1633
|
+
xyplot = []
|
1634
|
+
plotdata = self
|
1635
|
+
if not plotdata.type() == 'DOM_LIST':
|
1636
|
+
plotdata = [plotdata]
|
1637
|
+
|
1638
|
+
sig_on()
|
1639
|
+
for G in plotdata:
|
1640
|
+
if G.dim() > 2: # it is not a pnt. Ex: scatterplot
|
1641
|
+
for g in G:
|
1642
|
+
xyscat=xyscat+[[(g.real())._double,(g.im())._double]]
|
1643
|
+
|
1644
|
+
else:
|
1645
|
+
if G[1].type()=='DOM_LIST':
|
1646
|
+
l=G[1].op()
|
1647
|
+
else:
|
1648
|
+
l=G[1][2].op()
|
1649
|
+
xyplot=[[(u.real())._double,(u.im())._double] for u in l]
|
1650
|
+
|
1651
|
+
if xyscat:
|
1652
|
+
result = scatter_plot(xyscat)
|
1653
|
+
|
1654
|
+
else:
|
1655
|
+
result = line(xyplot)
|
1656
|
+
sig_off()
|
1657
|
+
|
1658
|
+
return result
|
1659
|
+
|
1660
|
+
# # # # # # # # # # # # # # # # # # # # # # # # #
|
1661
|
+
# WARNING:
|
1662
|
+
#
|
1663
|
+
# Do not use things like != in Pygen's __cinit__
|
1664
|
+
# with this __richcmp__ enabled
|
1665
|
+
# The methods will bug: a=Pygen(2); a.sin()
|
1666
|
+
#
|
1667
|
+
# # # # # # # # # # # # # # # # # # # # # # # # #
|
1668
|
+
|
1669
|
+
def __richcmp__(self, other, op):
|
1670
|
+
if not isinstance(other, Pygen):
|
1671
|
+
other = Pygen(other)
|
1672
|
+
if not isinstance(self, Pygen):
|
1673
|
+
self = Pygen(self)
|
1674
|
+
sig_on()
|
1675
|
+
result = giacgenrichcmp((<Pygen>self).gptr[0],(<Pygen>other).gptr[0], op, context_ptr )
|
1676
|
+
sig_off()
|
1677
|
+
return result == 1
|
1678
|
+
|
1679
|
+
#
|
1680
|
+
# Some attributes of the gen class:
|
1681
|
+
#
|
1682
|
+
|
1683
|
+
property _type:
|
1684
|
+
def __get__(self):
|
1685
|
+
sig_on()
|
1686
|
+
result = self.gptr.type
|
1687
|
+
sig_off()
|
1688
|
+
return result
|
1689
|
+
|
1690
|
+
property _subtype:
|
1691
|
+
def __get__(self):
|
1692
|
+
sig_on()
|
1693
|
+
result = self.gptr.subtype
|
1694
|
+
sig_off()
|
1695
|
+
return result
|
1696
|
+
|
1697
|
+
property _val: # immediate int (type _INT_)
|
1698
|
+
"""
|
1699
|
+
immediate int value of an _INT_ type gen.
|
1700
|
+
"""
|
1701
|
+
def __get__(self):
|
1702
|
+
if self._type == 0:
|
1703
|
+
sig_on()
|
1704
|
+
result = self.gptr.val
|
1705
|
+
sig_off()
|
1706
|
+
return result
|
1707
|
+
else:
|
1708
|
+
raise TypeError("cannot convert non _INT_ giac gen")
|
1709
|
+
|
1710
|
+
property _double: # immediate double (type _DOUBLE_)
|
1711
|
+
"""
|
1712
|
+
immediate conversion to float for a gen of _DOUBLE_ type.
|
1713
|
+
"""
|
1714
|
+
def __get__(self):
|
1715
|
+
if self._type == 1:
|
1716
|
+
sig_on()
|
1717
|
+
result = self.gptr._DOUBLE_val
|
1718
|
+
sig_off()
|
1719
|
+
return result
|
1720
|
+
else:
|
1721
|
+
raise TypeError("cannot convert non _DOUBLE_ giac gen")
|
1722
|
+
|
1723
|
+
property help:
|
1724
|
+
def __get__(self):
|
1725
|
+
return self._help()
|
1726
|
+
|
1727
|
+
###################################################
|
1728
|
+
# Add the others methods
|
1729
|
+
###################################################
|
1730
|
+
#
|
1731
|
+
# NB: with __getattr__ this is about 10 times slower: [a.normal() for i in range(10**4)]
|
1732
|
+
# than [GiacMethods["normal"](a) for i in range(10**4)]
|
1733
|
+
#
|
1734
|
+
# def __getattr__(self, name):
|
1735
|
+
# return GiacMethods[str(name)](self)
|
1736
|
+
|
1737
|
+
# test
|
1738
|
+
|
1739
|
+
def giacAiry_Ai(self, *args):
|
1740
|
+
cdef gen result = GIAC_Airy_Ai(self.gptr[0], context_ptr)
|
1741
|
+
return _wrap_gen(result)
|
1742
|
+
|
1743
|
+
def giacifactor(self, *args):
|
1744
|
+
cdef gen result
|
1745
|
+
sig_on()
|
1746
|
+
result = GIAC_eval(self.gptr[0], <int>1, context_ptr)
|
1747
|
+
result = GIAC_ifactor(result, context_ptr)
|
1748
|
+
sig_off()
|
1749
|
+
return _wrap_gen(result)
|
1750
|
+
|
1751
|
+
|
1752
|
+
################################################################
|
1753
|
+
# A wrapper from a cpp element of type giac gen to create #
|
1754
|
+
# the Python object #
|
1755
|
+
################################################################
|
1756
|
+
cdef inline _wrap_gen(gen g)except +:
|
1757
|
+
|
1758
|
+
# cdef Pygen pyg=Pygen('NULL')
|
1759
|
+
# It is much faster with ''
|
1760
|
+
# [x-x for i in range(10**4)]
|
1761
|
+
# ('clock: ', 0.010000000000000009,
|
1762
|
+
# than with 'NULL':
|
1763
|
+
# [x-x for i in range(10**4)]
|
1764
|
+
# ('clock: ', 1.1999999999999997,
|
1765
|
+
# # # # # #
|
1766
|
+
# This is faster than with:
|
1767
|
+
# cdef Pygen pyg=Pygen('')
|
1768
|
+
# ll=giac(range(10**6))
|
1769
|
+
# ('clock: ', 0.40000000000000036, ' time: ', 0.40346789360046387)
|
1770
|
+
# gg=[1 for i in ll]
|
1771
|
+
# ('clock: ', 0.669999999999999, ' time: ', 0.650738000869751)
|
1772
|
+
#
|
1773
|
+
# But beware when changing the None case in Pygen init.
|
1774
|
+
#
|
1775
|
+
sig_on()
|
1776
|
+
cdef Pygen pyg=Pygen()
|
1777
|
+
del pyg.gptr # Pygen.__cinit__() always creates a gen. So we have to delete it here.
|
1778
|
+
pyg.gptr=new gen(g)
|
1779
|
+
sig_off()
|
1780
|
+
return pyg
|
1781
|
+
# if(pyg.gptr !=NULL):
|
1782
|
+
# return pyg
|
1783
|
+
# else:
|
1784
|
+
# raise MemoryError("empty gen")
|
1785
|
+
|
1786
|
+
################################################################
|
1787
|
+
# A wrapper from a python list to a vector of gen #
|
1788
|
+
################################################################
|
1789
|
+
|
1790
|
+
cdef vecteur _wrap_pylist(L) except +:
|
1791
|
+
cdef vecteur * V
|
1792
|
+
cdef int i
|
1793
|
+
|
1794
|
+
if isinstance(L, (tuple, list, range)):
|
1795
|
+
n = len(L)
|
1796
|
+
V = new vecteur()
|
1797
|
+
|
1798
|
+
sig_on()
|
1799
|
+
for i in range(n):
|
1800
|
+
V.push_back((<Pygen>Pygen(L[i])).gptr[0])
|
1801
|
+
sig_off()
|
1802
|
+
return V[0]
|
1803
|
+
else:
|
1804
|
+
raise TypeError("argument must be a tuple or a list")
|
1805
|
+
|
1806
|
+
|
1807
|
+
#################################
|
1808
|
+
# slice wrapper for a giac list
|
1809
|
+
#################################
|
1810
|
+
cdef vecteur _getgiacslice(Pygen L, slice sl) except +:
|
1811
|
+
cdef vecteur * V
|
1812
|
+
cdef int u
|
1813
|
+
|
1814
|
+
if L.type()=="DOM_LIST":
|
1815
|
+
n=len(L)
|
1816
|
+
V=new vecteur()
|
1817
|
+
|
1818
|
+
sig_on()
|
1819
|
+
# for u in range(n)[sl]: #pb python3
|
1820
|
+
b, e, st = sl.indices(n)
|
1821
|
+
for u in range(b, e, st):
|
1822
|
+
V.push_back((L.gptr[0])[u])
|
1823
|
+
sig_off()
|
1824
|
+
return V[0]
|
1825
|
+
else:
|
1826
|
+
raise TypeError("argument must be a Pygen list and a slice")
|
1827
|
+
|
1828
|
+
|
1829
|
+
cdef gen pylongtogen(a) except +:
|
1830
|
+
# #
|
1831
|
+
# basic conversion of Python long integers to gen via Horner's Method #
|
1832
|
+
# #
|
1833
|
+
|
1834
|
+
aneg=False
|
1835
|
+
cdef gen g=gen(<int>0)
|
1836
|
+
cdef gen M
|
1837
|
+
|
1838
|
+
if (a<0):
|
1839
|
+
aneg=True
|
1840
|
+
a=-a
|
1841
|
+
if Pyversioninfo >= (2,7):
|
1842
|
+
size=a.bit_length() # bit_length python >= 2.7 required.
|
1843
|
+
shift=Pymaxint.bit_length()-1
|
1844
|
+
else:
|
1845
|
+
size=math.trunc(math.log(a,2))+1
|
1846
|
+
shift=math.trunc(math.log(Pymaxint))
|
1847
|
+
M=gen(<long long>(1<<shift))
|
1848
|
+
|
1849
|
+
while (size>=shift):
|
1850
|
+
size=size-shift
|
1851
|
+
i=int(a>>size)
|
1852
|
+
g=(g*M+gen(<long long>i))
|
1853
|
+
a=a-(i<<size)
|
1854
|
+
|
1855
|
+
g=g*gen(<long long>(1<<size))+gen(<long long> a)
|
1856
|
+
if aneg:
|
1857
|
+
# when cythonizing with cython 0.24:
|
1858
|
+
# g=-g gives an Invalid operand type for '-' (gen)
|
1859
|
+
g=GIAC_neg(g)
|
1860
|
+
return g
|
1861
|
+
|
1862
|
+
|
1863
|
+
#############################################################
|
1864
|
+
# Examples of python functions directly implemented from giac
|
1865
|
+
#############################################################
|
1866
|
+
#def giaceval(Pygen self):
|
1867
|
+
# cdef gen result
|
1868
|
+
# try:
|
1869
|
+
# result = GIAC_protecteval(self.gptr[0],1,context_ptr)
|
1870
|
+
# return _wrap_gen(result)
|
1871
|
+
# except:
|
1872
|
+
# raise
|
1873
|
+
#
|
1874
|
+
#
|
1875
|
+
#def giacfactor(Pygen self):
|
1876
|
+
#
|
1877
|
+
# cdef gen result
|
1878
|
+
# try:
|
1879
|
+
# result = GIAC_factor(self.gptr[0],context_ptr)
|
1880
|
+
# return _wrap_gen(result)
|
1881
|
+
# except:
|
1882
|
+
# raise
|
1883
|
+
#
|
1884
|
+
#
|
1885
|
+
#
|
1886
|
+
#def giacfactors(Pygen self):
|
1887
|
+
# cdef gen result
|
1888
|
+
# try:
|
1889
|
+
# result = GIAC_factors(self.gptr[0],context_ptr)
|
1890
|
+
# return _wrap_gen(result)
|
1891
|
+
# except:
|
1892
|
+
# raise
|
1893
|
+
#
|
1894
|
+
#
|
1895
|
+
#
|
1896
|
+
#
|
1897
|
+
#def giacnormal(Pygen self):
|
1898
|
+
# cdef gen result
|
1899
|
+
# try:
|
1900
|
+
# result = GIAC_normal(self.gptr[0],context_ptr)
|
1901
|
+
# return _wrap_gen(result)
|
1902
|
+
# except:
|
1903
|
+
# raise
|
1904
|
+
#
|
1905
|
+
#
|
1906
|
+
#def giacgcd(Pygen a, Pygen b):
|
1907
|
+
# cdef gen result
|
1908
|
+
# try:
|
1909
|
+
# result = gen( GIAC_makenewvecteur(a.gptr[0],b.gptr[0]) ,<short int>1)
|
1910
|
+
# result = GIAC_gcd(result,context_ptr)
|
1911
|
+
# return _wrap_gen(result)
|
1912
|
+
# except:
|
1913
|
+
# raise
|
1914
|
+
|
1915
|
+
|
1916
|
+
#############################################################
|
1917
|
+
# Most giac keywords
|
1918
|
+
#############################################################
|
1919
|
+
include 'keywords.pxi'
|
1920
|
+
GiacMethods={}
|
1921
|
+
|
1922
|
+
|
1923
|
+
class GiacFunction(Pygen):
|
1924
|
+
# a class to evaluate args before call
|
1925
|
+
"""
|
1926
|
+
A Subclass of Pygen to create functions with evaluating all the args
|
1927
|
+
before call so that they are substituted by their value.
|
1928
|
+
|
1929
|
+
EXAMPLES::
|
1930
|
+
|
1931
|
+
sage: from sage.libs.giac.giac import *
|
1932
|
+
sage: libgiac.simplify(exp(I*pi)) # simplify is a GiacFunction
|
1933
|
+
-1
|
1934
|
+
sage: libgiac('a:=1')
|
1935
|
+
1
|
1936
|
+
sage: libgiac.purge('a') # purge is not a GiacFunction
|
1937
|
+
1
|
1938
|
+
sage: libgiac('a')
|
1939
|
+
a
|
1940
|
+
"""
|
1941
|
+
def __call__(self, *args):
|
1942
|
+
n = len(args)
|
1943
|
+
if n == 1:
|
1944
|
+
args = (Pygen(args[0]).eval(),)
|
1945
|
+
return Pygen.__call__(self, *args)
|
1946
|
+
|
1947
|
+
|
1948
|
+
class GiacFunctionNoEV(Pygen):
|
1949
|
+
# a class to allow to write the __doc__ attribute.
|
1950
|
+
"""
|
1951
|
+
A Subclass of Pygen to create functions
|
1952
|
+
|
1953
|
+
EXAMPLES::
|
1954
|
+
|
1955
|
+
sage: from sage.libs.giac.giac import *
|
1956
|
+
sage: libgiac('a:=1')
|
1957
|
+
1
|
1958
|
+
sage: libgiac.purge('a') # purge is a GiacFunctionNoEV
|
1959
|
+
1
|
1960
|
+
sage: libgiac('a')
|
1961
|
+
a
|
1962
|
+
"""
|
1963
|
+
|
1964
|
+
|
1965
|
+
#############################################################
|
1966
|
+
# Some convenient settings
|
1967
|
+
############################################################
|
1968
|
+
Pygen('printpow(1)').eval() # default power is ^
|
1969
|
+
# FIXME: print I for sqrt(-1) instead of i
|
1970
|
+
# GIAC_try_parse_i(False,context_ptr); (does not work??)
|
1971
|
+
|
1972
|
+
NoEvArgsFunc=['purge','assume','quote']
|
1973
|
+
|
1974
|
+
for i in mostkeywords:
|
1975
|
+
if i in NoEvArgsFunc:
|
1976
|
+
# do not eval args before calling this function. Ex purge
|
1977
|
+
#tmp=Pygen(i)
|
1978
|
+
tmp = GiacFunctionNoEV(i)
|
1979
|
+
else:
|
1980
|
+
tmp = GiacFunction(i)
|
1981
|
+
# in the sage version we remove: globals()[i]=tmp
|
1982
|
+
GiacMethods[i] = tmp
|
1983
|
+
|
1984
|
+
# We put the giac names that should not be exported to Python in moremethods.
|
1985
|
+
for i in moremethods:
|
1986
|
+
tmp = GiacFunction(i)
|
1987
|
+
GiacMethods[i] = tmp
|
1988
|
+
|
1989
|
+
for i in mostkeywords+moremethods:
|
1990
|
+
GiacMethods[i].__doc__ = eval("Pygen." + i + ".__doc__")
|
1991
|
+
|
1992
|
+
# To avoid conflicts we export only these few ones. Most giac keywords will be
|
1993
|
+
# available through: libgiac.keywordname
|
1994
|
+
__all__ = ['Pygen', 'giacsettings', 'libgiac', 'loadgiacgen', 'GiacFunction',
|
1995
|
+
'GiacMethods', 'GiacMethods_base']
|
1996
|
+
|
1997
|
+
|
1998
|
+
def loadgiacgen(str filename):
|
1999
|
+
"""
|
2000
|
+
Open a file in giac compressed format to create a Pygen element.
|
2001
|
+
|
2002
|
+
Use the save method from Pygen elements to create such files.
|
2003
|
+
|
2004
|
+
In C++ these files can be opened with giac::unarchive and created with
|
2005
|
+
``giac::archive``.
|
2006
|
+
|
2007
|
+
EXAMPLES::
|
2008
|
+
|
2009
|
+
sage: from sage.libs.giac.giac import *
|
2010
|
+
sage: g=libgiac.texpand('cos(10*a+5*b)')
|
2011
|
+
sage: g.save("fichiertest") # doctest: +SKIP
|
2012
|
+
sage: a=loadgiacgen("fichiertest") # doctest: +SKIP
|
2013
|
+
sage: from tempfile import NamedTemporaryFile
|
2014
|
+
sage: F=NamedTemporaryFile() # chose a temporary file for a test
|
2015
|
+
sage: g.savegen(F.name)
|
2016
|
+
sage: a=loadgiacgen(F.name)
|
2017
|
+
sage: a.tcollect()
|
2018
|
+
cos(10*a+5*b)
|
2019
|
+
sage: F.close()
|
2020
|
+
"""
|
2021
|
+
cdef gen result
|
2022
|
+
sig_on()
|
2023
|
+
result = GIAC_unarchive( <string>encstring23(filename), context_ptr)
|
2024
|
+
sig_off()
|
2025
|
+
return _wrap_gen(result)
|
2026
|
+
|
2027
|
+
|
2028
|
+
class GiacInstance:
|
2029
|
+
"""
|
2030
|
+
This class is used to create the giac interpreter object.
|
2031
|
+
|
2032
|
+
EXAMPLES::
|
2033
|
+
|
2034
|
+
sage: from sage.libs.giac.giac import libgiac
|
2035
|
+
sage: isinstance(libgiac,sage.libs.giac.giac.GiacInstance)
|
2036
|
+
True
|
2037
|
+
sage: libgiac.solve('2*exp(x)<(exp(x*2)-1),x')
|
2038
|
+
list[x>(ln(sqrt(2)+1))]
|
2039
|
+
sage: libgiac.solve? # doctest: +SKIP
|
2040
|
+
...
|
2041
|
+
Docstring:
|
2042
|
+
From Giac's documentation:
|
2043
|
+
Help for solve: solve(Expr,[Var]) Solves a (or a set of) polynomial
|
2044
|
+
...
|
2045
|
+
"""
|
2046
|
+
|
2047
|
+
def __init__(self):
|
2048
|
+
self.__dict__.update(GiacMethods)
|
2049
|
+
|
2050
|
+
def __call__(self, s):
|
2051
|
+
return _giac(s)
|
2052
|
+
|
2053
|
+
def _sage_doc_(self):
|
2054
|
+
return _giac.__doc__
|
2055
|
+
|
2056
|
+
def eval(self, code, strip=True, **kwds):
|
2057
|
+
|
2058
|
+
if strip:
|
2059
|
+
code = code.replace("\n","").strip()
|
2060
|
+
return self(code)
|
2061
|
+
|
2062
|
+
__doc__ = _giac.__doc__
|
2063
|
+
|
2064
|
+
|
2065
|
+
libgiac = GiacInstance()
|
2066
|
+
|
2067
|
+
# Issue #23976 (bound threads with SAGE_NUM_THREADS)
|
2068
|
+
import os
|
2069
|
+
try:
|
2070
|
+
ncpus = int(os.environ['SAGE_NUM_THREADS'])
|
2071
|
+
except KeyError:
|
2072
|
+
ncpus = 1
|
2073
|
+
|
2074
|
+
giacsettings.threads = ncpus
|