Giac es una librerÃ­a en C++ con tipos para manipulaciones algebraicas. Xcas es una GUI (Interface GrÃ¡fica) unida a Giac que permite las funcionalidades de un Sistema de Algebra Computerizada (CAS).

Instalando giac
***************

Instalando los binarios
=======================

Si quieres usar xcas/giac como cualquier otro CAS y tu Sistema Operativo es Intel x86 GNU/Linux o Intel StrongARM GNU/Linux o Windows 9x, entonces no te tienes que preocupar de la compilaciÃ³n. En vez de ello, puedes instalar binarios precompilados:

  * x86 GNU/Linux como usuario normal: ftp://fourier.ujf-grenoble.fr/pub/hp48/xcas_user.tgz

     Descomprime el archivo con tar xvfz xcas_user.tgz

     despuÃ©s cd xcas

     y ./xcas

  * x86 GNU/Linux si tienes acceso como root: ftp://fourier.ujf-grenoble.fr/pub/hp48/xcas_root.tgz Descomprime el archivo desde el directorio /

  * ARM GNU/Linux: ftp://fourier.ujf-grenoble.fr/pub/hp48/xcas_ipaq.tgz

  * Windows 9x: ftp://fourier.ujf-grenoble.fr/pub/hp48/xcas.zip

     Ejecuta xcas desde el directorio donde descomprimiste xcas.

Requerimientos
==============

Necesitas un compilador de C++ que entienda la norma C++ ANSI 3. Por ejemplo gcc versiÃ³n 2.95 o superior, funcionarÃ¡. AdemÃ¡s, debes comprobar que tienes instalada la librerÃ­a GMP GNU Math Precision. Si no estÃ¡ instalada, debes compilar e instalar la fuente: estÃ¡ disponible en cualquier mirror ftp de GNU, mira en http://www.gnu.org para mas detalles. Si estÃ¡s usando GNU/Linux, la librerÃ­a GMP es muy probable que estÃ© instalada, pero las cabeceras puede que no, busca un paquete llamado algo asÃ­ como gmp-devel.

Opciones
========

 1. Si quieres funciones numÃ©ricas deberÃ­as instalar la Gnu Scientific Library, disponible en http://sources.redhat.com/gsl

 2. Si quieres usar NTL para algunas operaciones polinÃ³micas (actualmente factorizaciÃ³n), consigue la versiÃ³n >= 5.2 en http://www.shoup.net. AdemÃ¡s comprueba que configuraste con permiso namespace(esto no estÃ¡ por defecto) y GMP permitido (no estÃ¡ por defecto, pero tampoco es obligatorio) Si no estÃ¡s seguro de tu instalaciÃ³n vete al directorio del NTL y teclea

           make clean
           ./configure NTL_GMP_LIP=on NTL_STD_CXX=on
           make
           make install

 3. Si quieres funciones aritmÃ©ticas avanzadas, consigue PARI en http://www.parigp-home.de. Si te planteas usar PARI SIN NTL entonces DEBES HACER LOS SIGUIENTES CAMBIOS en el directorio fuente de PARI:

       * Archivo src/basemath/polarit2.c: quita la palabra static de la declaraciÃ³n:

                 static GEN
                 combine_factors(...)

       * Archivo src/headers/paridecl.h: AÃ±ade la lÃ­nea

          GEN     combine_factors(GEN a, GEN famod, GEN p, long klim, long hint);

          en la secciÃ³n * polarit2.c

       * Recompila (make all) y reinstala PARI (make install) y comprueba que la librerÃ­a libpari.a ha sido actualizada o copiala explicitamente desde el directorio O<your_os>

       * Cambia en /usr/local/include/pari/pariinl.h labs por std::abs si no podrÃ­as tener errores con el compilador.

     Comprueba en el directorio src, el fichero pari.cc que la memoria reservada a la pila de PARI se ajusta a tus necesidades (por defecto son 10MB de RAM) o modifica: long pari_mem_size=10000000;

 4. Si quieres tener GUI (Interface GrÃ¡fica de Usuario), comprueba que tienes FLTK 1.0 (o FLNX) instalado (disponible en http://www.fltk.org). AdemÃ¡s puedes obtener modificaciones del FLTK 1.0.11 desde http://www-fourier.ujf-grenoble.fr/~parisse/fltkpar.tgz esto aÃ±ade auto-selecciÃ³n de parentesis. ATENCION: Actualmente xcas no funciona con FLTK 1.1. Para el editor de matrices / hoja de cÃ¡lculo, necesitarÃ¡s ademÃ¡s FLVW http://flvw.sourceforge.net/

 5. TeXmacs ofrece interface para giac. Puedes obtener TeXmacs en http://www.texmacs.org. DespuÃ©s de instalar giac, ejecuta texmacs y usa Insert->Session->giac.

Opciones de configuraciÃ³n
==========================

El script del shell ./configure  reconoce las siguientes opciones:

 1. --enable-debug Permite imprimir vectores y aÃ±ade codigo de depuraciÃ³n

 2. --enable-fltk Soporte para GUI

 3. --enable-gsl Usa la librerÃ­a Gnu Scientific Library para coma flotante (p.e. funciones especiales ..)

 4. --enable-sscl Permite la inclusiÃ³n de cÃ³digo para algoritmos semi-clÃ¡sicos (producto Moyal, ...) No disponible aÃºn

 5. --enable-ntl Permite la inclusiÃ³n de cÃ³digo NTL

 6. --enable-pari Permite la inclusiÃ³n de cÃ³digo PARI

Estas opciones pueden ser desactivadas usando --disable-option-name en lugar de --enable-option-name. Por defecto configure usarÃ¡ estas opciones si las librerÃ­as estÃ¡n disponibles en tu sistema.

Para binarios de gran velocidad, antes de ejecutar configure haz (con bash como shell)

$ export CXXFLAGS="-O3 -fexpensive-optimizations -malign-loops=2 -malign-jumps=2 -malign-functions=2"

o (con tcsh como shell)

$ setenv CXXFLAGS "-O3 -fexpensive-optimizations -malign-loops=2 -malign-jumps=2 -malign-functions=2"

CompilaciÃ³n
============

Como con cualquier software GNU autoconfigurable, puedes teclear:

 ./configure

[aÃ±ade opciones necesarias: prueba ./configure -help para obtener mas informaciÃ³n]

 make

 make check

[pasa a ser root si es necesario]

 make install

Trucos:

  * Si tienes permiso de escritura en /usr/local/, FLTK y GSL instalados y no quieres capacidad de depuraciÃ³n, puedes teclear

      ./inst

  * Si tienes FLTK y GSL instalados y quieres capacidad de depuraciÃ³n, teclea

      ./setup

     [hazte root]

      make install

  * Si no quieres optimizaciÃ³n, cambia la variable de entorno CXXFLAGS a -g antes de ejecutar configure, con tcsh setenv CXXFLAGS -g, con bash export CXXFLAGS=-g.

  * Si quieres construir xcas para el procesador ARM con la distribuciÃ³n de Linux Familiar (p.e. para un iPaq http://www.handhelds.org) asumiendo que tienes instalado skiff toolchain y FLTK. Comprueba que  config.h define HAVE_LIBFLTK y no define HAVE_LIBGSL y HAVE_LIBGSLCBLAS a menos que tengas estas librerÃ­as tambiÃ©n, entonces

      make -f Makefile.ipaq

     NÃ³tese que nunca he conseguido construirlo con optimizaciÃ³n para el iPaq.

  * Si quieres el cas sÃ³lo en lÃ­nea de comandos, ejecuta

      ./configure --disable-gui

      make

  * Windows

     Puedes compilar la versiÃ³n librerÃ­a de giac bajo Unix. O asumiendo que tengas las herramientas cygwin, gmp y FLTK instaladas (mira en http://sources.redhat.com/cygwin para cygwin, ejecuta cygwin, vete al directorio src y ejecuta

      make -f Makefile.win

     DespuÃ©s de esto, puedes ejecutar xcas.exe de forma independiente, /usr/bin/cygwin1.dll proporcionada ha sido copiada en el path (p.e. en el mismo directorio que xcas.exe)

Problemas
=========

  * Si compruebas giac despuÃ©s de la compilaciÃ³n con make check, por favor nota que la respuesta asume que PARI y NTL no estÃ¡n permitidos (enabled). Si no obtendrÃ¡s algunos errores porque la factorizaciÃ³n no devolverÃ¡ los factores en el mismo orden.

  * OptimizaciÃ³n requiere mucha memoria para compilar. Si estÃ¡s bajo de memoria edita src/Makefile y si es necesario cambia la lÃ­nea :

     CXXFLAGS = -g -O2 por :

     CXXFLAGS = -g

  * Ha sido imposible compilar FLTK con gcc 3. Instala  2.95 o 2.96 o reconfigura sin soporte FLTK o compila solo la versiÃ³n de lÃ­nea de comandos de giac

  * Si tienes un error como

     autoheader: Symbol 'CONSTANT_DEBUG_SUPPORT' is not covered by ...

     ejecuta

     autoheader --localdir=.

  * Si obtienes un error compilando modpoly.cc, es casi seguro porque compilaste sin NTL namespaces. RecompÃ­lalo (vease secciÃ³n)

  * Si obtienes un error de uniÃ³n sobre combine_factors no encontrados en modfactor.o serÃ¡ porque no modificaste PARI correctamente u olvidaste reinstalar las librerÃ­as de PARI (vease secciÃ³n)

  * La compilaciÃ³n con Cygwin de Giac con PARI 2.1.1 requiere que hagas algun trabajo manual. No he podido compilar la versiÃ³n dinÃ¡mica de la librerÃ­a PARI. Por lo tanto tuve que hacer la instalaciÃ³n a mano

          cp libpari.a /usr/local/lib
          mkdir /usr/local/include/pari
          cp src/headers/*.h /usr/local/include/pari
          cp Ocygwin/*.h /usr/local/include/pari

     Entonces obtuve un error compilando pari.cc que desapareciÃ³n comentando la lÃ­nea causante en la cabecera /usr/local/include/pari/paricom.h DespuÃ©s de esto todo fuÃ© correctamente.

Usando xcas, una interface de usuario con giac
**********************************************

xcas es una interface de usuario con giac que es similar a una calculadora. Una interface de lÃ­nea de comandos llamada cas tambiÃ©n estÃ¡ disponible.

La interface
============

Puedes usar, pero no lo necesitas, un teclado puesto que esta interface estÃ¡ diseÃ±ada para ser usada tambiÃ©n en PDA. Usa el botÃ³n verde cambio para obtener los botones del teclado.

La ventana estÃ¡ compuesta de izquierda a derecha y de arriba a abajo por:

 1. La barra principal de menÃºs

 2. El historial o ventana grÃ¡fica

 3. La barra de herramientas del historial y el menu de EdiciÃ³n/dibujo

 4. la lÃ­nea de comandos

 5. La barra de menÃºs por teclas (como en las calculadoras grÃ¡ficas HP4x)

 6. Ayuda en lÃ­nea

 7. Botones tipo calculadora a la derecha

La interface se asemeja a las avanzadas calculadoras grÃ¡ficas (TI89, TI92, HP49G en modo algebraico): escribes un comando en la lÃ­nea de comandos con la ayuda del teclado y/o los botones, ayuda en lÃ­nea y menÃºs. Entonces pulsando Enter se evaluarÃ¡ tu expresiÃ³n y devolverÃ¡ el resultado al Ã¡rea del historial. Si un comando devuelve un objeto grÃ¡fico la ventana historial serÃ¡ reemplazada por la ventana grÃ¡fica. Puedes cambiar de ventana historial a grÃ¡fica usando el botÃ³n Geo en la barra de menÃºs por teclas.

La ayuda en lÃ­nea da una breve descripciÃ³n de todos los comandos del CAS con ejemplos que pueden ser pegados en la lÃ­nea de comandos. EstÃ¡ disponible por defecto en xcas o con el comando aide desde shell.

Imprimir requiere una instalaciÃ³n operativa de LaTeX con pstricks.

Comandos del sistema de Ã¡lgebra computerizado
==============================================

Una lista de comandos del CAS.

Comandos matemÃ¡ticos bÃ¡sicos
------------------------------

AritmÃ©tica de enteros y polinÃ³mios
------------------------------------

Los comandos  gcdy lcm se aplican a ambos tipos de argumentos: devuelven el mÃ¡ximo comÃºn divisor o el mÃ­nimo comÃºn mÃºltiplo. Otros comandos aritmÃ©ticos deben comenzar con la letra i si quieres usarlos con enteros, si no los argumentos serÃ¡n considerados como polinÃ³mios constantes.

Fucniones artimÃ©ticas de enteros
.................................

DivisiÃ³n euclÃ­dea entera
..........................

Dados dos enteros  a y  b, la divisiÃ³n euclÃ­dea entera estÃ¡ definida por la igualdad :

     a=b*q+r

donde normalmente  r se coge entre  0 y b-1, o en la representaciÃ³n simÃ©trica , entre -b/2 y b/2. Las funciones  iquo(a,b) y  irem(a,b) devuelven respectivamente q y r, o iquorem(a,b) devueltas ambas como un vector. La funciÃ³n smod(a,b) devolverÃ¡ r usando el convenio de resto simÃ©trico.

Mcd de enteros
..............

la funciÃ³n gcd(a,b) devuelve el mÃ¡ximo comÃºn divisor (Mcd) d de dos enteros a y  b. Si necesitas dos enteros u y v tales que:

     a*u+b*v=d

puedes usar en su lugar egcd(a,b) , devolverÃ¡  [u,v,d].

El comando  ichinrem([a,n],[b,m]) donde n y m son primos devolverÃ¡ un vector [c,n*m] tal que c=a (mod n) y  c=b (mod m).

Primalidad y factorizaciÃ³n
...........................

La funciÃ³n is_prime(a) devolverÃ¡ 0 si a no es primo. DevolverÃ¡ 2 si a es seguro primo, y 1 si a es pseudo-primo. Si has compilado xcas con soporte PARI, obtendrÃ¡s un certificado de primo en su lugar (vÃ©ase documentaciÃ³n de PARI para mÃ¡s informaciÃ³n).

Los comandos  nextprime(a) y  prevprime(a) devolverÃ¡n el siguiente o anterior (pseudo-)primo, de un entero a dado.

La funciÃ³n ifactor(a) devuelve la factorizaciÃ³n de a. Es una buena idea compilar con soporte PARI si tienes planeado factorizar enteros relativamente grandes (con factores primos de mas de 20 dÃ­gitos).

Otras funciones enteras (Legendre, Jacobi, ...)
...............................................

Funciones de enteras adicionales provistas por  xcas son

  * jacobi(a,b) y  legendre(a,b), vÃ©ase la documentaciÃ³n de  GMP para mÃ¡s detalles.

  * pa2b2(p) devuelve  [a,b] tal que p=a*a+b*b si p=1 (mod 4) es primo.

Funciones aritmÃ©ticas de polinÃ³mios
.....................................

Los polinÃ³mios tienen dos representaciones: representaciÃ³n simbÃ³lica o por un vector de coeficientes. En la representaciÃ³n simbÃ³lica puedes aÃ±adir el nombre de la variable como parÃ¡metro adicional a las funciones que uses, si no la variable por defecto serÃ¡ la usada. Para la representaciÃ³n por vector, es recomendable usar el delimitador correcto poly1[ en lugar de [ con  lo que las operaciones habituales (suma,..) se comportarÃ¡n correctamente (no como si fuesen vectores o matrices).

 1. quo(a,b) rem(a,b) y quorem(a,b) devuelven respectivamente los polinÃ³mios q, r y  [q,r] tales que  a=b*q+r y degree(r)<degree(b)

 2. gcd(a,b) devuelve el mÃ¡ximo comÃºn divisor de dos polinÃ³mios

 3. egcd(a,b) es el algorÃ­tmo Mcd eclÃ­deo extendido, al igual que para enteros devuelve una lista de 3 polinÃ³momios  u,v,d tales que  au+bv=d.

 4. chinrem devuelve el resto chino para polinÃ³mios escritos como listas. Los 2 argumentos son dos listas hechas de polinÃ³mios mÃ³dulo otro polinomio (donde los polinÃ³mios mÃ³dulo son primos entre ellos). La respuesta es el polinÃ³mio mÃ³dulo producto de los polinÃ³mios mÃ³dulo que reduce a los originales polinÃ³mios mÃ³dulo los originales polinÃ³mios mÃ³dulo

 5. cyclotomic toma un entero n como argumento y devuelve el polinÃ³mio ciclotÃ³mico n-Ã©simo.

Algebra, calculo, ...
---------------------

Reescribiendo expresiones
.........................

El comando normal reescribe una fracciÃ³n racional como una relaciÃ³n entre dos polinÃ³mios coprimos. Si una expresiÃ³n no es racional, primero es racionalizada sustituyendo las expresiones transcendentales (p.e. sin(x) ) por un identificador temporal. Expresiones algebraicas (p.e. sqrt(x)) tambiÃ©n son  normalizadas.

El comando factor factoriza polinÃ³mios. Como antes, expresiones no polinÃ³micas son racionalizadas primero. Puedes elegir la variable bÃ¡sica respecto a la cual el polinÃ³mio serÃ¡ factorizado aÃ±adiendola como segundo argumento a  factor.

La funciÃ³n texpand es usada para expandir expresiones transcendentales como exp(x+y)=exp(x)*exp(y) o reglas similares para funciones  trigonomÃ©tricas. La funciÃ³n  tlin realiza la operaciÃ³n inversa para funciones trigonomÃ©tricas , tal y como la funciÃ³n lin lo hace para las exponenciales.

La funciÃ³n  halftan reescribe expresiones trigonomÃ©tricas en tÃ©rminos de la tangente del Ã¡ngulo mitad. La funciÃ³n  hyp2exp reescribe funciones hiperbÃ³licas en tÃ©rminos exponenciales.

DerivaciÃ³n, integraciÃ³n
.........................

La instrucciÃ³n para diferenciaciÃ³n es diff(expression,variable). La antiderivada indefinida se obtiene usando integrate(expression,variable). Si necesitas integraciÃ³n definida entre los lÃ­mites a y b, escoge integrate(expression,variable,a,b) para integraciÃ³n exacta o romberg(expression,variable,a,b) para integraciÃ³n numÃ©rica.

Un ejemplo de integraciÃ³n definida son los coeficientes de Fourier de funciones periÃ³dicas. Son obtenidos usando fourier_an y fourier_bn para coeficientes trigonomÃ©tricos o usando fourier_cn para coeficientes exponenciales complejos.

Algunas antiderivadas discretas pueden ser obtenidas usando sum(variable,expression) .

LÃ­mites, desarrollos en serie.
...............................

Para un lÃ­mite la sintÃ¡sis es limit(expression,variable,limitpoint[,direction]). Para un desarrollo en serie series(expression,variable,limitpoint,order[,direction]). La implementaciÃ³n en giac de limit y series estÃ¡ basada en el algorÃ­tmo mrv.

Resolviendo ecuaciones
----------------------

Usando solve(expression,variable) se busca la soluciÃ³n exacta de ecuaciones polinÃ³micas. Usa newton para soulciones numÃ©ricas (de un mayor rango de ecuaciones).

Algebra lineal
--------------

Las operacions aritmÃ©ticas sobre matrices y vectorse se hacen usando los operadores habituales. El producto escalar de 2 vectores se obtiene usando el operador  *.

La eliminaciÃ³n Gaussiana sobre una matriz  (Gauss-Bareiss) se desarrolla usando  rref(m). El nÃºcleo de una aplicaciÃ³n lineal de matriz m se obtiene con  ker(m). Un sistema de ecuaciones lineales (escrito simbÃ³licamente como un vector) puede ser resuelto con linsolve([equations],[variables]).

El determinante de una  matriz puede ser obtenido usando dos algorÃ­tmos, o bien  Gauss-Bareiss usando  det(m), o calculando los menores det_minor(m). Realmente, un Ãºltimo mÃ©todo estÃ¡ disponible usando el cÃ¡lculo de los coeficientes constantes del polinÃ³mio caracterÃ­stico usando el algorÃ­tmo Fadeev-Leverrier.

El polinÃ³mio caracterÃ­stico de una matriz puede ser calculado por el algorÃ­tmo de Fadeev-Leverrier usando  pcar(m). Para matrices con los coeficientes en un campo finito, pcar_hessenberg(m) es una mejor opciÃ³n  (complejidad O(n^3) donde n es el tamaÃ±o de la matriz).

Los valores propios y los vectores propios son calculados usando respectivamente egvl(m) y egv(m). La forma normal de Jordan se obtiene usando jordan(m).

La formas cuadrÃ¡ticas  (escritas simbÃ³licamente) pueden ser reducidas a sumas y diferencias de cuadrados usando  gauss(expression,[variables]).

Hay algÃºn soporte para isometrÃ­as: mkisom puede ser usado para hacer una isometrÃ­a  desde sus propios elementos y isom(m) devuelve los elementos propios de una isometrÃ­a.

GeometrÃ­a
==========

Como cualquier otro objeto, puedes crear objetos geomÃ©tricos usando la lÃ­nea de comandos. Adicionalmente, si la ventana grÃ¡fica estÃ¡ activa (clicka en el botÃ³n  Geo si es  necesario), puedes crear puntos y segmentos con el ratÃ³n (o el lÃ¡piz apuntador) o mover un objeto geomÃ©trico. Para crear un punto,simplemente clicka. Para crear una lÃ­nea, pulsa cualquier botÃ³n del ratÃ³n, mueve el ratÃ³n y suelta el botÃ³n en el segundo punto. Para mover un objeto, primero selecciÃ³nalo clickando cerca de Ã©l. La lÃ­nea de comandos deberÃ¡ mostrar el nombre del objeto. Puedes moverlo pulsando el ratÃ³n cerca del objeto y moviÃ©ndolo. Suelta el botÃ³n del ratÃ³n en la posiciÃ³n final. Puedes cancelar un movimiento soltando el ratÃ³n fuera de la ventana grÃ¡fica. Como en cualquier paquete de geometrÃ­a dinÃ¡mica. todos los objetos dependientes de un objeto, se moverÃ¡n cuando muevas dicho objeto.

Para imprimir el grÃ¡fico actual, puedes usar la instrucciÃ³n graph2tex() o bien, sin argumentos (entonces el cÃ³digo LaTeX serÃ¡ insertado en su lugar en el historial) o con una cadena de texto conteniendo el nombre del fichero donde se guardarÃ¡ una versiÃ³n aislada del grÃ¡fico, por ejemplo graph2tex("figure.tex") crearÃ¡ un fichero llamado figure.tex que podrÃ¡s compilar con latex figure.tex.

El lenguaje script de xcas
==========================

Xcas y el programa cas proveen un lenguaje interpretado similar a otros populares lenguajes de programaciÃ³n de CAS. Este lenguaje scrip estÃ¡ disponible en 3 formas: sintÃ¡xis similar a C (por defecto) o en modo compatibilidad para programas simples de Maple o Mupad. Describiremos sÃ³lo la sintÃ¡xis similar a C. Las instrucciones deben acabar con punto y coma ;. Los grupos de instrucciones pueden ser combinados usando llaves, como en C.

SelecciÃ³n del modo del lenguage
================================

El comando maple_mode(0) o maple_mode(1) o maple_mode(2) puede ser usado para cambiar la forma del lenguaje respectivamente entre modo similar-C a similar-Maple o similar-Mupad. NÃ³tese que este comando tiene efecto sÃ³lo cuando la sesiÃ³n actual del interprete finaliza lo que significa cuando el siguiente comando sea procesado en modo interactivo o al finalizar el fichero de proceso por lotes actual, por lo tanto no deberÃ­as comenzar un script con este comando. En modo de proceso por lotes puedes cambiar el modo activando la variable de entorno MAPLE_MODE, por ejemplo con tcsh: setenv MAPLE_MODE 1 o con bash export MAPLE_MODE=1 cambiarÃ¡ a lenguaje similar a Maple. O puedes ejecutar maplec o mupadc en vez de cas. Adicionalmente puedes introducir el comando maple_mode(1) en el .xcasrc de tu directorio raÃ­z para cambiar el comportamiento por defecto. O dentro de xcas puedes ejecutar el comando Import del menÃº File y seleccionar la forma. El comando Export puede ser usado para traducir el nivel actual del historial dentro de xcas a un fichero, o el comando View as del menÃº Edit para traducirlo a la ventana de salida de la ayuda.

Datos
=====

El lenguaje acepta variables locales y globales, variables no son tecleadas. Las variables globales no necesitan ser declaradas, las locales deben ser declaradas al principio de una funciÃ³n por la palabra clave local seguido de los nombres de las variables locales separados por comas , con punto y coma final ;

El signo de asiganciÃ³n es := como en CAS populares y distinto a C. Otras operaciones (p.e. {+ - * /}) y llamadas a funciones son hechos como en C o como en una sesiÃ³n interactiva. Como en C, para comprobar igualdad se usa ==. El signo de igual simple = se usa para devolver una ecuaciÃ³n (esta ecuaciÃ³n serÃ¡ comprobada como un test sÃ³lo en algunas situaciones donde una ecuaciÃ³n no es esperada). Las otras clÃ¡usulas de test son != para distinto, < <= > >= para comparaciones de valores relaes. Puedes combinar tests con  && o and, y || o or. La negaciÃ³n booleana es ! o not.

La palabra clave para bucles es como en C

for (inicializacion;mientras_condition;incremento){ bloque_bucle }

Puedes romper un bucle dentro de la iteraciÃ³n con break;. Puedes saltar immediatamente a la siguiente iteraciÃ³n con continue;.

Las palabras clave para condicionales son como en C

if (condicion) { bloque_si_cierto } [ else { bloque_si_falso } ]

Adicionalmente, la selecciÃ³n mÃºltiple es traducida como en C

swith (variable){ case (valor_1): ... break; default: ... ; }

Las funciones son declaradas e implementadas juntas de esta manera

nombre_funcion(parametros):={ definicion }

Los parÃ¡metros son como variables locales con una inicializaciÃ³n adicional de los valores de los parÃ¡metros dentro de la funciÃ³n.

El return(valor_retorno) debe ser usado pra devolver el valor de la funciÃ³n.

No es posible pasar argumentos por referencia, sÃ³lo por valor.

Una vez que una funciÃ³n es definida, un fichero llamado nombre_funcion.cas es generado en el directorio actual. Una buena idea es agrupar definiciones de funciones correspondientes con el mismo tema en un fichero llamado con una extensiÃ³n .cc (de esta manera la identaciÃ³n similar a C ocurre automÃ¡ticamente cuando editas el fichero con tu editor favorito) y "compila" este fichero con cas ccnombrefichero.cc o dentro de xcas con el comando Run file del menÃº Files.

Una vez que una funciÃ³n estÃ¡ definida, si modificas el correspondiente fichero .cas, no afectarÃ¡ a la definiciÃ³n de la funciÃ³n correspondiente durante la sesiÃ³n actual.

En este capÃ­tulo primero describiremos el tipo de dato genÃ©rico de giac, la clase gen. DespuÃ©s describiremos los tipos de datos mÃ¡s importantes que gen cubre (polinÃ³mios, vectores, objetos simbÃ³licos y funciones unarias de gen). En este punto, el lector deberÃ­a ser capaz de programar usando giac, por lo tanto describimos como integrar cÃ³digo a giac por inclusiÃ³n en la librerÃ­a o como una librerÃ­a ejecutable separada (llamada mÃ³dulo). el Ãºltimo punto describe como puedes aÃ±adir nuevos objetos matemÃ¡ticos, p.e. quaternas, dentro del tipo gen.

Giac usa el lenguaje C++ porque es mÃ¡s fÃ¡cil escribir operaciones algebraicas usando operadores habituales, por ejemplo a+b*x es mÃ¡s fÃ¡cil de entender y modificar que add(a,mul(b,x)), pero no es necesario que aprendas programaciÃ³n orientada a objetos. De hecho, es mÃ¡s una librerÃ­a de C usando caracterÃ­sticas de C++ que facilitan la programaciÃ³n easier (como las secuencias I/O y la librerÃ­a de plantillas estandard). De todos modos necesitarÃ¡s un compilador de C++ reciente, p.e. gcc versiÃ³n 2.95 o posterior.

La clase gen
************

gen es la clase usada para representar objetos matemÃ¡ticos (#include <giac/gen.h>). Es una uniÃ³n en C, hecha bien de obejtos ``directos'' como int o double o de punteros al montÃ³n de objetos afectados que estÃ¡n referenciados. La reserva de memoria la realiza la propia librerÃ­a (salvo tipos de objetos definidos por el usuario). Puedes comprobar el tipo actual de una variable de tipo gen, p.e. gen e;, usando su campo type (p.e. if (e.type==...)). Este campo type de un gen es un int.

El gen podrÃ­a ser~:

 1. un entero inmediato (e.type==_INT_)

 2. un real (double) (e.type==_REAL)

 3. un entero de precision arbitraria (e.type==_ZINT)

 4. un nÃºmero complejo (e.type==_CINT), un puntero a dos objetos de tipo gen la parte real y la parte imaginaria

 5. un nombre global (e.type==_IDNT), con un puntero a un tipo identificateur

 6. un objeto simbÃ³lico (e.type==_SYMB), con un puntero a tipo symbolic

 7. un objeto vector (de hecho es una lista) (e.type==_VECT), con un puntero a un tipo vecteur

 8. un objeto funciÃ³n (e.type==_FUNC), con un puntero a un tipo unary_function_ptr

Otros tipos estÃ¡n disponibles (p.e. un puntero a un objeto gen_user que puedes derivar para hacer tus propias clases, o nÃºmeros de coma flotante con precision arbitraria que serÃ¡n implementados mÃ¡s tarde), para una descripciÃ³n completa mira en giac/gen.h (si tienes instalado giac la ruta a los ficheros incluidos es /usr/local/include/giac a menos que invalide la que estÃ¡ por defecto, si no lo instalas, la ruta es la ruta al directorio src de la distribuciÃ³n del cÃ³digo fuente).

Si quieres acceder al tipo subyacente, despues de comprobar que el tipo es correcto, puedes hacer lo siguiente:

 1. para un entero inmediato: int i=e.val;

 2. para un real (double): double d=e._DOUBLE_val;

 3. para enteros de precisiÃ³n arbitraria: mpz_t * m=e._ZINTptr;

 4. para nÃºmeros complejos: gen realpart=*e._CINTptr;

 5. para identificadores: identificateur i=*e._IDNTptr;

 6. para simbÃ³licos: symbolic s=*e._SYMBptr;

 7. para compuestos: vecteur v=*e._VECTptr;

 8. para objetos funciÃ³n: unary_function_ptr u=*e._FUNCptr

AdemÃ¡s del type principal, cada gen tiene subtype (subtipo). Este subtipo se usa algunas veces para seleccionar diferentes comportamientos, p.e. aÃ±adiendo una constante a un vector podrÃ­a aÃ±adir la constante a todos los tÃ©rminos para algunos obejtos geomÃ©tricos representados usando vectores, sÃ³lo a los tÃ©rminos de la diagonal de la matriz cuadrada, o al Ãºltimo tÃ©rmino de polinÃ³mios densos. Mira en giac/dispatch.h la descripciÃ³n de los subtipos.

PolinÃ³mios
===========

PolinÃ³mios estÃ¡n disponibles como:

  * polinÃ³mios multivariables escasos polynome, los ficheros de cabecera son gausspol.h y poly.h

  * polinÃ³mios univariables densos: poly1 o alias modpoly usado para polinÃ³mios univariables modulares. El tipo usado es el mismo que para vectores y matrices. Los ficheros de cabecera son giac/polygauss.h y giac/modpoly.h.

Un gen puede ser un polinÃ³mio si su campo type es respectivamente _POLY (escaso) o _VECT (denso). Las funciones de conversiÃ³n a y de la representaciÃ³n simbÃ³lica respecto a nombres globales son declaradas en giac/sym2poly.cc.

Vectores y matrices
===================

El tipo usado para vectores y matrices es el mismo, es un std::vector<gen> (a menos que lo tengas configurado con --enable-debug). El fichero cabecera es giac/vecteur.h. Un gen puede ser un vector si su campo type es _VECT.

SimbÃ³licos
===========

Los objetos simbÃ³licos son Ã¡rboles. El sommet es una unary_function_ptr (una clase apuntando a una funciÃ³n). El feuille es tambiÃ©n un gen atÃ³mico (para un funciÃ³n con un argumento) o un compuesto (feuille.type==_VECT) para una funciÃ³n con mÃ¡s de un argumento (estas funciones aparecen por lo tanto como una funciÃ³n con un argumento el cual es la lista de todos sus argumentos).

Funciones unarias
=================

En la librerÃ­a giac, cada funciÃ³n es vista como un funciÃ³n que coge un argumento y devuelve un argumento. Si una funciÃ³n debiese tener mÃ¡s de un argumento, metemos estos argumentos en un vector.

Los ficheros usual.cc/.h dan ejemplos de declaraciones p.ej. para funciones exponenciales y trigonomÃ©tricas. Las funciones unarias tienen los siguientes miembros~:

  * una funciÃ³n que coge un gen y devuelve un gen que hace todo el trabajo

  * derivadas parciales de esa funciÃ³n si existen

  * un desarrollo en serie especial de Taylor si es necesario (vease p.ej. taylor_asin). Ãste es siempre el caso si tu funciÃ³n estÃ¡ definida en infinito. Notese que esta funciÃ³n es ejecutada al inicio asÃ­ que puedes incluir cÃ³digo en ella por ejemplo para aÃ±adir tu funciÃ³n al paso de preproceso simbÃ³lico del algorÃ­tmo limit/series .

  * una cadena de texto identificadora para imprimir. Si quieres que el intÃ©rprete reconozca tu funciÃ³n, debes aÃ±adir una lÃ­nea en input_lexer.ll (mira por ejemplo "sin") o debes registrarla (mira mÃ¡s abajo).

  * dos funciones especial de impresiÃ³n si la impresiÃ³n normal (impresiÃ³n normal significa imprimir el nombre de la funciÃ³n seguido por el argumento(s) entre parÃ©ntesis) no es la forma correcta de imprimirla. Un puntero nulo significa que se usa impresiÃ³n normal.

Una vez que la unaria_funcion_unaria estÃ¡ definida, debes construtir un unaria_funcion_ptr para poder usar lo simbÃ³licos internos.

PodrÃ­as dar un argumento opcional para especificar un comportamiento para la evaluaciÃ³n de argumentos (citando). En este caso, podrÃ­as dar un segundo argumento opcional para registrar tu funciÃ³n dinÃ¡micamente en la lista de nombre de funciones reconozidas por el intÃ©rprete. AsegÃºrate de unir el fichero objeto de forma que la inicializaciÃ³n occurre despues de inicializarse input_lexer.ll, esto significa que debes poner tu fichero objeto antes de input_lexer.o cuando unas (mira por ejemplo la posiciÃ³n de moyal.o en el fichero Makefile.am , moyal es un ejemplo de registro dinÃ¡mico).

Tienes, por supuesto, la opciÃ³n de declarar el nombre de la funciÃ³n estÃ¡ticamente en el fichero input_lexer.ll.

Siempre debes declarar una funciÃ³n estÃ¡ticamente si no sigue la sintÃ¡xis estÃ¡ndar para una funciÃ³n.

AquÃ­ estÃ¡ un ejemplo de una funciÃ³n unible dinÃ¡micamente llamada example que requiere 2 argumentos y devuelve la suma dividida por el producto si los argumentos son enteros o se devuelve a si misma en otro caso. La cabecera en C++ de example.h serÃ­a algo asÃ­

     #ifndef __EXAMPLE_H
     #define __EXAMPLE_H
     #include <giac/gen.h>
     #include <giac/unary.h>

     #ifndef NO_NAMESPACE_GIAC
     namespace giac {
     #endif // ndef NO_NAMESPACE_GIAC

       gen example(const gen & a,const gen & b);
       gen _example(const gen & args);
       extern unary_function_ptr at_example ;

     #ifndef NO_NAMESPACE_GIAC
     } // namespace giac
     #endif // ndef NO_NAMESPACE_GIAC
     #endif // __EXAMPLE_H

El cÃ³digo en C++ serÃ­a algo como:

     using namespace std;
     #include <giac/giac.h>
     #include "example.h"

     #ifndef NO_NAMESPACE_GIAC
     namespace giac {
     #endif // ndef NO_NAMESPACE_GIAC

       gen example(const gen & a,const gen & b){
         if (is_integer(a) && is_integer(b))
           return (a+b)/(a*b);
         return symbolic(at_example,makevecteur(a,b));
       }

       gen _example(const gen & args){
         if ( (args.type!=_VECT) || (args._VECTptr->size()!=2) )
           setsizeerr(); // type checking : args must be a vector of size 2
         vecteur & v=*args._VECTptr;
         return example(v[0],v[1]);
       }
       const string _example_s("example");
       unary_function_unary __example(&_example,_example_s);
       unary_function_ptr at_example (&__example,0,true);

     #ifndef NO_NAMESPACE_GIAC
     }
     #endif // ndef NO_NAMESPACE_GIAC

CompÃ­lalo con

     c++ -g -c example.cc

Para probar tu cÃ³digo, podrÃ­as escribir el siguiente test.cc programa

     #include "example.h"

     using namespace std;
     using namespace giac;

     int main(){
       gen args;
       cout << "Enter argument of example function";
       cin >> args;
       cout << "Result: " << _example(args) << endl;
     }

CompÃ­lalo con el comando

     c++ -g example.o test.cc -lgiac -lgmp

PodrÃ­as necesitar unirlo a otras librerÃ­as p.ej. -lreadline -lhistory -lcurses dependiendo de tu instalaciÃ³n. Entonces ejecuta a.out. En este punto probarÃ­as con p.ej. [1,2].

Puedes depurar tu programa como siempre, p.ej. con gdb a.out, es recomendable crear un fichero .gdbinit en el directorio actual de forma que puedas usar el comando v para imprimir datos de giac, el fichero .gdbinit podrÃ­a contener :

     echo Defining v as print command for giac types\n
     define v
     print ($arg0).dbgprint()
     end

Cuando tu funciÃ³n estÃ© comprobada, puedes aÃ±adirla a la librerÃ­a. Edita el fichero Makefile.am del subdirectorio src de giac : simplemente aÃ±ade example.cc antes de input_lexer.cc en la lÃ­nea libgiac_la_SOURCES y aÃ±ade example.h en la lÃ­nea giacinclude_HEADERS .

Para reconstruir la librerÃ­a vete al directorio giac y escribe automake; make

Si quieres compartir tu funciÃ³n(es) con otras personas, debes ponerle licencia GPL (porque estarÃ¡ unida a cÃ³digo GPL). AÃ±ade la cabecera GPL a los ficheros, y envÃ­alos al e-mail de contribuciones de giac, actualmente mailto:parisse@fourier.ujf-grenoble.fr

     /*
      *  Copyright (C) 2002 Your name
      *
      *  This program is free software; you can redistribute it and/or modify
      *  it under the terms of the GNU General Public License as published by
      *  the Free Software Foundation; either version 2 of the License, or
      *  (at your option) any later version.
      *
      *  This program is distributed in the hope that it will be useful,
      *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      *  GNU General Public License for more details.
      *
      *  You should have received a copy of the GNU General Public License
      *  along with this program; if not, write to the Free Software
      *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      */

Otra forma de compartir tu cÃ³digo podrÃ­a ser construir una librerÃ­a dinÃ¡mica que puede ser cargada en tiempo de ejecuciÃ³n usando las facilidades de <dlfcns.h>. ATENCION: los mÃ³dulos no funcionan con binarios estÃ¡ticos. AsegÃºrate de tener binarios dinÃ¡micos (situaciÃ³n por defecto cuando compilas giac, pero el paquete xcas distribuido como binario estÃ¡ construido estÃ¡tico para evitar librerÃ­as incompatibles).

Definamos una funciÃ³n llamada  mydll en el fichero mydll.cc como este :

     #include <giac/giac.h>

     #ifndef NO_NAMESPACE_GIAC
     namespace giac {
     #endif // ndef NO_NAMESPACE_GIAC

       const string _mydll_s("mydll");
       gen _mydll(const gen & args){
         return sin(ln(args));
       }
       unary_function_unary __mydll(&giac::_mydll,_mydll_s);
       unary_function_ptr at_mydll (&__mydll,0,true); // auto-register

     #ifndef NO_NAMESPACE_GIAC
     } // namespace giac
     #endif // ndef NO_NAMESPACE_GIAC

CompÃ­lalo como esto

     c++ -fPIC -DPIC -g -c mydll.cc -o mydll.lo
     cc -shared  mydll.lo  -lc  -Wl,-soname -Wl,libmydll.so.0 -o libmydll.so.0.0.0
     rm -f libmydll.so.0 && ln -s libmydll.so.0.0.0 libmydll.so.0
     rm -f libmydll.so && ln -s libmydll.so.0.0.0 libmydll.so

La librerÃ­a es cargable en tiempo de ejecuciÃ³n de una seseiÃ³n usando el comando insmod("libmydll.so") asumiendo que estÃ¡ guardada en un directorio disponible desde LD_LIBRARY_PATH o en /etc/ld.so.conf si no debes poner la ruta al fichero librerÃ­a (comenzando con ./ si estÃ¡ en el directorio actual).

Una forma de comprobar tu cÃ³digo es aÃ±adir la lÃ­nea siguiente en tu fichero ~/.xcasrc  :

     insmod("ruta_a_libmydll/libmydll.so");

donde cambias  ruta_a_libmydll.so por la ruta real a libmydll.so por ejemplo /home/joe si tu nombre de conexiÃ³n (login) es joe y mydll estÃ¡ en tu directorio home. Entonces si estÃ¡s usando como editor emacs , pon como primera lÃ­nea del fichero mydll.cc

     // -*- mode:C++ ; compile-command: "g++ -I.. -fPIC -DPIC -g -c mydll.cc -o mydll.lo && ln -sf mydll.lo mydll.o && gcc -shared mydll.lo -lc  -Wl,-soname -Wl,libmydll.so.0 -o libmydll.so.0.0.0 && ln -sf libmydll.so.0.0.0 libmydll.so.0 && ln -sf libmydll.so.0.0.0 libmydll.so" -*-

Ahora puedes compilarlo con Compile del menÃº Tools y el cÃ³digo resultante es cargado automaticamente cuando comienzas una nueva sesiÃ³n con xcas o cas que hace que comprobar sea mÃ¡s ligero.

Datos definidos por usuario
===========================

La clase gen_user puede ser derivada de forma que puedes incluir tus propios datos en gen. Mira la declaraciÃ³n de gen_user en el fichero gen.h y en el ejemplo de las quaternas en los ficheros quater.h y quater.cc.

Algunso ejemplos de programas en C++ usando giac
************************************************

Un primer ejemplo
*****************

Teclea el texto siguiente con tu editor favorito

     #include <giac/giac.h>
     using namespace std;
     using namespace giac;

     int main(){
       gen e(string("x^2-1"));
       cout << factor(e) << endl;
     }

guÃ¡rdalo como p.ej. tryit.cc y compÃ­lalo con

c++ -g tryit.cc -lgiac -lgmp

Si obitenes sÃ­mbolos sin resolver, entonces puede que readline estÃ© activada y debas compilarlo como

c++ -g tryit.cc -lgiac -lgmp -lreadline -lcurses

Ahora puedes ejecutar a.out que imprimirÃ¡ la factorizaciÃ³n de x^2-1.

TambiÃ©n puedes ejecutar el programa paso a paso usando gdb. Recomendamos que copies el fichero .gdbinit del directorio src de la distribuciÃ³n giac, porque permite usar v nombrevar para imprimir la variable nombrevar de tipo gen.

Algunas explicaciones del cÃ³digo:

  * la directiva #include <giac/giac.h> incluye todas las cabeceras de giac (lo que incluye algunas cabeceras de STL como string o vector).

  * la directiva using namespace no es obligatoria, si no la usas, necesitas modificar algo del cÃ³digo, p.ej. usa std::string en vez de string o giac::gen en lugar de gen.

  * Variables del tipo gen pueden ser construidas a partir de cadenas (usando el intÃ©rprete), a partir de algunos tipos de C (como int o double), a partir de tipos de STL std::complex<double> o a partir de secuencias (usando el intÃ©rprete).

  * Operaciones como +, -, * estÃ¡n definidas en el tipo gen pero la divisiÃ³n no estÃ¡ redefinida para evitar confusiÃ³n entre enteros (usa iquo) y divisiÃ³n de double (reales) en C (usa rdiv). Para potencias, usa pow como de constumbre.