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