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.
Files changed (34) hide show
  1. passagemath_giac-10.5.33.dist-info/METADATA +153 -0
  2. passagemath_giac-10.5.33.dist-info/RECORD +34 -0
  3. passagemath_giac-10.5.33.dist-info/WHEEL +5 -0
  4. passagemath_giac-10.5.33.dist-info/top_level.txt +2 -0
  5. passagemath_giac.libs/libcrypto-79ca7c2e.so.3 +0 -0
  6. passagemath_giac.libs/libcurl-16a78e59.so.4.8.0 +0 -0
  7. passagemath_giac.libs/libgcc_s-69c45f16.so.1 +0 -0
  8. passagemath_giac.libs/libgfortran-db0b6589.so.5.0.0 +0 -0
  9. passagemath_giac.libs/libgiac-6d0de4c7.so.0.0.0 +0 -0
  10. passagemath_giac.libs/libglpk-aec1f3c8.so.40.3.1 +0 -0
  11. passagemath_giac.libs/libgmp-8e78bd9b.so.10.5.0 +0 -0
  12. passagemath_giac.libs/libgsl-75bb3fcc.so.28.0.0 +0 -0
  13. passagemath_giac.libs/libgslcblas-e0debfeb.so.0.0.0 +0 -0
  14. passagemath_giac.libs/libintl-3f4788bb.so.8.4.0 +0 -0
  15. passagemath_giac.libs/libmpfi-8dd9bae1.so.0.0.0 +0 -0
  16. passagemath_giac.libs/libmpfr-5ff10580.so.6.2.1 +0 -0
  17. passagemath_giac.libs/libncursesw-13f4e49c.so.6.5 +0 -0
  18. passagemath_giac.libs/libopenblas_neoversen2p-r0-05b86cab.3.28.so +0 -0
  19. passagemath_giac.libs/libpari-gmp-tls-e657f88e.so.2.15.5 +0 -0
  20. passagemath_giac.libs/libreadline-ae76ac25.so.8.2 +0 -0
  21. passagemath_giac.libs/libssl-7d993165.so.3 +0 -0
  22. passagemath_giac.libs/libstdc++-1f1a71be.so.6.0.33 +0 -0
  23. sage/all__sagemath_giac.py +10 -0
  24. sage/interfaces/all__sagemath_giac.py +1 -0
  25. sage/interfaces/giac.py +1264 -0
  26. sage/libs/all__sagemath_giac.py +7 -0
  27. sage/libs/giac/__init__.py +356 -0
  28. sage/libs/giac/auto-methods.pxi +16982 -0
  29. sage/libs/giac/giac.cpython-310-aarch64-linux-gnu.so +0 -0
  30. sage/libs/giac/giac.pxd +205 -0
  31. sage/libs/giac/giac.pyx +2074 -0
  32. sage/libs/giac/keywords.pxi +10 -0
  33. sage/libs/giac/misc.h +117 -0
  34. sage_wheels/bin/giac +0 -0
@@ -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